diff --git a/cmd/kubectl-moco/cmd/completion.go b/cmd/kubectl-moco/cmd/completion.go new file mode 100644 index 000000000..3defa93e5 --- /dev/null +++ b/cmd/kubectl-moco/cmd/completion.go @@ -0,0 +1,49 @@ +package cmd + +import ( + "context" + "strings" + + mocov1beta2 "github.com/cybozu-go/moco/api/v1beta2" + "github.com/spf13/cobra" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func mysqlClusterCandidates(ctx context.Context, cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) != 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + + var namespace string + + if cmd.Flags().Changed("namespace") { + ns, err := cmd.Flags().GetString("namespace") + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + namespace = ns + } else { + ns, _, err := kubeConfigFlags.ToRawKubeConfigLoader().Namespace() + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + namespace = ns + } + + clusters := &mocov1beta2.MySQLClusterList{} + if err := kubeClient.List(ctx, clusters, &client.ListOptions{ + Namespace: namespace, + }); err != nil { + return nil, cobra.ShellCompDirectiveError + } + + var candidates []string + for _, c := range clusters.Items { + if !strings.HasPrefix(c.Name, toComplete) { + continue + } + candidates = append(candidates, c.Name) + } + + return candidates, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/kubectl-moco/cmd/credential.go b/cmd/kubectl-moco/cmd/credential.go index 0c56e155f..ffc43734a 100644 --- a/cmd/kubectl-moco/cmd/credential.go +++ b/cmd/kubectl-moco/cmd/credential.go @@ -21,6 +21,9 @@ var credentialCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { return fetchCredential(cmd.Context(), args[0]) }, + ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return mysqlClusterCandidates(cmd.Context(), cmd, args, toComplete) + }, } func fetchCredential(ctx context.Context, clusterName string) error { @@ -47,5 +50,12 @@ func init() { fs.StringVarP(&credentialConfig.user, "mysql-user", "u", "moco-readonly", "User for login to mysql") fs.StringVar(&credentialConfig.format, "format", "plain", "The format of output [`plain` or `mycnf`]") + _ = credentialCmd.RegisterFlagCompletionFunc("mysql-user", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"moco-readonly", "moco-writable", "moco-admin"}, cobra.ShellCompDirectiveDefault + }) + _ = credentialCmd.RegisterFlagCompletionFunc("format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"plain", "mycnf"}, cobra.ShellCompDirectiveDefault + }) + rootCmd.AddCommand(credentialCmd) } diff --git a/cmd/kubectl-moco/cmd/mysql.go b/cmd/kubectl-moco/cmd/mysql.go index 44f707182..19e323ed6 100644 --- a/cmd/kubectl-moco/cmd/mysql.go +++ b/cmd/kubectl-moco/cmd/mysql.go @@ -36,6 +36,9 @@ var mysqlCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { return runMySQLCommand(cmd.Context(), args[0], cmd, args[1:]) }, + ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return mysqlClusterCandidates(cmd.Context(), cmd, args, toComplete) + }, } func runMySQLCommand(ctx context.Context, clusterName string, cmd *cobra.Command, args []string) error { diff --git a/cmd/kubectl-moco/cmd/switchover.go b/cmd/kubectl-moco/cmd/switchover.go index b0f175488..49bed93eb 100644 --- a/cmd/kubectl-moco/cmd/switchover.go +++ b/cmd/kubectl-moco/cmd/switchover.go @@ -19,6 +19,9 @@ var switchoverCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { return switchover(cmd.Context(), args[0]) }, + ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return mysqlClusterCandidates(cmd.Context(), cmd, args, toComplete) + }, } func switchover(ctx context.Context, name string) error {