From 8de22efd88060c41aa9a42abd8f3b8709e9309b8 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sat, 7 Sep 2019 19:09:05 -0400 Subject: [PATCH] feat(cli): Dynamic completion for global flags Inspired greatly from kubectl code. Completion is provided for: --kube-context - where the available contexts are listed --namespace - where the namespaces of the cluster are listed Signed-off-by: Marc Khouzam --- cmd/helm/root.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/cmd/helm/root.go b/cmd/helm/root.go index cbda8273f..30b452fcb 100644 --- a/cmd/helm/root.go +++ b/cmd/helm/root.go @@ -55,6 +55,40 @@ __helm_override_flags() fi done } + +__helm_override_flags_to_kubectl_flags() +{ + # --kubeconfig, -n, --namespace stay the same for kubectl + # --kube-context becomes --context for kubectl + __helm_debug "${FUNCNAME[0]}: flags to convert: $1" + echo "$1" | sed s/kube-context/context/ +} + +__helm_get_contexts() +{ + __helm_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + local template out + template="{{ range .contexts }}{{ .name }} {{ end }}" + if out=$(kubectl config -o template --template="${template}" view 2>/dev/null); then + COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) + fi +} + +__helm_get_namespaces() +{ + __helm_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + local template out + template="{{ range .items }}{{ .metadata.name }} {{ end }}" + + flags=$(__helm_override_flags_to_kubectl_flags "$(__helm_override_flags)") + __helm_debug "${FUNCNAME[0]}: override flags for kubectl are: $flags" + + # Must use eval in case the flags contain a variable such as $HOME + if out=$(eval kubectl get ${flags} -o template --template=\"${template}\" namespace 2>/dev/null); then + COMPREPLY+=( $( compgen -W "${out[*]}" -- "$cur" ) ) + fi +} + __helm_list_releases() { __helm_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" @@ -105,6 +139,15 @@ __helm_custom_func() ` ) +var ( + // Mapping of global flags that can have dynamic completion and the + // completion function to be used. + bashCompletionFlags = map[string]string{ + "namespace": "__helm_get_namespaces", + "kube-context": "__helm_get_contexts", + } +) + var globalUsage = `The Kubernetes package manager Common actions for Helm: @@ -196,6 +239,19 @@ func newRootCmd(actionConfig *action.Configuration, out io.Writer, args []string newDocsCmd(out), ) + // Add annotation to flags for which we can generate completion choices + for name, completion := range bashCompletionFlags { + if cmd.Flag(name) != nil { + if cmd.Flag(name).Annotations == nil { + cmd.Flag(name).Annotations = map[string][]string{} + } + cmd.Flag(name).Annotations[cobra.BashCompCustom] = append( + cmd.Flag(name).Annotations[cobra.BashCompCustom], + completion, + ) + } + } + // Add *experimental* subcommands registryClient, err := registry.NewClient( registry.ClientOptDebug(settings.Debug),