From 8854547d3518cf3c83eec80d9390a05c453f4b3e Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sat, 13 Mar 2021 16:28:37 -0500 Subject: [PATCH] feat(comp): Uninstall accepts multiple releases The 'uninstall' command can accept more than one release name as arguments; this commit teaches the completion logic to respect this. At the same time, the commit adds tests for the commands using the modified code path. Signed-off-by: Marc Khouzam --- cmd/helm/completion_test.go | 29 +++++++++++++++++++ cmd/helm/get_all.go | 2 +- cmd/helm/get_all_test.go | 4 +++ cmd/helm/get_hooks.go | 2 +- cmd/helm/get_hooks_test.go | 4 +++ cmd/helm/get_manifest.go | 2 +- cmd/helm/get_manifest_test.go | 4 +++ cmd/helm/get_notes.go | 2 +- cmd/helm/get_notes_test.go | 4 +++ cmd/helm/get_values.go | 2 +- cmd/helm/get_values_test.go | 4 +++ cmd/helm/history.go | 2 +- cmd/helm/history_test.go | 4 +++ cmd/helm/list.go | 29 +++++++++++++++++-- cmd/helm/release_testing.go | 2 +- cmd/helm/release_testing_test.go | 4 +++ cmd/helm/rollback.go | 2 +- cmd/helm/status.go | 2 +- .../testdata/output/release_list_comp.txt | 5 ++++ .../output/release_list_repeat_comp.txt | 4 +++ cmd/helm/uninstall.go | 5 +--- cmd/helm/uninstall_test.go | 4 +++ cmd/helm/upgrade.go | 2 +- 23 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 cmd/helm/testdata/output/release_list_comp.txt create mode 100644 cmd/helm/testdata/output/release_list_repeat_comp.txt diff --git a/cmd/helm/completion_test.go b/cmd/helm/completion_test.go index bd94f6b4c..6d53616d0 100644 --- a/cmd/helm/completion_test.go +++ b/cmd/helm/completion_test.go @@ -62,3 +62,32 @@ func TestCompletionFileCompletion(t *testing.T) { checkFileCompletion(t, "completion zsh", false) checkFileCompletion(t, "completion fish", false) } + +func checkReleaseCompletion(t *testing.T, cmdName string, multiReleasesAllowed bool) { + multiReleaseTestGolden := "output/empty_nofile_comp.txt" + if multiReleasesAllowed { + multiReleaseTestGolden = "output/release_list_repeat_comp.txt" + } + tests := []cmdTestCase{{ + name: "completion for uninstall", + cmd: fmt.Sprintf("__complete %s ''", cmdName), + golden: "output/release_list_comp.txt", + rels: []*release.Release{ + release.Mock(&release.MockReleaseOptions{Name: "athos"}), + release.Mock(&release.MockReleaseOptions{Name: "porthos"}), + release.Mock(&release.MockReleaseOptions{Name: "aramis"}), + }, + }, { + name: "completion for uninstall repetition", + cmd: fmt.Sprintf("__complete %s porthos ''", cmdName), + golden: multiReleaseTestGolden, + rels: []*release.Release{ + release.Mock(&release.MockReleaseOptions{Name: "athos"}), + release.Mock(&release.MockReleaseOptions{Name: "porthos"}), + release.Mock(&release.MockReleaseOptions{Name: "aramis"}), + }, + }} + for _, test := range tests { + runTestCmd(t, []cmdTestCase{test}) + } +} diff --git a/cmd/helm/get_all.go b/cmd/helm/get_all.go index 53f8d5905..bf367da7f 100644 --- a/cmd/helm/get_all.go +++ b/cmd/helm/get_all.go @@ -45,7 +45,7 @@ func newGetAllCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { res, err := client.Run(args[0]) diff --git a/cmd/helm/get_all_test.go b/cmd/helm/get_all_test.go index 0c140faf8..948f0aa71 100644 --- a/cmd/helm/get_all_test.go +++ b/cmd/helm/get_all_test.go @@ -42,6 +42,10 @@ func TestGetCmd(t *testing.T) { runTestCmd(t, tests) } +func TestGetAllCompletion(t *testing.T) { + checkReleaseCompletion(t, "get all", false) +} + func TestGetAllRevisionCompletion(t *testing.T) { revisionFlagCompletionTest(t, "get all") } diff --git a/cmd/helm/get_hooks.go b/cmd/helm/get_hooks.go index 8b78653b5..913e2c58a 100644 --- a/cmd/helm/get_hooks.go +++ b/cmd/helm/get_hooks.go @@ -45,7 +45,7 @@ func newGetHooksCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { res, err := client.Run(args[0]) diff --git a/cmd/helm/get_hooks_test.go b/cmd/helm/get_hooks_test.go index 6c010d1bd..251d5c731 100644 --- a/cmd/helm/get_hooks_test.go +++ b/cmd/helm/get_hooks_test.go @@ -37,6 +37,10 @@ func TestGetHooks(t *testing.T) { runTestCmd(t, tests) } +func TestGetHooksCompletion(t *testing.T) { + checkReleaseCompletion(t, "get hooks", false) +} + func TestGetHooksRevisionCompletion(t *testing.T) { revisionFlagCompletionTest(t, "get hooks") } diff --git a/cmd/helm/get_manifest.go b/cmd/helm/get_manifest.go index 8ffeb3676..baeaf8d72 100644 --- a/cmd/helm/get_manifest.go +++ b/cmd/helm/get_manifest.go @@ -47,7 +47,7 @@ func newGetManifestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { res, err := client.Run(args[0]) diff --git a/cmd/helm/get_manifest_test.go b/cmd/helm/get_manifest_test.go index f3f572e80..2f27476b6 100644 --- a/cmd/helm/get_manifest_test.go +++ b/cmd/helm/get_manifest_test.go @@ -37,6 +37,10 @@ func TestGetManifest(t *testing.T) { runTestCmd(t, tests) } +func TestGetManifestCompletion(t *testing.T) { + checkReleaseCompletion(t, "get manifest", false) +} + func TestGetManifestRevisionCompletion(t *testing.T) { revisionFlagCompletionTest(t, "get manifest") } diff --git a/cmd/helm/get_notes.go b/cmd/helm/get_notes.go index a9d29ce49..b71bcbdf6 100644 --- a/cmd/helm/get_notes.go +++ b/cmd/helm/get_notes.go @@ -43,7 +43,7 @@ func newGetNotesCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { res, err := client.Run(args[0]) diff --git a/cmd/helm/get_notes_test.go b/cmd/helm/get_notes_test.go index 7d43c87e7..8be9a3f7c 100644 --- a/cmd/helm/get_notes_test.go +++ b/cmd/helm/get_notes_test.go @@ -37,6 +37,10 @@ func TestGetNotesCmd(t *testing.T) { runTestCmd(t, tests) } +func TestGetNotesCompletion(t *testing.T) { + checkReleaseCompletion(t, "get notes", false) +} + func TestGetNotesRevisionCompletion(t *testing.T) { revisionFlagCompletionTest(t, "get notes") } diff --git a/cmd/helm/get_values.go b/cmd/helm/get_values.go index c8c87c033..6124e1b33 100644 --- a/cmd/helm/get_values.go +++ b/cmd/helm/get_values.go @@ -50,7 +50,7 @@ func newGetValuesCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { vals, err := client.Run(args[0]) diff --git a/cmd/helm/get_values_test.go b/cmd/helm/get_values_test.go index 2a71b1e4d..423c32859 100644 --- a/cmd/helm/get_values_test.go +++ b/cmd/helm/get_values_test.go @@ -53,6 +53,10 @@ func TestGetValuesCmd(t *testing.T) { runTestCmd(t, tests) } +func TestGetValuesCompletion(t *testing.T) { + checkReleaseCompletion(t, "get values", false) +} + func TestGetValuesRevisionCompletion(t *testing.T) { revisionFlagCompletionTest(t, "get values") } diff --git a/cmd/helm/history.go b/cmd/helm/history.go index 61f45c946..06ec07d6d 100644 --- a/cmd/helm/history.go +++ b/cmd/helm/history.go @@ -65,7 +65,7 @@ func newHistoryCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { history, err := getHistory(client, args[0]) diff --git a/cmd/helm/history_test.go b/cmd/helm/history_test.go index fffd983da..2663e9ee9 100644 --- a/cmd/helm/history_test.go +++ b/cmd/helm/history_test.go @@ -109,6 +109,10 @@ func revisionFlagCompletionTest(t *testing.T, cmdName string) { runTestCmd(t, tests) } +func TestHistoryCompletion(t *testing.T) { + checkReleaseCompletion(t, "history", false) +} + func TestHistoryFileCompletion(t *testing.T) { checkFileCompletion(t, "history", false) checkFileCompletion(t, "history myrelease", false) diff --git a/cmd/helm/list.go b/cmd/helm/list.go index 05e56fcab..f8be65b17 100644 --- a/cmd/helm/list.go +++ b/cmd/helm/list.go @@ -193,8 +193,32 @@ func (r *releaseListWriter) WriteYAML(out io.Writer) error { return output.EncodeYAML(out, r.releases) } +// Returns all releases from 'releases', except those with names matching 'ignoredReleases' +func filterReleases(releases []*release.Release, ignoredReleaseNames []string) []*release.Release { + // if ignoredReleaseNames is nil, just return releases + if ignoredReleaseNames == nil { + return releases + } + + var filteredReleases []*release.Release + for _, rel := range releases { + found := false + for _, ignoredName := range ignoredReleaseNames { + if rel.Name == ignoredName { + found = true + break + } + } + if !found { + filteredReleases = append(filteredReleases, rel) + } + } + + return filteredReleases +} + // Provide dynamic auto-completion for release names -func compListReleases(toComplete string, cfg *action.Configuration) ([]string, cobra.ShellCompDirective) { +func compListReleases(toComplete string, ignoredReleaseNames []string, cfg *action.Configuration) ([]string, cobra.ShellCompDirective) { cobra.CompDebugln(fmt.Sprintf("compListReleases with toComplete %s", toComplete), settings.Debug) client := action.NewList(cfg) @@ -209,7 +233,8 @@ func compListReleases(toComplete string, cfg *action.Configuration) ([]string, c } var choices []string - for _, rel := range releases { + filteredReleases := filterReleases(releases, ignoredReleaseNames) + for _, rel := range filteredReleases { choices = append(choices, fmt.Sprintf("%s\t%s-%s -> %s", rel.Name, rel.Chart.Metadata.Name, rel.Chart.Metadata.Version, rel.Info.Status.String())) } diff --git a/cmd/helm/release_testing.go b/cmd/helm/release_testing.go index fbf0dd112..2637cbb9f 100644 --- a/cmd/helm/release_testing.go +++ b/cmd/helm/release_testing.go @@ -52,7 +52,7 @@ func newReleaseTestCmd(cfg *action.Configuration, out io.Writer) *cobra.Command if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { client.Namespace = settings.Namespace() diff --git a/cmd/helm/release_testing_test.go b/cmd/helm/release_testing_test.go index 257e95721..680a9bd3e 100644 --- a/cmd/helm/release_testing_test.go +++ b/cmd/helm/release_testing_test.go @@ -20,6 +20,10 @@ import ( "testing" ) +func TestReleaseTestingCompletion(t *testing.T) { + checkReleaseCompletion(t, "test", false) +} + func TestReleaseTestingFileCompletion(t *testing.T) { checkFileCompletion(t, "test", false) checkFileCompletion(t, "test myrelease", false) diff --git a/cmd/helm/rollback.go b/cmd/helm/rollback.go index 9699b9c05..ea4b75cb1 100644 --- a/cmd/helm/rollback.go +++ b/cmd/helm/rollback.go @@ -48,7 +48,7 @@ func newRollbackCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Args: require.MinimumNArgs(1), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) } if len(args) == 1 { diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 7a3204cb9..6085251d5 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -59,7 +59,7 @@ func newStatusCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { rel, err := client.Run(args[0]) diff --git a/cmd/helm/testdata/output/release_list_comp.txt b/cmd/helm/testdata/output/release_list_comp.txt new file mode 100644 index 000000000..226c378a9 --- /dev/null +++ b/cmd/helm/testdata/output/release_list_comp.txt @@ -0,0 +1,5 @@ +aramis foo-0.1.0-beta.1 -> deployed +athos foo-0.1.0-beta.1 -> deployed +porthos foo-0.1.0-beta.1 -> deployed +:4 +Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/testdata/output/release_list_repeat_comp.txt b/cmd/helm/testdata/output/release_list_repeat_comp.txt new file mode 100644 index 000000000..aa330f47f --- /dev/null +++ b/cmd/helm/testdata/output/release_list_repeat_comp.txt @@ -0,0 +1,4 @@ +aramis foo-0.1.0-beta.1 -> deployed +athos foo-0.1.0-beta.1 -> deployed +:4 +Completion ended with directive: ShellCompDirectiveNoFileComp diff --git a/cmd/helm/uninstall.go b/cmd/helm/uninstall.go index 509918e53..f4f5d87e8 100644 --- a/cmd/helm/uninstall.go +++ b/cmd/helm/uninstall.go @@ -48,10 +48,7 @@ func newUninstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: uninstallDesc, Args: require.MinimumNArgs(1), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 0 { - return nil, cobra.ShellCompDirectiveNoFileComp - } - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) }, RunE: func(cmd *cobra.Command, args []string) error { for i := 0; i < len(args); i++ { diff --git a/cmd/helm/uninstall_test.go b/cmd/helm/uninstall_test.go index ad78361c1..1a33458c4 100644 --- a/cmd/helm/uninstall_test.go +++ b/cmd/helm/uninstall_test.go @@ -67,6 +67,10 @@ func TestUninstall(t *testing.T) { runTestCmd(t, tests) } +func TestUninstallCompletion(t *testing.T) { + checkReleaseCompletion(t, "uninstall", true) +} + func TestUninstallFileCompletion(t *testing.T) { checkFileCompletion(t, "uninstall", false) checkFileCompletion(t, "uninstall myrelease", false) diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index c2e92fb36..1952b8421 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -74,7 +74,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Args: require.ExactArgs(2), ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { - return compListReleases(toComplete, cfg) + return compListReleases(toComplete, args, cfg) } if len(args) == 1 { return compListCharts(toComplete, true)