diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/cmd.go b/staging/src/k8s.io/kubectl/pkg/cmd/cmd.go index 1f94844720c..aa641545399 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/cmd.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/cmd.go @@ -325,15 +325,6 @@ __kubectl_custom_func() { const kubectlCmdHeaders = "KUBECTL_COMMAND_HEADERS" -var ( - bashCompletionFlags = map[string]string{ - "namespace": "__kubectl_get_resource_namespace", - "context": "__kubectl_config_get_contexts", - "cluster": "__kubectl_config_get_clusters", - "user": "__kubectl_config_get_users", - } -) - // NewDefaultKubectlCommand creates the `kubectl` command with default arguments func NewDefaultKubectlCommand() *cobra.Command { return NewDefaultKubectlCommandWithArgs(NewDefaultPluginHandler(plugin.ValidPluginFilenamePrefixes), os.Args, os.Stdin, os.Stdout, os.Stderr) @@ -633,17 +624,7 @@ func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command { templates.ActsAsRootCommand(cmds, filters, groups...) - for name, completion := range bashCompletionFlags { - if cmds.Flag(name) != nil { - if cmds.Flag(name).Annotations == nil { - cmds.Flag(name).Annotations = map[string][]string{} - } - cmds.Flag(name).Annotations[cobra.BashCompCustom] = append( - cmds.Flag(name).Annotations[cobra.BashCompCustom], - completion, - ) - } - } + registerCompletionFuncForGlobalFlags(cmds, f) cmds.AddCommand(alpha) cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), ioStreams)) diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/completion.go b/staging/src/k8s.io/kubectl/pkg/cmd/completion.go new file mode 100644 index 00000000000..a561c07d45b --- /dev/null +++ b/staging/src/k8s.io/kubectl/pkg/cmd/completion.go @@ -0,0 +1,46 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "github.com/spf13/cobra" + "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/completion" +) + +func registerCompletionFuncForGlobalFlags(cmd *cobra.Command, f util.Factory) { + util.CheckErr(cmd.RegisterFlagCompletionFunc( + "namespace", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return completion.ListNamespaces(f, toComplete) + })) + util.CheckErr(cmd.RegisterFlagCompletionFunc( + "context", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return completion.ListContextsInKubeconfig(f, toComplete) + })) + util.CheckErr(cmd.RegisterFlagCompletionFunc( + "cluster", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return completion.ListClustersInKubeconfig(f, toComplete) + })) + util.CheckErr(cmd.RegisterFlagCompletionFunc( + "user", + func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return completion.ListUsersInKubeconfig(f, toComplete) + })) +} diff --git a/staging/src/k8s.io/kubectl/pkg/completion/utils.go b/staging/src/k8s.io/kubectl/pkg/completion/utils.go new file mode 100644 index 00000000000..bfb9f9bfe8b --- /dev/null +++ b/staging/src/k8s.io/kubectl/pkg/completion/utils.go @@ -0,0 +1,94 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package completion + +import ( + "context" + "strings" + "time" + + "github.com/spf13/cobra" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubectl/pkg/cmd/util" +) + +// ListNamespaces returns a list of namespaces which begins with `toComplete`. +func ListNamespaces(f util.Factory, toComplete string) ([]string, cobra.ShellCompDirective) { + clientSet, err := f.KubernetesClientSet() + if err != nil { + return nil, cobra.ShellCompDirectiveDefault + } + ctx, cancel := context.WithTimeout(context.TODO(), time.Second*3) + defer cancel() + namespaces, err := clientSet.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, cobra.ShellCompDirectiveDefault + } + var ret []string + for _, ns := range namespaces.Items { + if strings.HasPrefix(ns.Name, toComplete) { + ret = append(ret, ns.Name) + } + } + return ret, cobra.ShellCompDirectiveNoFileComp +} + +// ListContextsInKubeconfig returns a list of context names which begins with `toComplete`. +func ListContextsInKubeconfig(f util.Factory, toComplete string) ([]string, cobra.ShellCompDirective) { + config, err := f.ToRawKubeConfigLoader().RawConfig() + if err != nil { + return nil, cobra.ShellCompDirectiveNoFileComp + } + var ret []string + for name := range config.Contexts { + if strings.HasPrefix(name, toComplete) { + ret = append(ret, name) + } + } + return ret, cobra.ShellCompDirectiveNoFileComp +} + +// ListClustersInKubeconfig returns a list of cluster names which begins with `toComplete`. +func ListClustersInKubeconfig(f util.Factory, toComplete string) ([]string, cobra.ShellCompDirective) { + config, err := f.ToRawKubeConfigLoader().RawConfig() + if err != nil { + return nil, cobra.ShellCompDirectiveNoFileComp + } + var ret []string + for name := range config.Clusters { + if strings.HasPrefix(name, toComplete) { + ret = append(ret, name) + } + } + return ret, cobra.ShellCompDirectiveNoFileComp +} + +// ListUsersInKubeconfig returns a list of user names which begins with `toComplete`. +func ListUsersInKubeconfig(f util.Factory, toComplete string) ([]string, cobra.ShellCompDirective) { + config, err := f.ToRawKubeConfigLoader().RawConfig() + if err != nil { + return nil, cobra.ShellCompDirectiveNoFileComp + } + var ret []string + for name := range config.AuthInfos { + if strings.HasPrefix(name, toComplete) { + ret = append(ret, name) + } + } + return ret, cobra.ShellCompDirectiveNoFileComp +} diff --git a/vendor/modules.txt b/vendor/modules.txt index ebc4e11be34..4064ac74e0e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2070,6 +2070,7 @@ k8s.io/kubectl/pkg/cmd/util/podcmd k8s.io/kubectl/pkg/cmd/util/sanity k8s.io/kubectl/pkg/cmd/version k8s.io/kubectl/pkg/cmd/wait +k8s.io/kubectl/pkg/completion k8s.io/kubectl/pkg/describe k8s.io/kubectl/pkg/drain k8s.io/kubectl/pkg/explain