Merge branch 'master' into no-upgrade-existing

pull/5290/head
Michael FIG 7 years ago committed by GitHub
commit 99b750cc9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,17 +0,0 @@
version: "{build}"
clone_folder: c:\go\src\k8s.io\helm
environment:
GOPATH: c:\go
PATH: c:\ProgramData\bin;$(PATH)
install:
- ps: iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/fishworks/gofish/master/scripts/install.ps1'))
- gofish init
- gofish install glide
- glide install --strip-vendor
cache:
- vendor -> glide.lock
build: "off"
deploy: "off"
test_script:
- go build .\cmd\...
- go test .\...

@ -4,13 +4,13 @@ jobs:
working_directory: /go/src/k8s.io/helm working_directory: /go/src/k8s.io/helm
parallelism: 3 parallelism: 3
docker: docker:
- image: golang:1.11 - image: golang:1.12.1
environment: environment:
PROJECT_NAME: "kubernetes-helm" PROJECT_NAME: "kubernetes-helm"
steps: steps:
- checkout - checkout
- setup_remote_docker: - setup_remote_docker:
version: 17.09.0-ce version: 18.06.0-ce
- restore_cache: - restore_cache:
keys: keys:
- glide-{{ checksum "glide.yaml" }}-{{ checksum "glide.lock" }} - glide-{{ checksum "glide.yaml" }}-{{ checksum "glide.lock" }}

5
.gitignore vendored

@ -12,3 +12,8 @@ vendor/
*.exe *.exe
.idea/ .idea/
*.iml *.iml
*.swp
*~
.classpath
.project
.settings/**

@ -1,6 +1,6 @@
# Contributing Guidelines # Contributing Guidelines
The Kubernetes Helm project accepts contributions via GitHub pull requests. This document outlines the process to help get your contribution accepted. The Helm project accepts contributions via GitHub pull requests. This document outlines the process to help get your contribution accepted.
## Reporting a Security Issue ## Reporting a Security Issue
@ -15,7 +15,7 @@ us a chance to try to fix the issue before it is exploited in the wild.
The sign-off is a simple line at the end of the explanation for a commit. All The sign-off is a simple line at the end of the explanation for a commit. All
commits needs to be signed. Your signature certifies that you wrote the patch or commits needs to be signed. Your signature certifies that you wrote the patch or
otherwise have the right to contribute the material. The rules are pretty simple, otherwise have the right to contribute the material. The rules are pretty simple,
if you can certify the below (from [developercertificate.org](http://developercertificate.org/)): if you can certify the below (from [developercertificate.org](https://developercertificate.org/)):
``` ```
Developer Certificate of Origin Developer Certificate of Origin
@ -242,7 +242,7 @@ Documentation PRs will follow the same lifecycle as other PRs. They will also be
## The Triager ## The Triager
Each week, one of the core maintainers will serve as the designated "triager" starting after the Each week, one of the core maintainers will serve as the designated "triager" starting after the
public standup meetings on Thursday. This person will be in charge triaging new PRs and issues public stand-up meetings on Thursday. This person will be in charge triaging new PRs and issues
throughout the work week. throughout the work week.
## Labels ## Labels

@ -1,9 +1,10 @@
DOCKER_REGISTRY ?= gcr.io DOCKER_REGISTRY ?= gcr.io
IMAGE_PREFIX ?= kubernetes-helm IMAGE_PREFIX ?= kubernetes-helm
DEV_IMAGE ?= golang:1.11 DEV_IMAGE ?= golang:1.12.1
SHORT_NAME ?= tiller SHORT_NAME ?= tiller
SHORT_NAME_RUDDER ?= rudder SHORT_NAME_RUDDER ?= rudder
TARGETS ?= darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64 TARGETS ?= darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64
TARGET_OBJS ?= darwin-amd64.tar.gz darwin-amd64.tar.gz.sha256 linux-amd64.tar.gz linux-amd64.tar.gz.sha256 linux-386.tar.gz linux-386.tar.gz.sha256 linux-arm.tar.gz linux-arm.tar.gz.sha256 linux-arm64.tar.gz linux-arm64.tar.gz.sha256 linux-ppc64le.tar.gz linux-ppc64le.tar.gz.sha256 linux-s390x.tar.gz linux-s390x.tar.gz.sha256 windows-amd64.zip windows-amd64.zip.sha256
DIST_DIRS = find * -type d -exec DIST_DIRS = find * -type d -exec
# go option # go option
@ -44,10 +45,25 @@ dist:
$(DIST_DIRS) zip -r helm-${VERSION}-{}.zip {} \; \ $(DIST_DIRS) zip -r helm-${VERSION}-{}.zip {} \; \
) )
.PHONY: fetch-dist
fetch-dist:
mkdir -p _dist
cd _dist && \
for obj in ${TARGET_OBJS} ; do \
curl -sSL -o helm-${VERSION}-$${obj} https://storage.googleapis.com/kubernetes-helm/helm-${VERSION}-$${obj} ; \
done
.PHONY: sign
sign:
for f in _dist/*.{gz,zip,sha256} ; do \
gpg --armor --detach-sign $${f} ; \
done
.PHONY: checksum .PHONY: checksum
checksum: checksum:
for f in _dist/*.{gz,zip} ; do \ for f in _dist/*.{gz,zip} ; do \
shasum -a 256 "$${f}" | awk '{print $$1}' > "$${f}.sha256" ; \ shasum -a 256 "$${f}" | awk '{print $$1}' > "$${f}.sha256" ; \
echo -n "Checksum: " && cat $${f}.sha256 ; \
done done
.PHONY: check-docker .PHONY: check-docker

@ -3,7 +3,7 @@ Protobuf3 type declarations for the Helm API
Packages Packages
- `hapi.chart` Complete serialization of Heml charts - `hapi.chart` Complete serialization of Helm charts
- `hapi.release` Information about installed charts (Releases) such as metadata about when they were installed, their status, and how they were configured. - `hapi.release` Information about installed charts (Releases) such as metadata about when they were installed, their status, and how they were configured.
- `hapi.services.rudder` Definition for the ReleaseModuleService used by Tiller to manipulate releases on a given node - `hapi.services.rudder` Definition for the ReleaseModuleService used by Tiller to manipulate releases on a given node
- `hapi.services.tiller` Definition of the ReleaseService provided by Tiller and used by Helm clients to manipulate releases cluster wide. - `hapi.services.tiller` Definition of the ReleaseService provided by Tiller and used by Helm clients to manipulate releases cluster wide.

@ -29,7 +29,7 @@ message Status {
UNKNOWN = 0; UNKNOWN = 0;
// Status_DEPLOYED indicates that the release has been pushed to Kubernetes. // Status_DEPLOYED indicates that the release has been pushed to Kubernetes.
DEPLOYED = 1; DEPLOYED = 1;
// Status_DELETED indicates that a release has been deleted from Kubermetes. // Status_DELETED indicates that a release has been deleted from Kubernetes.
DELETED = 2; DELETED = 2;
// Status_SUPERSEDED indicates that this release object is outdated and a newer one exists. // Status_SUPERSEDED indicates that this release object is outdated and a newer one exists.
SUPERSEDED = 3; SUPERSEDED = 3;

@ -212,7 +212,8 @@ __helm_convert_bash_to_zsh() {
-e "s/${LWORD}compopt${RWORD}/__helm_compopt/g" \ -e "s/${LWORD}compopt${RWORD}/__helm_compopt/g" \
-e "s/${LWORD}declare${RWORD}/__helm_declare/g" \ -e "s/${LWORD}declare${RWORD}/__helm_declare/g" \
-e "s/\\\$(type${RWORD}/\$(__helm_type/g" \ -e "s/\\\$(type${RWORD}/\$(__helm_type/g" \
-e 's/aliashash\["\(\w\+\)"\]/aliashash[\1]/g' \ -e 's/aliashash\["\(.\{1,\}\)"\]/aliashash[\1]/g' \
-e 's/FUNCNAME/funcstack/g' \
<<'BASH_COMPLETION_EOF' <<'BASH_COMPLETION_EOF'
` `
out.Write([]byte(zshInitialization)) out.Write([]byte(zshInitialization))

@ -29,11 +29,11 @@ const dependencyBuildDesc = `
Build out the charts/ directory from the requirements.lock file. Build out the charts/ directory from the requirements.lock file.
Build is used to reconstruct a chart's dependencies to the state specified in Build is used to reconstruct a chart's dependencies to the state specified in
the lock file. This will not re-negotiate dependencies, as 'helm dependency update' the lock file.
does.
If no lock file is found, 'helm dependency build' will mirror the behavior If no lock file is found, 'helm dependency build' will mirror the behavior of
of 'helm dependency update'. the 'helm dependency update' command. This means it will update the on-disk
dependencies to mirror the requirements.yaml file and generate a lock file.
` `
type dependencyBuildCmd struct { type dependencyBuildCmd struct {

@ -30,6 +30,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/client-go/util/homedir" "k8s.io/client-go/util/homedir"
"k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
@ -137,7 +138,7 @@ func ensureTestHome(home helmpath.Home, t *testing.T) error {
} }
} }
localRepoIndexFile := home.LocalRepository(localRepositoryIndexFile) localRepoIndexFile := home.LocalRepository(installer.LocalRepositoryIndexFile)
if fi, err := os.Stat(localRepoIndexFile); err != nil { if fi, err := os.Stat(localRepoIndexFile); err != nil {
i := repo.NewIndexFile() i := repo.NewIndexFile()
if err := i.WriteFile(localRepoIndexFile, 0644); err != nil { if err := i.WriteFile(localRepoIndexFile, 0644); err != nil {

@ -31,11 +31,9 @@ import (
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/helm/cmd/helm/installer" "k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/helm/portforwarder" "k8s.io/helm/pkg/helm/portforwarder"
"k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/version" "k8s.io/helm/pkg/version"
) )
@ -60,12 +58,6 @@ To dump a manifest containing the Tiller deployment YAML, combine the
'--dry-run' and '--debug' flags. '--dry-run' and '--debug' flags.
` `
const (
stableRepository = "stable"
localRepository = "local"
localRepositoryIndexFile = "index.yaml"
)
var ( var (
stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com" stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com"
// This is the IPv4 loopback, not localhost, because we have to force IPv4 // This is the IPv4 loopback, not localhost, because we have to force IPv4
@ -266,14 +258,8 @@ func (i *initCmd) run() error {
return nil return nil
} }
if err := ensureDirectories(i.home, i.out); err != nil { if err := installer.Initialize(i.home, i.out, i.skipRefresh, settings, stableRepositoryURL, localRepositoryURL); err != nil {
return err return fmt.Errorf("error initializing: %s", err)
}
if err := ensureDefaultRepos(i.home, i.out, i.skipRefresh); err != nil {
return err
}
if err := ensureRepoFileFormat(i.home.RepositoryFile(), i.out); err != nil {
return err
} }
fmt.Fprintf(i.out, "$HELM_HOME has been configured at %s.\n", settings.Home) fmt.Fprintf(i.out, "$HELM_HOME has been configured at %s.\n", settings.Home)
@ -351,117 +337,6 @@ func (i *initCmd) ping(image string) error {
return nil return nil
} }
// ensureDirectories checks to see if $HELM_HOME exists.
//
// If $HELM_HOME does not exist, this function will create it.
func ensureDirectories(home helmpath.Home, out io.Writer) error {
configDirectories := []string{
home.String(),
home.Repository(),
home.Cache(),
home.LocalRepository(),
home.Plugins(),
home.Starters(),
home.Archive(),
}
for _, p := range configDirectories {
if fi, err := os.Stat(p); err != nil {
fmt.Fprintf(out, "Creating %s \n", p)
if err := os.MkdirAll(p, 0755); err != nil {
return fmt.Errorf("Could not create %s: %s", p, err)
}
} else if !fi.IsDir() {
return fmt.Errorf("%s must be a directory", p)
}
}
return nil
}
func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool) error {
repoFile := home.RepositoryFile()
if fi, err := os.Stat(repoFile); err != nil {
fmt.Fprintf(out, "Creating %s \n", repoFile)
f := repo.NewRepoFile()
sr, err := initStableRepo(home.CacheIndex(stableRepository), out, skipRefresh, home)
if err != nil {
return err
}
lr, err := initLocalRepo(home.LocalRepository(localRepositoryIndexFile), home.CacheIndex("local"), out, home)
if err != nil {
return err
}
f.Add(sr)
f.Add(lr)
if err := f.WriteFile(repoFile, 0644); err != nil {
return err
}
} else if fi.IsDir() {
return fmt.Errorf("%s must be a file, not a directory", repoFile)
}
return nil
}
func initStableRepo(cacheFile string, out io.Writer, skipRefresh bool, home helmpath.Home) (*repo.Entry, error) {
fmt.Fprintf(out, "Adding %s repo with URL: %s \n", stableRepository, stableRepositoryURL)
c := repo.Entry{
Name: stableRepository,
URL: stableRepositoryURL,
Cache: cacheFile,
}
r, err := repo.NewChartRepository(&c, getter.All(settings))
if err != nil {
return nil, err
}
if skipRefresh {
return &c, nil
}
// In this case, the cacheFile is always absolute. So passing empty string
// is safe.
if err := r.DownloadIndexFile(""); err != nil {
return nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", stableRepositoryURL, err.Error())
}
return &c, nil
}
func initLocalRepo(indexFile, cacheFile string, out io.Writer, home helmpath.Home) (*repo.Entry, error) {
if fi, err := os.Stat(indexFile); err != nil {
fmt.Fprintf(out, "Adding %s repo with URL: %s \n", localRepository, localRepositoryURL)
i := repo.NewIndexFile()
if err := i.WriteFile(indexFile, 0644); err != nil {
return nil, err
}
//TODO: take this out and replace with helm update functionality
if err := createLink(indexFile, cacheFile, home); err != nil {
return nil, err
}
} else if fi.IsDir() {
return nil, fmt.Errorf("%s must be a file, not a directory", indexFile)
}
return &repo.Entry{
Name: localRepository,
URL: localRepositoryURL,
Cache: cacheFile,
}, nil
}
func ensureRepoFileFormat(file string, out io.Writer) error {
r, err := repo.LoadRepositoriesFile(file)
if err == repo.ErrRepoOutOfDate {
fmt.Fprintln(out, "Updating repository file format...")
if err := r.WriteFile(file, 0644); err != nil {
return err
}
}
return nil
}
// watchTillerUntilReady waits for the tiller pod to become available. This is useful in situations where we // watchTillerUntilReady waits for the tiller pod to become available. This is useful in situations where we
// want to wait before we call New(). // want to wait before we call New().
// //

@ -28,7 +28,7 @@ import (
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1" "k8s.io/api/extensions/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -179,51 +179,6 @@ func TestInitCmd_dryRun(t *testing.T) {
} }
} }
func TestEnsureHome(t *testing.T) {
home, err := ioutil.TempDir("", "helm_home")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(home)
b := bytes.NewBuffer(nil)
hh := helmpath.Home(home)
settings.Home = hh
if err := ensureDirectories(hh, b); err != nil {
t.Error(err)
}
if err := ensureDefaultRepos(hh, b, false); err != nil {
t.Error(err)
}
if err := ensureDefaultRepos(hh, b, true); err != nil {
t.Error(err)
}
if err := ensureRepoFileFormat(hh.RepositoryFile(), b); err != nil {
t.Error(err)
}
expectedDirs := []string{hh.String(), hh.Repository(), hh.Cache(), hh.LocalRepository()}
for _, dir := range expectedDirs {
if fi, err := os.Stat(dir); err != nil {
t.Errorf("%s", err)
} else if !fi.IsDir() {
t.Errorf("%s is not a directory", fi)
}
}
if fi, err := os.Stat(hh.RepositoryFile()); err != nil {
t.Error(err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
if fi, err := os.Stat(hh.LocalRepository(localRepositoryIndexFile)); err != nil {
t.Errorf("%s", err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
}
func TestInitCmd_tlsOptions(t *testing.T) { func TestInitCmd_tlsOptions(t *testing.T) {
const testDir = "../../testdata" const testDir = "../../testdata"

@ -0,0 +1,163 @@
/*
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package installer // import "k8s.io/helm/cmd/helm/installer"
import (
"fmt"
"io"
"os"
"k8s.io/helm/pkg/getter"
helm_env "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo"
)
const (
stableRepository = "stable"
// LocalRepository is the standard name of the local repository
LocalRepository = "local"
// LocalRepositoryIndexFile is the standard name of the local repository index file
LocalRepositoryIndexFile = "index.yaml"
)
// Initialize initializes local config
//
// Returns an error if the command failed.
func Initialize(home helmpath.Home, out io.Writer, skipRefresh bool, settings helm_env.EnvSettings, stableRepositoryURL, localRepositoryURL string) error {
if err := ensureDirectories(home, out); err != nil {
return err
}
if err := ensureDefaultRepos(home, out, skipRefresh, settings, stableRepositoryURL, localRepositoryURL); err != nil {
return err
}
return ensureRepoFileFormat(home.RepositoryFile(), out)
}
// ensureDirectories checks to see if $HELM_HOME exists.
//
// If $HELM_HOME does not exist, this function will create it.
func ensureDirectories(home helmpath.Home, out io.Writer) error {
configDirectories := []string{
home.String(),
home.Repository(),
home.Cache(),
home.LocalRepository(),
home.Plugins(),
home.Starters(),
home.Archive(),
}
for _, p := range configDirectories {
if fi, err := os.Stat(p); err != nil {
fmt.Fprintf(out, "Creating %s \n", p)
if err := os.MkdirAll(p, 0755); err != nil {
return fmt.Errorf("Could not create %s: %s", p, err)
}
} else if !fi.IsDir() {
return fmt.Errorf("%s must be a directory", p)
}
}
return nil
}
func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool, settings helm_env.EnvSettings, stableRepositoryURL, localRepositoryURL string) error {
repoFile := home.RepositoryFile()
if fi, err := os.Stat(repoFile); err != nil {
fmt.Fprintf(out, "Creating %s \n", repoFile)
f := repo.NewRepoFile()
sr, err := initStableRepo(home.CacheIndex(stableRepository), home, out, skipRefresh, settings, stableRepositoryURL)
if err != nil {
return err
}
lr, err := initLocalRepo(home.LocalRepository(LocalRepositoryIndexFile), home.CacheIndex("local"), home, out, settings, localRepositoryURL)
if err != nil {
return err
}
f.Add(sr)
f.Add(lr)
if err := f.WriteFile(repoFile, 0644); err != nil {
return err
}
} else if fi.IsDir() {
return fmt.Errorf("%s must be a file, not a directory", repoFile)
}
return nil
}
func initStableRepo(cacheFile string, home helmpath.Home, out io.Writer, skipRefresh bool, settings helm_env.EnvSettings, stableRepositoryURL string) (*repo.Entry, error) {
fmt.Fprintf(out, "Adding %s repo with URL: %s \n", stableRepository, stableRepositoryURL)
c := repo.Entry{
Name: stableRepository,
URL: stableRepositoryURL,
Cache: cacheFile,
}
r, err := repo.NewChartRepository(&c, getter.All(settings))
if err != nil {
return nil, err
}
if skipRefresh {
return &c, nil
}
// In this case, the cacheFile is always absolute. So passing empty string
// is safe.
if err := r.DownloadIndexFile(""); err != nil {
return nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", stableRepositoryURL, err.Error())
}
return &c, nil
}
func initLocalRepo(indexFile, cacheFile string, home helmpath.Home, out io.Writer, settings helm_env.EnvSettings, localRepositoryURL string) (*repo.Entry, error) {
if fi, err := os.Stat(indexFile); err != nil {
fmt.Fprintf(out, "Adding %s repo with URL: %s \n", LocalRepository, localRepositoryURL)
i := repo.NewIndexFile()
if err := i.WriteFile(indexFile, 0644); err != nil {
return nil, err
}
//TODO: take this out and replace with helm update functionality
if err := createLink(indexFile, cacheFile, home); err != nil {
return nil, err
}
} else if fi.IsDir() {
return nil, fmt.Errorf("%s must be a file, not a directory", indexFile)
}
return &repo.Entry{
Name: LocalRepository,
URL: localRepositoryURL,
Cache: cacheFile,
}, nil
}
func ensureRepoFileFormat(file string, out io.Writer) error {
r, err := repo.LoadRepositoriesFile(file)
if err == repo.ErrRepoOutOfDate {
fmt.Fprintln(out, "Updating repository file format...")
if err := r.WriteFile(file, 0644); err != nil {
return err
}
}
return nil
}

@ -0,0 +1,120 @@
/*
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package installer // import "k8s.io/helm/cmd/helm/installer"
import (
"bytes"
"io/ioutil"
"os"
"testing"
helm_env "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
)
func TestInitialize(t *testing.T) {
home, err := ioutil.TempDir("", "helm_home")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(home)
b := bytes.NewBuffer(nil)
hh := helmpath.Home(home)
settings := helm_env.EnvSettings{
Home: hh,
}
stableRepositoryURL := "https://kubernetes-charts.storage.googleapis.com"
localRepositoryURL := "http://127.0.0.1:8879/charts"
if err := Initialize(hh, b, false, settings, stableRepositoryURL, localRepositoryURL); err != nil {
t.Error(err)
}
expectedDirs := []string{hh.String(), hh.Repository(), hh.Cache(), hh.LocalRepository()}
for _, dir := range expectedDirs {
if fi, err := os.Stat(dir); err != nil {
t.Errorf("%s", err)
} else if !fi.IsDir() {
t.Errorf("%s is not a directory", fi)
}
}
if fi, err := os.Stat(hh.RepositoryFile()); err != nil {
t.Error(err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
if fi, err := os.Stat(hh.LocalRepository(LocalRepositoryIndexFile)); err != nil {
t.Errorf("%s", err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
}
func TestEnsureHome(t *testing.T) {
home, err := ioutil.TempDir("", "helm_home")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(home)
b := bytes.NewBuffer(nil)
hh := helmpath.Home(home)
settings := helm_env.EnvSettings{
Home: hh,
}
stableRepositoryURL := "https://kubernetes-charts.storage.googleapis.com"
localRepositoryURL := "http://127.0.0.1:8879/charts"
if err := ensureDirectories(hh, b); err != nil {
t.Error(err)
}
if err := ensureDefaultRepos(hh, b, false, settings, stableRepositoryURL, localRepositoryURL); err != nil {
t.Error(err)
}
if err := ensureDefaultRepos(hh, b, true, settings, stableRepositoryURL, localRepositoryURL); err != nil {
t.Error(err)
}
if err := ensureRepoFileFormat(hh.RepositoryFile(), b); err != nil {
t.Error(err)
}
expectedDirs := []string{hh.String(), hh.Repository(), hh.Cache(), hh.LocalRepository()}
for _, dir := range expectedDirs {
if fi, err := os.Stat(dir); err != nil {
t.Errorf("%s", err)
} else if !fi.IsDir() {
t.Errorf("%s is not a directory", fi)
}
}
if fi, err := os.Stat(hh.RepositoryFile()); err != nil {
t.Error(err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
if fi, err := os.Stat(hh.LocalRepository(LocalRepositoryIndexFile)); err != nil {
t.Errorf("%s", err)
} else if fi.IsDir() {
t.Errorf("%s should not be a directory", fi)
}
}

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package main package installer // import "k8s.io/helm/cmd/helm/installer"
import ( import (
"os" "os"

@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package main package installer // import "k8s.io/helm/cmd/helm/installer"
import ( import (
"os" "os"

@ -31,13 +31,13 @@ const (
// Uninstall uses Kubernetes client to uninstall Tiller. // Uninstall uses Kubernetes client to uninstall Tiller.
func Uninstall(client kubernetes.Interface, opts *Options) error { func Uninstall(client kubernetes.Interface, opts *Options) error {
if err := deleteService(client.Core(), opts.Namespace); err != nil { if err := deleteService(client.CoreV1(), opts.Namespace); err != nil {
return err return err
} }
if err := deleteDeployment(client, opts.Namespace); err != nil { if err := deleteDeployment(client, opts.Namespace); err != nil {
return err return err
} }
return deleteSecret(client.Core(), opts.Namespace) return deleteSecret(client.CoreV1(), opts.Namespace)
} }
// deleteService deletes the Tiller Service resource // deleteService deletes the Tiller Service resource

@ -24,6 +24,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
@ -99,7 +100,7 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer, home helmpath.Ho
wg.Add(1) wg.Add(1)
go func(re *repo.ChartRepository) { go func(re *repo.ChartRepository) {
defer wg.Done() defer wg.Done()
if re.Config.Name == localRepository { if re.Config.Name == installer.LocalRepository {
mu.Lock() mu.Lock()
fmt.Fprintf(out, "...Skip %s chart repository\n", re.Config.Name) fmt.Fprintf(out, "...Skip %s chart repository\n", re.Config.Name)
mu.Unlock() mu.Unlock()
@ -124,6 +125,6 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer, home helmpath.Ho
return errors.New("Update Failed. Check log for details") return errors.New("Update Failed. Check log for details")
} }
fmt.Fprintln(out, "Update Complete. ⎈ Happy Helming! ") fmt.Fprintln(out, "Update Complete. ⎈ Happy Helming! ")
return nil return nil
} }

@ -27,7 +27,7 @@ import (
const verifyDesc = ` const verifyDesc = `
Verify that the given chart has a valid provenance file. Verify that the given chart has a valid provenance file.
Provenance files provide crytographic verification that a chart has not been Provenance files provide cryptographic verification that a chart has not been
tampered with, and was packaged by a trusted provider. tampered with, and was packaged by a trusted provider.
This command can be used to verify a local chart. Several other commands provide This command can be used to verify a local chart. Several other commands provide

@ -36,6 +36,7 @@ import (
"google.golang.org/grpc/health" "google.golang.org/grpc/health"
healthpb "google.golang.org/grpc/health/grpc_health_v1" healthpb "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/keepalive" "google.golang.org/grpc/keepalive"
"k8s.io/klog"
// Import to initialize client auth plugins. // Import to initialize client auth plugins.
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
@ -100,6 +101,7 @@ var (
) )
func main() { func main() {
klog.InitFlags(nil)
// TODO: use spf13/cobra for tiller instead of flags // TODO: use spf13/cobra for tiller instead of flags
flag.Parse() flag.Parse()

@ -22,7 +22,7 @@ The directory that contains a chart MUST have the same name as the chart. Thus,
## Version Numbers ## Version Numbers
Wherever possible, Helm uses [SemVer 2](http://semver.org) to represent version numbers. (Note that Docker image tags do not necessarily follow SemVer, and are thus considered an unfortunate exception to the rule.) Wherever possible, Helm uses [SemVer 2](https://semver.org) to represent version numbers. (Note that Docker image tags do not necessarily follow SemVer, and are thus considered an unfortunate exception to the rule.)
When SemVer versions are stored in Kubernetes labels, we conventionally alter the `+` character to an `_` character, as labels do not allow the `+` sign as a value. When SemVer versions are stored in Kubernetes labels, we conventionally alter the `+` character to an `_` character, as labels do not allow the `+` sign as a value.

@ -329,7 +329,7 @@ data:
- "Onions" - "Onions"
``` ```
Now, in this example we've done something tricky. The `toppings: |-` line is declaring a multi-line string. So our list of toppings is actually not a YAML list. It's a big string. Why would we do this? Because the data in ConfigMaps `data` is composed of key/value pairs, where both the key and the value are simple strings. To understand why this is the case, take a look at the [Kubernetes ConfigMap docs](http://kubernetes.io/docs/user-guide/configmap/). For us, though, this detail doesn't matter much. Now, in this example we've done something tricky. The `toppings: |-` line is declaring a multi-line string. So our list of toppings is actually not a YAML list. It's a big string. Why would we do this? Because the data in ConfigMaps `data` is composed of key/value pairs, where both the key and the value are simple strings. To understand why this is the case, take a look at the [Kubernetes ConfigMap docs](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/). For us, though, this detail doesn't matter much.
> The `|-` marker in YAML takes a multi-line string. This can be a useful technique for embedding big blocks of data inside of your manifests, as exemplified here. > The `|-` marker in YAML takes a multi-line string. This can be a useful technique for embedding big blocks of data inside of your manifests, as exemplified here.

@ -150,7 +150,7 @@ Template functions and pipelines are a powerful way to transform information and
## Operators are functions ## Operators are functions
Operators are implemented as functions that return a boolean value. To use `eq`, `ne`, `lt`, `gt`, `and`, `or`, `not` etcetera place the operator at the front of the statement followed by its parameters just as you would a function. To chain multiple operations together, separate individual functions by surrounding them with paranthesis. Operators are implemented as functions that return a boolean value. To use `eq`, `ne`, `lt`, `gt`, `and`, `or`, `not` etcetera place the operator at the front of the statement followed by its parameters just as you would a function. To chain multiple operations together, separate individual functions by surrounding them with parentheses.
```yaml ```yaml
{{/* include the body of this if statement when the variable .Values.fooString exists and is set to "foo" */}} {{/* include the body of this if statement when the variable .Values.fooString exists and is set to "foo" */}}

