github.com/docker/app@v0.9.1-beta3.0.20210611140623-a48f773ab002/internal/commands/root.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  
     8  	"github.com/deislabs/cnab-go/claim"
     9  	"github.com/docker/app/internal"
    10  	"github.com/docker/app/internal/cliopts"
    11  	"github.com/docker/app/internal/commands/build"
    12  	"github.com/docker/app/internal/commands/image"
    13  	"github.com/docker/app/internal/store"
    14  	appstore "github.com/docker/app/internal/store"
    15  	"github.com/docker/cli/cli/command"
    16  	"github.com/docker/cli/cli/config"
    17  	"github.com/spf13/cobra"
    18  	"github.com/spf13/pflag"
    19  )
    20  
    21  type mainOptions struct {
    22  	cliopts.InstallerContextOptions
    23  	showVersion bool
    24  }
    25  
    26  // NewRootCmd returns the base root command.
    27  func NewRootCmd(use string, dockerCli command.Cli) *cobra.Command {
    28  	var opts mainOptions
    29  	cmd := &cobra.Command{
    30  		Short:       "Docker App",
    31  		Long:        `A tool to build, share and run a Docker App`,
    32  		Use:         use,
    33  		Annotations: map[string]string{"experimentalCLI": "true"},
    34  		RunE: func(cmd *cobra.Command, args []string) error {
    35  			if opts.showVersion {
    36  				fmt.Fprintln(os.Stdout, internal.FullVersion()) //nolint:errcheck
    37  				return nil
    38  			}
    39  
    40  			if len(args) != 0 {
    41  				return fmt.Errorf("%q is not a docker app command\nSee 'docker app --help'", args[0])
    42  			}
    43  			cmd.HelpFunc()(cmd, args)
    44  			return nil
    45  		},
    46  	}
    47  	addCommands(cmd, dockerCli, &opts.InstallerContextOptions)
    48  
    49  	cmd.Flags().BoolVar(&opts.showVersion, "version", false, "Print version information")
    50  	opts.InstallerContextOptions.AddFlags(cmd.Flags())
    51  
    52  	return cmd
    53  }
    54  
    55  func addCommands(cmd *cobra.Command, dockerCli command.Cli, installerContext *cliopts.InstallerContextOptions) {
    56  	cmd.AddCommand(
    57  		runCmd(dockerCli, installerContext),
    58  		updateCmd(dockerCli, installerContext),
    59  		removeCmd(dockerCli, installerContext),
    60  		listCmd(dockerCli, installerContext),
    61  		initCmd(dockerCli),
    62  		validateCmd(),
    63  		pushCmd(dockerCli),
    64  		pullCmd(dockerCli),
    65  		image.Cmd(dockerCli, installerContext),
    66  		build.Cmd(dockerCli),
    67  		inspectCmd(dockerCli, installerContext),
    68  	)
    69  
    70  	if !dockerCli.ClientInfo().HasExperimental {
    71  		removeExperimentalCmdsAndFlags(cmd)
    72  	}
    73  }
    74  
    75  func removeExperimentalCmdsAndFlags(cmd *cobra.Command) {
    76  	enabledFlags := []*pflag.Flag{}
    77  	cmd.Flags().VisitAll(func(f *pflag.Flag) {
    78  		if _, disabled := f.Annotations["experimentalCLI"]; !disabled {
    79  			enabledFlags = append(enabledFlags, f)
    80  		}
    81  	})
    82  
    83  	if len(enabledFlags) != cmd.Flags().NFlag() {
    84  		cmd.ResetFlags()
    85  		for _, f := range enabledFlags {
    86  			cmd.Flags().AddFlag(f)
    87  		}
    88  	}
    89  
    90  	for _, subcmd := range cmd.Commands() {
    91  		if _, ok := subcmd.Annotations["experimentalCLI"]; ok {
    92  			cmd.RemoveCommand(subcmd)
    93  		} else {
    94  			removeExperimentalCmdsAndFlags(subcmd)
    95  		}
    96  	}
    97  }
    98  
    99  func muteDockerCli(dockerCli command.Cli) func() {
   100  	stdout := dockerCli.Out()
   101  	stderr := dockerCli.Err()
   102  	dockerCli.Apply(command.WithCombinedStreams(ioutil.Discard)) //nolint:errcheck // WithCombinedStreams cannot error
   103  	return func() {
   104  		dockerCli.Apply(command.WithOutputStream(stdout), command.WithErrorStream(stderr)) //nolint:errcheck // as above
   105  	}
   106  }
   107  
   108  func prepareStores(targetContext string) (store.ImageStore, store.InstallationStore, store.CredentialStore, error) {
   109  	appstore, err := store.NewApplicationStore(config.Dir())
   110  	if err != nil {
   111  		return nil, nil, nil, err
   112  	}
   113  	installationStore, err := appstore.InstallationStore(targetContext)
   114  	if err != nil {
   115  		return nil, nil, nil, err
   116  	}
   117  	imageStore, err := appstore.ImageStore()
   118  	if err != nil {
   119  		return nil, nil, nil, err
   120  	}
   121  	credentialStore, err := appstore.CredentialStore(targetContext)
   122  	if err != nil {
   123  		return nil, nil, nil, err
   124  	}
   125  	return imageStore, installationStore, credentialStore, nil
   126  }
   127  
   128  func prepareImageStore() (store.ImageStore, error) {
   129  	appstore, err := store.NewApplicationStore(config.Dir())
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	imageStore, err := appstore.ImageStore()
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	return imageStore, nil
   138  }
   139  
   140  type credentialOptions struct {
   141  	credentialsets   []string
   142  	credentials      []string
   143  	sendRegistryAuth bool
   144  }
   145  
   146  func (o *credentialOptions) addFlags(flags *pflag.FlagSet) {
   147  	flags.StringArrayVar(&o.credentialsets, "credential-set", []string{}, "Use a YAML file containing a credential set or a credential set present in the credential store")
   148  	flags.StringArrayVar(&o.credentials, "credential", nil, "Add a single credential, additive ontop of any --credential-set used")
   149  	flags.BoolVar(&o.sendRegistryAuth, "with-registry-auth", false, "Sends registry auth")
   150  }
   151  
   152  func (o *credentialOptions) CredentialSetOpts(dockerCli command.Cli, credentialStore store.CredentialStore) []credentialSetOpt {
   153  	return []credentialSetOpt{
   154  		addNamedCredentialSets(credentialStore, o.credentialsets),
   155  		addCredentials(o.credentials),
   156  		addDockerCredentials(dockerCli.CurrentContext(), dockerCli.ContextStore()),
   157  		addRegistryCredentials(o.sendRegistryAuth, dockerCli),
   158  	}
   159  }
   160  
   161  func IsInstallationFailed(installation *appstore.Installation) bool {
   162  	return installation.Result.Action == claim.ActionInstall &&
   163  		installation.Result.Status == claim.StatusFailure
   164  }