From 3e5b181a300bcfbdf2abff990904e4f5f3e8fc35 Mon Sep 17 00:00:00 2001 From: Taylor Thomas Date: Fri, 6 Sep 2019 15:34:24 -0600 Subject: [PATCH] ref(cmd): Refactors output flag to reuse more code This cuts down on the number of duplicate json/yaml marshaling blocks and simplifies how to add printing to a function by using simple "container" structs that know how to massage the data Signed-off-by: Taylor Thomas --- cmd/helm/install.go | 14 +---- cmd/helm/printer.go | 78 ++++++++++++++++++++++++ cmd/helm/repo_list.go | 82 ++++++++++--------------- cmd/helm/search.go | 116 ++++++++++++++++-------------------- cmd/helm/search_test.go | 9 ++- cmd/helm/status.go | 78 ++++++++---------------- cmd/helm/upgrade.go | 14 +---- docs/helm/helm_install.md | 2 +- docs/helm/helm_repo_list.md | 2 +- docs/helm/helm_search.md | 2 +- docs/helm/helm_status.md | 2 +- docs/helm/helm_upgrade.md | 2 +- 12 files changed, 199 insertions(+), 202 deletions(-) diff --git a/cmd/helm/install.go b/cmd/helm/install.go index a0fa6edfb..117c7ba5b 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -227,7 +227,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { f.BoolVar(&inst.depUp, "dep-up", false, "Run helm dependency update before installing the chart") f.BoolVar(&inst.subNotes, "render-subchart-notes", false, "Render subchart notes along with the parent") f.StringVar(&inst.description, "description", "", "Specify a description for the release") - f.StringVarP(&inst.output, "output", "o", "table", "Prints the output in the specified format (json|table|yaml)") + bindOutputFlag(cmd, &inst.output) // set defaults from environment settings.InitTLS(f) @@ -338,7 +338,7 @@ func (i *installCmd) run() error { return nil } - if i.output == "table" { + if outputFormat(i.output) == outputTable { i.printRelease(rel) } @@ -357,15 +357,7 @@ func (i *installCmd) run() error { return prettyError(err) } - output, err := PrintStatusFormated(i.output, status) - - if err != nil { - return err - } - - fmt.Fprintf(i.out, output) - - return nil + return write(i.out, &statusWriter{status}, outputFormat(i.output)) } // Merges source and destination map, preferring values from the source map diff --git a/cmd/helm/printer.go b/cmd/helm/printer.go index 2f42bdab0..1c89c04ef 100644 --- a/cmd/helm/printer.go +++ b/cmd/helm/printer.go @@ -17,16 +17,31 @@ limitations under the License. package main import ( + "encoding/json" "fmt" "io" "text/template" "time" + "github.com/ghodss/yaml" + "github.com/gosuri/uitable" + "github.com/spf13/cobra" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/proto/hapi/release" "k8s.io/helm/pkg/timeconv" ) +type outputFormat string + +const ( + outputFlag = "output" + + outputTable outputFormat = "table" + outputJSON outputFormat = "json" + outputYAML outputFormat = "yaml" +) + var printReleaseTemplate = `REVISION: {{.Release.Version}} RELEASED: {{.ReleaseDate}} CHART: {{.Release.Chart.Metadata.Name}}-{{.Release.Chart.Metadata.Version}} @@ -80,3 +95,66 @@ func debug(format string, args ...interface{}) { fmt.Printf(format, args...) } } + +// bindOutputFlag will add the output flag to the given command and bind the +// value to the given string pointer +func bindOutputFlag(cmd *cobra.Command, varRef *string) { + cmd.Flags().StringVarP(varRef, outputFlag, "o", string(outputTable), fmt.Sprintf("Prints the output in the specified format. Allowed values: %s, %s, %s", outputTable, outputJSON, outputYAML)) +} + +type outputWriter interface { + WriteTable(out io.Writer) error + WriteJSON(out io.Writer) error + WriteYAML(out io.Writer) error +} + +func write(out io.Writer, ow outputWriter, format outputFormat) error { + switch format { + case outputTable: + return ow.WriteTable(out) + case outputJSON: + return ow.WriteJSON(out) + case outputYAML: + return ow.WriteYAML(out) + } + return fmt.Errorf("unsupported format %s", format) +} + +// encodeJSON is a helper function to decorate any error message with a bit more +// context and avoid writing the same code over and over for printers +func encodeJSON(out io.Writer, obj interface{}) error { + enc := json.NewEncoder(out) + err := enc.Encode(obj) + if err != nil { + return fmt.Errorf("unable to write JSON output: %s", err) + } + return nil +} + +// encodeYAML is a helper function to decorate any error message with a bit more +// context and avoid writing the same code over and over for printers +func encodeYAML(out io.Writer, obj interface{}) error { + raw, err := yaml.Marshal(obj) + if err != nil { + return fmt.Errorf("unable to write YAML output: %s", err) + } + // Append a newline, as with a JSON encoder + raw = append(raw, []byte("\n")...) + _, err = out.Write(raw) + if err != nil { + return fmt.Errorf("unable to write YAML output: %s", err) + } + return nil +} + +// encodeTable is a helper function to decorate any error message with a bit +// more context and avoid writing the same code over and over for printers +func encodeTable(out io.Writer, table *uitable.Table) error { + raw := table.Bytes() + raw = append(raw, []byte("\n")...) + _, err := out.Write(raw) + if err != nil { + return fmt.Errorf("unable to write table output: %s", err) + } + return nil +} diff --git a/cmd/helm/repo_list.go b/cmd/helm/repo_list.go index 633bb7a75..a65b81908 100644 --- a/cmd/helm/repo_list.go +++ b/cmd/helm/repo_list.go @@ -17,12 +17,8 @@ limitations under the License. package main import ( - "encoding/json" - "fmt" "io" - "strings" - "github.com/ghodss/yaml" "github.com/gosuri/uitable" "github.com/spf13/cobra" @@ -41,10 +37,6 @@ type repositoryElement struct { URL string } -type repositories struct { - Repositories []*repositoryElement -} - func newRepoListCmd(out io.Writer) *cobra.Command { list := &repoListCmd{out: out} @@ -57,8 +49,7 @@ func newRepoListCmd(out io.Writer) *cobra.Command { }, } - f := cmd.Flags() - f.StringVarP(&list.output, "output", "o", "table", "Prints the output in the specified format (json|table|yaml)") + bindOutputFlag(cmd, &list.output) return cmd } @@ -68,59 +59,46 @@ func (a *repoListCmd) run() error { return err } - output, err := formatRepoListResult(a.output, repoFile) - - if err != nil { - return err - } - fmt.Fprintln(a.out, output) - - return nil + return write(a.out, &repoListWriter{repoFile.Repositories}, outputFormat(a.output)) } -func formatRepoListResult(format string, repoFile *repo.RepoFile) (string, error) { - var output string - var err error +//////////// Printer implementation below here +type repoListWriter struct { + repos []*repo.Entry +} - if len(repoFile.Repositories) == 0 { - err = fmt.Errorf("no repositories to show") - return output, err +func (r *repoListWriter) WriteTable(out io.Writer) error { + table := uitable.New() + table.AddRow("NAME", "URL") + for _, re := range r.repos { + table.AddRow(re.Name, re.URL) } + return encodeTable(out, table) +} - switch format { - case "table": - table := uitable.New() - table.AddRow("NAME", "URL") - for _, re := range repoFile.Repositories { - table.AddRow(re.Name, re.URL) - } - output = table.String() - - case "json": - output, err = printFormatedRepoFile(format, repoFile, json.Marshal) - - case "yaml": - output, err = printFormatedRepoFile(format, repoFile, yaml.Marshal) - } +func (r *repoListWriter) WriteJSON(out io.Writer) error { + return r.encodeByFormat(out, outputJSON) +} - return output, err +func (r *repoListWriter) WriteYAML(out io.Writer) error { + return r.encodeByFormat(out, outputYAML) } -func printFormatedRepoFile(format string, repoFile *repo.RepoFile, obj func(v interface{}) ([]byte, error)) (string, error) { - var output string - var err error - var repolist repositories +func (r *repoListWriter) encodeByFormat(out io.Writer, format outputFormat) error { + var repolist []repositoryElement - for _, re := range repoFile.Repositories { - repolist.Repositories = append(repolist.Repositories, &repositoryElement{Name: re.Name, URL: re.URL}) + for _, re := range r.repos { + repolist = append(repolist, repositoryElement{Name: re.Name, URL: re.URL}) } - o, e := obj(repolist) - if e != nil { - err = fmt.Errorf("Failed to Marshal %s output: %s", strings.ToUpper(format), e) - } else { - output = string(o) + switch format { + case outputJSON: + return encodeJSON(out, repolist) + case outputYAML: + return encodeYAML(out, repolist) } - return output, err + // Because this is a non-exported function and only called internally by + // WriteJSON and WriteYAML, we shouldn't get invalid types + return nil } diff --git a/cmd/helm/search.go b/cmd/helm/search.go index 92e842823..b55997ec8 100644 --- a/cmd/helm/search.go +++ b/cmd/helm/search.go @@ -17,13 +17,11 @@ limitations under the License. package main import ( - "encoding/json" "fmt" "io" "strings" "github.com/Masterminds/semver" - "github.com/ghodss/yaml" "github.com/gosuri/uitable" "github.com/spf13/cobra" @@ -60,10 +58,6 @@ type chartElement struct { Description string } -type searchResult struct { - Charts []*chartElement -} - func newSearchCmd(out io.Writer) *cobra.Command { sc := &searchCmd{out: out} @@ -82,7 +76,7 @@ func newSearchCmd(out io.Writer) *cobra.Command { 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.UintVar(&sc.colWidth, "col-width", 60, "Specifies the max column width of output") - f.StringVarP(&sc.output, "output", "o", "table", "Prints the output in the specified format (json|table|yaml)") + bindOutputFlag(cmd, &sc.output) return cmd } @@ -110,14 +104,7 @@ func (s *searchCmd) run(args []string) error { return err } - o, err := s.formatSearchResults(s.output, data, s.colWidth) - if err != nil { - return err - } - - fmt.Fprintln(s.out, o) - - return nil + return write(s.out, &searchWriter{data, s.colWidth}, outputFormat(s.output)) } func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, error) { @@ -148,55 +135,6 @@ func (s *searchCmd) applyConstraint(res []*search.Result) ([]*search.Result, err return data, nil } -func (s *searchCmd) formatSearchResults(format string, res []*search.Result, colWidth uint) (string, error) { - var output string - var err error - - switch format { - case "table": - if len(res) == 0 { - return "No results found", nil - } - table := uitable.New() - table.MaxColWidth = colWidth - table.AddRow("NAME", "CHART VERSION", "APP VERSION", "DESCRIPTION") - for _, r := range res { - table.AddRow(r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description) - } - output = table.String() - - case "json": - output, err = s.printFormated(format, res, json.Marshal) - - case "yaml": - output, err = s.printFormated(format, res, yaml.Marshal) - } - - return output, err -} - -func (s *searchCmd) printFormated(format string, res []*search.Result, obj func(v interface{}) ([]byte, error)) (string, error) { - var sResult searchResult - var output string - var err error - - if len(res) == 0 { - return "[]", nil - } - - for _, r := range res { - sResult.Charts = append(sResult.Charts, &chartElement{r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description}) - } - - o, e := obj(sResult) - if e != nil { - err = fmt.Errorf("Failed to Marshal %s output: %s", strings.ToUpper(format), e) - } else { - output = string(o) - } - return output, err -} - func (s *searchCmd) buildIndex() (*search.Index, error) { // Load the repositories.yaml rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile()) @@ -218,3 +156,53 @@ func (s *searchCmd) buildIndex() (*search.Index, error) { } return i, nil } + +//////////// Printer implementation below here +type searchWriter struct { + results []*search.Result + columnWidth uint +} + +func (r *searchWriter) WriteTable(out io.Writer) error { + if len(r.results) == 0 { + _, err := out.Write([]byte("No results found\n")) + if err != nil { + return fmt.Errorf("unable to write results: %s", err) + } + return nil + } + table := uitable.New() + table.MaxColWidth = r.columnWidth + table.AddRow("NAME", "CHART VERSION", "APP VERSION", "DESCRIPTION") + for _, r := range r.results { + table.AddRow(r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description) + } + return encodeTable(out, table) +} + +func (r *searchWriter) WriteJSON(out io.Writer) error { + return r.encodeByFormat(out, outputJSON) +} + +func (r *searchWriter) WriteYAML(out io.Writer) error { + return r.encodeByFormat(out, outputYAML) +} + +func (r *searchWriter) encodeByFormat(out io.Writer, format outputFormat) error { + var chartList []chartElement + + for _, r := range r.results { + chartList = append(chartList, chartElement{r.Name, r.Chart.Version, r.Chart.AppVersion, r.Chart.Description}) + } + + switch format { + case outputJSON: + return encodeJSON(out, chartList) + case outputYAML: + return encodeYAML(out, chartList) + } + + // Because this is a non-exported function and only called internally by + // WriteJSON and WriteYAML, we shouldn't get invalid types + return nil +} diff --git a/cmd/helm/search_test.go b/cmd/helm/search_test.go index 35a72260e..12824407c 100644 --- a/cmd/helm/search_test.go +++ b/cmd/helm/search_test.go @@ -18,7 +18,6 @@ package main import ( "io" - "regexp" "strings" "testing" @@ -90,25 +89,25 @@ func TestSearchCmd(t *testing.T) { name: "search for 'maria', expect one match output json", args: []string{"maria"}, flags: strings.Split("--output json", " "), - expected: regexp.QuoteMeta(`{"Charts":[{"Name":"testing/mariadb","Version":"0.3.0","AppVersion":"","Description":"Chart for MariaDB"}]}`), + expected: `[{"Name":"testing/mariadb","Version":"0.3.0","Appversion":"","Description":"Chart for MariaDB"}]`, }, { name: "search for 'alpine', expect two matches output json", args: []string{"alpine"}, flags: strings.Split("--output json", " "), - expected: regexp.QuoteMeta(`{"Charts":[{"Name":"testing/alpine","Version":"0.2.0","AppVersion":"2.3.4","Description":"Deploy a basic Alpine Linux pod"}]}`), + expected: `[{"Name":"testing/alpine","Version":"0.2.0","Appversion":"2.3.4","Description":"Deploy a basic Alpine Linux pod"}]`, }, { name: "search for 'maria', expect one match output yaml", args: []string{"maria"}, flags: strings.Split("--output yaml", " "), - expected: "Charts:\n- AppVersion: \"\"\n Description: Chart for MariaDB\n Name: testing/mariadb\n Version: 0.3.0\n\n", + expected: "- AppVersion: \"\"\n Description: Chart for MariaDB\n Name: testing/mariadb\n Version: 0.3.0\n\n", }, { name: "search for 'alpine', expect two matches output yaml", args: []string{"alpine"}, flags: strings.Split("--output yaml", " "), - expected: "Charts:\n- AppVersion: 2.3.4\n Description: Deploy a basic Alpine Linux pod\n Name: testing/alpine\n Version: 0.2.0\n\n", + expected: "- AppVersion: 2.3.4\n Description: Deploy a basic Alpine Linux pod\n Name: testing/alpine\n Version: 0.2.0\n\n", }, } diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 65025c8cc..23120980a 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -17,14 +17,11 @@ limitations under the License. package main import ( - "encoding/json" "fmt" "io" "regexp" - "strings" "text/tabwriter" - "github.com/ghodss/yaml" "github.com/gosuri/uitable" "github.com/gosuri/uitable/util/strutil" "github.com/spf13/cobra" @@ -80,7 +77,7 @@ func newStatusCmd(client helm.Interface, out io.Writer) *cobra.Command { f := cmd.Flags() settings.AddFlagsTLS(f) f.Int32Var(&status.version, "revision", 0, "If set, display the status of the named release with revision") - f.StringVarP(&status.outfmt, "output", "o", "table", "Prints the output in the specified format (json|table|yaml)") + bindOutputFlag(cmd, &status.outfmt) // set defaults from environment settings.InitTLS(f) @@ -94,82 +91,55 @@ func (s *statusCmd) run() error { return prettyError(err) } - output, err := PrintStatusFormated(s.outfmt, res) - - if err != nil { - return err - } + return write(s.out, &statusWriter{res}, outputFormat(s.outfmt)) +} - fmt.Fprintf(s.out, output) +type statusWriter struct { + status *services.GetReleaseStatusResponse +} +func (s *statusWriter) WriteTable(out io.Writer) error { + PrintStatus(out, s.status) + // There is no error handling here due to backwards compatibility with + // PrintStatus return nil } -// PrintStatusFormated prints out the status of a release. Shared because also used by -// install / upgrade -func PrintStatusFormated(format string, res *services.GetReleaseStatusResponse) (string, error) { - var output string - var err error - - switch format { - case "table": - output = printStatus(res) - - case "json": - output, err = printFormatedReleaseStatus(format, res, json.Marshal) - - case "yaml": - output, err = printFormatedReleaseStatus(format, res, yaml.Marshal) - - default: - err = fmt.Errorf("Unknown output format %q", err) - } - - return output, err +func (s *statusWriter) WriteJSON(out io.Writer) error { + return encodeJSON(out, s.status) } -func printFormatedReleaseStatus(format string, res *services.GetReleaseStatusResponse, obj func(v interface{}) ([]byte, error)) (string, error) { - var output string - var err error - - o, err := obj(res) - if err != nil { - return "", fmt.Errorf("Failed to Marshal %s output: %s", strings.ToUpper(format), err) - } - output = string(o) - - return output, err +func (s *statusWriter) WriteYAML(out io.Writer) error { + return encodeYAML(out, s.status) } -func printStatus(res *services.GetReleaseStatusResponse) string { - var out strings.Builder - +// PrintStatus prints out the status of a release. Shared because also used by +// install / upgrade +func PrintStatus(out io.Writer, res *services.GetReleaseStatusResponse) { if res.Info.LastDeployed != nil { - fmt.Fprintf(&out, "LAST DEPLOYED: %s\n", timeconv.String(res.Info.LastDeployed)) + fmt.Fprintf(out, "LAST DEPLOYED: %s\n", timeconv.String(res.Info.LastDeployed)) } - fmt.Fprintf(&out, "NAMESPACE: %s\n", res.Namespace) - fmt.Fprintf(&out, "STATUS: %s\n", res.Info.Status.Code) - fmt.Fprintf(&out, "\n") + fmt.Fprintf(out, "NAMESPACE: %s\n", res.Namespace) + fmt.Fprintf(out, "STATUS: %s\n", res.Info.Status.Code) + fmt.Fprintf(out, "\n") if len(res.Info.Status.Resources) > 0 { re := regexp.MustCompile(" +") - w := tabwriter.NewWriter(&out, 0, 0, 2, ' ', tabwriter.TabIndent) + w := tabwriter.NewWriter(out, 0, 0, 2, ' ', tabwriter.TabIndent) fmt.Fprintf(w, "RESOURCES:\n%s\n", re.ReplaceAllString(res.Info.Status.Resources, "\t")) w.Flush() } if res.Info.Status.LastTestSuiteRun != nil { lastRun := res.Info.Status.LastTestSuiteRun - fmt.Fprintf(&out, "TEST SUITE:\n%s\n%s\n\n%s\n", + fmt.Fprintf(out, "TEST SUITE:\n%s\n%s\n\n%s\n", fmt.Sprintf("Last Started: %s", timeconv.String(lastRun.StartedAt)), fmt.Sprintf("Last Completed: %s", timeconv.String(lastRun.CompletedAt)), formatTestResults(lastRun.Results)) } if len(res.Info.Status.Notes) > 0 { - fmt.Fprintf(&out, "NOTES:\n%s\n", res.Info.Status.Notes) + fmt.Fprintf(out, "NOTES:\n%s\n", res.Info.Status.Notes) } - - return out.String() } func formatTestResults(results []*release.TestRun) string { diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 5c5af66cc..a105820a6 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -182,7 +182,7 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { f.BoolVar(&upgrade.subNotes, "render-subchart-notes", false, "Render subchart notes along with parent") f.StringVar(&upgrade.description, "description", "", "Specify the description to use for the upgrade, rather than the default") f.BoolVar(&upgrade.cleanupOnFail, "cleanup-on-fail", false, "Allow deletion of new resources created in this upgrade when upgrade failed") - f.StringVarP(&upgrade.output, "output", "o", "table", "Prints the output in the specified format (json|table|yaml)") + bindOutputFlag(cmd, &upgrade.output) f.MarkDeprecated("disable-hooks", "Use --no-hooks instead") @@ -309,7 +309,7 @@ func (u *upgradeCmd) run() error { printRelease(u.out, resp.Release) } - if u.output == "table" { + if outputFormat(u.output) == outputTable { fmt.Fprintf(u.out, "Release %q has been upgraded.\n", u.release) } // Print the status like status command does @@ -318,13 +318,5 @@ func (u *upgradeCmd) run() error { return prettyError(err) } - output, err := PrintStatusFormated(u.output, status) - - if err != nil { - return err - } - - fmt.Fprintf(u.out, output) - - return nil + return write(u.out, &statusWriter{status}, outputFormat(u.output)) } diff --git a/docs/helm/helm_install.md b/docs/helm/helm_install.md index dc0591f6a..d44f9ded5 100644 --- a/docs/helm/helm_install.md +++ b/docs/helm/helm_install.md @@ -93,7 +93,7 @@ helm install [CHART] [flags] --namespace string Namespace to install the release into. Defaults to the current kube config namespace. --no-crd-hook Prevent CRD hooks from running, but run other hooks --no-hooks Prevent hooks from running during install - -o, --output string Prints the output in the specified format (json|table|yaml) (default "table") + -o, --output string Prints the output in the specified format. Allowed values: table, json, yaml (default "table") --password string Chart repository password where to locate the requested chart --render-subchart-notes Render subchart notes along with the parent --replace Re-use the given name, even if that name is already used. This is unsafe in production diff --git a/docs/helm/helm_repo_list.md b/docs/helm/helm_repo_list.md index 5f13c8c2d..3ff2cbaf0 100644 --- a/docs/helm/helm_repo_list.md +++ b/docs/helm/helm_repo_list.md @@ -14,7 +14,7 @@ helm repo list [flags] ``` -h, --help help for list - -o, --output string Prints the output in the specified format (json|table|yaml) (default "table") + -o, --output string Prints the output in the specified format. Allowed values: table, json, yaml (default "table") ``` ### Options inherited from parent commands diff --git a/docs/helm/helm_search.md b/docs/helm/helm_search.md index e040b738f..558cadfee 100644 --- a/docs/helm/helm_search.md +++ b/docs/helm/helm_search.md @@ -20,7 +20,7 @@ helm search [keyword] [flags] ``` --col-width uint Specifies the max column width of output (default 60) -h, --help help for search - -o, --output string Prints the output in the specified format (json|table|yaml) (default "table") + -o, --output string Prints the output in the specified format. Allowed values: table, json, yaml (default "table") -r, --regexp Use regular expressions for searching -v, --version string Search using semantic versioning constraints -l, --versions Show the long listing, with each version of each chart on its own line diff --git a/docs/helm/helm_status.md b/docs/helm/helm_status.md index 2c75ce21a..91c3a1427 100644 --- a/docs/helm/helm_status.md +++ b/docs/helm/helm_status.md @@ -23,7 +23,7 @@ helm status [flags] RELEASE_NAME ``` -h, --help help for status - -o, --output string Prints the output in the specified format (json|table|yaml) (default "table") + -o, --output string Prints the output in the specified format. Allowed values: table, json, yaml (default "table") --revision int32 If set, display the status of the named release with revision --tls Enable TLS for request --tls-ca-cert string Path to TLS CA certificate file (default "$HELM_HOME/ca.pem") diff --git a/docs/helm/helm_upgrade.md b/docs/helm/helm_upgrade.md index effb505f9..35888d568 100644 --- a/docs/helm/helm_upgrade.md +++ b/docs/helm/helm_upgrade.md @@ -79,7 +79,7 @@ helm upgrade [RELEASE] [CHART] [flags] --keyring string Path to the keyring that contains public signing keys (default "~/.gnupg/pubring.gpg") --namespace string Namespace to install the release into (only used if --install is set). Defaults to the current kube config namespace --no-hooks Disable pre/post upgrade hooks - -o, --output string Prints the output in the specified format (json|table|yaml) (default "table") + -o, --output string Prints the output in the specified format. Allowed values: table, json, yaml (default "table") --password string Chart repository password where to locate the requested chart --recreate-pods Performs pods restart for the resource if applicable --render-subchart-notes Render subchart notes along with parent