From a439c2faadd24a54f623e023c552184ab6298b63 Mon Sep 17 00:00:00 2001 From: sarvani mounika Date: Wed, 4 Mar 2020 11:37:58 +0000 Subject: [PATCH] Supporting helm3 to show up resource names that were deployed as part of release in helm status command Signed-off-by: sarvani mounika --- cmd/helm/status.go | 4 +- cmd/helm/testdata/output/status.json | 2 +- go.mod | 1 - go.sum | 2 + pkg/action/status.go | 15 ++++++- pkg/kube/client.go | 63 ++++++++++++++++++++++++++++ pkg/kube/fake/printer.go | 8 ++++ pkg/kube/interface.go | 2 + pkg/release/release.go | 2 + 9 files changed, 94 insertions(+), 5 deletions(-) diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 34543c6cb..6c0ca6593 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -114,7 +114,9 @@ func (s statusPrinter) WriteTable(out io.Writer) error { fmt.Fprintf(out, "NAMESPACE: %s\n", s.release.Namespace) fmt.Fprintf(out, "STATUS: %s\n", s.release.Info.Status.String()) fmt.Fprintf(out, "REVISION: %d\n", s.release.Version) - + if len(s.release.Resources) > 0 && s.release.Resources != "\n" { + fmt.Fprintf(out, "RESOURCES: %s\n", s.release.Resources) + } executions := executionsByHookEvent(s.release) if tests, ok := executions[release.HookTest]; !ok || len(tests) == 0 { fmt.Fprintln(out, "TEST SUITE: None") diff --git a/cmd/helm/testdata/output/status.json b/cmd/helm/testdata/output/status.json index 4b499c935..17c237356 100644 --- a/cmd/helm/testdata/output/status.json +++ b/cmd/helm/testdata/output/status.json @@ -1 +1 @@ -{"name":"flummoxed-chickadee","info":{"first_deployed":"","last_deployed":"2016-01-16T00:00:00Z","deleted":"","status":"deployed","notes":"release notes"},"namespace":"default"} +{"name":"flummoxed-chickadee","info":{"first_deployed":"","last_deployed":"2016-01-16T00:00:00Z","deleted":"","status":"deployed","notes":"release notes"},"namespace":"default","Resources":"\n"} diff --git a/go.mod b/go.mod index 4e3bcf9a1..7ba7a5542 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,6 @@ require ( github.com/stretchr/testify v1.4.0 github.com/xeipuuv/gojsonschema v1.1.0 golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d - honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect k8s.io/api v0.17.3 k8s.io/apiextensions-apiserver v0.17.3 k8s.io/apimachinery v0.17.3 diff --git a/go.sum b/go.sum index 39b57b4f2..140a74761 100644 --- a/go.sum +++ b/go.sum @@ -78,6 +78,7 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0Bsq github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -678,4 +679,5 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:w sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc h1:MksmcCZQWAQJCTA5T0jgI/0sJ51AVm4Z41MrmfczEoc= vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI= diff --git a/pkg/action/status.go b/pkg/action/status.go index a0c7f6e21..e2ae36b28 100644 --- a/pkg/action/status.go +++ b/pkg/action/status.go @@ -17,6 +17,8 @@ limitations under the License. package action import ( + "bytes" + "helm.sh/helm/v3/pkg/release" ) @@ -41,6 +43,15 @@ func (s *Status) Run(name string) (*release.Release, error) { if err := s.cfg.KubeClient.IsReachable(); err != nil { return nil, err } - - return s.cfg.releaseContent(name, s.Version) + rel, err := s.cfg.releaseContent(name, s.Version) + if err != nil { + return nil, err + } + resources, _ := s.cfg.KubeClient.Build(bytes.NewBufferString(rel.Manifest), true) + resp, err := s.cfg.KubeClient.Get(resources) + if err != nil { + return nil, err + } + rel.Resources = "\n" + resp + return rel, nil } diff --git a/pkg/kube/client.go b/pkg/kube/client.go index b761c6d12..4c71ea849 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -17,6 +17,7 @@ limitations under the License. package kube // import "helm.sh/helm/v3/pkg/kube" import ( + "bytes" "context" "encoding/json" "fmt" @@ -35,6 +36,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -43,8 +45,10 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/resource" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" cachetools "k8s.io/client-go/tools/cache" watchtools "k8s.io/client-go/tools/watch" + "k8s.io/kubectl/pkg/cmd/get" cmdutil "k8s.io/kubectl/pkg/cmd/util" ) @@ -105,6 +109,64 @@ func (c *Client) Create(resources ResourceList) (*Result, error) { return &Result{Created: resources}, nil } +func transformRequests(req *rest.Request) { + group := metav1beta1.GroupName + version := metav1beta1.SchemeGroupVersion.Version + + tableParam := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group) + req.SetHeader("Accept", tableParam) + + // if sorting, ensure we receive the full object in order to introspect its fields via jsonpath + req.Param("includeObject", "Object") +} + +func (c *Client) Get(resources ResourceList) (string, error) { + buf := new(bytes.Buffer) + printFlags := get.NewHumanPrintFlags() + typePrinter, _ := printFlags.ToPrinter("") + printer := &get.TablePrinter{Delegate: typePrinter} + objs := make(map[string][]runtime.Object) + err := resources.Visit(func(info *resource.Info, err error) error { + if err != nil { + return err + } + gvk := info.ResourceMapping().GroupVersionKind + vk := gvk.Version + "/" + gvk.Kind + obj, err := getResource(info) + if err != nil { + return err + } + objs[vk] = append(objs[vk], obj) + return nil + }) + if err != nil { + return "", err + } + for t, ot := range objs { + if _, err = fmt.Fprintf(buf, "==> %s\n", t); err != nil { + return "", err + } + for _, o := range ot { + if err := printer.PrintObj(o, buf); err != nil { + c.Log("failed to print object type %s, object: %q :\n %v", t, o, err) + return "", err + } + } + if _, err := buf.WriteString("\n"); err != nil { + return "", err + } + } + return buf.String(), nil +} + +func getResource(info *resource.Info) (runtime.Object, error) { + obj, err := resource.NewHelper(info.Client, info.Mapping).Get(info.Namespace, info.Name, false) + if err != nil { + return nil, err + } + return obj, nil +} + // Wait up to the given timeout for the specified resources to be ready func (c *Client) Wait(resources ResourceList, timeout time.Duration) error { cs, err := c.Factory.KubernetesClientSet() @@ -148,6 +210,7 @@ func (c *Client) Build(reader io.Reader, validate bool) (ResourceList, error) { Unstructured(). Schema(schema). Stream(reader, ""). + TransformRequests(transformRequests). Do().Infos() return result, scrubValidationError(err) } diff --git a/pkg/kube/fake/printer.go b/pkg/kube/fake/printer.go index 58b389ab5..d200b0309 100644 --- a/pkg/kube/fake/printer.go +++ b/pkg/kube/fake/printer.go @@ -47,6 +47,14 @@ func (p *PrintingKubeClient) Create(resources kube.ResourceList) (*kube.Result, return &kube.Result{Created: resources}, nil } +func (p *PrintingKubeClient) Get(resources kube.ResourceList) (string, error) { + _, err := io.Copy(p.Out, bufferize(resources)) + if err != nil { + return "", err + } + return "", nil +} + func (p *PrintingKubeClient) Wait(resources kube.ResourceList, _ time.Duration) error { _, err := io.Copy(p.Out, bufferize(resources)) return err diff --git a/pkg/kube/interface.go b/pkg/kube/interface.go index 4bf61211e..3aa4e3cf9 100644 --- a/pkg/kube/interface.go +++ b/pkg/kube/interface.go @@ -61,6 +61,8 @@ type Interface interface { // isReachable checks whether the client is able to connect to the cluster IsReachable() error + + Get(resources ResourceList) (string, error) } var _ Interface = (*Client)(nil) diff --git a/pkg/release/release.go b/pkg/release/release.go index a436998aa..bf1556f10 100644 --- a/pkg/release/release.go +++ b/pkg/release/release.go @@ -37,6 +37,8 @@ type Release struct { Version int `json:"version,omitempty"` // Namespace is the kubernetes namespace of the release. Namespace string `json:"namespace,omitempty"` + + Resources string } // SetStatus is a helper for setting the status on a release.