diff --git a/cmd/helm/completion_test.go b/cmd/helm/completion_test.go index 7eee398327d..bd94f6b4c8e 100644 --- a/cmd/helm/completion_test.go +++ b/cmd/helm/completion_test.go @@ -29,9 +29,14 @@ import ( func checkFileCompletion(t *testing.T, cmdName string, shouldBePerformed bool) { storage := storageFixture() storage.Create(&release.Release{ - Name: "myrelease", - Info: &release.Info{Status: release.StatusDeployed}, - Chart: &chart.Chart{}, + Name: "myrelease", + Info: &release.Info{Status: release.StatusDeployed}, + Chart: &chart.Chart{ + Metadata: &chart.Metadata{ + Name: "Myrelease-Chart", + Version: "1.2.3", + }, + }, Version: 1, }) diff --git a/cmd/helm/flags.go b/cmd/helm/flags.go index 5b028863204..87dc23fdc38 100644 --- a/cmd/helm/flags.go +++ b/cmd/helm/flags.go @@ -21,6 +21,7 @@ import ( "fmt" "log" "path/filepath" + "sort" "strings" "github.com/spf13/cobra" @@ -66,11 +67,14 @@ func bindOutputFlag(cmd *cobra.Command, varRef *output.Format) { err := cmd.RegisterFlagCompletionFunc(outputFlag, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { var formatNames []string - for _, format := range output.Formats() { + for format, desc := range output.FormatsWithDesc() { if strings.HasPrefix(format, toComplete) { - formatNames = append(formatNames, format) + formatNames = append(formatNames, fmt.Sprintf("%s\t%s", format, desc)) } } + + // Sort the results to get a deterministic order for the tests + sort.Strings(formatNames) return formatNames, cobra.ShellCompDirectiveNoFileComp }) @@ -150,7 +154,21 @@ func compVersionFlag(chartRef string, toComplete string) ([]string, cobra.ShellC for _, details := range indexFile.Entries[chartName] { version := details.Metadata.Version if strings.HasPrefix(version, toComplete) { - versions = append(versions, version) + appVersion := details.Metadata.AppVersion + appVersionDesc := "" + if appVersion != "" { + appVersionDesc = fmt.Sprintf("App: %s, ", appVersion) + } + created := details.Created.Format("January 2, 2006") + createdDesc := "" + if created != "" { + createdDesc = fmt.Sprintf("Created: %s ", created) + } + deprecated := "" + if details.Metadata.Deprecated { + deprecated = "(deprecated)" + } + versions = append(versions, fmt.Sprintf("%s\t%s%s%s", version, appVersionDesc, createdDesc, deprecated)) } } } diff --git a/cmd/helm/history.go b/cmd/helm/history.go index f55eea9fd76..61f45c94658 100644 --- a/cmd/helm/history.go +++ b/cmd/helm/history.go @@ -193,7 +193,9 @@ func compListRevisions(toComplete string, cfg *action.Configuration, releaseName for _, release := range hist { version := strconv.Itoa(release.Version) if strings.HasPrefix(version, toComplete) { - revisions = append(revisions, version) + appVersion := fmt.Sprintf("App: %s", release.Chart.Metadata.AppVersion) + chartDesc := fmt.Sprintf("Chart: %s-%s", release.Chart.Metadata.Name, release.Chart.Metadata.Version) + revisions = append(revisions, fmt.Sprintf("%s\t%s, %s", version, appVersion, chartDesc)) } } return revisions, cobra.ShellCompDirectiveNoFileComp diff --git a/cmd/helm/list.go b/cmd/helm/list.go index 9d7bea439c2..a1db03cf65d 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -203,14 +203,15 @@ func compListReleases(toComplete string, cfg *action.Configuration) ([]string, c client.Filter = fmt.Sprintf("^%s", toComplete) client.SetStateMask() - results, err := client.Run() + releases, err := client.Run() if err != nil { return nil, cobra.ShellCompDirectiveDefault } var choices []string - for _, res := range results { - choices = append(choices, res.Name) + for _, rel := range releases { + choices = append(choices, + fmt.Sprintf("%s\t%s-%s -> %s", rel.Name, rel.Chart.Metadata.Name, rel.Chart.Metadata.Version, rel.Info.Status.String())) } return choices, cobra.ShellCompDirectiveNoFileComp diff --git a/cmd/helm/plugin_list.go b/cmd/helm/plugin_list.go index eb4e5c8153d..6c3926a9d55 100644 --- a/cmd/helm/plugin_list.go +++ b/cmd/helm/plugin_list.go @@ -83,7 +83,7 @@ func compListPlugins(toComplete string, ignoredPluginNames []string) []string { filteredPlugins := filterPlugins(plugins, ignoredPluginNames) for _, p := range filteredPlugins { if strings.HasPrefix(p.Metadata.Name, toComplete) { - pNames = append(pNames, p.Metadata.Name) + pNames = append(pNames, fmt.Sprintf("%s\t%s", p.Metadata.Name, p.Metadata.Usage)) } } } diff --git a/cmd/helm/root.go b/cmd/helm/root.go index 8025a9ddf6e..de24a6208a4 100644 --- a/cmd/helm/root.go +++ b/cmd/helm/root.go @@ -131,13 +131,13 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string if config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( loadingRules, &clientcmd.ConfigOverrides{}).RawConfig(); err == nil { - ctxs := []string{} - for name := range config.Contexts { + comps := []string{} + for name, context := range config.Contexts { if strings.HasPrefix(name, toComplete) { - ctxs = append(ctxs, name) + comps = append(comps, fmt.Sprintf("%s\t%s", name, context.Cluster)) } } - return ctxs, cobra.ShellCompDirectiveNoFileComp + return comps, cobra.ShellCompDirectiveNoFileComp } return nil, cobra.ShellCompDirectiveNoFileComp }) diff --git a/cmd/helm/status_test.go b/cmd/helm/status_test.go index 280f486a355..7f305d56bae 100644 --- a/cmd/helm/status_test.go +++ b/cmd/helm/status_test.go @@ -118,56 +118,72 @@ func mustParseTime(t string) helmtime.Time { } func TestStatusCompletion(t *testing.T) { - releasesMockWithStatus := func(info *release.Info, hooks ...*release.Hook) []*release.Release { - info.LastDeployed = helmtime.Unix(1452902400, 0).UTC() - return []*release.Release{{ + rels := []*release.Release{ + { Name: "athos", Namespace: "default", - Info: info, - Chart: &chart.Chart{}, - Hooks: hooks, + Info: &release.Info{ + Status: release.StatusDeployed, + }, + Chart: &chart.Chart{ + Metadata: &chart.Metadata{ + Name: "Athos-chart", + Version: "1.2.3", + }, + }, }, { Name: "porthos", Namespace: "default", - Info: info, - Chart: &chart.Chart{}, - Hooks: hooks, + Info: &release.Info{ + Status: release.StatusFailed, + }, + Chart: &chart.Chart{ + Metadata: &chart.Metadata{ + Name: "Porthos-chart", + Version: "111.222.333", + }, + }, }, { Name: "aramis", Namespace: "default", - Info: info, - Chart: &chart.Chart{}, - Hooks: hooks, + Info: &release.Info{ + Status: release.StatusUninstalled, + }, + Chart: &chart.Chart{ + Metadata: &chart.Metadata{ + Name: "Aramis-chart", + Version: "0.0.0", + }, + }, }, { Name: "dartagnan", Namespace: "gascony", - Info: info, - Chart: &chart.Chart{}, - Hooks: hooks, + Info: &release.Info{ + Status: release.StatusUnknown, + }, + Chart: &chart.Chart{ + Metadata: &chart.Metadata{ + Name: "Dartagnan-chart", + Version: "1.2.3-prerelease", + }, + }, }} - } tests := []cmdTestCase{{ name: "completion for status", cmd: "__complete status a", golden: "output/status-comp.txt", - rels: releasesMockWithStatus(&release.Info{ - Status: release.StatusDeployed, - }), + rels: rels, }, { name: "completion for status with too many arguments", cmd: "__complete status dartagnan ''", golden: "output/status-wrong-args-comp.txt", - rels: releasesMockWithStatus(&release.Info{ - Status: release.StatusDeployed, - }), + rels: rels, }, { - name: "completion for status with too many arguments", + name: "completion for status with global flag", cmd: "__complete status --debug a", golden: "output/status-comp.txt", - rels: releasesMockWithStatus(&release.Info{ - Status: release.StatusDeployed, - }), + rels: rels, }} runTestCmd(t, tests) } diff --git a/cmd/helm/testdata/helmhome/helm/repository/testing-index.yaml b/cmd/helm/testdata/helmhome/helm/repository/testing-index.yaml index 889d7d87aea..91e4d463f1b 100644 --- a/cmd/helm/testdata/helmhome/helm/repository/testing-index.yaml +++ b/cmd/helm/testdata/helmhome/helm/repository/testing-index.yaml @@ -4,6 +4,8 @@ entries: - name: alpine url: https://charts.helm.sh/stable/alpine-0.1.0.tgz checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d + created: "2018-06-27T10:00:18.230700509Z" + deprecated: true home: https://helm.sh/helm sources: - https://github.com/helm/helm @@ -17,6 +19,7 @@ entries: - name: alpine url: https://charts.helm.sh/stable/alpine-0.2.0.tgz checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d + created: "2018-07-09T11:34:37.797864902Z" home: https://helm.sh/helm sources: - https://github.com/helm/helm @@ -30,6 +33,7 @@ entries: - name: alpine url: https://charts.helm.sh/stable/alpine-0.3.0-rc.1.tgz checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d + created: "2020-11-12T08:44:58.872726222Z" home: https://helm.sh/helm sources: - https://github.com/helm/helm @@ -44,6 +48,7 @@ entries: - name: mariadb url: https://charts.helm.sh/stable/mariadb-0.3.0.tgz checksum: 65229f6de44a2be9f215d11dbff311673fc8ba56 + created: "2018-04-23T08:20:27.160959131Z" home: https://mariadb.org sources: - https://github.com/bitnami/bitnami-docker-mariadb diff --git a/cmd/helm/testdata/output/output-comp.txt b/cmd/helm/testdata/output/output-comp.txt index e7799a56b9c..6232b2928bd 100644 --- a/cmd/helm/testdata/output/output-comp.txt +++ b/cmd/helm/testdata/output/output-comp.txt @@ -1,5 +1,5 @@ -table -json -yaml +json Output result in JSON format +table Output result in human-readable format +yaml Output result in YAML format :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/plugin_list_comp.txt b/cmd/helm/testdata/output/plugin_list_comp.txt index e33b6ce52ff..833efc5e92a 100644 --- a/cmd/helm/testdata/output/plugin_list_comp.txt +++ b/cmd/helm/testdata/output/plugin_list_comp.txt @@ -1,7 +1,7 @@ -args -echo -env -exitwith -fullenv +args echo args +echo echo stuff +env env stuff +exitwith exitwith code +fullenv show env vars :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/plugin_repeat_comp.txt b/cmd/helm/testdata/output/plugin_repeat_comp.txt index 9e2ee56abd5..3fa05f0b3ae 100644 --- a/cmd/helm/testdata/output/plugin_repeat_comp.txt +++ b/cmd/helm/testdata/output/plugin_repeat_comp.txt @@ -1,6 +1,6 @@ -echo -env -exitwith -fullenv +echo echo stuff +env env stuff +exitwith exitwith code +fullenv show env vars :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/revision-comp.txt b/cmd/helm/testdata/output/revision-comp.txt index 50f7a90926a..fe9faf1f10c 100644 --- a/cmd/helm/testdata/output/revision-comp.txt +++ b/cmd/helm/testdata/output/revision-comp.txt @@ -1,6 +1,6 @@ -8 -9 -10 -11 +8 App: 1.0, Chart: foo-0.1.0-beta.1 +9 App: 1.0, Chart: foo-0.1.0-beta.1 +10 App: 1.0, Chart: foo-0.1.0-beta.1 +11 App: 1.0, Chart: foo-0.1.0-beta.1 :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/rollback-comp.txt b/cmd/helm/testdata/output/rollback-comp.txt index f7741af12de..2cfeed1f965 100644 --- a/cmd/helm/testdata/output/rollback-comp.txt +++ b/cmd/helm/testdata/output/rollback-comp.txt @@ -1,4 +1,4 @@ -carabins -musketeers +carabins foo-0.1.0-beta.1 -> superseded +musketeers foo-0.1.0-beta.1 -> deployed :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/status-comp.txt b/cmd/helm/testdata/output/status-comp.txt index 8d4d21df7bd..4f56ab30a30 100644 --- a/cmd/helm/testdata/output/status-comp.txt +++ b/cmd/helm/testdata/output/status-comp.txt @@ -1,4 +1,4 @@ -aramis -athos +aramis Aramis-chart-0.0.0 -> uninstalled +athos Athos-chart-1.2.3 -> deployed :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/version-comp.txt b/cmd/helm/testdata/output/version-comp.txt index 098e2cec2df..5b0556cf5f6 100644 --- a/cmd/helm/testdata/output/version-comp.txt +++ b/cmd/helm/testdata/output/version-comp.txt @@ -1,5 +1,5 @@ -0.3.0-rc.1 -0.2.0 -0.1.0 +0.3.0-rc.1 App: 3.0.0, Created: November 12, 2020 +0.2.0 App: 2.3.4, Created: July 9, 2018 +0.1.0 App: 1.2.3, Created: June 27, 2018 (deprecated) :4 Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/pkg/cli/output/output.go b/pkg/cli/output/output.go index e4eb046fc44..a46c977ad97 100644 --- a/pkg/cli/output/output.go +++ b/pkg/cli/output/output.go @@ -40,6 +40,16 @@ func Formats() []string { return []string{Table.String(), JSON.String(), YAML.String()} } +// FormatsWithDesc returns a list of the string representation of the supported formats +// including a description +func FormatsWithDesc() map[string]string { + return map[string]string{ + Table.String(): "Output result in human-readable format", + JSON.String(): "Output result in JSON format", + YAML.String(): "Output result in YAML format", + } +} + // ErrInvalidFormatType is returned when an unsupported format type is used var ErrInvalidFormatType = fmt.Errorf("invalid format type")