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  }