From 27c3ff595a6ec7aad28bba27a37cf782b83528d7 Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Mon, 20 Mar 2017 18:21:15 -0600 Subject: [PATCH] fix(tiller): fix helm status failure on missing resource This fixes a bug in which 'helm status' fails if any of the expected resources are missing in Kubernetes. Now it prints a list of missing resources at the end of the status report. Closes #2118 --- pkg/kube/client.go | 11 ++++++++++- pkg/kube/client_test.go | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/pkg/kube/client.go b/pkg/kube/client.go index a43627416..a4d1e086d 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -151,11 +151,14 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { if err != nil { return "", err } + missing := []string{} err = perform(c, namespace, infos, func(info *resource.Info) error { log.Printf("Doing get for: '%s'", info.Name) obj, err := resource.NewHelper(info.Client, info.Mapping).Get(info.Namespace, info.Name, info.Export) if err != nil { - return err + log.Printf("WARNING: Failed Get for resource %q: %s", info.Name, err) + missing = append(missing, fmt.Sprintf("%v\t\t%s", info.Mapping.Resource, info.Name)) + return nil } // We need to grab the ObjectReference so we can correctly group the objects. or, err := api.GetReference(obj) @@ -194,6 +197,12 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { return "", err } } + if len(missing) > 0 { + buf.WriteString("==> MISSING\nKIND\t\tNAME\n") + for _, s := range missing { + fmt.Fprintln(buf, s) + } + } return buf.String(), nil } diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go index 8a9980abb..02736f3bf 100644 --- a/pkg/kube/client_test.go +++ b/pkg/kube/client_test.go @@ -59,6 +59,7 @@ func newPodWithStatus(name string, status api.PodStatus, namespace string) api.P ObjectMeta: api.ObjectMeta{ Name: name, Namespace: ns, + SelfLink: "/api/v1/namespaces/default/pods/" + name, }, Spec: api.PodSpec{ Containers: []api.Container{{ @@ -279,6 +280,49 @@ func TestBuild(t *testing.T) { } } +func TestGet(t *testing.T) { + list := newPodList("starfish", "otter") + f, tf, _, ns := cmdtesting.NewAPIFactory() + tf.Client = &fake.RESTClient{ + NegotiatedSerializer: ns, + Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + p, m := req.URL.Path, req.Method + //actions = append(actions, p+":"+m) + t.Logf("got request %s %s", p, m) + switch { + case p == "/namespaces/default/pods/starfish" && m == "GET": + return newResponse(404, notFoundBody()) + case p == "/namespaces/default/pods/otter" && m == "GET": + return newResponse(200, &list.Items[1]) + default: + t.Fatalf("unexpected request: %s %s", req.Method, req.URL.Path) + return nil, nil + } + }), + } + c := &Client{Factory: f} + + // Test Success + data := strings.NewReader("kind: Pod\napiVersion: v1\nmetadata:\n name: otter") + o, err := c.Get("default", data) + if err != nil { + t.Errorf("Expected missing results, got %q", err) + } + if !strings.Contains(o, "==> v1/Pod") && !strings.Contains(o, "otter") { + t.Errorf("Expected v1/Pod otter, got %s", o) + } + + // Test failure + data = strings.NewReader("kind: Pod\napiVersion: v1\nmetadata:\n name: starfish") + o, err = c.Get("default", data) + if err != nil { + t.Errorf("Expected missing results, got %q", err) + } + if !strings.Contains(o, "MISSING") && !strings.Contains(o, "pods\t\tstarfish") { + t.Errorf("Expected missing starfish, got %s", o) + } +} + func TestPerform(t *testing.T) { tests := []struct { name string