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 }