diff --git a/cmd/helm/create.go b/cmd/helm/create.go index d56f118bc..4d4dc153d 100644 --- a/cmd/helm/create.go +++ b/cmd/helm/create.go @@ -37,16 +37,11 @@ For example, 'helm create foo' will create a directory structure that looks something like this: foo/ - | - |- .helmignore # Contains patterns to ignore when packaging Helm charts. - | - |- Chart.yaml # Information about your chart - | - |- values.yaml # The default values for your templates - | - |- charts/ # Charts that this chart depends on - | - |- templates/ # The template files + ├── .helmignore # Contains patterns to ignore when packaging Helm charts. + ├── Chart.yaml # Information about your chart + ├── values.yaml # The default values for your templates + ├── charts/ # Charts that this chart depends on + └── templates/ # The template files 'helm create' takes a path for an argument. If directories in the given path do not exist, Helm will attempt to create them as it goes. If the given @@ -54,38 +49,40 @@ destination exists and there are files in that directory, conflicting files will be overwritten, but other files will be left alone. ` -type createCmd struct { - home helmpath.Home - name string - out io.Writer - starter string +type createOptions struct { + starter string // --starter + + // args + name string + + home helmpath.Home } func newCreateCmd(out io.Writer) *cobra.Command { - cc := &createCmd{out: out} + o := &createOptions{} cmd := &cobra.Command{ Use: "create NAME", Short: "create a new chart with the given name", Long: createDesc, RunE: func(cmd *cobra.Command, args []string) error { - cc.home = settings.Home + o.home = settings.Home if len(args) == 0 { return errors.New("the name of the new chart is required") } - cc.name = args[0] - return cc.run() + o.name = args[0] + return o.run(out) }, } - cmd.Flags().StringVarP(&cc.starter, "starter", "p", "", "the named Helm starter scaffold") + cmd.Flags().StringVarP(&o.starter, "starter", "p", "", "the named Helm starter scaffold") return cmd } -func (c *createCmd) run() error { - fmt.Fprintf(c.out, "Creating %s\n", c.name) +func (o *createOptions) run(out io.Writer) error { + fmt.Fprintf(out, "Creating %s\n", o.name) - chartname := filepath.Base(c.name) + chartname := filepath.Base(o.name) cfile := &chart.Metadata{ Name: chartname, Description: "A Helm chart for Kubernetes", @@ -94,12 +91,12 @@ func (c *createCmd) run() error { APIVersion: chartutil.APIVersionv1, } - if c.starter != "" { + if o.starter != "" { // Create from the starter - lstarter := filepath.Join(c.home.Starters(), c.starter) - return chartutil.CreateFrom(cfile, filepath.Dir(c.name), lstarter) + lstarter := filepath.Join(o.home.Starters(), o.starter) + return chartutil.CreateFrom(cfile, filepath.Dir(o.name), lstarter) } - _, err := chartutil.Create(cfile, filepath.Dir(c.name)) + _, err := chartutil.Create(cfile, filepath.Dir(o.name)) return err } diff --git a/cmd/helm/delete.go b/cmd/helm/delete.go index 20d29b203..1ed7edddc 100644 --- a/cmd/helm/delete.go +++ b/cmd/helm/delete.go @@ -34,22 +34,20 @@ Use the '--dry-run' flag to see which releases will be deleted without actually deleting them. ` -type deleteCmd struct { - name string - dryRun bool - disableHooks bool - purge bool - timeout int64 - - out io.Writer +type deleteOptions struct { + disableHooks bool // --no-hooks + dryRun bool // --dry-run + purge bool // --purge + timeout int64 // --timeout + + // args + name string + client helm.Interface } func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command { - del := &deleteCmd{ - out: out, - client: c, - } + o := &deleteOptions{client: c} cmd := &cobra.Command{ Use: "delete [flags] RELEASE_NAME [...]", @@ -61,39 +59,39 @@ func newDeleteCmd(c helm.Interface, out io.Writer) *cobra.Command { if len(args) == 0 { return errors.New("command 'delete' requires a release name") } - del.client = ensureHelmClient(del.client, false) + o.client = ensureHelmClient(o.client, false) for i := 0; i < len(args); i++ { - del.name = args[i] - if err := del.run(); err != nil { + o.name = args[i] + if err := o.run(out); err != nil { return err } - fmt.Fprintf(out, "release \"%s\" deleted\n", del.name) + fmt.Fprintf(out, "release \"%s\" deleted\n", o.name) } return nil }, } f := cmd.Flags() - f.BoolVar(&del.dryRun, "dry-run", false, "simulate a delete") - f.BoolVar(&del.disableHooks, "no-hooks", false, "prevent hooks from running during deletion") - f.BoolVar(&del.purge, "purge", false, "remove the release from the store and make its name free for later use") - f.Int64Var(&del.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") + f.BoolVar(&o.dryRun, "dry-run", false, "simulate a delete") + f.BoolVar(&o.disableHooks, "no-hooks", false, "prevent hooks from running during deletion") + f.BoolVar(&o.purge, "purge", false, "remove the release from the store and make its name free for later use") + f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") return cmd } -func (d *deleteCmd) run() error { +func (o *deleteOptions) run(out io.Writer) error { opts := []helm.DeleteOption{ - helm.DeleteDryRun(d.dryRun), - helm.DeleteDisableHooks(d.disableHooks), - helm.DeletePurge(d.purge), - helm.DeleteTimeout(d.timeout), + helm.DeleteDryRun(o.dryRun), + helm.DeleteDisableHooks(o.disableHooks), + helm.DeletePurge(o.purge), + helm.DeleteTimeout(o.timeout), } - res, err := d.client.DeleteRelease(d.name, opts...) + res, err := o.client.DeleteRelease(o.name, opts...) if res != nil && res.Info != "" { - fmt.Fprintln(d.out, res.Info) + fmt.Fprintln(out, res.Info) } return err diff --git a/cmd/helm/dependency.go b/cmd/helm/dependency.go index b3ce2d064..37e408c10 100644 --- a/cmd/helm/dependency.go +++ b/cmd/helm/dependency.go @@ -102,13 +102,14 @@ func newDependencyCmd(out io.Writer) *cobra.Command { return cmd } -type dependencyListCmd struct { - out io.Writer +type dependencyLisOptions struct { chartpath string } func newDependencyListCmd(out io.Writer) *cobra.Command { - dlc := &dependencyListCmd{out: out} + o := &dependencyLisOptions{ + chartpath: ".", + } cmd := &cobra.Command{ Use: "list [flags] CHART", @@ -116,20 +117,17 @@ func newDependencyListCmd(out io.Writer) *cobra.Command { Short: "list the dependencies for the given chart", Long: dependencyListDesc, RunE: func(cmd *cobra.Command, args []string) error { - cp := "." if len(args) > 0 { - cp = args[0] + o.chartpath = filepath.Clean(args[0]) } - - dlc.chartpath = filepath.Clean(cp) - return dlc.run() + return o.run(out) }, } return cmd } -func (l *dependencyListCmd) run() error { - c, err := chartutil.Load(l.chartpath) +func (o *dependencyLisOptions) run(out io.Writer) error { + c, err := chartutil.Load(o.chartpath) if err != nil { return err } @@ -137,21 +135,21 @@ func (l *dependencyListCmd) run() error { r, err := chartutil.LoadRequirements(c) if err != nil { if err == chartutil.ErrRequirementsNotFound { - fmt.Fprintf(l.out, "WARNING: no requirements at %s/charts\n", l.chartpath) + fmt.Fprintf(out, "WARNING: no requirements at %s/charts\n", o.chartpath) return nil } return err } - l.printRequirements(r, l.out) - fmt.Fprintln(l.out) - l.printMissing(r) + o.printRequirements(out, r) + fmt.Fprintln(out) + o.printMissing(out, r) return nil } -func (l *dependencyListCmd) dependencyStatus(dep *chartutil.Dependency) string { +func (o *dependencyLisOptions) dependencyStatus(dep *chartutil.Dependency) string { filename := fmt.Sprintf("%s-%s.tgz", dep.Name, "*") - archives, err := filepath.Glob(filepath.Join(l.chartpath, "charts", filename)) + archives, err := filepath.Glob(filepath.Join(o.chartpath, "charts", filename)) if err != nil { return "bad pattern" } else if len(archives) > 1 { @@ -187,7 +185,7 @@ func (l *dependencyListCmd) dependencyStatus(dep *chartutil.Dependency) string { } } - folder := filepath.Join(l.chartpath, "charts", dep.Name) + folder := filepath.Join(o.chartpath, "charts", dep.Name) if fi, err := os.Stat(folder); err != nil { return "missing" } else if !fi.IsDir() { @@ -224,29 +222,29 @@ func (l *dependencyListCmd) dependencyStatus(dep *chartutil.Dependency) string { } // printRequirements prints all of the requirements in the yaml file. -func (l *dependencyListCmd) printRequirements(reqs *chartutil.Requirements, out io.Writer) { +func (o *dependencyLisOptions) printRequirements(out io.Writer, reqs *chartutil.Requirements) { table := uitable.New() table.MaxColWidth = 80 table.AddRow("NAME", "VERSION", "REPOSITORY", "STATUS") for _, row := range reqs.Dependencies { - table.AddRow(row.Name, row.Version, row.Repository, l.dependencyStatus(row)) + table.AddRow(row.Name, row.Version, row.Repository, o.dependencyStatus(row)) } fmt.Fprintln(out, table) } // printMissing prints warnings about charts that are present on disk, but are not in the requirements. -func (l *dependencyListCmd) printMissing(reqs *chartutil.Requirements) { - folder := filepath.Join(l.chartpath, "charts/*") +func (o *dependencyLisOptions) printMissing(out io.Writer, reqs *chartutil.Requirements) { + folder := filepath.Join(o.chartpath, "charts/*") files, err := filepath.Glob(folder) if err != nil { - fmt.Fprintln(l.out, err) + fmt.Fprintln(out, err) return } for _, f := range files { fi, err := os.Stat(f) if err != nil { - fmt.Fprintf(l.out, "Warning: %s\n", err) + fmt.Fprintf(out, "Warning: %s\n", err) } // Skip anything that is not a directory and not a tgz file. if !fi.IsDir() && filepath.Ext(f) != ".tgz" { @@ -254,7 +252,7 @@ func (l *dependencyListCmd) printMissing(reqs *chartutil.Requirements) { } c, err := chartutil.Load(f) if err != nil { - fmt.Fprintf(l.out, "WARNING: %q is not a chart.\n", f) + fmt.Fprintf(out, "WARNING: %q is not a chart.\n", f) continue } found := false @@ -265,7 +263,7 @@ func (l *dependencyListCmd) printMissing(reqs *chartutil.Requirements) { } } if !found { - fmt.Fprintf(l.out, "WARNING: %q is not in requirements.yaml.\n", f) + fmt.Fprintf(out, "WARNING: %q is not in requirements.yaml.\n", f) } } diff --git a/cmd/helm/dependency_build.go b/cmd/helm/dependency_build.go index ec5fd14b7..69ff3637d 100644 --- a/cmd/helm/dependency_build.go +++ b/cmd/helm/dependency_build.go @@ -36,48 +36,50 @@ If no lock file is found, 'helm dependency build' will mirror the behavior of 'helm dependency update'. ` -type dependencyBuildCmd struct { - out io.Writer +type dependencyBuildOptions struct { + keyring string // --keyring + verify bool // --verify + + // args chartpath string - verify bool - keyring string - helmhome helmpath.Home + + helmhome helmpath.Home } func newDependencyBuildCmd(out io.Writer) *cobra.Command { - dbc := &dependencyBuildCmd{out: out} + o := &dependencyBuildOptions{ + chartpath: ".", + } cmd := &cobra.Command{ Use: "build [flags] CHART", Short: "rebuild the charts/ directory based on the requirements.lock file", Long: dependencyBuildDesc, RunE: func(cmd *cobra.Command, args []string) error { - dbc.helmhome = settings.Home - dbc.chartpath = "." - + o.helmhome = settings.Home if len(args) > 0 { - dbc.chartpath = args[0] + o.chartpath = args[0] } - return dbc.run() + return o.run(out) }, } f := cmd.Flags() - f.BoolVar(&dbc.verify, "verify", false, "verify the packages against signatures") - f.StringVar(&dbc.keyring, "keyring", defaultKeyring(), "keyring containing public keys") + f.BoolVar(&o.verify, "verify", false, "verify the packages against signatures") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys") return cmd } -func (d *dependencyBuildCmd) run() error { +func (o *dependencyBuildOptions) run(out io.Writer) error { man := &downloader.Manager{ - Out: d.out, - ChartPath: d.chartpath, - HelmHome: d.helmhome, - Keyring: d.keyring, + Out: out, + ChartPath: o.chartpath, + HelmHome: o.helmhome, + Keyring: o.keyring, Getters: getter.All(settings), } - if d.verify { + if o.verify { man.Verify = downloader.VerifyIfPossible } diff --git a/cmd/helm/dependency_update.go b/cmd/helm/dependency_update.go index 20708fb5f..47c116e00 100644 --- a/cmd/helm/dependency_update.go +++ b/cmd/helm/dependency_update.go @@ -41,19 +41,23 @@ reason, an update command will not remove charts unless they are (a) present in the requirements.yaml file, but (b) at the wrong version. ` -// dependencyUpdateCmd describes a 'helm dependency update' -type dependencyUpdateCmd struct { - out io.Writer - chartpath string - helmhome helmpath.Home - verify bool - keyring string - skipRefresh bool +// dependencyUpdateOptions describes a 'helm dependency update' +type dependencyUpdateOptions struct { + keyring string // --keyring + skipRefresh bool // --skip-refresh + verify bool // --verify + + // args + chartpath string + + helmhome helmpath.Home } // newDependencyUpdateCmd creates a new dependency update command. func newDependencyUpdateCmd(out io.Writer) *cobra.Command { - duc := &dependencyUpdateCmd{out: out} + o := &dependencyUpdateOptions{ + chartpath: ".", + } cmd := &cobra.Command{ Use: "update [flags] CHART", @@ -61,42 +65,33 @@ func newDependencyUpdateCmd(out io.Writer) *cobra.Command { Short: "update charts/ based on the contents of requirements.yaml", Long: dependencyUpDesc, RunE: func(cmd *cobra.Command, args []string) error { - cp := "." if len(args) > 0 { - cp = args[0] + o.chartpath = filepath.Clean(args[0]) } - - var err error - duc.chartpath, err = filepath.Abs(cp) - if err != nil { - return err - } - - duc.helmhome = settings.Home - - return duc.run() + o.helmhome = settings.Home + return o.run(out) }, } f := cmd.Flags() - f.BoolVar(&duc.verify, "verify", false, "verify the packages against signatures") - f.StringVar(&duc.keyring, "keyring", defaultKeyring(), "keyring containing public keys") - f.BoolVar(&duc.skipRefresh, "skip-refresh", false, "do not refresh the local repository cache") + f.BoolVar(&o.verify, "verify", false, "verify the packages against signatures") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys") + f.BoolVar(&o.skipRefresh, "skip-refresh", false, "do not refresh the local repository cache") return cmd } // run runs the full dependency update process. -func (d *dependencyUpdateCmd) run() error { +func (o *dependencyUpdateOptions) run(out io.Writer) error { man := &downloader.Manager{ - Out: d.out, - ChartPath: d.chartpath, - HelmHome: d.helmhome, - Keyring: d.keyring, - SkipUpdate: d.skipRefresh, + Out: out, + ChartPath: o.chartpath, + HelmHome: o.helmhome, + Keyring: o.keyring, + SkipUpdate: o.skipRefresh, Getters: getter.All(settings), } - if d.verify { + if o.verify { man.Verify = downloader.VerifyAlways } if settings.Debug { diff --git a/cmd/helm/dependency_update_test.go b/cmd/helm/dependency_update_test.go index 71292b4e7..f8d0537bc 100644 --- a/cmd/helm/dependency_update_test.go +++ b/cmd/helm/dependency_update_test.go @@ -190,11 +190,11 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) { } out := bytes.NewBuffer(nil) - duc := &dependencyUpdateCmd{out: out} - duc.helmhome = helmpath.Home(hh) - duc.chartpath = hh.Path(chartname) + o := &dependencyUpdateOptions{} + o.helmhome = helmpath.Home(hh) + o.chartpath = hh.Path(chartname) - if err := duc.run(); err != nil { + if err := o.run(out); err != nil { output := out.String() t.Logf("Output: %s", output) t.Fatal(err) @@ -203,14 +203,14 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) { // Chart repo is down srv.Stop() - if err := duc.run(); err == nil { + if err := o.run(out); err == nil { output := out.String() t.Logf("Output: %s", output) t.Fatal("Expected error, got nil") } // Make sure charts dir still has dependencies - files, err := ioutil.ReadDir(filepath.Join(duc.chartpath, "charts")) + files, err := ioutil.ReadDir(filepath.Join(o.chartpath, "charts")) if err != nil { t.Fatal(err) } @@ -226,7 +226,7 @@ func TestDependencyUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) { } // Make sure tmpcharts is deleted - if _, err := os.Stat(filepath.Join(duc.chartpath, "tmpcharts")); !os.IsNotExist(err) { + if _, err := os.Stat(filepath.Join(o.chartpath, "tmpcharts")); !os.IsNotExist(err) { t.Fatalf("tmpcharts dir still exists") } } diff --git a/cmd/helm/docs.go b/cmd/helm/docs.go index e5b9f7521..443d2b09f 100644 --- a/cmd/helm/docs.go +++ b/cmd/helm/docs.go @@ -37,15 +37,14 @@ It can also generate bash autocompletions. $ helm docs markdown -dir mydocs/ ` -type docsCmd struct { - out io.Writer +type docsOptions struct { dest string docTypeString string topCmd *cobra.Command } func newDocsCmd(out io.Writer) *cobra.Command { - dc := &docsCmd{out: out} + o := &docsOptions{} cmd := &cobra.Command{ Use: "docs", @@ -53,28 +52,28 @@ func newDocsCmd(out io.Writer) *cobra.Command { Long: docsDesc, Hidden: true, RunE: func(cmd *cobra.Command, args []string) error { - dc.topCmd = cmd.Root() - return dc.run() + o.topCmd = cmd.Root() + return o.run(out) }, } f := cmd.Flags() - f.StringVar(&dc.dest, "dir", "./", "directory to which documentation is written") - f.StringVar(&dc.docTypeString, "type", "markdown", "the type of documentation to generate (markdown, man, bash)") + f.StringVar(&o.dest, "dir", "./", "directory to which documentation is written") + f.StringVar(&o.docTypeString, "type", "markdown", "the type of documentation to generate (markdown, man, bash)") return cmd } -func (d *docsCmd) run() error { - switch d.docTypeString { +func (o *docsOptions) run(out io.Writer) error { + switch o.docTypeString { case "markdown", "mdown", "md": - return doc.GenMarkdownTree(d.topCmd, d.dest) + return doc.GenMarkdownTree(o.topCmd, o.dest) case "man": manHdr := &doc.GenManHeader{Title: "HELM", Section: "1"} - return doc.GenManTree(d.topCmd, manHdr, d.dest) + return doc.GenManTree(o.topCmd, manHdr, o.dest) case "bash": - return d.topCmd.GenBashCompletionFile(filepath.Join(d.dest, "completions.bash")) + return o.topCmd.GenBashCompletionFile(filepath.Join(o.dest, "completions.bash")) default: - return fmt.Errorf("unknown doc type %q. Try 'markdown' or 'man'", d.docTypeString) + return fmt.Errorf("unknown doc type %q. Try 'markdown' or 'man'", o.docTypeString) } } diff --git a/cmd/helm/fetch.go b/cmd/helm/fetch.go index 069f57eff..df39b91f4 100644 --- a/cmd/helm/fetch.go +++ b/cmd/helm/fetch.go @@ -24,6 +24,7 @@ import ( "path/filepath" "github.com/spf13/cobra" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/getter" @@ -45,31 +46,27 @@ file, and MUST pass the verification process. Failure in any part of this will result in an error, and the chart will not be saved locally. ` -type fetchCmd struct { - untar bool - untardir string - chartRef string - destdir string - version string - repoURL string - username string - password string - - verify bool - verifyLater bool - keyring string +type fetchOptions struct { + caFile string // --ca-file + certFile string // --cert-file + destdir string // --destination + devel bool // --devel + keyFile string // --key-file + keyring string // --keyring + password string // --password + repoURL string // --repo + untar bool // --untar + untardir string // --untardir + username string // --username + verify bool // --verify + verifyLater bool // --prov + version string // --version - certFile string - keyFile string - caFile string - - devel bool - - out io.Writer + chartRef string } func newFetchCmd(out io.Writer) *cobra.Command { - fch := &fetchCmd{out: out} + o := &fetchOptions{} cmd := &cobra.Command{ Use: "fetch [flags] [chart URL | repo/chartname] [...]", @@ -80,14 +77,14 @@ func newFetchCmd(out io.Writer) *cobra.Command { return fmt.Errorf("need at least one argument, url or repo/name of the chart") } - if fch.version == "" && fch.devel { + if o.version == "" && o.devel { debug("setting version to >0.0.0-0") - fch.version = ">0.0.0-0" + o.version = ">0.0.0-0" } for i := 0; i < len(args); i++ { - fch.chartRef = args[i] - if err := fch.run(); err != nil { + o.chartRef = args[i] + if err := o.run(out); err != nil { return err } } @@ -96,45 +93,45 @@ func newFetchCmd(out io.Writer) *cobra.Command { } f := cmd.Flags() - f.BoolVar(&fch.untar, "untar", false, "if set to true, will untar the chart after downloading it") - f.StringVar(&fch.untardir, "untardir", ".", "if untar is specified, this flag specifies the name of the directory into which the chart is expanded") - f.BoolVar(&fch.verify, "verify", false, "verify the package against its signature") - f.BoolVar(&fch.verifyLater, "prov", false, "fetch the provenance file, but don't perform verification") - f.StringVar(&fch.version, "version", "", "specific version of a chart. Without this, the latest version is fetched") - f.StringVar(&fch.keyring, "keyring", defaultKeyring(), "keyring containing public keys") - f.StringVarP(&fch.destdir, "destination", "d", ".", "location to write the chart. If this and tardir are specified, tardir is appended to this") - f.StringVar(&fch.repoURL, "repo", "", "chart repository url where to locate the requested chart") - f.StringVar(&fch.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") - f.StringVar(&fch.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") - f.StringVar(&fch.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") - f.BoolVar(&fch.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") - f.StringVar(&fch.username, "username", "", "chart repository username") - f.StringVar(&fch.password, "password", "", "chart repository password") + f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") + f.BoolVar(&o.untar, "untar", false, "if set to true, will untar the chart after downloading it") + f.BoolVar(&o.verify, "verify", false, "verify the package against its signature") + f.BoolVar(&o.verifyLater, "prov", false, "fetch the provenance file, but don't perform verification") + f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") + f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") + f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys") + f.StringVar(&o.password, "password", "", "chart repository password") + f.StringVar(&o.repoURL, "repo", "", "chart repository url where to locate the requested chart") + f.StringVar(&o.untardir, "untardir", ".", "if untar is specified, this flag specifies the name of the directory into which the chart is expanded") + f.StringVar(&o.username, "username", "", "chart repository username") + f.StringVar(&o.version, "version", "", "specific version of a chart. Without this, the latest version is fetched") + f.StringVarP(&o.destdir, "destination", "d", ".", "location to write the chart. If this and tardir are specified, tardir is appended to this") return cmd } -func (f *fetchCmd) run() error { +func (o *fetchOptions) run(out io.Writer) error { c := downloader.ChartDownloader{ HelmHome: settings.Home, - Out: f.out, - Keyring: f.keyring, + Out: out, + Keyring: o.keyring, Verify: downloader.VerifyNever, Getters: getter.All(settings), - Username: f.username, - Password: f.password, + Username: o.username, + Password: o.password, } - if f.verify { + if o.verify { c.Verify = downloader.VerifyAlways - } else if f.verifyLater { + } else if o.verifyLater { c.Verify = downloader.VerifyLater } // If untar is set, we fetch to a tempdir, then untar and copy after // verification. - dest := f.destdir - if f.untar { + dest := o.destdir + if o.untar { var err error dest, err = ioutil.TempDir("", "helm-") if err != nil { @@ -143,28 +140,28 @@ func (f *fetchCmd) run() error { defer os.RemoveAll(dest) } - if f.repoURL != "" { - chartURL, err := repo.FindChartInAuthRepoURL(f.repoURL, f.username, f.password, f.chartRef, f.version, f.certFile, f.keyFile, f.caFile, getter.All(settings)) + if o.repoURL != "" { + chartURL, err := repo.FindChartInAuthRepoURL(o.repoURL, o.username, o.password, o.chartRef, o.version, o.certFile, o.keyFile, o.caFile, getter.All(settings)) if err != nil { return err } - f.chartRef = chartURL + o.chartRef = chartURL } - saved, v, err := c.DownloadTo(f.chartRef, f.version, dest) + saved, v, err := c.DownloadTo(o.chartRef, o.version, dest) if err != nil { return err } - if f.verify { - fmt.Fprintf(f.out, "Verification: %v\n", v) + if o.verify { + fmt.Fprintf(out, "Verification: %v\n", v) } // After verification, untar the chart into the requested directory. - if f.untar { - ud := f.untardir + if o.untar { + ud := o.untardir if !filepath.IsAbs(ud) { - ud = filepath.Join(f.destdir, ud) + ud = filepath.Join(o.destdir, ud) } if fi, err := os.Stat(ud); err != nil { if err := os.MkdirAll(ud, 0755); err != nil { diff --git a/cmd/helm/get.go b/cmd/helm/get.go index 960a3c1bd..b15ca8d90 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -40,19 +40,16 @@ chart, the supplied values, and the generated manifest file. var errReleaseRequired = errors.New("release name is required") -type getCmd struct { +type getOptions struct { + version int // --revision + release string - version int - out io.Writer client helm.Interface } func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { - get := &getCmd{ - out: out, - client: client, - } + o := &getOptions{client: client} cmd := &cobra.Command{ Use: "get [flags] RELEASE_NAME", @@ -62,13 +59,13 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { if len(args) == 0 { return errReleaseRequired } - get.release = args[0] - get.client = ensureHelmClient(get.client, false) - return get.run() + o.release = args[0] + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } - cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision") + cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision") cmd.AddCommand(newGetValuesCmd(client, out)) cmd.AddCommand(newGetManifestCmd(client, out)) @@ -77,11 +74,10 @@ func newGetCmd(client helm.Interface, out io.Writer) *cobra.Command { return cmd } -// getCmd is the command that implements 'helm get' -func (g *getCmd) run() error { +func (g *getOptions) run(out io.Writer) error { res, err := g.client.ReleaseContent(g.release, g.version) if err != nil { return err } - return printRelease(g.out, res) + return printRelease(out, res) } diff --git a/cmd/helm/get_hooks.go b/cmd/helm/get_hooks.go index 5024c991f..4716d7a62 100644 --- a/cmd/helm/get_hooks.go +++ b/cmd/helm/get_hooks.go @@ -31,18 +31,15 @@ This command downloads hooks for a given release. Hooks are formatted in YAML and separated by the YAML '---\n' separator. ` -type getHooksCmd struct { +type getHooksOptions struct { release string - out io.Writer client helm.Interface version int } func newGetHooksCmd(client helm.Interface, out io.Writer) *cobra.Command { - ghc := &getHooksCmd{ - out: out, - client: client, - } + o := &getHooksOptions{client: client} + cmd := &cobra.Command{ Use: "hooks [flags] RELEASE_NAME", Short: "download all hooks for a named release", @@ -51,24 +48,24 @@ func newGetHooksCmd(client helm.Interface, out io.Writer) *cobra.Command { if len(args) == 0 { return errReleaseRequired } - ghc.release = args[0] - ghc.client = ensureHelmClient(ghc.client, false) - return ghc.run() + o.release = args[0] + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } - cmd.Flags().IntVar(&ghc.version, "revision", 0, "get the named release with revision") + cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision") return cmd } -func (g *getHooksCmd) run() error { - res, err := g.client.ReleaseContent(g.release, g.version) +func (o *getHooksOptions) run(out io.Writer) error { + res, err := o.client.ReleaseContent(o.release, o.version) if err != nil { - fmt.Fprintln(g.out, g.release) + fmt.Fprintln(out, o.release) return err } for _, hook := range res.Hooks { - fmt.Fprintf(g.out, "---\n# %s\n%s", hook.Name, hook.Manifest) + fmt.Fprintf(out, "---\n# %s\n%s", hook.Name, hook.Manifest) } return nil } diff --git a/cmd/helm/get_manifest.go b/cmd/helm/get_manifest.go index 66bc0e2e8..217d3d9cc 100644 --- a/cmd/helm/get_manifest.go +++ b/cmd/helm/get_manifest.go @@ -33,18 +33,17 @@ 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 { +type getManifestOptions struct { + version int // --revision + release string - out io.Writer - client helm.Interface - version int + + client helm.Interface } func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command { - get := &getManifestCmd{ - out: out, - client: client, - } + o := &getManifestOptions{client: client} + cmd := &cobra.Command{ Use: "manifest [flags] RELEASE_NAME", Short: "download the manifest for a named release", @@ -53,22 +52,22 @@ func newGetManifestCmd(client helm.Interface, out io.Writer) *cobra.Command { if len(args) == 0 { return errReleaseRequired } - get.release = args[0] - get.client = ensureHelmClient(get.client, false) - return get.run() + o.release = args[0] + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } - cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision") + cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision") return cmd } // getManifest implements 'helm get manifest' -func (g *getManifestCmd) run() error { - res, err := g.client.ReleaseContent(g.release, g.version) +func (o *getManifestOptions) run(out io.Writer) error { + res, err := o.client.ReleaseContent(o.release, o.version) if err != nil { return err } - fmt.Fprintln(g.out, res.Manifest) + fmt.Fprintln(out, res.Manifest) return nil } diff --git a/cmd/helm/get_values.go b/cmd/helm/get_values.go index 7571e5dae..a1e26a43d 100644 --- a/cmd/helm/get_values.go +++ b/cmd/helm/get_values.go @@ -30,19 +30,18 @@ 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 - version int +type getValuesOptions struct { + allValues bool // --all + version int // --revision + + release string + + client helm.Interface } func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command { - get := &getValuesCmd{ - out: out, - client: client, - } + o := &getValuesOptions{client: client} + cmd := &cobra.Command{ Use: "values [flags] RELEASE_NAME", Short: "download the values file for a named release", @@ -51,26 +50,26 @@ func newGetValuesCmd(client helm.Interface, out io.Writer) *cobra.Command { if len(args) == 0 { return errReleaseRequired } - get.release = args[0] - get.client = ensureHelmClient(get.client, false) - return get.run() + o.release = args[0] + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } - cmd.Flags().IntVar(&get.version, "revision", 0, "get the named release with revision") - cmd.Flags().BoolVarP(&get.allValues, "all", "a", false, "dump all (computed) values") + cmd.Flags().BoolVarP(&o.allValues, "all", "a", false, "dump all (computed) values") + cmd.Flags().IntVar(&o.version, "revision", 0, "get the named release with revision") return cmd } // getValues implements 'helm get values' -func (g *getValuesCmd) run() error { - res, err := g.client.ReleaseContent(g.release, g.version) +func (o *getValuesOptions) run(out io.Writer) error { + res, err := o.client.ReleaseContent(o.release, o.version) if err != nil { return err } // If the user wants all values, compute the values and return. - if g.allValues { + if o.allValues { cfg, err := chartutil.CoalesceValues(res.Chart, res.Config) if err != nil { return err @@ -79,10 +78,10 @@ func (g *getValuesCmd) run() error { if err != nil { return err } - fmt.Fprintln(g.out, cfgStr) + fmt.Fprintln(out, cfgStr) return nil } - fmt.Fprintln(g.out, string(res.Config)) + fmt.Fprintln(out, string(res.Config)) return nil } diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index d9cf1d574..c40516059 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -30,13 +30,13 @@ import ( "k8s.io/client-go/tools/clientcmd" "k8s.io/helm/pkg/helm" - helm_env "k8s.io/helm/pkg/helm/environment" + "k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/storage/driver" ) var ( - settings helm_env.EnvSettings + settings environment.EnvSettings config clientcmd.ClientConfig configOnce sync.Once ) diff --git a/cmd/helm/history.go b/cmd/helm/history.go index 84cff22c8..a4e894075 100644 --- a/cmd/helm/history.go +++ b/cmd/helm/history.go @@ -56,17 +56,18 @@ The historical release set is printed as a formatted table, e.g: 4 Mon Oct 3 10:15:13 2016 deployed alpine-0.1.0 Upgraded successfully ` -type historyCmd struct { - max int - rls string - out io.Writer - helmc helm.Interface - colWidth uint - outputFormat string +type historyOptions struct { + colWidth uint // --col-width + max int // --max + outputFormat string // --output + + release string + + client helm.Interface } -func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command { - his := &historyCmd{out: w, helmc: c} +func newHistoryCmd(c helm.Interface, out io.Writer) *cobra.Command { + o := &historyOptions{client: c} cmd := &cobra.Command{ Use: "history [flags] RELEASE_NAME", @@ -77,22 +78,22 @@ func newHistoryCmd(c helm.Interface, w io.Writer) *cobra.Command { if len(args) == 0 { return errReleaseRequired } - his.helmc = ensureHelmClient(his.helmc, false) - his.rls = args[0] - return his.run() + o.client = ensureHelmClient(o.client, false) + o.release = args[0] + return o.run(out) }, } f := cmd.Flags() - f.IntVar(&his.max, "max", 256, "maximum number of revision to include in history") - f.UintVar(&his.colWidth, "col-width", 60, "specifies the max column width of output") - f.StringVarP(&his.outputFormat, "output", "o", "table", "prints the output in the specified format (json|table|yaml)") + f.IntVar(&o.max, "max", 256, "maximum number of revision to include in history") + f.UintVar(&o.colWidth, "col-width", 60, "specifies the max column width of output") + f.StringVarP(&o.outputFormat, "output", "o", "table", "prints the output in the specified format (json|table|yaml)") return cmd } -func (cmd *historyCmd) run() error { - rels, err := cmd.helmc.ReleaseHistory(cmd.rls, cmd.max) +func (o *historyOptions) run(out io.Writer) error { + rels, err := o.client.ReleaseHistory(o.release, o.max) if err != nil { return err } @@ -105,22 +106,22 @@ func (cmd *historyCmd) run() error { var history []byte var formattingError error - switch cmd.outputFormat { + switch o.outputFormat { case "yaml": history, formattingError = yaml.Marshal(releaseHistory) case "json": history, formattingError = json.Marshal(releaseHistory) case "table": - history = formatAsTable(releaseHistory, cmd.colWidth) + history = formatAsTable(releaseHistory, o.colWidth) default: - return fmt.Errorf("unknown output format %q", cmd.outputFormat) + return fmt.Errorf("unknown output format %q", o.outputFormat) } if formattingError != nil { return formattingError } - fmt.Fprintln(cmd.out, string(history)) + fmt.Fprintln(out, string(history)) return nil } diff --git a/cmd/helm/init.go b/cmd/helm/init.go index c4faed4a4..a19db0d31 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -33,18 +33,20 @@ const initDesc = ` This command sets up local configuration in $HELM_HOME (default ~/.helm/). ` -const stableRepository = "stable" +const ( + stableRepository = "stable" + defaultStableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com" +) -var stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com" +type initOptions struct { + skipRefresh bool // --skip-refresh + stableRepositoryURL string // --stable-repo-url -type initCmd struct { - skipRefresh bool - out io.Writer - home helmpath.Home + home helmpath.Home } func newInitCmd(out io.Writer) *cobra.Command { - i := &initCmd{out: out} + o := &initOptions{} cmd := &cobra.Command{ Use: "init", @@ -54,31 +56,31 @@ func newInitCmd(out io.Writer) *cobra.Command { if len(args) != 0 { return errors.New("This command does not accept arguments") } - i.home = settings.Home - return i.run() + o.home = settings.Home + return o.run(out) }, } f := cmd.Flags() - f.BoolVar(&i.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache") - f.StringVar(&stableRepositoryURL, "stable-repo-url", stableRepositoryURL, "URL for stable repository") + f.BoolVar(&o.skipRefresh, "skip-refresh", false, "do not refresh (download) the local repository cache") + f.StringVar(&o.stableRepositoryURL, "stable-repo-url", defaultStableRepositoryURL, "URL for stable repository") return cmd } -// run initializes local config and installs Tiller to Kubernetes cluster. -func (i *initCmd) run() error { - if err := ensureDirectories(i.home, i.out); err != nil { +// run initializes local config. +func (o *initOptions) run(out io.Writer) error { + if err := ensureDirectories(o.home, out); err != nil { return err } - if err := ensureDefaultRepos(i.home, i.out, i.skipRefresh); err != nil { + if err := ensureDefaultRepos(o.home, out, o.skipRefresh, o.stableRepositoryURL); err != nil { return err } - if err := ensureRepoFileFormat(i.home.RepositoryFile(), i.out); err != nil { + if err := ensureRepoFileFormat(o.home.RepositoryFile(), out); err != nil { return err } - fmt.Fprintf(i.out, "$HELM_HOME has been configured at %s.\n", settings.Home) - fmt.Fprintln(i.out, "Happy Helming!") + fmt.Fprintf(out, "$HELM_HOME has been configured at %s.\n", settings.Home) + fmt.Fprintln(out, "Happy Helming!") return nil } @@ -108,12 +110,12 @@ func ensureDirectories(home helmpath.Home, out io.Writer) error { return nil } -func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool) error { +func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool, url 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), out, skipRefresh, home) + sr, err := initRepo(url, home.CacheIndex(stableRepository), out, skipRefresh, home) if err != nil { return err } @@ -127,11 +129,11 @@ func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool) err 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) +func initRepo(url, cacheFile string, out io.Writer, skipRefresh bool, home helmpath.Home) (*repo.Entry, error) { + fmt.Fprintf(out, "Adding %s repo with URL: %s \n", stableRepository, url) c := repo.Entry{ Name: stableRepository, - URL: stableRepositoryURL, + URL: url, Cache: cacheFile, } r, err := repo.NewChartRepository(&c, getter.All(settings)) @@ -146,7 +148,7 @@ func initStableRepo(cacheFile string, out io.Writer, skipRefresh bool, home helm // 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 nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error()) } return &c, nil diff --git a/cmd/helm/init_test.go b/cmd/helm/init_test.go index 00fa3673c..5ee148bae 100644 --- a/cmd/helm/init_test.go +++ b/cmd/helm/init_test.go @@ -38,10 +38,10 @@ func TestEnsureHome(t *testing.T) { if err := ensureDirectories(hh, b); err != nil { t.Error(err) } - if err := ensureDefaultRepos(hh, b, false); err != nil { + if err := ensureDefaultRepos(hh, b, false, defaultStableRepositoryURL); err != nil { t.Error(err) } - if err := ensureDefaultRepos(hh, b, true); err != nil { + if err := ensureDefaultRepos(hh, b, true, defaultStableRepositoryURL); err != nil { t.Error(err) } if err := ensureRepoFileFormat(hh.RepositoryFile(), b); err != nil { diff --git a/cmd/helm/inspect.go b/cmd/helm/inspect.go index 830e2948e..266e6d0c5 100644 --- a/cmd/helm/inspect.go +++ b/cmd/helm/inspect.go @@ -50,20 +50,18 @@ This command inspects a chart (directory, file, or URL) and displays the content of the README file ` -type inspectCmd struct { +type inspectOptions struct { chartpath string output string verify bool keyring string - out io.Writer version string repoURL string username string password string - - certFile string - keyFile string - caFile string + certFile string + keyFile string + caFile string } const ( @@ -76,10 +74,7 @@ const ( var readmeFileNames = []string{"readme.md", "readme.txt", "readme"} func newInspectCmd(out io.Writer) *cobra.Command { - insp := &inspectCmd{ - out: out, - output: all, - } + o := &inspectOptions{output: all} inspectCommand := &cobra.Command{ Use: "inspect [CHART]", @@ -89,13 +84,13 @@ func newInspectCmd(out io.Writer) *cobra.Command { if err := checkArgsLength(len(args), "chart name"); err != nil { return err } - cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring, - insp.certFile, insp.keyFile, insp.caFile) + cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring, + o.certFile, o.keyFile, o.caFile) if err != nil { return err } - insp.chartpath = cp - return insp.run() + o.chartpath = cp + return o.run(out) }, } @@ -104,17 +99,17 @@ func newInspectCmd(out io.Writer) *cobra.Command { Short: "shows inspect values", Long: inspectValuesDesc, RunE: func(cmd *cobra.Command, args []string) error { - insp.output = valuesOnly + o.output = valuesOnly if err := checkArgsLength(len(args), "chart name"); err != nil { return err } - cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring, - insp.certFile, insp.keyFile, insp.caFile) + cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring, + o.certFile, o.keyFile, o.caFile) if err != nil { return err } - insp.chartpath = cp - return insp.run() + o.chartpath = cp + return o.run(out) }, } @@ -123,17 +118,17 @@ func newInspectCmd(out io.Writer) *cobra.Command { Short: "shows inspect chart", Long: inspectChartDesc, RunE: func(cmd *cobra.Command, args []string) error { - insp.output = chartOnly + o.output = chartOnly if err := checkArgsLength(len(args), "chart name"); err != nil { return err } - cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring, - insp.certFile, insp.keyFile, insp.caFile) + cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring, + o.certFile, o.keyFile, o.caFile) if err != nil { return err } - insp.chartpath = cp - return insp.run() + o.chartpath = cp + return o.run(out) }, } @@ -142,17 +137,17 @@ func newInspectCmd(out io.Writer) *cobra.Command { Short: "shows inspect readme", Long: readmeChartDesc, RunE: func(cmd *cobra.Command, args []string) error { - insp.output = readmeOnly + o.output = readmeOnly if err := checkArgsLength(len(args), "chart name"); err != nil { return err } - cp, err := locateChartPath(insp.repoURL, insp.username, insp.password, args[0], insp.version, insp.verify, insp.keyring, - insp.certFile, insp.keyFile, insp.caFile) + cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring, + o.certFile, o.keyFile, o.caFile) if err != nil { return err } - insp.chartpath = cp - return insp.run() + o.chartpath = cp + return o.run(out) }, } @@ -160,56 +155,56 @@ func newInspectCmd(out io.Writer) *cobra.Command { vflag := "verify" vdesc := "verify the provenance data for this chart" for _, subCmd := range cmds { - subCmd.Flags().BoolVar(&insp.verify, vflag, false, vdesc) + subCmd.Flags().BoolVar(&o.verify, vflag, false, vdesc) } kflag := "keyring" kdesc := "path to the keyring containing public verification keys" kdefault := defaultKeyring() for _, subCmd := range cmds { - subCmd.Flags().StringVar(&insp.keyring, kflag, kdefault, kdesc) + subCmd.Flags().StringVar(&o.keyring, kflag, kdefault, kdesc) } verflag := "version" verdesc := "version of the chart. By default, the newest chart is shown" for _, subCmd := range cmds { - subCmd.Flags().StringVar(&insp.version, verflag, "", verdesc) + subCmd.Flags().StringVar(&o.version, verflag, "", verdesc) } repoURL := "repo" repoURLdesc := "chart repository url where to locate the requested chart" for _, subCmd := range cmds { - subCmd.Flags().StringVar(&insp.repoURL, repoURL, "", repoURLdesc) + subCmd.Flags().StringVar(&o.repoURL, repoURL, "", repoURLdesc) } username := "username" usernamedesc := "chart repository username where to locate the requested chart" - inspectCommand.Flags().StringVar(&insp.username, username, "", usernamedesc) - valuesSubCmd.Flags().StringVar(&insp.username, username, "", usernamedesc) - chartSubCmd.Flags().StringVar(&insp.username, username, "", usernamedesc) + inspectCommand.Flags().StringVar(&o.username, username, "", usernamedesc) + valuesSubCmd.Flags().StringVar(&o.username, username, "", usernamedesc) + chartSubCmd.Flags().StringVar(&o.username, username, "", usernamedesc) password := "password" passworddesc := "chart repository password where to locate the requested chart" - inspectCommand.Flags().StringVar(&insp.password, password, "", passworddesc) - valuesSubCmd.Flags().StringVar(&insp.password, password, "", passworddesc) - chartSubCmd.Flags().StringVar(&insp.password, password, "", passworddesc) + inspectCommand.Flags().StringVar(&o.password, password, "", passworddesc) + valuesSubCmd.Flags().StringVar(&o.password, password, "", passworddesc) + chartSubCmd.Flags().StringVar(&o.password, password, "", passworddesc) certFile := "cert-file" certFiledesc := "verify certificates of HTTPS-enabled servers using this CA bundle" for _, subCmd := range cmds { - subCmd.Flags().StringVar(&insp.certFile, certFile, "", certFiledesc) + subCmd.Flags().StringVar(&o.certFile, certFile, "", certFiledesc) } keyFile := "key-file" keyFiledesc := "identify HTTPS client using this SSL key file" for _, subCmd := range cmds { - subCmd.Flags().StringVar(&insp.keyFile, keyFile, "", keyFiledesc) + subCmd.Flags().StringVar(&o.keyFile, keyFile, "", keyFiledesc) } caFile := "ca-file" caFiledesc := "chart repository url where to locate the requested chart" for _, subCmd := range cmds { - subCmd.Flags().StringVar(&insp.caFile, caFile, "", caFiledesc) + subCmd.Flags().StringVar(&o.caFile, caFile, "", caFiledesc) } for _, subCmd := range cmds[1:] { @@ -219,7 +214,7 @@ func newInspectCmd(out io.Writer) *cobra.Command { return inspectCommand } -func (i *inspectCmd) run() error { +func (i *inspectOptions) run(out io.Writer) error { chrt, err := chartutil.Load(i.chartpath) if err != nil { return err @@ -230,25 +225,25 @@ func (i *inspectCmd) run() error { } if i.output == chartOnly || i.output == all { - fmt.Fprintln(i.out, string(cf)) + fmt.Fprintln(out, string(cf)) } if (i.output == valuesOnly || i.output == all) && chrt.Values != nil { if i.output == all { - fmt.Fprintln(i.out, "---") + fmt.Fprintln(out, "---") } - fmt.Fprintln(i.out, string(chrt.Values)) + fmt.Fprintln(out, string(chrt.Values)) } if i.output == readmeOnly || i.output == all { if i.output == all { - fmt.Fprintln(i.out, "---") + fmt.Fprintln(out, "---") } readme := findReadme(chrt.Files) if readme == nil { return nil } - fmt.Fprintln(i.out, string(readme.Data)) + fmt.Fprintln(out, string(readme.Data)) } return nil } diff --git a/cmd/helm/inspect_test.go b/cmd/helm/inspect_test.go index 44d71fbbd..5241cb2cc 100644 --- a/cmd/helm/inspect_test.go +++ b/cmd/helm/inspect_test.go @@ -26,12 +26,11 @@ import ( func TestInspect(t *testing.T) { b := bytes.NewBuffer(nil) - insp := &inspectCmd{ + o := &inspectOptions{ chartpath: "testdata/testcharts/alpine", output: all, - out: b, } - insp.run() + o.run(b) // Load the data from the textfixture directly. cdata, err := ioutil.ReadFile("testdata/testcharts/alpine/Chart.yaml") @@ -68,12 +67,11 @@ func TestInspect(t *testing.T) { // Regression tests for missing values. See issue #1024. b.Reset() - insp = &inspectCmd{ + o = &inspectOptions{ chartpath: "testdata/testcharts/novals", output: "values", - out: b, } - insp.run() + o.run(b) if b.Len() != 0 { t.Errorf("expected empty values buffer, got %q", b.String()) } diff --git a/cmd/helm/install.go b/cmd/helm/install.go index fb33ca65c..0bec126a2 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -104,7 +104,7 @@ To see the list of chart repositories, use 'helm repo list'. To search for charts in a repository, use 'helm search'. ` -type installCmd struct { +type installOptions struct { name string // --name valueFiles valueFiles // --values dryRun bool // --dry-run @@ -128,7 +128,6 @@ type installCmd struct { caFile string // --ca-file chartPath string // arg - out io.Writer client helm.Interface } @@ -150,10 +149,7 @@ func (v *valueFiles) Set(value string) error { } func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { - inst := &installCmd{ - out: out, - client: c, - } + o := &installOptions{client: c} cmd := &cobra.Command{ Use: "install [CHART]", @@ -164,69 +160,69 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { return err } - debug("Original chart version: %q", inst.version) - if inst.version == "" && inst.devel { + debug("Original chart version: %q", o.version) + if o.version == "" && o.devel { debug("setting version to >0.0.0-0") - inst.version = ">0.0.0-0" + o.version = ">0.0.0-0" } - cp, err := locateChartPath(inst.repoURL, inst.username, inst.password, args[0], inst.version, inst.verify, inst.keyring, - inst.certFile, inst.keyFile, inst.caFile) + cp, err := locateChartPath(o.repoURL, o.username, o.password, args[0], o.version, o.verify, o.keyring, + o.certFile, o.keyFile, o.caFile) if err != nil { return err } - inst.chartPath = cp - inst.client = ensureHelmClient(inst.client, false) - return inst.run() + o.chartPath = cp + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } f := cmd.Flags() - f.VarP(&inst.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") - f.StringVarP(&inst.name, "name", "", "", "release name. If unspecified, it will autogenerate one for you") - f.BoolVar(&inst.dryRun, "dry-run", false, "simulate an install") - f.BoolVar(&inst.disableHooks, "no-hooks", false, "prevent hooks from running during install") - f.BoolVar(&inst.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production") - f.StringArrayVar(&inst.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.StringArrayVar(&inst.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.StringVar(&inst.nameTemplate, "name-template", "", "specify template used to name the release") - f.BoolVar(&inst.verify, "verify", false, "verify the package before installing it") - f.StringVar(&inst.keyring, "keyring", defaultKeyring(), "location of public keys used for verification") - f.StringVar(&inst.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed") - f.Int64Var(&inst.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") - f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") - f.StringVar(&inst.repoURL, "repo", "", "chart repository url where to locate the requested chart") - f.StringVar(&inst.username, "username", "", "chart repository username where to locate the requested chart") - f.StringVar(&inst.password, "password", "", "chart repository password where to locate the requested chart") - f.StringVar(&inst.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") - f.StringVar(&inst.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") - f.StringVar(&inst.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") - f.BoolVar(&inst.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") - f.BoolVar(&inst.depUp, "dep-up", false, "run helm dependency update before installing the chart") + f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") + f.StringVarP(&o.name, "name", "", "", "release name. If unspecified, it will autogenerate one for you") + f.BoolVar(&o.dryRun, "dry-run", false, "simulate an install") + f.BoolVar(&o.disableHooks, "no-hooks", false, "prevent hooks from running during install") + f.BoolVar(&o.replace, "replace", false, "re-use the given name, even if that name is already used. This is unsafe in production") + f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.StringVar(&o.nameTemplate, "name-template", "", "specify template used to name the release") + f.BoolVar(&o.verify, "verify", false, "verify the package before installing it") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "location of public keys used for verification") + f.StringVar(&o.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed") + f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") + f.BoolVar(&o.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") + f.StringVar(&o.repoURL, "repo", "", "chart repository url where to locate the requested chart") + f.StringVar(&o.username, "username", "", "chart repository username where to locate the requested chart") + f.StringVar(&o.password, "password", "", "chart repository password where to locate the requested chart") + f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") + f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") + f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") + f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") + f.BoolVar(&o.depUp, "dep-up", false, "run helm dependency update before installing the chart") return cmd } -func (i *installCmd) run() error { - debug("CHART PATH: %s\n", i.chartPath) +func (o *installOptions) run(out io.Writer) error { + debug("CHART PATH: %s\n", o.chartPath) - rawVals, err := vals(i.valueFiles, i.values, i.stringValues) + rawVals, err := vals(o.valueFiles, o.values, o.stringValues) if err != nil { return err } // If template is specified, try to run the template. - if i.nameTemplate != "" { - i.name, err = generateName(i.nameTemplate) + if o.nameTemplate != "" { + o.name, err = generateName(o.nameTemplate) if err != nil { return err } // Print the final name so the user knows what the final name of the release is. - fmt.Printf("FINAL NAME: %s\n", i.name) + fmt.Printf("FINAL NAME: %s\n", o.name) } // Check chart requirements to make sure all dependencies are present in /charts - chartRequested, err := chartutil.Load(i.chartPath) + chartRequested, err := chartutil.Load(o.chartPath) if err != nil { return err } @@ -236,10 +232,10 @@ func (i *installCmd) run() error { // As of Helm 2.4.0, this is treated as a stopping condition: // https://github.com/kubernetes/helm/issues/2209 if err := checkDependencies(chartRequested, req); err != nil { - if i.depUp { + if o.depUp { man := &downloader.Manager{ - Out: i.out, - ChartPath: i.chartPath, + Out: out, + ChartPath: o.chartPath, HelmHome: settings.Home, Keyring: defaultKeyring(), SkipUpdate: false, @@ -257,16 +253,16 @@ func (i *installCmd) run() error { return fmt.Errorf("cannot load requirements: %v", err) } - rel, err := i.client.InstallReleaseFromChart( + rel, err := o.client.InstallReleaseFromChart( chartRequested, getNamespace(), helm.ValueOverrides(rawVals), - helm.ReleaseName(i.name), - helm.InstallDryRun(i.dryRun), - helm.InstallReuseName(i.replace), - helm.InstallDisableHooks(i.disableHooks), - helm.InstallTimeout(i.timeout), - helm.InstallWait(i.wait)) + helm.ReleaseName(o.name), + helm.InstallDryRun(o.dryRun), + helm.InstallReuseName(o.replace), + helm.InstallDisableHooks(o.disableHooks), + helm.InstallTimeout(o.timeout), + helm.InstallWait(o.wait)) if err != nil { return err } @@ -274,19 +270,19 @@ func (i *installCmd) run() error { if rel == nil { return nil } - i.printRelease(rel) + o.printRelease(out, rel) // If this is a dry run, we can't display status. - if i.dryRun { + if o.dryRun { return nil } // Print the status like status command does - status, err := i.client.ReleaseStatus(rel.Name, 0) + status, err := o.client.ReleaseStatus(rel.Name, 0) if err != nil { return err } - PrintStatus(i.out, status) + PrintStatus(out, status) return nil } @@ -363,14 +359,14 @@ func vals(valueFiles valueFiles, values []string, stringValues []string) ([]byte } // printRelease prints info about a release if the Debug is true. -func (i *installCmd) printRelease(rel *release.Release) { +func (o *installOptions) printRelease(out io.Writer, rel *release.Release) { if rel == nil { return } // TODO: Switch to text/template like everything else. - fmt.Fprintf(i.out, "NAME: %s\n", rel.Name) + fmt.Fprintf(out, "NAME: %s\n", rel.Name) if settings.Debug { - printRelease(i.out, rel) + printRelease(out, rel) } } diff --git a/cmd/helm/lint.go b/cmd/helm/lint.go index 54c7f0db3..ae7e533d6 100644 --- a/cmd/helm/lint.go +++ b/cmd/helm/lint.go @@ -43,60 +43,57 @@ it will emit [ERROR] messages. If it encounters issues that break with conventio or recommendation, it will emit [WARNING] messages. ` -type lintCmd struct { +type lintOptions struct { valueFiles valueFiles values []string sValues []string strict bool paths []string - out io.Writer } func newLintCmd(out io.Writer) *cobra.Command { - l := &lintCmd{ - paths: []string{"."}, - out: out, - } + o := &lintOptions{paths: []string{"."}} + cmd := &cobra.Command{ Use: "lint [flags] PATH", Short: "examines a chart for possible issues", Long: longLintHelp, RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { - l.paths = args + o.paths = args } - return l.run() + return o.run(out) }, } - cmd.Flags().VarP(&l.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)") - cmd.Flags().StringArrayVar(&l.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - cmd.Flags().StringArrayVar(&l.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - cmd.Flags().BoolVar(&l.strict, "strict", false, "fail on lint warnings") + cmd.Flags().VarP(&o.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)") + cmd.Flags().StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + cmd.Flags().StringArrayVar(&o.sValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + cmd.Flags().BoolVar(&o.strict, "strict", false, "fail on lint warnings") return cmd } var errLintNoChart = errors.New("No chart found for linting (missing Chart.yaml)") -func (l *lintCmd) run() error { +func (o *lintOptions) run(out io.Writer) error { var lowestTolerance int - if l.strict { + if o.strict { lowestTolerance = support.WarningSev } else { lowestTolerance = support.ErrorSev } // Get the raw values - rvals, err := l.vals() + rvals, err := o.vals() if err != nil { return err } var total int var failures int - for _, path := range l.paths { - if linter, err := lintChart(path, rvals, getNamespace(), l.strict); err != nil { + for _, path := range o.paths { + if linter, err := lintChart(path, rvals, getNamespace(), o.strict); err != nil { fmt.Println("==> Skipping", path) fmt.Println(err) if err == errLintNoChart { @@ -126,7 +123,7 @@ func (l *lintCmd) run() error { return fmt.Errorf("%s, %d chart(s) failed", msg, failures) } - fmt.Fprintf(l.out, "%s, no failures\n", msg) + fmt.Fprintf(out, "%s, no failures\n", msg) return nil } @@ -170,11 +167,11 @@ func lintChart(path string, vals []byte, namespace string, strict bool) (support return lint.All(chartPath, vals, namespace, strict), nil } -func (l *lintCmd) vals() ([]byte, error) { +func (o *lintOptions) vals() ([]byte, error) { base := map[string]interface{}{} // User specified a values files via -f/--values - for _, filePath := range l.valueFiles { + for _, filePath := range o.valueFiles { currentMap := map[string]interface{}{} bytes, err := ioutil.ReadFile(filePath) if err != nil { @@ -189,14 +186,14 @@ func (l *lintCmd) vals() ([]byte, error) { } // User specified a value via --set - for _, value := range l.values { + for _, value := range o.values { if err := strvals.ParseInto(value, base); err != nil { return []byte{}, fmt.Errorf("failed parsing --set data: %s", err) } } // User specified a value via --set-string - for _, value := range l.sValues { + for _, value := range o.sValues { if err := strvals.ParseIntoString(value, base); err != nil { return []byte{}, fmt.Errorf("failed parsing --set-string data: %s", err) } diff --git a/cmd/helm/list.go b/cmd/helm/list.go index b2df59a7a..16a7a9d9f 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -56,31 +56,31 @@ server's default, which may be much higher than 256. Pairing the '--max' flag with the '--offset' flag allows you to page through results. ` -type listCmd struct { - filter string - short bool - limit int - offset string - byDate bool - sortDesc bool - out io.Writer - all bool - deleted bool - deleting bool - deployed bool - failed bool - superseded bool - pending bool - client helm.Interface - colWidth uint - allNamespaces bool +type listOptions struct { + // flags + all bool // --all + allNamespaces bool // --all-namespaces + byDate bool // --date + colWidth uint // --col-width + deleted bool // --deleted + deleting bool // --deleting + deployed bool // --deployed + failed bool // --failed + limit int // --max + offset string // --offset + pending bool // --pending + short bool // --short + sortDesc bool // --reverse + superseded bool // --superseded + + // args + filter string + + client helm.Interface } func newListCmd(client helm.Interface, out io.Writer) *cobra.Command { - list := &listCmd{ - out: out, - client: client, - } + o := &listOptions{client: client} cmd := &cobra.Command{ Use: "list [flags] [FILTER]", @@ -89,48 +89,49 @@ func newListCmd(client helm.Interface, out io.Writer) *cobra.Command { Aliases: []string{"ls"}, RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { - list.filter = strings.Join(args, " ") + o.filter = strings.Join(args, " ") } - list.client = ensureHelmClient(list.client, list.allNamespaces) - return list.run() + o.client = ensureHelmClient(o.client, o.allNamespaces) + return o.run(out) }, } f := cmd.Flags() - f.BoolVarP(&list.short, "short", "q", false, "output short (quiet) listing format") - f.BoolVarP(&list.byDate, "date", "d", false, "sort by release date") - f.BoolVarP(&list.sortDesc, "reverse", "r", false, "reverse the sort order") - f.IntVarP(&list.limit, "max", "m", 256, "maximum number of releases to fetch") - f.StringVarP(&list.offset, "offset", "o", "", "next release name in the list, used to offset from start value") - f.BoolVarP(&list.all, "all", "a", false, "show all releases, not just the ones marked deployed") - f.BoolVar(&list.deleted, "deleted", false, "show deleted releases") - f.BoolVar(&list.deleting, "deleting", false, "show releases that are currently being deleted") - f.BoolVar(&list.deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled") - f.BoolVar(&list.failed, "failed", false, "show failed releases") - f.BoolVar(&list.pending, "pending", false, "show pending releases") - f.UintVar(&list.colWidth, "col-width", 60, "specifies the max column width of output") - f.BoolVar(&list.allNamespaces, "all-namespaces", false, "list releases across all namespaces") + f.BoolVarP(&o.short, "short", "q", false, "output short (quiet) listing format") + f.BoolVarP(&o.byDate, "date", "d", false, "sort by release date") + f.BoolVarP(&o.sortDesc, "reverse", "r", false, "reverse the sort order") + f.IntVarP(&o.limit, "max", "m", 256, "maximum number of releases to fetch") + f.StringVarP(&o.offset, "offset", "o", "", "next release name in the list, used to offset from start value") + f.BoolVarP(&o.all, "all", "a", false, "show all releases, not just the ones marked deployed") + f.BoolVar(&o.deleted, "deleted", false, "show deleted releases") + f.BoolVar(&o.superseded, "superseded", false, "show superseded releases") + f.BoolVar(&o.deleting, "deleting", false, "show releases that are currently being deleted") + f.BoolVar(&o.deployed, "deployed", false, "show deployed releases. If no other is specified, this will be automatically enabled") + f.BoolVar(&o.failed, "failed", false, "show failed releases") + f.BoolVar(&o.pending, "pending", false, "show pending releases") + f.UintVar(&o.colWidth, "col-width", 60, "specifies the max column width of output") + f.BoolVar(&o.allNamespaces, "all-namespaces", false, "list releases across all namespaces") return cmd } -func (l *listCmd) run() error { +func (o *listOptions) run(out io.Writer) error { sortBy := hapi.SortByName - if l.byDate { + if o.byDate { sortBy = hapi.SortByLastReleased } sortOrder := hapi.SortAsc - if l.sortDesc { + if o.sortDesc { sortOrder = hapi.SortDesc } - stats := l.statusCodes() + stats := o.statusCodes() - res, err := l.client.ListReleases( - helm.ReleaseListLimit(l.limit), - helm.ReleaseListOffset(l.offset), - helm.ReleaseListFilter(l.filter), + res, err := o.client.ListReleases( + helm.ReleaseListLimit(o.limit), + helm.ReleaseListOffset(o.offset), + helm.ReleaseListFilter(o.filter), helm.ReleaseListSort(sortBy), helm.ReleaseListOrder(sortOrder), helm.ReleaseListStatuses(stats), @@ -146,13 +147,13 @@ func (l *listCmd) run() error { rels := filterList(res) - if l.short { + if o.short { for _, r := range rels { - fmt.Fprintln(l.out, r.Name) + fmt.Fprintln(out, r.Name) } return nil } - fmt.Fprintln(l.out, formatList(rels, l.colWidth)) + fmt.Fprintln(out, formatList(rels, o.colWidth)) return nil } @@ -181,8 +182,8 @@ func filterList(rels []*release.Release) []*release.Release { } // statusCodes gets the list of status codes that are to be included in the results. -func (l *listCmd) statusCodes() []release.ReleaseStatus { - if l.all { +func (o *listOptions) statusCodes() []release.ReleaseStatus { + if o.all { return []release.ReleaseStatus{ release.StatusUnknown, release.StatusDeployed, @@ -195,22 +196,22 @@ func (l *listCmd) statusCodes() []release.ReleaseStatus { } } status := []release.ReleaseStatus{} - if l.deployed { + if o.deployed { status = append(status, release.StatusDeployed) } - if l.deleted { + if o.deleted { status = append(status, release.StatusDeleted) } - if l.deleting { + if o.deleting { status = append(status, release.StatusDeleting) } - if l.failed { + if o.failed { status = append(status, release.StatusFailed) } - if l.superseded { + if o.superseded { status = append(status, release.StatusSuperseded) } - if l.pending { + if o.pending { status = append(status, release.StatusPendingInstall, release.StatusPendingUpgrade, release.StatusPendingRollback) } diff --git a/cmd/helm/package.go b/cmd/helm/package.go index 75c60e9be..d82421372 100644 --- a/cmd/helm/package.go +++ b/cmd/helm/package.go @@ -49,46 +49,47 @@ Chart.yaml file, and (if found) build the current directory into a chart. Versioned chart archives are used by Helm package repositories. ` -type packageCmd struct { - sign bool - path string - valueFiles valueFiles - values []string - stringValues []string - key string - keyring string - version string - appVersion string - destination string - dependencyUpdate bool - - out io.Writer +type packageOptions struct { + appVersion string // --app-version + dependencyUpdate bool // --dependency-update + destination string // --destination + key string // --key + keyring string // --keyring + sign bool // --sign + stringValues []string // --set-string + valueFiles valueFiles // --values + values []string // --set + version string // --version + + // args + path string + home helmpath.Home } func newPackageCmd(out io.Writer) *cobra.Command { - pkg := &packageCmd{out: out} + o := &packageOptions{} cmd := &cobra.Command{ Use: "package [flags] [CHART_PATH] [...]", Short: "package a chart directory into a chart archive", Long: packageDesc, RunE: func(cmd *cobra.Command, args []string) error { - pkg.home = settings.Home + o.home = settings.Home if len(args) == 0 { return fmt.Errorf("need at least one argument, the path to the chart") } - if pkg.sign { - if pkg.key == "" { + if o.sign { + if o.key == "" { return errors.New("--key is required for signing a package") } - if pkg.keyring == "" { + if o.keyring == "" { return errors.New("--keyring is required for signing a package") } } for i := 0; i < len(args); i++ { - pkg.path = args[i] - if err := pkg.run(); err != nil { + o.path = args[i] + if err := o.run(out); err != nil { return err } } @@ -97,32 +98,32 @@ func newPackageCmd(out io.Writer) *cobra.Command { } f := cmd.Flags() - f.VarP(&pkg.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") - f.StringArrayVar(&pkg.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.StringArrayVar(&pkg.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.BoolVar(&pkg.sign, "sign", false, "use a PGP private key to sign this package") - f.StringVar(&pkg.key, "key", "", "name of the key to use when signing. Used if --sign is true") - f.StringVar(&pkg.keyring, "keyring", defaultKeyring(), "location of a public keyring") - f.StringVar(&pkg.version, "version", "", "set the version on the chart to this semver version") - f.StringVar(&pkg.appVersion, "app-version", "", "set the appVersion on the chart to this version") - f.StringVarP(&pkg.destination, "destination", "d", ".", "location to write the chart.") - f.BoolVarP(&pkg.dependencyUpdate, "dependency-update", "u", false, `update dependencies from "requirements.yaml" to dir "charts/" before packaging`) + f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") + f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.BoolVar(&o.sign, "sign", false, "use a PGP private key to sign this package") + f.StringVar(&o.key, "key", "", "name of the key to use when signing. Used if --sign is true") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "location of a public keyring") + f.StringVar(&o.version, "version", "", "set the version on the chart to this semver version") + f.StringVar(&o.appVersion, "app-version", "", "set the appVersion on the chart to this version") + f.StringVarP(&o.destination, "destination", "d", ".", "location to write the chart.") + f.BoolVarP(&o.dependencyUpdate, "dependency-update", "u", false, `update dependencies from "requirements.yaml" to dir "charts/" before packaging`) return cmd } -func (p *packageCmd) run() error { - path, err := filepath.Abs(p.path) +func (o *packageOptions) run(out io.Writer) error { + path, err := filepath.Abs(o.path) if err != nil { return err } - if p.dependencyUpdate { + if o.dependencyUpdate { downloadManager := &downloader.Manager{ - Out: p.out, + Out: out, ChartPath: path, HelmHome: settings.Home, - Keyring: p.keyring, + Keyring: o.keyring, Getters: getter.All(settings), Debug: settings.Debug, } @@ -137,7 +138,7 @@ func (p *packageCmd) run() error { return err } - overrideVals, err := vals(p.valueFiles, p.values, p.stringValues) + overrideVals, err := vals(o.valueFiles, o.values, o.stringValues) if err != nil { return err } @@ -152,16 +153,16 @@ func (p *packageCmd) run() error { ch.Values = newVals // If version is set, modify the version. - if len(p.version) != 0 { - if err := setVersion(ch, p.version); err != nil { + if len(o.version) != 0 { + if err := setVersion(ch, o.version); err != nil { return err } - debug("Setting version to %s", p.version) + debug("Setting version to %s", o.version) } - if p.appVersion != "" { - ch.Metadata.AppVersion = p.appVersion - debug("Setting appVersion to %s", p.appVersion) + if o.appVersion != "" { + ch.Metadata.AppVersion = o.appVersion + debug("Setting appVersion to %s", o.appVersion) } if filepath.Base(path) != ch.Metadata.Name { @@ -179,7 +180,7 @@ func (p *packageCmd) run() error { } var dest string - if p.destination == "." { + if o.destination == "." { // Save to the current working directory. dest, err = os.Getwd() if err != nil { @@ -187,18 +188,18 @@ func (p *packageCmd) run() error { } } else { // Otherwise save to set destination - dest = p.destination + dest = o.destination } name, err := chartutil.Save(ch, dest) if err == nil { - fmt.Fprintf(p.out, "Successfully packaged chart and saved it to: %s\n", name) + fmt.Fprintf(out, "Successfully packaged chart and saved it to: %s\n", name) } else { return fmt.Errorf("Failed to save: %s", err) } - if p.sign { - err = p.clearsign(name) + if o.sign { + err = o.clearsign(name) } return err @@ -215,9 +216,9 @@ func setVersion(ch *chart.Chart, ver string) error { return nil } -func (p *packageCmd) clearsign(filename string) error { +func (o *packageOptions) clearsign(filename string) error { // Load keyring - signer, err := provenance.NewFromKeyring(p.keyring, p.key) + signer, err := provenance.NewFromKeyring(o.keyring, o.key) if err != nil { return err } diff --git a/cmd/helm/plugin_install.go b/cmd/helm/plugin_install.go index f36178808..614a9e8a9 100644 --- a/cmd/helm/plugin_install.go +++ b/cmd/helm/plugin_install.go @@ -26,11 +26,10 @@ import ( "github.com/spf13/cobra" ) -type pluginInstallCmd struct { +type pluginInstallOptions struct { source string version string home helmpath.Home - out io.Writer } const pluginInstallDesc = ` @@ -41,35 +40,35 @@ Example usage: ` func newPluginInstallCmd(out io.Writer) *cobra.Command { - pcmd := &pluginInstallCmd{out: out} + o := &pluginInstallOptions{} cmd := &cobra.Command{ Use: "install [options] ...", Short: "install one or more Helm plugins", Long: pluginInstallDesc, PreRunE: func(cmd *cobra.Command, args []string) error { - return pcmd.complete(args) + return o.complete(args) }, RunE: func(cmd *cobra.Command, args []string) error { - return pcmd.run() + return o.run(out) }, } - cmd.Flags().StringVar(&pcmd.version, "version", "", "specify a version constraint. If this is not specified, the latest version is installed") + cmd.Flags().StringVar(&o.version, "version", "", "specify a version constraint. If this is not specified, the latest version is installed") return cmd } -func (pcmd *pluginInstallCmd) complete(args []string) error { +func (o *pluginInstallOptions) complete(args []string) error { if err := checkArgsLength(len(args), "plugin"); err != nil { return err } - pcmd.source = args[0] - pcmd.home = settings.Home + o.source = args[0] + o.home = settings.Home return nil } -func (pcmd *pluginInstallCmd) run() error { +func (o *pluginInstallOptions) run(out io.Writer) error { installer.Debug = settings.Debug - i, err := installer.NewForSource(pcmd.source, pcmd.version, pcmd.home) + i, err := installer.NewForSource(o.source, o.version, o.home) if err != nil { return err } @@ -87,6 +86,6 @@ func (pcmd *pluginInstallCmd) run() error { return err } - fmt.Fprintf(pcmd.out, "Installed plugin: %s\n", p.Metadata.Name) + fmt.Fprintf(out, "Installed plugin: %s\n", p.Metadata.Name) return nil } diff --git a/cmd/helm/plugin_list.go b/cmd/helm/plugin_list.go index e7618f38a..367605f61 100644 --- a/cmd/helm/plugin_list.go +++ b/cmd/helm/plugin_list.go @@ -25,25 +25,24 @@ import ( "github.com/spf13/cobra" ) -type pluginListCmd struct { +type pluginListOptions struct { home helmpath.Home - out io.Writer } func newPluginListCmd(out io.Writer) *cobra.Command { - pcmd := &pluginListCmd{out: out} + o := &pluginListOptions{} cmd := &cobra.Command{ Use: "list", Short: "list installed Helm plugins", RunE: func(cmd *cobra.Command, args []string) error { - pcmd.home = settings.Home - return pcmd.run() + o.home = settings.Home + return o.run(out) }, } return cmd } -func (pcmd *pluginListCmd) run() error { +func (o *pluginListOptions) run(out io.Writer) error { debug("pluginDirs: %s", settings.PluginDirs()) plugins, err := findPlugins(settings.PluginDirs()) if err != nil { @@ -55,6 +54,6 @@ func (pcmd *pluginListCmd) run() error { for _, p := range plugins { table.AddRow(p.Metadata.Name, p.Metadata.Version, p.Metadata.Description) } - fmt.Fprintln(pcmd.out, table) + fmt.Fprintln(out, table) return nil } diff --git a/cmd/helm/plugin_remove.go b/cmd/helm/plugin_remove.go index ec1154734..f52430479 100644 --- a/cmd/helm/plugin_remove.go +++ b/cmd/helm/plugin_remove.go @@ -28,49 +28,48 @@ import ( "github.com/spf13/cobra" ) -type pluginRemoveCmd struct { +type pluginRemoveOptions struct { names []string home helmpath.Home - out io.Writer } func newPluginRemoveCmd(out io.Writer) *cobra.Command { - pcmd := &pluginRemoveCmd{out: out} + o := &pluginRemoveOptions{} cmd := &cobra.Command{ Use: "remove ...", Short: "remove one or more Helm plugins", PreRunE: func(cmd *cobra.Command, args []string) error { - return pcmd.complete(args) + return o.complete(args) }, RunE: func(cmd *cobra.Command, args []string) error { - return pcmd.run() + return o.run(out) }, } return cmd } -func (pcmd *pluginRemoveCmd) complete(args []string) error { +func (o *pluginRemoveOptions) complete(args []string) error { if len(args) == 0 { return errors.New("please provide plugin name to remove") } - pcmd.names = args - pcmd.home = settings.Home + o.names = args + o.home = settings.Home return nil } -func (pcmd *pluginRemoveCmd) run() error { +func (o *pluginRemoveOptions) run(out io.Writer) error { debug("loading installed plugins from %s", settings.PluginDirs()) plugins, err := findPlugins(settings.PluginDirs()) if err != nil { return err } var errorPlugins []string - for _, name := range pcmd.names { + for _, name := range o.names { if found := findPlugin(plugins, name); found != nil { if err := removePlugin(found); err != nil { errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to remove plugin %s, got error (%v)", name, err)) } else { - fmt.Fprintf(pcmd.out, "Removed plugin: %s\n", name) + fmt.Fprintf(out, "Removed plugin: %s\n", name) } } else { errorPlugins = append(errorPlugins, fmt.Sprintf("Plugin: %s not found", name)) diff --git a/cmd/helm/plugin_update.go b/cmd/helm/plugin_update.go index d3778764d..d91a5aa3e 100644 --- a/cmd/helm/plugin_update.go +++ b/cmd/helm/plugin_update.go @@ -29,37 +29,36 @@ import ( "github.com/spf13/cobra" ) -type pluginUpdateCmd struct { +type pluginUpdateOptions struct { names []string home helmpath.Home - out io.Writer } func newPluginUpdateCmd(out io.Writer) *cobra.Command { - pcmd := &pluginUpdateCmd{out: out} + o := &pluginUpdateOptions{} cmd := &cobra.Command{ Use: "update ...", Short: "update one or more Helm plugins", PreRunE: func(cmd *cobra.Command, args []string) error { - return pcmd.complete(args) + return o.complete(args) }, RunE: func(cmd *cobra.Command, args []string) error { - return pcmd.run() + return o.run(out) }, } return cmd } -func (pcmd *pluginUpdateCmd) complete(args []string) error { +func (o *pluginUpdateOptions) complete(args []string) error { if len(args) == 0 { return errors.New("please provide plugin name to update") } - pcmd.names = args - pcmd.home = settings.Home + o.names = args + o.home = settings.Home return nil } -func (pcmd *pluginUpdateCmd) run() error { +func (o *pluginUpdateOptions) run(out io.Writer) error { installer.Debug = settings.Debug debug("loading installed plugins from %s", settings.PluginDirs()) plugins, err := findPlugins(settings.PluginDirs()) @@ -68,12 +67,12 @@ func (pcmd *pluginUpdateCmd) run() error { } var errorPlugins []string - for _, name := range pcmd.names { + for _, name := range o.names { if found := findPlugin(plugins, name); found != nil { - if err := updatePlugin(found, pcmd.home); err != nil { + if err := updatePlugin(found, o.home); err != nil { errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to update plugin %s, got error (%v)", name, err)) } else { - fmt.Fprintf(pcmd.out, "Updated plugin: %s\n", name) + fmt.Fprintf(out, "Updated plugin: %s\n", name) } } else { errorPlugins = append(errorPlugins, fmt.Sprintf("Plugin: %s not found", name)) diff --git a/cmd/helm/release_testing.go b/cmd/helm/release_testing.go index b3a3927ee..63f277fc0 100644 --- a/cmd/helm/release_testing.go +++ b/cmd/helm/release_testing.go @@ -33,19 +33,15 @@ The argument this command takes is the name of a deployed release. The tests to be run are defined in the chart that was installed. ` -type releaseTestCmd struct { +type releaseTestOptions struct { name string - out io.Writer client helm.Interface timeout int64 cleanup bool } func newReleaseTestCmd(c helm.Interface, out io.Writer) *cobra.Command { - rlsTest := &releaseTestCmd{ - out: out, - client: c, - } + o := &releaseTestOptions{client: c} cmd := &cobra.Command{ Use: "test [RELEASE]", @@ -56,24 +52,24 @@ func newReleaseTestCmd(c helm.Interface, out io.Writer) *cobra.Command { return err } - rlsTest.name = args[0] - rlsTest.client = ensureHelmClient(rlsTest.client, false) - return rlsTest.run() + o.name = args[0] + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } f := cmd.Flags() - f.Int64Var(&rlsTest.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") - f.BoolVar(&rlsTest.cleanup, "cleanup", false, "delete test pods upon completion") + f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") + f.BoolVar(&o.cleanup, "cleanup", false, "delete test pods upon completion") return cmd } -func (t *releaseTestCmd) run() (err error) { - c, errc := t.client.RunReleaseTest( - t.name, - helm.ReleaseTestTimeout(t.timeout), - helm.ReleaseTestCleanup(t.cleanup), +func (o *releaseTestOptions) run(out io.Writer) (err error) { + c, errc := o.client.RunReleaseTest( + o.name, + helm.ReleaseTestTimeout(o.timeout), + helm.ReleaseTestCleanup(o.cleanup), ) testErr := &testErr{} @@ -92,12 +88,9 @@ func (t *releaseTestCmd) run() (err error) { if res.Status == release.TestRunFailure { testErr.failed++ } - - fmt.Fprintf(t.out, res.Msg+"\n") - + fmt.Fprintf(out, res.Msg+"\n") } } - } type testErr struct { diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 77a64cc89..f615ceffe 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -27,7 +27,7 @@ import ( "k8s.io/helm/pkg/repo" ) -type repoAddCmd struct { +type repoAddOptions struct { name string url string username string @@ -38,12 +38,10 @@ type repoAddCmd struct { certFile string keyFile string caFile string - - out io.Writer } func newRepoAddCmd(out io.Writer) *cobra.Command { - add := &repoAddCmd{out: out} + o := &repoAddOptions{} cmd := &cobra.Command{ Use: "add [flags] [NAME] [URL]", @@ -53,30 +51,30 @@ func newRepoAddCmd(out io.Writer) *cobra.Command { return err } - add.name = args[0] - add.url = args[1] - add.home = settings.Home + o.name = args[0] + o.url = args[1] + o.home = settings.Home - return add.run() + return o.run(out) }, } f := cmd.Flags() - f.StringVar(&add.username, "username", "", "chart repository username") - f.StringVar(&add.password, "password", "", "chart repository password") - f.BoolVar(&add.noupdate, "no-update", false, "raise error if repo is already registered") - f.StringVar(&add.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") - f.StringVar(&add.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") - f.StringVar(&add.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") + f.StringVar(&o.username, "username", "", "chart repository username") + f.StringVar(&o.password, "password", "", "chart repository password") + f.BoolVar(&o.noupdate, "no-update", false, "raise error if repo is already registered") + f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") + f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") + f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") return cmd } -func (a *repoAddCmd) run() error { - if err := addRepository(a.name, a.url, a.username, a.password, a.home, a.certFile, a.keyFile, a.caFile, a.noupdate); err != nil { +func (o *repoAddOptions) run(out io.Writer) error { + if err := addRepository(o.name, o.url, o.username, o.password, o.home, o.certFile, o.keyFile, o.caFile, o.noupdate); err != nil { return err } - fmt.Fprintf(a.out, "%q has been added to your repositories\n", a.name) + fmt.Fprintf(out, "%q has been added to your repositories\n", o.name) return nil } diff --git a/cmd/helm/repo_index.go b/cmd/helm/repo_index.go index 540057eb8..82758ebc5 100644 --- a/cmd/helm/repo_index.go +++ b/cmd/helm/repo_index.go @@ -38,15 +38,14 @@ flag. In this case, the charts found in the current directory will be merged into the existing index, with local charts taking priority over existing charts. ` -type repoIndexCmd struct { +type repoIndexOptions struct { dir string url string - out io.Writer merge string } func newRepoIndexCmd(out io.Writer) *cobra.Command { - index := &repoIndexCmd{out: out} + o := &repoIndexOptions{} cmd := &cobra.Command{ Use: "index [flags] [DIR]", @@ -57,20 +56,20 @@ func newRepoIndexCmd(out io.Writer) *cobra.Command { return err } - index.dir = args[0] + o.dir = args[0] - return index.run() + return o.run(out) }, } f := cmd.Flags() - f.StringVar(&index.url, "url", "", "url of chart repository") - f.StringVar(&index.merge, "merge", "", "merge the generated index into the given index") + f.StringVar(&o.url, "url", "", "url of chart repository") + f.StringVar(&o.merge, "merge", "", "merge the generated index into the given index") return cmd } -func (i *repoIndexCmd) run() error { +func (i *repoIndexOptions) run(out io.Writer) error { path, err := filepath.Abs(i.dir) if err != nil { return err diff --git a/cmd/helm/repo_list.go b/cmd/helm/repo_list.go index 0f795b2b0..9a34b96bd 100644 --- a/cmd/helm/repo_list.go +++ b/cmd/helm/repo_list.go @@ -28,28 +28,27 @@ import ( "k8s.io/helm/pkg/repo" ) -type repoListCmd struct { - out io.Writer +type repoListOptions struct { home helmpath.Home } func newRepoListCmd(out io.Writer) *cobra.Command { - list := &repoListCmd{out: out} + o := &repoListOptions{} cmd := &cobra.Command{ Use: "list [flags]", Short: "list chart repositories", RunE: func(cmd *cobra.Command, args []string) error { - list.home = settings.Home - return list.run() + o.home = settings.Home + return o.run(out) }, } return cmd } -func (a *repoListCmd) run() error { - f, err := repo.LoadRepositoriesFile(a.home.RepositoryFile()) +func (o *repoListOptions) run(out io.Writer) error { + f, err := repo.LoadRepositoriesFile(o.home.RepositoryFile()) if err != nil { return err } @@ -61,6 +60,6 @@ func (a *repoListCmd) run() error { for _, re := range f.Repositories { table.AddRow(re.Name, re.URL) } - fmt.Fprintln(a.out, table) + fmt.Fprintln(out, table) return nil } diff --git a/cmd/helm/repo_remove.go b/cmd/helm/repo_remove.go index 201ee9ca8..fceb75f7c 100644 --- a/cmd/helm/repo_remove.go +++ b/cmd/helm/repo_remove.go @@ -27,14 +27,13 @@ import ( "k8s.io/helm/pkg/repo" ) -type repoRemoveCmd struct { - out io.Writer +type repoRemoveOptions struct { name string home helmpath.Home } func newRepoRemoveCmd(out io.Writer) *cobra.Command { - remove := &repoRemoveCmd{out: out} + o := &repoRemoveOptions{} cmd := &cobra.Command{ Use: "remove [flags] [NAME]", @@ -44,18 +43,18 @@ func newRepoRemoveCmd(out io.Writer) *cobra.Command { if err := checkArgsLength(len(args), "name of chart repository"); err != nil { return err } - remove.name = args[0] - remove.home = settings.Home + o.name = args[0] + o.home = settings.Home - return remove.run() + return o.run(out) }, } return cmd } -func (r *repoRemoveCmd) run() error { - return removeRepoLine(r.out, r.name, r.home) +func (r *repoRemoveOptions) run(out io.Writer) error { + return removeRepoLine(out, r.name, r.home) } func removeRepoLine(out io.Writer, name string, home helmpath.Home) error { diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 3532211ce..7bf63f514 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -39,32 +39,29 @@ future releases. var errNoRepositories = errors.New("no repositories found. You must add one before updating") -type repoUpdateCmd struct { +type repoUpdateOptions struct { update func([]*repo.ChartRepository, io.Writer, helmpath.Home) home helmpath.Home - out io.Writer } func newRepoUpdateCmd(out io.Writer) *cobra.Command { - u := &repoUpdateCmd{ - out: out, - update: updateCharts, - } + o := &repoUpdateOptions{update: updateCharts} + cmd := &cobra.Command{ Use: "update", Aliases: []string{"up"}, Short: "update information of available charts locally from chart repositories", Long: updateDesc, RunE: func(cmd *cobra.Command, args []string) error { - u.home = settings.Home - return u.run() + o.home = settings.Home + return o.run(out) }, } return cmd } -func (u *repoUpdateCmd) run() error { - f, err := repo.LoadRepositoriesFile(u.home.RepositoryFile()) +func (o *repoUpdateOptions) run(out io.Writer) error { + f, err := repo.LoadRepositoriesFile(o.home.RepositoryFile()) if err != nil { return err } @@ -81,7 +78,7 @@ func (u *repoUpdateCmd) run() error { repos = append(repos, r) } - u.update(repos, u.out, u.home) + o.update(repos, out, o.home) return nil } diff --git a/cmd/helm/repo_update_test.go b/cmd/helm/repo_update_test.go index 5dac59130..582113314 100644 --- a/cmd/helm/repo_update_test.go +++ b/cmd/helm/repo_update_test.go @@ -51,12 +51,11 @@ func TestUpdateCmd(t *testing.T) { fmt.Fprintln(out, re.Config.Name) } } - uc := &repoUpdateCmd{ + o := &repoUpdateOptions{ update: updater, home: helmpath.Home(thome), - out: out, } - if err := uc.run(); err != nil { + if err := o.run(out); err != nil { t.Fatal(err) } diff --git a/cmd/helm/rollback.go b/cmd/helm/rollback.go index 145011f36..429b6aaef 100644 --- a/cmd/helm/rollback.go +++ b/cmd/helm/rollback.go @@ -34,24 +34,20 @@ second is a revision (version) number. To see revision numbers, run 'helm history RELEASE'. ` -type rollbackCmd struct { +type rollbackOptions struct { name string revision int dryRun bool recreate bool force bool disableHooks bool - out io.Writer client helm.Interface timeout int64 wait bool } func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { - rollback := &rollbackCmd{ - out: out, - client: c, - } + o := &rollbackOptions{client: c} cmd := &cobra.Command{ Use: "rollback [flags] [RELEASE] [REVISION]", @@ -62,45 +58,45 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { return err } - rollback.name = args[0] + o.name = args[0] v64, err := strconv.ParseInt(args[1], 10, 32) if err != nil { return fmt.Errorf("invalid revision number '%q': %s", args[1], err) } - rollback.revision = int(v64) - rollback.client = ensureHelmClient(rollback.client, false) - return rollback.run() + o.revision = int(v64) + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } f := cmd.Flags() - f.BoolVar(&rollback.dryRun, "dry-run", false, "simulate a rollback") - f.BoolVar(&rollback.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable") - f.BoolVar(&rollback.force, "force", false, "force resource update through delete/recreate if needed") - f.BoolVar(&rollback.disableHooks, "no-hooks", false, "prevent hooks from running during rollback") - f.Int64Var(&rollback.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") - f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") + f.BoolVar(&o.dryRun, "dry-run", false, "simulate a rollback") + f.BoolVar(&o.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable") + f.BoolVar(&o.force, "force", false, "force resource update through delete/recreate if needed") + f.BoolVar(&o.disableHooks, "no-hooks", false, "prevent hooks from running during rollback") + f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") + f.BoolVar(&o.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") return cmd } -func (r *rollbackCmd) run() error { - _, err := r.client.RollbackRelease( - r.name, - helm.RollbackDryRun(r.dryRun), - helm.RollbackRecreate(r.recreate), - helm.RollbackForce(r.force), - helm.RollbackDisableHooks(r.disableHooks), - helm.RollbackVersion(r.revision), - helm.RollbackTimeout(r.timeout), - helm.RollbackWait(r.wait)) +func (o *rollbackOptions) run(out io.Writer) error { + _, err := o.client.RollbackRelease( + o.name, + helm.RollbackDryRun(o.dryRun), + helm.RollbackRecreate(o.recreate), + helm.RollbackForce(o.force), + helm.RollbackDisableHooks(o.disableHooks), + helm.RollbackVersion(o.revision), + helm.RollbackTimeout(o.timeout), + helm.RollbackWait(o.wait)) if err != nil { return err } - fmt.Fprintf(r.out, "Rollback was a success! Happy Helming!\n") + fmt.Fprintf(out, "Rollback was a success! Happy Helming!\n") return nil } diff --git a/cmd/helm/search.go b/cmd/helm/search.go index 845bfd0be..2200f0016 100644 --- a/cmd/helm/search.go +++ b/cmd/helm/search.go @@ -40,8 +40,7 @@ Repositories are managed with 'helm repo' commands. // searchMaxScore suggests that any score higher than this is not considered a match. const searchMaxScore = 25 -type searchCmd struct { - out io.Writer +type searchOptions struct { helmhome helmpath.Home versions bool @@ -50,28 +49,28 @@ type searchCmd struct { } func newSearchCmd(out io.Writer) *cobra.Command { - sc := &searchCmd{out: out} + o := &searchOptions{} cmd := &cobra.Command{ Use: "search [keyword]", Short: "search for a keyword in charts", Long: searchDesc, RunE: func(cmd *cobra.Command, args []string) error { - sc.helmhome = settings.Home - return sc.run(args) + o.helmhome = settings.Home + return o.run(out, args) }, } f := cmd.Flags() - f.BoolVarP(&sc.regexp, "regexp", "r", false, "use regular expressions for searching") - f.BoolVarP(&sc.versions, "versions", "l", false, "show the long listing, with each version of each chart on its own line") - f.StringVarP(&sc.version, "version", "v", "", "search using semantic versioning constraints") + f.BoolVarP(&o.regexp, "regexp", "r", false, "use regular expressions for searching") + f.BoolVarP(&o.versions, "versions", "l", false, "show the long listing, with each version of each chart on its own line") + f.StringVarP(&o.version, "version", "v", "", "search using semantic versioning constraints") return cmd } -func (s *searchCmd) run(args []string) error { - index, err := s.buildIndex() +func (o *searchOptions) run(out io.Writer, args []string) error { + index, err := o.buildIndex(out) if err != nil { return err } @@ -81,29 +80,29 @@ func (s *searchCmd) run(args []string) error { res = index.All() } else { q := strings.Join(args, " ") - res, err = index.Search(q, searchMaxScore, s.regexp) + res, err = index.Search(q, searchMaxScore, o.regexp) if err != nil { return err } } search.SortScore(res) - data, err := s.applyConstraint(res) + data, err := o.applyConstraint(res) if err != nil { return err } - fmt.Fprintln(s.out, s.formatSearchResults(data)) + fmt.Fprintln(out, o.formatSearchResults(data)) return nil } -func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, error) { - if len(s.version) == 0 { +func (o *searchOptions) applyConstraint(res []*search.Result) ([]*search.Result, error) { + if len(o.version) == 0 { return res, nil } - constraint, err := semver.NewConstraint(s.version) + constraint, err := semver.NewConstraint(o.version) if err != nil { return res, fmt.Errorf("an invalid version/constraint format: %s", err) } @@ -117,7 +116,7 @@ func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, err v, err := semver.NewVersion(r.Chart.Version) if err != nil || constraint.Check(v) { data = append(data, r) - if !s.versions { + if !o.versions { foundNames[r.Name] = true // If user hasn't requested all versions, only show the latest that matches } } @@ -126,7 +125,7 @@ func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, err return data, nil } -func (s *searchCmd) formatSearchResults(res []*search.Result) string { +func (o *searchOptions) formatSearchResults(res []*search.Result) string { if len(res) == 0 { return "No results found" } @@ -139,9 +138,9 @@ func (s *searchCmd) formatSearchResults(res []*search.Result) string { return table.String() } -func (s *searchCmd) buildIndex() (*search.Index, error) { +func (o *searchOptions) buildIndex(out io.Writer) (*search.Index, error) { // Load the repositories.yaml - rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile()) + rf, err := repo.LoadRepositoriesFile(o.helmhome.RepositoryFile()) if err != nil { return nil, err } @@ -149,14 +148,15 @@ func (s *searchCmd) buildIndex() (*search.Index, error) { i := search.NewIndex() for _, re := range rf.Repositories { n := re.Name - f := s.helmhome.CacheIndex(n) + f := o.helmhome.CacheIndex(n) ind, err := repo.LoadIndexFile(f) if err != nil { - fmt.Fprintf(s.out, "WARNING: Repo %q is corrupt or missing. Try 'helm repo update'.", n) + // TODO should print to stderr + fmt.Fprintf(out, "WARNING: Repo %q is corrupt or missing. Try 'helm repo update'.", n) continue } - i.AddRepo(n, ind, s.versions || len(s.version) > 0) + i.AddRepo(n, ind, o.versions || len(o.version) > 0) } return i, nil } diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 891d88554..ab30cddb5 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -44,19 +44,15 @@ The status consists of: - additional notes provided by the chart ` -type statusCmd struct { +type statusOptions struct { release string - out io.Writer client helm.Interface version int outfmt string } func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { - status := &statusCmd{ - out: out, - client: client, - } + o := &statusOptions{client: client} cmd := &cobra.Command{ Use: "status [flags] RELEASE_NAME", @@ -66,45 +62,45 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { if len(args) == 0 { return errReleaseRequired } - status.release = args[0] - status.client = ensureHelmClient(status.client, false) - return status.run() + o.release = args[0] + o.client = ensureHelmClient(o.client, false) + return o.run(out) }, } - cmd.PersistentFlags().IntVar(&status.version, "revision", 0, "if set, display the status of the named release with revision") - cmd.PersistentFlags().StringVarP(&status.outfmt, "output", "o", "", "output the status in the specified format (json or yaml)") + cmd.PersistentFlags().IntVar(&o.version, "revision", 0, "if set, display the status of the named release with revision") + cmd.PersistentFlags().StringVarP(&o.outfmt, "output", "o", "", "output the status in the specified format (json or yaml)") return cmd } -func (s *statusCmd) run() error { - res, err := s.client.ReleaseStatus(s.release, s.version) +func (o *statusOptions) run(out io.Writer) error { + res, err := o.client.ReleaseStatus(o.release, o.version) if err != nil { return err } - switch s.outfmt { + switch o.outfmt { case "": - PrintStatus(s.out, res) + PrintStatus(out, res) return nil case "json": data, err := json.Marshal(res) if err != nil { return fmt.Errorf("Failed to Marshal JSON output: %s", err) } - s.out.Write(data) + out.Write(data) return nil case "yaml": data, err := yaml.Marshal(res) if err != nil { return fmt.Errorf("Failed to Marshal YAML output: %s", err) } - s.out.Write(data) + out.Write(data) return nil } - return fmt.Errorf("Unknown output format %q", s.outfmt) + return fmt.Errorf("Unknown output format %q", o.outfmt) } // PrintStatus prints out the status of a release. Shared because also used by diff --git a/cmd/helm/template.go b/cmd/helm/template.go index 1377d27cd..83966bfe9 100644 --- a/cmd/helm/template.go +++ b/cmd/helm/template.go @@ -60,10 +60,9 @@ To render just one template in a chart, use '-x': $ helm template mychart -x templates/deployment.yaml ` -type templateCmd struct { +type templateOptions struct { valueFiles valueFiles chartPath string - out io.Writer values []string stringValues []string nameTemplate string @@ -75,52 +74,51 @@ type templateCmd struct { } func newTemplateCmd(out io.Writer) *cobra.Command { - - t := &templateCmd{ - out: out, - } + o := &templateOptions{} cmd := &cobra.Command{ Use: "template [flags] CHART", Short: fmt.Sprintf("locally render templates"), Long: templateDesc, - RunE: t.run, + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return errors.New("chart is required") + } + // verify chart path exists + if _, err := os.Stat(args[0]); err == nil { + if o.chartPath, err = filepath.Abs(args[0]); err != nil { + return err + } + } else { + return err + } + return o.run(out) + }, } f := cmd.Flags() - f.BoolVar(&t.showNotes, "notes", false, "show the computed NOTES.txt file as well") - f.StringVarP(&t.releaseName, "name", "", "RELEASE-NAME", "release name") - f.StringArrayVarP(&t.renderFiles, "execute", "x", []string{}, "only execute the given templates") - f.VarP(&t.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)") - f.StringArrayVar(&t.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.StringArrayVar(&t.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.StringVar(&t.nameTemplate, "name-template", "", "specify template used to name the release") - f.StringVar(&t.kubeVersion, "kube-version", defaultKubeVersion, "kubernetes version used as Capabilities.KubeVersion.Major/Minor") - f.StringVar(&t.outputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout") + f.BoolVar(&o.showNotes, "notes", false, "show the computed NOTES.txt file as well") + f.StringVarP(&o.releaseName, "name", "", "RELEASE-NAME", "release name") + f.StringArrayVarP(&o.renderFiles, "execute", "x", []string{}, "only execute the given templates") + f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)") + f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.StringVar(&o.nameTemplate, "name-template", "", "specify template used to name the release") + f.StringVar(&o.kubeVersion, "kube-version", defaultKubeVersion, "kubernetes version used as Capabilities.KubeVersion.Major/Minor") + f.StringVar(&o.outputDir, "output-dir", "", "writes the executed templates to files in output-dir instead of stdout") return cmd } -func (t *templateCmd) run(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return errors.New("chart is required") - } - // verify chart path exists - if _, err := os.Stat(args[0]); err == nil { - if t.chartPath, err = filepath.Abs(args[0]); err != nil { - return err - } - } else { - return err - } +func (o *templateOptions) run(out io.Writer) error { // verify specified templates exist relative to chart rf := []string{} var af string var err error - if len(t.renderFiles) > 0 { - for _, f := range t.renderFiles { + if len(o.renderFiles) > 0 { + for _, f := range o.renderFiles { if !filepath.IsAbs(f) { - af, err = filepath.Abs(filepath.Join(t.chartPath, f)) + af, err = filepath.Abs(filepath.Join(o.chartPath, f)) if err != nil { return fmt.Errorf("could not resolve template path: %s", err) } @@ -136,29 +134,29 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { } // verify that output-dir exists if provided - if t.outputDir != "" { - _, err = os.Stat(t.outputDir) + if o.outputDir != "" { + _, err = os.Stat(o.outputDir) if os.IsNotExist(err) { - return fmt.Errorf("output-dir '%s' does not exist", t.outputDir) + return fmt.Errorf("output-dir '%s' does not exist", o.outputDir) } } // get combined values and create config - config, err := vals(t.valueFiles, t.values, t.stringValues) + config, err := vals(o.valueFiles, o.values, o.stringValues) if err != nil { return err } // If template is specified, try to run the template. - if t.nameTemplate != "" { - t.releaseName, err = generateName(t.nameTemplate) + if o.nameTemplate != "" { + o.releaseName, err = generateName(o.nameTemplate) if err != nil { return err } } // Check chart requirements to make sure all dependencies are present in /charts - c, err := chartutil.Load(t.chartPath) + c, err := chartutil.Load(o.chartPath) if err != nil { return err } @@ -171,7 +169,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { return fmt.Errorf("cannot load requirements: %v", err) } options := chartutil.ReleaseOptions{ - Name: t.releaseName, + Name: o.releaseName, Time: time.Now(), Namespace: getNamespace(), } @@ -195,7 +193,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { } // kubernetes version - kv, err := semver.NewVersion(t.kubeVersion) + kv, err := semver.NewVersion(o.kubeVersion) if err != nil { return fmt.Errorf("could not parse a kubernetes version: %v", err) } @@ -208,14 +206,14 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { return err } - out, err := renderer.Render(c, vals) + rendered, err := renderer.Render(c, vals) listManifests := []tiller.Manifest{} if err != nil { return err } // extract kind and name re := regexp.MustCompile("kind:(.*)\n") - for k, v := range out { + for k, v := range rendered { match := re.FindStringSubmatch(v) h := "Unknown" if len(match) == 2 { @@ -228,7 +226,7 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { // make needle path absolute d := strings.Split(needle, string(os.PathSeparator)) dd := d[1:] - an := filepath.Join(t.chartPath, strings.Join(dd, string(os.PathSeparator))) + an := filepath.Join(o.chartPath, strings.Join(dd, string(os.PathSeparator))) for _, h := range haystack { if h == an { @@ -239,34 +237,34 @@ func (t *templateCmd) run(cmd *cobra.Command, args []string) error { } if settings.Debug { rel := &release.Release{ - Name: t.releaseName, + Name: o.releaseName, Chart: c, Config: config, Version: 1, Info: &release.Info{LastDeployed: time.Now()}, } - printRelease(os.Stdout, rel) + printRelease(out, rel) } for _, m := range tiller.SortByKind(listManifests) { - if len(t.renderFiles) > 0 && !in(m.Name, rf) { + if len(o.renderFiles) > 0 && !in(m.Name, rf) { continue } data := m.Content b := filepath.Base(m.Name) - if !t.showNotes && b == "NOTES.txt" { + if !o.showNotes && b == "NOTES.txt" { continue } if strings.HasPrefix(b, "_") { continue } - if t.outputDir != "" { + if o.outputDir != "" { // blank template after execution if whitespaceRegex.MatchString(data) { continue } - err = writeToFile(t.outputDir, m.Name, data) + err = writeToFile(o.outputDir, m.Name, data) if err != nil { return err } diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 6f2611886..4e2a2efc0 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -53,10 +53,9 @@ set for a key called 'foo', the 'newbar' value would take precedence: $ helm upgrade --set foo=bar --set foo=newbar redis ./redis ` -type upgradeCmd struct { +type upgradeOptions struct { release string chart string - out io.Writer client helm.Interface dryRun bool recreate bool @@ -84,11 +83,7 @@ type upgradeCmd struct { } func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { - - upgrade := &upgradeCmd{ - out: out, - client: client, - } + o := &upgradeOptions{client: client} cmd := &cobra.Command{ Use: "upgrade [RELEASE] [CHART]", @@ -99,82 +94,81 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { return err } - if upgrade.version == "" && upgrade.devel { + if o.version == "" && o.devel { debug("setting version to >0.0.0-0") - upgrade.version = ">0.0.0-0" + o.version = ">0.0.0-0" } - upgrade.release = args[0] - upgrade.chart = args[1] - upgrade.client = ensureHelmClient(upgrade.client, false) + o.release = args[0] + o.chart = args[1] + o.client = ensureHelmClient(o.client, false) - return upgrade.run() + return o.run(out) }, } f := cmd.Flags() - f.VarP(&upgrade.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") - f.BoolVar(&upgrade.dryRun, "dry-run", false, "simulate an upgrade") - f.BoolVar(&upgrade.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable") - f.BoolVar(&upgrade.force, "force", false, "force resource update through delete/recreate if needed") - f.StringArrayVar(&upgrade.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.StringArrayVar(&upgrade.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") - f.BoolVar(&upgrade.disableHooks, "disable-hooks", false, "disable pre/post upgrade hooks. DEPRECATED. Use no-hooks") - f.BoolVar(&upgrade.disableHooks, "no-hooks", false, "disable pre/post upgrade hooks") - f.BoolVar(&upgrade.verify, "verify", false, "verify the provenance of the chart before upgrading") - f.StringVar(&upgrade.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys") - f.BoolVarP(&upgrade.install, "install", "i", false, "if a release by this name doesn't already exist, run an install") - f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used") - f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") - f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart") - f.BoolVar(&upgrade.reuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored.") - f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") - f.StringVar(&upgrade.repoURL, "repo", "", "chart repository url where to locate the requested chart") - f.StringVar(&upgrade.username, "username", "", "chart repository username where to locate the requested chart") - f.StringVar(&upgrade.password, "password", "", "chart repository password where to locate the requested chart") - f.StringVar(&upgrade.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") - f.StringVar(&upgrade.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") - f.StringVar(&upgrade.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") - f.BoolVar(&upgrade.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") + f.VarP(&o.valueFiles, "values", "f", "specify values in a YAML file or a URL(can specify multiple)") + f.BoolVar(&o.dryRun, "dry-run", false, "simulate an upgrade") + f.BoolVar(&o.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable") + f.BoolVar(&o.force, "force", false, "force resource update through delete/recreate if needed") + f.StringArrayVar(&o.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.StringArrayVar(&o.stringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") + f.BoolVar(&o.disableHooks, "disable-hooks", false, "disable pre/post upgrade hooks. DEPRECATED. Use no-hooks") + f.BoolVar(&o.disableHooks, "no-hooks", false, "disable pre/post upgrade hooks") + f.BoolVar(&o.verify, "verify", false, "verify the provenance of the chart before upgrading") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "path to the keyring that contains public signing keys") + f.BoolVarP(&o.install, "install", "i", false, "if a release by this name doesn't already exist, run an install") + f.StringVar(&o.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used") + f.Int64Var(&o.timeout, "timeout", 300, "time in seconds to wait for any individual Kubernetes operation (like Jobs for hooks)") + f.BoolVar(&o.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart") + f.BoolVar(&o.reuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored.") + f.BoolVar(&o.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout") + f.StringVar(&o.repoURL, "repo", "", "chart repository url where to locate the requested chart") + f.StringVar(&o.username, "username", "", "chart repository username where to locate the requested chart") + f.StringVar(&o.password, "password", "", "chart repository password where to locate the requested chart") + f.StringVar(&o.certFile, "cert-file", "", "identify HTTPS client using this SSL certificate file") + f.StringVar(&o.keyFile, "key-file", "", "identify HTTPS client using this SSL key file") + f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") + f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") f.MarkDeprecated("disable-hooks", "use --no-hooks instead") return cmd } -func (u *upgradeCmd) run() error { - chartPath, err := locateChartPath(u.repoURL, u.username, u.password, u.chart, u.version, u.verify, u.keyring, u.certFile, u.keyFile, u.caFile) +func (o *upgradeOptions) run(out io.Writer) error { + chartPath, err := locateChartPath(o.repoURL, o.username, o.password, o.chart, o.version, o.verify, o.keyring, o.certFile, o.keyFile, o.caFile) if err != nil { return err } - if u.install { + if o.install { // If a release does not exist, install it. If another error occurs during // the check, ignore the error and continue with the upgrade. - _, err := u.client.ReleaseHistory(u.release, 1) + _, err := o.client.ReleaseHistory(o.release, 1) - if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(u.release).Error()) { - fmt.Fprintf(u.out, "Release %q does not exist. Installing it now.\n", u.release) - ic := &installCmd{ + if err != nil && strings.Contains(err.Error(), driver.ErrReleaseNotFound(o.release).Error()) { + fmt.Fprintf(out, "Release %q does not exist. Installing it now.\n", o.release) + io := &installOptions{ chartPath: chartPath, - client: u.client, - out: u.out, - name: u.release, - valueFiles: u.valueFiles, - dryRun: u.dryRun, - verify: u.verify, - disableHooks: u.disableHooks, - keyring: u.keyring, - values: u.values, - stringValues: u.stringValues, - timeout: u.timeout, - wait: u.wait, + client: o.client, + name: o.release, + valueFiles: o.valueFiles, + dryRun: o.dryRun, + verify: o.verify, + disableHooks: o.disableHooks, + keyring: o.keyring, + values: o.values, + stringValues: o.stringValues, + timeout: o.timeout, + wait: o.wait, } - return ic.run() + return io.run(out) } } - rawVals, err := vals(u.valueFiles, u.values, u.stringValues) + rawVals, err := vals(o.valueFiles, o.values, o.stringValues) if err != nil { return err } @@ -192,34 +186,34 @@ func (u *upgradeCmd) run() error { return err } - resp, err := u.client.UpdateRelease( - u.release, + resp, err := o.client.UpdateRelease( + o.release, chartPath, helm.UpdateValueOverrides(rawVals), - helm.UpgradeDryRun(u.dryRun), - helm.UpgradeRecreate(u.recreate), - helm.UpgradeForce(u.force), - helm.UpgradeDisableHooks(u.disableHooks), - helm.UpgradeTimeout(u.timeout), - helm.ResetValues(u.resetValues), - helm.ReuseValues(u.reuseValues), - helm.UpgradeWait(u.wait)) + helm.UpgradeDryRun(o.dryRun), + helm.UpgradeRecreate(o.recreate), + helm.UpgradeForce(o.force), + helm.UpgradeDisableHooks(o.disableHooks), + helm.UpgradeTimeout(o.timeout), + helm.ResetValues(o.resetValues), + helm.ReuseValues(o.reuseValues), + helm.UpgradeWait(o.wait)) if err != nil { return fmt.Errorf("UPGRADE FAILED: %v", err) } if settings.Debug { - printRelease(u.out, resp) + printRelease(out, resp) } - fmt.Fprintf(u.out, "Release %q has been upgraded. Happy Helming!\n", u.release) + fmt.Fprintf(out, "Release %q has been upgraded. Happy Helming!\n", o.release) // Print the status like status command does - status, err := u.client.ReleaseStatus(u.release, 0) + status, err := o.client.ReleaseStatus(o.release, 0) if err != nil { return err } - PrintStatus(u.out, status) + PrintStatus(out, status) return nil } diff --git a/cmd/helm/verify.go b/cmd/helm/verify.go index e82eb4e33..c1a1e975d 100644 --- a/cmd/helm/verify.go +++ b/cmd/helm/verify.go @@ -35,15 +35,13 @@ This command can be used to verify a local chart. Several other commands provide the 'helm package --sign' command. ` -type verifyCmd struct { +type verifyOptions struct { keyring string chartfile string - - out io.Writer } func newVerifyCmd(out io.Writer) *cobra.Command { - vc := &verifyCmd{out: out} + o := &verifyOptions{} cmd := &cobra.Command{ Use: "verify [flags] PATH", @@ -53,18 +51,18 @@ func newVerifyCmd(out io.Writer) *cobra.Command { if len(args) == 0 { return errors.New("a path to a package file is required") } - vc.chartfile = args[0] - return vc.run() + o.chartfile = args[0] + return o.run(out) }, } f := cmd.Flags() - f.StringVar(&vc.keyring, "keyring", defaultKeyring(), "keyring containing public keys") + f.StringVar(&o.keyring, "keyring", defaultKeyring(), "keyring containing public keys") return cmd } -func (v *verifyCmd) run() error { - _, err := downloader.VerifyChart(v.chartfile, v.keyring) +func (o *verifyOptions) run(out io.Writer) error { + _, err := downloader.VerifyChart(o.chartfile, o.keyring) return err } diff --git a/cmd/helm/version.go b/cmd/helm/version.go index 100259896..7641523b9 100644 --- a/cmd/helm/version.go +++ b/cmd/helm/version.go @@ -40,39 +40,38 @@ version.BuildInfo{Version:"v2.0.0", GitCommit:"ff52399e51bb880526e9cd0ed8386f643 built, and "dirty" if the binary was built from locally modified code. ` -type versionCmd struct { - out io.Writer +type versionOptions struct { short bool template string } func newVersionCmd(out io.Writer) *cobra.Command { - version := &versionCmd{out: out} + o := &versionOptions{} cmd := &cobra.Command{ Use: "version", Short: "print the client version information", Long: versionDesc, RunE: func(cmd *cobra.Command, args []string) error { - return version.run() + return o.run(out) }, } f := cmd.Flags() - f.BoolVar(&version.short, "short", false, "print the version number") - f.StringVar(&version.template, "template", "", "template for version string format") + f.BoolVar(&o.short, "short", false, "print the version number") + f.StringVar(&o.template, "template", "", "template for version string format") return cmd } -func (v *versionCmd) run() error { - if v.template != "" { - tt, err := template.New("_").Parse(v.template) +func (o *versionOptions) run(out io.Writer) error { + if o.template != "" { + tt, err := template.New("_").Parse(o.template) if err != nil { return err } - return tt.Execute(v.out, version.GetBuildInfo()) + return tt.Execute(out, version.GetBuildInfo()) } - fmt.Fprintln(v.out, formatVersion(v.short)) + fmt.Fprintln(out, formatVersion(o.short)) return nil }