From 7c01a28c5cda4f5587099ad3424787fad1fbc4b4 Mon Sep 17 00:00:00 2001 From: Adam Reese Date: Thu, 30 Jun 2016 15:02:12 -0700 Subject: [PATCH] test(cmd): add unit tests for get command --- cmd/helm/get.go | 108 +++--------------------------------- cmd/helm/get_manifest.go | 70 +++++++++++++++++++++++ cmd/helm/get_test.go | 49 ++++++++++++++++ cmd/helm/get_values.go | 84 ++++++++++++++++++++++++++++ cmd/helm/get_values_test.go | 49 ++++++++++++++++ cmd/helm/helm_test.go | 70 +++++++++++++++++++++++ cmd/helm/list_test.go | 48 ++-------------- 7 files changed, 334 insertions(+), 144 deletions(-) create mode 100644 cmd/helm/get_manifest.go create mode 100644 cmd/helm/get_test.go create mode 100644 cmd/helm/get_values.go create mode 100644 cmd/helm/get_values_test.go create mode 100644 cmd/helm/helm_test.go diff --git a/cmd/helm/get.go b/cmd/helm/get.go index ab3ef238e..6238773e1 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -42,18 +42,6 @@ By default, this prints a human readable collection of information about the chart, the supplied values, and the generated manifest file. ` -var getValuesHelp = ` -This command downloads a values file for a given release. -` - -var getManifestHelp = ` -This command fetches the generated manifest for a given release. - -A manifest is a YAML-encoded representation of the Kubernetes resources that -were generated from this release's chart(s). If a chart is dependent on other -charts, those resources will also be included in the manifest. -` - var errReleaseRequired = errors.New("release name is required") type getCmd struct { @@ -68,74 +56,29 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { client: client, } cmd := &cobra.Command{ - Use: "get [flags] RELEASE_NAME", - Short: "download a named release", - Long: getHelp, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return errReleaseRequired - } - get.release = args[0] - return get.run() - }, + Use: "get [flags] RELEASE_NAME", + Short: "download a named release", + Long: getHelp, PersistentPreRunE: setupConnection, - } - cmd.AddCommand(newGetValuesCmd(client, out)) - cmd.AddCommand(newGetManifestCmd(client, out)) - return cmd -} - -type getValuesCmd struct { - allValues bool - getCmd -} - -func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command { - get := &getValuesCmd{} - get.out = out - get.client = client - cmd := &cobra.Command{ - Use: "values [flags] RELEASE_NAME", - Short: "download the values file for a named release", - Long: getValuesHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errReleaseRequired } get.release = args[0] - return get.run() - }, - } - cmd.Flags().BoolVarP(&get.allValues, "all", "a", false, "dump all (computed) values") - return cmd -} - -type getManifestCmd struct { - getCmd -} - -func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command { - get := &getManifestCmd{} - get.out = out - get.client = client - cmd := &cobra.Command{ - Use: "manifest [flags] RELEASE_NAME", - Short: "download the manifest for a named release", - Long: getManifestHelp, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return errReleaseRequired + if get.client == nil { + get.client = helm.NewClient(helm.HelmHost(helm.Config.ServAddr)) } - get.release = args[0] return get.run() }, } + cmd.AddCommand(newGetValuesCmd(client, out)) + cmd.AddCommand(newGetManifestCmd(client, out)) return cmd } // getCmd is the command that implements 'helm get' func (g *getCmd) run() error { - res, err := helm.GetReleaseContent(g.release) + res, err := g.client.ReleaseContent(g.release) if err != nil { return prettyError(err) } @@ -159,38 +102,3 @@ func (g *getCmd) run() error { fmt.Fprintln(g.out, res.Release.Manifest) return nil } - -// getValues implements 'helm get values' -func (g *getValuesCmd) run() error { - res, err := helm.GetReleaseContent(g.release) - if err != nil { - return prettyError(err) - } - - // If the user wants all values, compute the values and return. - if g.allValues { - cfg, err := chartutil.CoalesceValues(res.Release.Chart, res.Release.Config, nil) - if err != nil { - return err - } - cfgStr, err := cfg.YAML() - if err != nil { - return err - } - fmt.Fprintln(g.out, cfgStr) - return nil - } - - fmt.Fprintln(g.out, res.Release.Config.Raw) - return nil -} - -// getManifest implements 'helm get manifest' -func (g *getManifestCmd) run() error { - res, err := helm.GetReleaseContent(g.release) - if err != nil { - return prettyError(err) - } - fmt.Fprintln(g.out, res.Release.Manifest) - return nil -} diff --git a/cmd/helm/get_manifest.go b/cmd/helm/get_manifest.go new file mode 100644 index 000000000..21a76155c --- /dev/null +++ b/cmd/helm/get_manifest.go @@ -0,0 +1,70 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 main + +import ( + "fmt" + "io" + + "github.com/spf13/cobra" + + "k8s.io/helm/pkg/helm" +) + +var getManifestHelp = ` +This command fetches the generated manifest for a given release. + +A manifest is a YAML-encoded representation of the Kubernetes resources that +were generated from this release's chart(s). If a chart is dependent on other +charts, those resources will also be included in the manifest. +` + +type getManifestCmd struct { + release string + out io.Writer + client helm.Interface +} + +func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command { + get := &getManifestCmd{ + out: out, + client: client, + } + cmd := &cobra.Command{ + Use: "manifest [flags] RELEASE_NAME", + Short: "download the manifest for a named release", + Long: getManifestHelp, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errReleaseRequired + } + get.release = args[0] + return get.run() + }, + } + return cmd +} + +// getManifest implements 'helm get manifest' +func (g *getManifestCmd) run() error { + res, err := helm.GetReleaseContent(g.release) + if err != nil { + return prettyError(err) + } + fmt.Fprintln(g.out, res.Release.Manifest) + return nil +} diff --git a/cmd/helm/get_test.go b/cmd/helm/get_test.go new file mode 100644 index 000000000..3bfb56017 --- /dev/null +++ b/cmd/helm/get_test.go @@ -0,0 +1,49 @@ +package main + +import ( + "bytes" + "testing" + + "k8s.io/helm/pkg/helm" + "k8s.io/helm/pkg/proto/hapi/release" +) + +func TestGetCmd(t *testing.T) { + tests := []struct { + name string + args []string + client helm.Interface + expected string + err bool + }{ + { + name: "with a release", + client: &fakeReleaseClient{ + rels: []*release.Release{ + releaseMock("thomas-guide"), + }, + }, + args: []string{"thomas-guide"}, + expected: "CHART: foo-0.1.0-beta.1\nRELEASED: Fri Sep 2 15:04:05 1977\nUSER-SUPPLIED VALUES:\nname: \"value\"\nCOMPUTED VALUES:\nname: value\n\nMANIFEST:", + }, + { + name: "requires release name arg", + client: &fakeReleaseClient{}, + err: true, + }, + } + + var buf bytes.Buffer + for _, tt := range tests { + cmd := newGetCmd(tt.client, &buf) + err := cmd.RunE(cmd, tt.args) + if (err != nil) != tt.err { + t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err) + } + actual := string(bytes.TrimSpace(buf.Bytes())) + if actual != tt.expected { + t.Errorf("%q. expected %q, got %q", tt.name, tt.expected, actual) + } + buf.Reset() + } +} diff --git a/cmd/helm/get_values.go b/cmd/helm/get_values.go new file mode 100644 index 000000000..3765e762c --- /dev/null +++ b/cmd/helm/get_values.go @@ -0,0 +1,84 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 main + +import ( + "fmt" + "io" + + "github.com/spf13/cobra" + + "k8s.io/helm/pkg/chartutil" + "k8s.io/helm/pkg/helm" +) + +var getValuesHelp = ` +This command downloads a values file for a given release. +` + +type getValuesCmd struct { + release string + allValues bool + out io.Writer + client helm.Interface +} + +func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command { + get := &getValuesCmd{ + out: out, + client: client, + } + cmd := &cobra.Command{ + Use: "values [flags] RELEASE_NAME", + Short: "download the values file for a named release", + Long: getValuesHelp, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errReleaseRequired + } + get.release = args[0] + return get.run() + }, + } + cmd.Flags().BoolVarP(&get.allValues, "all", "a", false, "dump all (computed) values") + return cmd +} + +// getValues implements 'helm get values' +func (g *getValuesCmd) run() error { + res, err := g.client.ReleaseContent(g.release) + if err != nil { + return prettyError(err) + } + + // If the user wants all values, compute the values and return. + if g.allValues { + cfg, err := chartutil.CoalesceValues(res.Release.Chart, res.Release.Config, nil) + if err != nil { + return err + } + cfgStr, err := cfg.YAML() + if err != nil { + return err + } + fmt.Fprintln(g.out, cfgStr) + return nil + } + + fmt.Fprintln(g.out, res.Release.Config.Raw) + return nil +} diff --git a/cmd/helm/get_values_test.go b/cmd/helm/get_values_test.go new file mode 100644 index 000000000..5ccf9a5f6 --- /dev/null +++ b/cmd/helm/get_values_test.go @@ -0,0 +1,49 @@ +package main + +import ( + "bytes" + "testing" + + "k8s.io/helm/pkg/helm" + "k8s.io/helm/pkg/proto/hapi/release" +) + +func TestGetValuesCmd(t *testing.T) { + tests := []struct { + name string + args []string + client helm.Interface + expected string + err bool + }{ + { + name: "with a release", + client: &fakeReleaseClient{ + rels: []*release.Release{ + releaseMock("thomas-guide"), + }, + }, + args: []string{"thomas-guide"}, + expected: "name: \"value\"", + }, + { + name: "requires release name arg", + client: &fakeReleaseClient{}, + err: true, + }, + } + + var buf bytes.Buffer + for _, tt := range tests { + cmd := newGetValuesCmd(tt.client, &buf) + err := cmd.RunE(cmd, tt.args) + if (err != nil) != tt.err { + t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err) + } + actual := string(bytes.TrimSpace(buf.Bytes())) + if actual != tt.expected { + t.Errorf("%q. expected %q, got %q", tt.name, tt.expected, actual) + } + buf.Reset() + } +} diff --git a/cmd/helm/helm_test.go b/cmd/helm/helm_test.go new file mode 100644 index 000000000..8cee5f0aa --- /dev/null +++ b/cmd/helm/helm_test.go @@ -0,0 +1,70 @@ +package main + +import ( + "github.com/golang/protobuf/ptypes/timestamp" + + "k8s.io/helm/pkg/helm" + "k8s.io/helm/pkg/proto/hapi/chart" + "k8s.io/helm/pkg/proto/hapi/release" + rls "k8s.io/helm/pkg/proto/hapi/services" +) + +func releaseMock(name string) *release.Release { + date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0} + return &release.Release{ + Name: name, + Info: &release.Info{ + FirstDeployed: &date, + LastDeployed: &date, + Status: &release.Status{Code: release.Status_DEPLOYED}, + }, + Chart: &chart.Chart{ + Metadata: &chart.Metadata{ + Name: "foo", + Version: "0.1.0-beta.1", + }, + Templates: []*chart.Template{ + {Name: "foo.tpl", Data: []byte("Hello")}, + }, + }, + Config: &chart.Config{Raw: `name: "value"`}, + } +} + +type fakeReleaseClient struct { + rels []*release.Release + err error +} + +func (c *fakeReleaseClient) ListReleases(opts ...helm.ReleaseListOption) (*rls.ListReleasesResponse, error) { + resp := &rls.ListReleasesResponse{ + Count: int64(len(c.rels)), + Releases: c.rels, + } + return resp, c.err +} + +func (c *fakeReleaseClient) InstallRelease(chStr string, opts ...helm.InstallOption) (*rls.InstallReleaseResponse, error) { + return nil, nil +} + +func (c *fakeReleaseClient) DeleteRelease(rlsName string, opts ...helm.DeleteOption) (*rls.UninstallReleaseResponse, error) { + return nil, nil +} + +func (c *fakeReleaseClient) ReleaseStatus(rlsName string, opts ...helm.StatusOption) (*rls.GetReleaseStatusResponse, error) { + return nil, nil +} + +func (c *fakeReleaseClient) UpdateRelease(rlsName string, opts ...helm.UpdateOption) (*rls.UpdateReleaseResponse, error) { + return nil, nil +} + +func (c *fakeReleaseClient) ReleaseContent(rlsName string, opts ...helm.ContentOption) (resp *rls.GetReleaseContentResponse, err error) { + if len(c.rels) > 0 { + resp = &rls.GetReleaseContentResponse{ + Release: c.rels[0], + } + } + return resp, c.err +} diff --git a/cmd/helm/list_test.go b/cmd/helm/list_test.go index dace068f7..bc87039c5 100644 --- a/cmd/helm/list_test.go +++ b/cmd/helm/list_test.go @@ -4,50 +4,10 @@ import ( "bytes" "testing" - "github.com/golang/protobuf/ptypes/timestamp" - "k8s.io/helm/pkg/helm" - "k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/release" - rls "k8s.io/helm/pkg/proto/hapi/services" ) -func releaseMock(name string) *release.Release { - date := timestamp.Timestamp{Seconds: 242085845, Nanos: 0} - return &release.Release{ - Name: name, - Info: &release.Info{ - FirstDeployed: &date, - LastDeployed: &date, - Status: &release.Status{Code: release.Status_DEPLOYED}, - }, - Chart: &chart.Chart{ - Metadata: &chart.Metadata{ - Name: "foo", - Version: "0.1.0-beta.1", - }, - Templates: []*chart.Template{ - {Name: "foo.tpl", Data: []byte("Hello")}, - }, - }, - Config: &chart.Config{Raw: `name = "value"`}, - } -} - -type fakeReleaseLister struct { - helm.Interface - rels []*release.Release - err error -} - -func (fl *fakeReleaseLister) ListReleases(opts ...helm.ReleaseListOption) (*rls.ListReleasesResponse, error) { - resp := &rls.ListReleasesResponse{ - Count: int64(len(fl.rels)), - Releases: fl.rels, - } - return resp, fl.err -} - func TestListRun(t *testing.T) { tests := []struct { name string @@ -58,7 +18,7 @@ func TestListRun(t *testing.T) { { name: "with a release", listCmd: &listCmd{ - client: &fakeReleaseLister{ + client: &fakeReleaseClient{ rels: []*release.Release{ releaseMock("thomas-guide"), }, @@ -69,7 +29,7 @@ func TestListRun(t *testing.T) { { name: "list --long", listCmd: &listCmd{ - client: &fakeReleaseLister{ + client: &fakeReleaseClient{ rels: []*release.Release{ releaseMock("atlas"), }, @@ -106,7 +66,7 @@ func TestListCmd(t *testing.T) { }{ { name: "with a release", - client: &fakeReleaseLister{ + client: &fakeReleaseClient{ rels: []*release.Release{ releaseMock("thomas-guide"), }, @@ -116,7 +76,7 @@ func TestListCmd(t *testing.T) { { name: "list --long", flags: map[string]string{"long": "1"}, - client: &fakeReleaseLister{ + client: &fakeReleaseClient{ rels: []*release.Release{ releaseMock("atlas"), },