diff --git a/cli/cmds/cluster_create.go b/cli/cmds/cluster_create.go index c2be9323..191d1b1e 100644 --- a/cli/cmds/cluster_create.go +++ b/cli/cmds/cluster_create.go @@ -70,6 +70,7 @@ func NewClusterCreateCmd(appCtx *AppContext) *cobra.Command { } CobraFlagNamespace(appCtx, cmd.Flags()) + createFlags(cmd, createConfig) return cmd diff --git a/cli/cmds/cluster_create_flags.go b/cli/cmds/cluster_create_flags.go index 47d2585b..35526afc 100644 --- a/cli/cmds/cluster_create_flags.go +++ b/cli/cmds/cluster_create_flags.go @@ -4,6 +4,7 @@ import ( "errors" "time" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/api/resource" @@ -32,6 +33,13 @@ func createFlags(cmd *cobra.Command, cfg *CreateConfig) { cmd.Flags().StringVar(&cfg.policy, "policy", "", "The policy to create the cluster in") cmd.Flags().StringVar(&cfg.customCertsPath, "custom-certs", "", "The path for custom certificate directory") cmd.Flags().DurationVar(&cfg.timeout, "timeout", 3*time.Minute, "The timeout for waiting for the cluster to become ready (e.g., 10s, 5m, 1h).") + + mustRegisterFlagCompletion(cmd, "mode", completeClusterMode) + mustRegisterFlagCompletion(cmd, "persistence-type", completePersistenceMode) + + if err := cmd.MarkFlagDirname("custom-certs"); err != nil { + logrus.Fatal(err) + } } func validateCreateConfig(cfg *CreateConfig) error { diff --git a/cli/cmds/completion.go b/cli/cmds/completion.go new file mode 100644 index 00000000..761b0518 --- /dev/null +++ b/cli/cmds/completion.go @@ -0,0 +1,68 @@ +package cmds + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/rancher/k3k/pkg/apis/k3k.io/v1beta1" +) + +var completeClusterMode = cobra.FixedCompletions( + []string{ + string(v1beta1.SharedClusterMode), + string(v1beta1.VirtualClusterMode), + }, + cobra.ShellCompDirectiveNoFileComp, +) + +var completePersistenceMode = cobra.FixedCompletions( + []string{ + string(v1beta1.DynamicPersistenceMode), + string(v1beta1.EphemeralPersistenceMode), + }, + cobra.ShellCompDirectiveNoFileComp, +) + +// mustRegisterFlagCompletion registers a completion function for a flag and +// aborts if the flag does not exist. This only fails on programmer error, so +// there is no reason to bubble it up to the caller. +func mustRegisterFlagCompletion(cmd *cobra.Command, flagName string, f cobra.CompletionFunc) { + if err := cmd.RegisterFlagCompletionFunc(flagName, f); err != nil { + logrus.Fatal(err) + } +} + +// disableFileCompletion walks the command tree and turns off cobra's default +// filename completion for both positional arguments and flag values, leaving +// anything that is explicitly configured (enum completers, MarkFlagFilename, +// MarkFlagDirname, ValidArgs, bool flags) untouched. +func disableFileCompletion(cmd *cobra.Command) { + if cmd.ValidArgsFunction == nil && len(cmd.ValidArgs) == 0 { + cmd.ValidArgsFunction = cobra.NoFileCompletions + } + + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Value.Type() == "bool" { + return + } + + if _, ok := cmd.GetFlagCompletionFunc(f.Name); ok { + return + } + + if _, ok := f.Annotations[cobra.BashCompFilenameExt]; ok { + return + } + + if _, ok := f.Annotations[cobra.BashCompSubdirsInDir]; ok { + return + } + + _ = cmd.RegisterFlagCompletionFunc(f.Name, cobra.NoFileCompletions) + }) + + for _, sub := range cmd.Commands() { + disableFileCompletion(sub) + } +} diff --git a/cli/cmds/policy_create.go b/cli/cmds/policy_create.go index 7d999d01..4bdbe9aa 100644 --- a/cli/cmds/policy_create.go +++ b/cli/cmds/policy_create.go @@ -50,6 +50,8 @@ func NewPolicyCreateCmd(appCtx *AppContext) *cobra.Command { cmd.Flags().StringSliceVar(&config.namespaces, "namespace", []string{}, "The namespaces where to bind the policy") cmd.Flags().BoolVar(&config.overwrite, "overwrite", false, "Overwrite namespace binding of existing policy") + mustRegisterFlagCompletion(cmd, "mode", completeClusterMode) + return cmd } diff --git a/cli/cmds/root.go b/cli/cmds/root.go index 6907bd4a..b2527d5c 100644 --- a/cli/cmds/root.go +++ b/cli/cmds/root.go @@ -70,12 +70,18 @@ func NewRootCmd() *cobra.Command { rootCmd.PersistentFlags().StringVar(&appCtx.Kubeconfig, "kubeconfig", "", "kubeconfig path ($HOME/.kube/config or $KUBECONFIG if set)") rootCmd.PersistentFlags().BoolVar(&appCtx.Debug, "debug", false, "Turn on debug logs") + if err := rootCmd.MarkPersistentFlagFilename("kubeconfig"); err != nil { + logrus.Fatal(err) + } + rootCmd.AddCommand( NewClusterCmd(appCtx), NewPolicyCmd(appCtx), NewKubeconfigCmd(appCtx), ) + disableFileCompletion(rootCmd) + return rootCmd }