@ -51,8 +51,8 @@ already there.
- `NOTES.txt`: The "help text" for your chart. This will be displayed to your users - `NOTES.txt`: The "help text" for your chart. This will be displayed to your users
when they run `helm install`. when they run `helm install`.
- `deployment.yaml`: A basic manifest for creating a Kubernetes [deployment](http://kubernetes.io/docs/user-guide/deployments/) - `deployment.yaml`: A basic manifest for creating a Kubernetes [deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- `service.yaml`: A basic manifest for creating a [service endpoint](http://kubernetes.io/docs/user-guide/services/) for your deployment - `service.yaml`: A basic manifest for creating a [service endpoint](https://kubernetes.io/docs/concepts/services-networking/service/) for your deployment
- `_helpers.tpl`: A place to put template helpers that you can re-use throughout the chart - `_helpers.tpl`: A place to put template helpers that you can re-use throughout the chart
And what we're going to do is... _remove them all!_ That way we can work through our tutorial from scratch. We'll actually create our own `NOTES.txt` and `_helpers.tpl` as we go. And what we're going to do is... _remove them all!_ That way we can work through our tutorial from scratch. We'll actually create our own `NOTES.txt` and `_helpers.tpl` as we go.

@ -4,7 +4,7 @@ The `.helmignore` file is used to specify files you don't want to include in you
If this file exists, the `helm package` command will ignore all the files that match the pattern specified in the `.helmignore` file while packaging your application. If this file exists, the `helm package` command will ignore all the files that match the pattern specified in the `.helmignore` file while packaging your application.
This can help in avoiding unncessary or sensitive files or directories from being added in your helm chart. This can help in avoiding unnecessary or sensitive files or directories from being added in your helm chart.
The `.helmignore` file supports Unix shell glob matching, relative path matching, and negation (prefixed with !). Only one pattern per line is considered. The `.helmignore` file supports Unix shell glob matching, relative path matching, and negation (prefixed with !). Only one pattern per line is considered.

@ -5,7 +5,7 @@ This guide is intended to give you, the chart developer, a strong understanding
But there are many things this guide has not covered when it comes to the practical day-to-day development of charts. Here are some useful pointers to other documentation that will help you as you create new charts: But there are many things this guide has not covered when it comes to the practical day-to-day development of charts. Here are some useful pointers to other documentation that will help you as you create new charts:
- The [Helm Charts project](https://github.com/helm/charts) is an indispensable source of charts. That project is also sets the standard for best practices in chart development. - The [Helm Charts project](https://github.com/helm/charts) is an indispensable source of charts. That project is also sets the standard for best practices in chart development.
- The Kubernetes [User's Guide](http://kubernetes.io/docs/user-guide/) provides detailed examples of the various resource kinds that you can use, from ConfigMaps and Secrets to DaemonSets and Deployments. - The Kubernetes [Documentation](https://kubernetes.io/docs/home/) provides detailed examples of the various resource kinds that you can use, from ConfigMaps and Secrets to DaemonSets and Deployments.
- The Helm [Charts Guide](../charts.md) explains the workflow of using charts. - The Helm [Charts Guide](../charts.md) explains the workflow of using charts.
- The Helm [Chart Hooks Guide](../charts_hooks.md) explains how to create lifecycle hooks. - The Helm [Chart Hooks Guide](../charts_hooks.md) explains how to create lifecycle hooks.
- The Helm [Charts Tips and Tricks](../charts_tips_and_tricks.md) article provides some useful tips for writing charts. - The Helm [Charts Tips and Tricks](../charts_tips_and_tricks.md) article provides some useful tips for writing charts.

@ -7,7 +7,7 @@ to read.
## Scalars and Collections ## Scalars and Collections
According to the [YAML spec](http://yaml.org/spec/1.2/spec.html), there are two According to the [YAML spec](https://yaml.org/spec/1.2/spec.html), there are two
types of collections, and many scalar types. types of collections, and many scalar types.
The two types of collections are maps and sequences: The two types of collections are maps and sequences:

@ -71,7 +71,7 @@ Other fields will be silently ignored.
### Charts and Versioning ### Charts and Versioning
Every chart must have a version number. A version must follow the Every chart must have a version number. A version must follow the
[SemVer 2](http://semver.org/) standard. Unlike Helm Classic, Kubernetes [SemVer 2](https://semver.org/) standard. Unlike Helm Classic, Kubernetes
Helm uses version numbers as release markers. Packages in repositories Helm uses version numbers as release markers. Packages in repositories
are identified by name plus version. are identified by name plus version.
@ -492,7 +492,7 @@ create/update all of the above Kubernetes objects in the following order:
This is because when Helm installs/upgrades charts, This is because when Helm installs/upgrades charts,
the Kubernetes objects from the charts and all its dependencies are the Kubernetes objects from the charts and all its dependencies are
- aggregrated into a single set; then - aggregated into a single set; then
- sorted by type followed by name; and then - sorted by type followed by name; and then
- created/updated in that order. - created/updated in that order.
@ -792,7 +792,7 @@ standard references that will help you out.
- [Go templates](https://godoc.org/text/template) - [Go templates](https://godoc.org/text/template)
- [Extra template functions](https://godoc.org/github.com/Masterminds/sprig) - [Extra template functions](https://godoc.org/github.com/Masterminds/sprig)
- [The YAML format](http://yaml.org/spec/) - [The YAML format](https://yaml.org/spec/)
## Using Helm to Manage Charts ## Using Helm to Manage Charts

@ -248,8 +248,8 @@ annotated.
When a helm release, that uses a hook, is being updated, it is possible that the hook resource might already exist in the cluster. In such circumstances, by default, helm will fail trying to install the hook resource with an `"... already exists"` error. When a helm release, that uses a hook, is being updated, it is possible that the hook resource might already exist in the cluster. In such circumstances, by default, helm will fail trying to install the hook resource with an `"... already exists"` error.
A common reason why the hook resource might already exist is that it was not deleted following use on a previous install/upgrade. There are, in fact, good reasons why one might want to keep the hook: for example, to aid manual debugging in case something went wrong. In this case, the recommended way of ensuring subsequent attemps to create the hook do not fail is to define a `"hook-delete-policy"` that can handle this: `"helm.sh/hook-delete-policy": "before-hook-creation"`. This hook annotation causes any existing hook to be removed, before the new hook is installed. A common reason why the hook resource might already exist is that it was not deleted following use on a previous install/upgrade. There are, in fact, good reasons why one might want to keep the hook: for example, to aid manual debugging in case something went wrong. In this case, the recommended way of ensuring subsequent attempts to create the hook do not fail is to define a `"hook-delete-policy"` that can handle this: `"helm.sh/hook-delete-policy": "before-hook-creation"`. This hook annotation causes any existing hook to be removed, before the new hook is installed.
If it is preferred to actually delete the hook after each use (rather than have to handle it on a subsequent use, as shown above), then this can be achived using a delete policy of `"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"`. If it is preferred to actually delete the hook after each use (rather than have to handle it on a subsequent use, as shown above), then this can be achieved using a delete policy of `"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"`.

@ -235,6 +235,9 @@ orphaned. Helm will no longer manage it in any way. This can lead to problems
if using `helm install --replace` on a release that has already been deleted, but if using `helm install --replace` on a release that has already been deleted, but
has kept resources. has kept resources.
To explicitly opt in to resource deletion, for example when overriding a chart's
default annotations, set the resource policy annotation value to `delete`.
### Using with Random Secrets ### Using with Random Secrets
For the case where a chart installs a randomized secret that should not be For the case where a chart installs a randomized secret that should not be
@ -310,7 +313,7 @@ According to the YAML specification, YAML is a superset of JSON. That
means that any valid JSON structure ought to be valid in YAML. means that any valid JSON structure ought to be valid in YAML.
This has an advantage: Sometimes template developers may find it easier This has an advantage: Sometimes template developers may find it easier
to express a datastructure with a JSON-like syntax rather than deal with to express a data structure with a JSON-like syntax rather than deal with
YAML's whitespace sensitivity. YAML's whitespace sensitivity.
As a best practice, templates should follow a YAML-like syntax _unless_ As a best practice, templates should follow a YAML-like syntax _unless_

@ -32,7 +32,7 @@ docker-test`.
To run Helm and Tiller locally, you can run `bin/helm` or `bin/tiller`. To run Helm and Tiller locally, you can run `bin/helm` or `bin/tiller`.
- Helm and Tiller are known to run on macOS and most Linuxes, including - Helm and Tiller are known to run on macOS and most Linux distributions, including
Alpine. Alpine.
- Tiller must have access to a Kubernetes cluster. It learns about the - Tiller must have access to a Kubernetes cluster. It learns about the
cluster by examining the Kube config files that `kubectl` uses. cluster by examining the Kube config files that `kubectl` uses.
@ -170,7 +170,7 @@ workflow for doing this is as follows:
5. When you are ready for us to review, sign your commit, push your branch to GitHub, and 5. When you are ready for us to review, sign your commit, push your branch to GitHub, and
then open a new pull request with us. then open a new pull request with us.
For Git commit messages, we follow the [Semantic Commit Messages](http://karma-runner.github.io/0.13/dev/git-commit-msg.html): For Git commit messages, we follow the [Semantic Commit Messages](https://karma-runner.github.io/0.13/dev/git-commit-msg.html):
``` ```
fix(helm): add --foo flag to 'helm install' fix(helm): add --foo flag to 'helm install'
@ -201,7 +201,7 @@ Common scopes:
Read more: Read more:
- The [Deis Guidelines](https://github.com/deis/workflow/blob/master/src/contributing/submitting-a-pull-request.md) - The [Deis Guidelines](https://github.com/deis/workflow/blob/master/src/contributing/submitting-a-pull-request.md)
were the inspiration for this section. were the inspiration for this section.
- Karma Runner [defines](http://karma-runner.github.io/0.13/dev/git-commit-msg.html) the semantic commit message idea. - Karma Runner [defines](https://karma-runner.github.io/0.13/dev/git-commit-msg.html) the semantic commit message idea.
### Go Conventions ### Go Conventions

@ -37,7 +37,7 @@ are bundled with it.
## Chart Version ## Chart Version
Charts are versioned according to the [SemVer 2 Charts are versioned according to the [SemVer 2
spec](http://semver.org). A version number is required on every chart. spec](https://semver.org). A version number is required on every chart.
## Chart.yaml ## Chart.yaml

@ -8,12 +8,11 @@ rebuild the charts/ directory based on the requirements.lock file
Build out the charts/ directory from the requirements.lock file. Build out the charts/ directory from the requirements.lock file.
Build is used to reconstruct a chart's dependencies to the state specified in Build is used to reconstruct a chart's dependencies to the state specified in
the lock file. This will not re-negotiate dependencies, as 'helm dependency update' the lock file.
does.
If no lock file is found, 'helm dependency build' will mirror the behavior
of 'helm dependency update'.
If no lock file is found, 'helm dependency build' will mirror the behavior of
the 'helm dependency update' command. This means it will update the on-disk
dependencies to mirror the requirements.yaml file and generate a lock file.
``` ```
helm dependency build [flags] CHART helm dependency build [flags] CHART

@ -7,7 +7,7 @@ verify that a chart at the given path has been signed and is valid
Verify that the given chart has a valid provenance file. Verify that the given chart has a valid provenance file.
Provenance files provide crytographic verification that a chart has not been Provenance files provide cryptographic verification that a chart has not been
tampered with, and was packaged by a trusted provider. tampered with, and was packaged by a trusted provider.
This command can be used to verify a local chart. Several other commands provide This command can be used to verify a local chart. Several other commands provide

@ -12,7 +12,7 @@ Differences from Helm Classic:
- Helm's chart format has changed for the better: - Helm's chart format has changed for the better:
- Dependencies are immutable and stored inside of a chart's `charts/` - Dependencies are immutable and stored inside of a chart's `charts/`
directory. directory.
- Charts are strongly versioned using [SemVer 2](http://semver.org/spec/v2.0.0.html) - Charts are strongly versioned using [SemVer 2](https://semver.org/spec/v2.0.0.html)
- Charts can be loaded from directories or from chart archive files - Charts can be loaded from directories or from chart archive files
- Helm supports Go templates without requiring you to run `generate` - Helm supports Go templates without requiring you to run `generate`
or `template` commands. or `template` commands.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 53 KiB

@ -19,13 +19,12 @@ Build out the charts/ directory from the requirements.lock file.
.PP .PP
Build is used to reconstruct a chart's dependencies to the state specified in Build is used to reconstruct a chart's dependencies to the state specified in
the lock file. This will not re\-negotiate dependencies, as 'helm dependency update' the lock file.
does.
.PP .PP
If no lock file is found, 'helm dependency build' will mirror the behavior If no lock file is found, 'helm dependency build' will mirror the behavior of
of 'helm dependency update'. the 'helm dependency update' command. This means it will update the on-disk
dependencies to mirror the requirements.yaml file and generate a lock file.
.SH OPTIONS .SH OPTIONS
.PP .PP

@ -18,7 +18,7 @@ helm\-verify \- verify that a chart at the given path has been signed and is val
Verify that the given chart has a valid provenance file. Verify that the given chart has a valid provenance file.
.PP .PP
Provenance files provide crytographic verification that a chart has not been Provenance files provide cryptographic verification that a chart has not been
tampered with, and was packaged by a trusted provider. tampered with, and was packaged by a trusted provider.
.PP .PP

@ -180,7 +180,7 @@ The following pieces of provenance data are added:
* The signature (SHA256, just like Docker) of the chart package (the .tgz file) * The signature (SHA256, just like Docker) of the chart package (the .tgz file)
is included, and may be used to verify the integrity of the chart package. is included, and may be used to verify the integrity of the chart package.
* The entire body is signed using the algorithm used by PGP (see * The entire body is signed using the algorithm used by PGP (see
[http://keybase.io] for an emerging way of making crypto signing and [https://keybase.io] for an emerging way of making crypto signing and
verification easy). verification easy).
The combination of this gives users the following assurances: The combination of this gives users the following assurances:
@ -202,7 +202,7 @@ keywords:
- proxy - proxy
source: source:
- https://github.com/foo/bar - https://github.com/foo/bar
home: http://nginx.com home: https://nginx.com
... ...
files: files:
@ -221,7 +221,7 @@ first is the Chart.yaml. The second is the checksums, a map of filenames to
SHA-256 digests (value shown is fake/truncated) SHA-256 digests (value shown is fake/truncated)
The signature block is a standard PGP signature, which provides [tamper The signature block is a standard PGP signature, which provides [tamper
resistance](http://www.rossde.com/PGP/pgp_signatures.html). resistance](https://www.rossde.com/PGP/pgp_signatures.html).
## Chart Repositories ## Chart Repositories

@ -54,9 +54,11 @@ Once you have Helm ready, you can initialize the local CLI and also
install Tiller into your Kubernetes cluster in one step: install Tiller into your Kubernetes cluster in one step:
```console ```console
$ helm init $ helm init --history-max 200
``` ```
**TIP:** Setting `--history-max` on helm init is recommended as configmaps and other objects in helm history can grow large in number if not purged by max limit. Without a max history set the history is kept indefinitely, leaving a large number of records for helm and tiller to maintain.
This will install Tiller into the Kubernetes cluster you saw with This will install Tiller into the Kubernetes cluster you saw with
`kubectl config current-context`. `kubectl config current-context`.

@ -43,7 +43,7 @@ _Note: The cluster-admin role is created by default in a Kubernetes cluster, so
$ kubectl create -f rbac-config.yaml $ kubectl create -f rbac-config.yaml
serviceaccount "tiller" created serviceaccount "tiller" created
clusterrolebinding "tiller" created clusterrolebinding "tiller" created
$ helm init --service-account tiller $ helm init --service-account tiller --history-max 200
``` ```
### Example: Deploy Tiller in a namespace, restricted to deploying resources only in that namespace ### Example: Deploy Tiller in a namespace, restricted to deploying resources only in that namespace

@ -8,9 +8,9 @@ or [pull request](https://github.com/helm/helm/pulls).
## Article, Blogs, How-Tos, and Extra Documentation ## Article, Blogs, How-Tos, and Extra Documentation
- [Awesome Helm](https://github.com/cdwv/awesome-helm) - List of awesome Helm resources - [Awesome Helm](https://github.com/cdwv/awesome-helm) - List of awesome Helm resources
- [CI/CD with Kubernetes, Helm & Wercker ](http://www.slideshare.net/Diacode/cicd-with-kubernetes-helm-wercker-madscalability) - [CI/CD with Kubernetes, Helm & Wercker ](https://www.slideshare.net/Diacode/cicd-with-kubernetes-helm-wercker-madscalability)
- [Creating a Helm Plugin in 3 Steps](http://technosophos.com/2017/03/21/creating-a-helm-plugin.html) - [Creating a Helm Plugin in 3 Steps](http://technosophos.com/2017/03/21/creating-a-helm-plugin.html)
- [Deploying Kubernetes Applications with Helm](http://cloudacademy.com/blog/deploying-kubernetes-applications-with-helm/) - [Deploying Kubernetes Applications with Helm](https://cloudacademy.com/blog/deploying-kubernetes-applications-with-helm/)
- [GitLab, Consumer Driven Contracts, Helm and Kubernetes](https://medium.com/@enxebre/gitlab-consumer-driven-contracts-helm-and-kubernetes-b7235a60a1cb#.xwp1y4tgi) - [GitLab, Consumer Driven Contracts, Helm and Kubernetes](https://medium.com/@enxebre/gitlab-consumer-driven-contracts-helm-and-kubernetes-b7235a60a1cb#.xwp1y4tgi)
- [Honestbee's Helm Chart Conventions](https://gist.github.com/so0k/f927a4b60003cedd101a0911757c605a) - [Honestbee's Helm Chart Conventions](https://gist.github.com/so0k/f927a4b60003cedd101a0911757c605a)
- [Releasing backward-incompatible changes: Kubernetes, Jenkins, Prometheus Operator, Helm and Traefik](https://medium.com/@enxebre/releasing-backward-incompatible-changes-kubernetes-jenkins-plugin-prometheus-operator-helm-self-6263ca61a1b1#.e0c7elxhq) - [Releasing backward-incompatible changes: Kubernetes, Jenkins, Prometheus Operator, Helm and Traefik](https://medium.com/@enxebre/releasing-backward-incompatible-changes-kubernetes-jenkins-plugin-prometheus-operator-helm-self-6263ca61a1b1#.e0c7elxhq)
@ -90,7 +90,7 @@ Tools layered on top of Helm or Tiller.
Platforms, distributions, and services that include Helm support. Platforms, distributions, and services that include Helm support.
- [Fabric8](https://fabric8.io) - Integrated development platform for Kubernetes - [Fabric8](https://fabric8.io) - Integrated development platform for Kubernetes
- [Jenkins X](http://jenkins-x.io/) - open source automated CI/CD for Kubernetes which uses Helm for [promoting](http://jenkins-x.io/about/features/#promotion) applications through [environments via GitOps](http://jenkins-x.io/about/features/#environments) - [Jenkins X](https://jenkins-x.io/) - open source automated CI/CD for Kubernetes which uses Helm for [promoting](https://jenkins-x.io/about/features/#promotion) applications through [environments via GitOps](https://jenkins-x.io/about/features/#environments)
- [Kubernetic](https://kubernetic.com/) - Kubernetes Desktop Client - [Kubernetic](https://kubernetic.com/) - Kubernetes Desktop Client
- [Qstack](https://qstack.com) - [Qstack](https://qstack.com)

@ -41,7 +41,7 @@ Just kidding! :trollface:
All releases will be of the form vX.Y.Z where X is the major version number, Y All releases will be of the form vX.Y.Z where X is the major version number, Y
is the minor version number and Z is the patch release number. This project is the minor version number and Z is the patch release number. This project
strictly follows [semantic versioning](http://semver.org/) so following this strictly follows [semantic versioning](https://semver.org/) so following this
step is critical. step is critical.
It is important to note that this document assumes that the git remote in your It is important to note that this document assumes that the git remote in your
@ -250,7 +250,25 @@ git tag --sign --annotate "${RELEASE_NAME}" --message "Helm release ${RELEASE_NA
git push upstream $RELEASE_NAME git push upstream $RELEASE_NAME
``` ```
## 7. Write the Release Notes ## 7. PGP Sign the downloads
While hashes provide a signature that the content of the downloads is what it
was generated, signed packages provide traceability of where the package came
from.
To do this, run the following `make` commands:
```shell
make clean
make fetch-dist
make sign
```
This will generate ascii armored signature files for each of the files pushed by CI.
All of the signature files need to be uploaded to the release on GitHub.
## 8. Write the Release Notes
We will auto-generate a changelog based on the commits that occurred during a We will auto-generate a changelog based on the commits that occurred during a
release cycle, but it is usually more beneficial to the end-user if the release release cycle, but it is usually more beneficial to the end-user if the release
@ -286,14 +304,14 @@ The community keeps growing, and we'd love to see you there!
Download Helm X.Y. The common platform binaries are here: Download Helm X.Y. The common platform binaries are here:
- [MacOS amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-darwin-amd64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-darwin-amd64.tar.gz.sha256)) - [MacOS amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-darwin-amd64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-darwin-amd64.tar.gz.sha256) / CHECKSUM_VAL)
- [Linux amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-amd64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-amd64.tar.gz.sha256)) - [Linux amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-amd64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-amd64.tar.gz.sha256) / CHECKSUM_VAL)
- [Linux arm](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm.tar.gz.sha256)) - [Linux arm](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm.tar.gz.sha256) / CHECKSUM_VAL)
- [Linux arm64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm64.tar.gz.sha256)) - [Linux arm64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm64.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-arm64.tar.gz.sha256) / CHECKSUM_VAL)
- [Linux i386](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-386.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-386.tar.gz.sha256)) - [Linux i386](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-386.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-386.tar.gz.sha256) / CHECKSUM_VAL)
- [Linux ppc64le](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-ppc64le.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-ppc64le.tar.gz.sha256)) - [Linux ppc64le](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-ppc64le.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-ppc64le.tar.gz.sha256) / CHECKSUM_VAL)
- [Linux s390x](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-s390x.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-s390x.tar.gz.sha256)) - [Linux s390x](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-s390x.tar.gz) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-linux-s390x.tar.gz.sha256) / CHECKSUM_VAL)
- [Windows amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-windows-amd64.zip) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-windows-amd64.zip.sha256)) - [Windows amd64](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-windows-amd64.zip) ([checksum](https://storage.googleapis.com/kubernetes-helm/helm-vX.Y.Z-windows-amd64.zip.sha256) / CHECKSUM_VAL)
Once you have the client installed, upgrade Tiller with `helm init --upgrade`. Once you have the client installed, upgrade Tiller with `helm init --upgrade`.
@ -332,10 +350,11 @@ git log --no-merges --pretty=format:'- %s %H (%aN)' $PREVIOUS_RELEASE..$RELEASE_
After generating the changelog, you will need to categorize the changes as shown After generating the changelog, you will need to categorize the changes as shown
in the example above. in the example above.
Once finished, go into GitHub and edit the release notes for the tagged release Once finished, go into GitHub and edit the release notes for the tagged release with the notes written here.
with the notes written here.
Remember to attach the ascii armored signatures generated in the previous step to the release notes.
## 8. Evangelize ## 9. Evangelize
Congratulations! You're done. Go grab yourself a $DRINK_OF_CHOICE. You've earned Congratulations! You're done. Go grab yourself a $DRINK_OF_CHOICE. You've earned
it. it.

@ -288,7 +288,7 @@ not available for public resolution.
By default, the Helm client connects to Tiller via tunnel (i.e. kube proxy) at 127.0.0.1. During the TLS handshake, By default, the Helm client connects to Tiller via tunnel (i.e. kube proxy) at 127.0.0.1. During the TLS handshake,
a target, usually provided as a hostname (e.g. example.com), is checked against the subject and subject alternative a target, usually provided as a hostname (e.g. example.com), is checked against the subject and subject alternative
names of the certificate (i.e. hostname verficiation). However, because of the tunnel, the target is an IP address. names of the certificate (i.e. hostname verification). However, because of the tunnel, the target is an IP address.
Therefore, to validate the certificate, the IP address 127.0.0.1 must be listed as an IP subject alternative name Therefore, to validate the certificate, the IP address 127.0.0.1 must be listed as an IP subject alternative name
(IP SAN) in the Tiller certificate. (IP SAN) in the Tiller certificate.

@ -17,9 +17,9 @@ cluster. Think of it like the Kubernetes equivalent of a Homebrew formula,
an Apt dpkg, or a Yum RPM file. an Apt dpkg, or a Yum RPM file.
A *Repository* is the place where charts can be collected and shared. A *Repository* is the place where charts can be collected and shared.
It's like Perl's [CPAN archive](http://www.cpan.org) or the It's like Perl's [CPAN archive](https://www.cpan.org) or the
[Fedora Package Database](https://admin.fedoraproject.org/pkgdb/), but for [Fedora Package Database](https://apps.fedoraproject.org/packages/s/pkgdb), but
Kubernetes packages. for Kubernetes packages.
A *Release* is an instance of a chart running in a Kubernetes cluster. A *Release* is an instance of a chart running in a Kubernetes cluster.
One chart can often be installed many times into the same cluster. And One chart can often be installed many times into the same cluster. And
@ -190,7 +190,7 @@ imageTag: 10.1.14-r3
## Specify a imagePullPolicy ## Specify a imagePullPolicy
## Default to 'Always' if imageTag is 'latest', else set to 'IfNotPresent' ## Default to 'Always' if imageTag is 'latest', else set to 'IfNotPresent'
## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images
## ##
# imagePullPolicy: # imagePullPolicy:

162
glide.lock generated

@ -1,13 +1,11 @@
hash: 2af9a5c4f891a0f44109a929a494b5aeaaffa3a87cd1f3881f25f79845703d5b hash: 9a8f0b6c906f605bb879fbcdf0c122096f7698fe6a975ec4e6648f2ee85fce3e
updated: 2018-12-14T21:39:31.112097Z updated: 2019-03-26T10:33:38.977361532-07:00
imports: imports:
- name: cloud.google.com/go - name: cloud.google.com/go
version: 3b1ae45394a234c385be014e9a488f2bb6eef821 version: 3b1ae45394a234c385be014e9a488f2bb6eef821
subpackages: subpackages:
- compute/metadata - compute/metadata
- internal - internal
- name: github.com/aokoli/goutils
version: 9c37978a95bd5c709a15883b6242714ea6709e64
- name: github.com/asaskevich/govalidator - name: github.com/asaskevich/govalidator
version: 7664702784775e51966f0885f5cd27435916517b version: 7664702784775e51966f0885f5cd27435916517b
- name: github.com/Azure/go-ansiterm - name: github.com/Azure/go-ansiterm
@ -86,14 +84,18 @@ imports:
version: 449fdfce4d962303d702fec724ef0ad181c92528 version: 449fdfce4d962303d702fec724ef0ad181c92528
subpackages: subpackages:
- spdy - spdy
- name: github.com/emicklei/go-restful
version: ff4f55a206334ef123e4f79bbf348980da81ca46
subpackages:
- log
- name: github.com/evanphx/json-patch - name: github.com/evanphx/json-patch
version: 36442dbdb585210f8d5a1b45e67aa323c197d5c4 version: 5858425f75500d40c52783dce87d085a483ce135
- name: github.com/exponent-io/jsonpath - name: github.com/exponent-io/jsonpath
version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5 version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5
- name: github.com/fatih/camelcase - name: github.com/fatih/camelcase
version: f6a740d52f961c60348ebb109adde9f4635d7540 version: f6a740d52f961c60348ebb109adde9f4635d7540
- name: github.com/ghodss/yaml - name: github.com/ghodss/yaml
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee version: c7ce16629ff4cd059ed96ed06419dd3856fd3577
- name: github.com/go-openapi/jsonpointer - name: github.com/go-openapi/jsonpointer
version: ef5f0afec364d3b9396b7b77b43dbe26bf1f8004 version: ef5f0afec364d3b9396b7b77b43dbe26bf1f8004
- name: github.com/go-openapi/jsonreference - name: github.com/go-openapi/jsonreference
@ -122,7 +124,7 @@ imports:
subpackages: subpackages:
- lru - lru
- name: github.com/golang/protobuf - name: github.com/golang/protobuf
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 version: aa810b61a9c79d51363740d207bb46cf8e620ed5
subpackages: subpackages:
- proto - proto
- ptypes - ptypes
@ -132,7 +134,7 @@ imports:
- name: github.com/google/btree - name: github.com/google/btree
version: 7d79101e329e5a3adf994758c578dab82b90c017 version: 7d79101e329e5a3adf994758c578dab82b90c017
- name: github.com/google/gofuzz - name: github.com/google/gofuzz
version: 44d81051d367757e1c7c6a5a86423ece9afcf63c version: 24818f796faf91cd76ec7bddd72458fbced7a6c1
- name: github.com/google/uuid - name: github.com/google/uuid
version: 064e2069ce9c359c118179501254f67d7d37ba24 version: 064e2069ce9c359c118179501254f67d7d37ba24
- name: github.com/googleapis/gnostic - name: github.com/googleapis/gnostic
@ -142,7 +144,7 @@ imports:
- compiler - compiler
- extensions - extensions
- name: github.com/gophercloud/gophercloud - name: github.com/gophercloud/gophercloud
version: 781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d version: c818fa66e4c88b30db28038fe3f18f2f4a0db9a8
subpackages: subpackages:
- openstack - openstack
- openstack/identity/v2/tenants - openstack/identity/v2/tenants
@ -162,17 +164,19 @@ imports:
- name: github.com/grpc-ecosystem/go-grpc-prometheus - name: github.com/grpc-ecosystem/go-grpc-prometheus
version: 0c1b191dbfe51efdabe3c14b9f6f3b96429e0722 version: 0c1b191dbfe51efdabe3c14b9f6f3b96429e0722
- name: github.com/hashicorp/golang-lru - name: github.com/hashicorp/golang-lru
version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 version: 20f1fb78b0740ba8c3cb143a61e86ba5c8669768
subpackages: subpackages:
- simplelru - simplelru
- name: github.com/huandu/xstrings - name: github.com/huandu/xstrings
version: 3959339b333561bf62a38b424fd41517c2c90f40 version: f02667b379e2fb5916c3cda2cf31e0eb885d79f8
- name: github.com/imdario/mergo - name: github.com/imdario/mergo
version: 9316a62528ac99aaecb4e47eadd6dc8aa6533d58 version: 9316a62528ac99aaecb4e47eadd6dc8aa6533d58
- name: github.com/inconshreveable/mousetrap - name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
- name: github.com/json-iterator/go - name: github.com/json-iterator/go
version: ab8a2e0c74be9d3be70b3184d9acc634935ded82 version: ab8a2e0c74be9d3be70b3184d9acc634935ded82
- name: github.com/liggitt/tabwriter
version: 89fcab3d43de07060e4fd4c1547430ed57e87f24
- name: github.com/mailru/easyjson - name: github.com/mailru/easyjson
version: 2f5df55504ebc322e4d52d34df6a1f5b503bf26d version: 2f5df55504ebc322e4d52d34df6a1f5b503bf26d
subpackages: subpackages:
@ -181,10 +185,12 @@ imports:
- jwriter - jwriter
- name: github.com/MakeNowJust/heredoc - name: github.com/MakeNowJust/heredoc
version: bb23615498cded5e105af4ce27de75b089cbe851 version: bb23615498cded5e105af4ce27de75b089cbe851
- name: github.com/Masterminds/goutils
version: 41ac8693c5c10a92ea1ff5ac3a7f95646f6123b0
- name: github.com/Masterminds/semver - name: github.com/Masterminds/semver
version: 517734cc7d6470c0d07130e40fd40bdeb9bcd3fd version: 517734cc7d6470c0d07130e40fd40bdeb9bcd3fd
- name: github.com/Masterminds/sprig - name: github.com/Masterminds/sprig
version: 15f9564e7e9cf0da02a48e0d25f12a7b83559aa6 version: 9f8fceff796fb9f4e992cd2bece016be0121ab74
- name: github.com/Masterminds/vcs - name: github.com/Masterminds/vcs
version: 3084677c2c188840777bff30054f2b553729d329 version: 3084677c2c188840777bff30054f2b553729d329
- name: github.com/mattn/go-runewidth - name: github.com/mattn/go-runewidth
@ -215,7 +221,7 @@ imports:
subpackages: subpackages:
- go - go
- name: github.com/prometheus/common - name: github.com/prometheus/common
version: 13ba4ddd0caa9c28ca7b7bffe1dfa9ed8d5ef207 version: cfeb6f9992ffa54aaa4f2170ade4067ee478b250
subpackages: subpackages:
- expfmt - expfmt
- internal/bitbucket.org/ww/goautoneg - internal/bitbucket.org/ww/goautoneg
@ -259,15 +265,15 @@ imports:
- scrypt - scrypt
- ssh/terminal - ssh/terminal
- name: golang.org/x/net - name: golang.org/x/net
version: 0ed95abb35c445290478a5348a7b38bb154135fd version: 65e2d4e15006aab9813ff8769e768bbf4bb667a0
subpackages: subpackages:
- context - context
- context/ctxhttp - context/ctxhttp
- http/httpguts
- http2 - http2
- http2/hpack - http2/hpack
- idna - idna
- internal/timeseries - internal/timeseries
- lex/httplex
- trace - trace
- name: golang.org/x/oauth2 - name: golang.org/x/oauth2
version: a6bd8cefa1811bd24b86f8902872e4e8225f74c4 version: a6bd8cefa1811bd24b86f8902872e4e8225f74c4
@ -281,7 +287,7 @@ imports:
subpackages: subpackages:
- semaphore - semaphore
- name: golang.org/x/sys - name: golang.org/x/sys
version: 95c6576299259db960f6c5b9b69ea52422860fce version: b90733256f2e882e81d52f9126de08df5615afd9
subpackages: subpackages:
- unix - unix
- windows - windows
@ -325,26 +331,40 @@ imports:
subpackages: subpackages:
- googleapis/rpc/status - googleapis/rpc/status
- name: google.golang.org/grpc - name: google.golang.org/grpc
version: 5ffe3083946d5603a0578721101dc8165b1d5b5f version: a02b0774206b209466313a0b525d2c738fe407eb
subpackages: subpackages:
- balancer - balancer
- balancer/base
- balancer/roundrobin
- binarylog/grpc_binarylog_v1
- codes - codes
- connectivity - connectivity
- credentials - credentials
- grpclb/grpc_lb_v1/messages - credentials/internal
- encoding
- encoding/proto
- grpclog - grpclog
- health - health
- health/grpc_health_v1 - health/grpc_health_v1
- internal - internal
- internal/backoff
- internal/binarylog
- internal/channelz
- internal/envconfig
- internal/grpcrand
- internal/grpcsync
- internal/syscall
- internal/transport
- keepalive - keepalive
- metadata - metadata
- naming - naming
- peer - peer
- resolver - resolver
- resolver/dns
- resolver/passthrough
- stats - stats
- status - status
- tap - tap
- transport
- name: gopkg.in/inf.v0 - name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/square/go-jose.v2 - name: gopkg.in/square/go-jose.v2
@ -354,12 +374,11 @@ imports:
- json - json
- jwt - jwt
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: 670d4cfef0544295bc27a114dbac37980d83185a version: 5420a8b6744d3b0345ab293f6fcba19c978f1183
- name: k8s.io/api - name: k8s.io/api
version: 05914d821849570fba9eacfb29466f2d8d3cd229 version: 40a48860b5abbba9aa891b02b32da429b08d96a0
subpackages: subpackages:
- admission/v1beta1 - admission/v1beta1
- admissionregistration/v1alpha1
- admissionregistration/v1beta1 - admissionregistration/v1beta1
- apps/v1 - apps/v1
- apps/v1beta1 - apps/v1beta1
@ -376,16 +395,21 @@ imports:
- batch/v1beta1 - batch/v1beta1
- batch/v2alpha1 - batch/v2alpha1
- certificates/v1beta1 - certificates/v1beta1
- coordination/v1
- coordination/v1beta1 - coordination/v1beta1
- core/v1 - core/v1
- events/v1beta1 - events/v1beta1
- extensions/v1beta1 - extensions/v1beta1
- imagepolicy/v1alpha1 - imagepolicy/v1alpha1
- networking/v1 - networking/v1
- networking/v1beta1
- node/v1alpha1
- node/v1beta1
- policy/v1beta1 - policy/v1beta1
- rbac/v1 - rbac/v1
- rbac/v1alpha1 - rbac/v1alpha1
- rbac/v1beta1 - rbac/v1beta1
- scheduling/v1
- scheduling/v1alpha1 - scheduling/v1alpha1
- scheduling/v1beta1 - scheduling/v1beta1
- settings/v1alpha1 - settings/v1alpha1
@ -393,11 +417,11 @@ imports:
- storage/v1alpha1 - storage/v1alpha1
- storage/v1beta1 - storage/v1beta1
- name: k8s.io/apiextensions-apiserver - name: k8s.io/apiextensions-apiserver
version: 0fe22c71c47604641d9aa352c785b7912c200562 version: 53c4693659ed354d76121458fb819202dd1635fa
subpackages: subpackages:
- pkg/features - pkg/features
- name: k8s.io/apimachinery - name: k8s.io/apimachinery
version: 2b1284ed4c93a43499e781493253e2ac5959c4fd version: d7deff9243b165ee192f5551710ea4285dcfd615
subpackages: subpackages:
- pkg/api/equality - pkg/api/equality
- pkg/api/errors - pkg/api/errors
@ -453,7 +477,7 @@ imports:
- third_party/forked/golang/netutil - third_party/forked/golang/netutil
- third_party/forked/golang/reflect - third_party/forked/golang/reflect
- name: k8s.io/apiserver - name: k8s.io/apiserver
version: 3ccfe8365421eb08e334b195786a2973460741d8 version: 8b27c41bdbb11ff103caa673315e097bf0289171
subpackages: subpackages:
- pkg/authentication/authenticator - pkg/authentication/authenticator
- pkg/authentication/serviceaccount - pkg/authentication/serviceaccount
@ -461,23 +485,31 @@ imports:
- pkg/features - pkg/features
- pkg/util/feature - pkg/util/feature
- name: k8s.io/cli-runtime - name: k8s.io/cli-runtime
version: 835b10687cb6556f6b113099ef925146a56d5981 version: 2899ed30580fdbc8286718edb4382b529463099d
subpackages: subpackages:
- pkg/genericclioptions - pkg/genericclioptions
- pkg/genericclioptions/printers - pkg/kustomize
- pkg/genericclioptions/resource - pkg/kustomize/k8sdeps
- pkg/kustomize/k8sdeps/configmapandsecret
- pkg/kustomize/k8sdeps/kunstruct
- pkg/kustomize/k8sdeps/kv
- pkg/kustomize/k8sdeps/transformer
- pkg/kustomize/k8sdeps/transformer/hash
- pkg/kustomize/k8sdeps/transformer/patch
- pkg/kustomize/k8sdeps/validator
- pkg/printers
- pkg/resource
- name: k8s.io/client-go - name: k8s.io/client-go
version: 8d9ed539ba3134352c586810e749e58df4e94e4f version: 6ee68ca5fd8355d024d02f9db0b3b667e8357a0f
subpackages: subpackages:
- discovery - discovery
- discovery/cached/disk
- discovery/fake - discovery/fake
- dynamic - dynamic
- dynamic/fake - dynamic/fake
- kubernetes - kubernetes
- kubernetes/fake - kubernetes/fake
- kubernetes/scheme - kubernetes/scheme
- kubernetes/typed/admissionregistration/v1alpha1
- kubernetes/typed/admissionregistration/v1alpha1/fake
- kubernetes/typed/admissionregistration/v1beta1 - kubernetes/typed/admissionregistration/v1beta1
- kubernetes/typed/admissionregistration/v1beta1/fake - kubernetes/typed/admissionregistration/v1beta1/fake
- kubernetes/typed/apps/v1 - kubernetes/typed/apps/v1
@ -510,6 +542,8 @@ imports:
- kubernetes/typed/batch/v2alpha1/fake - kubernetes/typed/batch/v2alpha1/fake
- kubernetes/typed/certificates/v1beta1 - kubernetes/typed/certificates/v1beta1
- kubernetes/typed/certificates/v1beta1/fake - kubernetes/typed/certificates/v1beta1/fake
- kubernetes/typed/coordination/v1
- kubernetes/typed/coordination/v1/fake
- kubernetes/typed/coordination/v1beta1 - kubernetes/typed/coordination/v1beta1
- kubernetes/typed/coordination/v1beta1/fake - kubernetes/typed/coordination/v1beta1/fake
- kubernetes/typed/core/v1 - kubernetes/typed/core/v1
@ -520,6 +554,12 @@ imports:
- kubernetes/typed/extensions/v1beta1/fake - kubernetes/typed/extensions/v1beta1/fake
- kubernetes/typed/networking/v1 - kubernetes/typed/networking/v1
- kubernetes/typed/networking/v1/fake - kubernetes/typed/networking/v1/fake
- kubernetes/typed/networking/v1beta1
- kubernetes/typed/networking/v1beta1/fake
- kubernetes/typed/node/v1alpha1
- kubernetes/typed/node/v1alpha1/fake
- kubernetes/typed/node/v1beta1
- kubernetes/typed/node/v1beta1/fake
- kubernetes/typed/policy/v1beta1 - kubernetes/typed/policy/v1beta1
- kubernetes/typed/policy/v1beta1/fake - kubernetes/typed/policy/v1beta1/fake
- kubernetes/typed/rbac/v1 - kubernetes/typed/rbac/v1
@ -528,6 +568,8 @@ imports:
- kubernetes/typed/rbac/v1alpha1/fake - kubernetes/typed/rbac/v1alpha1/fake
- kubernetes/typed/rbac/v1beta1 - kubernetes/typed/rbac/v1beta1
- kubernetes/typed/rbac/v1beta1/fake - kubernetes/typed/rbac/v1beta1/fake
- kubernetes/typed/scheduling/v1
- kubernetes/typed/scheduling/v1/fake
- kubernetes/typed/scheduling/v1alpha1 - kubernetes/typed/scheduling/v1alpha1
- kubernetes/typed/scheduling/v1alpha1/fake - kubernetes/typed/scheduling/v1alpha1/fake
- kubernetes/typed/scheduling/v1beta1 - kubernetes/typed/scheduling/v1beta1
@ -574,30 +616,35 @@ imports:
- tools/pager - tools/pager
- tools/portforward - tools/portforward
- tools/record - tools/record
- tools/record/util
- tools/reference - tools/reference
- tools/remotecommand - tools/remotecommand
- tools/watch - tools/watch
- transport - transport
- transport/spdy - transport/spdy
- util/buffer
- util/cert - util/cert
- util/connrotation - util/connrotation
- util/exec - util/exec
- util/flowcontrol - util/flowcontrol
- util/homedir - util/homedir
- util/integer
- util/jsonpath - util/jsonpath
- util/keyutil
- util/retry - util/retry
- name: k8s.io/cloud-provider
version: 9c9d72d1bf90eb62005f5112f3eea019b272c44b
subpackages:
- features
- name: k8s.io/klog - name: k8s.io/klog
version: 8139d8cb77af419532b33dfa7dd09fbc5f1d344f version: 8e90cee79f823779174776412c13478955131846
- name: k8s.io/kube-openapi - name: k8s.io/kube-openapi
version: c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d version: b3a7cee44a305be0a69e1b9ac03018307287e1b0
subpackages: subpackages:
- pkg/common
- pkg/util/proto - pkg/util/proto
- pkg/util/proto/testing - pkg/util/proto/testing
- pkg/util/proto/validation - pkg/util/proto/validation
- name: k8s.io/kubernetes - name: k8s.io/kubernetes
version: f2c8f1cadf1808ec28476682e49a3cce2b09efbf version: b805719a99126e54bcbc0a3d9ee8a45cd7e85632
subpackages: subpackages:
- pkg/api/legacyscheme - pkg/api/legacyscheme
- pkg/api/service - pkg/api/service
@ -630,6 +677,7 @@ imports:
- pkg/apis/certificates/v1beta1 - pkg/apis/certificates/v1beta1
- pkg/apis/coordination - pkg/apis/coordination
- pkg/apis/coordination/install - pkg/apis/coordination/install
- pkg/apis/coordination/v1
- pkg/apis/coordination/v1beta1 - pkg/apis/coordination/v1beta1
- pkg/apis/core - pkg/apis/core
- pkg/apis/core/helper - pkg/apis/core/helper
@ -645,6 +693,7 @@ imports:
- pkg/apis/extensions/install - pkg/apis/extensions/install
- pkg/apis/extensions/v1beta1 - pkg/apis/extensions/v1beta1
- pkg/apis/networking - pkg/apis/networking
- pkg/apis/node
- pkg/apis/policy - pkg/apis/policy
- pkg/apis/policy/install - pkg/apis/policy/install
- pkg/apis/policy/v1beta1 - pkg/apis/policy/v1beta1
@ -655,6 +704,7 @@ imports:
- pkg/apis/rbac/v1beta1 - pkg/apis/rbac/v1beta1
- pkg/apis/scheduling - pkg/apis/scheduling
- pkg/apis/scheduling/install - pkg/apis/scheduling/install
- pkg/apis/scheduling/v1
- pkg/apis/scheduling/v1alpha1 - pkg/apis/scheduling/v1alpha1
- pkg/apis/scheduling/v1beta1 - pkg/apis/scheduling/v1beta1
- pkg/apis/settings - pkg/apis/settings
@ -699,30 +749,54 @@ imports:
- pkg/kubectl/util/templates - pkg/kubectl/util/templates
- pkg/kubectl/util/term - pkg/kubectl/util/term
- pkg/kubectl/validation - pkg/kubectl/validation
- pkg/kubelet/apis
- pkg/kubelet/types - pkg/kubelet/types
- pkg/master/ports - pkg/master/ports
- pkg/printers - pkg/printers
- pkg/printers/internalversion - pkg/printers/internalversion
- pkg/scheduler/api
- pkg/security/apparmor - pkg/security/apparmor
- pkg/serviceaccount - pkg/serviceaccount
- pkg/util/file
- pkg/util/hash - pkg/util/hash
- pkg/util/interrupt - pkg/util/interrupt
- pkg/util/labels - pkg/util/labels
- pkg/util/net/sets
- pkg/util/node - pkg/util/node
- pkg/util/parsers - pkg/util/parsers
- pkg/util/taints - pkg/util/taints
- pkg/version - pkg/version
- name: k8s.io/utils - name: k8s.io/utils
version: 66066c83e385e385ccc3c964b44fd7dcd413d0ed version: c2654d5206da6b7b6ace12841e8f359bb89b443c
subpackages: subpackages:
- clock - buffer
- exec - exec
- exec/testing - integer
- net
- path
- pointer - pointer
- trace
- name: sigs.k8s.io/kustomize
version: a6f65144121d1955266b0cd836ce954c04122dc8
subpackages:
- pkg/commands/build
- pkg/constants
- pkg/expansion
- pkg/factory
- pkg/fs
- pkg/git
- pkg/gvk
- pkg/ifc
- pkg/ifc/transformer
- pkg/image
- pkg/internal/error
- pkg/loader
- pkg/patch
- pkg/patch/transformer
- pkg/resid
- pkg/resmap
- pkg/resource
- pkg/target
- pkg/transformers
- pkg/transformers/config
- pkg/transformers/config/defaultconfig
- pkg/types
- name: sigs.k8s.io/yaml - name: sigs.k8s.io/yaml
version: fd68e9863619f6ec2fdd8625fe1f02e7c877e480 version: fd68e9863619f6ec2fdd8625fe1f02e7c877e480
- name: vbom.ml/util - name: vbom.ml/util
@ -731,7 +805,7 @@ imports:
- sortorder - sortorder
testImports: testImports:
- name: github.com/pmezard/go-difflib - name: github.com/pmezard/go-difflib
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d version: 5d4384ee4fb2527b0a1256a821ebfc92f91efefc
subpackages: subpackages:
- difflib - difflib
- name: github.com/stretchr/testify - name: github.com/stretchr/testify

@ -6,6 +6,12 @@ import:
- package: golang.org/x/sync - package: golang.org/x/sync
subpackages: subpackages:
- semaphore - semaphore
# This is temporary and can probably be removed the next time gRPC is updated
- package: golang.org/x/sys
version: b90733256f2e882e81d52f9126de08df5615afd9
subpackages:
- unix
- windows
- package: github.com/spf13/cobra - package: github.com/spf13/cobra
version: fe5e611709b0c57fa4a89136deaa8e1d4004d053 version: fe5e611709b0c57fa4a89136deaa8e1d4004d053
- package: github.com/spf13/pflag - package: github.com/spf13/pflag
@ -15,20 +21,20 @@ import:
- package: github.com/imdario/mergo - package: github.com/imdario/mergo
version: v0.3.5 version: v0.3.5
- package: github.com/Masterminds/sprig - package: github.com/Masterminds/sprig
version: ^2.16.0 version: ^2.19.0
- package: github.com/ghodss/yaml - package: github.com/ghodss/yaml
- package: github.com/Masterminds/semver - package: github.com/Masterminds/semver
version: ~1.3.1 version: ~1.3.1
- package: github.com/technosophos/moniker - package: github.com/technosophos/moniker
version: ~0.2 version: ~0.2
- package: github.com/golang/protobuf - package: github.com/golang/protobuf
version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 version: 1.2.0
subpackages: subpackages:
- proto - proto
- ptypes/any - ptypes/any
- ptypes/timestamp - ptypes/timestamp
- package: google.golang.org/grpc - package: google.golang.org/grpc
version: 1.7.2 version: 1.18.0
- package: github.com/gosuri/uitable - package: github.com/gosuri/uitable
- package: github.com/asaskevich/govalidator - package: github.com/asaskevich/govalidator
version: ^4.0.0 version: ^4.0.0
@ -45,19 +51,19 @@ import:
version: 0.8.0 version: 0.8.0
- package: github.com/grpc-ecosystem/go-grpc-prometheus - package: github.com/grpc-ecosystem/go-grpc-prometheus
- package: k8s.io/kubernetes - package: k8s.io/kubernetes
version: release-1.13 version: release-1.14
- package: k8s.io/client-go - package: k8s.io/client-go
version: kubernetes-1.13.1 version: kubernetes-1.14.0
- package: k8s.io/api - package: k8s.io/api
version: kubernetes-1.13.1 version: kubernetes-1.14.0
- package: k8s.io/apimachinery - package: k8s.io/apimachinery
version: kubernetes-1.13.1 version: kubernetes-1.14.0
- package: k8s.io/apiserver - package: k8s.io/apiserver
version: kubernetes-1.13.1 version: kubernetes-1.14.0
- package: k8s.io/cli-runtime - package: k8s.io/cli-runtime
version: kubernetes-1.13.1 version: kubernetes-1.14.0
- package: k8s.io/apiextensions-apiserver - package: k8s.io/apiextensions-apiserver
version: kubernetes-1.13.1 version: kubernetes-1.14.0
- package: github.com/cyphar/filepath-securejoin - package: github.com/cyphar/filepath-securejoin
version: ^0.2.1 version: ^0.2.1

@ -40,7 +40,7 @@ var (
// Capabilities describes the capabilities of the Kubernetes cluster that Tiller is attached to. // Capabilities describes the capabilities of the Kubernetes cluster that Tiller is attached to.
type Capabilities struct { type Capabilities struct {
// List of all supported API versions // APIVersions list of all supported API versions
APIVersions VersionSet APIVersions VersionSet
// KubeVersion is the Kubernetes version // KubeVersion is the Kubernetes version
KubeVersion *version.Info KubeVersion *version.Info

@ -85,7 +85,7 @@ type Requirements struct {
// //
// It represents the state that the dependencies should be in. // It represents the state that the dependencies should be in.
type RequirementsLock struct { type RequirementsLock struct {
// Genderated is the date the lock file was last generated. // Generated is the date the lock file was last generated.
Generated time.Time `json:"generated"` Generated time.Time `json:"generated"`
// Digest is a hash of the requirements file used to generate it. // Digest is a hash of the requirements file used to generate it.
Digest string `json:"digest"` Digest string `json:"digest"`

@ -63,6 +63,12 @@ func SaveDir(c *chart.Chart, dest string) error {
// Save templates // Save templates
for _, f := range c.Templates { for _, f := range c.Templates {
n := filepath.Join(outdir, f.Name) n := filepath.Join(outdir, f.Name)
d := filepath.Dir(n)
if err := os.MkdirAll(d, 0755); err != nil {
return err
}
if err := ioutil.WriteFile(n, f.Data, 0644); err != nil { if err := ioutil.WriteFile(n, f.Data, 0644); err != nil {
return err return err
} }

@ -48,6 +48,9 @@ func TestSave(t *testing.T) {
Files: []*any.Any{ Files: []*any.Any{
{TypeUrl: "scheherazade/shahryar.txt", Value: []byte("1,001 Nights")}, {TypeUrl: "scheherazade/shahryar.txt", Value: []byte("1,001 Nights")},
}, },
Templates: []*chart.Template{
{Name: "templates/scheherazade/shahryar.txt.tmpl", Data: []byte("{{ \"1,001 Nights\" }}")},
},
} }
where, err := Save(c, tmp) where, err := Save(c, tmp)
@ -75,6 +78,9 @@ func TestSave(t *testing.T) {
if len(c2.Files) != 1 || c2.Files[0].TypeUrl != "scheherazade/shahryar.txt" { if len(c2.Files) != 1 || c2.Files[0].TypeUrl != "scheherazade/shahryar.txt" {
t.Fatal("Files data did not match") t.Fatal("Files data did not match")
} }
if len(c2.Templates) != 1 || c2.Templates[0].Name != "templates/scheherazade/shahryar.txt.tmpl" {
t.Fatal("Templates data did not match")
}
} }
func TestSavePreservesTimestamps(t *testing.T) { func TestSavePreservesTimestamps(t *testing.T) {
@ -100,6 +106,9 @@ func TestSavePreservesTimestamps(t *testing.T) {
Files: []*any.Any{ Files: []*any.Any{
{TypeUrl: "scheherazade/shahryar.txt", Value: []byte("1,001 Nights")}, {TypeUrl: "scheherazade/shahryar.txt", Value: []byte("1,001 Nights")},
}, },
Templates: []*chart.Template{
{Name: "templates/scheherazade/shahryar.txt.tmpl", Data: []byte("{{ \"1,001 Nights\" }}")},
},
} }
where, err := Save(c, tmp) where, err := Save(c, tmp)
@ -171,6 +180,9 @@ func TestSaveDir(t *testing.T) {
Files: []*any.Any{ Files: []*any.Any{
{TypeUrl: "scheherazade/shahryar.txt", Value: []byte("1,001 Nights")}, {TypeUrl: "scheherazade/shahryar.txt", Value: []byte("1,001 Nights")},
}, },
Templates: []*chart.Template{
{Name: "templates/scheherazade/shahryar.txt.tmpl", Data: []byte("{{ \"1,001 Nights\" }}")},
},
} }
if err := SaveDir(c, tmp); err != nil { if err := SaveDir(c, tmp); err != nil {
@ -191,4 +203,7 @@ func TestSaveDir(t *testing.T) {
if len(c2.Files) != 1 || c2.Files[0].TypeUrl != "scheherazade/shahryar.txt" { if len(c2.Files) != 1 || c2.Files[0].TypeUrl != "scheherazade/shahryar.txt" {
t.Fatal("Files data did not match") t.Fatal("Files data did not match")
} }
if len(c2.Templates) != 1 || c2.Templates[0].Name != "templates/scheherazade/shahryar.txt.tmpl" {
t.Fatal("Templates data did not match")
}
} }

@ -65,11 +65,11 @@ type ChartDownloader struct {
Keyring string Keyring string
// HelmHome is the $HELM_HOME. // HelmHome is the $HELM_HOME.
HelmHome helmpath.Home HelmHome helmpath.Home
// Getter collection for the operation // Getters collection for the operation
Getters getter.Providers Getters getter.Providers
// Chart repository username // Username chart repository username
Username string Username string
// Chart repository password // Password chart repository password
Password string Password string
} }
@ -213,7 +213,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
cv, err := i.Get(chartName, version) cv, err := i.Get(chartName, version)
if err != nil { if err != nil {
return u, r.Client, fmt.Errorf("chart %q matching %s not found in %s index. (try 'helm repo update'). %s", chartName, version, r.Config.Name, err) return u, r.Client, fmt.Errorf("chart %q matching version %q not found in %s index. (try 'helm repo update'). %s", chartName, version, r.Config.Name, err)
} }
if len(cv.URLs) == 0 { if len(cv.URLs) == 0 {
@ -243,14 +243,14 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
return u, r.Client, nil return u, r.Client, nil
} }
// If HttpGetter is used, this method sets the configured repository credentials on the HttpGetter. // setCredentials if HttpGetter is used, this method sets the configured repository credentials on the HttpGetter.
func (c *ChartDownloader) setCredentials(r *repo.ChartRepository) { func (c *ChartDownloader) setCredentials(r *repo.ChartRepository) {
if t, ok := r.Client.(*getter.HttpGetter); ok { if t, ok := r.Client.(*getter.HttpGetter); ok {
t.SetCredentials(c.getRepoCredentials(r)) t.SetCredentials(c.getRepoCredentials(r))
} }
} }
// If this ChartDownloader is not configured to use credentials, and the chart repository sent as an argument is, // getRepoCredentials if this ChartDownloader is not configured to use credentials, and the chart repository sent as an argument is,
// then the repository's configured credentials are returned. // then the repository's configured credentials are returned.
// Else, this ChartDownloader's credentials are returned. // Else, this ChartDownloader's credentials are returned.
func (c *ChartDownloader) getRepoCredentials(r *repo.ChartRepository) (username, password string) { func (c *ChartDownloader) getRepoCredentials(r *repo.ChartRepository) (username, password string) {

@ -604,7 +604,7 @@ func writeLock(chartpath string, lock *chartutil.RequirementsLock) error {
return ioutil.WriteFile(dest, data, 0644) return ioutil.WriteFile(dest, data, 0644)
} }
// archive a dep chart from local directory and save it into charts/ // tarFromLocalDir archive a dep chart from local directory and save it into charts/
func tarFromLocalDir(chartpath string, name string, repo string, version string) (string, error) { func tarFromLocalDir(chartpath string, name string, repo string, version string) (string, error) {
destPath := filepath.Join(chartpath, "charts") destPath := filepath.Join(chartpath, "charts")

@ -130,7 +130,7 @@ type renderable struct {
tpl string tpl string
// vals are the values to be supplied to the template. // vals are the values to be supplied to the template.
vals chartutil.Values vals chartutil.Values
// namespace prefix to the templates of the current chart // basePath namespace prefix to the templates of the current chart
basePath string basePath string
} }

@ -334,7 +334,7 @@ func (h *Client) connect(ctx context.Context) (conn *grpc.ClientConn, err error)
return conn, nil return conn, nil
} }
// Executes tiller.ListReleases RPC. // list executes tiller.ListReleases RPC.
func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) { func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.ListReleasesResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -365,7 +365,7 @@ func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.L
return resp, nil return resp, nil
} }
// Executes tiller.InstallRelease RPC. // install executes tiller.InstallRelease RPC.
func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) { func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*rls.InstallReleaseResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -377,7 +377,7 @@ func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (*
return rlc.InstallRelease(ctx, req) return rlc.InstallRelease(ctx, req)
} }
// Executes tiller.UninstallRelease RPC. // delete executes tiller.UninstallRelease RPC.
func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) { func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (*rls.UninstallReleaseResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -389,7 +389,7 @@ func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) (
return rlc.UninstallRelease(ctx, req) return rlc.UninstallRelease(ctx, req)
} }
// Executes tiller.UpdateRelease RPC. // update executes tiller.UpdateRelease RPC.
func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) { func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rls.UpdateReleaseResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -401,7 +401,7 @@ func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rl
return rlc.UpdateRelease(ctx, req) return rlc.UpdateRelease(ctx, req)
} }
// Executes tiller.RollbackRelease RPC. // rollback executes tiller.RollbackRelease RPC.
func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) { func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) (*rls.RollbackReleaseResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -413,7 +413,7 @@ func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest)
return rlc.RollbackRelease(ctx, req) return rlc.RollbackRelease(ctx, req)
} }
// Executes tiller.GetReleaseStatus RPC. // status executes tiller.GetReleaseStatus RPC.
func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) { func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (*rls.GetReleaseStatusResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -425,7 +425,7 @@ func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) (
return rlc.GetReleaseStatus(ctx, req) return rlc.GetReleaseStatus(ctx, req)
} }
// Executes tiller.GetReleaseContent RPC. // content executes tiller.GetReleaseContent RPC.
func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) { func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) (*rls.GetReleaseContentResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -437,7 +437,7 @@ func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest)
return rlc.GetReleaseContent(ctx, req) return rlc.GetReleaseContent(ctx, req)
} }
// Executes tiller.GetVersion RPC. // version executes tiller.GetVersion RPC.
func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) { func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.GetVersionResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -449,7 +449,7 @@ func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls.
return rlc.GetVersion(ctx, req) return rlc.GetVersion(ctx, req)
} }
// Executes tiller.GetHistory RPC. // history executes tiller.GetHistory RPC.
func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) { func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.GetHistoryResponse, error) {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {
@ -461,7 +461,7 @@ func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls.
return rlc.GetHistory(ctx, req) return rlc.GetHistory(ctx, req)
} }
// Executes tiller.TestRelease RPC. // test executes tiller.TestRelease RPC.
func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) { func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan *rls.TestReleaseResponse, <-chan error) {
errc := make(chan error, 1) errc := make(chan error, 1)
c, err := h.connect(ctx) c, err := h.connect(ctx)
@ -499,7 +499,7 @@ func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan
return ch, errc return ch, errc
} }
// Executes tiller.Ping RPC. // ping executes tiller.Ping RPC.
func (h *Client) ping(ctx context.Context) error { func (h *Client) ping(ctx context.Context) error {
c, err := h.connect(ctx) c, err := h.connect(ctx)
if err != nil { if err != nil {

@ -24,6 +24,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"sort"
"strings" "strings"
"time" "time"
@ -46,7 +47,7 @@ import (
"k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
watchtools "k8s.io/client-go/tools/watch" watchtools "k8s.io/client-go/tools/watch"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
@ -73,7 +74,7 @@ type Client struct {
// New creates a new Client. // New creates a new Client.
func New(getter genericclioptions.RESTClientGetter) *Client { func New(getter genericclioptions.RESTClientGetter) *Client {
if getter == nil { if getter == nil {
getter = genericclioptions.NewConfigFlags() getter = genericclioptions.NewConfigFlags(true)
} }
return &Client{ return &Client{
Factory: cmdutil.NewFactory(getter), Factory: cmdutil.NewFactory(getter),
@ -155,13 +156,41 @@ func (c *Client) Build(namespace string, reader io.Reader) (Result, error) {
return result, scrubValidationError(err) return result, scrubValidationError(err)
} }
// Return the resource info as internal
func resourceInfoToObject(info *resource.Info, c *Client) runtime.Object {
internalObj, err := asInternal(info)
if err != nil {
// If the problem is just that the resource is not registered, don't print any
// error. This is normal for custom resources.
if !runtime.IsNotRegisteredError(err) {
c.Log("Warning: conversion to internal type failed: %v", err)
}
// Add the unstructured object in this situation. It will still get listed, just
// with less information.
return info.Object
}
return internalObj
}
func sortByKey(objs map[string](map[string]runtime.Object)) []string {
var keys []string
// Create a simple slice, so we can sort it
for key := range objs {
keys = append(keys, key)
}
// Sort alphabetically by version/kind keys
sort.Strings(keys)
return keys
}
// Get gets Kubernetes resources as pretty-printed string. // Get gets Kubernetes resources as pretty-printed string.
// //
// Namespace will set the namespace. // Namespace will set the namespace.
func (c *Client) Get(namespace string, reader io.Reader) (string, error) { func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// Since we don't know what order the objects come in, let's group them by the types, so // Since we don't know what order the objects come in, let's group them by the types and then sort them, so
// that when we print them, they come out looking good (headers apply to subgroups, etc.). // that when we print them, they come out looking good (headers apply to subgroups, etc.).
objs := make(map[string][]runtime.Object) objs := make(map[string](map[string]runtime.Object))
infos, err := c.BuildUnstructured(namespace, reader) infos, err := c.BuildUnstructured(namespace, reader)
if err != nil { if err != nil {
return "", err return "", err
@ -182,19 +211,15 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// versions per cluster, but this certainly won't hurt anything, so let's be safe. // versions per cluster, but this certainly won't hurt anything, so let's be safe.
gvk := info.ResourceMapping().GroupVersionKind gvk := info.ResourceMapping().GroupVersionKind
vk := gvk.Version + "/" + gvk.Kind vk := gvk.Version + "/" + gvk.Kind
internalObj, err := asInternal(info)
if err != nil { // Initialize map. The main map groups resources based on version/kind
// If the problem is just that the resource is not registered, don't print any // The second level is a simple 'Name' to 'Object', that will help sort
// error. This is normal for custom resources. // the individual resource later
if !runtime.IsNotRegisteredError(err) { if objs[vk] == nil {
c.Log("Warning: conversion to internal type failed: %v", err) objs[vk] = make(map[string]runtime.Object)
}
// Add the unstructured object in this situation. It will still get listed, just
// with less information.
objs[vk] = append(objs[vk], info.Object)
} else {
objs[vk] = append(objs[vk], internalObj)
} }
// Map between the resource name to the underlying info object
objs[vk][info.Name] = resourceInfoToObject(info, c)
//Get the relation pods //Get the relation pods
objPods, err = c.getSelectRelationPod(info, objPods) objPods, err = c.getSelectRelationPod(info, objPods)
@ -212,8 +237,12 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
for key, podItems := range objPods { for key, podItems := range objPods {
for i := range podItems { for i := range podItems {
pod := &core.Pod{} pod := &core.Pod{}
legacyscheme.Scheme.Convert(&podItems[i], pod, nil) legacyscheme.Scheme.Convert(&podItems[i], pod, nil)
objs[key+"(related)"] = append(objs[key+"(related)"], pod) if objs[key+"(related)"] == nil {
objs[key+"(related)"] = make(map[string]runtime.Object)
}
objs[key+"(related)"][pod.ObjectMeta.Name] = runtime.Object(pod)
} }
} }
@ -223,14 +252,28 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) {
// track of tab widths. // track of tab widths.
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
printFlags := get.NewHumanPrintFlags() printFlags := get.NewHumanPrintFlags()
for t, ot := range objs {
// Sort alphabetically by version/kind keys
vkKeys := sortByKey(objs)
// Iterate on sorted version/kind types
for _, t := range vkKeys {
if _, err = fmt.Fprintf(buf, "==> %s\n", t); err != nil { if _, err = fmt.Fprintf(buf, "==> %s\n", t); err != nil {
return "", err return "", err
} }
typePrinter, _ := printFlags.ToPrinter("") typePrinter, _ := printFlags.ToPrinter("")
for _, o := range ot {
if err := typePrinter.PrintObj(o, buf); err != nil { var sortedResources []string
c.Log("failed to print object type %s, object: %q :\n %v", t, o, err) for resource := range objs[t] {
sortedResources = append(sortedResources, resource)
}
sort.Strings(sortedResources)
// Now that each individual resource within the specific version/kind
// is sorted, we print each resource using the k8s printer
vk := objs[t]
for _, resourceName := range sortedResources {
if err := typePrinter.PrintObj(vk[resourceName], buf); err != nil {
c.Log("failed to print object type %s, object: %q :\n %v", t, resourceName, err)
return "", err return "", err
} }
} }
@ -290,9 +333,18 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
} }
originalInfo := original.Get(info) originalInfo := original.Get(info)
// The resource already exists in the cluster, but it wasn't defined in the previous release.
// In this case, we consider it to be a resource that was previously un-managed by the release and error out,
// asking for the user to intervene.
//
// See https://github.com/helm/helm/issues/1193 for more info.
if originalInfo == nil { if originalInfo == nil {
kind := info.Mapping.GroupVersionKind.Kind return fmt.Errorf(
return fmt.Errorf("no %s with the name %q found", kind, info.Name) "kind %s with the name %q already exists in the cluster and wasn't defined in the previous release. Before upgrading, please either delete the resource from the cluster or remove it from the chart",
info.Mapping.GroupVersionKind.Kind,
info.Name,
)
} }
if err := updateResource(c, info, originalInfo.Object, force, recreate); err != nil { if err := updateResource(c, info, originalInfo.Object, force, recreate); err != nil {
@ -320,8 +372,9 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
if err != nil { if err != nil {
c.Log("Unable to get annotations on %q, err: %s", info.Name, err) c.Log("Unable to get annotations on %q, err: %s", info.Name, err)
} }
if annotations != nil && annotations[ResourcePolicyAnno] == KeepPolicy { if ResourcePolicyIsKeep(annotations) {
c.Log("Skipping delete of %q due to annotation [%s=%s]", info.Name, ResourcePolicyAnno, KeepPolicy) policy := annotations[ResourcePolicyAnno]
c.Log("Skipping delete of %q due to annotation [%s=%s]", info.Name, ResourcePolicyAnno, policy)
continue continue
} }

@ -21,14 +21,15 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"sort"
"strings" "strings"
"testing" "testing"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
@ -77,6 +78,18 @@ func newPodList(names ...string) v1.PodList {
return list return list
} }
func newService(name string) v1.Service {
ns := v1.NamespaceDefault
return v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
SelfLink: "/api/v1/namespaces/default/services/" + name,
},
Spec: v1.ServiceSpec{},
}
}
func notFoundBody() *metav1.Status { func notFoundBody() *metav1.Status {
return &metav1.Status{ return &metav1.Status{
Code: http.StatusNotFound, Code: http.StatusNotFound,
@ -200,7 +213,7 @@ func TestUpdate(t *testing.T) {
// Test resource policy is respected // Test resource policy is respected
actions = nil actions = nil
listA.Items[2].ObjectMeta.Annotations = map[string]string{ResourcePolicyAnno: KeepPolicy} listA.Items[2].ObjectMeta.Annotations = map[string]string{ResourcePolicyAnno: "keep"}
if err := c.Update(v1.NamespaceDefault, objBody(&listA), objBody(&listB), false, false, 0, false); err != nil { if err := c.Update(v1.NamespaceDefault, objBody(&listA), objBody(&listB), false, false, 0, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -211,6 +224,43 @@ func TestUpdate(t *testing.T) {
} }
} }
func TestUpdateNonManagedResourceError(t *testing.T) {
actual := newPodList("starfish")
current := newPodList()
target := newPodList("starfish")
tf := cmdtesting.NewTestFactory()
defer tf.Cleanup()
tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
t.Logf("got request %s %s", p, m)
switch {
case p == "/namespaces/default/pods/starfish" && m == "GET":
return newResponse(200, &actual.Items[0])
default:
t.Fatalf("unexpected request: %s %s", req.Method, req.URL.Path)
return nil, nil
}
}),
}
c := &Client{
Factory: tf,
Log: nopLogger,
}
if err := c.Update(v1.NamespaceDefault, objBody(&current), objBody(&target), false, false, 0, false); err != nil {
if err.Error() != "kind Pod with the name \"starfish\" already exists in the cluster and wasn't defined in the previous release. Before upgrading, please either delete the resource from the cluster or remove it from the chart" {
t.Fatal(err)
}
} else {
t.Fatalf("error expected")
}
}
func TestBuild(t *testing.T) { func TestBuild(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -295,6 +345,95 @@ func TestGet(t *testing.T) {
} }
} }
func TestResourceTypeSortOrder(t *testing.T) {
pod := newPod("my-pod")
service := newService("my-service")
c := newTestClient()
defer c.Cleanup()
c.TestFactory.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
t.Logf("got request %s %s", p, m)
switch {
case p == "/namespaces/default/pods/my-pod" && m == "GET":
return newResponse(200, &pod)
case p == "/namespaces/default/services/my-service" && m == "GET":
return newResponse(200, &service)
default:
t.Fatalf("unexpected request: %s %s", req.Method, req.URL.Path)
return nil, nil
}
}),
}
// Test sorting order
data := strings.NewReader(testResourceTypeSortOrder)
o, err := c.Get("default", data)
if err != nil {
t.Errorf("Expected missing results, got %q", err)
}
podIndex := strings.Index(o, "my-pod")
serviceIndex := strings.Index(o, "my-service")
if podIndex == -1 {
t.Errorf("Expected v1/Pod my-pod, got %s", o)
}
if serviceIndex == -1 {
t.Errorf("Expected v1/Service my-service, got %s", o)
}
if !sort.IntsAreSorted([]int{podIndex, serviceIndex}) {
t.Errorf("Expected order: [v1/Pod v1/Service], got %s", o)
}
}
func TestResourceSortOrder(t *testing.T) {
list := newPodList("albacore", "coral", "beluga")
c := newTestClient()
defer c.Cleanup()
c.TestFactory.UnstructuredClient = &fake.RESTClient{
GroupVersion: schema.GroupVersion{Version: "v1"},
NegotiatedSerializer: unstructuredSerializer,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
p, m := req.URL.Path, req.Method
t.Logf("got request %s %s", p, m)
switch {
case p == "/namespaces/default/pods/albacore" && m == "GET":
return newResponse(200, &list.Items[0])
case p == "/namespaces/default/pods/coral" && m == "GET":
return newResponse(200, &list.Items[1])
case p == "/namespaces/default/pods/beluga" && m == "GET":
return newResponse(200, &list.Items[2])
default:
t.Fatalf("unexpected request: %s %s", req.Method, req.URL.Path)
return nil, nil
}
}),
}
// Test sorting order
data := strings.NewReader(testResourceSortOrder)
o, err := c.Get("default", data)
if err != nil {
t.Errorf("Expected missing results, got %q", err)
}
albacoreIndex := strings.Index(o, "albacore")
belugaIndex := strings.Index(o, "beluga")
coralIndex := strings.Index(o, "coral")
if albacoreIndex == -1 {
t.Errorf("Expected v1/Pod albacore, got %s", o)
}
if belugaIndex == -1 {
t.Errorf("Expected v1/Pod beluga, got %s", o)
}
if coralIndex == -1 {
t.Errorf("Expected v1/Pod coral, got %s", o)
}
if !sort.IntsAreSorted([]int{albacoreIndex, belugaIndex, coralIndex}) {
t.Errorf("Expected order: [albacore beluga coral], got %s", o)
}
}
func TestPerform(t *testing.T) { func TestPerform(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -376,6 +515,35 @@ func TestReal(t *testing.T) {
} }
} }
const testResourceTypeSortOrder = `
kind: Service
apiVersion: v1
metadata:
name: my-service
---
kind: Pod
apiVersion: v1
metadata:
name: my-pod
`
const testResourceSortOrder = `
kind: Pod
apiVersion: v1
metadata:
name: albacore
---
kind: Pod
apiVersion: v1
metadata:
name: coral
---
kind: Pod
apiVersion: v1
metadata:
name: beluga
`
const testServiceManifest = ` const testServiceManifest = `
kind: Service kind: Service
apiVersion: v1 apiVersion: v1

@ -19,14 +19,29 @@ package kube
// ResourcePolicyAnno is the annotation name for a resource policy // ResourcePolicyAnno is the annotation name for a resource policy
const ResourcePolicyAnno = "helm.sh/resource-policy" const ResourcePolicyAnno = "helm.sh/resource-policy"
// KeepPolicy is the resource policy type for keep // deletePolicy is the resource policy type for delete
// //
// This resource policy type allows resources to skip being deleted // This resource policy type allows explicitly opting in to the default
// during an uninstallRelease action. // resource deletion behavior, for example when overriding a chart's
const KeepPolicy = "keep" // default annotations. Any other value allows resources to skip being
// deleted during an uninstallRelease action.
const deletePolicy = "delete"
// NoUpgradeExistingPolicy is the resource policy type for no-upgrade-existing // NoUpgradeExistingPolicy is the resource policy type for no-upgrade-existing
// //
// This resource policy type allows resources to skip upgrading // This resource policy type allows resources to skip upgrading
// an existing resource if it already exists. // an existing resource if it already exists.
const NoUpgradeExistingPolicy = "no-upgrade-existing" const NoUpgradeExistingPolicy = "no-upgrade-existing"
// ResourcePolicyIsKeep accepts a map of Kubernetes resource annotations and
// returns true if the resource should be kept, otherwise false if it is safe
// for Helm to delete.
func ResourcePolicyIsKeep(annotations map[string]string) bool {
if annotations != nil {
resourcePolicyType, ok := annotations[ResourcePolicyAnno]
if ok && resourcePolicyType != deletePolicy {
return true
}
}
return false
}

@ -0,0 +1,72 @@
/*
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kube
import "testing"
func TestResourcePolicyIsKeep(t *testing.T) {
type annotations map[string]string
type testcase struct {
annotations
keep bool
}
cases := []testcase{
{nil, false},
{
annotations{
"foo": "bar",
},
false,
},
{
annotations{
ResourcePolicyAnno: "keep",
},
true,
},
{
annotations{
ResourcePolicyAnno: "KEEP ",
},
true,
},
{
annotations{
ResourcePolicyAnno: "",
},
true,
},
{
annotations{
ResourcePolicyAnno: "delete",
},
false,
},
{
annotations{
ResourcePolicyAnno: "DELETE",
},
true,
},
}
for _, tc := range cases {
if tc.keep != ResourcePolicyIsKeep(tc.annotations) {
t.Errorf("Expected function to return %t for annotations %v", tc.keep, tc.annotations)
}
}
}

@ -16,7 +16,7 @@ limitations under the License.
package kube // import "k8s.io/helm/pkg/kube" package kube // import "k8s.io/helm/pkg/kube"
import "k8s.io/cli-runtime/pkg/genericclioptions/resource" import "k8s.io/cli-runtime/pkg/resource"
// Result provides convenience methods for comparing collections of Infos. // Result provides convenience methods for comparing collections of Infos.
type Result []*resource.Info type Result []*resource.Info

@ -21,7 +21,7 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/resource"
) )
func TestResult(t *testing.T) { func TestResult(t *testing.T) {

@ -467,18 +467,18 @@ func (m *UpdateReleaseRequest) GetForce() bool {
return false return false
} }
func (m *UpdateReleaseRequest) GetSubNotes() bool { func (m *UpdateReleaseRequest) GetDescription() string {
if m != nil { if m != nil {
return m.SubNotes return m.Description
} }
return false return ""
} }
func (m *UpdateReleaseRequest) GetDescription() string { func (m *UpdateReleaseRequest) GetSubNotes() bool {
if m != nil { if m != nil {
return m.Description return m.SubNotes
} }
return "" return false
} }
// UpdateReleaseResponse is the response to an update request. // UpdateReleaseResponse is the response to an update request.
@ -711,18 +711,18 @@ func (m *InstallReleaseRequest) GetDisableCrdHook() bool {
return false return false
} }
func (m *InstallReleaseRequest) GetSubNotes() bool { func (m *InstallReleaseRequest) GetDescription() string {
if m != nil { if m != nil {
return m.SubNotes return m.Description
} }
return false return ""
} }
func (m *InstallReleaseRequest) GetDescription() string { func (m *InstallReleaseRequest) GetSubNotes() bool {
if m != nil { if m != nil {
return m.Description return m.SubNotes
} }
return "" return false
} }
// InstallReleaseResponse is the response from a release installation. // InstallReleaseResponse is the response from a release installation.
@ -752,7 +752,7 @@ type UninstallReleaseRequest struct {
Purge bool `protobuf:"varint,3,opt,name=purge" json:"purge,omitempty"` Purge bool `protobuf:"varint,3,opt,name=purge" json:"purge,omitempty"`
// timeout specifies the max amount of time any kubernetes client command can run. // timeout specifies the max amount of time any kubernetes client command can run.
Timeout int64 `protobuf:"varint,4,opt,name=timeout" json:"timeout,omitempty"` Timeout int64 `protobuf:"varint,4,opt,name=timeout" json:"timeout,omitempty"`
// Description, if set, will set the description for the uninnstalled release // Description, if set, will set the description for the uninstalled release
Description string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"` Description string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"`
} }
@ -1018,7 +1018,7 @@ type ReleaseServiceClient interface {
GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error)
// RollbackRelease rolls back a release to a previous version. // RollbackRelease rolls back a release to a previous version.
RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*RollbackReleaseResponse, error) RollbackRelease(ctx context.Context, in *RollbackReleaseRequest, opts ...grpc.CallOption) (*RollbackReleaseResponse, error)
// ReleaseHistory retrieves a releasse's history. // ReleaseHistory retrieves a release's history.
GetHistory(ctx context.Context, in *GetHistoryRequest, opts ...grpc.CallOption) (*GetHistoryResponse, error) GetHistory(ctx context.Context, in *GetHistoryRequest, opts ...grpc.CallOption) (*GetHistoryResponse, error)
// RunReleaseTest executes the tests defined of a named release // RunReleaseTest executes the tests defined of a named release
RunReleaseTest(ctx context.Context, in *TestReleaseRequest, opts ...grpc.CallOption) (ReleaseService_RunReleaseTestClient, error) RunReleaseTest(ctx context.Context, in *TestReleaseRequest, opts ...grpc.CallOption) (ReleaseService_RunReleaseTestClient, error)
@ -1190,7 +1190,7 @@ type ReleaseServiceServer interface {
GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error)
// RollbackRelease rolls back a release to a previous version. // RollbackRelease rolls back a release to a previous version.
RollbackRelease(context.Context, *RollbackReleaseRequest) (*RollbackReleaseResponse, error) RollbackRelease(context.Context, *RollbackReleaseRequest) (*RollbackReleaseResponse, error)
// ReleaseHistory retrieves a releasse's history. // ReleaseHistory retrieves a release's history.
GetHistory(context.Context, *GetHistoryRequest) (*GetHistoryResponse, error) GetHistory(context.Context, *GetHistoryRequest) (*GetHistoryResponse, error)
// RunReleaseTest executes the tests defined of a named release // RunReleaseTest executes the tests defined of a named release
RunReleaseTest(*TestReleaseRequest, ReleaseService_RunReleaseTestServer) error RunReleaseTest(*TestReleaseRequest, ReleaseService_RunReleaseTestServer) error
@ -1441,86 +1441,87 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{
func init() { proto.RegisterFile("hapi/services/tiller.proto", fileDescriptor0) } func init() { proto.RegisterFile("hapi/services/tiller.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 1289 bytes of a gzipped FileDescriptorProto // 1308 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xed, 0x72, 0xdb, 0x44, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xed, 0x6e, 0x1b, 0x45,
0x17, 0x8e, 0x2d, 0x7f, 0x1e, 0xa7, 0x7e, 0xdd, 0x6d, 0x9a, 0xa8, 0x7a, 0x0b, 0x63, 0xc4, 0x40, 0x17, 0x8e, 0xbd, 0xfe, 0x3c, 0x4e, 0xfc, 0xba, 0xd3, 0x34, 0xd9, 0xee, 0x5b, 0x50, 0x58, 0x04,
0xdd, 0x42, 0x1d, 0x30, 0xfc, 0x61, 0x86, 0x61, 0x26, 0x75, 0x3d, 0x49, 0x21, 0xa4, 0x33, 0x72, 0x75, 0x0b, 0x75, 0xc0, 0xf0, 0x07, 0x09, 0x21, 0xa5, 0xae, 0x95, 0x14, 0x82, 0x2b, 0xad, 0xdb,
0x5b, 0x66, 0x98, 0x61, 0x3c, 0x8a, 0xbd, 0x6e, 0x45, 0x65, 0xc9, 0x68, 0x57, 0xa1, 0xb9, 0x00, 0x22, 0x21, 0x21, 0x6b, 0x63, 0x8f, 0xdb, 0xa5, 0xeb, 0x5d, 0xb3, 0x33, 0x1b, 0x9a, 0x1b, 0x40,
0x98, 0xe1, 0x3e, 0xb8, 0x10, 0xee, 0x83, 0xeb, 0xe0, 0x3f, 0xb3, 0x5f, 0x8a, 0x56, 0x96, 0x1c, 0xe2, 0x27, 0x97, 0x80, 0xc4, 0x85, 0x70, 0x1f, 0xdc, 0x0c, 0x9a, 0xaf, 0xcd, 0xce, 0x7a, 0xd7,
0x91, 0x3f, 0xb1, 0x76, 0xcf, 0xd9, 0xf3, 0xf1, 0x3c, 0x7b, 0xce, 0x9e, 0x80, 0xf5, 0xc6, 0x5d, 0x5d, 0xf2, 0x27, 0xde, 0x99, 0x73, 0xe6, 0x7c, 0x3c, 0xcf, 0x9c, 0x33, 0x27, 0x60, 0xbd, 0x76,
0x7b, 0x87, 0x04, 0x47, 0x17, 0xde, 0x1c, 0x93, 0x43, 0xea, 0xf9, 0x3e, 0x8e, 0x86, 0xeb, 0x28, 0xd7, 0xde, 0x31, 0xc1, 0xd1, 0xa5, 0x37, 0xc7, 0xe4, 0x98, 0x7a, 0xbe, 0x8f, 0xa3, 0xc1, 0x3a,
0xa4, 0x21, 0xda, 0x63, 0xb2, 0xa1, 0x92, 0x0d, 0x85, 0xcc, 0xda, 0xe7, 0x27, 0xe6, 0x6f, 0xdc, 0x0a, 0x69, 0x88, 0xf6, 0x99, 0x6c, 0xa0, 0x64, 0x03, 0x21, 0xb3, 0x0e, 0xf8, 0x89, 0xf9, 0x6b,
0x88, 0x8a, 0xbf, 0x42, 0xdb, 0x3a, 0x48, 0xef, 0x87, 0xc1, 0xd2, 0x7b, 0x2d, 0x05, 0xc2, 0x45, 0x37, 0xa2, 0xe2, 0xaf, 0xd0, 0xb6, 0x0e, 0xd3, 0xfb, 0x61, 0xb0, 0xf4, 0x5e, 0x49, 0x81, 0x70,
0x84, 0x7d, 0xec, 0x12, 0xac, 0x7e, 0xb5, 0x43, 0x4a, 0xe6, 0x05, 0xcb, 0x50, 0x0a, 0xfe, 0xaf, 0x11, 0x61, 0x1f, 0xbb, 0x04, 0xab, 0x5f, 0xed, 0x90, 0x92, 0x79, 0xc1, 0x32, 0x94, 0x82, 0xff,
0x09, 0x28, 0x26, 0x74, 0x16, 0xc5, 0x81, 0x14, 0xde, 0xd3, 0x84, 0x84, 0xba, 0x34, 0x26, 0x9a, 0x6b, 0x02, 0x8a, 0x09, 0x9d, 0x45, 0x71, 0x20, 0x85, 0x77, 0x35, 0x21, 0xa1, 0x2e, 0x8d, 0x89,
0xb3, 0x0b, 0x1c, 0x11, 0x2f, 0x0c, 0xd4, 0xaf, 0x90, 0xd9, 0x7f, 0x55, 0xe1, 0xce, 0xa9, 0x47, 0xe6, 0xec, 0x12, 0x47, 0xc4, 0x0b, 0x03, 0xf5, 0x2b, 0x64, 0xf6, 0xdf, 0x55, 0xb8, 0x7d, 0xee,
0xa8, 0x23, 0x0e, 0x12, 0x07, 0xff, 0x12, 0x63, 0x42, 0xd1, 0x1e, 0xd4, 0x7d, 0x6f, 0xe5, 0x51, 0x11, 0xea, 0x88, 0x83, 0xc4, 0xc1, 0xbf, 0xc4, 0x98, 0x50, 0xb4, 0x0f, 0x75, 0xdf, 0x5b, 0x79,
0xb3, 0xd2, 0xaf, 0x0c, 0x0c, 0x47, 0x2c, 0xd0, 0x3e, 0x34, 0xc2, 0xe5, 0x92, 0x60, 0x6a, 0x56, 0xd4, 0xac, 0x1c, 0x55, 0xfa, 0x86, 0x23, 0x16, 0xe8, 0x00, 0x1a, 0xe1, 0x72, 0x49, 0x30, 0x35,
0xfb, 0x95, 0x41, 0xdb, 0x91, 0x2b, 0xf4, 0x0d, 0x34, 0x49, 0x18, 0xd1, 0xd9, 0xf9, 0xa5, 0x69, 0xab, 0x47, 0x95, 0x7e, 0xdb, 0x91, 0x2b, 0xf4, 0x0d, 0x34, 0x49, 0x18, 0xd1, 0xd9, 0xc5, 0x95,
0xf4, 0x2b, 0x83, 0xee, 0xe8, 0xa3, 0x61, 0x1e, 0x4e, 0x43, 0xe6, 0x69, 0x1a, 0x46, 0x74, 0xc8, 0x69, 0x1c, 0x55, 0xfa, 0xdd, 0xe1, 0x47, 0x83, 0x3c, 0x9c, 0x06, 0xcc, 0xd3, 0x34, 0x8c, 0xe8,
0xfe, 0x3c, 0xb9, 0x74, 0x1a, 0x84, 0xff, 0x32, 0xbb, 0x4b, 0xcf, 0xa7, 0x38, 0x32, 0x6b, 0xc2, 0x80, 0xfd, 0x79, 0x7c, 0xe5, 0x34, 0x08, 0xff, 0x65, 0x76, 0x97, 0x9e, 0x4f, 0x71, 0x64, 0xd6,
0xae, 0x58, 0xa1, 0x63, 0x00, 0x6e, 0x37, 0x8c, 0x16, 0x38, 0x32, 0xeb, 0xdc, 0xf4, 0xa0, 0x84, 0x84, 0x5d, 0xb1, 0x42, 0xa7, 0x00, 0xdc, 0x6e, 0x18, 0x2d, 0x70, 0x64, 0xd6, 0xb9, 0xe9, 0x7e,
0xe9, 0xe7, 0x4c, 0xdf, 0x69, 0x13, 0xf5, 0x89, 0xbe, 0x86, 0x5d, 0x01, 0xc9, 0x6c, 0x1e, 0x2e, 0x09, 0xd3, 0xcf, 0x98, 0xbe, 0xd3, 0x26, 0xea, 0x13, 0x7d, 0x0d, 0xbb, 0x02, 0x92, 0xd9, 0x3c,
0x30, 0x31, 0x1b, 0x7d, 0x63, 0xd0, 0x1d, 0xdd, 0x13, 0xa6, 0x14, 0xfc, 0x53, 0x01, 0xda, 0x38, 0x5c, 0x60, 0x62, 0x36, 0x8e, 0x8c, 0x7e, 0x77, 0x78, 0x57, 0x98, 0x52, 0xf0, 0x4f, 0x05, 0x68,
0x5c, 0x60, 0xa7, 0x23, 0xd4, 0xd9, 0x37, 0x41, 0xf7, 0xa1, 0x1d, 0xb8, 0x2b, 0x4c, 0xd6, 0xee, 0xa3, 0x70, 0x81, 0x9d, 0x8e, 0x50, 0x67, 0xdf, 0x04, 0xdd, 0x83, 0x76, 0xe0, 0xae, 0x30, 0x59,
0x1c, 0x9b, 0x4d, 0x1e, 0xe1, 0xd5, 0x86, 0x1d, 0x40, 0x4b, 0x39, 0xb7, 0x9f, 0x40, 0x43, 0xa4, 0xbb, 0x73, 0x6c, 0x36, 0x79, 0x84, 0xd7, 0x1b, 0x76, 0x00, 0x2d, 0xe5, 0xdc, 0x7e, 0x0c, 0x0d,
0x86, 0x3a, 0xd0, 0x7c, 0x79, 0xf6, 0xdd, 0xd9, 0xf3, 0x1f, 0xce, 0x7a, 0x3b, 0xa8, 0x05, 0xb5, 0x91, 0x1a, 0xea, 0x40, 0xf3, 0xc5, 0xe4, 0xbb, 0xc9, 0xb3, 0x1f, 0x26, 0xbd, 0x1d, 0xd4, 0x82,
0xb3, 0xa3, 0xef, 0x27, 0xbd, 0x0a, 0xba, 0x0d, 0xb7, 0x4e, 0x8f, 0xa6, 0x2f, 0x66, 0xce, 0xe4, 0xda, 0xe4, 0xe4, 0xfb, 0x71, 0xaf, 0x82, 0x6e, 0xc1, 0xde, 0xf9, 0xc9, 0xf4, 0xf9, 0xcc, 0x19,
0x74, 0x72, 0x34, 0x9d, 0x3c, 0xed, 0x55, 0x51, 0x17, 0x60, 0x7c, 0x72, 0xe4, 0xbc, 0x98, 0x71, 0x9f, 0x8f, 0x4f, 0xa6, 0xe3, 0x27, 0xbd, 0x2a, 0xea, 0x02, 0x8c, 0xce, 0x4e, 0x9c, 0xe7, 0x33,
0x15, 0xc3, 0x7e, 0x1f, 0xda, 0x49, 0x0e, 0xa8, 0x09, 0xc6, 0xd1, 0x74, 0x2c, 0x4c, 0x3c, 0x9d, 0xae, 0x62, 0xd8, 0xef, 0x43, 0x3b, 0xc9, 0x01, 0x35, 0xc1, 0x38, 0x99, 0x8e, 0x84, 0x89, 0x27,
0x4c, 0xc7, 0xbd, 0x8a, 0xfd, 0x47, 0x05, 0xf6, 0x74, 0xca, 0xc8, 0x3a, 0x0c, 0x08, 0x66, 0x9c, 0xe3, 0xe9, 0xa8, 0x57, 0xb1, 0x7f, 0xaf, 0xc0, 0xbe, 0x4e, 0x19, 0x59, 0x87, 0x01, 0xc1, 0x8c,
0xcd, 0xc3, 0x38, 0x48, 0x38, 0xe3, 0x0b, 0x84, 0xa0, 0x16, 0xe0, 0x77, 0x8a, 0x31, 0xfe, 0xcd, 0xb3, 0x79, 0x18, 0x07, 0x09, 0x67, 0x7c, 0x81, 0x10, 0xd4, 0x02, 0xfc, 0x56, 0x31, 0xc6, 0xbf,
0x34, 0x69, 0x48, 0x5d, 0x9f, 0xb3, 0x65, 0x38, 0x62, 0x81, 0x3e, 0x87, 0x96, 0x84, 0x82, 0x98, 0x99, 0x26, 0x0d, 0xa9, 0xeb, 0x73, 0xb6, 0x0c, 0x47, 0x2c, 0xd0, 0xe7, 0xd0, 0x92, 0x50, 0x10,
0xb5, 0xbe, 0x31, 0xe8, 0x8c, 0xee, 0xea, 0x00, 0x49, 0x8f, 0x4e, 0xa2, 0x66, 0x1f, 0xc3, 0xc1, 0xb3, 0x76, 0x64, 0xf4, 0x3b, 0xc3, 0x3b, 0x3a, 0x40, 0xd2, 0xa3, 0x93, 0xa8, 0xd9, 0xa7, 0x70,
0x31, 0x56, 0x91, 0x08, 0xfc, 0xd4, 0x0d, 0x62, 0x7e, 0xdd, 0x15, 0xe6, 0xc1, 0x30, 0xbf, 0xee, 0x78, 0x8a, 0x55, 0x24, 0x02, 0x3f, 0x75, 0x83, 0x98, 0x5f, 0x77, 0x85, 0x79, 0x30, 0xcc, 0xaf,
0x0a, 0x23, 0x13, 0x9a, 0xf2, 0xfa, 0xf1, 0x70, 0xea, 0x8e, 0x5a, 0xda, 0x14, 0xcc, 0x4d, 0x43, 0xbb, 0xc2, 0xc8, 0x84, 0xa6, 0xbc, 0x7e, 0x3c, 0x9c, 0xba, 0xa3, 0x96, 0x36, 0x05, 0x73, 0xd3,
0x32, 0xaf, 0x3c, 0x4b, 0x1f, 0x43, 0x8d, 0x55, 0x06, 0x37, 0xd3, 0x19, 0x21, 0x3d, 0xce, 0x67, 0x90, 0xcc, 0x2b, 0xcf, 0xd2, 0xc7, 0x50, 0x63, 0x95, 0xc1, 0xcd, 0x74, 0x86, 0x48, 0x8f, 0xf3,
0xc1, 0x32, 0x74, 0xb8, 0x5c, 0xa7, 0xce, 0xc8, 0x52, 0x77, 0x92, 0xf6, 0x3a, 0x0e, 0x03, 0x8a, 0x69, 0xb0, 0x0c, 0x1d, 0x2e, 0xd7, 0xa9, 0x33, 0xb2, 0xd4, 0x9d, 0xa5, 0xbd, 0x8e, 0xc2, 0x80,
0x03, 0x7a, 0xb3, 0xf8, 0x4f, 0xe1, 0x5e, 0x8e, 0x25, 0x99, 0xc0, 0x21, 0x34, 0x65, 0x68, 0xdc, 0xe2, 0x80, 0xde, 0x2c, 0xfe, 0x73, 0xb8, 0x9b, 0x63, 0x49, 0x26, 0x70, 0x0c, 0x4d, 0x19, 0x1a,
0x5a, 0x21, 0xae, 0x4a, 0xcb, 0xfe, 0xcd, 0x80, 0xbd, 0x97, 0xeb, 0x85, 0x4b, 0xb1, 0x12, 0x6d, 0xb7, 0x56, 0x88, 0xab, 0xd2, 0xb2, 0xff, 0x34, 0x60, 0xff, 0xc5, 0x7a, 0xe1, 0x52, 0xac, 0x44,
0x09, 0xea, 0x01, 0xd4, 0x79, 0x87, 0x91, 0x58, 0xdc, 0x16, 0xb6, 0x45, 0x1b, 0x1a, 0xb3, 0xbf, 0x5b, 0x82, 0xba, 0x0f, 0x75, 0xde, 0x61, 0x24, 0x16, 0xb7, 0x84, 0x6d, 0xd1, 0x86, 0x46, 0xec,
0x8e, 0x90, 0xa3, 0x47, 0xd0, 0xb8, 0x70, 0xfd, 0x18, 0x13, 0x0e, 0x44, 0x82, 0x9a, 0xd4, 0xe4, 0xaf, 0x23, 0xe4, 0xe8, 0x21, 0x34, 0x2e, 0x5d, 0x3f, 0xc6, 0x84, 0x03, 0x91, 0xa0, 0x26, 0x35,
0xed, 0xc9, 0x91, 0x1a, 0xe8, 0x00, 0x9a, 0x8b, 0xe8, 0x92, 0xf5, 0x17, 0x5e, 0x92, 0x2d, 0xa7, 0x79, 0x7b, 0x72, 0xa4, 0x06, 0x3a, 0x84, 0xe6, 0x22, 0xba, 0x62, 0xfd, 0x85, 0x97, 0x64, 0xcb,
0xb1, 0x88, 0x2e, 0x9d, 0x38, 0x40, 0x1f, 0xc2, 0xad, 0x85, 0x47, 0xdc, 0x73, 0x1f, 0xcf, 0xde, 0x69, 0x2c, 0xa2, 0x2b, 0x27, 0x0e, 0xd0, 0x87, 0xb0, 0xb7, 0xf0, 0x88, 0x7b, 0xe1, 0xe3, 0xd9,
0x84, 0xe1, 0x5b, 0xc2, 0xab, 0xb2, 0xe5, 0xec, 0xca, 0xcd, 0x13, 0xb6, 0x87, 0x2c, 0x76, 0x93, 0xeb, 0x30, 0x7c, 0x43, 0x78, 0x55, 0xb6, 0x9c, 0x5d, 0xb9, 0x79, 0xc6, 0xf6, 0x90, 0xc5, 0x6e,
0xe6, 0x11, 0x76, 0x29, 0x36, 0x1b, 0x5c, 0x9e, 0xac, 0x19, 0x86, 0xd4, 0x5b, 0xe1, 0x30, 0xa6, 0xd2, 0x3c, 0xc2, 0x2e, 0xc5, 0x66, 0x83, 0xcb, 0x93, 0x35, 0xc3, 0x90, 0x7a, 0x2b, 0x1c, 0xc6,
0xbc, 0x94, 0x0c, 0x47, 0x2d, 0xd1, 0x07, 0xb0, 0x1b, 0x61, 0x82, 0xe9, 0x4c, 0x46, 0xd9, 0xe2, 0x94, 0x97, 0x92, 0xe1, 0xa8, 0x25, 0xfa, 0x00, 0x76, 0x23, 0x4c, 0x30, 0x9d, 0xc9, 0x28, 0x5b,
0x27, 0x3b, 0x7c, 0xef, 0x95, 0x08, 0x0b, 0x41, 0xed, 0x57, 0xd7, 0xa3, 0x66, 0x9b, 0x8b, 0xf8, 0xfc, 0x64, 0x87, 0xef, 0xbd, 0x14, 0x61, 0x21, 0xa8, 0xfd, 0xea, 0x7a, 0xd4, 0x6c, 0x73, 0x11,
0xb7, 0x38, 0x16, 0x13, 0xac, 0x8e, 0x81, 0x3a, 0x16, 0x13, 0x2c, 0x8f, 0xed, 0x41, 0x7d, 0x19, 0xff, 0x16, 0xc7, 0x62, 0x82, 0xd5, 0x31, 0x50, 0xc7, 0x62, 0x82, 0xe5, 0xb1, 0x7d, 0xa8, 0x2f,
0x46, 0x73, 0x6c, 0x76, 0xb8, 0x4c, 0x2c, 0x50, 0x1f, 0x3a, 0x0b, 0x4c, 0xe6, 0x91, 0xb7, 0xa6, 0xc3, 0x68, 0x8e, 0xcd, 0x0e, 0x97, 0x89, 0x05, 0x3a, 0x82, 0xce, 0x02, 0x93, 0x79, 0xe4, 0xad,
0x8c, 0xd1, 0x5d, 0x8e, 0x69, 0x7a, 0xcb, 0x3e, 0x81, 0xbb, 0x19, 0x1a, 0x6e, 0xca, 0xe8, 0xef, 0x29, 0x63, 0x74, 0x97, 0x63, 0x9a, 0xde, 0x62, 0x79, 0x90, 0xf8, 0x62, 0x12, 0x52, 0x4c, 0xcc,
0x55, 0xd8, 0x77, 0x42, 0xdf, 0x3f, 0x77, 0xe7, 0x6f, 0x4b, 0x70, 0x9a, 0x82, 0xbf, 0xba, 0x1d, 0x3d, 0x91, 0x87, 0x5a, 0xdb, 0x67, 0x70, 0x27, 0x43, 0xd1, 0x4d, 0xd9, 0xfe, 0xad, 0x0a, 0x07,
0x7e, 0x23, 0x07, 0xfe, 0xd4, 0x35, 0xad, 0x69, 0xd7, 0x54, 0x23, 0xa6, 0x5e, 0x4c, 0x4c, 0x43, 0x4e, 0xe8, 0xfb, 0x17, 0xee, 0xfc, 0x4d, 0x09, 0xbe, 0x53, 0xd4, 0x54, 0xb7, 0x53, 0x63, 0xe4,
0x27, 0x46, 0xa1, 0xde, 0x4c, 0xa1, 0x9e, 0x40, 0xda, 0xda, 0x02, 0x69, 0x7b, 0x13, 0xd2, 0x6f, 0x50, 0x93, 0xba, 0xc2, 0x35, 0xed, 0x0a, 0x6b, 0xa4, 0xd5, 0x8b, 0x49, 0x6b, 0xe8, 0xa4, 0x29,
0xe1, 0x60, 0x03, 0x87, 0x9b, 0x82, 0xfa, 0x4f, 0x15, 0xee, 0x3e, 0x0b, 0x08, 0x75, 0x7d, 0x3f, 0x46, 0x9a, 0x29, 0x46, 0x12, 0xb8, 0x5b, 0x5b, 0xe0, 0x6e, 0x6f, 0xc0, 0x6d, 0x7f, 0x0b, 0x87,
0x83, 0x69, 0x52, 0x13, 0x95, 0xd2, 0x35, 0x51, 0xfd, 0x2f, 0x35, 0x61, 0x68, 0xa4, 0x28, 0x06, 0x1b, 0x38, 0xdc, 0x14, 0xd4, 0x3f, 0x0c, 0xb8, 0xf3, 0x34, 0x20, 0xd4, 0xf5, 0xfd, 0x0c, 0xa6,
0x6b, 0x29, 0x06, 0x4b, 0xd5, 0x89, 0xd6, 0x9d, 0x1a, 0x99, 0xee, 0x84, 0xde, 0x03, 0x10, 0x17, 0x49, 0xbd, 0x54, 0x4a, 0xd7, 0x4b, 0xf5, 0xbf, 0xd4, 0x8b, 0xa1, 0x91, 0xa2, 0x18, 0xac, 0xa5,
0x9b, 0x1b, 0x17, 0xe0, 0xb7, 0xf9, 0xce, 0x99, 0x6c, 0x46, 0x8a, 0xaf, 0x56, 0x3e, 0x5f, 0xe9, 0x18, 0x2c, 0x55, 0x43, 0x5a, 0xe7, 0x6a, 0x64, 0x3a, 0x17, 0x7a, 0x0f, 0x40, 0x5c, 0x7a, 0x6e,
0x2a, 0x19, 0x40, 0x4f, 0xc5, 0x33, 0x8f, 0x16, 0x3c, 0x26, 0x59, 0x29, 0x5d, 0xb9, 0x3f, 0x8e, 0x5c, 0x80, 0xdf, 0xe6, 0x3b, 0x13, 0xd9, 0xa8, 0x14, 0x5f, 0xad, 0x7c, 0xbe, 0xd2, 0x15, 0xd4,
0x16, 0x2c, 0xaa, 0x2c, 0x87, 0x9d, 0x4d, 0x0e, 0x9f, 0xc1, 0x7e, 0x16, 0xf6, 0x9b, 0x52, 0xf8, 0x87, 0x9e, 0x8a, 0x67, 0x1e, 0x2d, 0x78, 0x4c, 0xb2, 0x8a, 0xba, 0x72, 0x7f, 0x14, 0x2d, 0x58,
0x67, 0x05, 0x0e, 0x5e, 0x06, 0x5e, 0x2e, 0x89, 0x79, 0x85, 0xb1, 0x01, 0x6b, 0x35, 0x07, 0xd6, 0x54, 0x59, 0x0e, 0x3b, 0xdb, 0x4b, 0x66, 0x37, 0x53, 0x32, 0x4f, 0xe1, 0x20, 0x4b, 0xc9, 0x4d,
0x3d, 0xa8, 0xaf, 0xe3, 0xe8, 0x35, 0x96, 0x34, 0x89, 0x45, 0x1a, 0xaf, 0x9a, 0x8e, 0x57, 0x26, 0xe9, 0xfd, 0xab, 0x02, 0x87, 0x2f, 0x02, 0x2f, 0x97, 0xe0, 0xbc, 0xa2, 0xd9, 0x80, 0xbc, 0x9a,
0xe3, 0xfa, 0x66, 0xc6, 0x33, 0x30, 0x37, 0xa3, 0xbc, 0x61, 0xce, 0x2c, 0xaf, 0xe4, 0xed, 0x6a, 0x03, 0xf9, 0x3e, 0xd4, 0xd7, 0x71, 0xf4, 0x0a, 0x4b, 0x0a, 0xc5, 0x22, 0x8d, 0x65, 0x4d, 0xc7,
0x8b, 0x77, 0xca, 0xbe, 0x03, 0xb7, 0x8f, 0x31, 0x7d, 0x25, 0xca, 0x54, 0x02, 0x60, 0x4f, 0x00, 0x32, 0x83, 0x46, 0x7d, 0xf3, 0x46, 0xcf, 0xc0, 0xdc, 0x8c, 0xf2, 0x86, 0x39, 0xb3, 0xbc, 0x92,
0xa5, 0x37, 0xaf, 0xfc, 0xc9, 0x2d, 0xdd, 0x9f, 0x1a, 0xec, 0x94, 0xbe, 0xd2, 0xb2, 0xbf, 0xe2, 0x37, 0xaf, 0x2d, 0xde, 0x37, 0xfb, 0x36, 0xdc, 0x3a, 0xc5, 0xf4, 0xa5, 0x28, 0x61, 0x09, 0x80,
0xb6, 0x4f, 0x3c, 0x42, 0xc3, 0xe8, 0x72, 0x1b, 0xb8, 0x3d, 0x30, 0x56, 0xee, 0x3b, 0xf9, 0xb4, 0x3d, 0x06, 0x94, 0xde, 0xbc, 0xf6, 0x27, 0xb7, 0x74, 0x7f, 0x6a, 0x20, 0x54, 0xfa, 0x4a, 0xcb,
0xb1, 0x4f, 0xfb, 0x98, 0x47, 0x90, 0x1c, 0x95, 0x11, 0xa4, 0x07, 0x85, 0x4a, 0xb9, 0x41, 0xe1, 0xfe, 0x8a, 0xdb, 0x3e, 0xf3, 0x08, 0x0d, 0xa3, 0xab, 0x6d, 0xe0, 0xf6, 0xc0, 0x58, 0xb9, 0x6f,
0x1d, 0xa0, 0x17, 0x38, 0x99, 0x59, 0xae, 0x79, 0x63, 0x15, 0x4d, 0x55, 0x9d, 0x26, 0x13, 0x9a, 0xe5, 0x93, 0xc8, 0x3e, 0xed, 0x53, 0x1e, 0x41, 0x72, 0x54, 0x46, 0x90, 0x1e, 0x30, 0x2a, 0xe5,
0x73, 0x1f, 0xbb, 0x41, 0xbc, 0x96, 0xc4, 0xaa, 0x25, 0x6b, 0x6b, 0x6b, 0x37, 0x72, 0x7d, 0x1f, 0x06, 0x8c, 0xb7, 0x80, 0x9e, 0xe3, 0x64, 0xd6, 0x79, 0xc7, 0xdb, 0xac, 0x68, 0xaa, 0xea, 0x34,
0xfb, 0xf2, 0xb9, 0x4a, 0xd6, 0xf6, 0x4f, 0x70, 0x47, 0xf3, 0x2c, 0x73, 0x60, 0xb9, 0x92, 0xd7, 0x99, 0xd0, 0x9c, 0xfb, 0xd8, 0x0d, 0xe2, 0xb5, 0x24, 0x56, 0x2d, 0xd9, 0x65, 0x5d, 0xbb, 0x91,
0xd2, 0x33, 0xfb, 0x44, 0x5f, 0x42, 0x43, 0x0c, 0x7d, 0xdc, 0x6f, 0x77, 0x74, 0x5f, 0xcf, 0x89, 0xeb, 0xfb, 0xd8, 0x97, 0xcf, 0x5c, 0xb2, 0xb6, 0x7f, 0x82, 0xdb, 0x9a, 0x67, 0x99, 0x03, 0xcb,
0x1b, 0x89, 0x03, 0x39, 0x25, 0x3a, 0x52, 0x77, 0xf4, 0x77, 0x0b, 0xba, 0x6a, 0x6c, 0x11, 0x23, 0x95, 0xbc, 0x92, 0x9e, 0xd9, 0x27, 0xfa, 0x12, 0x1a, 0x62, 0x58, 0xe4, 0x7e, 0xbb, 0xc3, 0x7b,
0x29, 0xf2, 0x60, 0x37, 0x3d, 0x9f, 0xa1, 0x87, 0xc5, 0x13, 0x6b, 0x66, 0xec, 0xb6, 0x1e, 0x95, 0x7a, 0x4e, 0xdc, 0x48, 0x1c, 0xc8, 0xe9, 0xd2, 0x91, 0xba, 0xc3, 0x7f, 0x5a, 0xd0, 0x55, 0xe3,
0x51, 0x15, 0x19, 0xd8, 0x3b, 0x9f, 0x55, 0x10, 0x81, 0x5e, 0x76, 0x6c, 0x42, 0x8f, 0xf3, 0x6d, 0x8e, 0x18, 0x65, 0x91, 0x07, 0xbb, 0xe9, 0xb9, 0x0e, 0x3d, 0x28, 0x9e, 0x74, 0x33, 0xe3, 0xba,
0x14, 0xcc, 0x69, 0xd6, 0xb0, 0xac, 0xba, 0x72, 0x8b, 0x2e, 0xf8, 0x7d, 0xd2, 0x67, 0x1d, 0x74, 0xf5, 0xb0, 0x8c, 0xaa, 0xc8, 0xc0, 0xde, 0xf9, 0xac, 0x82, 0x08, 0xf4, 0xb2, 0xe3, 0x16, 0x7a,
0xad, 0x19, 0x7d, 0xbc, 0xb2, 0x0e, 0x4b, 0xeb, 0x27, 0x7e, 0x7f, 0x86, 0x5b, 0xda, 0x6b, 0x8c, 0x94, 0x6f, 0xa3, 0x60, 0xbe, 0xb3, 0x06, 0x65, 0xd5, 0x95, 0x5b, 0x74, 0xc9, 0xef, 0x93, 0x3e,
0x0a, 0xd0, 0xca, 0x9b, 0x9c, 0xac, 0x4f, 0x4a, 0xe9, 0x26, 0xbe, 0x56, 0xd0, 0xd5, 0x5b, 0x1c, 0x23, 0xa1, 0x77, 0x9a, 0xd1, 0xc7, 0x32, 0xeb, 0xb8, 0xb4, 0x7e, 0xe2, 0xf7, 0x67, 0xd8, 0xd3,
0x2a, 0x30, 0x90, 0xfb, 0xfe, 0x58, 0x9f, 0x96, 0x53, 0x4e, 0xdc, 0x11, 0xe8, 0x65, 0xfb, 0x4b, 0x5e, 0x6a, 0x54, 0x80, 0x56, 0xde, 0xc4, 0x65, 0x7d, 0x52, 0x4a, 0x37, 0xf1, 0xb5, 0x82, 0xae,
0x11, 0x8f, 0x05, 0xdd, 0xb2, 0x88, 0xc7, 0xa2, 0xb6, 0x65, 0xef, 0x20, 0x17, 0xe0, 0xaa, 0xbd, 0xde, 0xe2, 0x50, 0x81, 0x81, 0xdc, 0xb7, 0xc9, 0xfa, 0xb4, 0x9c, 0x72, 0xe2, 0x8e, 0x40, 0x2f,
0xa0, 0x07, 0x85, 0x84, 0xe8, 0x5d, 0xc9, 0x1a, 0x5c, 0xaf, 0x98, 0xb8, 0x58, 0xc3, 0xff, 0x32, 0xdb, 0x5f, 0x8a, 0x78, 0x2c, 0xe8, 0x96, 0x45, 0x3c, 0x16, 0xb5, 0x2d, 0x7b, 0x07, 0xb9, 0x00,
0xaf, 0x3d, 0x2a, 0x80, 0x26, 0x7f, 0x38, 0xb2, 0x1e, 0x97, 0xd4, 0xce, 0x24, 0x25, 0x3b, 0xd6, 0xd7, 0xed, 0x05, 0xdd, 0x2f, 0x24, 0x44, 0xef, 0x4a, 0x56, 0xff, 0xdd, 0x8a, 0x89, 0x8b, 0x35,
0x96, 0xa4, 0xf4, 0x76, 0xb8, 0x25, 0xa9, 0x4c, 0xf3, 0xb3, 0x77, 0x90, 0x07, 0x5d, 0x27, 0x0e, 0xfc, 0x2f, 0x33, 0x09, 0xa0, 0x02, 0x68, 0xf2, 0x07, 0x27, 0xeb, 0x51, 0x49, 0xed, 0x4c, 0x52,
0xa4, 0x6b, 0xd6, 0x16, 0x50, 0xc1, 0xe9, 0xcd, 0x8e, 0x67, 0x3d, 0x2c, 0xa1, 0x79, 0x55, 0xdf, 0xb2, 0x63, 0x6d, 0x49, 0x4a, 0x6f, 0x87, 0x5b, 0x92, 0xca, 0x34, 0x3f, 0x7b, 0x07, 0x79, 0xd0,
0x4f, 0xe0, 0xc7, 0x96, 0x52, 0x3d, 0x6f, 0xf0, 0xff, 0xd8, 0xbf, 0xf8, 0x37, 0x00, 0x00, 0xff, 0x75, 0xe2, 0x40, 0xba, 0x66, 0x6d, 0x01, 0x15, 0x9c, 0xde, 0xec, 0x78, 0xd6, 0x83, 0x12, 0x9a,
0xff, 0xb6, 0x48, 0x98, 0x76, 0x9f, 0x10, 0x00, 0x00, 0xd7, 0xf5, 0xfd, 0x18, 0x7e, 0x6c, 0x29, 0xd5, 0x8b, 0x06, 0xff, 0x4f, 0xff, 0x8b, 0x7f, 0x03,
0x00, 0x00, 0xff, 0xff, 0x30, 0x18, 0x95, 0x9c, 0xd7, 0x10, 0x00, 0x00,
} }

@ -175,7 +175,7 @@ func verifyIndex(t *testing.T, actual *IndexFile) {
t.Errorf("Expected %q, got %q", e.Version, g.Version) t.Errorf("Expected %q, got %q", e.Version, g.Version)
} }
if len(g.Keywords) != 3 { if len(g.Keywords) != 3 {
t.Error("Expected 3 keyrwords.") t.Error("Expected 3 keywords.")
} }
if len(g.Maintainers) != 2 { if len(g.Maintainers) != 2 {
t.Error("Expected 2 maintainers.") t.Error("Expected 2 maintainers.")

@ -168,6 +168,15 @@ func (i IndexFile) Get(name, version string) (*ChartVersion, error) {
} }
} }
// when customer input exact version, check whether have exact match one first
if len(version) != 0 {
for _, ver := range vs {
if version == ver.Version {
return ver, nil
}
}
}
for _, ver := range vs { for _, ver := range vs {
test, err := semver.NewVersion(ver.Version) test, err := semver.NewVersion(ver.Version)
if err != nil { if err != nil {

@ -20,6 +20,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"testing" "testing"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
@ -39,14 +40,17 @@ func TestIndexFile(t *testing.T) {
i.Add(&chart.Metadata{Name: "cutter", Version: "0.1.1"}, "cutter-0.1.1.tgz", "http://example.com/charts", "sha256:1234567890abc") i.Add(&chart.Metadata{Name: "cutter", Version: "0.1.1"}, "cutter-0.1.1.tgz", "http://example.com/charts", "sha256:1234567890abc")
i.Add(&chart.Metadata{Name: "cutter", Version: "0.1.0"}, "cutter-0.1.0.tgz", "http://example.com/charts", "sha256:1234567890abc") i.Add(&chart.Metadata{Name: "cutter", Version: "0.1.0"}, "cutter-0.1.0.tgz", "http://example.com/charts", "sha256:1234567890abc")
i.Add(&chart.Metadata{Name: "cutter", Version: "0.2.0"}, "cutter-0.2.0.tgz", "http://example.com/charts", "sha256:1234567890abc") i.Add(&chart.Metadata{Name: "cutter", Version: "0.2.0"}, "cutter-0.2.0.tgz", "http://example.com/charts", "sha256:1234567890abc")
i.Add(&chart.Metadata{Name: "setter", Version: "0.1.9+alpha"}, "setter-0.1.9+alpha.tgz", "http://example.com/charts", "sha256:1234567890abc")
i.Add(&chart.Metadata{Name: "setter", Version: "0.1.9+beta"}, "setter-0.1.9+beta.tgz", "http://example.com/charts", "sha256:1234567890abc")
i.SortEntries() i.SortEntries()
if i.APIVersion != APIVersionV1 { if i.APIVersion != APIVersionV1 {
t.Error("Expected API version v1") t.Error("Expected API version v1")
} }
if len(i.Entries) != 2 { if len(i.Entries) != 3 {
t.Errorf("Expected 2 charts. Got %d", len(i.Entries)) t.Errorf("Expected 3 charts. Got %d", len(i.Entries))
} }
if i.Entries["clipper"][0].Name != "clipper" { if i.Entries["clipper"][0].Name != "clipper" {
@ -54,13 +58,23 @@ func TestIndexFile(t *testing.T) {
} }
if len(i.Entries["cutter"]) != 3 { if len(i.Entries["cutter"]) != 3 {
t.Error("Expected two cutters.") t.Error("Expected three cutters.")
} }
// Test that the sort worked. 0.2 should be at the first index for Cutter. // Test that the sort worked. 0.2 should be at the first index for Cutter.
if v := i.Entries["cutter"][0].Version; v != "0.2.0" { if v := i.Entries["cutter"][0].Version; v != "0.2.0" {
t.Errorf("Unexpected first version: %s", v) t.Errorf("Unexpected first version: %s", v)
} }
cv, err := i.Get("setter", "0.1.9")
if err == nil && strings.Index(cv.Metadata.Version, "0.1.9") < 0 {
t.Errorf("Unexpected version: %s", cv.Metadata.Version)
}
cv, err = i.Get("setter", "0.1.9+alpha")
if err != nil || cv.Metadata.Version != "0.1.9+alpha" {
t.Errorf("Expected version: 0.1.9+alpha")
}
} }
func TestLoadIndex(t *testing.T) { func TestLoadIndex(t *testing.T) {

@ -26,8 +26,8 @@ import (
"io" "io"
"time" "time"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/engine" "k8s.io/helm/pkg/engine"

@ -22,8 +22,8 @@ import (
"testing" "testing"
"time" "time"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"

@ -61,7 +61,7 @@ var (
// errInvalidRevision indicates that an invalid release revision number was provided. // errInvalidRevision indicates that an invalid release revision number was provided.
errInvalidRevision = errors.New("invalid release revision") errInvalidRevision = errors.New("invalid release revision")
//errInvalidName indicates that an invalid release name was provided //errInvalidName indicates that an invalid release name was provided
errInvalidName = errors.New("invalid release name, must match regex ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+$ and the length must not longer than 53") errInvalidName = errors.New("invalid release name, must match regex ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])+$ and the length must not be longer than 53")
) )
// ListDefaultLimit is the default limit for number of items returned in a list. // ListDefaultLimit is the default limit for number of items returned in a list.
@ -115,7 +115,7 @@ func NewReleaseServer(env *environment.Environment, clientset kubernetes.Interfa
// request values are not altered. // request values are not altered.
func (s *ReleaseServer) reuseValues(req *services.UpdateReleaseRequest, current *release.Release) error { func (s *ReleaseServer) reuseValues(req *services.UpdateReleaseRequest, current *release.Release) error {
if req.ResetValues { if req.ResetValues {
// If ResetValues is set, we comletely ignore current.Config. // If ResetValues is set, we completely ignore current.Config.
s.Log("resetting values to the chart's original version") s.Log("resetting values to the chart's original version")
return nil return nil
} }
@ -191,11 +191,11 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) {
rel := h[0] rel := h[0]
if st := rel.Info.Status.Code; reuse && (st == release.Status_DELETED || st == release.Status_FAILED) { if st := rel.Info.Status.Code; reuse && (st == release.Status_DELETED || st == release.Status_FAILED) {
// Allowe re-use of names if the previous release is marked deleted. // Allow re-use of names if the previous release is marked deleted.
s.Log("name %s exists but is not in use, reusing name", start) s.Log("name %s exists but is not in use, reusing name", start)
return start, nil return start, nil
} else if reuse { } else if reuse {
return "", fmt.Errorf("a released named %s is in use, cannot re-use a name that is still in use", start) return "", fmt.Errorf("a release named %s is in use, cannot re-use a name that is still in use", start)
} }
return "", fmt.Errorf("a release named %s already exists.\nRun: helm ls --all %s; to check the status of the release\nOr run: helm del --purge %s; to delete it", start, start, start) return "", fmt.Errorf("a release named %s already exists.\nRun: helm ls --all %s; to check the status of the release\nOr run: helm del --purge %s; to delete it", start, start, start)

@ -31,8 +31,8 @@ import (
"github.com/technosophos/moniker" "github.com/technosophos/moniker"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/cli-runtime/pkg/genericclioptions/resource" "k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
@ -89,13 +89,22 @@ spec:
var manifestWithKeep = `kind: ConfigMap var manifestWithKeep = `kind: ConfigMap
metadata: metadata:
name: test-cm-keep name: test-cm-keep-a
annotations: annotations:
"helm.sh/resource-policy": keep "helm.sh/resource-policy": keep
data: data:
name: value name: value
` `
var manifestWithKeepEmpty = `kind: ConfigMap
metadata:
name: test-cm-keep-b
annotations:
"helm.sh/resource-policy": ""
data:
name: value
`
var manifestWithUpgradeHooks = `kind: ConfigMap var manifestWithUpgradeHooks = `kind: ConfigMap
metadata: metadata:
name: test-cm name: test-cm
@ -449,23 +458,27 @@ func releaseWithKeepStub(rlsName string) *release.Release {
Name: "bunnychart", Name: "bunnychart",
}, },
Templates: []*chart.Template{ Templates: []*chart.Template{
{Name: "templates/configmap", Data: []byte(manifestWithKeep)}, {Name: "templates/configmap-keep-a", Data: []byte(manifestWithKeep)},
{Name: "templates/configmap-keep-b", Data: []byte(manifestWithKeepEmpty)},
}, },
} }
date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0} date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0}
return &release.Release{ rl := &release.Release{
Name: rlsName, Name: rlsName,
Info: &release.Info{ Info: &release.Info{
FirstDeployed: &date, FirstDeployed: &date,
LastDeployed: &date, LastDeployed: &date,
Status: &release.Status{Code: release.Status_DEPLOYED}, Status: &release.Status{Code: release.Status_DEPLOYED},
}, },
Chart: ch, Chart: ch,
Config: &chart.Config{Raw: `name: value`}, Config: &chart.Config{Raw: `name: value`},
Version: 1, Version: 1,
Manifest: manifestWithKeep,
} }
helm.RenderReleaseMock(rl, false)
return rl
} }
func MockEnvironment() *environment.Environment { func MockEnvironment() *environment.Environment {

@ -150,7 +150,10 @@ func TestUninstallReleaseWithKeepPolicy(t *testing.T) {
if res.Info == "" { if res.Info == "" {
t.Errorf("Expected response info to not be empty") t.Errorf("Expected response info to not be empty")
} else { } else {
if !strings.Contains(res.Info, "[ConfigMap] test-cm-keep") { if !strings.Contains(res.Info, "[ConfigMap] test-cm-keep-a") {
t.Errorf("unexpected output: %s", res.Info)
}
if !strings.Contains(res.Info, "[ConfigMap] test-cm-keep-b") {
t.Errorf("unexpected output: %s", res.Info) t.Errorf("unexpected output: %s", res.Info)
} }
} }

@ -604,7 +604,7 @@ func TestUpdateReleasePendingInstall_Force(t *testing.T) {
t.Error("Expected failed update") t.Error("Expected failed update")
} }
expectedError := "a released named forceful-luke is in use, cannot re-use a name that is still in use" expectedError := "a release named forceful-luke is in use, cannot re-use a name that is still in use"
got := err.Error() got := err.Error()
if err.Error() != expectedError { if err.Error() != expectedError {
t.Errorf("Expected error %q, got %q", expectedError, got) t.Errorf("Expected error %q, got %q", expectedError, got)

@ -34,17 +34,11 @@ func filterManifestsToKeep(manifests []Manifest) ([]Manifest, []Manifest) {
continue continue
} }
resourcePolicyType, ok := m.Head.Metadata.Annotations[kube.ResourcePolicyAnno] if kube.ResourcePolicyIsKeep(m.Head.Metadata.Annotations) {
if !ok {
remaining = append(remaining, m)
continue
}
resourcePolicyType = strings.ToLower(strings.TrimSpace(resourcePolicyType))
if resourcePolicyType == kube.KeepPolicy {
keep = append(keep, m) keep = append(keep, m)
} else {
remaining = append(remaining, m)
} }
} }
return keep, remaining return keep, remaining
} }

@ -40,7 +40,7 @@ type Options struct {
ClientAuth tls.ClientAuthType ClientAuth tls.ClientAuthType
} }
// ClientConfig retusn a TLS configuration for use by a Helm client. // ClientConfig returns a TLS configuration for use by a Helm client.
func ClientConfig(opts Options) (cfg *tls.Config, err error) { func ClientConfig(opts Options) (cfg *tls.Config, err error) {
var cert *tls.Certificate var cert *tls.Certificate
var pool *x509.CertPool var pool *x509.CertPool

@ -1,3 +1,5 @@
#!/usr/bin/env bash
# bash completion for helm -*- shell-script -*- # bash completion for helm -*- shell-script -*-
__debug() __debug()

@ -77,16 +77,16 @@ verifySupported() {
# checkDesiredVersion checks if the desired version is available. # checkDesiredVersion checks if the desired version is available.
checkDesiredVersion() { checkDesiredVersion() {
# Use the GitHub releases webpage for the project to find the desired version for this project. if [ "x$DESIRED_VERSION" == "x" ]; then
local release_url="https://github.com/helm/helm/releases/${DESIRED_VERSION:-latest}" # Get tag from release URL
if type "curl" > /dev/null; then local latest_release_url="https://github.com/helm/helm/releases/latest"
TAG=$(curl -SsL $release_url | awk '/\/tag\//' | grep -v no-underline | head -n 1 | cut -d '"' -f 2 | awk '{n=split($NF,a,"/");print a[n]}' | awk 'a !~ $0{print}; {a=$0}') if type "curl" > /dev/null; then
elif type "wget" > /dev/null; then TAG=$(curl -Ls -o /dev/null -w %{url_effective} $latest_release_url | grep -oE "[^/]+$" )
TAG=$(wget -q -O - $release_url | awk '/\/tag\//' | grep -v no-underline | head -n 1 | cut -d '"' -f 2 | awk '{n=split($NF,a,"/");print a[n]}' | awk 'a !~ $0{print}; {a=$0}') elif type "wget" > /dev/null; then
fi TAG=$(wget $latest_release_url --server-response -O /dev/null 2>&1 | awk '/^ Location: /{DEST=$2} END{ print DEST}' | grep -oE "[^/]+$")
if [ "x$TAG" == "x" ]; then fi
echo "Cannot determine ${DESIRED_VERSION} tag." else
exit 1 TAG=$DESIRED_VERSION
fi fi
} }

Loading…
Cancel
Save