From 7c55fdcf024e83d78b47102dd27315728400c860 Mon Sep 17 00:00:00 2001 From: Elad Iwanir Date: Tue, 8 Jan 2019 20:00:49 +0200 Subject: [PATCH 01/57] Sort resources output by 'helm status' Signed-off-by: Elad Iwanir --- pkg/kube/client.go | 81 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 19 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 4a387d524..513f7400d 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -24,6 +24,7 @@ import ( "fmt" "io" "log" + "sort" "strings" "time" @@ -151,13 +152,41 @@ func (c *Client) Build(namespace string, reader io.Reader) (Result, error) { return result, scrubValidationError(err) } +// Return the resource info as internal +func resourceInfoToObject(info *resource.Info) 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. // // Namespace will set the namespace. 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.). - objs := make(map[string][]runtime.Object) + objs := make(map[string](map[string]runtime.Object)) infos, err := c.BuildUnstructured(namespace, reader) if err != nil { return "", err @@ -178,19 +207,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. gvk := info.ResourceMapping().GroupVersionKind vk := gvk.Version + "/" + gvk.Kind - 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. - objs[vk] = append(objs[vk], info.Object) - } else { - objs[vk] = append(objs[vk], internalObj) + + // Initialize map. The main map groups resources based on version/kind + // The second level is a simple 'Name' to 'Object', that will help sort + // the individual resource later + if objs[vk] == nil { + objs[vk] = make(map[string]runtime.Object) } + // Map between the resource name to the underlying info object + objs[vk][info.Name] = resourceInfoToObject(info) //Get the relation pods objPods, err = c.getSelectRelationPod(info, objPods) @@ -208,8 +233,12 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { for key, podItems := range objPods { for i := range podItems { pod := &core.Pod{} + 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) } } @@ -219,14 +248,28 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { // track of tab widths. buf := new(bytes.Buffer) 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 { return "", err } typePrinter, _ := printFlags.ToPrinter("") - for _, o := range ot { - if err := typePrinter.PrintObj(o, buf); err != nil { - c.Log("failed to print object type %s, object: %q :\n %v", t, o, err) + + var sortedResources []string + 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 + for _, resourceName := range sortedResources { + vk := objs[t] + 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 } } From cbf9ad11be1153d72cade3212d708112af97eefe Mon Sep 17 00:00:00 2001 From: Elad Iwanir Date: Tue, 8 Jan 2019 20:14:39 +0200 Subject: [PATCH 02/57] fix minor build issue Signed-off-by: Elad Iwanir --- pkg/kube/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 513f7400d..9aa821b5a 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -153,7 +153,7 @@ func (c *Client) Build(namespace string, reader io.Reader) (Result, error) { } // Return the resource info as internal -func resourceInfoToObject(info *resource.Info) runtime.Object { +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 @@ -215,7 +215,7 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { objs[vk] = make(map[string]runtime.Object) } // Map between the resource name to the underlying info object - objs[vk][info.Name] = resourceInfoToObject(info) + objs[vk][info.Name] = resourceInfoToObject(info, c) //Get the relation pods objPods, err = c.getSelectRelationPod(info, objPods) From a1ea9678be1442fc04883cc4b2c8bab526f72a9c Mon Sep 17 00:00:00 2001 From: Ian Howell Date: Wed, 6 Feb 2019 15:51:11 -0600 Subject: [PATCH 03/57] Add unit tests for checking sort order on helm get Signed-off-by: Ian Howell --- pkg/kube/client.go | 2 +- pkg/kube/client_test.go | 131 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 9aa821b5a..c5f3bf77f 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -266,8 +266,8 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { // 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 { - vk := objs[t] 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 diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index de33881c8..81356540e 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -21,6 +21,7 @@ import ( "io" "io/ioutil" "net/http" + "sort" "strings" "testing" @@ -77,6 +78,18 @@ func newPodList(names ...string) v1.PodList { 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 { return &metav1.Status{ Code: http.StatusNotFound, @@ -280,6 +293,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) { tests := []struct { name string @@ -361,6 +463,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: beluga +--- +kind: Pod +apiVersion: v1 +metadata: + name: coral +` + const testServiceManifest = ` kind: Service apiVersion: v1 From 2734066bcccb67e2021e28c90f595ed25259f0bb Mon Sep 17 00:00:00 2001 From: Elad Iwanir Date: Thu, 7 Feb 2019 22:56:38 +0200 Subject: [PATCH 04/57] changing return order of test items so the sorting tests will fail if actually broken Signed-off-by: Elad Iwanir --- pkg/kube/client_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 81356540e..9c60f57e3 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -484,12 +484,12 @@ metadata: kind: Pod apiVersion: v1 metadata: - name: beluga + name: coral --- kind: Pod apiVersion: v1 metadata: - name: coral + name: beluga ` const testServiceManifest = ` From 5767f13aaa5bfb513747b73f3c5d8cd4b0640684 Mon Sep 17 00:00:00 2001 From: xichengliudui <1693291525@qq.com> Date: Sun, 10 Feb 2019 23:57:53 -0500 Subject: [PATCH 05/57] Fix function comment to consistent with its name Signed-off-by: xichengliudui <1693291525@qq.com> --- pkg/chartutil/capabilities.go | 2 +- pkg/chartutil/requirements.go | 2 +- pkg/downloader/chart_downloader.go | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/chartutil/capabilities.go b/pkg/chartutil/capabilities.go index d7e660b8a..b4533e417 100644 --- a/pkg/chartutil/capabilities.go +++ b/pkg/chartutil/capabilities.go @@ -40,7 +40,7 @@ var ( // Capabilities describes the capabilities of the Kubernetes cluster that Tiller is attached to. type Capabilities struct { - // List of all supported API versions + // APIVersions list of all supported API versions APIVersions VersionSet // KubeVersion is the Kubernetes version KubeVersion *version.Info diff --git a/pkg/chartutil/requirements.go b/pkg/chartutil/requirements.go index 0f1128305..f21a22005 100644 --- a/pkg/chartutil/requirements.go +++ b/pkg/chartutil/requirements.go @@ -85,7 +85,7 @@ type Requirements struct { // // It represents the state that the dependencies should be in. 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"` // Digest is a hash of the requirements file used to generate it. Digest string `json:"digest"` diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index 5e6287299..453e81470 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -65,11 +65,11 @@ type ChartDownloader struct { Keyring string // HelmHome is the $HELM_HOME. HelmHome helmpath.Home - // Getter collection for the operation + // Getters collection for the operation Getters getter.Providers - // Chart repository username + // Username chart repository username Username string - // Chart repository password + // Password chart repository password Password string } @@ -243,14 +243,14 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge 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) { if t, ok := r.Client.(*getter.HttpGetter); ok { 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. // Else, this ChartDownloader's credentials are returned. func (c *ChartDownloader) getRepoCredentials(r *repo.ChartRepository) (username, password string) { From 9fb9850aca4afab0d38bcd73218098a145b4e7ac Mon Sep 17 00:00:00 2001 From: lIuDuI <1693291525@qq.com> Date: Tue, 12 Feb 2019 22:26:24 +0800 Subject: [PATCH 06/57] Fix function comment to consistent with its name (#5294) Signed-off-by: xichengliudui <1693291525@qq.com> --- pkg/downloader/manager.go | 2 +- pkg/engine/engine.go | 2 +- pkg/helm/client.go | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index aea48bd7e..372940880 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -604,7 +604,7 @@ func writeLock(chartpath string, lock *chartutil.RequirementsLock) error { 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) { destPath := filepath.Join(chartpath, "charts") diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index f3dd869c9..9a155de2e 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -130,7 +130,7 @@ type renderable struct { tpl string // vals are the values to be supplied to the template. vals chartutil.Values - // namespace prefix to the templates of the current chart + // basePath namespace prefix to the templates of the current chart basePath string } diff --git a/pkg/helm/client.go b/pkg/helm/client.go index 0d4d16039..fa867c2d3 100644 --- a/pkg/helm/client.go +++ b/pkg/helm/client.go @@ -334,7 +334,7 @@ func (h *Client) connect(ctx context.Context) (conn *grpc.ClientConn, err error) 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) { c, err := h.connect(ctx) if err != nil { @@ -365,7 +365,7 @@ func (h *Client) list(ctx context.Context, req *rls.ListReleasesRequest) (*rls.L 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) { c, err := h.connect(ctx) if err != nil { @@ -377,7 +377,7 @@ func (h *Client) install(ctx context.Context, req *rls.InstallReleaseRequest) (* 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) { c, err := h.connect(ctx) if err != nil { @@ -389,7 +389,7 @@ func (h *Client) delete(ctx context.Context, req *rls.UninstallReleaseRequest) ( 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) { c, err := h.connect(ctx) if err != nil { @@ -401,7 +401,7 @@ func (h *Client) update(ctx context.Context, req *rls.UpdateReleaseRequest) (*rl 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) { c, err := h.connect(ctx) if err != nil { @@ -413,7 +413,7 @@ func (h *Client) rollback(ctx context.Context, req *rls.RollbackReleaseRequest) 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) { c, err := h.connect(ctx) if err != nil { @@ -425,7 +425,7 @@ func (h *Client) status(ctx context.Context, req *rls.GetReleaseStatusRequest) ( 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) { c, err := h.connect(ctx) if err != nil { @@ -437,7 +437,7 @@ func (h *Client) content(ctx context.Context, req *rls.GetReleaseContentRequest) 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) { c, err := h.connect(ctx) if err != nil { @@ -449,7 +449,7 @@ func (h *Client) version(ctx context.Context, req *rls.GetVersionRequest) (*rls. 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) { c, err := h.connect(ctx) if err != nil { @@ -461,7 +461,7 @@ func (h *Client) history(ctx context.Context, req *rls.GetHistoryRequest) (*rls. 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) { errc := make(chan error, 1) c, err := h.connect(ctx) @@ -499,7 +499,7 @@ func (h *Client) test(ctx context.Context, req *rls.TestReleaseRequest) (<-chan return ch, errc } -// Executes tiller.Ping RPC. +// ping executes tiller.Ping RPC. func (h *Client) ping(ctx context.Context) error { c, err := h.connect(ctx) if err != nil { From 70c509e77ee2acecc722c429bc78415b2c660616 Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Tue, 12 Feb 2019 08:42:58 -0700 Subject: [PATCH 07/57] fix: Update gRPC to get better TLS connection handling (v2 minor release) (#5210) * fix: Update gRPC to get better TLS connection handling To avoid backward compatibility breakers, we have been pinned to a very old version of gRPC. But it appears that there have been some very significant network fixes since then. Looking closely at #3480, it appears that some of this fixes may be directly related to solving that bug. Note that this regenerates a few of the Go proto files, so the binary wire format may be broken. That means this MUST be held to a minor version, not a patch release. To test: - Build both client and server - Install Tiller into your cluster - Perform a number of Helm-Tiller interactions (`helm version`, `helm list`) Closes #3480 Signed-off-by: Matt Butcher * Switched to latest protobuf Signed-off-by: Matt Butcher --- glide.lock | 34 +++-- glide.yaml | 10 +- pkg/proto/hapi/services/tiller.pb.go | 195 ++++++++++++++------------- 3 files changed, 130 insertions(+), 109 deletions(-) diff --git a/glide.lock b/glide.lock index 105dada1f..1fa7c3d95 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 2af9a5c4f891a0f44109a929a494b5aeaaffa3a87cd1f3881f25f79845703d5b -updated: 2018-12-14T21:39:31.112097Z +hash: 5dc21cc57b38ab1076f9e12d1e4248047ccc4470af8f81c8560560cb492bee9e +updated: 2019-02-08T15:20:12.179155-07:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -122,7 +122,7 @@ imports: subpackages: - lru - name: github.com/golang/protobuf - version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 + version: aa810b61a9c79d51363740d207bb46cf8e620ed5 subpackages: - proto - ptypes @@ -166,7 +166,7 @@ imports: subpackages: - simplelru - name: github.com/huandu/xstrings - version: 3959339b333561bf62a38b424fd41517c2c90f40 + version: f02667b379e2fb5916c3cda2cf31e0eb885d79f8 - name: github.com/imdario/mergo version: 9316a62528ac99aaecb4e47eadd6dc8aa6533d58 - name: github.com/inconshreveable/mousetrap @@ -184,7 +184,7 @@ imports: - name: github.com/Masterminds/semver version: 517734cc7d6470c0d07130e40fd40bdeb9bcd3fd - name: github.com/Masterminds/sprig - version: 15f9564e7e9cf0da02a48e0d25f12a7b83559aa6 + version: 544a9b1d90f323f6509491b389714fbbd126bee3 - name: github.com/Masterminds/vcs version: 3084677c2c188840777bff30054f2b553729d329 - name: github.com/mattn/go-runewidth @@ -281,7 +281,7 @@ imports: subpackages: - semaphore - name: golang.org/x/sys - version: 95c6576299259db960f6c5b9b69ea52422860fce + version: b90733256f2e882e81d52f9126de08df5615afd9 subpackages: - unix - windows @@ -325,26 +325,40 @@ imports: subpackages: - googleapis/rpc/status - name: google.golang.org/grpc - version: 5ffe3083946d5603a0578721101dc8165b1d5b5f + version: a02b0774206b209466313a0b525d2c738fe407eb subpackages: - balancer + - balancer/base + - balancer/roundrobin + - binarylog/grpc_binarylog_v1 - codes - connectivity - credentials - - grpclb/grpc_lb_v1/messages + - credentials/internal + - encoding + - encoding/proto - grpclog - health - health/grpc_health_v1 - internal + - internal/backoff + - internal/binarylog + - internal/channelz + - internal/envconfig + - internal/grpcrand + - internal/grpcsync + - internal/syscall + - internal/transport - keepalive - metadata - naming - peer - resolver + - resolver/dns + - resolver/passthrough - stats - status - tap - - transport - name: gopkg.in/inf.v0 version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 - name: gopkg.in/square/go-jose.v2 @@ -597,7 +611,7 @@ imports: - pkg/util/proto/testing - pkg/util/proto/validation - name: k8s.io/kubernetes - version: f2c8f1cadf1808ec28476682e49a3cce2b09efbf + version: c6d339953bd4fd8c021a6b5fb46d7952b30be9f9 subpackages: - pkg/api/legacyscheme - pkg/api/service diff --git a/glide.yaml b/glide.yaml index bf81b22ee..42c10b347 100644 --- a/glide.yaml +++ b/glide.yaml @@ -6,6 +6,12 @@ import: - package: golang.org/x/sync subpackages: - 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 version: fe5e611709b0c57fa4a89136deaa8e1d4004d053 - package: github.com/spf13/pflag @@ -22,13 +28,13 @@ import: - package: github.com/technosophos/moniker version: ~0.2 - package: github.com/golang/protobuf - version: 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 + version: 1.2.0 subpackages: - proto - ptypes/any - ptypes/timestamp - package: google.golang.org/grpc - version: 1.7.2 + version: 1.18.0 - package: github.com/gosuri/uitable - package: github.com/asaskevich/govalidator version: ^4.0.0 diff --git a/pkg/proto/hapi/services/tiller.pb.go b/pkg/proto/hapi/services/tiller.pb.go index 8708d0a18..ce76cad12 100644 --- a/pkg/proto/hapi/services/tiller.pb.go +++ b/pkg/proto/hapi/services/tiller.pb.go @@ -467,18 +467,18 @@ func (m *UpdateReleaseRequest) GetForce() bool { return false } -func (m *UpdateReleaseRequest) GetSubNotes() bool { +func (m *UpdateReleaseRequest) GetDescription() string { 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 { - return m.Description + return m.SubNotes } - return "" + return false } // UpdateReleaseResponse is the response to an update request. @@ -711,18 +711,18 @@ func (m *InstallReleaseRequest) GetDisableCrdHook() bool { return false } -func (m *InstallReleaseRequest) GetSubNotes() bool { +func (m *InstallReleaseRequest) GetDescription() string { 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 { - return m.Description + return m.SubNotes } - return "" + return false } // 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"` // timeout specifies the max amount of time any kubernetes client command can run. 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"` } @@ -1018,7 +1018,7 @@ type ReleaseServiceClient interface { GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) // RollbackRelease rolls back a release to a previous version. 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) // RunReleaseTest executes the tests defined of a named release 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) // RollbackRelease rolls back a release to a previous version. RollbackRelease(context.Context, *RollbackReleaseRequest) (*RollbackReleaseResponse, error) - // ReleaseHistory retrieves a releasse's history. + // ReleaseHistory retrieves a release's history. GetHistory(context.Context, *GetHistoryRequest) (*GetHistoryResponse, error) // RunReleaseTest executes the tests defined of a named release RunReleaseTest(*TestReleaseRequest, ReleaseService_RunReleaseTestServer) error @@ -1441,86 +1441,87 @@ var _ReleaseService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("hapi/services/tiller.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1289 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xed, 0x72, 0xdb, 0x44, - 0x17, 0x8e, 0x2d, 0x7f, 0x1e, 0xa7, 0x7e, 0xdd, 0x6d, 0x9a, 0xa8, 0x7a, 0x0b, 0x63, 0xc4, 0x40, - 0xdd, 0x42, 0x1d, 0x30, 0xfc, 0x61, 0x86, 0x61, 0x26, 0x75, 0x3d, 0x49, 0x21, 0xa4, 0x33, 0x72, - 0x5b, 0x66, 0x98, 0x61, 0x3c, 0x8a, 0xbd, 0x6e, 0x45, 0x65, 0xc9, 0x68, 0x57, 0xa1, 0xb9, 0x00, - 0x98, 0xe1, 0x3e, 0xb8, 0x10, 0xee, 0x83, 0xeb, 0xe0, 0x3f, 0xb3, 0x5f, 0x8a, 0x56, 0x96, 0x1c, - 0x91, 0x3f, 0xb1, 0x76, 0xcf, 0xd9, 0xf3, 0xf1, 0x3c, 0x7b, 0xce, 0x9e, 0x80, 0xf5, 0xc6, 0x5d, - 0x7b, 0x87, 0x04, 0x47, 0x17, 0xde, 0x1c, 0x93, 0x43, 0xea, 0xf9, 0x3e, 0x8e, 0x86, 0xeb, 0x28, - 0xa4, 0x21, 0xda, 0x63, 0xb2, 0xa1, 0x92, 0x0d, 0x85, 0xcc, 0xda, 0xe7, 0x27, 0xe6, 0x6f, 0xdc, - 0x88, 0x8a, 0xbf, 0x42, 0xdb, 0x3a, 0x48, 0xef, 0x87, 0xc1, 0xd2, 0x7b, 0x2d, 0x05, 0xc2, 0x45, - 0x84, 0x7d, 0xec, 0x12, 0xac, 0x7e, 0xb5, 0x43, 0x4a, 0xe6, 0x05, 0xcb, 0x50, 0x0a, 0xfe, 0xaf, - 0x09, 0x28, 0x26, 0x74, 0x16, 0xc5, 0x81, 0x14, 0xde, 0xd3, 0x84, 0x84, 0xba, 0x34, 0x26, 0x9a, - 0xb3, 0x0b, 0x1c, 0x11, 0x2f, 0x0c, 0xd4, 0xaf, 0x90, 0xd9, 0x7f, 0x55, 0xe1, 0xce, 0xa9, 0x47, - 0xa8, 0x23, 0x0e, 0x12, 0x07, 0xff, 0x12, 0x63, 0x42, 0xd1, 0x1e, 0xd4, 0x7d, 0x6f, 0xe5, 0x51, - 0xb3, 0xd2, 0xaf, 0x0c, 0x0c, 0x47, 0x2c, 0xd0, 0x3e, 0x34, 0xc2, 0xe5, 0x92, 0x60, 0x6a, 0x56, - 0xfb, 0x95, 0x41, 0xdb, 0x91, 0x2b, 0xf4, 0x0d, 0x34, 0x49, 0x18, 0xd1, 0xd9, 0xf9, 0xa5, 0x69, - 0xf4, 0x2b, 0x83, 0xee, 0xe8, 0xa3, 0x61, 0x1e, 0x4e, 0x43, 0xe6, 0x69, 0x1a, 0x46, 0x74, 0xc8, - 0xfe, 0x3c, 0xb9, 0x74, 0x1a, 0x84, 0xff, 0x32, 0xbb, 0x4b, 0xcf, 0xa7, 0x38, 0x32, 0x6b, 0xc2, - 0xae, 0x58, 0xa1, 0x63, 0x00, 0x6e, 0x37, 0x8c, 0x16, 0x38, 0x32, 0xeb, 0xdc, 0xf4, 0xa0, 0x84, - 0xe9, 0xe7, 0x4c, 0xdf, 0x69, 0x13, 0xf5, 0x89, 0xbe, 0x86, 0x5d, 0x01, 0xc9, 0x6c, 0x1e, 0x2e, - 0x30, 0x31, 0x1b, 0x7d, 0x63, 0xd0, 0x1d, 0xdd, 0x13, 0xa6, 0x14, 0xfc, 0x53, 0x01, 0xda, 0x38, - 0x5c, 0x60, 0xa7, 0x23, 0xd4, 0xd9, 0x37, 0x41, 0xf7, 0xa1, 0x1d, 0xb8, 0x2b, 0x4c, 0xd6, 0xee, - 0x1c, 0x9b, 0x4d, 0x1e, 0xe1, 0xd5, 0x86, 0x1d, 0x40, 0x4b, 0x39, 0xb7, 0x9f, 0x40, 0x43, 0xa4, - 0x86, 0x3a, 0xd0, 0x7c, 0x79, 0xf6, 0xdd, 0xd9, 0xf3, 0x1f, 0xce, 0x7a, 0x3b, 0xa8, 0x05, 0xb5, - 0xb3, 0xa3, 0xef, 0x27, 0xbd, 0x0a, 0xba, 0x0d, 0xb7, 0x4e, 0x8f, 0xa6, 0x2f, 0x66, 0xce, 0xe4, - 0x74, 0x72, 0x34, 0x9d, 0x3c, 0xed, 0x55, 0x51, 0x17, 0x60, 0x7c, 0x72, 0xe4, 0xbc, 0x98, 0x71, - 0x15, 0xc3, 0x7e, 0x1f, 0xda, 0x49, 0x0e, 0xa8, 0x09, 0xc6, 0xd1, 0x74, 0x2c, 0x4c, 0x3c, 0x9d, - 0x4c, 0xc7, 0xbd, 0x8a, 0xfd, 0x47, 0x05, 0xf6, 0x74, 0xca, 0xc8, 0x3a, 0x0c, 0x08, 0x66, 0x9c, - 0xcd, 0xc3, 0x38, 0x48, 0x38, 0xe3, 0x0b, 0x84, 0xa0, 0x16, 0xe0, 0x77, 0x8a, 0x31, 0xfe, 0xcd, - 0x34, 0x69, 0x48, 0x5d, 0x9f, 0xb3, 0x65, 0x38, 0x62, 0x81, 0x3e, 0x87, 0x96, 0x84, 0x82, 0x98, - 0xb5, 0xbe, 0x31, 0xe8, 0x8c, 0xee, 0xea, 0x00, 0x49, 0x8f, 0x4e, 0xa2, 0x66, 0x1f, 0xc3, 0xc1, - 0x31, 0x56, 0x91, 0x08, 0xfc, 0xd4, 0x0d, 0x62, 0x7e, 0xdd, 0x15, 0xe6, 0xc1, 0x30, 0xbf, 0xee, - 0x0a, 0x23, 0x13, 0x9a, 0xf2, 0xfa, 0xf1, 0x70, 0xea, 0x8e, 0x5a, 0xda, 0x14, 0xcc, 0x4d, 0x43, - 0x32, 0xaf, 0x3c, 0x4b, 0x1f, 0x43, 0x8d, 0x55, 0x06, 0x37, 0xd3, 0x19, 0x21, 0x3d, 0xce, 0x67, - 0xc1, 0x32, 0x74, 0xb8, 0x5c, 0xa7, 0xce, 0xc8, 0x52, 0x77, 0x92, 0xf6, 0x3a, 0x0e, 0x03, 0x8a, - 0x03, 0x7a, 0xb3, 0xf8, 0x4f, 0xe1, 0x5e, 0x8e, 0x25, 0x99, 0xc0, 0x21, 0x34, 0x65, 0x68, 0xdc, - 0x5a, 0x21, 0xae, 0x4a, 0xcb, 0xfe, 0xcd, 0x80, 0xbd, 0x97, 0xeb, 0x85, 0x4b, 0xb1, 0x12, 0x6d, - 0x09, 0xea, 0x01, 0xd4, 0x79, 0x87, 0x91, 0x58, 0xdc, 0x16, 0xb6, 0x45, 0x1b, 0x1a, 0xb3, 0xbf, - 0x8e, 0x90, 0xa3, 0x47, 0xd0, 0xb8, 0x70, 0xfd, 0x18, 0x13, 0x0e, 0x44, 0x82, 0x9a, 0xd4, 0xe4, - 0xed, 0xc9, 0x91, 0x1a, 0xe8, 0x00, 0x9a, 0x8b, 0xe8, 0x92, 0xf5, 0x17, 0x5e, 0x92, 0x2d, 0xa7, - 0xb1, 0x88, 0x2e, 0x9d, 0x38, 0x40, 0x1f, 0xc2, 0xad, 0x85, 0x47, 0xdc, 0x73, 0x1f, 0xcf, 0xde, - 0x84, 0xe1, 0x5b, 0xc2, 0xab, 0xb2, 0xe5, 0xec, 0xca, 0xcd, 0x13, 0xb6, 0x87, 0x2c, 0x76, 0x93, - 0xe6, 0x11, 0x76, 0x29, 0x36, 0x1b, 0x5c, 0x9e, 0xac, 0x19, 0x86, 0xd4, 0x5b, 0xe1, 0x30, 0xa6, - 0xbc, 0x94, 0x0c, 0x47, 0x2d, 0xd1, 0x07, 0xb0, 0x1b, 0x61, 0x82, 0xe9, 0x4c, 0x46, 0xd9, 0xe2, - 0x27, 0x3b, 0x7c, 0xef, 0x95, 0x08, 0x0b, 0x41, 0xed, 0x57, 0xd7, 0xa3, 0x66, 0x9b, 0x8b, 0xf8, - 0xb7, 0x38, 0x16, 0x13, 0xac, 0x8e, 0x81, 0x3a, 0x16, 0x13, 0x2c, 0x8f, 0xed, 0x41, 0x7d, 0x19, - 0x46, 0x73, 0x6c, 0x76, 0xb8, 0x4c, 0x2c, 0x50, 0x1f, 0x3a, 0x0b, 0x4c, 0xe6, 0x91, 0xb7, 0xa6, - 0x8c, 0xd1, 0x5d, 0x8e, 0x69, 0x7a, 0xcb, 0x3e, 0x81, 0xbb, 0x19, 0x1a, 0x6e, 0xca, 0xe8, 0xef, - 0x55, 0xd8, 0x77, 0x42, 0xdf, 0x3f, 0x77, 0xe7, 0x6f, 0x4b, 0x70, 0x9a, 0x82, 0xbf, 0xba, 0x1d, - 0x7e, 0x23, 0x07, 0xfe, 0xd4, 0x35, 0xad, 0x69, 0xd7, 0x54, 0x23, 0xa6, 0x5e, 0x4c, 0x4c, 0x43, - 0x27, 0x46, 0xa1, 0xde, 0x4c, 0xa1, 0x9e, 0x40, 0xda, 0xda, 0x02, 0x69, 0x7b, 0x13, 0xd2, 0x6f, - 0xe1, 0x60, 0x03, 0x87, 0x9b, 0x82, 0xfa, 0x4f, 0x15, 0xee, 0x3e, 0x0b, 0x08, 0x75, 0x7d, 0x3f, - 0x83, 0x69, 0x52, 0x13, 0x95, 0xd2, 0x35, 0x51, 0xfd, 0x2f, 0x35, 0x61, 0x68, 0xa4, 0x28, 0x06, - 0x6b, 0x29, 0x06, 0x4b, 0xd5, 0x89, 0xd6, 0x9d, 0x1a, 0x99, 0xee, 0x84, 0xde, 0x03, 0x10, 0x17, - 0x9b, 0x1b, 0x17, 0xe0, 0xb7, 0xf9, 0xce, 0x99, 0x6c, 0x46, 0x8a, 0xaf, 0x56, 0x3e, 0x5f, 0xe9, - 0x2a, 0x19, 0x40, 0x4f, 0xc5, 0x33, 0x8f, 0x16, 0x3c, 0x26, 0x59, 0x29, 0x5d, 0xb9, 0x3f, 0x8e, - 0x16, 0x2c, 0xaa, 0x2c, 0x87, 0x9d, 0x4d, 0x0e, 0x9f, 0xc1, 0x7e, 0x16, 0xf6, 0x9b, 0x52, 0xf8, - 0x67, 0x05, 0x0e, 0x5e, 0x06, 0x5e, 0x2e, 0x89, 0x79, 0x85, 0xb1, 0x01, 0x6b, 0x35, 0x07, 0xd6, - 0x3d, 0xa8, 0xaf, 0xe3, 0xe8, 0x35, 0x96, 0x34, 0x89, 0x45, 0x1a, 0xaf, 0x9a, 0x8e, 0x57, 0x26, - 0xe3, 0xfa, 0x66, 0xc6, 0x33, 0x30, 0x37, 0xa3, 0xbc, 0x61, 0xce, 0x2c, 0xaf, 0xe4, 0xed, 0x6a, - 0x8b, 0x77, 0xca, 0xbe, 0x03, 0xb7, 0x8f, 0x31, 0x7d, 0x25, 0xca, 0x54, 0x02, 0x60, 0x4f, 0x00, - 0xa5, 0x37, 0xaf, 0xfc, 0xc9, 0x2d, 0xdd, 0x9f, 0x1a, 0xec, 0x94, 0xbe, 0xd2, 0xb2, 0xbf, 0xe2, - 0xb6, 0x4f, 0x3c, 0x42, 0xc3, 0xe8, 0x72, 0x1b, 0xb8, 0x3d, 0x30, 0x56, 0xee, 0x3b, 0xf9, 0xb4, - 0xb1, 0x4f, 0xfb, 0x98, 0x47, 0x90, 0x1c, 0x95, 0x11, 0xa4, 0x07, 0x85, 0x4a, 0xb9, 0x41, 0xe1, - 0x1d, 0xa0, 0x17, 0x38, 0x99, 0x59, 0xae, 0x79, 0x63, 0x15, 0x4d, 0x55, 0x9d, 0x26, 0x13, 0x9a, - 0x73, 0x1f, 0xbb, 0x41, 0xbc, 0x96, 0xc4, 0xaa, 0x25, 0x6b, 0x6b, 0x6b, 0x37, 0x72, 0x7d, 0x1f, - 0xfb, 0xf2, 0xb9, 0x4a, 0xd6, 0xf6, 0x4f, 0x70, 0x47, 0xf3, 0x2c, 0x73, 0x60, 0xb9, 0x92, 0xd7, - 0xd2, 0x33, 0xfb, 0x44, 0x5f, 0x42, 0x43, 0x0c, 0x7d, 0xdc, 0x6f, 0x77, 0x74, 0x5f, 0xcf, 0x89, - 0x1b, 0x89, 0x03, 0x39, 0x25, 0x3a, 0x52, 0x77, 0xf4, 0x77, 0x0b, 0xba, 0x6a, 0x6c, 0x11, 0x23, - 0x29, 0xf2, 0x60, 0x37, 0x3d, 0x9f, 0xa1, 0x87, 0xc5, 0x13, 0x6b, 0x66, 0xec, 0xb6, 0x1e, 0x95, - 0x51, 0x15, 0x19, 0xd8, 0x3b, 0x9f, 0x55, 0x10, 0x81, 0x5e, 0x76, 0x6c, 0x42, 0x8f, 0xf3, 0x6d, - 0x14, 0xcc, 0x69, 0xd6, 0xb0, 0xac, 0xba, 0x72, 0x8b, 0x2e, 0xf8, 0x7d, 0xd2, 0x67, 0x1d, 0x74, - 0xad, 0x19, 0x7d, 0xbc, 0xb2, 0x0e, 0x4b, 0xeb, 0x27, 0x7e, 0x7f, 0x86, 0x5b, 0xda, 0x6b, 0x8c, - 0x0a, 0xd0, 0xca, 0x9b, 0x9c, 0xac, 0x4f, 0x4a, 0xe9, 0x26, 0xbe, 0x56, 0xd0, 0xd5, 0x5b, 0x1c, - 0x2a, 0x30, 0x90, 0xfb, 0xfe, 0x58, 0x9f, 0x96, 0x53, 0x4e, 0xdc, 0x11, 0xe8, 0x65, 0xfb, 0x4b, - 0x11, 0x8f, 0x05, 0xdd, 0xb2, 0x88, 0xc7, 0xa2, 0xb6, 0x65, 0xef, 0x20, 0x17, 0xe0, 0xaa, 0xbd, - 0xa0, 0x07, 0x85, 0x84, 0xe8, 0x5d, 0xc9, 0x1a, 0x5c, 0xaf, 0x98, 0xb8, 0x58, 0xc3, 0xff, 0x32, - 0xaf, 0x3d, 0x2a, 0x80, 0x26, 0x7f, 0x38, 0xb2, 0x1e, 0x97, 0xd4, 0xce, 0x24, 0x25, 0x3b, 0xd6, - 0x96, 0xa4, 0xf4, 0x76, 0xb8, 0x25, 0xa9, 0x4c, 0xf3, 0xb3, 0x77, 0x90, 0x07, 0x5d, 0x27, 0x0e, - 0xa4, 0x6b, 0xd6, 0x16, 0x50, 0xc1, 0xe9, 0xcd, 0x8e, 0x67, 0x3d, 0x2c, 0xa1, 0x79, 0x55, 0xdf, - 0x4f, 0xe0, 0xc7, 0x96, 0x52, 0x3d, 0x6f, 0xf0, 0xff, 0xd8, 0xbf, 0xf8, 0x37, 0x00, 0x00, 0xff, - 0xff, 0xb6, 0x48, 0x98, 0x76, 0x9f, 0x10, 0x00, 0x00, + // 1308 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x57, 0xed, 0x6e, 0x1b, 0x45, + 0x17, 0x8e, 0xbd, 0xfe, 0x3c, 0x4e, 0xfc, 0xba, 0xd3, 0x34, 0xd9, 0xee, 0x5b, 0x50, 0x58, 0x04, + 0x75, 0x0b, 0x75, 0xc0, 0xf0, 0x07, 0x09, 0x21, 0xa5, 0xae, 0x95, 0x14, 0x82, 0x2b, 0xad, 0xdb, + 0x22, 0x21, 0x21, 0x6b, 0x63, 0x8f, 0xdb, 0xa5, 0xeb, 0x5d, 0xb3, 0x33, 0x1b, 0x9a, 0x1b, 0x40, + 0xe2, 0x27, 0x97, 0x80, 0xc4, 0x85, 0x70, 0x1f, 0xdc, 0x0c, 0x9a, 0xaf, 0xcd, 0xce, 0x7a, 0xd7, + 0x5d, 0xf2, 0x27, 0xde, 0x99, 0x73, 0xe6, 0x7c, 0x3c, 0xcf, 0x9c, 0x33, 0x27, 0x60, 0xbd, 0x76, + 0xd7, 0xde, 0x31, 0xc1, 0xd1, 0xa5, 0x37, 0xc7, 0xe4, 0x98, 0x7a, 0xbe, 0x8f, 0xa3, 0xc1, 0x3a, + 0x0a, 0x69, 0x88, 0xf6, 0x99, 0x6c, 0xa0, 0x64, 0x03, 0x21, 0xb3, 0x0e, 0xf8, 0x89, 0xf9, 0x6b, + 0x37, 0xa2, 0xe2, 0xaf, 0xd0, 0xb6, 0x0e, 0xd3, 0xfb, 0x61, 0xb0, 0xf4, 0x5e, 0x49, 0x81, 0x70, + 0x11, 0x61, 0x1f, 0xbb, 0x04, 0xab, 0x5f, 0xed, 0x90, 0x92, 0x79, 0xc1, 0x32, 0x94, 0x82, 0xff, + 0x6b, 0x02, 0x8a, 0x09, 0x9d, 0x45, 0x71, 0x20, 0x85, 0x77, 0x35, 0x21, 0xa1, 0x2e, 0x8d, 0x89, + 0xe6, 0xec, 0x12, 0x47, 0xc4, 0x0b, 0x03, 0xf5, 0x2b, 0x64, 0xf6, 0xdf, 0x55, 0xb8, 0x7d, 0xee, + 0x11, 0xea, 0x88, 0x83, 0xc4, 0xc1, 0xbf, 0xc4, 0x98, 0x50, 0xb4, 0x0f, 0x75, 0xdf, 0x5b, 0x79, + 0xd4, 0xac, 0x1c, 0x55, 0xfa, 0x86, 0x23, 0x16, 0xe8, 0x00, 0x1a, 0xe1, 0x72, 0x49, 0x30, 0x35, + 0xab, 0x47, 0x95, 0x7e, 0xdb, 0x91, 0x2b, 0xf4, 0x0d, 0x34, 0x49, 0x18, 0xd1, 0xd9, 0xc5, 0x95, + 0x69, 0x1c, 0x55, 0xfa, 0xdd, 0xe1, 0x47, 0x83, 0x3c, 0x9c, 0x06, 0xcc, 0xd3, 0x34, 0x8c, 0xe8, + 0x80, 0xfd, 0x79, 0x7c, 0xe5, 0x34, 0x08, 0xff, 0x65, 0x76, 0x97, 0x9e, 0x4f, 0x71, 0x64, 0xd6, + 0x84, 0x5d, 0xb1, 0x42, 0xa7, 0x00, 0xdc, 0x6e, 0x18, 0x2d, 0x70, 0x64, 0xd6, 0xb9, 0xe9, 0x7e, + 0x09, 0xd3, 0xcf, 0x98, 0xbe, 0xd3, 0x26, 0xea, 0x13, 0x7d, 0x0d, 0xbb, 0x02, 0x92, 0xd9, 0x3c, + 0x5c, 0x60, 0x62, 0x36, 0x8e, 0x8c, 0x7e, 0x77, 0x78, 0x57, 0x98, 0x52, 0xf0, 0x4f, 0x05, 0x68, + 0xa3, 0x70, 0x81, 0x9d, 0x8e, 0x50, 0x67, 0xdf, 0x04, 0xdd, 0x83, 0x76, 0xe0, 0xae, 0x30, 0x59, + 0xbb, 0x73, 0x6c, 0x36, 0x79, 0x84, 0xd7, 0x1b, 0x76, 0x00, 0x2d, 0xe5, 0xdc, 0x7e, 0x0c, 0x0d, + 0x91, 0x1a, 0xea, 0x40, 0xf3, 0xc5, 0xe4, 0xbb, 0xc9, 0xb3, 0x1f, 0x26, 0xbd, 0x1d, 0xd4, 0x82, + 0xda, 0xe4, 0xe4, 0xfb, 0x71, 0xaf, 0x82, 0x6e, 0xc1, 0xde, 0xf9, 0xc9, 0xf4, 0xf9, 0xcc, 0x19, + 0x9f, 0x8f, 0x4f, 0xa6, 0xe3, 0x27, 0xbd, 0x2a, 0xea, 0x02, 0x8c, 0xce, 0x4e, 0x9c, 0xe7, 0x33, + 0xae, 0x62, 0xd8, 0xef, 0x43, 0x3b, 0xc9, 0x01, 0x35, 0xc1, 0x38, 0x99, 0x8e, 0x84, 0x89, 0x27, + 0xe3, 0xe9, 0xa8, 0x57, 0xb1, 0x7f, 0xaf, 0xc0, 0xbe, 0x4e, 0x19, 0x59, 0x87, 0x01, 0xc1, 0x8c, + 0xb3, 0x79, 0x18, 0x07, 0x09, 0x67, 0x7c, 0x81, 0x10, 0xd4, 0x02, 0xfc, 0x56, 0x31, 0xc6, 0xbf, + 0x99, 0x26, 0x0d, 0xa9, 0xeb, 0x73, 0xb6, 0x0c, 0x47, 0x2c, 0xd0, 0xe7, 0xd0, 0x92, 0x50, 0x10, + 0xb3, 0x76, 0x64, 0xf4, 0x3b, 0xc3, 0x3b, 0x3a, 0x40, 0xd2, 0xa3, 0x93, 0xa8, 0xd9, 0xa7, 0x70, + 0x78, 0x8a, 0x55, 0x24, 0x02, 0x3f, 0x75, 0x83, 0x98, 0x5f, 0x77, 0x85, 0x79, 0x30, 0xcc, 0xaf, + 0xbb, 0xc2, 0xc8, 0x84, 0xa6, 0xbc, 0x7e, 0x3c, 0x9c, 0xba, 0xa3, 0x96, 0x36, 0x05, 0x73, 0xd3, + 0x90, 0xcc, 0x2b, 0xcf, 0xd2, 0xc7, 0x50, 0x63, 0x95, 0xc1, 0xcd, 0x74, 0x86, 0x48, 0x8f, 0xf3, + 0x69, 0xb0, 0x0c, 0x1d, 0x2e, 0xd7, 0xa9, 0x33, 0xb2, 0xd4, 0x9d, 0xa5, 0xbd, 0x8e, 0xc2, 0x80, + 0xe2, 0x80, 0xde, 0x2c, 0xfe, 0x73, 0xb8, 0x9b, 0x63, 0x49, 0x26, 0x70, 0x0c, 0x4d, 0x19, 0x1a, + 0xb7, 0x56, 0x88, 0xab, 0xd2, 0xb2, 0xff, 0x34, 0x60, 0xff, 0xc5, 0x7a, 0xe1, 0x52, 0xac, 0x44, + 0x5b, 0x82, 0xba, 0x0f, 0x75, 0xde, 0x61, 0x24, 0x16, 0xb7, 0x84, 0x6d, 0xd1, 0x86, 0x46, 0xec, + 0xaf, 0x23, 0xe4, 0xe8, 0x21, 0x34, 0x2e, 0x5d, 0x3f, 0xc6, 0x84, 0x03, 0x91, 0xa0, 0x26, 0x35, + 0x79, 0x7b, 0x72, 0xa4, 0x06, 0x3a, 0x84, 0xe6, 0x22, 0xba, 0x62, 0xfd, 0x85, 0x97, 0x64, 0xcb, + 0x69, 0x2c, 0xa2, 0x2b, 0x27, 0x0e, 0xd0, 0x87, 0xb0, 0xb7, 0xf0, 0x88, 0x7b, 0xe1, 0xe3, 0xd9, + 0xeb, 0x30, 0x7c, 0x43, 0x78, 0x55, 0xb6, 0x9c, 0x5d, 0xb9, 0x79, 0xc6, 0xf6, 0x90, 0xc5, 0x6e, + 0xd2, 0x3c, 0xc2, 0x2e, 0xc5, 0x66, 0x83, 0xcb, 0x93, 0x35, 0xc3, 0x90, 0x7a, 0x2b, 0x1c, 0xc6, + 0x94, 0x97, 0x92, 0xe1, 0xa8, 0x25, 0xfa, 0x00, 0x76, 0x23, 0x4c, 0x30, 0x9d, 0xc9, 0x28, 0x5b, + 0xfc, 0x64, 0x87, 0xef, 0xbd, 0x14, 0x61, 0x21, 0xa8, 0xfd, 0xea, 0x7a, 0xd4, 0x6c, 0x73, 0x11, + 0xff, 0x16, 0xc7, 0x62, 0x82, 0xd5, 0x31, 0x50, 0xc7, 0x62, 0x82, 0xe5, 0xb1, 0x7d, 0xa8, 0x2f, + 0xc3, 0x68, 0x8e, 0xcd, 0x0e, 0x97, 0x89, 0x05, 0x3a, 0x82, 0xce, 0x02, 0x93, 0x79, 0xe4, 0xad, + 0x29, 0x63, 0x74, 0x97, 0x63, 0x9a, 0xde, 0x62, 0x79, 0x90, 0xf8, 0x62, 0x12, 0x52, 0x4c, 0xcc, + 0x3d, 0x91, 0x87, 0x5a, 0xdb, 0x67, 0x70, 0x27, 0x43, 0xd1, 0x4d, 0xd9, 0xfe, 0xad, 0x0a, 0x07, + 0x4e, 0xe8, 0xfb, 0x17, 0xee, 0xfc, 0x4d, 0x09, 0xbe, 0x53, 0xd4, 0x54, 0xb7, 0x53, 0x63, 0xe4, + 0x50, 0x93, 0xba, 0xc2, 0x35, 0xed, 0x0a, 0x6b, 0xa4, 0xd5, 0x8b, 0x49, 0x6b, 0xe8, 0xa4, 0x29, + 0x46, 0x9a, 0x29, 0x46, 0x12, 0xb8, 0x5b, 0x5b, 0xe0, 0x6e, 0x6f, 0xc0, 0x6d, 0x7f, 0x0b, 0x87, + 0x1b, 0x38, 0xdc, 0x14, 0xd4, 0x3f, 0x0c, 0xb8, 0xf3, 0x34, 0x20, 0xd4, 0xf5, 0xfd, 0x0c, 0xa6, + 0x49, 0xbd, 0x54, 0x4a, 0xd7, 0x4b, 0xf5, 0xbf, 0xd4, 0x8b, 0xa1, 0x91, 0xa2, 0x18, 0xac, 0xa5, + 0x18, 0x2c, 0x55, 0x43, 0x5a, 0xe7, 0x6a, 0x64, 0x3a, 0x17, 0x7a, 0x0f, 0x40, 0x5c, 0x7a, 0x6e, + 0x5c, 0x80, 0xdf, 0xe6, 0x3b, 0x13, 0xd9, 0xa8, 0x14, 0x5f, 0xad, 0x7c, 0xbe, 0xd2, 0x15, 0xd4, + 0x87, 0x9e, 0x8a, 0x67, 0x1e, 0x2d, 0x78, 0x4c, 0xb2, 0x8a, 0xba, 0x72, 0x7f, 0x14, 0x2d, 0x58, + 0x54, 0x59, 0x0e, 0x3b, 0xdb, 0x4b, 0x66, 0x37, 0x53, 0x32, 0x4f, 0xe1, 0x20, 0x4b, 0xc9, 0x4d, + 0xe9, 0xfd, 0xab, 0x02, 0x87, 0x2f, 0x02, 0x2f, 0x97, 0xe0, 0xbc, 0xa2, 0xd9, 0x80, 0xbc, 0x9a, + 0x03, 0xf9, 0x3e, 0xd4, 0xd7, 0x71, 0xf4, 0x0a, 0x4b, 0x0a, 0xc5, 0x22, 0x8d, 0x65, 0x4d, 0xc7, + 0x32, 0x83, 0x46, 0x7d, 0xf3, 0x46, 0xcf, 0xc0, 0xdc, 0x8c, 0xf2, 0x86, 0x39, 0xb3, 0xbc, 0x92, + 0x37, 0xaf, 0x2d, 0xde, 0x37, 0xfb, 0x36, 0xdc, 0x3a, 0xc5, 0xf4, 0xa5, 0x28, 0x61, 0x09, 0x80, + 0x3d, 0x06, 0x94, 0xde, 0xbc, 0xf6, 0x27, 0xb7, 0x74, 0x7f, 0x6a, 0x20, 0x54, 0xfa, 0x4a, 0xcb, + 0xfe, 0x8a, 0xdb, 0x3e, 0xf3, 0x08, 0x0d, 0xa3, 0xab, 0x6d, 0xe0, 0xf6, 0xc0, 0x58, 0xb9, 0x6f, + 0xe5, 0x93, 0xc8, 0x3e, 0xed, 0x53, 0x1e, 0x41, 0x72, 0x54, 0x46, 0x90, 0x1e, 0x30, 0x2a, 0xe5, + 0x06, 0x8c, 0xb7, 0x80, 0x9e, 0xe3, 0x64, 0xd6, 0x79, 0xc7, 0xdb, 0xac, 0x68, 0xaa, 0xea, 0x34, + 0x99, 0xd0, 0x9c, 0xfb, 0xd8, 0x0d, 0xe2, 0xb5, 0x24, 0x56, 0x2d, 0xd9, 0x65, 0x5d, 0xbb, 0x91, + 0xeb, 0xfb, 0xd8, 0x97, 0xcf, 0x5c, 0xb2, 0xb6, 0x7f, 0x82, 0xdb, 0x9a, 0x67, 0x99, 0x03, 0xcb, + 0x95, 0xbc, 0x92, 0x9e, 0xd9, 0x27, 0xfa, 0x12, 0x1a, 0x62, 0x58, 0xe4, 0x7e, 0xbb, 0xc3, 0x7b, + 0x7a, 0x4e, 0xdc, 0x48, 0x1c, 0xc8, 0xe9, 0xd2, 0x91, 0xba, 0xc3, 0x7f, 0x5a, 0xd0, 0x55, 0xe3, + 0x8e, 0x18, 0x65, 0x91, 0x07, 0xbb, 0xe9, 0xb9, 0x0e, 0x3d, 0x28, 0x9e, 0x74, 0x33, 0xe3, 0xba, + 0xf5, 0xb0, 0x8c, 0xaa, 0xc8, 0xc0, 0xde, 0xf9, 0xac, 0x82, 0x08, 0xf4, 0xb2, 0xe3, 0x16, 0x7a, + 0x94, 0x6f, 0xa3, 0x60, 0xbe, 0xb3, 0x06, 0x65, 0xd5, 0x95, 0x5b, 0x74, 0xc9, 0xef, 0x93, 0x3e, + 0x23, 0xa1, 0x77, 0x9a, 0xd1, 0xc7, 0x32, 0xeb, 0xb8, 0xb4, 0x7e, 0xe2, 0xf7, 0x67, 0xd8, 0xd3, + 0x5e, 0x6a, 0x54, 0x80, 0x56, 0xde, 0xc4, 0x65, 0x7d, 0x52, 0x4a, 0x37, 0xf1, 0xb5, 0x82, 0xae, + 0xde, 0xe2, 0x50, 0x81, 0x81, 0xdc, 0xb7, 0xc9, 0xfa, 0xb4, 0x9c, 0x72, 0xe2, 0x8e, 0x40, 0x2f, + 0xdb, 0x5f, 0x8a, 0x78, 0x2c, 0xe8, 0x96, 0x45, 0x3c, 0x16, 0xb5, 0x2d, 0x7b, 0x07, 0xb9, 0x00, + 0xd7, 0xed, 0x05, 0xdd, 0x2f, 0x24, 0x44, 0xef, 0x4a, 0x56, 0xff, 0xdd, 0x8a, 0x89, 0x8b, 0x35, + 0xfc, 0x2f, 0x33, 0x09, 0xa0, 0x02, 0x68, 0xf2, 0x07, 0x27, 0xeb, 0x51, 0x49, 0xed, 0x4c, 0x52, + 0xb2, 0x63, 0x6d, 0x49, 0x4a, 0x6f, 0x87, 0x5b, 0x92, 0xca, 0x34, 0x3f, 0x7b, 0x07, 0x79, 0xd0, + 0x75, 0xe2, 0x40, 0xba, 0x66, 0x6d, 0x01, 0x15, 0x9c, 0xde, 0xec, 0x78, 0xd6, 0x83, 0x12, 0x9a, + 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, } From f5986db184cf6d16dcd48760ac749a20236fb845 Mon Sep 17 00:00:00 2001 From: liaoj Date: Wed, 13 Feb 2019 01:02:09 +0800 Subject: [PATCH 08/57] fix: helm fetch wrong version chart (#4850) when customer use --version flag, the version format include the Build metadata, the metadata will be ingorned Signed-off-by: jliao --- pkg/repo/index.go | 9 +++++++++ pkg/repo/index_test.go | 20 +++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/pkg/repo/index.go b/pkg/repo/index.go index 9031463f3..ac19528fa 100644 --- a/pkg/repo/index.go +++ b/pkg/repo/index.go @@ -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 { test, err := semver.NewVersion(ver.Version) if err != nil { diff --git a/pkg/repo/index_test.go b/pkg/repo/index_test.go index 7c9239b7a..7e9998a4d 100644 --- a/pkg/repo/index_test.go +++ b/pkg/repo/index_test.go @@ -20,6 +20,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "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.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: "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() if i.APIVersion != APIVersionV1 { t.Error("Expected API version v1") } - if len(i.Entries) != 2 { - t.Errorf("Expected 2 charts. Got %d", len(i.Entries)) + if len(i.Entries) != 3 { + t.Errorf("Expected 3 charts. Got %d", len(i.Entries)) } if i.Entries["clipper"][0].Name != "clipper" { @@ -54,13 +58,23 @@ func TestIndexFile(t *testing.T) { } 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. if v := i.Entries["cutter"][0].Version; v != "0.2.0" { 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) { From 5b38cc2d888218b74a8ba1cef4341e7a18e1df26 Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Tue, 12 Feb 2019 13:54:11 -0700 Subject: [PATCH 09/57] ref: Update Sprig to 2.18.0 (#5300) * ref: Update Sprig to 2.18.0 This fixes a problem with Go 1.11 and also adds some new functions. Signed-off-by: Matt Butcher * Added the glide.lock file. Signed-off-by: Matt Butcher --- glide.lock | 10 +++++----- glide.yaml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/glide.lock b/glide.lock index 1fa7c3d95..792ef28cd 100644 --- a/glide.lock +++ b/glide.lock @@ -1,13 +1,11 @@ -hash: 5dc21cc57b38ab1076f9e12d1e4248047ccc4470af8f81c8560560cb492bee9e -updated: 2019-02-08T15:20:12.179155-07:00 +hash: 70f4fe304d0034fd077f122570adc6bb5f40ceee5f4f53d8930ba5ad700a911d +updated: 2019-02-12T13:10:08.039408-07:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 subpackages: - compute/metadata - internal -- name: github.com/aokoli/goutils - version: 9c37978a95bd5c709a15883b6242714ea6709e64 - name: github.com/asaskevich/govalidator version: 7664702784775e51966f0885f5cd27435916517b - name: github.com/Azure/go-ansiterm @@ -181,10 +179,12 @@ imports: - jwriter - name: github.com/MakeNowJust/heredoc version: bb23615498cded5e105af4ce27de75b089cbe851 +- name: github.com/Masterminds/goutils + version: 41ac8693c5c10a92ea1ff5ac3a7f95646f6123b0 - name: github.com/Masterminds/semver version: 517734cc7d6470c0d07130e40fd40bdeb9bcd3fd - name: github.com/Masterminds/sprig - version: 544a9b1d90f323f6509491b389714fbbd126bee3 + version: b1fe2752acccf8c3d7f8a1e7c75c7ae7d83a1975 - name: github.com/Masterminds/vcs version: 3084677c2c188840777bff30054f2b553729d329 - name: github.com/mattn/go-runewidth diff --git a/glide.yaml b/glide.yaml index 42c10b347..e482e23c2 100644 --- a/glide.yaml +++ b/glide.yaml @@ -21,7 +21,7 @@ import: - package: github.com/imdario/mergo version: v0.3.5 - package: github.com/Masterminds/sprig - version: ^2.16.0 + version: ^2.18.0 - package: github.com/ghodss/yaml - package: github.com/Masterminds/semver version: ~1.3.1 From c99a3c676a11206352024d7851076106d2840b45 Mon Sep 17 00:00:00 2001 From: tuanvcw Date: Wed, 13 Feb 2019 21:59:17 +0700 Subject: [PATCH 10/57] Update deprecated links in docs (#5302) Signed-off-by: Vu Cong Tuan --- docs/chart_template_guide/control_structures.md | 2 +- docs/chart_template_guide/getting_started.md | 4 ++-- docs/chart_template_guide/wrapping_up.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/chart_template_guide/control_structures.md b/docs/chart_template_guide/control_structures.md index e2f9ca89d..d411c2f79 100644 --- a/docs/chart_template_guide/control_structures.md +++ b/docs/chart_template_guide/control_structures.md @@ -329,7 +329,7 @@ data: - "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. diff --git a/docs/chart_template_guide/getting_started.md b/docs/chart_template_guide/getting_started.md index 87ae5fa3c..eb1d966d3 100644 --- a/docs/chart_template_guide/getting_started.md +++ b/docs/chart_template_guide/getting_started.md @@ -51,8 +51,8 @@ already there. - `NOTES.txt`: The "help text" for your chart. This will be displayed to your users when they run `helm install`. -- `deployment.yaml`: A basic manifest for creating a Kubernetes [deployment](http://kubernetes.io/docs/user-guide/deployments/) -- `service.yaml`: A basic manifest for creating a [service endpoint](http://kubernetes.io/docs/user-guide/services/) for your deployment +- `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](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 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. diff --git a/docs/chart_template_guide/wrapping_up.md b/docs/chart_template_guide/wrapping_up.md index ea5dc1183..c7ecad475 100755 --- a/docs/chart_template_guide/wrapping_up.md +++ b/docs/chart_template_guide/wrapping_up.md @@ -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: - 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 [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. From 5464a822ccd6d99da8b25d8ef690263c6d7a2d8c Mon Sep 17 00:00:00 2001 From: Nguyen Van Trung Date: Fri, 15 Feb 2019 12:17:44 +0700 Subject: [PATCH 11/57] Change http to https for security links Signed-off-by: Nguyen Van Trung --- CONTRIBUTING.md | 2 +- docs/chart_best_practices/conventions.md | 2 +- docs/chart_template_guide/yaml_techniques.md | 2 +- docs/charts.md | 4 ++-- docs/developers.md | 4 ++-- docs/glossary.md | 2 +- docs/history.md | 2 +- docs/provenance.md | 6 +++--- docs/related.md | 6 +++--- docs/release_checklist.md | 2 +- docs/using_helm.md | 4 ++-- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7736cbd6b..a20c2b90b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 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, -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 diff --git a/docs/chart_best_practices/conventions.md b/docs/chart_best_practices/conventions.md index 524928e25..c8bbd7d94 100644 --- a/docs/chart_best_practices/conventions.md +++ b/docs/chart_best_practices/conventions.md @@ -22,7 +22,7 @@ The directory that contains a chart MUST have the same name as the chart. Thus, ## 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. diff --git a/docs/chart_template_guide/yaml_techniques.md b/docs/chart_template_guide/yaml_techniques.md index 00b33b674..0a84e4a25 100644 --- a/docs/chart_template_guide/yaml_techniques.md +++ b/docs/chart_template_guide/yaml_techniques.md @@ -7,7 +7,7 @@ to read. ## 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. The two types of collections are maps and sequences: diff --git a/docs/charts.md b/docs/charts.md index 7bc4f0020..d91dfe54e 100644 --- a/docs/charts.md +++ b/docs/charts.md @@ -71,7 +71,7 @@ Other fields will be silently ignored. ### Charts and Versioning 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 are identified by name plus version. @@ -792,7 +792,7 @@ standard references that will help you out. - [Go templates](https://godoc.org/text/template) - [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 diff --git a/docs/developers.md b/docs/developers.md index 4edc4bea1..fb704cb17 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -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 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' @@ -201,7 +201,7 @@ Common scopes: Read more: - The [Deis Guidelines](https://github.com/deis/workflow/blob/master/src/contributing/submitting-a-pull-request.md) 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 diff --git a/docs/glossary.md b/docs/glossary.md index 875807268..02a5c125f 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -37,7 +37,7 @@ are bundled with it. ## Chart Version 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 diff --git a/docs/history.md b/docs/history.md index 71e63c6b2..1a3d9dbe4 100644 --- a/docs/history.md +++ b/docs/history.md @@ -12,7 +12,7 @@ Differences from Helm Classic: - Helm's chart format has changed for the better: - Dependencies are immutable and stored inside of a chart's `charts/` 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 - Helm supports Go templates without requiring you to run `generate` or `template` commands. diff --git a/docs/provenance.md b/docs/provenance.md index 163e72842..3f259a391 100644 --- a/docs/provenance.md +++ b/docs/provenance.md @@ -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) 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 - [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). The combination of this gives users the following assurances: @@ -202,7 +202,7 @@ keywords: - proxy source: - https://github.com/foo/bar -home: http://nginx.com +home: https://nginx.com ... 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) 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 diff --git a/docs/related.md b/docs/related.md index ba1b0dfbf..a8e494172 100644 --- a/docs/related.md +++ b/docs/related.md @@ -8,9 +8,9 @@ or [pull request](https://github.com/helm/helm/pulls). ## Article, Blogs, How-Tos, and Extra Documentation - [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) -- [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) - [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) @@ -90,7 +90,7 @@ Tools layered on top of Helm or Tiller. Platforms, distributions, and services that include Helm support. - [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 - [Qstack](https://qstack.com) diff --git a/docs/release_checklist.md b/docs/release_checklist.md index 4011b6675..d1c6c967a 100644 --- a/docs/release_checklist.md +++ b/docs/release_checklist.md @@ -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 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. It is important to note that this document assumes that the git remote in your diff --git a/docs/using_helm.md b/docs/using_helm.md index db723d993..79b5aef6f 100755 --- a/docs/using_helm.md +++ b/docs/using_helm.md @@ -17,7 +17,7 @@ cluster. Think of it like the Kubernetes equivalent of a Homebrew formula, an Apt dpkg, or a Yum RPM file. 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 Kubernetes packages. @@ -190,7 +190,7 @@ imageTag: 10.1.14-r3 ## Specify a imagePullPolicy ## 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: From 9f964c11da1c1ae865aed2be87c1929f04683b82 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 15 Feb 2019 17:28:31 +0000 Subject: [PATCH 12/57] fix: helm display confused error message if version is empty (without quotes) (#5310) Signed-off-by: Alex Gladkikh --- pkg/downloader/chart_downloader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index 453e81470..1ef85f501 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -213,7 +213,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge cv, err := i.Get(chartName, version) 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 %q not found in %s index. (try 'helm repo update'). %s", chartName, version, r.Config.Name, err) } if len(cv.URLs) == 0 { From 35b782219041d39a56557728b5b6933cca7178d9 Mon Sep 17 00:00:00 2001 From: Matt Farina Date: Fri, 15 Feb 2019 12:48:46 -0500 Subject: [PATCH 13/57] Noting the version as the match element That the match is based on version is implicit. Making it explicit because I had to think when I saw it. Signed-off-by: Matt Farina --- pkg/downloader/chart_downloader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index 1ef85f501..563188ec3 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -213,7 +213,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge cv, err := i.Get(chartName, version) if err != nil { - return u, r.Client, fmt.Errorf("chart %q matching %q 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 { From 63d262e5ec3c1b0d935995c7354b2b239c18ff14 Mon Sep 17 00:00:00 2001 From: Matt Farina Date: Fri, 15 Feb 2019 12:58:23 -0500 Subject: [PATCH 14/57] Display the checksums in CI When Helm is packaging up the bundles it generates the checksums but does not display them. Having them here will aide in the generation of release notes and provide another source listing them. Signed-off-by: Matt Farina --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 0677cafe4..20ce7e5a4 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,7 @@ dist: checksum: for f in _dist/*.{gz,zip} ; do \ shasum -a 256 "$${f}" | awk '{print $$1}' > "$${f}.sha256" ; \ + echo -n "Checksum: " && cat $${f}.sha256 ; \ done .PHONY: check-docker From d76eebb319eda349371f561c881ca91cc53907ad Mon Sep 17 00:00:00 2001 From: Matt Farina Date: Fri, 15 Feb 2019 15:22:23 -0500 Subject: [PATCH 15/57] Adding PGP signing to the release process Signed-off-by: Matt Farina --- docs/release_checklist.md | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/docs/release_checklist.md b/docs/release_checklist.md index d1c6c967a..c1595fb58 100644 --- a/docs/release_checklist.md +++ b/docs/release_checklist.md @@ -250,7 +250,21 @@ git tag --sign --annotate "${RELEASE_NAME}" --message "Helm release ${RELEASE_NA 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 follow the following steps: + +1. Download each of the release bundles generated by the CI system +2. Sign each of them using GnuPG using the command `gpg --armor --detach-sign [FILE NAME]`. + This will generate a file name `[FILE NAME].asc` with an ascii armored signature. + +Each of the signature files needs 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 release cycle, but it is usually more beneficial to the end-user if the release @@ -286,14 +300,14 @@ The community keeps growing, and we'd love to see you there! 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)) -- [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 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 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 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 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 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)) -- [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)) +- [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) / 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) / 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) / 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) / 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) / 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) / 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) / CHECKSUM_VAL) Once you have the client installed, upgrade Tiller with `helm init --upgrade`. @@ -335,7 +349,7 @@ in the example above. Once finished, go into GitHub and edit the release notes for the tagged release with the notes written here. -## 8. Evangelize +## 9. Evangelize Congratulations! You're done. Go grab yourself a $DRINK_OF_CHOICE. You've earned it. From 8224e3348ef004cbff7321e2b26b8fbcd7e190a3 Mon Sep 17 00:00:00 2001 From: Marc Jansen Date: Tue, 19 Feb 2019 13:31:47 +0100 Subject: [PATCH 16/57] Symmetrical asterisks (#5325) Signed-off-by: Marc Jansen --- cmd/helm/repo_update.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 1a239b407..42d242b83 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -124,6 +124,6 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer, home helmpath.Ho 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 } From 73a17eb59900348234ad7c4cba75a537dcef9708 Mon Sep 17 00:00:00 2001 From: Miroslav Spousta Date: Tue, 19 Feb 2019 23:46:01 +0100 Subject: [PATCH 17/57] Fix wording in error message (#5322) Signed-off-by: Miroslav Spousta --- pkg/tiller/release_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index b85118cd2..ffb922e40 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -61,7 +61,7 @@ var ( // errInvalidRevision indicates that an invalid release revision number was provided. errInvalidRevision = errors.New("invalid release revision") //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. From d24ba97faeb39f692f74c87d183a723b4138ee52 Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Wed, 20 Feb 2019 13:29:50 +0700 Subject: [PATCH 18/57] Correct misspelling of Helm Although it is spelling mistakes, it might make an affects while reading. Signed-off-by: Nguyen Hai Truong --- _proto/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_proto/README.md b/_proto/README.md index 0ebd6b6a4..7704572eb 100644 --- a/_proto/README.md +++ b/_proto/README.md @@ -3,7 +3,7 @@ Protobuf3 type declarations for the Helm API 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.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. From 2ca5d2ab9cf41a23a1d650ae2dc88a44344c898b Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Wed, 20 Feb 2019 14:35:35 +0700 Subject: [PATCH 19/57] trivial fix typo Signed-off-by: Nguyen Hai Truong --- docs/tiller_ssl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tiller_ssl.md b/docs/tiller_ssl.md index 41e704653..3d64635ae 100644 --- a/docs/tiller_ssl.md +++ b/docs/tiller_ssl.md @@ -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, 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 (IP SAN) in the Tiller certificate. From 8f9144332665f1aecb1b29925e70504cfb9210f5 Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Thu, 21 Feb 2019 01:25:43 +0700 Subject: [PATCH 20/57] Adding '/usr/bin/env bash' (#5334) This commit aims to add '/usr/bin/env bash' as a shebang line to indicates scripts use bash shell for interpreting. Signed-off-by: Nguyen Hai Truong --- scripts/completions.bash | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/completions.bash b/scripts/completions.bash index c24f3d257..36cb01f15 100644 --- a/scripts/completions.bash +++ b/scripts/completions.bash @@ -1,3 +1,5 @@ +#!/usr/bin/env bash + # bash completion for helm -*- shell-script -*- __debug() From fbc89e13d1e0a92b39d3088dc02f5fdccae48aca Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Thu, 21 Feb 2019 01:25:59 +0700 Subject: [PATCH 21/57] The 'Linuxes' is obscure (#5332) Using `Linux distributions` instead of `Linuxes` Signed-off-by: Nguyen Hai Truong --- docs/developers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developers.md b/docs/developers.md index fb704cb17..70203b2d0 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -32,7 +32,7 @@ docker-test`. 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. - Tiller must have access to a Kubernetes cluster. It learns about the cluster by examining the Kube config files that `kubectl` uses. From ead111dd4f699b3cb0a56f1e6d4585e3363f925b Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Wed, 20 Feb 2019 10:30:31 -0800 Subject: [PATCH 22/57] add `make sign` and `make fetch-dist` (#5329) Signed-off-by: Matthew Fisher --- Makefile | 15 +++++++++++++++ docs/release_checklist.md | 21 +++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 20ce7e5a4..7248bbed2 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ DEV_IMAGE ?= golang:1.11 SHORT_NAME ?= tiller SHORT_NAME_RUDDER ?= rudder 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 # go option @@ -44,6 +45,20 @@ dist: $(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 checksum: for f in _dist/*.{gz,zip} ; do \ diff --git a/docs/release_checklist.md b/docs/release_checklist.md index c1595fb58..bddb50ffb 100644 --- a/docs/release_checklist.md +++ b/docs/release_checklist.md @@ -256,13 +256,17 @@ 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 follow the following steps: +To do this, run the following `make` commands: -1. Download each of the release bundles generated by the CI system -2. Sign each of them using GnuPG using the command `gpg --armor --detach-sign [FILE NAME]`. - This will generate a file name `[FILE NAME].asc` with an ascii armored signature. +```shell +make clean +make fetch-dist +make sign +``` -Each of the signature files needs to be uploaded to the release on GitHub. +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 @@ -322,7 +326,7 @@ The [Quickstart Guide](https://docs.helm.sh/using_helm/#quickstart-guide) will g ### Features - ref(*): kubernetes v1.11 support efadbd88035654b2951f3958167afed014c46bc6 (Adam Reese) -- feat(helm): add $HELM_KEY_PASSPHRASE environment variable for signing helm charts (#4778) 1e26b5300b5166fabb90002535aacd2f9cc7d787 +- feat(helm): add $HELM_KEY_PASSPHRASE environment variable for signing helm charts (#4778) 1e26b5300b5166fabb90002535aacd2f9cc7d787 ### Bug fixes - fix circle not building tags f4f932fabd197f7e6d608c8672b33a483b4b76fa (Matthew Fisher) @@ -346,8 +350,9 @@ 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 in the example above. -Once finished, go into GitHub and edit the release notes for the tagged release -with the notes written here. +Once finished, go into GitHub and edit the release notes for the tagged release with the notes written here. + +Remember to attach the ascii armored signatures generated in the previous step to the release notes. ## 9. Evangelize From d9d2b3ae4812d756297ac89b8930eee61273c871 Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Tue, 26 Feb 2019 22:36:23 +0700 Subject: [PATCH 23/57] Fix many misspelling words (#5357) Although it is spelling mistakes, it might make an affects while reading. Co-Authored-By: Dao Cong Tien tiendc@vn.fujitsu.com Signed-off-by: Nguyen Hai Truong --- cmd/helm/verify.go | 2 +- docs/helm/helm_verify.md | 2 +- docs/man/man1/helm_verify.1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/helm/verify.go b/cmd/helm/verify.go index bbc8347c1..6b8e6895d 100644 --- a/cmd/helm/verify.go +++ b/cmd/helm/verify.go @@ -27,7 +27,7 @@ import ( const verifyDesc = ` 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. This command can be used to verify a local chart. Several other commands provide diff --git a/docs/helm/helm_verify.md b/docs/helm/helm_verify.md index 30ed43679..acd1c2923 100644 --- a/docs/helm/helm_verify.md +++ b/docs/helm/helm_verify.md @@ -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. -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. This command can be used to verify a local chart. Several other commands provide diff --git a/docs/man/man1/helm_verify.1 b/docs/man/man1/helm_verify.1 index 5297924ae..341449ad8 100644 --- a/docs/man/man1/helm_verify.1 +++ b/docs/man/man1/helm_verify.1 @@ -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. .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. .PP From 44eba6d28c87a58299d94e0832fb52385923d2d1 Mon Sep 17 00:00:00 2001 From: hnwolf Date: Tue, 26 Feb 2019 22:40:06 +0700 Subject: [PATCH 24/57] Update incorrect link (#5359) Signed-off-by: Nguyen Hung Phuong --- docs/using_helm.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/using_helm.md b/docs/using_helm.md index 79b5aef6f..faf3cc20f 100755 --- a/docs/using_helm.md +++ b/docs/using_helm.md @@ -18,8 +18,8 @@ an Apt dpkg, or a Yum RPM file. A *Repository* is the place where charts can be collected and shared. It's like Perl's [CPAN archive](https://www.cpan.org) or the -[Fedora Package Database](https://admin.fedoraproject.org/pkgdb/), but for -Kubernetes packages. +[Fedora Package Database](https://apps.fedoraproject.org/packages/s/pkgdb), but +for Kubernetes packages. 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 From 268695813ba957821e53a784ac849aa3ca7f70a3 Mon Sep 17 00:00:00 2001 From: tuanvcw Date: Tue, 26 Feb 2019 22:41:50 +0700 Subject: [PATCH 25/57] Fix typos in various places (#5360) Signed-off-by: Vu Cong Tuan --- _proto/hapi/release/status.proto | 2 +- pkg/repo/chartrepo_test.go | 2 +- pkg/tiller/release_server.go | 4 ++-- pkg/tlsutil/cfg.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/_proto/hapi/release/status.proto b/_proto/hapi/release/status.proto index aa90760b3..e6ccd3d6e 100644 --- a/_proto/hapi/release/status.proto +++ b/_proto/hapi/release/status.proto @@ -29,7 +29,7 @@ message Status { UNKNOWN = 0; // Status_DEPLOYED indicates that the release has been pushed to Kubernetes. 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; // Status_SUPERSEDED indicates that this release object is outdated and a newer one exists. SUPERSEDED = 3; diff --git a/pkg/repo/chartrepo_test.go b/pkg/repo/chartrepo_test.go index a2f1daeb8..ed09b5c6d 100644 --- a/pkg/repo/chartrepo_test.go +++ b/pkg/repo/chartrepo_test.go @@ -175,7 +175,7 @@ func verifyIndex(t *testing.T, actual *IndexFile) { t.Errorf("Expected %q, got %q", e.Version, g.Version) } if len(g.Keywords) != 3 { - t.Error("Expected 3 keyrwords.") + t.Error("Expected 3 keywords.") } if len(g.Maintainers) != 2 { t.Error("Expected 2 maintainers.") diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index ffb922e40..eb3e876d0 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -115,7 +115,7 @@ func NewReleaseServer(env *environment.Environment, clientset kubernetes.Interfa // request values are not altered. func (s *ReleaseServer) reuseValues(req *services.UpdateReleaseRequest, current *release.Release) error { 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") return nil } @@ -191,7 +191,7 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) { rel := h[0] 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) return start, nil } else if reuse { diff --git a/pkg/tlsutil/cfg.go b/pkg/tlsutil/cfg.go index 2c1dfd340..6c2a829df 100644 --- a/pkg/tlsutil/cfg.go +++ b/pkg/tlsutil/cfg.go @@ -40,7 +40,7 @@ type Options struct { 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) { var cert *tls.Certificate var pool *x509.CertPool From cdc09e54bca50a53c1e54f0e67b15a0913f5af1d Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Wed, 27 Feb 2019 01:30:52 +0700 Subject: [PATCH 26/57] Ignore Unix swap files `*.swp` in .gitignore (#5364) Co-Authored-By: Dao Cong Tien tiendc@vn.fujitsu.com Signed-off-by: Nguyen Hai Truong --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2414f7f2b..cfba70998 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ rootfs/rudder vendor/ *.exe .idea/ -*.iml \ No newline at end of file +*.iml +*.swp From 42e424bb3bd24df1508d43b0bd40e0047e24abe9 Mon Sep 17 00:00:00 2001 From: Nguyen Hai Truong Date: Wed, 27 Feb 2019 10:09:39 +0700 Subject: [PATCH 27/57] Insert *~ when using emacs in .gitignore (#5366) Ignore temporary files *~ when editting source codes with emacs. Signed-off-by: Nguyen Hai Truong --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cfba70998..14d942bf1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ vendor/ .idea/ *.iml *.swp +*~ From 63c970c5ce29b0971cdc6409d9c0e156321ea32a Mon Sep 17 00:00:00 2001 From: Nguyen Quang Huy Date: Wed, 27 Feb 2019 22:00:20 +0700 Subject: [PATCH 28/57] Fix some typos (#5352) Correct some words spelling for reading more easily. Signed-off-by: Nguyen Quang Huy Co-Authored-By: Nguyen Van Trung --- CONTRIBUTING.md | 2 +- docs/chart_template_guide/functions_and_pipelines.md | 2 +- docs/chart_template_guide/helm_ignore_file.md | 2 +- docs/charts.md | 2 +- docs/charts_hooks.md | 4 ++-- docs/charts_tips_and_tricks.md | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a20c2b90b..c9716d0ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -242,7 +242,7 @@ Documentation PRs will follow the same lifecycle as other PRs. They will also be ## The Triager 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. ## Labels diff --git a/docs/chart_template_guide/functions_and_pipelines.md b/docs/chart_template_guide/functions_and_pipelines.md index fe5a3c2b2..1c099887d 100644 --- a/docs/chart_template_guide/functions_and_pipelines.md +++ b/docs/chart_template_guide/functions_and_pipelines.md @@ -150,7 +150,7 @@ Template functions and pipelines are a powerful way to transform information and ## 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 {{/* include the body of this if statement when the variable .Values.fooString exists and is set to "foo" */}} diff --git a/docs/chart_template_guide/helm_ignore_file.md b/docs/chart_template_guide/helm_ignore_file.md index 6793bdfec..5980f439c 100644 --- a/docs/chart_template_guide/helm_ignore_file.md +++ b/docs/chart_template_guide/helm_ignore_file.md @@ -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. -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. diff --git a/docs/charts.md b/docs/charts.md index d91dfe54e..6137898c2 100644 --- a/docs/charts.md +++ b/docs/charts.md @@ -492,7 +492,7 @@ create/update all of the above Kubernetes objects in the following order: This is because when Helm installs/upgrades charts, 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 - created/updated in that order. diff --git a/docs/charts_hooks.md b/docs/charts_hooks.md index fbb302481..6d436402d 100644 --- a/docs/charts_hooks.md +++ b/docs/charts_hooks.md @@ -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. -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"`. diff --git a/docs/charts_tips_and_tricks.md b/docs/charts_tips_and_tricks.md index e2c73b14f..d988184c5 100644 --- a/docs/charts_tips_and_tricks.md +++ b/docs/charts_tips_and_tricks.md @@ -281,7 +281,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. 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. As a best practice, templates should follow a YAML-like syntax _unless_ From 33589472cf02d8d10e96e06085d95791c0611a75 Mon Sep 17 00:00:00 2001 From: Nguyen Van Duc Date: Thu, 28 Feb 2019 01:38:51 +0700 Subject: [PATCH 29/57] Add .gitignore files for Eclipse (#5368) Signed-off-by: vanduc95 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 14d942bf1..d1ec13265 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ vendor/ *.iml *.swp *~ +.classpath +.project +.settings/** From 55fbed95d586db554b33cfa4dceff1475d2d4d41 Mon Sep 17 00:00:00 2001 From: Jacob LeGrone Date: Mon, 4 Mar 2019 10:09:05 -0500 Subject: [PATCH 30/57] feat(resource-policy): delete manifests when policy value is delete Signed-off-by: Jacob LeGrone --- pkg/kube/client.go | 8 +++++--- pkg/kube/resource_policy.go | 23 +++++++++++++++++++---- pkg/tiller/resource_policy.go | 12 +++--------- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index eccf888e8..955c75ab1 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -23,12 +23,13 @@ import ( goerrors "errors" "fmt" "io" - "k8s.io/apimachinery/pkg/api/meta" "log" "sort" "strings" "time" + "k8s.io/apimachinery/pkg/api/meta" + "github.com/evanphx/json-patch" appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" @@ -362,8 +363,9 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader if err != nil { c.Log("Unable to get annotations on %q, err: %s", info.Name, err) } - if annotations != nil && annotations[ResourcePolicyAnno] == KeepPolicy { - c.Log("Skipping delete of %q due to annotation [%s=%s]", info.Name, ResourcePolicyAnno, KeepPolicy) + if ResourcePolicyIsKeep(annotations) { + policy := annotations[ResourcePolicyAnno] + c.Log("Skipping delete of %q due to annotation [%s=%s]", info.Name, ResourcePolicyAnno, policy) continue } diff --git a/pkg/kube/resource_policy.go b/pkg/kube/resource_policy.go index 45cebcba8..9bce63a7c 100644 --- a/pkg/kube/resource_policy.go +++ b/pkg/kube/resource_policy.go @@ -19,8 +19,23 @@ package kube // ResourcePolicyAnno is the annotation name for a 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 -// during an uninstallRelease action. -const KeepPolicy = "keep" +// This resource policy type allows explicitly opting in to the default +// resource deletion behavior, for example when overriding a chart's +// default annotations. Any other value allows resources to skip being +// deleted during an uninstallRelease action. +const deletePolicy = "delete" + +// 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 +} diff --git a/pkg/tiller/resource_policy.go b/pkg/tiller/resource_policy.go index aa9c5d2bd..c97621fcd 100644 --- a/pkg/tiller/resource_policy.go +++ b/pkg/tiller/resource_policy.go @@ -34,17 +34,11 @@ func filterManifestsToKeep(manifests []Manifest) ([]Manifest, []Manifest) { continue } - resourcePolicyType, ok := m.Head.Metadata.Annotations[kube.ResourcePolicyAnno] - if !ok { - remaining = append(remaining, m) - continue - } - - resourcePolicyType = strings.ToLower(strings.TrimSpace(resourcePolicyType)) - if resourcePolicyType == kube.KeepPolicy { + if kube.ResourcePolicyIsKeep(m.Head.Metadata.Annotations) { keep = append(keep, m) + } else { + remaining = append(remaining, m) } - } return keep, remaining } From ce4c3f51ade97b71a6eee5068d4f529d60b1272b Mon Sep 17 00:00:00 2001 From: Jacob LeGrone Date: Mon, 4 Mar 2019 10:17:37 -0500 Subject: [PATCH 31/57] test(resource-policy): verify behavior of non-standard policy types Signed-off-by: Jacob LeGrone --- pkg/kube/client_test.go | 2 +- pkg/kube/resource_policy_test.go | 72 ++++++++++++++++++++++++++++ pkg/tiller/release_server_test.go | 27 ++++++++--- pkg/tiller/release_uninstall_test.go | 5 +- 4 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 pkg/kube/resource_policy_test.go diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index f601b6536..89e630bb3 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -213,7 +213,7 @@ func TestUpdate(t *testing.T) { // Test resource policy is respected 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 { t.Fatal(err) } diff --git a/pkg/kube/resource_policy_test.go b/pkg/kube/resource_policy_test.go new file mode 100644 index 000000000..de6061b48 --- /dev/null +++ b/pkg/kube/resource_policy_test.go @@ -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) + } + } +} diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index a1502e8a2..4e29e4413 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -89,13 +89,22 @@ spec: var manifestWithKeep = `kind: ConfigMap metadata: - name: test-cm-keep + name: test-cm-keep-a annotations: "helm.sh/resource-policy": keep data: name: value ` +var manifestWithKeepEmpty = `kind: ConfigMap +metadata: + name: test-cm-keep-b + annotations: + "helm.sh/resource-policy": "" +data: + name: value +` + var manifestWithUpgradeHooks = `kind: ConfigMap metadata: name: test-cm @@ -449,23 +458,27 @@ func releaseWithKeepStub(rlsName string) *release.Release { Name: "bunnychart", }, 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} - return &release.Release{ + rl := &release.Release{ Name: rlsName, Info: &release.Info{ FirstDeployed: &date, LastDeployed: &date, Status: &release.Status{Code: release.Status_DEPLOYED}, }, - Chart: ch, - Config: &chart.Config{Raw: `name: value`}, - Version: 1, - Manifest: manifestWithKeep, + Chart: ch, + Config: &chart.Config{Raw: `name: value`}, + Version: 1, } + + helm.RenderReleaseMock(rl, false) + + return rl } func MockEnvironment() *environment.Environment { diff --git a/pkg/tiller/release_uninstall_test.go b/pkg/tiller/release_uninstall_test.go index cb59b6bf5..d95a52c4d 100644 --- a/pkg/tiller/release_uninstall_test.go +++ b/pkg/tiller/release_uninstall_test.go @@ -150,7 +150,10 @@ func TestUninstallReleaseWithKeepPolicy(t *testing.T) { if res.Info == "" { t.Errorf("Expected response info to not be empty") } 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) } } From e06c605b88d38c369a52dc86a2fa9890ea1aab66 Mon Sep 17 00:00:00 2001 From: Jacob LeGrone Date: Mon, 4 Mar 2019 10:18:26 -0500 Subject: [PATCH 32/57] docs(resource-policy): explain "delete" policy type Signed-off-by: Jacob LeGrone --- docs/charts_tips_and_tricks.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/charts_tips_and_tricks.md b/docs/charts_tips_and_tricks.md index d988184c5..fd7a08f7e 100644 --- a/docs/charts_tips_and_tricks.md +++ b/docs/charts_tips_and_tricks.md @@ -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 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 "Partials" and Template Includes Sometimes you want to create some reusable parts in your chart, whether From 9689b02321be284f001a58c469d5ce13cd044b71 Mon Sep 17 00:00:00 2001 From: anton <0verc1ocker@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:18:26 -0500 Subject: [PATCH 33/57] Add --max-history tip and to the quickstart helm init docs (#5328) Signed-off-by: 0verc1ocker --- docs/quickstart.md | 4 +++- docs/rbac.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index ef3cb460e..d7f2e3b91 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -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: ```console -$ helm init +$ helm init --max-history 200 ``` +**TIP:** Setting `--max-history` 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 `kubectl config current-context`. diff --git a/docs/rbac.md b/docs/rbac.md index 4b39ecdc6..45371cda8 100644 --- a/docs/rbac.md +++ b/docs/rbac.md @@ -43,7 +43,7 @@ _Note: The cluster-admin role is created by default in a Kubernetes cluster, so $ kubectl create -f rbac-config.yaml serviceaccount "tiller" created clusterrolebinding "tiller" created -$ helm init --service-account tiller +$ helm init --service-account tiller --max-history 200 ``` ### Example: Deploy Tiller in a namespace, restricted to deploying resources only in that namespace From c94c00915f29fba5e816c277ff617babb3790cb1 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 5 Mar 2019 18:04:54 -0500 Subject: [PATCH 34/57] Fix #5046 compatible with MacOS (#5406) Signed-off-by: Marc Khouzam --- cmd/helm/completion.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/helm/completion.go b/cmd/helm/completion.go index d0249b2ea..3c0318941 100644 --- a/cmd/helm/completion.go +++ b/cmd/helm/completion.go @@ -212,7 +212,7 @@ __helm_convert_bash_to_zsh() { -e "s/${LWORD}compopt${RWORD}/__helm_compopt/g" \ -e "s/${LWORD}declare${RWORD}/__helm_declare/g" \ -e "s/\\\$(type${RWORD}/\$(__helm_type/g" \ - -e 's/aliashash\["\(\w\+\)"\]/aliashash[\1]/g' \ + -e 's/aliashash\["\(.\{1,\}\)"\]/aliashash[\1]/g' \ <<'BASH_COMPLETION_EOF' ` out.Write([]byte(zshInitialization)) From 7da53d6e70e7dde7760fb89a29bd63a8cf30e897 Mon Sep 17 00:00:00 2001 From: Patrick Decat Date: Sat, 19 Jan 2019 14:52:14 +0100 Subject: [PATCH 35/57] Refactor helm init command for reuse, allowing other programs to initialize local helm home directory without shelling out to the helm binary Signed-off-by: Patrick Decat --- cmd/helm/helm_test.go | 3 +- cmd/helm/init.go | 129 +----------------- cmd/helm/init_test.go | 47 +------ cmd/helm/installer/init.go | 166 +++++++++++++++++++++++ cmd/helm/installer/init_test.go | 120 ++++++++++++++++ cmd/helm/{ => installer}/init_unix.go | 2 +- cmd/helm/{ => installer}/init_windows.go | 2 +- cmd/helm/repo_update.go | 3 +- 8 files changed, 295 insertions(+), 177 deletions(-) create mode 100644 cmd/helm/installer/init.go create mode 100644 cmd/helm/installer/init_test.go rename cmd/helm/{ => installer}/init_unix.go (92%) rename cmd/helm/{ => installer}/init_windows.go (92%) diff --git a/cmd/helm/helm_test.go b/cmd/helm/helm_test.go index 6e915fa7b..83f1173f2 100644 --- a/cmd/helm/helm_test.go +++ b/cmd/helm/helm_test.go @@ -30,6 +30,7 @@ import ( "github.com/spf13/cobra" "k8s.io/client-go/util/homedir" + "k8s.io/helm/cmd/helm/installer" "k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm/environment" "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 { i := repo.NewIndexFile() if err := i.WriteFile(localRepoIndexFile, 0644); err != nil { diff --git a/cmd/helm/init.go b/cmd/helm/init.go index db35ef037..682189f84 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -31,11 +31,9 @@ import ( "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/helm/cmd/helm/installer" - "k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/portforwarder" - "k8s.io/helm/pkg/repo" "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. ` -const ( - stableRepository = "stable" - localRepository = "local" - localRepositoryIndexFile = "index.yaml" -) - var ( stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com" // This is the IPv4 loopback, not localhost, because we have to force IPv4 @@ -266,14 +258,8 @@ func (i *initCmd) run() error { return nil } - if err := ensureDirectories(i.home, i.out); err != nil { - return 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 + if err := installer.Initialize(i.home, i.out, i.skipRefresh, settings, stableRepositoryURL, localRepositoryURL); err != nil { + return fmt.Errorf("error initializing: %s", err) } 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 } -// 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 // want to wait before we call New(). // diff --git a/cmd/helm/init_test.go b/cmd/helm/init_test.go index fd6ef97c4..b58303f42 100644 --- a/cmd/helm/init_test.go +++ b/cmd/helm/init_test.go @@ -28,7 +28,7 @@ import ( "github.com/ghodss/yaml" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" 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) { const testDir = "../../testdata" diff --git a/cmd/helm/installer/init.go b/cmd/helm/installer/init.go new file mode 100644 index 000000000..9edfc0797 --- /dev/null +++ b/cmd/helm/installer/init.go @@ -0,0 +1,166 @@ +/* +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 + } + if err := ensureRepoFileFormat(home.RepositoryFile(), out); err != nil { + return err + } + + 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, 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 +} diff --git a/cmd/helm/installer/init_test.go b/cmd/helm/installer/init_test.go new file mode 100644 index 000000000..1d53687e6 --- /dev/null +++ b/cmd/helm/installer/init_test.go @@ -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) + } +} diff --git a/cmd/helm/init_unix.go b/cmd/helm/installer/init_unix.go similarity index 92% rename from cmd/helm/init_unix.go rename to cmd/helm/installer/init_unix.go index bf61f1925..d7f15a1c2 100644 --- a/cmd/helm/init_unix.go +++ b/cmd/helm/installer/init_unix.go @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package main +package installer // import "k8s.io/helm/cmd/helm/installer" import ( "os" diff --git a/cmd/helm/init_windows.go b/cmd/helm/installer/init_windows.go similarity index 92% rename from cmd/helm/init_windows.go rename to cmd/helm/installer/init_windows.go index 447044bba..48c56e288 100644 --- a/cmd/helm/init_windows.go +++ b/cmd/helm/installer/init_windows.go @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package main +package installer // import "k8s.io/helm/cmd/helm/installer" import ( "os" diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 42d242b83..2628b7f2f 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" + "k8s.io/helm/cmd/helm/installer" "k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/repo" @@ -99,7 +100,7 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer, home helmpath.Ho wg.Add(1) go func(re *repo.ChartRepository) { defer wg.Done() - if re.Config.Name == localRepository { + if re.Config.Name == installer.LocalRepository { mu.Lock() fmt.Fprintf(out, "...Skip %s chart repository\n", re.Config.Name) mu.Unlock() From ea1bd7e1637b2573a2f418ef607fd3a671293cd9 Mon Sep 17 00:00:00 2001 From: Martin Hickey Date: Wed, 6 Mar 2019 17:27:15 +0000 Subject: [PATCH 36/57] Update dependency build doc to improve understanding (#5379) Signed-off-by: Martin Hickey --- cmd/helm/dependency_build.go | 8 ++++---- docs/helm/helm_dependency_build.md | 9 ++++----- docs/man/man1/helm_dependency_build.1 | 9 ++++----- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/cmd/helm/dependency_build.go b/cmd/helm/dependency_build.go index 3af3c1243..64a80f3bd 100644 --- a/cmd/helm/dependency_build.go +++ b/cmd/helm/dependency_build.go @@ -29,11 +29,11 @@ const dependencyBuildDesc = ` Build out the charts/ directory from the requirements.lock file. 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' -does. +the lock file. -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. ` type dependencyBuildCmd struct { diff --git a/docs/helm/helm_dependency_build.md b/docs/helm/helm_dependency_build.md index fba70f2ec..1df32d9ab 100644 --- a/docs/helm/helm_dependency_build.md +++ b/docs/helm/helm_dependency_build.md @@ -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 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' -does. - -If no lock file is found, 'helm dependency build' will mirror the behavior -of 'helm dependency update'. +the lock file. +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 diff --git a/docs/man/man1/helm_dependency_build.1 b/docs/man/man1/helm_dependency_build.1 index adc225a81..ef92e8959 100644 --- a/docs/man/man1/helm_dependency_build.1 +++ b/docs/man/man1/helm_dependency_build.1 @@ -19,13 +19,12 @@ Build out the charts/ directory from the requirements.lock file. .PP 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' -does. +the lock file. .PP -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. .SH OPTIONS .PP From 3c86f112e246f3dcf8e5f550c78edbb297d24073 Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Wed, 6 Mar 2019 17:39:51 -0800 Subject: [PATCH 37/57] restore klog flags (#5411) Signed-off-by: Matthew Fisher --- cmd/tiller/tiller.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/tiller/tiller.go b/cmd/tiller/tiller.go index 478ca92f4..a1141b591 100644 --- a/cmd/tiller/tiller.go +++ b/cmd/tiller/tiller.go @@ -36,6 +36,7 @@ import ( "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/keepalive" + "k8s.io/klog" // Import to initialize client auth plugins. _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -100,6 +101,7 @@ var ( ) func main() { + klog.InitFlags(nil) // TODO: use spf13/cobra for tiller instead of flags flag.Parse() From 29264c5765dd77e7270d4c41ce2e48e43b9408c4 Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Wed, 6 Mar 2019 17:43:56 -0800 Subject: [PATCH 38/57] disable AppVeyor for branches other than master This should disable AppVeyor from running against dev-v3 PRs. Signed-off-by: Matthew Fisher --- .appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 40d02927d..4fe8ae6e5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,7 @@ version: "{build}" +branches: + only: + - master clone_folder: c:\go\src\k8s.io\helm environment: GOPATH: c:\go From 367b6fc12122536633ff16c67bdd2304192100f5 Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Thu, 7 Mar 2019 16:58:12 -0700 Subject: [PATCH 39/57] chore: Update sprig to 2.19.0 (#5390) Update to the latest Sprig version, which is a reversion of some of the functions added in 2.18. Signed-off-by: Matt Butcher --- glide.lock | 6 +++--- glide.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index 792ef28cd..764424e94 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 70f4fe304d0034fd077f122570adc6bb5f40ceee5f4f53d8930ba5ad700a911d -updated: 2019-02-12T13:10:08.039408-07:00 +hash: 3a24b27ab669b7bd977526dd455c5739fc2e2c14eace7dab92060ff1a39fd804 +updated: 2019-03-02T10:15:45.243405-07:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -184,7 +184,7 @@ imports: - name: github.com/Masterminds/semver version: 517734cc7d6470c0d07130e40fd40bdeb9bcd3fd - name: github.com/Masterminds/sprig - version: b1fe2752acccf8c3d7f8a1e7c75c7ae7d83a1975 + version: 9f8fceff796fb9f4e992cd2bece016be0121ab74 - name: github.com/Masterminds/vcs version: 3084677c2c188840777bff30054f2b553729d329 - name: github.com/mattn/go-runewidth diff --git a/glide.yaml b/glide.yaml index e482e23c2..c7d823196 100644 --- a/glide.yaml +++ b/glide.yaml @@ -21,7 +21,7 @@ import: - package: github.com/imdario/mergo version: v0.3.5 - package: github.com/Masterminds/sprig - version: ^2.18.0 + version: ^2.19.0 - package: github.com/ghodss/yaml - package: github.com/Masterminds/semver version: ~1.3.1 From a9c10fe104302f19e0eda5cec5b2ca314991cff0 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Fri, 8 Mar 2019 17:46:30 -0500 Subject: [PATCH 40/57] pkg/chartutil: fix SaveDir for nested templates directories Signed-off-by: Joe Lanford --- pkg/chartutil/save.go | 6 ++++++ pkg/chartutil/save_test.go | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go index 400b85e91..0482b1eb9 100644 --- a/pkg/chartutil/save.go +++ b/pkg/chartutil/save.go @@ -63,6 +63,12 @@ func SaveDir(c *chart.Chart, dest string) error { // Save templates for _, f := range c.Templates { 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 { return err } diff --git a/pkg/chartutil/save_test.go b/pkg/chartutil/save_test.go index 0ec305e78..9952fbbb0 100644 --- a/pkg/chartutil/save_test.go +++ b/pkg/chartutil/save_test.go @@ -48,6 +48,9 @@ func TestSave(t *testing.T) { Files: []*any.Any{ {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) @@ -75,6 +78,9 @@ func TestSave(t *testing.T) { if len(c2.Files) != 1 || c2.Files[0].TypeUrl != "scheherazade/shahryar.txt" { 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) { @@ -100,6 +106,9 @@ func TestSavePreservesTimestamps(t *testing.T) { Files: []*any.Any{ {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) @@ -171,6 +180,9 @@ func TestSaveDir(t *testing.T) { Files: []*any.Any{ {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 { @@ -191,4 +203,7 @@ func TestSaveDir(t *testing.T) { if len(c2.Files) != 1 || c2.Files[0].TypeUrl != "scheherazade/shahryar.txt" { 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") + } } From 4fec4b67661b7cc48b8ed1f1c5827a255c74db75 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sat, 9 Mar 2019 22:28:36 -0500 Subject: [PATCH 41/57] Fix debug printouts for zsh completion Cobra provides some out-of-the-box debugging for bash completion. To use it, one must set the variable BASH_COMP_DEBUG_FILE to some file where the debug output will be written. Many of the debug printouts indicate the current method name; they do so by using bash's ${FUNCNAME[0]} variable. This variable is different in zsh. To obtain the current method name in zsh we must use ${funcstack[1]}. This commit adds the proper sed modification to convert from bash to zsh. Signed-off-by: Marc Khouzam --- cmd/helm/completion.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/helm/completion.go b/cmd/helm/completion.go index 3c0318941..962f06e3b 100644 --- a/cmd/helm/completion.go +++ b/cmd/helm/completion.go @@ -213,6 +213,7 @@ __helm_convert_bash_to_zsh() { -e "s/${LWORD}declare${RWORD}/__helm_declare/g" \ -e "s/\\\$(type${RWORD}/\$(__helm_type/g" \ -e 's/aliashash\["\(.\{1,\}\)"\]/aliashash[\1]/g' \ + -e 's/FUNCNAME\[0\]/funcstack[1]/g' \ <<'BASH_COMPLETION_EOF' ` out.Write([]byte(zshInitialization)) From 9cc6902875135a26c5edb2fecb08f39d9eeb2dd6 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sun, 10 Mar 2019 00:22:08 -0500 Subject: [PATCH 42/57] Must use index 0 for funcstack Normally zsh arrays start at index 1 but when emulating other shells this may change. During completion, we run the command emulate -L sh which affects the indexing of zsh arrays to make it start at 0. Consequently, when replacing FUNCNAME by funcstack, we should not change the index. Signed-off-by: Marc Khouzam --- cmd/helm/completion.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/helm/completion.go b/cmd/helm/completion.go index 962f06e3b..039dcbe5f 100644 --- a/cmd/helm/completion.go +++ b/cmd/helm/completion.go @@ -213,7 +213,7 @@ __helm_convert_bash_to_zsh() { -e "s/${LWORD}declare${RWORD}/__helm_declare/g" \ -e "s/\\\$(type${RWORD}/\$(__helm_type/g" \ -e 's/aliashash\["\(.\{1,\}\)"\]/aliashash[\1]/g' \ - -e 's/FUNCNAME\[0\]/funcstack[1]/g' \ + -e 's/FUNCNAME/funcstack/g' \ <<'BASH_COMPLETION_EOF' ` out.Write([]byte(zshInitialization)) From 528dc95521674baeb1a61d43d9a1c5378ddba80f Mon Sep 17 00:00:00 2001 From: tariqibrahim Date: Sun, 10 Mar 2019 03:11:30 -0700 Subject: [PATCH 43/57] update docker version and golang image version in helm Signed-off-by: tariqibrahim --- .circleci/config.yml | 4 ++-- Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 96f53ee40..c83ee10cf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,13 +4,13 @@ jobs: working_directory: /go/src/k8s.io/helm parallelism: 3 docker: - - image: golang:1.11 + - image: golang:1.12 environment: PROJECT_NAME: "kubernetes-helm" steps: - checkout - setup_remote_docker: - version: 17.09.0-ce + version: 18.06.0-ce - restore_cache: keys: - glide-{{ checksum "glide.yaml" }}-{{ checksum "glide.lock" }} diff --git a/Makefile b/Makefile index 0677cafe4..ea7dd5fb7 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ DOCKER_REGISTRY ?= gcr.io IMAGE_PREFIX ?= kubernetes-helm -DEV_IMAGE ?= golang:1.11 +DEV_IMAGE ?= golang:1.12 SHORT_NAME ?= tiller SHORT_NAME_RUDDER ?= rudder TARGETS ?= darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64 From b480badd05ad01006363763c92b5394cdc5fc9c4 Mon Sep 17 00:00:00 2001 From: Jens Frank Date: Tue, 12 Mar 2019 00:11:26 +0100 Subject: [PATCH 44/57] Fix "helm init" parameters In the quickstart guide, --max-history is recommended as parameter for helm init. The actual name of the parameter is --history-max. Signed-off-by: Jens Frank --- docs/quickstart.md | 4 ++-- docs/rbac.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/quickstart.md b/docs/quickstart.md index d7f2e3b91..6e760ced8 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -54,10 +54,10 @@ Once you have Helm ready, you can initialize the local CLI and also install Tiller into your Kubernetes cluster in one step: ```console -$ helm init --max-history 200 +$ helm init --history-max 200 ``` -**TIP:** Setting `--max-history` 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. +**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 `kubectl config current-context`. diff --git a/docs/rbac.md b/docs/rbac.md index 45371cda8..d53edda49 100644 --- a/docs/rbac.md +++ b/docs/rbac.md @@ -43,7 +43,7 @@ _Note: The cluster-admin role is created by default in a Kubernetes cluster, so $ kubectl create -f rbac-config.yaml serviceaccount "tiller" created clusterrolebinding "tiller" created -$ helm init --service-account tiller --max-history 200 +$ helm init --service-account tiller --history-max 200 ``` ### Example: Deploy Tiller in a namespace, restricted to deploying resources only in that namespace From f2a83630efdd289a8d45581364d6a27e81b93ad1 Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Tue, 12 Mar 2019 08:05:23 -0700 Subject: [PATCH 45/57] remove appveyor Signed-off-by: Matthew Fisher --- .appveyor.yml | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 4fe8ae6e5..000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: "{build}" -branches: - only: - - master -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 .\... From a52b4b915df10f24b11774830738094cfbeacdd9 Mon Sep 17 00:00:00 2001 From: robertavram Date: Fri, 15 Mar 2019 12:19:36 -0400 Subject: [PATCH 46/57] update outdated docs image for google storage permissions Signed-off-by: robertavram --- docs/images/make-bucket-public.png | Bin 15768 -> 54186 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/make-bucket-public.png b/docs/images/make-bucket-public.png index f8a5e17f02b62f312325975638ea9bcaa2d7cb9e..e457e34b23adcb6f974c9035db63c1f2cc7f4293 100644 GIT binary patch literal 54186 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

^&-}$oN({|79XZP$L-fF5VQIa!|6A%zkswgXJ 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 MvASaMBlD2|15`@6hX4Qo From bc85db3a196d1f372e91528056dcdcb434903bb9 Mon Sep 17 00:00:00 2001 From: Pavel Eremeev Date: Sat, 16 Mar 2019 15:22:57 +0000 Subject: [PATCH 47/57] refactor(*): make "not found" error message user-friendly Signed-off-by: Pavel Eremeev --- pkg/kube/client.go | 10 ++++++++-- pkg/kube/client_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 955c75ab1..3830c4eef 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -333,9 +333,15 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader } originalInfo := original.Get(info) + + // Resource exists in the current cluster state, but not in the current helm configuration + // See: https://github.com/helm/helm/issues/1193 for more info if originalInfo == nil { - kind := info.Mapping.GroupVersionKind.Kind - return fmt.Errorf("no %s with the name %q found", kind, info.Name) + return fmt.Errorf( + "%s %q is not managed by Helm; delete the resource from the current cluster state to let Helm manage it", + info.Mapping.GroupVersionKind.Kind, + info.Name, + ) } if err := updateResource(c, info, originalInfo.Object, force, recreate); err != nil { diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 89e630bb3..5bd9449b7 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -224,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(¤t), objBody(&target), false, false, 0, false); err != nil { + if err.Error() != "Pod \"starfish\" is not managed by Helm; delete the resource from the current cluster state to let Helm manage it" { + t.Fatal(err) + } + } else { + t.Fatalf("error expected") + } +} + func TestBuild(t *testing.T) { tests := []struct { name string From 83d66b643c591e8ba9a63f2173115e30c6619bbd Mon Sep 17 00:00:00 2001 From: tariqibrahim Date: Sun, 17 Mar 2019 20:53:54 -0700 Subject: [PATCH 48/57] update kubernetes deps to latest patch releases Signed-off-by: tariqibrahim --- glide.lock | 20 ++++++++++---------- glide.yaml | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/glide.lock b/glide.lock index 764424e94..824e30041 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 3a24b27ab669b7bd977526dd455c5739fc2e2c14eace7dab92060ff1a39fd804 -updated: 2019-03-02T10:15:45.243405-07:00 +hash: f86919aea9f9b6df70967eb0b00d8a3807a2f5e924d7bd82d317f7969fddb3ef +updated: 2019-03-17T20:36:59.222397-07:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -85,7 +85,7 @@ imports: subpackages: - spdy - name: github.com/evanphx/json-patch - version: 36442dbdb585210f8d5a1b45e67aa323c197d5c4 + version: 5858425f75500d40c52783dce87d085a483ce135 - name: github.com/exponent-io/jsonpath version: d6023ce2651d8eafb5c75bb0c7167536102ec9f5 - name: github.com/fatih/camelcase @@ -370,7 +370,7 @@ imports: - name: gopkg.in/yaml.v2 version: 670d4cfef0544295bc27a114dbac37980d83185a - name: k8s.io/api - version: 05914d821849570fba9eacfb29466f2d8d3cd229 + version: 5cb15d34447165a97c76ed5a60e4e99c8a01ecfe subpackages: - admission/v1beta1 - admissionregistration/v1alpha1 @@ -407,11 +407,11 @@ imports: - storage/v1alpha1 - storage/v1beta1 - name: k8s.io/apiextensions-apiserver - version: 0fe22c71c47604641d9aa352c785b7912c200562 + version: d002e88f6236312f0289d9d1deab106751718ff0 subpackages: - pkg/features - name: k8s.io/apimachinery - version: 2b1284ed4c93a43499e781493253e2ac5959c4fd + version: 86fb29eff6288413d76bd8506874fddd9fccdff0 subpackages: - pkg/api/equality - pkg/api/errors @@ -467,7 +467,7 @@ imports: - third_party/forked/golang/netutil - third_party/forked/golang/reflect - name: k8s.io/apiserver - version: 3ccfe8365421eb08e334b195786a2973460741d8 + version: 79427f02047f9189a75b8cdaadccaf65a126853e subpackages: - pkg/authentication/authenticator - pkg/authentication/serviceaccount @@ -475,13 +475,13 @@ imports: - pkg/features - pkg/util/feature - name: k8s.io/cli-runtime - version: 835b10687cb6556f6b113099ef925146a56d5981 + version: a9e421a7932607ce4623ff45add8274499cca193 subpackages: - pkg/genericclioptions - pkg/genericclioptions/printers - pkg/genericclioptions/resource - name: k8s.io/client-go - version: 8d9ed539ba3134352c586810e749e58df4e94e4f + version: b40b2a5939e43f7ffe0028ad67586b7ce50bb675 subpackages: - discovery - discovery/fake @@ -611,7 +611,7 @@ imports: - pkg/util/proto/testing - pkg/util/proto/validation - name: k8s.io/kubernetes - version: c6d339953bd4fd8c021a6b5fb46d7952b30be9f9 + version: f2c8f1cadf1808ec28476682e49a3cce2b09efbf subpackages: - pkg/api/legacyscheme - pkg/api/service diff --git a/glide.yaml b/glide.yaml index c7d823196..23a3cdaf4 100644 --- a/glide.yaml +++ b/glide.yaml @@ -53,17 +53,17 @@ import: - package: k8s.io/kubernetes version: release-1.13 - package: k8s.io/client-go - version: kubernetes-1.13.1 + version: kubernetes-1.13.4 - package: k8s.io/api - version: kubernetes-1.13.1 + version: kubernetes-1.13.4 - package: k8s.io/apimachinery - version: kubernetes-1.13.1 + version: kubernetes-1.13.4 - package: k8s.io/apiserver - version: kubernetes-1.13.1 + version: kubernetes-1.13.4 - package: k8s.io/cli-runtime - version: kubernetes-1.13.1 + version: kubernetes-1.13.4 - package: k8s.io/apiextensions-apiserver - version: kubernetes-1.13.1 + version: kubernetes-1.13.4 - package: github.com/cyphar/filepath-securejoin version: ^0.2.1 From 63ef73d4168980e650bc95c225f9be1b63b7b37c Mon Sep 17 00:00:00 2001 From: Mikhail Kirpichev Date: Mon, 18 Mar 2019 18:54:53 +0300 Subject: [PATCH 49/57] fix(tiller): fixed a typo in tiller and unit test There was a typo in a tiller error with "released named" message, I've changed it to "a release named". Also fix a unit-test for it. Signed-off-by: Mikhail Kirpichev --- pkg/tiller/release_server.go | 2 +- pkg/tiller/release_update_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index eb3e876d0..d32fd82f6 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -195,7 +195,7 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) { s.Log("name %s exists but is not in use, reusing name", start) return start, nil } 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) diff --git a/pkg/tiller/release_update_test.go b/pkg/tiller/release_update_test.go index ea1c88f62..e47e526d6 100644 --- a/pkg/tiller/release_update_test.go +++ b/pkg/tiller/release_update_test.go @@ -604,7 +604,7 @@ func TestUpdateReleasePendingInstall_Force(t *testing.T) { 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() if err.Error() != expectedError { t.Errorf("Expected error %q, got %q", expectedError, got) From ab9cc982a0616e28d6e308d69033534cb7e62025 Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Tue, 19 Mar 2019 21:00:12 -0700 Subject: [PATCH 50/57] fix(scripts): use a more precise method of grepping Github recently changed the output of the releases page. grepping for the exact tag fixes the issue where the wrong tag was being filtered. Signed-off-by: Matthew Fisher --- scripts/get | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/get b/scripts/get index 9c93e1e84..bc13039e2 100755 --- a/scripts/get +++ b/scripts/get @@ -80,9 +80,9 @@ checkDesiredVersion() { # Use the GitHub releases webpage for the project to find the desired version for this project. local release_url="https://github.com/helm/helm/releases/${DESIRED_VERSION:-latest}" if type "curl" > /dev/null; then - 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}') + TAG=$(curl -SsL $release_url | awk '/\/tag\//' | grep -v no-underline | grep " /dev/null; then - 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}') + TAG=$(wget -q -O - $release_url | awk '/\/tag\//' | grep -v no-underline | grep " Date: Wed, 20 Mar 2019 10:52:00 -0700 Subject: [PATCH 51/57] style: fix golint error in init.go for redundant err!=nil check Signed-off-by: tariqibrahim --- cmd/helm/installer/init.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cmd/helm/installer/init.go b/cmd/helm/installer/init.go index 9edfc0797..7731a4a98 100644 --- a/cmd/helm/installer/init.go +++ b/cmd/helm/installer/init.go @@ -47,11 +47,8 @@ func Initialize(home helmpath.Home, out io.Writer, skipRefresh bool, settings he if err := ensureDefaultRepos(home, out, skipRefresh, settings, stableRepositoryURL, localRepositoryURL); err != nil { return err } - if err := ensureRepoFileFormat(home.RepositoryFile(), out); err != nil { - return err - } - return nil + return ensureRepoFileFormat(home.RepositoryFile(), out) } // ensureDirectories checks to see if $HELM_HOME exists. From 7cb03fb5628f3decb9ab547c1f71ca6a21a31ee8 Mon Sep 17 00:00:00 2001 From: Arief Hidayat Date: Thu, 21 Mar 2019 17:48:18 +0800 Subject: [PATCH 52/57] fix(script): follow redirected URL of github latest release When checking version and desired version is not set, we follow redirected URL of github latest release to get the latest tag instead of trying to get the tag value from html content. Closes #5480 Signed-off-by: Arief Hidayat --- scripts/get | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scripts/get b/scripts/get index bc13039e2..4daf504da 100755 --- a/scripts/get +++ b/scripts/get @@ -78,16 +78,31 @@ verifySupported() { # checkDesiredVersion checks if the desired version is available. checkDesiredVersion() { # Use the GitHub releases webpage for the project to find the desired version for this project. - local release_url="https://github.com/helm/helm/releases/${DESIRED_VERSION:-latest}" + local latest_release_url="https://github.com/helm/helm/releases/latest" + local release_url + if [ "x$DESIRED_VERSION" == "x" ]; then + if type "curl" > /dev/null; then + release_url=$(curl -Ls -o /dev/null -w %{url_effective} $latest_release_url) + elif type "wget" > /dev/null; then + release_url=$(wget $latest_release_url --server-response -O /dev/null 2>&1 | awk '/^ Location: /{DEST=$2} END{ print DEST}') + fi + else + release_url="https://github.com/helm/helm/releases/${DESIRED_VERSION}" + fi + + local status_code if type "curl" > /dev/null; then - TAG=$(curl -SsL $release_url | awk '/\/tag\//' | grep -v no-underline | grep " /dev/null; then - TAG=$(wget -q -O - $release_url | awk '/\/tag\//' | grep -v no-underline | grep "&1 | grep "HTTP/" | awk '{print $2}') fi - if [ "x$TAG" == "x" ]; then + + if [[ "$status_code" -ne 200 ]] ; then echo "Cannot determine ${DESIRED_VERSION} tag." exit 1 fi + + TAG=$(echo $release_url | grep -oE "[^/]+$" ) } # checkHelmInstalledVersion checks which version of helm is installed and From 65193adc10bc50edcf96499b5321c7aab46b796c Mon Sep 17 00:00:00 2001 From: Arief Hidayat Date: Fri, 22 Mar 2019 22:50:35 +0700 Subject: [PATCH 53/57] fix(script): remove check on release URL Closes #5480 Signed-off-by: Arief Hidayat --- scripts/get | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/scripts/get b/scripts/get index 4daf504da..5479abddb 100755 --- a/scripts/get +++ b/scripts/get @@ -77,32 +77,17 @@ verifySupported() { # checkDesiredVersion checks if the desired version is available. checkDesiredVersion() { - # Use the GitHub releases webpage for the project to find the desired version for this project. - local latest_release_url="https://github.com/helm/helm/releases/latest" - local release_url if [ "x$DESIRED_VERSION" == "x" ]; then + # Get tag from release URL + local latest_release_url="https://github.com/helm/helm/releases/latest" if type "curl" > /dev/null; then - release_url=$(curl -Ls -o /dev/null -w %{url_effective} $latest_release_url) + TAG=$(curl -Ls -o /dev/null -w %{url_effective} $latest_release_url | grep -oE "[^/]+$" ) elif type "wget" > /dev/null; then - release_url=$(wget $latest_release_url --server-response -O /dev/null 2>&1 | awk '/^ Location: /{DEST=$2} END{ print DEST}') + TAG=$(wget $latest_release_url --server-response -O /dev/null 2>&1 | awk '/^ Location: /{DEST=$2} END{ print DEST}' | grep -oE "[^/]+$") fi else - release_url="https://github.com/helm/helm/releases/${DESIRED_VERSION}" + TAG=$DESIRED_VERSION fi - - local status_code - if type "curl" > /dev/null; then - status_code=$(curl --write-out %{http_code} --silent --output /dev/null $release_url) - elif type "wget" > /dev/null; then - status_code=$(wget --spider -S $release_url -O /dev/null 2>&1 | grep "HTTP/" | awk '{print $2}') - fi - - if [[ "$status_code" -ne 200 ]] ; then - echo "Cannot determine ${DESIRED_VERSION} tag." - exit 1 - fi - - TAG=$(echo $release_url | grep -oE "[^/]+$" ) } # checkHelmInstalledVersion checks which version of helm is installed and From 175bb2e4c4aded1f291cfc59d7ce6f63c076b6f4 Mon Sep 17 00:00:00 2001 From: Devin Burnette Date: Sat, 23 Mar 2019 01:54:46 -0400 Subject: [PATCH 54/57] remove kubernetes Signed-off-by: Devin Burnette --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9716d0ce..fc35e0643 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # 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 From 470203a173942dac23396dbba575cc9b16253486 Mon Sep 17 00:00:00 2001 From: ialidzhikov Date: Sun, 24 Mar 2019 23:17:46 +0200 Subject: [PATCH 55/57] Update golang version Signed-off-by: ialidzhikov --- .circleci/config.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c83ee10cf..7bba262a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,7 +4,7 @@ jobs: working_directory: /go/src/k8s.io/helm parallelism: 3 docker: - - image: golang:1.12 + - image: golang:1.12.1 environment: PROJECT_NAME: "kubernetes-helm" steps: diff --git a/Makefile b/Makefile index f4b08ace8..3584521a4 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ DOCKER_REGISTRY ?= gcr.io IMAGE_PREFIX ?= kubernetes-helm -DEV_IMAGE ?= golang:1.12 +DEV_IMAGE ?= golang:1.12.1 SHORT_NAME ?= tiller SHORT_NAME_RUDDER ?= rudder TARGETS ?= darwin/amd64 linux/amd64 linux/386 linux/arm linux/arm64 linux/ppc64le linux/s390x windows/amd64 From 535f9cece5c4147c74a88106f83690b197806dfa Mon Sep 17 00:00:00 2001 From: Pavel Eremeev Date: Mon, 25 Mar 2019 12:02:44 +0000 Subject: [PATCH 56/57] refactor(*): update error message Signed-off-by: Pavel Eremeev --- pkg/kube/client.go | 9 ++++++--- pkg/kube/client_test.go | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 3830c4eef..37c1d53e4 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -334,11 +334,14 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader originalInfo := original.Get(info) - // Resource exists in the current cluster state, but not in the current helm configuration - // See: https://github.com/helm/helm/issues/1193 for more 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 { return fmt.Errorf( - "%s %q is not managed by Helm; delete the resource from the current cluster state to let Helm manage it", + "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, ) diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 5bd9449b7..401ac7e58 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -253,7 +253,7 @@ func TestUpdateNonManagedResourceError(t *testing.T) { } if err := c.Update(v1.NamespaceDefault, objBody(¤t), objBody(&target), false, false, 0, false); err != nil { - if err.Error() != "Pod \"starfish\" is not managed by Helm; delete the resource from the current cluster state to let Helm manage it" { + 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 { From 3c871c0030866519805ee360ae58037cf2129a88 Mon Sep 17 00:00:00 2001 From: Matthew Fisher Date: Tue, 26 Mar 2019 10:51:40 -0700 Subject: [PATCH 57/57] chore(glide): bump kubernetes to 1.14 Signed-off-by: Matthew Fisher --- cmd/helm/installer/uninstall.go | 4 +- glide.lock | 128 +++++++++++++++------ glide.yaml | 14 +-- pkg/kube/client.go | 4 +- pkg/kube/client_test.go | 4 +- pkg/kube/result.go | 2 +- pkg/kube/result_test.go | 2 +- pkg/tiller/environment/environment.go | 4 +- pkg/tiller/environment/environment_test.go | 4 +- pkg/tiller/release_server_test.go | 4 +- 10 files changed, 115 insertions(+), 55 deletions(-) diff --git a/cmd/helm/installer/uninstall.go b/cmd/helm/installer/uninstall.go index 87fbd4050..b1d78004e 100644 --- a/cmd/helm/installer/uninstall.go +++ b/cmd/helm/installer/uninstall.go @@ -31,13 +31,13 @@ const ( // Uninstall uses Kubernetes client to uninstall Tiller. 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 } if err := deleteDeployment(client, opts.Namespace); err != nil { return err } - return deleteSecret(client.Core(), opts.Namespace) + return deleteSecret(client.CoreV1(), opts.Namespace) } // deleteService deletes the Tiller Service resource diff --git a/glide.lock b/glide.lock index 824e30041..eedbd9381 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: f86919aea9f9b6df70967eb0b00d8a3807a2f5e924d7bd82d317f7969fddb3ef -updated: 2019-03-17T20:36:59.222397-07:00 +hash: 9a8f0b6c906f605bb879fbcdf0c122096f7698fe6a975ec4e6648f2ee85fce3e +updated: 2019-03-26T10:33:38.977361532-07:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -84,6 +84,10 @@ imports: version: 449fdfce4d962303d702fec724ef0ad181c92528 subpackages: - spdy +- name: github.com/emicklei/go-restful + version: ff4f55a206334ef123e4f79bbf348980da81ca46 + subpackages: + - log - name: github.com/evanphx/json-patch version: 5858425f75500d40c52783dce87d085a483ce135 - name: github.com/exponent-io/jsonpath @@ -91,7 +95,7 @@ imports: - name: github.com/fatih/camelcase version: f6a740d52f961c60348ebb109adde9f4635d7540 - name: github.com/ghodss/yaml - version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee + version: c7ce16629ff4cd059ed96ed06419dd3856fd3577 - name: github.com/go-openapi/jsonpointer version: ef5f0afec364d3b9396b7b77b43dbe26bf1f8004 - name: github.com/go-openapi/jsonreference @@ -130,7 +134,7 @@ imports: - name: github.com/google/btree version: 7d79101e329e5a3adf994758c578dab82b90c017 - name: github.com/google/gofuzz - version: 44d81051d367757e1c7c6a5a86423ece9afcf63c + version: 24818f796faf91cd76ec7bddd72458fbced7a6c1 - name: github.com/google/uuid version: 064e2069ce9c359c118179501254f67d7d37ba24 - name: github.com/googleapis/gnostic @@ -140,7 +144,7 @@ imports: - compiler - extensions - name: github.com/gophercloud/gophercloud - version: 781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d + version: c818fa66e4c88b30db28038fe3f18f2f4a0db9a8 subpackages: - openstack - openstack/identity/v2/tenants @@ -160,7 +164,7 @@ imports: - name: github.com/grpc-ecosystem/go-grpc-prometheus version: 0c1b191dbfe51efdabe3c14b9f6f3b96429e0722 - name: github.com/hashicorp/golang-lru - version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 + version: 20f1fb78b0740ba8c3cb143a61e86ba5c8669768 subpackages: - simplelru - name: github.com/huandu/xstrings @@ -171,6 +175,8 @@ imports: version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 - name: github.com/json-iterator/go version: ab8a2e0c74be9d3be70b3184d9acc634935ded82 +- name: github.com/liggitt/tabwriter + version: 89fcab3d43de07060e4fd4c1547430ed57e87f24 - name: github.com/mailru/easyjson version: 2f5df55504ebc322e4d52d34df6a1f5b503bf26d subpackages: @@ -215,7 +221,7 @@ imports: subpackages: - go - name: github.com/prometheus/common - version: 13ba4ddd0caa9c28ca7b7bffe1dfa9ed8d5ef207 + version: cfeb6f9992ffa54aaa4f2170ade4067ee478b250 subpackages: - expfmt - internal/bitbucket.org/ww/goautoneg @@ -259,15 +265,15 @@ imports: - scrypt - ssh/terminal - name: golang.org/x/net - version: 0ed95abb35c445290478a5348a7b38bb154135fd + version: 65e2d4e15006aab9813ff8769e768bbf4bb667a0 subpackages: - context - context/ctxhttp + - http/httpguts - http2 - http2/hpack - idna - internal/timeseries - - lex/httplex - trace - name: golang.org/x/oauth2 version: a6bd8cefa1811bd24b86f8902872e4e8225f74c4 @@ -368,12 +374,11 @@ imports: - json - jwt - name: gopkg.in/yaml.v2 - version: 670d4cfef0544295bc27a114dbac37980d83185a + version: 5420a8b6744d3b0345ab293f6fcba19c978f1183 - name: k8s.io/api - version: 5cb15d34447165a97c76ed5a60e4e99c8a01ecfe + version: 40a48860b5abbba9aa891b02b32da429b08d96a0 subpackages: - admission/v1beta1 - - admissionregistration/v1alpha1 - admissionregistration/v1beta1 - apps/v1 - apps/v1beta1 @@ -390,16 +395,21 @@ imports: - batch/v1beta1 - batch/v2alpha1 - certificates/v1beta1 + - coordination/v1 - coordination/v1beta1 - core/v1 - events/v1beta1 - extensions/v1beta1 - imagepolicy/v1alpha1 - networking/v1 + - networking/v1beta1 + - node/v1alpha1 + - node/v1beta1 - policy/v1beta1 - rbac/v1 - rbac/v1alpha1 - rbac/v1beta1 + - scheduling/v1 - scheduling/v1alpha1 - scheduling/v1beta1 - settings/v1alpha1 @@ -407,11 +417,11 @@ imports: - storage/v1alpha1 - storage/v1beta1 - name: k8s.io/apiextensions-apiserver - version: d002e88f6236312f0289d9d1deab106751718ff0 + version: 53c4693659ed354d76121458fb819202dd1635fa subpackages: - pkg/features - name: k8s.io/apimachinery - version: 86fb29eff6288413d76bd8506874fddd9fccdff0 + version: d7deff9243b165ee192f5551710ea4285dcfd615 subpackages: - pkg/api/equality - pkg/api/errors @@ -467,7 +477,7 @@ imports: - third_party/forked/golang/netutil - third_party/forked/golang/reflect - name: k8s.io/apiserver - version: 79427f02047f9189a75b8cdaadccaf65a126853e + version: 8b27c41bdbb11ff103caa673315e097bf0289171 subpackages: - pkg/authentication/authenticator - pkg/authentication/serviceaccount @@ -475,23 +485,31 @@ imports: - pkg/features - pkg/util/feature - name: k8s.io/cli-runtime - version: a9e421a7932607ce4623ff45add8274499cca193 + version: 2899ed30580fdbc8286718edb4382b529463099d subpackages: - pkg/genericclioptions - - pkg/genericclioptions/printers - - pkg/genericclioptions/resource + - pkg/kustomize + - 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 - version: b40b2a5939e43f7ffe0028ad67586b7ce50bb675 + version: 6ee68ca5fd8355d024d02f9db0b3b667e8357a0f subpackages: - discovery + - discovery/cached/disk - discovery/fake - dynamic - dynamic/fake - kubernetes - kubernetes/fake - kubernetes/scheme - - kubernetes/typed/admissionregistration/v1alpha1 - - kubernetes/typed/admissionregistration/v1alpha1/fake - kubernetes/typed/admissionregistration/v1beta1 - kubernetes/typed/admissionregistration/v1beta1/fake - kubernetes/typed/apps/v1 @@ -524,6 +542,8 @@ imports: - kubernetes/typed/batch/v2alpha1/fake - kubernetes/typed/certificates/v1beta1 - kubernetes/typed/certificates/v1beta1/fake + - kubernetes/typed/coordination/v1 + - kubernetes/typed/coordination/v1/fake - kubernetes/typed/coordination/v1beta1 - kubernetes/typed/coordination/v1beta1/fake - kubernetes/typed/core/v1 @@ -534,6 +554,12 @@ imports: - kubernetes/typed/extensions/v1beta1/fake - kubernetes/typed/networking/v1 - 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/fake - kubernetes/typed/rbac/v1 @@ -542,6 +568,8 @@ imports: - kubernetes/typed/rbac/v1alpha1/fake - kubernetes/typed/rbac/v1beta1 - kubernetes/typed/rbac/v1beta1/fake + - kubernetes/typed/scheduling/v1 + - kubernetes/typed/scheduling/v1/fake - kubernetes/typed/scheduling/v1alpha1 - kubernetes/typed/scheduling/v1alpha1/fake - kubernetes/typed/scheduling/v1beta1 @@ -588,30 +616,35 @@ imports: - tools/pager - tools/portforward - tools/record + - tools/record/util - tools/reference - tools/remotecommand - tools/watch - transport - transport/spdy - - util/buffer - util/cert - util/connrotation - util/exec - util/flowcontrol - util/homedir - - util/integer - util/jsonpath + - util/keyutil - util/retry +- name: k8s.io/cloud-provider + version: 9c9d72d1bf90eb62005f5112f3eea019b272c44b + subpackages: + - features - name: k8s.io/klog - version: 8139d8cb77af419532b33dfa7dd09fbc5f1d344f + version: 8e90cee79f823779174776412c13478955131846 - name: k8s.io/kube-openapi - version: c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d + version: b3a7cee44a305be0a69e1b9ac03018307287e1b0 subpackages: + - pkg/common - pkg/util/proto - pkg/util/proto/testing - pkg/util/proto/validation - name: k8s.io/kubernetes - version: f2c8f1cadf1808ec28476682e49a3cce2b09efbf + version: b805719a99126e54bcbc0a3d9ee8a45cd7e85632 subpackages: - pkg/api/legacyscheme - pkg/api/service @@ -644,6 +677,7 @@ imports: - pkg/apis/certificates/v1beta1 - pkg/apis/coordination - pkg/apis/coordination/install + - pkg/apis/coordination/v1 - pkg/apis/coordination/v1beta1 - pkg/apis/core - pkg/apis/core/helper @@ -659,6 +693,7 @@ imports: - pkg/apis/extensions/install - pkg/apis/extensions/v1beta1 - pkg/apis/networking + - pkg/apis/node - pkg/apis/policy - pkg/apis/policy/install - pkg/apis/policy/v1beta1 @@ -669,6 +704,7 @@ imports: - pkg/apis/rbac/v1beta1 - pkg/apis/scheduling - pkg/apis/scheduling/install + - pkg/apis/scheduling/v1 - pkg/apis/scheduling/v1alpha1 - pkg/apis/scheduling/v1beta1 - pkg/apis/settings @@ -713,30 +749,54 @@ imports: - pkg/kubectl/util/templates - pkg/kubectl/util/term - pkg/kubectl/validation - - pkg/kubelet/apis - pkg/kubelet/types - pkg/master/ports - pkg/printers - pkg/printers/internalversion - - pkg/scheduler/api - pkg/security/apparmor - pkg/serviceaccount - - pkg/util/file - pkg/util/hash - pkg/util/interrupt - pkg/util/labels - - pkg/util/net/sets - pkg/util/node - pkg/util/parsers - pkg/util/taints - pkg/version - name: k8s.io/utils - version: 66066c83e385e385ccc3c964b44fd7dcd413d0ed + version: c2654d5206da6b7b6ace12841e8f359bb89b443c subpackages: - - clock + - buffer - exec - - exec/testing + - integer + - net + - path - 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 version: fd68e9863619f6ec2fdd8625fe1f02e7c877e480 - name: vbom.ml/util @@ -745,7 +805,7 @@ imports: - sortorder testImports: - name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + version: 5d4384ee4fb2527b0a1256a821ebfc92f91efefc subpackages: - difflib - name: github.com/stretchr/testify diff --git a/glide.yaml b/glide.yaml index 23a3cdaf4..8600ed0ac 100644 --- a/glide.yaml +++ b/glide.yaml @@ -51,19 +51,19 @@ import: version: 0.8.0 - package: github.com/grpc-ecosystem/go-grpc-prometheus - package: k8s.io/kubernetes - version: release-1.13 + version: release-1.14 - package: k8s.io/client-go - version: kubernetes-1.13.4 + version: kubernetes-1.14.0 - package: k8s.io/api - version: kubernetes-1.13.4 + version: kubernetes-1.14.0 - package: k8s.io/apimachinery - version: kubernetes-1.13.4 + version: kubernetes-1.14.0 - package: k8s.io/apiserver - version: kubernetes-1.13.4 + version: kubernetes-1.14.0 - package: k8s.io/cli-runtime - version: kubernetes-1.13.4 + version: kubernetes-1.14.0 - package: k8s.io/apiextensions-apiserver - version: kubernetes-1.13.4 + version: kubernetes-1.14.0 - package: github.com/cyphar/filepath-securejoin version: ^0.2.1 diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 37c1d53e4..66c822ebd 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -47,7 +47,7 @@ import ( "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/watch" "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" watchtools "k8s.io/client-go/tools/watch" "k8s.io/kubernetes/pkg/api/legacyscheme" @@ -74,7 +74,7 @@ type Client struct { // New creates a new Client. func New(getter genericclioptions.RESTClientGetter) *Client { if getter == nil { - getter = genericclioptions.NewConfigFlags() + getter = genericclioptions.NewConfigFlags(true) } return &Client{ Factory: cmdutil.NewFactory(getter), diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 401ac7e58..a41490f9b 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -25,11 +25,11 @@ import ( "strings" "testing" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "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/rest/fake" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" diff --git a/pkg/kube/result.go b/pkg/kube/result.go index cc222a66f..cf4a4195e 100644 --- a/pkg/kube/result.go +++ b/pkg/kube/result.go @@ -16,7 +16,7 @@ limitations under the License. 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. type Result []*resource.Info diff --git a/pkg/kube/result_test.go b/pkg/kube/result_test.go index c4cf989b8..d4c18ee6a 100644 --- a/pkg/kube/result_test.go +++ b/pkg/kube/result_test.go @@ -21,7 +21,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/cli-runtime/pkg/genericclioptions/resource" + "k8s.io/cli-runtime/pkg/resource" ) func TestResult(t *testing.T) { diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go index 290337d7b..dca7c0756 100644 --- a/pkg/tiller/environment/environment.go +++ b/pkg/tiller/environment/environment.go @@ -26,8 +26,8 @@ import ( "io" "time" - "k8s.io/api/core/v1" - "k8s.io/cli-runtime/pkg/genericclioptions/resource" + v1 "k8s.io/api/core/v1" + "k8s.io/cli-runtime/pkg/resource" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/engine" diff --git a/pkg/tiller/environment/environment_test.go b/pkg/tiller/environment/environment_test.go index 5c19a9b21..9e9b549d4 100644 --- a/pkg/tiller/environment/environment_test.go +++ b/pkg/tiller/environment/environment_test.go @@ -22,8 +22,8 @@ import ( "testing" "time" - "k8s.io/api/core/v1" - "k8s.io/cli-runtime/pkg/genericclioptions/resource" + v1 "k8s.io/api/core/v1" + "k8s.io/cli-runtime/pkg/resource" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/kube" diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index 4e29e4413..ecf5ffd17 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -31,8 +31,8 @@ import ( "github.com/technosophos/moniker" "golang.org/x/net/context" "google.golang.org/grpc/metadata" - "k8s.io/api/core/v1" - "k8s.io/cli-runtime/pkg/genericclioptions/resource" + v1 "k8s.io/api/core/v1" + "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/kubernetes/fake" "k8s.io/helm/pkg/helm"