github.com/justincormack/cli@v0.0.0-20201215022714-831ebeae9675/cli/command/stack/cmd.go (about) 1 package stack 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "github.com/docker/cli/cli" 9 "github.com/docker/cli/cli/command" 10 "github.com/spf13/cobra" 11 "github.com/spf13/pflag" 12 ) 13 14 var errUnsupportedAllOrchestrator = fmt.Errorf(`no orchestrator specified: use either "kubernetes" or "swarm"`) 15 16 type commonOptions struct { 17 orchestrator command.Orchestrator 18 } 19 20 func (o *commonOptions) Orchestrator() command.Orchestrator { 21 if o == nil { 22 return command.OrchestratorSwarm 23 } 24 return o.orchestrator 25 } 26 27 // NewStackCommand returns a cobra command for `stack` subcommands 28 func NewStackCommand(dockerCli command.Cli) *cobra.Command { 29 var opts commonOptions 30 cmd := &cobra.Command{ 31 Use: "stack [OPTIONS]", 32 Short: "Manage Docker stacks", 33 Args: cli.NoArgs, 34 PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 35 orchestrator, err := getOrchestrator(dockerCli, cmd) 36 if err != nil { 37 return err 38 } 39 opts.orchestrator = orchestrator 40 hideOrchestrationFlags(cmd, orchestrator) 41 return checkSupportedFlag(cmd, orchestrator) 42 }, 43 44 RunE: command.ShowHelp(dockerCli.Err()), 45 Annotations: map[string]string{ 46 "version": "1.25", 47 }, 48 } 49 defaultHelpFunc := cmd.HelpFunc() 50 cmd.SetHelpFunc(func(c *cobra.Command, args []string) { 51 if err := cmd.Root().PersistentPreRunE(c, args); err != nil { 52 fmt.Fprintln(dockerCli.Err(), err) 53 return 54 } 55 if err := cmd.PersistentPreRunE(c, args); err != nil { 56 fmt.Fprintln(dockerCli.Err(), err) 57 return 58 } 59 hideOrchestrationFlags(c, opts.orchestrator) 60 defaultHelpFunc(c, args) 61 }) 62 cmd.AddCommand( 63 newDeployCommand(dockerCli, &opts), 64 newListCommand(dockerCli, &opts), 65 newPsCommand(dockerCli, &opts), 66 newRemoveCommand(dockerCli, &opts), 67 newServicesCommand(dockerCli, &opts), 68 ) 69 flags := cmd.PersistentFlags() 70 flags.String("kubeconfig", "", "Kubernetes config file") 71 flags.SetAnnotation("kubeconfig", "kubernetes", nil) 72 flags.String("orchestrator", "", "Orchestrator to use (swarm|kubernetes|all)") 73 return cmd 74 } 75 76 func getOrchestrator(dockerCli command.Cli, cmd *cobra.Command) (command.Orchestrator, error) { 77 var orchestratorFlag string 78 if o, err := cmd.Flags().GetString("orchestrator"); err == nil { 79 orchestratorFlag = o 80 } 81 return dockerCli.StackOrchestrator(orchestratorFlag) 82 } 83 84 func hideOrchestrationFlags(cmd *cobra.Command, orchestrator command.Orchestrator) { 85 cmd.Flags().VisitAll(func(f *pflag.Flag) { 86 if _, ok := f.Annotations["kubernetes"]; ok && !orchestrator.HasKubernetes() { 87 f.Hidden = true 88 } 89 if _, ok := f.Annotations["swarm"]; ok && !orchestrator.HasSwarm() { 90 f.Hidden = true 91 } 92 }) 93 for _, subcmd := range cmd.Commands() { 94 hideOrchestrationFlags(subcmd, orchestrator) 95 } 96 } 97 98 func checkSupportedFlag(cmd *cobra.Command, orchestrator command.Orchestrator) error { 99 errs := []string{} 100 cmd.Flags().VisitAll(func(f *pflag.Flag) { 101 if !f.Changed { 102 return 103 } 104 if _, ok := f.Annotations["kubernetes"]; ok && !orchestrator.HasKubernetes() { 105 errs = append(errs, fmt.Sprintf(`"--%s" is only supported on a Docker cli with kubernetes features enabled`, f.Name)) 106 } 107 if _, ok := f.Annotations["swarm"]; ok && !orchestrator.HasSwarm() { 108 errs = append(errs, fmt.Sprintf(`"--%s" is only supported on a Docker cli with swarm features enabled`, f.Name)) 109 } 110 }) 111 for _, subcmd := range cmd.Commands() { 112 if err := checkSupportedFlag(subcmd, orchestrator); err != nil { 113 errs = append(errs, err.Error()) 114 } 115 } 116 if len(errs) > 0 { 117 return errors.New(strings.Join(errs, "\n")) 118 } 119 return nil 120 }