mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Make kubectl bash completion namespace aware and add noun aliases
- add namespace filtering to bash completion - add --namespace flag bash completion - add bash completion noun aliases - adapt to new cobra package structure
This commit is contained in:
parent
8af3be87e4
commit
7e0bb885f1
@ -21,7 +21,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
@ -48,5 +48,5 @@ func main() {
|
||||
os.Setenv("HOME", "/home/username")
|
||||
// TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
cobra.GenMarkdownTree(kubectl, outDir)
|
||||
doc.GenMarkdownTree(kubectl, outDir)
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
"k8s.io/kubernetes/cmd/genutils"
|
||||
apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||
cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app"
|
||||
@ -51,23 +51,23 @@ func main() {
|
||||
case "kube-apiserver":
|
||||
// generate docs for kube-apiserver
|
||||
apiserver := apiservapp.NewAPIServerCommand()
|
||||
cobra.GenMarkdownTree(apiserver, outDir)
|
||||
doc.GenMarkdownTree(apiserver, outDir)
|
||||
case "kube-controller-manager":
|
||||
// generate docs for kube-controller-manager
|
||||
controllermanager := cmapp.NewControllerManagerCommand()
|
||||
cobra.GenMarkdownTree(controllermanager, outDir)
|
||||
doc.GenMarkdownTree(controllermanager, outDir)
|
||||
case "kube-proxy":
|
||||
// generate docs for kube-proxy
|
||||
proxy := proxyapp.NewProxyCommand()
|
||||
cobra.GenMarkdownTree(proxy, outDir)
|
||||
doc.GenMarkdownTree(proxy, outDir)
|
||||
case "kube-scheduler":
|
||||
// generate docs for kube-scheduler
|
||||
scheduler := schapp.NewSchedulerCommand()
|
||||
cobra.GenMarkdownTree(scheduler, outDir)
|
||||
doc.GenMarkdownTree(scheduler, outDir)
|
||||
case "kubelet":
|
||||
// generate docs for kubelet
|
||||
kubelet := kubeletapp.NewKubeletCommand()
|
||||
cobra.GenMarkdownTree(kubelet, outDir)
|
||||
doc.GenMarkdownTree(kubelet, outDir)
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Module %s is not supported", module)
|
||||
os.Exit(1)
|
||||
|
@ -30,12 +30,47 @@ import (
|
||||
|
||||
const (
|
||||
bash_completion_func = `# call kubectl get $1,
|
||||
__kubectl_namespace_flag()
|
||||
{
|
||||
local ret two_word_ns
|
||||
ret=""
|
||||
two_word_ns=false
|
||||
for w in "${words[@]}"; do
|
||||
if [ "$two_word_ns" = true ]; then
|
||||
ret="--namespace=${w}"
|
||||
two_word_ns=false
|
||||
continue
|
||||
fi
|
||||
case "${w}" in
|
||||
--namespace=*)
|
||||
ret=${w}
|
||||
;;
|
||||
--namespace)
|
||||
two_word_ns=true
|
||||
;;
|
||||
--all-namespaces)
|
||||
ret=${w}
|
||||
;;
|
||||
esac
|
||||
done
|
||||
echo $ret
|
||||
}
|
||||
|
||||
__kubectl_get_namespaces()
|
||||
{
|
||||
local template kubectl_out
|
||||
template="{{ range .items }}{{ .metadata.name }} {{ end }}"
|
||||
if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then
|
||||
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
||||
fi
|
||||
}
|
||||
|
||||
__kubectl_parse_get()
|
||||
{
|
||||
local template
|
||||
template="{{ range .items }}{{ .metadata.name }} {{ end }}"
|
||||
local kubectl_out
|
||||
if kubectl_out=$(kubectl get -o template --template="${template}" "$1" 2>/dev/null); then
|
||||
if kubectl_out=$(kubectl get $(__kubectl_namespace_flag) -o template --template="${template}" "$1" 2>/dev/null); then
|
||||
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
||||
fi
|
||||
}
|
||||
@ -71,7 +106,7 @@ __kubectl_get_containers()
|
||||
fi
|
||||
local last=${nouns[${len} -1]}
|
||||
local kubectl_out
|
||||
if kubectl_out=$(kubectl get -o template --template="${template}" pods "${last}" 2>/dev/null); then
|
||||
if kubectl_out=$(kubectl get $(__kubectl_namespace_flag) -o template --template="${template}" pods "${last}" 2>/dev/null); then
|
||||
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
||||
fi
|
||||
}
|
||||
@ -196,6 +231,14 @@ Find more information at https://github.com/kubernetes/kubernetes.`,
|
||||
cmds.AddCommand(NewCmdExplain(f, out))
|
||||
cmds.AddCommand(NewCmdConvert(f, out))
|
||||
|
||||
if cmds.Flag("namespace").Annotations == nil {
|
||||
cmds.Flag("namespace").Annotations = map[string][]string{}
|
||||
}
|
||||
cmds.Flag("namespace").Annotations[cobra.BashCompCustom] = append(
|
||||
cmds.Flag("namespace").Annotations[cobra.BashCompCustom],
|
||||
"__kubectl_get_namespaces",
|
||||
)
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
||||
|
@ -71,11 +71,12 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
options := &DeleteOptions{}
|
||||
|
||||
// retrieve a list of handled resources from printer as valid args
|
||||
validArgs := []string{}
|
||||
validArgs, argAliases := []string{}, []string{}
|
||||
p, err := f.Printer(nil, false, false, false, false, false, false, []string{})
|
||||
cmdutil.CheckErr(err)
|
||||
if p != nil {
|
||||
validArgs = p.HandledResources()
|
||||
argAliases = kubectl.ResourceAliases(validArgs)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@ -89,6 +90,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: argAliases,
|
||||
}
|
||||
usage := "Filename, directory, or URL to a file containing the resource to delete."
|
||||
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
||||
|
@ -74,6 +74,9 @@ kubectl describe pods frontend`
|
||||
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
options := &DescribeOptions{}
|
||||
|
||||
validArgs := kubectl.DescribableResources()
|
||||
argAliases := kubectl.ResourceAliases(validArgs)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)",
|
||||
Short: "Show details of a specific resource or group of resources",
|
||||
@ -83,7 +86,8 @@ func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
err := RunDescribe(f, out, cmd, args, options)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: kubectl.DescribableResources(),
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: argAliases,
|
||||
}
|
||||
usage := "Filename, directory, or URL to a file containing the resource to describe"
|
||||
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
||||
|
@ -74,11 +74,12 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
options := &GetOptions{}
|
||||
|
||||
// retrieve a list of handled resources from printer as valid args
|
||||
validArgs := []string{}
|
||||
validArgs, argAliases := []string{}, []string{}
|
||||
p, err := f.Printer(nil, false, false, false, false, false, false, []string{})
|
||||
cmdutil.CheckErr(err)
|
||||
if p != nil {
|
||||
validArgs = p.HandledResources()
|
||||
argAliases = kubectl.ResourceAliases(validArgs)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@ -91,6 +92,7 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: argAliases,
|
||||
}
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
||||
|
@ -73,11 +73,12 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
options := &LabelOptions{}
|
||||
|
||||
// retrieve a list of handled resources from printer as valid args
|
||||
validArgs := []string{}
|
||||
validArgs, argAliases := []string{}, []string{}
|
||||
p, err := f.Printer(nil, false, false, false, false, false, false, []string{})
|
||||
cmdutil.CheckErr(err)
|
||||
if p != nil {
|
||||
validArgs = p.HandledResources()
|
||||
argAliases = kubectl.ResourceAliases(validArgs)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@ -90,6 +91,7 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: argAliases,
|
||||
}
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.")
|
||||
|
@ -175,6 +175,35 @@ func expandResourceShortcut(resource unversioned.GroupVersionResource) unversion
|
||||
return resource
|
||||
}
|
||||
|
||||
// ResourceAliases returns the resource shortcuts and plural forms for the given resources.
|
||||
func ResourceAliases(rs []string) []string {
|
||||
as := make([]string, 0, len(rs))
|
||||
plurals := make(map[string]struct{}, len(rs))
|
||||
for _, r := range rs {
|
||||
var plural string
|
||||
switch {
|
||||
case r == "endpoints":
|
||||
plural = r // exception. "endpoint" does not exist. Why?
|
||||
case strings.HasSuffix(r, "y"):
|
||||
plural = r[0:len(r)-1] + "ies"
|
||||
case strings.HasSuffix(r, "s"):
|
||||
plural = r + "es"
|
||||
default:
|
||||
plural = r + "s"
|
||||
}
|
||||
as = append(as, plural)
|
||||
|
||||
plurals[plural] = struct{}{}
|
||||
}
|
||||
|
||||
for sf, r := range shortForms {
|
||||
if _, found := plurals[r]; found {
|
||||
as = append(as, sf)
|
||||
}
|
||||
}
|
||||
return as
|
||||
}
|
||||
|
||||
// parseFileSource parses the source given. Acceptable formats include:
|
||||
//
|
||||
// 1. source-path: the basename will become the key name
|
||||
|
Loading…
Reference in New Issue
Block a user