Merge branch 'master' into improve_search_regexp_doc

pull/3934/head^2
Julien 7 years ago committed by GitHub
commit 50890b7969
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright 2016 The Kubernetes Authors All rights reserved.
# Copyright The Helm Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright 2016 The Kubernetes Authors All rights reserved.
# Copyright The Helm Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright 2016 The Kubernetes Authors All rights reserved.
# Copyright The Helm Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

1
.gitignore vendored

@ -5,6 +5,7 @@
_dist/
_proto/*.pb.go
bin/
rootfs/helm
rootfs/tiller
rootfs/rudder
vendor/

@ -7,7 +7,7 @@ The Kubernetes Helm project accepts contributions via GitHub pull requests. This
Most of the time, when you find a bug in Helm, it should be reported
using [GitHub issues](https://github.com/kubernetes/helm/issues). However, if
you are reporting a _security vulnerability_, please email a report to
[helm-security@deis.com](mailto:helm-security@deis.com). This will give
[cncf-kubernetes-helm-security@lists.cncf.io](mailto:cncf-kubernetes-helm-security@lists.cncf.io). This will give
us a chance to try to fix the issue before it is exploited in the wild.
## Contributor License Agreements
@ -31,7 +31,9 @@ apply to [third_party](third_party/) and [vendor](vendor/).
Whether you are a user or contributor, official support channels include:
- GitHub [issues](https://github.com/kubernetes/helm/issues/new)
- Slack: #Helm room in the [Kubernetes Slack](http://slack.kubernetes.io/)
- Slack [Kubernetes Slack](http://slack.kubernetes.io/):
- User: #helm-users
- Contributor: #helm-dev
Before opening a new issue or submitting a new pull request, it's helpful to search the project - it's likely that another user has already reported the issue you're facing, or it's a known issue that we're already aware of.
@ -53,7 +55,7 @@ An issue that we are not sure we will be doing will not be added to any mileston
A milestone (and hence release) is considered done when all outstanding issues/PRs have been closed or moved to another milestone.
## Semver
## Semantic Versioning
Helm maintains a strong commitment to backward compatibility. All of our changes to protocols and formats are backward compatible from Helm 2.0 until Helm 3.0. No features, flags, or commands are removed or substantially modified (other than bug fixes).

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 The Kubernetes Authors All Rights Reserved
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -2,7 +2,7 @@ DOCKER_REGISTRY ?= gcr.io
IMAGE_PREFIX ?= kubernetes-helm
SHORT_NAME ?= tiller
SHORT_NAME_RUDDER ?= rudder
TARGETS ?= darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le windows/amd64
TARGETS ?= darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64
DIST_DIRS = find * -type d -exec
APP = helm
@ -60,6 +60,7 @@ check-docker:
docker-binary: BINDIR = ./rootfs
docker-binary: GOFLAGS += -a -installsuffix cgo
docker-binary:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO) build -o $(BINDIR)/helm $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' k8s.io/helm/cmd/helm
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO) build -o $(BINDIR)/tiller $(GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' k8s.io/helm/cmd/tiller
.PHONY: docker-build

@ -28,3 +28,4 @@ emeritus:
- migmartri
- seh
- vaikas-google
- rimusz

@ -1,7 +1,7 @@
# Kubernetes Helm
[![CircleCI](https://circleci.com/gh/kubernetes/helm.svg?style=svg)](https://circleci.com/gh/kubernetes/helm)
[![Go Report Card](https://goreportcard.com/badge/github.com/kubernetes/helm)](https://goreportcard.com/report/github.com/kubernetes/helm)
[![CircleCI](https://circleci.com/gh/helm/helm.svg?style=svg)](https://circleci.com/gh/helm/helm)
[![Go Report Card](https://goreportcard.com/badge/github.com/helm/helm)](https://goreportcard.com/report/github.com/helm/helm)
[![GoDoc](https://godoc.org/github.com/kubernetes/helm?status.svg)](https://godoc.org/github.com/kubernetes/helm)
Helm is a tool for managing Kubernetes charts. Charts are packages of
@ -9,7 +9,7 @@ pre-configured Kubernetes resources.
Use Helm to:
- Find and use [popular software packaged as Kubernetes charts](https://github.com/kubernetes/charts)
- Find and use [popular software packaged as Kubernetes charts](https://github.com/helm/charts)
- Share your own applications as Kubernetes charts
- Create reproducible builds of your Kubernetes applications
- Intelligently manage your Kubernetes manifest files
@ -32,14 +32,15 @@ Think of it like apt/yum/homebrew for Kubernetes.
## Install
Binary downloads of the Helm client can be found on [the latest Releases page](https://github.com/kubernetes/helm/releases/latest).
Binary downloads of the Helm client can be found on [the Releases page](https://github.com/helm/helm/releases/latest).
Unpack the `helm` binary and add it to your PATH and you are good to go!
If you want to use a package manager:
- macOS/[homebrew](https://brew.sh/) users can use `brew install kubernetes-helm`.
- Windows/[chocolatey](https://chocolatey.org/) users can use `choco install kubernetes-helm`.
- [Homebrew](https://brew.sh/) users can use `brew install kubernetes-helm`.
- [Chocolatey](https://chocolatey.org/) users can use `choco install kubernetes-helm`.
- [GoFish](https://gofi.sh/) users can use `gofish install helm`.
To rapidly get Helm up and running, start with the [Quick Start Guide](https://docs.helm.sh/using_helm/#quickstart-guide).
@ -52,16 +53,16 @@ Get started with the [Quick Start guide](https://docs.helm.sh/using_helm/#quicks
## Roadmap
The [Helm roadmap uses Github milestones](https://github.com/kubernetes/helm/milestones) to track the progress of the project.
The [Helm roadmap uses Github milestones](https://github.com/helm/helm/milestones) to track the progress of the project.
## Community, discussion, contribution, and support
You can reach the Helm community and developers via the following channels:
- [Kubernetes Slack](http://slack.k8s.io):
- #helm-users
- #helm-dev
- #charts
- [#helm-users](https://kubernetes.slack.com/messages/helm-users)
- [#helm-dev](https://kubernetes.slack.com/messages/helm-dev)
- [#charts](https://kubernetes.slack.com/messages/charts)
- Mailing Lists:
- [Helm Mailing List](https://lists.cncf.io/g/cncf-kubernetes-helm)
- [Kubernetes SIG Apps Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-apps)

@ -0,0 +1,20 @@
# Defined below are the security contacts for this repo.
#
# They are the contact point for the Product Security Team to reach out
# to for triaging and handling of incoming issues.
#
# The below names agree to abide by the
# [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy)
# and will be removed and replaced if they violate that agreement.
#
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
# INSTRUCTIONS AT https://github.com/kubernetes/helm/blob/master/CONTRIBUTING.md#reporting-a-security-issue
adamreese
bacongobbler
mattfarina
michelleN
prydonius
SlickNik
technosophos
thomastaylor312

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2017 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -89,7 +89,7 @@ service ReleaseService {
//
// Releases can be retrieved in chunks by setting limit and offset.
//
// Releases can be sorted according to a few pre-determined sort stategies.
// Releases can be sorted according to a few pre-determined sort strategies.
message ListReleasesRequest {
// Limit is the maximum number of releases to be returned.
int64 limit = 1;
@ -209,6 +209,8 @@ message UpdateReleaseRequest {
bool reuse_values = 10;
// Force resource update through delete/recreate if needed.
bool force = 11;
// Description, if set, will set the description for the updated release
string description = 12;
}
// UpdateReleaseResponse is the response to an update request.
@ -234,6 +236,8 @@ message RollbackReleaseRequest {
bool wait = 7;
// Force resource update through delete/recreate if needed.
bool force = 8;
// Description, if set, will set the description for the rollback
string description = 9;
}
// RollbackReleaseResponse is the response to an update request.
@ -260,10 +264,10 @@ message InstallReleaseRequest {
// DisableHooks causes the server to skip running any hooks for the install.
bool disable_hooks = 5;
// Namepace is the kubernetes namespace of the release.
// Namespace is the kubernetes namespace of the release.
string namespace = 6;
// ReuseName requests that Tiller re-uses a name, instead of erroring out.
// Reuse_name requests that Tiller re-uses a name, instead of erroring out.
bool reuse_name = 7;
// timeout specifies the max amount of time any kubernetes client command can run.
@ -273,6 +277,9 @@ message InstallReleaseRequest {
bool wait = 9;
bool disable_crd_hook = 10;
// Description, if set, will set the description for the installed release
string description = 11;
}
// InstallReleaseResponse is the response from a release installation.
@ -290,6 +297,8 @@ message UninstallReleaseRequest {
bool purge = 3;
// timeout specifies the max amount of time any kubernetes client command can run.
int64 timeout = 4;
// Description, if set, will set the description for the uninnstalled release
string description = 5;
}
// UninstallReleaseResponse represents a successful response to an uninstall request.

@ -1,4 +1,4 @@
// Copyright 2016 The Kubernetes Authors All rights reserved.
// Copyright The Helm Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -40,6 +40,7 @@ type deleteCmd struct {
disableHooks bool
purge bool
timeout int64
description string
out io.Writer
client helm.Interface
@ -81,6 +82,7 @@ func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&del.disableHooks, "no-hooks", false, "prevent hooks from running during deletion")
f.BoolVar(&del.purge, "purge", false, "remove the release from the store and make its name free for later use")
f.Int64Var(&del.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.StringVar(&del.description, "description", "", "specify a description for the release")
return cmd
}
@ -91,6 +93,7 @@ func (d *deleteCmd) run() error {
helm.DeleteDisableHooks(d.disableHooks),
helm.DeletePurge(d.purge),
helm.DeleteTimeout(d.timeout),
helm.DeleteDescription(d.description),
}
res, err := d.client.DeleteRelease(d.name, opts...)
if res != nil && res.Info != "" {

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -61,6 +61,14 @@ func TestDelete(t *testing.T) {
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
},
{
name: "delete with description",
args: []string{"aeneas"},
flags: []string{"--description", "foo"},
expected: "",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}),
rels: []*release.Release{helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"})},
},
{
name: "delete without release",
args: []string{},

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -141,7 +141,7 @@ func (l *dependencyListCmd) run() error {
r, err := chartutil.LoadRequirements(c)
if err != nil {
if err == chartutil.ErrRequirementsNotFound {
fmt.Fprintf(l.out, "WARNING: no requirements at %s/charts\n", l.chartpath)
fmt.Fprintf(l.out, "WARNING: no requirements at %s\n", filepath.Join(l.chartpath, "charts"))
return nil
}
return err

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -158,7 +158,12 @@ func init() {
func main() {
cmd := newRootCmd(os.Args[1:])
if err := cmd.Execute(); err != nil {
os.Exit(1)
switch e := err.(type) {
case pluginError:
os.Exit(e.code)
default:
os.Exit(1)
}
}
}
@ -169,7 +174,7 @@ func markDeprecated(cmd *cobra.Command, notice string) *cobra.Command {
func setupConnection() error {
if settings.TillerHost == "" {
config, client, err := getKubeClient(settings.KubeContext)
config, client, err := getKubeClient(settings.KubeContext, settings.KubeConfig)
if err != nil {
return err
}
@ -223,8 +228,8 @@ func prettyError(err error) error {
}
// configForContext creates a Kubernetes REST client configuration for a given kubeconfig context.
func configForContext(context string) (*rest.Config, error) {
config, err := kube.GetConfig(context).ClientConfig()
func configForContext(context string, kubeconfig string) (*rest.Config, error) {
config, err := kube.GetConfig(context, kubeconfig).ClientConfig()
if err != nil {
return nil, fmt.Errorf("could not get Kubernetes config for context %q: %s", context, err)
}
@ -232,8 +237,8 @@ func configForContext(context string) (*rest.Config, error) {
}
// getKubeClient creates a Kubernetes config and client for a given kubeconfig context.
func getKubeClient(context string) (*rest.Config, kubernetes.Interface, error) {
config, err := configForContext(context)
func getKubeClient(context string, kubeconfig string) (*rest.Config, kubernetes.Interface, error) {
config, err := configForContext(context, kubeconfig)
if err != nil {
return nil, nil, err
}
@ -247,8 +252,8 @@ func getKubeClient(context string) (*rest.Config, kubernetes.Interface, error) {
// getInternalKubeClient creates a Kubernetes config and an "internal" client for a given kubeconfig context.
//
// Prefer the similar getKubeClient if you don't need to use such an internal client.
func getInternalKubeClient(context string) (internalclientset.Interface, error) {
config, err := configForContext(context)
func getInternalKubeClient(context string, kubeconfig string) (internalclientset.Interface, error) {
config, err := configForContext(context, kubeconfig)
if err != nil {
return nil, err
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -181,95 +181,64 @@ func (i *initCmd) run() error {
i.opts.MaxHistory = i.maxHistory
i.opts.Replicas = i.replicas
writeYAMLManifest := func(apiVersion, kind, body string, first, last bool) error {
writeYAMLManifests := func(manifests []string) error {
w := i.out
if !first {
// YAML starting document boundary marker
for _, manifest := range manifests {
if _, err := fmt.Fprintln(w, "---"); err != nil {
return err
}
if _, err := fmt.Fprintln(w, manifest); err != nil {
return err
}
}
if _, err := fmt.Fprintln(w, "apiVersion:", apiVersion); err != nil {
return err
}
if _, err := fmt.Fprintln(w, "kind:", kind); err != nil {
return err
}
if _, err := fmt.Fprint(w, body); err != nil {
return err
}
if !last {
return nil
}
// YAML ending document boundary marker
_, err := fmt.Fprintln(w, "...")
return err
}
if len(i.opts.Output) > 0 {
var body string
var manifests []string
var err error
const tm = `{"apiVersion":"extensions/v1beta1","kind":"Deployment",`
if body, err = installer.DeploymentManifest(&i.opts); err != nil {
if manifests, err = installer.TillerManifests(&i.opts); err != nil {
return err
}
switch i.opts.Output.String() {
case "json":
var out bytes.Buffer
jsonb, err := yaml.ToJSON([]byte(body))
if err != nil {
return err
}
buf := bytes.NewBuffer(make([]byte, 0, len(tm)+len(jsonb)-1))
buf.WriteString(tm)
// Drop the opening object delimiter ('{').
buf.Write(jsonb[1:])
if err := json.Indent(&out, buf.Bytes(), "", " "); err != nil {
return err
}
if _, err = i.out.Write(out.Bytes()); err != nil {
return err
for _, manifest := range manifests {
var out bytes.Buffer
jsonb, err := yaml.ToJSON([]byte(manifest))
if err != nil {
return err
}
buf := bytes.NewBuffer(jsonb)
if err := json.Indent(&out, buf.Bytes(), "", " "); err != nil {
return err
}
if _, err = i.out.Write(out.Bytes()); err != nil {
return err
}
fmt.Fprint(i.out, "\n")
}
return nil
case "yaml":
if err := writeYAMLManifest("extensions/v1beta1", "Deployment", body, true, false); err != nil {
return err
}
return nil
return writeYAMLManifests(manifests)
default:
return fmt.Errorf("unknown output format: %q", i.opts.Output)
}
}
if settings.Debug {
var body string
var manifests []string
var err error
// write Deployment manifest
if body, err = installer.DeploymentManifest(&i.opts); err != nil {
return err
}
if err := writeYAMLManifest("extensions/v1beta1", "Deployment", body, true, false); err != nil {
// write Tiller manifests
if manifests, err = installer.TillerManifests(&i.opts); err != nil {
return err
}
// write Service manifest
if body, err = installer.ServiceManifest(i.namespace); err != nil {
return err
}
if err := writeYAMLManifest("v1", "Service", body, false, !i.opts.EnableTLS); err != nil {
if err = writeYAMLManifests(manifests); err != nil {
return err
}
// write Secret manifest
if i.opts.EnableTLS {
if body, err = installer.SecretManifest(&i.opts); err != nil {
return err
}
if err := writeYAMLManifest("v1", "Secret", body, false, true); err != nil {
return err
}
}
}
if i.dryRun {
@ -289,7 +258,7 @@ func (i *initCmd) run() error {
if !i.clientOnly {
if i.kubeClient == nil {
_, c, err := getKubeClient(settings.KubeContext)
_, c, err := getKubeClient(settings.KubeContext, settings.KubeConfig)
if err != nil {
return fmt.Errorf("could not get kubernetes client: %s", err)
}
@ -312,9 +281,12 @@ func (i *initCmd) run() error {
"(Use --client-only to suppress this message, or --upgrade to upgrade Tiller to the current version.)")
}
} else {
fmt.Fprintln(i.out, "\nTiller (the Helm server-side component) has been installed into your Kubernetes Cluster.\n\n"+
"Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.\n"+
"For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation")
fmt.Fprintln(i.out, "\nTiller (the Helm server-side component) has been installed into your Kubernetes Cluster.")
if !tlsVerify {
fmt.Fprintln(i.out, "\nPlease note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.\n"+
"To prevent this, run `helm init` with the --tiller-tls-verify flag.\n"+
"For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation")
}
}
if err := i.ping(); err != nil {
return err
@ -329,7 +301,7 @@ func (i *initCmd) run() error {
func (i *initCmd) ping() error {
if i.wait {
_, kubeClient, err := getKubeClient(settings.KubeContext)
_, kubeClient, err := getKubeClient(settings.KubeContext, settings.KubeConfig)
if err != nil {
return err
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -18,6 +18,7 @@ package main
import (
"bytes"
"io"
"io/ioutil"
"os"
"path/filepath"
@ -32,11 +33,10 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
yamlutil "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/kubernetes/fake"
testcore "k8s.io/client-go/testing"
"encoding/json"
"k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/helm/helmpath"
)
@ -306,7 +306,7 @@ func TestInitCmd_tlsOptions(t *testing.T) {
}
}
// TestInitCmd_output tests that init -o formats are unmarshal-able
// TestInitCmd_output tests that init -o can be decoded
func TestInitCmd_output(t *testing.T) {
// This is purely defensive in this case.
home, err := ioutil.TempDir("", "helm_home")
@ -320,26 +320,14 @@ func TestInitCmd_output(t *testing.T) {
settings.Debug = dbg
}()
fc := fake.NewSimpleClientset()
tests := []struct {
expectF func([]byte, interface{}) error
expectName string
}{
{
json.Unmarshal,
"json",
},
{
yaml.Unmarshal,
"yaml",
},
}
tests := []string{"json", "yaml"}
for _, s := range tests {
var buf bytes.Buffer
cmd := &initCmd{
out: &buf,
home: helmpath.Home(home),
kubeClient: fc,
opts: installer.Options{Output: installer.OutputFormat(s.expectName)},
opts: installer.Options{Output: installer.OutputFormat(s)},
namespace: v1.NamespaceDefault,
}
if err := cmd.run(); err != nil {
@ -348,10 +336,17 @@ func TestInitCmd_output(t *testing.T) {
if got := len(fc.Actions()); got != 0 {
t.Errorf("expected no server calls, got %d", got)
}
d := &v1beta1.Deployment{}
if err = s.expectF(buf.Bytes(), &d); err != nil {
t.Errorf("error unmarshalling init %s output %s %s", s.expectName, err, buf.String())
var obj interface{}
decoder := yamlutil.NewYAMLOrJSONDecoder(&buf, 4096)
for {
err := decoder.Decode(&obj)
if err != nil {
if err == io.EOF {
break
}
t.Errorf("error decoding init %s output %s %s", s, err, buf.String())
}
}
}
}

@ -1,7 +1,7 @@
// +build !windows
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,7 +1,7 @@
// +build windows
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -50,8 +50,10 @@ The install argument must be a chart reference, a path to a packaged chart,
a path to an unpacked chart directory or a URL.
To override values in a chart, use either the '--values' flag and pass in a file
or use the '--set' flag and pass configuration from the command line, to force
a string value use '--set-string'.
or use the '--set' flag and pass configuration from the command line. To force string
values in '--set', use '--set-string' instead. In case a value is large and therefore
you want not to use neither '--values' nor '--set', use '--set-file' to read the
single large value from file.
$ helm install -f myvalues.yaml ./redis
@ -63,6 +65,9 @@ or
$ helm install --set-string long_int=1234567890 ./redis
or
$ helm install --set-file multiline_text=path/to/textfile
You can specify the '--values'/'-f' flag multiple times. The priority will be given to the
last (right-most) file specified. For example, if both myvalues.yaml and override.yaml
contained a key called 'Test', the value set in override.yaml would take precedence:
@ -120,6 +125,7 @@ type installCmd struct {
client helm.Interface
values []string
stringValues []string
fileValues []string
nameTemplate string
version string
timeout int64
@ -129,6 +135,7 @@ type installCmd struct {
password string
devel bool
depUp bool
description string
certFile string
keyFile string
@ -195,6 +202,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&inst.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production")
f.StringArrayVar(&inst.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&inst.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&inst.fileValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)")
f.StringVar(&inst.nameTemplate, "name-template", "", "specify template used to name the release")
f.BoolVar(&inst.verify, "verify", false, "verify the package before installing it")
f.StringVar(&inst.keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
@ -209,6 +217,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.StringVar(&inst.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&inst.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&inst.depUp, "dep-up", false, "run helm dependency update before installing the chart")
f.StringVar(&inst.description, "description", "", "specify a description for the release")
return cmd
}
@ -220,7 +229,7 @@ func (i *installCmd) run() error {
i.namespace = defaultNamespace()
}
rawVals, err := vals(i.valueFiles, i.values, i.stringValues, i.certFile, i.keyFile, i.caFile)
rawVals, err := vals(i.valueFiles, i.values, i.stringValues, i.fileValues, i.certFile, i.keyFile, i.caFile)
if err != nil {
return err
}
@ -258,6 +267,12 @@ func (i *installCmd) run() error {
if err := man.Update(); err != nil {
return prettyError(err)
}
// Update all dependencies which are present in /charts.
chartRequested, err = chartutil.Load(i.chartPath)
if err != nil {
return prettyError(err)
}
} else {
return prettyError(err)
}
@ -277,7 +292,8 @@ func (i *installCmd) run() error {
helm.InstallDisableHooks(i.disableHooks),
helm.InstallDisableCRDHook(i.disableCRDHook),
helm.InstallTimeout(i.timeout),
helm.InstallWait(i.wait))
helm.InstallWait(i.wait),
helm.InstallDescription(i.description))
if err != nil {
return prettyError(err)
}
@ -334,8 +350,8 @@ func mergeValues(dest map[string]interface{}, src map[string]interface{}) map[st
}
// vals merges values from files specified via -f/--values and
// directly via --set or --set-string, marshaling them to YAML
func vals(valueFiles valueFiles, values []string, stringValues []string, CertFile, KeyFile, CAFile string) ([]byte, error) {
// directly via --set or --set-string or --set-file, marshaling them to YAML
func vals(valueFiles valueFiles, values []string, stringValues []string, fileValues []string, CertFile, KeyFile, CAFile string) ([]byte, error) {
base := map[string]interface{}{}
// User specified a values files via -f/--values
@ -375,6 +391,17 @@ func vals(valueFiles valueFiles, values []string, stringValues []string, CertFil
}
}
// User specified a value via --set-file
for _, value := range fileValues {
reader := func(rs []rune) (interface{}, error) {
bytes, err := readFile(string(rs), CertFile, KeyFile, CAFile)
return string(bytes), err
}
if err := strvals.ParseIntoFile(value, base, reader); err != nil {
return []byte{}, fmt.Errorf("failed parsing --set-file data: %s", err)
}
}
return yaml.Marshal(base)
}
@ -482,7 +509,7 @@ func generateName(nameTemplate string) (string, error) {
}
func defaultNamespace() string {
if ns, _, err := kube.GetConfig(settings.KubeContext).Namespace(); err == nil {
if ns, _, err := kube.GetConfig(settings.KubeContext, settings.KubeConfig).Namespace(); err == nil {
return ns
}
return "default"

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -115,6 +115,13 @@ func TestInstall(t *testing.T) {
expected: "FOOBAR",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "FOOBAR"}),
},
{
name: "install with custom description",
args: []string{"testdata/testcharts/alpine"},
flags: []string{"--name", "virgil", "--description", "foobar"},
expected: "virgil",
resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil", Description: "foobar"}),
},
// Install, perform chart verification along the way.
{
name: "install with verification, missing provenance",

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import (
"k8s.io/api/extensions/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
@ -104,7 +105,7 @@ func semverCompare(image string) int {
// createDeployment creates the Tiller Deployment resource.
func createDeployment(client extensionsclient.DeploymentsGetter, opts *Options) error {
obj, err := deployment(opts)
obj, err := generateDeployment(opts)
if err != nil {
return err
}
@ -113,40 +114,68 @@ func createDeployment(client extensionsclient.DeploymentsGetter, opts *Options)
}
// deployment gets the deployment object that installs Tiller.
func deployment(opts *Options) (*v1beta1.Deployment, error) {
return generateDeployment(opts)
// Deployment gets a deployment object that can be used to generate a manifest
// as a string. This object should not be submitted directly to the Kubernetes
// api
func Deployment(opts *Options) (*v1beta1.Deployment, error) {
dep, err := generateDeployment(opts)
if err != nil {
return nil, err
}
dep.TypeMeta = metav1.TypeMeta{
Kind: "Deployment",
APIVersion: "extensions/v1beta1",
}
return dep, nil
}
// createService creates the Tiller service resource
func createService(client corev1.ServicesGetter, namespace string) error {
obj := service(namespace)
obj := generateService(namespace)
_, err := client.Services(obj.Namespace).Create(obj)
return err
}
// service gets the service object that installs Tiller.
func service(namespace string) *v1.Service {
return generateService(namespace)
// Service gets a service object that can be used to generate a manifest as a
// string. This object should not be submitted directly to the Kubernetes api
func Service(namespace string) *v1.Service {
svc := generateService(namespace)
svc.TypeMeta = metav1.TypeMeta{
Kind: "Service",
APIVersion: "v1",
}
return svc
}
// DeploymentManifest gets the manifest (as a string) that describes the Tiller Deployment
// resource.
func DeploymentManifest(opts *Options) (string, error) {
obj, err := deployment(opts)
// TillerManifests gets the Deployment, Service, and Secret (if tls-enabled) manifests
func TillerManifests(opts *Options) ([]string, error) {
dep, err := Deployment(opts)
if err != nil {
return "", err
return []string{}, err
}
svc := Service(opts.Namespace)
objs := []runtime.Object{dep, svc}
if opts.EnableTLS {
secret, err := Secret(opts)
if err != nil {
return []string{}, err
}
objs = append(objs, secret)
}
manifests := make([]string, len(objs))
for i, obj := range objs {
o, err := yaml.Marshal(obj)
if err != nil {
return []string{}, err
}
manifests[i] = string(o)
}
buf, err := yaml.Marshal(obj)
return string(buf), err
}
// ServiceManifest gets the manifest (as a string) that describes the Tiller Service
// resource.
func ServiceManifest(namespace string) (string, error) {
obj := service(namespace)
buf, err := yaml.Marshal(obj)
return string(buf), err
return manifests, err
}
func generateLabels(labels map[string]string) map[string]string {
@ -321,14 +350,20 @@ func generateService(namespace string) *v1.Service {
return s
}
// SecretManifest gets the manifest (as a string) that describes the Tiller Secret resource.
func SecretManifest(opts *Options) (string, error) {
o, err := generateSecret(opts)
// Secret gets a secret object that can be used to generate a manifest as a
// string. This object should not be submitted directly to the Kubernetes api
func Secret(opts *Options) (*v1.Secret, error) {
secret, err := generateSecret(opts)
if err != nil {
return "", err
return nil, err
}
secret.TypeMeta = metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
}
buf, err := yaml.Marshal(o)
return string(buf), err
return secret, nil
}
// createSecret creates the Tiller secret resource.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -34,7 +34,7 @@ import (
"k8s.io/helm/pkg/version"
)
func TestDeploymentManifest(t *testing.T) {
func TestDeployment(t *testing.T) {
tests := []struct {
name string
image string
@ -48,14 +48,10 @@ func TestDeploymentManifest(t *testing.T) {
}
for _, tt := range tests {
o, err := DeploymentManifest(&Options{Namespace: v1.NamespaceDefault, ImageSpec: tt.image, UseCanary: tt.canary})
dep, err := Deployment(&Options{Namespace: v1.NamespaceDefault, ImageSpec: tt.image, UseCanary: tt.canary})
if err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
var dep v1beta1.Deployment
if err := yaml.Unmarshal([]byte(o), &dep); err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
if got := dep.Spec.Template.Spec.Containers[0].Image; got != tt.expect {
t.Errorf("%s: expected image %q, got %q", tt.name, tt.expect, got)
@ -71,7 +67,7 @@ func TestDeploymentManifest(t *testing.T) {
}
}
func TestDeploymentManifestForServiceAccount(t *testing.T) {
func TestDeploymentForServiceAccount(t *testing.T) {
tests := []struct {
name string
image string
@ -84,22 +80,18 @@ func TestDeploymentManifestForServiceAccount(t *testing.T) {
{"withoutSA", "", false, "gcr.io/kubernetes-helm/tiller:latest", "IfNotPresent", ""},
}
for _, tt := range tests {
o, err := DeploymentManifest(&Options{Namespace: v1.NamespaceDefault, ImageSpec: tt.image, UseCanary: tt.canary, ServiceAccount: tt.serviceAccount})
d, err := Deployment(&Options{Namespace: v1.NamespaceDefault, ImageSpec: tt.image, UseCanary: tt.canary, ServiceAccount: tt.serviceAccount})
if err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
var d v1beta1.Deployment
if err := yaml.Unmarshal([]byte(o), &d); err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
if got := d.Spec.Template.Spec.ServiceAccountName; got != tt.serviceAccount {
t.Errorf("%s: expected service account value %q, got %q", tt.name, tt.serviceAccount, got)
}
}
}
func TestDeploymentManifest_WithTLS(t *testing.T) {
func TestDeployment_WithTLS(t *testing.T) {
tests := []struct {
opts Options
name string
@ -126,15 +118,11 @@ func TestDeploymentManifest_WithTLS(t *testing.T) {
},
}
for _, tt := range tests {
o, err := DeploymentManifest(&tt.opts)
d, err := Deployment(&tt.opts)
if err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
var d v1beta1.Deployment
if err := yaml.Unmarshal([]byte(o), &d); err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
// verify environment variable in deployment reflect the use of tls being enabled.
if got := d.Spec.Template.Spec.Containers[0].Env[2].Value; got != tt.verify {
t.Errorf("%s: expected tls verify env value %q, got %q", tt.name, tt.verify, got)
@ -146,14 +134,7 @@ func TestDeploymentManifest_WithTLS(t *testing.T) {
}
func TestServiceManifest(t *testing.T) {
o, err := ServiceManifest(v1.NamespaceDefault)
if err != nil {
t.Fatalf("error %q", err)
}
var svc v1.Service
if err := yaml.Unmarshal([]byte(o), &svc); err != nil {
t.Fatalf("error %q", err)
}
svc := Service(v1.NamespaceDefault)
if got := svc.ObjectMeta.Namespace; got != v1.NamespaceDefault {
t.Errorf("expected namespace %s, got %s", v1.NamespaceDefault, got)
@ -161,7 +142,7 @@ func TestServiceManifest(t *testing.T) {
}
func TestSecretManifest(t *testing.T) {
o, err := SecretManifest(&Options{
obj, err := Secret(&Options{
VerifyTLS: true,
EnableTLS: true,
Namespace: v1.NamespaceDefault,
@ -174,11 +155,6 @@ func TestSecretManifest(t *testing.T) {
t.Fatalf("error %q", err)
}
var obj v1.Secret
if err := yaml.Unmarshal([]byte(o), &obj); err != nil {
t.Fatalf("error %q", err)
}
if got := obj.ObjectMeta.Namespace; got != v1.NamespaceDefault {
t.Errorf("expected namespace %s, got %s", v1.NamespaceDefault, got)
}
@ -362,13 +338,13 @@ func TestInstall_canary(t *testing.T) {
func TestUpgrade(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:v2.0.0"
serviceAccount := "newServiceAccount"
existingDeployment, _ := deployment(&Options{
existingDeployment, _ := generateDeployment(&Options{
Namespace: v1.NamespaceDefault,
ImageSpec: "imageToReplace:v1.0.0",
ServiceAccount: "serviceAccountToReplace",
UseCanary: false,
})
existingService := service(v1.NamespaceDefault)
existingService := generateService(v1.NamespaceDefault)
fc := &fake.Clientset{}
fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
@ -403,7 +379,7 @@ func TestUpgrade(t *testing.T) {
func TestUpgrade_serviceNotFound(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:v2.0.0"
existingDeployment, _ := deployment(&Options{
existingDeployment, _ := generateDeployment(&Options{
Namespace: v1.NamespaceDefault,
ImageSpec: "imageToReplace",
UseCanary: false,
@ -446,13 +422,13 @@ func TestUpgrade_serviceNotFound(t *testing.T) {
func TestUgrade_newerVersion(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:v2.0.0"
serviceAccount := "newServiceAccount"
existingDeployment, _ := deployment(&Options{
existingDeployment, _ := generateDeployment(&Options{
Namespace: v1.NamespaceDefault,
ImageSpec: "imageToReplace:v100.5.0",
ServiceAccount: "serviceAccountToReplace",
UseCanary: false,
})
existingService := service(v1.NamespaceDefault)
existingService := generateService(v1.NamespaceDefault)
fc := &fake.Clientset{}
fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
@ -506,13 +482,13 @@ func TestUgrade_newerVersion(t *testing.T) {
func TestUpgrade_identical(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:v2.0.0"
serviceAccount := "newServiceAccount"
existingDeployment, _ := deployment(&Options{
existingDeployment, _ := generateDeployment(&Options{
Namespace: v1.NamespaceDefault,
ImageSpec: "imageToReplace:v2.0.0",
ServiceAccount: "serviceAccountToReplace",
UseCanary: false,
})
existingService := service(v1.NamespaceDefault)
existingService := generateService(v1.NamespaceDefault)
fc := &fake.Clientset{}
fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
@ -547,13 +523,13 @@ func TestUpgrade_identical(t *testing.T) {
func TestUpgrade_canaryClient(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:canary"
serviceAccount := "newServiceAccount"
existingDeployment, _ := deployment(&Options{
existingDeployment, _ := generateDeployment(&Options{
Namespace: v1.NamespaceDefault,
ImageSpec: "imageToReplace:v1.0.0",
ServiceAccount: "serviceAccountToReplace",
UseCanary: false,
})
existingService := service(v1.NamespaceDefault)
existingService := generateService(v1.NamespaceDefault)
fc := &fake.Clientset{}
fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
@ -588,13 +564,13 @@ func TestUpgrade_canaryClient(t *testing.T) {
func TestUpgrade_canaryServer(t *testing.T) {
image := "gcr.io/kubernetes-helm/tiller:v2.0.0"
serviceAccount := "newServiceAccount"
existingDeployment, _ := deployment(&Options{
existingDeployment, _ := generateDeployment(&Options{
Namespace: v1.NamespaceDefault,
ImageSpec: "imageToReplace:canary",
ServiceAccount: "serviceAccountToReplace",
UseCanary: false,
})
existingService := service(v1.NamespaceDefault)
existingService := generateService(v1.NamespaceDefault)
fc := &fake.Clientset{}
fc.AddReactor("get", "deployments", func(action testcore.Action) (bool, runtime.Object, error) {
@ -634,7 +610,8 @@ func tlsTestFile(t *testing.T, path string) string {
}
return path
}
func TestDeploymentManifest_WithNodeSelectors(t *testing.T) {
func TestDeployment_WithNodeSelectors(t *testing.T) {
tests := []struct {
opts Options
name string
@ -658,15 +635,11 @@ func TestDeploymentManifest_WithNodeSelectors(t *testing.T) {
},
}
for _, tt := range tests {
o, err := DeploymentManifest(&tt.opts)
d, err := Deployment(&tt.opts)
if err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
var d v1beta1.Deployment
if err := yaml.Unmarshal([]byte(o), &d); err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
// Verify that environment variables in Deployment reflect the use of TLS being enabled.
got := d.Spec.Template.Spec.NodeSelector
for k, v := range tt.expect {
@ -676,7 +649,8 @@ func TestDeploymentManifest_WithNodeSelectors(t *testing.T) {
}
}
}
func TestDeploymentManifest_WithSetValues(t *testing.T) {
func TestDeployment_WithSetValues(t *testing.T) {
tests := []struct {
opts Options
name string
@ -703,11 +677,17 @@ func TestDeploymentManifest_WithSetValues(t *testing.T) {
},
}
for _, tt := range tests {
o, err := DeploymentManifest(&tt.opts)
d, err := Deployment(&tt.opts)
if err != nil {
t.Fatalf("%s: error %q", tt.name, err)
}
values, err := chartutil.ReadValues([]byte(o))
o, err := yaml.Marshal(d)
if err != nil {
t.Errorf("Error marshaling Deployment: %s", err)
}
values, err := chartutil.ReadValues(o)
if err != nil {
t.Errorf("Error converting Deployment manifest to Values: %s", err)
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -50,7 +50,7 @@ type Options struct {
// Force allows to force upgrading tiller if deployed version is greater than current version
ForceUpgrade bool
// ImageSpec indentifies the image Tiller will use when deployed.
// ImageSpec identifies the image Tiller will use when deployed.
//
// Valid if and only if UseCanary is false.
ImageSpec string

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -47,6 +47,7 @@ type lintCmd struct {
valueFiles valueFiles
values []string
sValues []string
fValues []string
namespace string
strict bool
paths []string
@ -73,7 +74,8 @@ func newLintCmd(out io.Writer) *cobra.Command {
cmd.Flags().VarP(&l.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
cmd.Flags().StringArrayVar(&l.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringArrayVar(&l.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
cmd.Flags().StringVar(&l.namespace, "namespace", "default", "namespace to install the release into (only used if --install is set)")
cmd.Flags().StringArrayVar(&l.fValues, "set-file", []string{}, "set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)")
cmd.Flags().StringVar(&l.namespace, "namespace", "default", "namespace to put the release into")
cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings")
return cmd
@ -172,6 +174,12 @@ func lintChart(path string, vals []byte, namespace string, strict bool) (support
return lint.All(chartPath, vals, namespace, strict), nil
}
// vals merges values from files specified via -f/--values and
// directly via --set or --set-string or --set-file, marshaling them to YAML
//
// This func is implemented intentionally and separately from the `vals` func for the `install` and `upgrade` comammdsn.
// Compared to the alternative func, this func lacks the parameters for tls opts - ca key, cert, and ca cert.
// That's because this command, `lint`, is explicitly forbidden from making server connections.
func (l *lintCmd) vals() ([]byte, error) {
base := map[string]interface{}{}
@ -204,5 +212,16 @@ func (l *lintCmd) vals() ([]byte, error) {
}
}
// User specified a value via --set-file
for _, value := range l.fValues {
reader := func(rs []rune) (interface{}, error) {
bytes, err := ioutil.ReadFile(string(rs))
return string(bytes), err
}
if err := strvals.ParseIntoFile(value, base, reader); err != nil {
return []byte{}, fmt.Errorf("failed parsing --set-file data: %s", err)
}
}
return yaml.Marshal(base)
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -17,10 +17,12 @@ limitations under the License.
package main
import (
"encoding/json"
"fmt"
"io"
"strings"
"github.com/ghodss/yaml"
"github.com/gosuri/uitable"
"github.com/spf13/cobra"
@ -75,6 +77,22 @@ type listCmd struct {
pending bool
client helm.Interface
colWidth uint
output string
}
type listResult struct {
Next string
Releases []listRelease
}
type listRelease struct {
Name string
Revision int32
Updated string
Status string
Chart string
AppVersion string
Namespace string
}
func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
@ -114,6 +132,7 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&list.pending, "pending", false, "show pending releases")
f.StringVar(&list.namespace, "namespace", "", "show releases within a specific namespace")
f.UintVar(&list.colWidth, "col-width", 60, "specifies the max column width of output")
f.StringVar(&list.output, "output", "", "output the specified format (json or yaml)")
// TODO: Do we want this as a feature of 'helm list'?
//f.BoolVar(&list.superseded, "history", true, "show historical releases")
@ -147,24 +166,21 @@ func (l *listCmd) run() error {
if err != nil {
return prettyError(err)
}
if len(res.GetReleases()) == 0 {
if res == nil {
return nil
}
if res.Next != "" && !l.short {
fmt.Fprintf(l.out, "\tnext: %s\n", res.Next)
}
rels := filterList(res.GetReleases())
rels := filterList(res.Releases)
result := getListResult(rels, res.Next)
if l.short {
for _, r := range rels {
fmt.Fprintln(l.out, r.Name)
}
return nil
output, err := formatResult(l.output, l.short, result, l.colWidth)
if err != nil {
return prettyError(err)
}
fmt.Fprintln(l.out, formatList(rels, l.colWidth))
fmt.Fprintln(l.out, output)
return nil
}
@ -233,23 +249,98 @@ func (l *listCmd) statusCodes() []release.Status_Code {
return status
}
func formatList(rels []*release.Release, colWidth uint) string {
table := uitable.New()
table.MaxColWidth = colWidth
table.AddRow("NAME", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION", "NAMESPACE")
func getListResult(rels []*release.Release, next string) listResult {
listReleases := []listRelease{}
for _, r := range rels {
md := r.GetChart().GetMetadata()
c := fmt.Sprintf("%s-%s", md.GetName(), md.GetVersion())
t := "-"
if tspb := r.GetInfo().GetLastDeployed(); tspb != nil {
t = timeconv.String(tspb)
}
s := r.GetInfo().GetStatus().GetCode().String()
v := r.GetVersion()
a := md.GetAppVersion()
n := r.GetNamespace()
table.AddRow(r.GetName(), v, t, s, c, a, n)
lr := listRelease{
Name: r.GetName(),
Revision: r.GetVersion(),
Updated: t,
Status: r.GetInfo().GetStatus().GetCode().String(),
Chart: fmt.Sprintf("%s-%s", md.GetName(), md.GetVersion()),
AppVersion: md.GetAppVersion(),
Namespace: r.GetNamespace(),
}
listReleases = append(listReleases, lr)
}
return listResult{
Releases: listReleases,
Next: next,
}
return table.String()
}
func shortenListResult(result listResult) []string {
names := []string{}
for _, r := range result.Releases {
names = append(names, r.Name)
}
return names
}
func formatResult(format string, short bool, result listResult, colWidth uint) (string, error) {
var output string
var err error
var shortResult []string
var finalResult interface{}
if short {
shortResult = shortenListResult(result)
finalResult = shortResult
} else {
finalResult = result
}
switch format {
case "":
if short {
output = formatTextShort(shortResult)
} else {
output = formatText(result, colWidth)
}
case "json":
o, e := json.Marshal(finalResult)
if e != nil {
err = fmt.Errorf("Failed to Marshal JSON output: %s", e)
} else {
output = string(o)
}
case "yaml":
o, e := yaml.Marshal(finalResult)
if e != nil {
err = fmt.Errorf("Failed to Marshal YAML output: %s", e)
} else {
output = string(o)
}
default:
err = fmt.Errorf("Unknown output format \"%s\"", format)
}
return output, err
}
func formatText(result listResult, colWidth uint) string {
nextOutput := ""
if result.Next != "" {
nextOutput = fmt.Sprintf("\tnext: %s\n", result.Next)
}
table := uitable.New()
table.MaxColWidth = colWidth
table.AddRow("NAME", "REVISION", "UPDATED", "STATUS", "CHART", "APP VERSION", "NAMESPACE")
for _, lr := range result.Releases {
table.AddRow(lr.Name, lr.Revision, lr.Updated, lr.Status, lr.Chart, lr.AppVersion, lr.Namespace)
}
return fmt.Sprintf("%s%s", nextOutput, table.String())
}
func formatTextShort(shortResult []string) string {
return strings.Join(shortResult, "\n")
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -18,16 +18,18 @@ package main
import (
"io"
"regexp"
"testing"
"github.com/spf13/cobra"
"io/ioutil"
"os"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/proto/hapi/chart"
"k8s.io/helm/pkg/proto/hapi/release"
"os"
)
func TestListCmd(t *testing.T) {
@ -46,6 +48,11 @@ func TestListCmd(t *testing.T) {
ch, _ := chartutil.Load(chartPath)
tests := []releaseCase{
{
name: "empty",
rels: []*release.Release{},
expected: "",
},
{
name: "with a release",
rels: []*release.Release{
@ -67,6 +74,77 @@ func TestListCmd(t *testing.T) {
},
expected: "NAME \tREVISION\tUPDATED \tSTATUS \tCHART \tAPP VERSION\tNAMESPACE\natlas\t1 \t(.*)\tDEPLOYED\tfoo-0.1.0-beta.1\t2.X.A \tdefault \n",
},
{
name: "with json output",
flags: []string{"--max", "1", "--output", "json"},
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide"}),
},
expected: regexp.QuoteMeta(`{"Next":"atlas-guide","Releases":[{"Name":"thomas-guide","Revision":1,"Updated":"`) + `([^"]*)` + regexp.QuoteMeta(`","Status":"DEPLOYED","Chart":"foo-0.1.0-beta.1","AppVersion":"","Namespace":"default"}]}
`),
},
{
name: "with yaml output",
flags: []string{"--max", "1", "--output", "yaml"},
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "thomas-guide"}),
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas-guide"}),
},
expected: regexp.QuoteMeta(`Next: atlas-guide
Releases:
- AppVersion: ""
Chart: foo-0.1.0-beta.1
Name: thomas-guide
Namespace: default
Revision: 1
Status: DEPLOYED
Updated: `) + `(.*)` + `
`,
},
{
name: "with short json output",
flags: []string{"-q", "--output", "json"},
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas"}),
},
expected: regexp.QuoteMeta(`["atlas"]
`),
},
{
name: "with short yaml output",
flags: []string{"-q", "--output", "yaml"},
rels: []*release.Release{
helm.ReleaseMock(&helm.MockReleaseOptions{Name: "atlas"}),
},
expected: regexp.QuoteMeta(`- atlas
`),
},
{
name: "with json output without next",
flags: []string{"--output", "json"},
rels: []*release.Release{},
expected: regexp.QuoteMeta(`{"Next":"","Releases":[]}
`),
},
{
name: "with yaml output without next",
flags: []string{"--output", "yaml"},
rels: []*release.Release{},
expected: regexp.QuoteMeta(`Next: ""
Releases: []
`),
},
{
name: "with unknown output format",
flags: []string{"--output", "_unknown_"},
rels: []*release.Release{},
err: true,
expected: regexp.QuoteMeta(``),
},
{
name: "list, one deployed, one failed",
flags: []string{"-q"},

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
@ -22,12 +22,18 @@ import (
"os/exec"
"path/filepath"
"strings"
"syscall"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/plugin"
)
type pluginError struct {
error
code int
}
// loadPlugins loads plugins into the command list.
//
// This follows a different pattern than the other commands because it has
@ -87,7 +93,11 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
if err := prog.Run(); err != nil {
if eerr, ok := err.(*exec.ExitError); ok {
os.Stderr.Write(eerr.Stderr)
return fmt.Errorf("plugin %q exited with error", md.Name)
status := eerr.Sys().(syscall.WaitStatus)
return pluginError{
error: fmt.Errorf("plugin %q exited with error", md.Name),
code: status.ExitStatus(),
}
}
return err
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -91,7 +91,7 @@ func index(dir, url, mergeTo string) error {
var i2 *repo.IndexFile
if _, err := os.Stat(mergeTo); os.IsNotExist(err) {
i2 = repo.NewIndexFile()
i2.WriteFile(mergeTo, 0755)
i2.WriteFile(mergeTo, 0644)
} else {
i2, err = repo.LoadIndexFile(mergeTo)
if err != nil {
@ -101,5 +101,5 @@ func index(dir, url, mergeTo string) error {
i.Merge(i2)
}
i.SortEntries()
return i.WriteFile(out, 0755)
return i.WriteFile(out, 0644)
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -86,7 +86,7 @@ func newResetCmd(client helm.Interface, out io.Writer) *cobra.Command {
// runReset uninstalls tiller from Kubernetes Cluster and deletes local config
func (d *resetCmd) run() error {
if d.kubeClient == nil {
c, err := getInternalKubeClient(settings.KubeContext)
c, err := getInternalKubeClient(settings.KubeContext, settings.KubeConfig)
if err != nil {
return fmt.Errorf("could not get kubernetes client: %s", err)
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -45,6 +45,7 @@ type rollbackCmd struct {
client helm.Interface
timeout int64
wait bool
description string
}
func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
@ -83,6 +84,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&rollback.disableHooks, "no-hooks", false, "prevent hooks from running during rollback")
f.Int64Var(&rollback.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.StringVar(&rollback.description, "description", "", "specify a description for the release")
return cmd
}
@ -96,7 +98,8 @@ func (r *rollbackCmd) run() error {
helm.RollbackDisableHooks(r.disableHooks),
helm.RollbackVersion(r.revision),
helm.RollbackTimeout(r.timeout),
helm.RollbackWait(r.wait))
helm.RollbackWait(r.wait),
helm.RollbackDescription(r.description))
if err != nil {
return prettyError(err)
}

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -45,6 +45,12 @@ func TestRollbackCmd(t *testing.T) {
flags: []string{"--wait"},
expected: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release with description",
args: []string{"funny-honey", "1"},
flags: []string{"--description", "foo"},
expected: "Rollback was a success! Happy Helming!",
},
{
name: "rollback a release without revision",
args: []string{"funny-honey"},

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save