mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +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"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra/doc"
|
||||||
"k8s.io/kubernetes/cmd/genutils"
|
"k8s.io/kubernetes/cmd/genutils"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
"k8s.io/kubernetes/pkg/kubectl/cmd"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
@ -48,5 +48,5 @@ func main() {
|
|||||||
os.Setenv("HOME", "/home/username")
|
os.Setenv("HOME", "/home/username")
|
||||||
// TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
// 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)
|
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"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra/doc"
|
||||||
"k8s.io/kubernetes/cmd/genutils"
|
"k8s.io/kubernetes/cmd/genutils"
|
||||||
apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||||
cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app"
|
cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app"
|
||||||
@ -51,23 +51,23 @@ func main() {
|
|||||||
case "kube-apiserver":
|
case "kube-apiserver":
|
||||||
// generate docs for kube-apiserver
|
// generate docs for kube-apiserver
|
||||||
apiserver := apiservapp.NewAPIServerCommand()
|
apiserver := apiservapp.NewAPIServerCommand()
|
||||||
cobra.GenMarkdownTree(apiserver, outDir)
|
doc.GenMarkdownTree(apiserver, outDir)
|
||||||
case "kube-controller-manager":
|
case "kube-controller-manager":
|
||||||
// generate docs for kube-controller-manager
|
// generate docs for kube-controller-manager
|
||||||
controllermanager := cmapp.NewControllerManagerCommand()
|
controllermanager := cmapp.NewControllerManagerCommand()
|
||||||
cobra.GenMarkdownTree(controllermanager, outDir)
|
doc.GenMarkdownTree(controllermanager, outDir)
|
||||||
case "kube-proxy":
|
case "kube-proxy":
|
||||||
// generate docs for kube-proxy
|
// generate docs for kube-proxy
|
||||||
proxy := proxyapp.NewProxyCommand()
|
proxy := proxyapp.NewProxyCommand()
|
||||||
cobra.GenMarkdownTree(proxy, outDir)
|
doc.GenMarkdownTree(proxy, outDir)
|
||||||
case "kube-scheduler":
|
case "kube-scheduler":
|
||||||
// generate docs for kube-scheduler
|
// generate docs for kube-scheduler
|
||||||
scheduler := schapp.NewSchedulerCommand()
|
scheduler := schapp.NewSchedulerCommand()
|
||||||
cobra.GenMarkdownTree(scheduler, outDir)
|
doc.GenMarkdownTree(scheduler, outDir)
|
||||||
case "kubelet":
|
case "kubelet":
|
||||||
// generate docs for kubelet
|
// generate docs for kubelet
|
||||||
kubelet := kubeletapp.NewKubeletCommand()
|
kubelet := kubeletapp.NewKubeletCommand()
|
||||||
cobra.GenMarkdownTree(kubelet, outDir)
|
doc.GenMarkdownTree(kubelet, outDir)
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "Module %s is not supported", module)
|
fmt.Fprintf(os.Stderr, "Module %s is not supported", module)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -30,12 +30,47 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
bash_completion_func = `# call kubectl get $1,
|
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()
|
__kubectl_parse_get()
|
||||||
{
|
{
|
||||||
local template
|
local template
|
||||||
template="{{ range .items }}{{ .metadata.name }} {{ end }}"
|
template="{{ range .items }}{{ .metadata.name }} {{ end }}"
|
||||||
local kubectl_out
|
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" ) )
|
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@ -71,7 +106,7 @@ __kubectl_get_containers()
|
|||||||
fi
|
fi
|
||||||
local last=${nouns[${len} -1]}
|
local last=${nouns[${len} -1]}
|
||||||
local kubectl_out
|
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" ) )
|
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@ -196,6 +231,14 @@ Find more information at https://github.com/kubernetes/kubernetes.`,
|
|||||||
cmds.AddCommand(NewCmdExplain(f, out))
|
cmds.AddCommand(NewCmdExplain(f, out))
|
||||||
cmds.AddCommand(NewCmdConvert(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
|
return cmds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,11 +71,12 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
options := &DeleteOptions{}
|
options := &DeleteOptions{}
|
||||||
|
|
||||||
// retrieve a list of handled resources from printer as valid args
|
// 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{})
|
p, err := f.Printer(nil, false, false, false, false, false, false, []string{})
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
if p != nil {
|
if p != nil {
|
||||||
validArgs = p.HandledResources()
|
validArgs = p.HandledResources()
|
||||||
|
argAliases = kubectl.ResourceAliases(validArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -88,7 +89,8 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
err := RunDelete(f, out, cmd, args, options)
|
err := RunDelete(f, out, cmd, args, options)
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
ValidArgs: validArgs,
|
ValidArgs: validArgs,
|
||||||
|
ArgAliases: argAliases,
|
||||||
}
|
}
|
||||||
usage := "Filename, directory, or URL to a file containing the resource to delete."
|
usage := "Filename, directory, or URL to a file containing the resource to delete."
|
||||||
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
||||||
|
@ -74,6 +74,9 @@ kubectl describe pods frontend`
|
|||||||
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
options := &DescribeOptions{}
|
options := &DescribeOptions{}
|
||||||
|
|
||||||
|
validArgs := kubectl.DescribableResources()
|
||||||
|
argAliases := kubectl.ResourceAliases(validArgs)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)",
|
Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)",
|
||||||
Short: "Show details of a specific resource or group of resources",
|
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)
|
err := RunDescribe(f, out, cmd, args, options)
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
ValidArgs: kubectl.DescribableResources(),
|
ValidArgs: validArgs,
|
||||||
|
ArgAliases: argAliases,
|
||||||
}
|
}
|
||||||
usage := "Filename, directory, or URL to a file containing the resource to describe"
|
usage := "Filename, directory, or URL to a file containing the resource to describe"
|
||||||
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
|
||||||
|
@ -74,11 +74,12 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
options := &GetOptions{}
|
options := &GetOptions{}
|
||||||
|
|
||||||
// retrieve a list of handled resources from printer as valid args
|
// 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{})
|
p, err := f.Printer(nil, false, false, false, false, false, false, []string{})
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
if p != nil {
|
if p != nil {
|
||||||
validArgs = p.HandledResources()
|
validArgs = p.HandledResources()
|
||||||
|
argAliases = kubectl.ResourceAliases(validArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -90,7 +91,8 @@ func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
err := RunGet(f, out, cmd, args, options)
|
err := RunGet(f, out, cmd, args, options)
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
ValidArgs: validArgs,
|
ValidArgs: validArgs,
|
||||||
|
ArgAliases: argAliases,
|
||||||
}
|
}
|
||||||
cmdutil.AddPrinterFlags(cmd)
|
cmdutil.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
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{}
|
options := &LabelOptions{}
|
||||||
|
|
||||||
// retrieve a list of handled resources from printer as valid args
|
// 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{})
|
p, err := f.Printer(nil, false, false, false, false, false, false, []string{})
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
if p != nil {
|
if p != nil {
|
||||||
validArgs = p.HandledResources()
|
validArgs = p.HandledResources()
|
||||||
|
argAliases = kubectl.ResourceAliases(validArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@ -89,7 +90,8 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
err := RunLabel(f, out, cmd, args, options)
|
err := RunLabel(f, out, cmd, args, options)
|
||||||
cmdutil.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
ValidArgs: validArgs,
|
ValidArgs: validArgs,
|
||||||
|
ArgAliases: argAliases,
|
||||||
}
|
}
|
||||||
cmdutil.AddPrinterFlags(cmd)
|
cmdutil.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.")
|
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
|
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:
|
// parseFileSource parses the source given. Acceptable formats include:
|
||||||
//
|
//
|
||||||
// 1. source-path: the basename will become the key name
|
// 1. source-path: the basename will become the key name
|
||||||
|
Loading…
Reference in New Issue
Block a user