Implementing autocompletion for karmadactl
Signed-off-by: zhzhuang-zju <m17799853869@163.com>
This commit is contained in:
parent
4ac95b95a1
commit
a684edd354
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -57,5 +58,7 @@ func NewCmdAnnotate(f util.Factory, parentCommand string, ioStreams genericioopt
|
||||||
}
|
}
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
options.AddNamespaceFlag(cmd.Flags())
|
options.AddNamespaceFlag(cmd.Flags())
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -83,6 +84,10 @@ func NewCmdAPIResources(f util.Factory, parentCommand string, ioStreams generici
|
||||||
cmd.Flags().StringVar(&o.SortBy, "sort-by", o.SortBy, "If non-empty, sort list of resources using specified field. The field can be either 'name' or 'kind'.")
|
cmd.Flags().StringVar(&o.SortBy, "sort-by", o.SortBy, "If non-empty, sort list of resources using specified field. The field can be either 'name' or 'kind'.")
|
||||||
cmd.Flags().BoolVar(&o.Cached, "cached", o.Cached, "Use the cached list of resources if available.")
|
cmd.Flags().BoolVar(&o.Cached, "cached", o.Cached, "Use the cached list of resources if available.")
|
||||||
cmd.Flags().StringSliceVar(&o.Categories, "categories", o.Categories, "Limit to resources that belong to the specified categories.")
|
cmd.Flags().StringSliceVar(&o.Categories, "categories", o.Categories, "Limit to resources that belong to the specified categories.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(cmd, options.KarmadaControlPlane, options.Members)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -62,6 +63,11 @@ func NewCmdAPIVersions(f util.Factory, parentCommand string, ioStreams genericio
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
cmd.Flags().VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
cmd.Flags().VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
||||||
cmd.Flags().StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
cmd.Flags().StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(cmd, options.KarmadaControlPlane, options.Members)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/util/names"
|
"github.com/karmada-io/karmada/pkg/util/names"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -93,6 +94,7 @@ func NewCmdApply(f util.Factory, parentCommand string, streams genericiooptions.
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Example: fmt.Sprintf(applyExample, parentCommand),
|
Example: fmt.Sprintf(applyExample, parentCommand),
|
||||||
|
ValidArgsFunction: utilcomp.ResourceTypeAndNameCompletionFunc(f),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(f, cmd, parentCommand, args); err != nil {
|
if err := o.Complete(f, cmd, parentCommand, args); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -113,6 +115,11 @@ func NewCmdApply(f util.Factory, parentCommand string, streams genericiooptions.
|
||||||
options.AddNamespaceFlag(flags)
|
options.AddNamespaceFlag(flags)
|
||||||
flags.BoolVarP(&o.AllClusters, "all-clusters", "", o.AllClusters, "If present, propagates a group of resources to all member clusters.")
|
flags.BoolVarP(&o.AllClusters, "all-clusters", "", o.AllClusters, "If present, propagates a group of resources to all member clusters.")
|
||||||
flags.StringSliceVarP(&o.Clusters, "cluster", "C", o.Clusters, "If present, propagates a group of resources to specified clusters.")
|
flags.StringSliceVarP(&o.Clusters, "cluster", "C", o.Clusters, "If present, propagates a group of resources to specified clusters.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,11 @@ import (
|
||||||
"k8s.io/cli-runtime/pkg/genericiooptions"
|
"k8s.io/cli-runtime/pkg/genericiooptions"
|
||||||
kubectlattach "k8s.io/kubectl/pkg/cmd/attach"
|
kubectlattach "k8s.io/kubectl/pkg/cmd/attach"
|
||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/util/completion"
|
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -64,7 +64,7 @@ func NewCmdAttach(f util.Factory, parentCommand string, streams genericiooptions
|
||||||
Short: "Attach to a running container",
|
Short: "Attach to a running container",
|
||||||
Long: "Attach to a process that is already running inside an existing container.",
|
Long: "Attach to a process that is already running inside an existing container.",
|
||||||
Example: fmt.Sprintf(attachExample, parentCommand),
|
Example: fmt.Sprintf(attachExample, parentCommand),
|
||||||
ValidArgsFunction: completion.PodResourceNameCompletionFunc(f),
|
ValidArgsFunction: utilcomp.PodResourceNameCompletionFunc(f),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||||
cmdutil.CheckErr(o.Validate())
|
cmdutil.CheckErr(o.Validate())
|
||||||
|
@ -85,6 +85,11 @@ func NewCmdAttach(f util.Factory, parentCommand string, streams genericiooptions
|
||||||
cmd.Flags().BoolVarP(&o.Quiet, "quiet", "q", o.Quiet, "Only print output from the remote session")
|
cmd.Flags().BoolVarP(&o.Quiet, "quiet", "q", o.Quiet, "Only print output from the remote session")
|
||||||
cmd.Flags().VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
cmd.Flags().VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
||||||
cmd.Flags().StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
cmd.Flags().StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(cmd, options.KarmadaControlPlane, options.Members)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 The Karmada 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 (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultBoilerPlate = `
|
||||||
|
# Copyright 2024 The Karmada 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.
|
||||||
|
`
|
||||||
|
|
||||||
|
var (
|
||||||
|
completionLong = templates.LongDesc(i18n.T(`
|
||||||
|
Output shell completion code for the specified shell (bash, zsh).
|
||||||
|
The shell code must be evaluated to provide interactive
|
||||||
|
completion of kubectl commands. This can be done by sourcing it from
|
||||||
|
the .bash_profile.
|
||||||
|
|
||||||
|
Note for zsh users: zsh completions are only supported in versions of zsh >= 5.2.`))
|
||||||
|
|
||||||
|
completionExample = templates.Examples(i18n.T(`
|
||||||
|
# Installing bash completion on Linux
|
||||||
|
## If bash-completion is not installed on Linux, install the 'bash-completion' package
|
||||||
|
1. apt-get install bash-completion
|
||||||
|
2. source /usr/share/bash-completion/bash_completion
|
||||||
|
## Load the %[1]s completion code for bash into the current shell
|
||||||
|
source <(%[1]s completion bash)
|
||||||
|
## Or, write bash completion code to a file and source it from .bash_profile
|
||||||
|
1. %[1]s completion bash > ~/.kube/completion.bash.inc
|
||||||
|
2. echo "source '$HOME/.kube/completion.bash.inc'" >> $HOME/.bash_profile
|
||||||
|
3. source $HOME/.bash_profile
|
||||||
|
|
||||||
|
# Load the %[1]s completion code for zsh into the current shell
|
||||||
|
source <(%[1]s completion zsh)
|
||||||
|
# Set the %[1]s completion code for zsh to autoload on startup
|
||||||
|
%[1]s completion zsh > "${fpath[1]}/%[1]s"`))
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TODO: support output shell completion code for more specified shell, like `fish` and `powershell`.
|
||||||
|
completionShells = map[string]func(out io.Writer, boilerPlate string, cmd *cobra.Command) error{
|
||||||
|
"bash": runCompletionBash,
|
||||||
|
"zsh": runCompletionZsh,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewCmdCompletion creates the `completion` command
|
||||||
|
func NewCmdCompletion(parentCommand string, out io.Writer, boilerPlate string) *cobra.Command {
|
||||||
|
var shells []string
|
||||||
|
for s := range completionShells {
|
||||||
|
shells = append(shells, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "completion SHELL",
|
||||||
|
DisableFlagsInUseLine: true,
|
||||||
|
Short: "Output shell completion code for the specified shell (bash, zsh)",
|
||||||
|
Long: completionLong,
|
||||||
|
Example: fmt.Sprintf(completionExample, parentCommand),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cmdutil.CheckErr(RunCompletion(out, boilerPlate, cmd, args))
|
||||||
|
},
|
||||||
|
ValidArgs: shells,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunCompletion checks given arguments and executes command
|
||||||
|
func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return cmdutil.UsageErrorf(cmd, "Shell not specified.")
|
||||||
|
}
|
||||||
|
if len(args) > 1 {
|
||||||
|
return cmdutil.UsageErrorf(cmd, "Too many arguments. Expected only the shell type.")
|
||||||
|
}
|
||||||
|
run, found := completionShells[args[0]]
|
||||||
|
if !found {
|
||||||
|
return cmdutil.UsageErrorf(cmd, "Unsupported shell type %q.", args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return run(out, boilerPlate, cmd.Parent())
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCompletionBash(out io.Writer, boilerPlate string, cmd *cobra.Command) error {
|
||||||
|
if len(boilerPlate) == 0 {
|
||||||
|
boilerPlate = defaultBoilerPlate
|
||||||
|
}
|
||||||
|
if _, err := out.Write([]byte(boilerPlate)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd.GenBashCompletionV2(out, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCompletionZsh(out io.Writer, boilerPlate string, cmd *cobra.Command) error {
|
||||||
|
zshHead := fmt.Sprintf("#compdef %[1]s\ncompdef _%[1]s %[1]s\n", cmd.Name())
|
||||||
|
if _, err := out.Write([]byte(zshHead)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(boilerPlate) == 0 {
|
||||||
|
boilerPlate = defaultBoilerPlate
|
||||||
|
}
|
||||||
|
if _, err := out.Write([]byte(boilerPlate)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd.GenZshCompletion(out)
|
||||||
|
}
|
|
@ -33,6 +33,7 @@ import (
|
||||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -61,6 +62,7 @@ const (
|
||||||
// NewCmdCordon defines the `cordon` command that mark cluster as unschedulable.
|
// NewCmdCordon defines the `cordon` command that mark cluster as unschedulable.
|
||||||
func NewCmdCordon(f util.Factory, parentCommand string) *cobra.Command {
|
func NewCmdCordon(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
opts := CommandCordonOption{}
|
opts := CommandCordonOption{}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "cordon CLUSTER",
|
Use: "cordon CLUSTER",
|
||||||
Short: "Mark cluster as unschedulable",
|
Short: "Mark cluster as unschedulable",
|
||||||
|
@ -68,6 +70,7 @@ func NewCmdCordon(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
Example: fmt.Sprintf(cordonExample, parentCommand),
|
Example: fmt.Sprintf(cordonExample, parentCommand),
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgsFunction: utilcomp.SpecifiedResourceTypeAndNameCompletionFunc(f, []string{"cluster"}),
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if err := opts.Complete(args); err != nil {
|
if err := opts.Complete(args); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -86,12 +89,14 @@ func NewCmdCordon(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
options.AddKubeConfigFlags(flags)
|
options.AddKubeConfigFlags(flags)
|
||||||
flags.BoolVar(&opts.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
|
flags.BoolVar(&opts.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCmdUncordon defines the `uncordon` command that mark cluster as schedulable.
|
// NewCmdUncordon defines the `uncordon` command that mark cluster as schedulable.
|
||||||
func NewCmdUncordon(f util.Factory, parentCommand string) *cobra.Command {
|
func NewCmdUncordon(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
opts := CommandCordonOption{}
|
opts := CommandCordonOption{}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "uncordon CLUSTER",
|
Use: "uncordon CLUSTER",
|
||||||
Short: "Mark cluster as schedulable",
|
Short: "Mark cluster as schedulable",
|
||||||
|
@ -99,6 +104,7 @@ func NewCmdUncordon(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
Example: fmt.Sprintf(uncordonExample, parentCommand),
|
Example: fmt.Sprintf(uncordonExample, parentCommand),
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgsFunction: utilcomp.SpecifiedResourceTypeAndNameCompletionFunc(f, []string{"cluster"}),
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if err := opts.Complete(args); err != nil {
|
if err := opts.Complete(args); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -117,6 +123,7 @@ func NewCmdUncordon(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
options.AddKubeConfigFlags(flags)
|
options.AddKubeConfigFlags(flags)
|
||||||
flags.BoolVar(&opts.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
|
flags.BoolVar(&opts.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -55,5 +56,9 @@ func NewCmdCreate(f util.Factory, parentCommand string, ioStreams genericiooptio
|
||||||
}
|
}
|
||||||
options.AddKubeConfigFlags(cmd.PersistentFlags())
|
options.AddKubeConfigFlags(cmd.PersistentFlags())
|
||||||
options.AddNamespaceFlag(cmd.PersistentFlags())
|
options.AddNamespaceFlag(cmd.PersistentFlags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -98,5 +99,8 @@ func NewCmdDelete(f util.Factory, parentCommand string, ioStreams genericiooptio
|
||||||
}
|
}
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
options.AddNamespaceFlag(cmd.Flags())
|
options.AddNamespaceFlag(cmd.Flags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -74,6 +75,7 @@ func NewCmdDescribe(f util.Factory, parentCommand string, streams genericiooptio
|
||||||
Long: fmt.Sprintf(describeLong, parentCommand),
|
Long: fmt.Sprintf(describeLong, parentCommand),
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgsFunction: utilcomp.ResourceTypeAndNameCompletionFunc(f),
|
||||||
Example: fmt.Sprintf(describeExample, parentCommand),
|
Example: fmt.Sprintf(describeExample, parentCommand),
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(f, args, kubedescribeFlags, parentCommand); err != nil {
|
if err := o.Complete(f, args, kubedescribeFlags, parentCommand); err != nil {
|
||||||
|
@ -101,6 +103,10 @@ func NewCmdDescribe(f util.Factory, parentCommand string, streams genericiooptio
|
||||||
flags.VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
flags.VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
||||||
flags.StringVarP(&o.Cluster, "cluster", "C", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
flags.StringVarP(&o.Cluster, "cluster", "C", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(cmd, options.KarmadaControlPlane, options.Members)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -56,5 +57,8 @@ func NewCmdEdit(f util.Factory, parentCommand string, ioStreams genericiooptions
|
||||||
}
|
}
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
options.AddNamespaceFlag(cmd.Flags())
|
options.AddNamespaceFlag(cmd.Flags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -80,6 +81,7 @@ func NewCmdExec(f util.Factory, parentCommand string, streams genericiooptions.I
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Example: fmt.Sprintf(execExample, parentCommand),
|
Example: fmt.Sprintf(execExample, parentCommand),
|
||||||
|
ValidArgsFunction: utilcomp.PodResourceNameCompletionFunc(f),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
argsLenAtDash := cmd.ArgsLenAtDash()
|
argsLenAtDash := cmd.ArgsLenAtDash()
|
||||||
if err := o.Complete(f, cmd, args, argsLenAtDash); err != nil {
|
if err := o.Complete(f, cmd, args, argsLenAtDash); err != nil {
|
||||||
|
@ -111,6 +113,13 @@ func NewCmdExec(f util.Factory, parentCommand string, streams genericiooptions.I
|
||||||
flags.BoolVarP(&o.KubectlExecOptions.Quiet, "quiet", "q", o.KubectlExecOptions.Quiet, "Only print output from the remote session")
|
flags.BoolVarP(&o.KubectlExecOptions.Quiet, "quiet", "q", o.KubectlExecOptions.Quiet, "Only print output from the remote session")
|
||||||
flags.VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
flags.VarP(&o.OperationScope, "operation-scope", "s", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.")
|
||||||
flags.StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
flags.StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is members, for example: --operation-scope=members --cluster=member1")
|
||||||
|
|
||||||
|
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc("container", utilcomp.ContainerCompletionFunc(f)))
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(cmd, options.KarmadaControlPlane, options.Members)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -90,6 +91,11 @@ func NewCmdExplain(f util.Factory, parentCommand string, streams genericiooption
|
||||||
// Only enable --output as a valid flag if the feature is enabled
|
// Only enable --output as a valid flag if the feature is enabled
|
||||||
flags.StringVar(&o.OutputFormat, "output", plaintextTemplateName, "Format in which to render the schema. Valid values are: (plaintext, plaintext-openapiv2).")
|
flags.StringVar(&o.OutputFormat, "output", plaintextTemplateName, "Format in which to render the schema. Valid values are: (plaintext, plaintext-openapiv2).")
|
||||||
flags.StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is member clusters, for example: --operation-scope=all --cluster=member1")
|
flags.StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is member clusters, for example: --operation-scope=all --cluster=member1")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(cmd, options.KarmadaControlPlane, options.Members)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,13 +130,13 @@ func NewCmdGet(f util.Factory, parentCommand string, streams genericiooptions.IO
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Example: fmt.Sprintf(getExample, parentCommand),
|
Example: fmt.Sprintf(getExample, parentCommand),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(f); err != nil {
|
if err := o.Complete(f, cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := o.Validate(cmd); err != nil {
|
if err := o.Validate(cmd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := o.Run(f, cmd, args); err != nil {
|
if err := o.Run(f, args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -167,7 +167,7 @@ func NewCmdGet(f util.Factory, parentCommand string, streams genericiooptions.IO
|
||||||
type CommandGetOptions struct {
|
type CommandGetOptions struct {
|
||||||
Clusters []string
|
Clusters []string
|
||||||
OperationScope options.OperationScope
|
OperationScope options.OperationScope
|
||||||
targetMemberClusters []string
|
TargetMemberClusters []string
|
||||||
|
|
||||||
PrintFlags *get.PrintFlags
|
PrintFlags *get.PrintFlags
|
||||||
ToPrinter func(*meta.RESTMapping, *bool, bool, bool) (printers.ResourcePrinterFunc, error)
|
ToPrinter func(*meta.RESTMapping, *bool, bool, bool) (printers.ResourcePrinterFunc, error)
|
||||||
|
@ -198,7 +198,7 @@ type CommandGetOptions struct {
|
||||||
|
|
||||||
genericiooptions.IOStreams
|
genericiooptions.IOStreams
|
||||||
|
|
||||||
karmadaClient karmadaclientset.Interface
|
KarmadaClient karmadaclientset.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommandGetOptions returns a CommandGetOptions with default chunk size 500.
|
// NewCommandGetOptions returns a CommandGetOptions with default chunk size 500.
|
||||||
|
@ -212,9 +212,7 @@ func NewCommandGetOptions(streams genericiooptions.IOStreams) *CommandGetOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete takes the command arguments and infers any remaining options.
|
// Complete takes the command arguments and infers any remaining options.
|
||||||
func (g *CommandGetOptions) Complete(f util.Factory) error {
|
func (g *CommandGetOptions) Complete(f util.Factory, cmd *cobra.Command) error {
|
||||||
newScheme := gclient.NewSchema()
|
|
||||||
|
|
||||||
err := g.handleNamespaceScopeFlags(f)
|
err := g.handleNamespaceScopeFlags(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -225,12 +223,54 @@ func (g *CommandGetOptions) Complete(f util.Factory) error {
|
||||||
templateArg = *g.PrintFlags.TemplateFlags.TemplateArgument
|
templateArg = *g.PrintFlags.TemplateFlags.TemplateArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outputOption := cmd.Flags().Lookup("output").Value.String()
|
||||||
|
if strings.Contains(outputOption, "custom-columns") || outputOption == "yaml" || strings.Contains(outputOption, "json") {
|
||||||
|
g.ServerPrint = false
|
||||||
|
}
|
||||||
|
|
||||||
// human readable printers have special conversion rules, so we determine if we're using one.
|
// human readable printers have special conversion rules, so we determine if we're using one.
|
||||||
if (len(*g.PrintFlags.OutputFormat) == 0 && len(templateArg) == 0) || *g.PrintFlags.OutputFormat == "wide" {
|
if (len(*g.PrintFlags.OutputFormat) == 0 && len(templateArg) == 0) || *g.PrintFlags.OutputFormat == "wide" {
|
||||||
g.IsHumanReadablePrinter = true
|
g.IsHumanReadablePrinter = true
|
||||||
}
|
}
|
||||||
|
|
||||||
g.ToPrinter = func(mapping *meta.RESTMapping, outputObjects *bool, withNamespace bool, withKind bool) (printers.ResourcePrinterFunc, error) {
|
g.ToPrinter = g.getResourcePrinter()
|
||||||
|
karmadaClient, err := f.KarmadaClientSet()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g.KarmadaClient = karmadaClient
|
||||||
|
return g.HandleClusterScopeFlags()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate checks the set of flags provided by the user.
|
||||||
|
func (g *CommandGetOptions) Validate(cmd *cobra.Command) error {
|
||||||
|
if cmdutil.GetFlagBool(cmd, "show-labels") {
|
||||||
|
outputOption := cmd.Flags().Lookup("output").Value.String()
|
||||||
|
if outputOption != "" && outputOption != "wide" {
|
||||||
|
return fmt.Errorf("--show-labels option cannot be used with %s printer", outputOption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.OutputWatchEvents && !(g.Watch || g.WatchOnly) {
|
||||||
|
return fmt.Errorf("--output-watch-events option can only be used with --watch or --watch-only")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := options.VerifyOperationScopeFlags(g.OperationScope); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.ContainMembersScope(g.OperationScope) && len(g.Clusters) > 0 {
|
||||||
|
clusters, err := g.KarmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return util.VerifyClustersExist(g.Clusters, clusters)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *CommandGetOptions) getResourcePrinter() func(mapping *meta.RESTMapping, outputObjects *bool, withNamespace bool, withKind bool) (printers.ResourcePrinterFunc, error) {
|
||||||
|
newScheme := gclient.NewSchema()
|
||||||
|
return func(mapping *meta.RESTMapping, outputObjects *bool, withNamespace bool, withKind bool) (printers.ResourcePrinterFunc, error) {
|
||||||
// make a new copy of current flags / opts before mutating
|
// make a new copy of current flags / opts before mutating
|
||||||
printFlags := g.PrintFlags.Copy()
|
printFlags := g.PrintFlags.Copy()
|
||||||
|
|
||||||
|
@ -263,51 +303,20 @@ func (g *CommandGetOptions) Complete(f util.Factory) error {
|
||||||
|
|
||||||
return printer.PrintObj, nil
|
return printer.PrintObj, nil
|
||||||
}
|
}
|
||||||
karmadaClient, err := f.KarmadaClientSet()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
g.karmadaClient = karmadaClient
|
|
||||||
return g.handleClusterScopeFlags()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate checks the set of flags provided by the user.
|
// HandleClusterScopeFlags used to handle flags related to cluster scope.
|
||||||
func (g *CommandGetOptions) Validate(cmd *cobra.Command) error {
|
func (g *CommandGetOptions) HandleClusterScopeFlags() error {
|
||||||
if cmdutil.GetFlagBool(cmd, "show-labels") {
|
|
||||||
outputOption := cmd.Flags().Lookup("output").Value.String()
|
|
||||||
if outputOption != "" && outputOption != "wide" {
|
|
||||||
return fmt.Errorf("--show-labels option cannot be used with %s printer", outputOption)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if g.OutputWatchEvents && !(g.Watch || g.WatchOnly) {
|
|
||||||
return fmt.Errorf("--output-watch-events option can only be used with --watch or --watch-only")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := options.VerifyOperationScopeFlags(g.OperationScope); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.ContainMembersScope(g.OperationScope) && len(g.Clusters) > 0 {
|
|
||||||
clusters, err := g.karmadaClient.ClusterV1alpha1().Clusters().List(context.TODO(), metav1.ListOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return util.VerifyClustersExist(g.Clusters, clusters)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *CommandGetOptions) handleClusterScopeFlags() error {
|
|
||||||
var err error
|
var err error
|
||||||
switch g.OperationScope {
|
switch g.OperationScope {
|
||||||
case options.KarmadaControlPlane:
|
case options.KarmadaControlPlane:
|
||||||
g.targetMemberClusters = []string{}
|
g.TargetMemberClusters = []string{}
|
||||||
case options.Members, options.All:
|
case options.Members, options.All:
|
||||||
if len(g.Clusters) == 0 {
|
if len(g.Clusters) == 0 {
|
||||||
g.targetMemberClusters, err = LoadRegisteredClusters(g.karmadaClient)
|
g.TargetMemberClusters, err = LoadRegisteredClusters(g.KarmadaClient)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
g.targetMemberClusters = g.Clusters
|
g.TargetMemberClusters = g.Clusters
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -339,7 +348,7 @@ type WatchObj struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run performs the get operation.
|
// Run performs the get operation.
|
||||||
func (g *CommandGetOptions) Run(f util.Factory, cmd *cobra.Command, args []string) error {
|
func (g *CommandGetOptions) Run(f util.Factory, args []string) error {
|
||||||
mux := sync.Mutex{}
|
mux := sync.Mutex{}
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
@ -347,24 +356,19 @@ func (g *CommandGetOptions) Run(f util.Factory, cmd *cobra.Command, args []strin
|
||||||
var watchObjs []WatchObj
|
var watchObjs []WatchObj
|
||||||
var allErrs []error
|
var allErrs []error
|
||||||
|
|
||||||
outputOption := cmd.Flags().Lookup("output").Value.String()
|
|
||||||
if strings.Contains(outputOption, "custom-columns") || outputOption == "yaml" || strings.Contains(outputOption, "json") {
|
|
||||||
g.ServerPrint = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.ContainKarmadaScope(g.OperationScope) {
|
if options.ContainKarmadaScope(g.OperationScope) {
|
||||||
g.getObjInfo(&mux, f, "Karmada", true, &objs, &watchObjs, &allErrs, args)
|
g.getObjInfo(&mux, f, "Karmada", true, &objs, &watchObjs, &allErrs, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(g.targetMemberClusters) != 0 {
|
if len(g.TargetMemberClusters) != 0 {
|
||||||
wg.Add(len(g.targetMemberClusters))
|
wg.Add(len(g.TargetMemberClusters))
|
||||||
for idx := range g.targetMemberClusters {
|
for idx := range g.TargetMemberClusters {
|
||||||
memberFactory, err := f.FactoryForMemberCluster(g.targetMemberClusters[idx])
|
memberFactory, err := f.FactoryForMemberCluster(g.TargetMemberClusters[idx])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
g.getObjInfo(&mux, memberFactory, g.targetMemberClusters[idx], false, &objs, &watchObjs, &allErrs, args)
|
g.getObjInfo(&mux, memberFactory, g.TargetMemberClusters[idx], false, &objs, &watchObjs, &allErrs, args)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -476,7 +480,7 @@ func (g *CommandGetOptions) printIfNotFindResource(written int, allErrs *[]error
|
||||||
if written != 0 || g.IgnoreNotFound || len(*allErrs) != 0 {
|
if written != 0 || g.IgnoreNotFound || len(*allErrs) != 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !options.ContainKarmadaScope(g.OperationScope) && len(g.targetMemberClusters) == 0 {
|
if !options.ContainKarmadaScope(g.OperationScope) && len(g.TargetMemberClusters) == 0 {
|
||||||
fmt.Fprintln(g.ErrOut, "No member Clusters found in Karmada control plane")
|
fmt.Fprintln(g.ErrOut, "No member Clusters found in Karmada control plane")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import (
|
||||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/genericresource"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util/genericresource"
|
||||||
"github.com/karmada-io/karmada/pkg/util/gclient"
|
"github.com/karmada-io/karmada/pkg/util/gclient"
|
||||||
"github.com/karmada-io/karmada/pkg/util/helper"
|
"github.com/karmada-io/karmada/pkg/util/helper"
|
||||||
|
@ -131,6 +132,7 @@ func NewCmdInterpret(f util.Factory, parentCommand string, streams genericioopti
|
||||||
cmdutil.AddJsonFilenameFlag(flags, &o.FilenameOptions.Filenames, "Filename, directory, or URL to files containing the customizations")
|
cmdutil.AddJsonFilenameFlag(flags, &o.FilenameOptions.Filenames, "Filename, directory, or URL to files containing the customizations")
|
||||||
flags.BoolVarP(&o.FilenameOptions.Recursive, "recursive", "R", false, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.")
|
flags.BoolVarP(&o.FilenameOptions.Recursive, "recursive", "R", false, "Process the directory used in -f, --filename recursively. Useful when you want to manage related manifests organized within the same directory.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/util"
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ func NewCmdJoin(f cmdutil.Factory, parentCommand string) *cobra.Command {
|
||||||
opts.AddFlags(flags)
|
opts.AddFlags(flags)
|
||||||
options.AddKubeConfigFlags(flags)
|
options.AddKubeConfigFlags(flags)
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/apply"
|
"github.com/karmada-io/karmada/pkg/karmadactl/apply"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/attach"
|
"github.com/karmada-io/karmada/pkg/karmadactl/attach"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit"
|
"github.com/karmada-io/karmada/pkg/karmadactl/cmdinit"
|
||||||
|
"github.com/karmada-io/karmada/pkg/karmadactl/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/cordon"
|
"github.com/karmada-io/karmada/pkg/karmadactl/cordon"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/create"
|
"github.com/karmada-io/karmada/pkg/karmadactl/create"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/deinit"
|
"github.com/karmada-io/karmada/pkg/karmadactl/deinit"
|
||||||
|
@ -56,6 +57,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/top"
|
"github.com/karmada-io/karmada/pkg/karmadactl/top"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/unjoin"
|
"github.com/karmada-io/karmada/pkg/karmadactl/unjoin"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/version/sharedcommand"
|
"github.com/karmada-io/karmada/pkg/version/sharedcommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,12 +93,21 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
|
||||||
_ = flag.CommandLine.Parse(nil)
|
_ = flag.CommandLine.Parse(nil)
|
||||||
f := util.NewFactory(options.DefaultConfigFlags)
|
f := util.NewFactory(options.DefaultConfigFlags)
|
||||||
ioStreams := genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
|
ioStreams := genericiooptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
|
||||||
|
|
||||||
|
// Avoid import cycle by setting ValidArgsFunction here instead of in NewCmdGet()
|
||||||
|
getCmd := get.NewCmdGet(f, parentCommand, ioStreams)
|
||||||
|
getCmd.ValidArgsFunction = utilcomp.ResourceTypeAndNameCompletionFunc(f)
|
||||||
|
utilcomp.RegisterCompletionFuncForClustersFlag(getCmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(getCmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(getCmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForOperationScopeFlag(getCmd)
|
||||||
|
|
||||||
groups := templates.CommandGroups{
|
groups := templates.CommandGroups{
|
||||||
{
|
{
|
||||||
Message: "Basic Commands:",
|
Message: "Basic Commands:",
|
||||||
Commands: []*cobra.Command{
|
Commands: []*cobra.Command{
|
||||||
explain.NewCmdExplain(f, parentCommand, ioStreams),
|
explain.NewCmdExplain(f, parentCommand, ioStreams),
|
||||||
get.NewCmdGet(f, parentCommand, ioStreams),
|
getCmd,
|
||||||
create.NewCmdCreate(f, parentCommand, ioStreams),
|
create.NewCmdCreate(f, parentCommand, ioStreams),
|
||||||
karmadactldelete.NewCmdDelete(f, parentCommand, ioStreams),
|
karmadactldelete.NewCmdDelete(f, parentCommand, ioStreams),
|
||||||
edit.NewCmdEdit(f, parentCommand, ioStreams),
|
edit.NewCmdEdit(f, parentCommand, ioStreams),
|
||||||
|
@ -146,6 +157,7 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
|
||||||
Commands: []*cobra.Command{
|
Commands: []*cobra.Command{
|
||||||
label.NewCmdLabel(f, parentCommand, ioStreams),
|
label.NewCmdLabel(f, parentCommand, ioStreams),
|
||||||
annotate.NewCmdAnnotate(f, parentCommand, ioStreams),
|
annotate.NewCmdAnnotate(f, parentCommand, ioStreams),
|
||||||
|
completion.NewCmdCompletion(parentCommand, ioStreams.Out, ""),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -165,6 +177,8 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command {
|
||||||
|
|
||||||
templates.ActsAsRootCommand(rootCmd, filters, groups...)
|
templates.ActsAsRootCommand(rootCmd, filters, groups...)
|
||||||
|
|
||||||
|
utilcomp.SetFactoryForCompletion(f)
|
||||||
|
|
||||||
return rootCmd
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -56,5 +57,8 @@ func NewCmdLabel(f util.Factory, parentCommand string, ioStreams genericiooption
|
||||||
}
|
}
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
options.AddNamespaceFlag(cmd.Flags())
|
options.AddNamespaceFlag(cmd.Flags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -79,6 +80,7 @@ func NewCmdLogs(f util.Factory, parentCommand string, streams genericiooptions.I
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Example: fmt.Sprintf(logsExample, parentCommand),
|
Example: fmt.Sprintf(logsExample, parentCommand),
|
||||||
|
ValidArgsFunction: utilcomp.PodResourceNameAndContainerCompletionFunc(f),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(cmd, args, f); err != nil {
|
if err := o.Complete(cmd, args, f); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -102,6 +104,9 @@ func NewCmdLogs(f util.Factory, parentCommand string, streams genericiooptions.I
|
||||||
flags.StringVarP(&o.Cluster, "cluster", "C", "", "Specify a member cluster")
|
flags.StringVarP(&o.Cluster, "cluster", "C", "", "Specify a member cluster")
|
||||||
o.KubectlLogsOptions.AddFlags(cmd)
|
o.KubectlLogsOptions.AddFlags(cmd)
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -52,5 +53,8 @@ func NewCmdPatch(f util.Factory, parentCommand string, ioStreams genericiooption
|
||||||
}
|
}
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
options.AddNamespaceFlag(cmd.Flags())
|
options.AddNamespaceFlag(cmd.Flags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/get"
|
"github.com/karmada-io/karmada/pkg/karmadactl/get"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/declarative"
|
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/declarative"
|
||||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/webhook"
|
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/webhook"
|
||||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/webhook/request"
|
"github.com/karmada-io/karmada/pkg/resourceinterpreter/customized/webhook/request"
|
||||||
|
@ -103,6 +104,7 @@ func NewCmdPromote(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
Example: fmt.Sprintf(promoteExample, parentCommand),
|
Example: fmt.Sprintf(promoteExample, parentCommand),
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgsFunction: utilcomp.ResourceTypeAndNameCompletionFunc(f),
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if err := opts.Complete(f, args); err != nil {
|
if err := opts.Complete(f, args); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -125,6 +127,9 @@ func NewCmdPromote(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
options.AddKubeConfigFlags(flag)
|
options.AddKubeConfigFlags(flag)
|
||||||
options.AddNamespaceFlag(flag)
|
options.AddNamespaceFlag(flag)
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForClusterFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
"github.com/karmada-io/karmada/pkg/generated/clientset/versioned/scheme"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/util/lifted"
|
"github.com/karmada-io/karmada/pkg/util/lifted"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -84,6 +85,7 @@ func NewCmdTaint(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
Example: fmt.Sprintf(taintExample, parentCommand),
|
Example: fmt.Sprintf(taintExample, parentCommand),
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgsFunction: utilcomp.SpecifiedResourceTypeAndNameCompletionFunc(f, []string{"cluster"}),
|
||||||
RunE: func(_ *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if err := opts.Complete(f, args); err != nil {
|
if err := opts.Complete(f, args); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -107,6 +109,7 @@ func NewCmdTaint(f util.Factory, parentCommand string) *cobra.Command {
|
||||||
flags.BoolVar(&opts.overwrite, "overwrite", opts.overwrite, "If true, allow taints to be overwritten, otherwise reject taint updates that overwrite existing taints.")
|
flags.BoolVar(&opts.overwrite, "overwrite", opts.overwrite, "If true, allow taints to be overwritten, otherwise reject taint updates that overwrite existing taints.")
|
||||||
flags.BoolVar(&opts.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
|
flags.BoolVar(&opts.DryRun, "dry-run", false, "Run the command in dry-run mode, without making any server requests.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
tokenutil "github.com/karmada-io/karmada/pkg/karmadactl/util/bootstraptoken"
|
tokenutil "github.com/karmada-io/karmada/pkg/karmadactl/util/bootstraptoken"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -135,6 +136,7 @@ func NewCmdTokenCreate(f util.Factory, out io.Writer, tokenOpts *CommandTokenOpt
|
||||||
cmd.Flags().StringSliceVar(&tokenOpts.Groups, "groups", tokenutil.DefaultGroups, fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern))
|
cmd.Flags().StringSliceVar(&tokenOpts.Groups, "groups", tokenutil.DefaultGroups, fmt.Sprintf("Extra groups that this token will authenticate as when used for authentication. Must match %q", bootstrapapi.BootstrapGroupPattern))
|
||||||
cmd.Flags().StringVar(&tokenOpts.Description, "description", tokenOpts.Description, "A human friendly description of how this token is used.")
|
cmd.Flags().StringVar(&tokenOpts.Description, "description", tokenOpts.Description, "A human friendly description of how this token is used.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +160,7 @@ func NewCmdTokenList(f util.Factory, out io.Writer, errW io.Writer, tokenOpts *C
|
||||||
|
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +193,7 @@ func NewCmdTokenDelete(f util.Factory, out io.Writer, tokenOpts *CommandTokenOpt
|
||||||
|
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ import (
|
||||||
"k8s.io/cli-runtime/pkg/genericiooptions"
|
"k8s.io/cli-runtime/pkg/genericiooptions"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/util/completion"
|
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
@ -42,6 +41,7 @@ import (
|
||||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeOptions contains all the options for running the top-node cli command.
|
// NodeOptions contains all the options for running the top-node cli command.
|
||||||
|
@ -104,13 +104,16 @@ func NewCmdTopNode(f util.Factory, parentCommand string, o *NodeOptions, streams
|
||||||
Short: i18n.T("Display resource (CPU/memory) usage of nodes"),
|
Short: i18n.T("Display resource (CPU/memory) usage of nodes"),
|
||||||
Long: topNodeLong,
|
Long: topNodeLong,
|
||||||
Example: fmt.Sprintf(topNodeExample, parentCommand),
|
Example: fmt.Sprintf(topNodeExample, parentCommand),
|
||||||
ValidArgsFunction: completion.ResourceNameCompletionFunc(f, "node"),
|
ValidArgsFunction: utilcomp.ResourceNameCompletionFunc(f, "node"),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||||
cmdutil.CheckErr(o.Validate())
|
cmdutil.CheckErr(o.Validate())
|
||||||
cmdutil.CheckErr(o.RunTopNode(f))
|
cmdutil.CheckErr(o.RunTopNode(f))
|
||||||
},
|
},
|
||||||
Aliases: []string{"nodes", "no"},
|
Aliases: []string{"nodes", "no"},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"parent": "top", // used for completion code to set default operation scope.
|
||||||
|
},
|
||||||
}
|
}
|
||||||
cmdutil.AddLabelSelectorFlagVar(cmd, &o.Selector)
|
cmdutil.AddLabelSelectorFlagVar(cmd, &o.Selector)
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
|
@ -120,6 +123,8 @@ func NewCmdTopNode(f util.Factory, parentCommand string, o *NodeOptions, streams
|
||||||
cmd.Flags().BoolVar(&o.UseProtocolBuffers, "use-protocol-buffers", o.UseProtocolBuffers, "Enables using protocol-buffers to access Metrics API.")
|
cmd.Flags().BoolVar(&o.UseProtocolBuffers, "use-protocol-buffers", o.UseProtocolBuffers, "Enables using protocol-buffers to access Metrics API.")
|
||||||
cmd.Flags().BoolVar(&o.ShowCapacity, "show-capacity", o.ShowCapacity, "Print node resources based on Capacity instead of Allocatable(default) of the nodes.")
|
cmd.Flags().BoolVar(&o.ShowCapacity, "show-capacity", o.ShowCapacity, "Print node resources based on Capacity instead of Allocatable(default) of the nodes.")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForClustersFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ import (
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/util/completion"
|
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
metricsapi "k8s.io/metrics/pkg/apis/metrics"
|
||||||
|
@ -44,6 +43,7 @@ import (
|
||||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PodOptions contains the options to the top command.
|
// PodOptions contains the options to the top command.
|
||||||
|
@ -115,13 +115,16 @@ func NewCmdTopPod(f util.Factory, parentCommand string, o *PodOptions, streams g
|
||||||
Short: i18n.T("Display resource (CPU/memory) usage of pods of member clusters"),
|
Short: i18n.T("Display resource (CPU/memory) usage of pods of member clusters"),
|
||||||
Long: topPodLong,
|
Long: topPodLong,
|
||||||
Example: fmt.Sprintf(topPodExample, parentCommand),
|
Example: fmt.Sprintf(topPodExample, parentCommand),
|
||||||
ValidArgsFunction: completion.ResourceNameCompletionFunc(f, "pod"),
|
ValidArgsFunction: utilcomp.ResourceNameCompletionFunc(f, "pod"),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||||
cmdutil.CheckErr(o.Validate())
|
cmdutil.CheckErr(o.Validate())
|
||||||
cmdutil.CheckErr(o.RunTopPod(f))
|
cmdutil.CheckErr(o.RunTopPod(f))
|
||||||
},
|
},
|
||||||
Aliases: []string{"pods", "po"},
|
Aliases: []string{"pods", "po"},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"parent": "top", // used for completion code to set default operation scope.
|
||||||
|
},
|
||||||
}
|
}
|
||||||
cmdutil.AddLabelSelectorFlagVar(cmd, &o.LabelSelector)
|
cmdutil.AddLabelSelectorFlagVar(cmd, &o.LabelSelector)
|
||||||
options.AddKubeConfigFlags(cmd.Flags())
|
options.AddKubeConfigFlags(cmd.Flags())
|
||||||
|
@ -134,6 +137,10 @@ func NewCmdTopPod(f util.Factory, parentCommand string, o *PodOptions, streams g
|
||||||
cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "If present, print output without headers.")
|
cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "If present, print output without headers.")
|
||||||
cmd.Flags().BoolVar(&o.UseProtocolBuffers, "use-protocol-buffers", o.UseProtocolBuffers, "Enables using protocol-buffers to access Metrics API.")
|
cmd.Flags().BoolVar(&o.UseProtocolBuffers, "use-protocol-buffers", o.UseProtocolBuffers, "Enables using protocol-buffers to access Metrics API.")
|
||||||
cmd.Flags().BoolVar(&o.Sum, "sum", o.Sum, "Print the sum of the resource usage")
|
cmd.Flags().BoolVar(&o.Sum, "sum", o.Sum, "Print the sum of the resource usage")
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
|
utilcomp.RegisterCompletionFuncForNamespaceFlag(cmd, f)
|
||||||
|
utilcomp.RegisterCompletionFuncForClustersFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
cmdutil "github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
"github.com/karmada-io/karmada/pkg/karmadactl/util/apiclient"
|
||||||
|
utilcomp "github.com/karmada-io/karmada/pkg/karmadactl/util/completion"
|
||||||
"github.com/karmada-io/karmada/pkg/util"
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
"github.com/karmada-io/karmada/pkg/util/names"
|
"github.com/karmada-io/karmada/pkg/util/names"
|
||||||
)
|
)
|
||||||
|
@ -86,6 +87,7 @@ func NewCmdUnjoin(f cmdutil.Factory, parentCommand string) *cobra.Command {
|
||||||
opts.AddFlags(flags)
|
opts.AddFlags(flags)
|
||||||
options.AddKubeConfigFlags(flags)
|
options.AddKubeConfigFlags(flags)
|
||||||
|
|
||||||
|
utilcomp.RegisterCompletionFuncForKarmadaContextFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024 The Karmada 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 (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericiooptions"
|
||||||
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
|
"k8s.io/kubectl/pkg/cmd/apiresources"
|
||||||
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
|
"k8s.io/kubectl/pkg/polymorphichelpers"
|
||||||
|
"k8s.io/kubectl/pkg/scheme"
|
||||||
|
|
||||||
|
"github.com/karmada-io/karmada/pkg/karmadactl/get"
|
||||||
|
"github.com/karmada-io/karmada/pkg/karmadactl/options"
|
||||||
|
"github.com/karmada-io/karmada/pkg/karmadactl/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
var factory util.Factory
|
||||||
|
|
||||||
|
// SetFactoryForCompletion Store the factory which is needed by the completion functions.
|
||||||
|
// Not all commands have access to the factory, so cannot pass it to the completion functions.
|
||||||
|
func SetFactoryForCompletion(f util.Factory) {
|
||||||
|
factory = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceTypeAndNameCompletionFunc Returns a completion function that completes resource types
|
||||||
|
// and resource names that match the toComplete prefix. It supports the <type>/<name> form.
|
||||||
|
func ResourceTypeAndNameCompletionFunc(f util.Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return resourceTypeAndNameCompletionFunc(f, nil, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpecifiedResourceTypeAndNameCompletionFunc Returns a completion function that completes resource
|
||||||
|
// types limited to the specified allowedTypes, and resource names that match the toComplete prefix.
|
||||||
|
// It allows for multiple resources. It supports the <type>/<name> form.
|
||||||
|
func SpecifiedResourceTypeAndNameCompletionFunc(f util.Factory, allowedTypes []string) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return resourceTypeAndNameCompletionFunc(f, allowedTypes, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceNameCompletionFunc Returns a completion function that completes as a first argument
|
||||||
|
// the resource names specified by the resourceType parameter, and which match the toComplete prefix.
|
||||||
|
// This function does NOT support the <type>/<name> form: it is meant to be used by commands
|
||||||
|
// that don't support that form. For commands that apply to pods and that support the <type>/<name>
|
||||||
|
// form, please use PodResourceNameCompletionFunc()
|
||||||
|
func ResourceNameCompletionFunc(f util.Factory, resourceType string) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var comps []string
|
||||||
|
if len(args) == 0 {
|
||||||
|
comps = CompGetResource(f, cmd, resourceType, toComplete)
|
||||||
|
}
|
||||||
|
return comps, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodResourceNameCompletionFunc Returns a completion function that completes:
|
||||||
|
// 1- pod names that match the toComplete prefix
|
||||||
|
// 2- resource types containing pods which match the toComplete prefix
|
||||||
|
func PodResourceNameCompletionFunc(f util.Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var comps []string
|
||||||
|
directive := cobra.ShellCompDirectiveNoFileComp
|
||||||
|
if len(args) == 0 {
|
||||||
|
comps, directive = doPodResourceCompletion(f, cmd, toComplete)
|
||||||
|
}
|
||||||
|
return comps, directive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodResourceNameAndContainerCompletionFunc Returns a completion function that completes, as a first argument:
|
||||||
|
// 1- pod names that match the toComplete prefix
|
||||||
|
// 2- resource types containing pods which match the toComplete prefix
|
||||||
|
// and as a second argument the containers within the specified pod.
|
||||||
|
func PodResourceNameAndContainerCompletionFunc(f util.Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var comps []string
|
||||||
|
directive := cobra.ShellCompDirectiveNoFileComp
|
||||||
|
if len(args) == 0 {
|
||||||
|
comps, directive = doPodResourceCompletion(f, cmd, toComplete)
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
podName := convertResourceNameToPodName(f, args[0])
|
||||||
|
comps = CompGetContainers(f, cmd, podName, toComplete)
|
||||||
|
}
|
||||||
|
return comps, directive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerCompletionFunc Returns a completion function that completes the containers within the
|
||||||
|
// pod specified by the first argument. The resource containing the pod can be specified in
|
||||||
|
// the <type>/<name> form.
|
||||||
|
func ContainerCompletionFunc(f util.Factory) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var comps []string
|
||||||
|
// We need the pod name to be able to complete the container names, it must be in args[0].
|
||||||
|
// That first argument can also be of the form <type>/<name> so we need to convert it.
|
||||||
|
if len(args) > 0 {
|
||||||
|
podName := convertResourceNameToPodName(f, args[0])
|
||||||
|
comps = CompGetContainers(f, cmd, podName, toComplete)
|
||||||
|
}
|
||||||
|
return comps, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompGetResource gets the list of the resource specified which begin with `toComplete`.
|
||||||
|
func CompGetResource(f util.Factory, cmd *cobra.Command, resourceName string, toComplete string) []string {
|
||||||
|
template := "{{ range .items }}{{ .metadata.name }} {{ end }}"
|
||||||
|
return CompGetFromTemplate(&template, f, cmd, "", []string{resourceName}, toComplete)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompGetContainers gets the list of containers of the specified pod which begin with `toComplete`.
|
||||||
|
func CompGetContainers(f util.Factory, cmd *cobra.Command, podName string, toComplete string) []string {
|
||||||
|
template := "{{ range .spec.initContainers }}{{ .name }} {{end}}{{ range .spec.containers }}{{ .name }} {{ end }}"
|
||||||
|
return CompGetFromTemplate(&template, f, cmd, "", []string{"pod", podName}, toComplete)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompGetFromTemplate executes a Get operation using the specified template and args and returns the results
|
||||||
|
// which begin with `toComplete`.
|
||||||
|
func CompGetFromTemplate(template *string, f util.Factory, cmd *cobra.Command, namespace string, args []string, toComplete string) []string {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
streams := genericiooptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: io.Discard}
|
||||||
|
o := get.NewCommandGetOptions(streams)
|
||||||
|
|
||||||
|
// Get the list of names of the specified resource
|
||||||
|
o.PrintFlags.TemplateFlags.GoTemplatePrintFlags.TemplateArgument = template
|
||||||
|
format := "go-template"
|
||||||
|
o.PrintFlags.OutputFormat = &format
|
||||||
|
|
||||||
|
// Do the steps Complete() would have done.
|
||||||
|
// We cannot actually call Complete() or Validate() as these function check for
|
||||||
|
// the presence of flags, which, in our case won't be there
|
||||||
|
if namespace != "" {
|
||||||
|
o.Namespace = namespace
|
||||||
|
o.ExplicitNamespace = true
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
o.Namespace, o.ExplicitNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
o.ToPrinter = func(_ *meta.RESTMapping, _ *bool, _ bool, _ bool) (printers.ResourcePrinterFunc, error) {
|
||||||
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return printer.PrintObj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
o.OperationScope = options.KarmadaControlPlane
|
||||||
|
// currently, the operation-scope of command `top`, `logs` and `promote` is members.
|
||||||
|
if cmd.Annotations["parent"] == "top" || cmd.Name() == "logs" || cmd.Name() == "promote" {
|
||||||
|
o.OperationScope = options.Members
|
||||||
|
}
|
||||||
|
operationScopeFlag := cmd.Flag("operation-scope")
|
||||||
|
if operationScopeFlag != nil {
|
||||||
|
o.OperationScope = options.OperationScope(operationScopeFlag.Value.String())
|
||||||
|
}
|
||||||
|
o.Clusters, _ = cmd.Flags().GetStringSlice("clusters")
|
||||||
|
clusterFlag := cmd.Flag("cluster")
|
||||||
|
if clusterFlag != nil {
|
||||||
|
cluster := clusterFlag.Value.String()
|
||||||
|
if len(cluster) != 0 {
|
||||||
|
o.Clusters = []string{cluster}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
o.KarmadaClient, _ = f.KarmadaClientSet()
|
||||||
|
if err := o.HandleClusterScopeFlags(); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := o.Run(f, args); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var comps []string
|
||||||
|
resources := strings.Split(buf.String(), " ")
|
||||||
|
for _, res := range resources {
|
||||||
|
if res != "" && strings.HasPrefix(res, toComplete) {
|
||||||
|
comps = append(comps, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comps
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListContextsInConfig returns a list of context names which begin with `toComplete`
|
||||||
|
func ListContextsInConfig(toComplete string) []string {
|
||||||
|
config, err := factory.ToRawKubeConfigLoader().RawConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var ret []string
|
||||||
|
for name := range config.Contexts {
|
||||||
|
if strings.HasPrefix(name, toComplete) {
|
||||||
|
ret = append(ret, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListClustersInConfig returns a list of cluster names which begin with `toComplete`
|
||||||
|
func ListClustersInConfig(toComplete string) []string {
|
||||||
|
set, err := factory.KarmadaClientSet()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err := set.ClusterV1alpha1().Clusters().List(context.Background(), metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret []string
|
||||||
|
for _, cluster := range list.Items {
|
||||||
|
if strings.HasPrefix(cluster.Name, toComplete) {
|
||||||
|
ret = append(ret, cluster.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// compGetResourceList returns the list of api resources which begin with `toComplete`.
|
||||||
|
func compGetResourceList(restClientGetter genericclioptions.RESTClientGetter, cmd *cobra.Command, toComplete string) []string {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
streams := genericiooptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: io.Discard}
|
||||||
|
|
||||||
|
// TODO: Using karmadactlapiresources.CommandAPIResourcesOptions to adapt to the operation scope.
|
||||||
|
o := apiresources.NewAPIResourceOptions(streams)
|
||||||
|
|
||||||
|
if err := o.Complete(restClientGetter, cmd, nil); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of resources
|
||||||
|
o.Output = "name"
|
||||||
|
o.Cached = true
|
||||||
|
o.Verbs = []string{"get"}
|
||||||
|
// TODO:Should set --request-timeout=5s
|
||||||
|
|
||||||
|
// Ignore errors as the output may still be valid
|
||||||
|
if err := o.RunAPIResources(); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resources can be a comma-separated list. The last element is then
|
||||||
|
// the one we should complete. For example if toComplete=="pods,secre"
|
||||||
|
// we should return "pods,secrets"
|
||||||
|
prefix := ""
|
||||||
|
suffix := toComplete
|
||||||
|
lastIdx := strings.LastIndex(toComplete, ",")
|
||||||
|
if lastIdx != -1 {
|
||||||
|
prefix = toComplete[0 : lastIdx+1]
|
||||||
|
suffix = toComplete[lastIdx+1:]
|
||||||
|
}
|
||||||
|
var comps []string
|
||||||
|
resources := strings.Split(buf.String(), "\n")
|
||||||
|
for _, res := range resources {
|
||||||
|
if res != "" && strings.HasPrefix(res, suffix) {
|
||||||
|
comps = append(comps, fmt.Sprintf("%s%s", prefix, res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comps
|
||||||
|
}
|
||||||
|
|
||||||
|
// resourceTypeAndNameCompletionFunc Returns a completion function that completes resource types
|
||||||
|
// and resource names that match the toComplete prefix. It supports the <type>/<name> form.
|
||||||
|
//
|
||||||
|
//nolint:gocyclo
|
||||||
|
func resourceTypeAndNameCompletionFunc(f util.Factory, allowedTypes []string, allowRepeat bool) func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var comps []string
|
||||||
|
directive := cobra.ShellCompDirectiveNoFileComp
|
||||||
|
|
||||||
|
if len(args) > 0 && !strings.Contains(args[0], "/") {
|
||||||
|
// The first argument is of the form <type> (e.g., pods)
|
||||||
|
// All following arguments should be a resource name.
|
||||||
|
if allowRepeat || len(args) == 1 {
|
||||||
|
comps = CompGetResource(f, cmd, args[0], toComplete)
|
||||||
|
|
||||||
|
// Remove choices already on the command-line
|
||||||
|
if len(args) > 1 {
|
||||||
|
comps = cmdutil.Difference(comps, args[1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
slashIdx := strings.Index(toComplete, "/")
|
||||||
|
if slashIdx == -1 {
|
||||||
|
if len(args) == 0 {
|
||||||
|
// We are completing the first argument. We default to the normal
|
||||||
|
// <type> form (not the form <type>/<name>).
|
||||||
|
// So we suggest resource types and let the shell add a space after
|
||||||
|
// the completion.
|
||||||
|
if len(allowedTypes) == 0 {
|
||||||
|
comps = compGetResourceList(f, cmd, toComplete)
|
||||||
|
} else {
|
||||||
|
for _, c := range allowedTypes {
|
||||||
|
if strings.HasPrefix(c, toComplete) {
|
||||||
|
comps = append(comps, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Here we know the first argument contains a / (<type>/<name>).
|
||||||
|
// All other arguments must also use that form.
|
||||||
|
if allowRepeat {
|
||||||
|
// Since toComplete does not already contain a / we know we are completing a
|
||||||
|
// resource type. Disable adding a space after the completion, and add the /
|
||||||
|
directive |= cobra.ShellCompDirectiveNoSpace
|
||||||
|
|
||||||
|
if len(allowedTypes) == 0 {
|
||||||
|
typeComps := compGetResourceList(f, cmd, toComplete)
|
||||||
|
for _, c := range typeComps {
|
||||||
|
comps = append(comps, fmt.Sprintf("%s/", c))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, c := range allowedTypes {
|
||||||
|
if strings.HasPrefix(c, toComplete) {
|
||||||
|
comps = append(comps, fmt.Sprintf("%s/", c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We are completing an argument of the form <type>/<name>
|
||||||
|
// and since the / is already present, we are completing the resource name.
|
||||||
|
if allowRepeat || len(args) == 0 {
|
||||||
|
resourceType := toComplete[:slashIdx]
|
||||||
|
toComplete = toComplete[slashIdx+1:]
|
||||||
|
nameComps := CompGetResource(f, cmd, resourceType, toComplete)
|
||||||
|
for _, c := range nameComps {
|
||||||
|
comps = append(comps, fmt.Sprintf("%s/%s", resourceType, c))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove choices already on the command-line.
|
||||||
|
if len(args) > 0 {
|
||||||
|
comps = cmdutil.Difference(comps, args[0:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comps, directive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// doPodResourceCompletion Returns completions of:
|
||||||
|
// 1- pod names that match the toComplete prefix
|
||||||
|
// 2- resource types containing pods which match the toComplete prefix
|
||||||
|
func doPodResourceCompletion(f util.Factory, cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var comps []string
|
||||||
|
directive := cobra.ShellCompDirectiveNoFileComp
|
||||||
|
slashIdx := strings.Index(toComplete, "/")
|
||||||
|
if slashIdx == -1 {
|
||||||
|
// Standard case, complete pod names
|
||||||
|
comps = CompGetResource(f, cmd, "pod", toComplete)
|
||||||
|
|
||||||
|
// Also include resource choices for the <type>/<name> form,
|
||||||
|
// but only for resources that contain pods
|
||||||
|
resourcesWithPods := []string{
|
||||||
|
"daemonsets",
|
||||||
|
"deployments",
|
||||||
|
"pods",
|
||||||
|
"jobs",
|
||||||
|
"replicasets",
|
||||||
|
"replicationcontrollers",
|
||||||
|
"services",
|
||||||
|
"statefulsets"}
|
||||||
|
|
||||||
|
if len(comps) == 0 {
|
||||||
|
// If there are no pods to complete, we will only be completing
|
||||||
|
// <type>/. We should disable adding a space after the /.
|
||||||
|
directive |= cobra.ShellCompDirectiveNoSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, resource := range resourcesWithPods {
|
||||||
|
if strings.HasPrefix(resource, toComplete) {
|
||||||
|
comps = append(comps, fmt.Sprintf("%s/", resource))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Dealing with the <type>/<name> form, use the specified resource type
|
||||||
|
resourceType := toComplete[:slashIdx]
|
||||||
|
toComplete = toComplete[slashIdx+1:]
|
||||||
|
nameComps := CompGetResource(f, cmd, resourceType, toComplete)
|
||||||
|
for _, c := range nameComps {
|
||||||
|
comps = append(comps, fmt.Sprintf("%s/%s", resourceType, c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return comps, directive
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertResourceNameToPodName Converts a resource name to a pod name.
|
||||||
|
// If the resource name is of the form <type>/<name>, we use
|
||||||
|
// polymorphichelpers.AttachablePodForObjectFn(), if not, the resource name
|
||||||
|
// is already a pod name.
|
||||||
|
func convertResourceNameToPodName(f cmdutil.Factory, resourceName string) string {
|
||||||
|
var podName string
|
||||||
|
if !strings.Contains(resourceName, "/") {
|
||||||
|
// When we don't have the <type>/<name> form, the resource name is the pod name
|
||||||
|
podName = resourceName
|
||||||
|
} else {
|
||||||
|
// if the resource name is of the form <type>/<name>, we need to convert it to a pod name
|
||||||
|
ns, _, err := f.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
resourceWithPod, err := f.NewBuilder().
|
||||||
|
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
||||||
|
ContinueOnError().
|
||||||
|
NamespaceParam(ns).DefaultNamespace().
|
||||||
|
ResourceNames("pods", resourceName).
|
||||||
|
Do().Object()
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// For shell completion, use a short timeout
|
||||||
|
forwardablePod, err := polymorphichelpers.AttachablePodForObjectFn(f, resourceWithPod, 100*time.Millisecond)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
podName = forwardablePod.Name
|
||||||
|
}
|
||||||
|
return podName
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterCompletionFuncForNamespaceFlag registers CompletionFunc for flag namespace.
|
||||||
|
func RegisterCompletionFuncForNamespaceFlag(cmd *cobra.Command, f util.Factory) {
|
||||||
|
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc(
|
||||||
|
"namespace",
|
||||||
|
func(cmd *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return CompGetResource(f, cmd, "namespace", toComplete), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterCompletionFuncForClusterFlag registers CompletionFunc for flag cluster.
|
||||||
|
func RegisterCompletionFuncForClusterFlag(cmd *cobra.Command) {
|
||||||
|
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc(
|
||||||
|
"cluster",
|
||||||
|
func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return ListClustersInConfig(toComplete), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterCompletionFuncForClustersFlag registers CompletionFunc for flag clusters.
|
||||||
|
func RegisterCompletionFuncForClustersFlag(cmd *cobra.Command) {
|
||||||
|
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc(
|
||||||
|
"clusters",
|
||||||
|
func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return ListClustersInConfig(toComplete), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterCompletionFuncForKarmadaContextFlag registers CompletionFunc for flag karmada-context.
|
||||||
|
func RegisterCompletionFuncForKarmadaContextFlag(cmd *cobra.Command) {
|
||||||
|
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc(
|
||||||
|
"karmada-context",
|
||||||
|
func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return ListContextsInConfig(toComplete), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterCompletionFuncForOperationScopeFlag registers CompletionFunc for flag operation-scope.
|
||||||
|
func RegisterCompletionFuncForOperationScopeFlag(cmd *cobra.Command, supportScope ...options.OperationScope) {
|
||||||
|
cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc(
|
||||||
|
"operation-scope",
|
||||||
|
func(_ *cobra.Command, _ []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
var ret []string
|
||||||
|
|
||||||
|
if len(supportScope) == 0 {
|
||||||
|
supportScope = []options.OperationScope{options.KarmadaControlPlane, options.Members, options.All}
|
||||||
|
}
|
||||||
|
for _, scope := range supportScope {
|
||||||
|
if strings.HasPrefix(scope.String(), toComplete) {
|
||||||
|
ret = append(ret, scope.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}))
|
||||||
|
}
|
Loading…
Reference in New Issue