github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/cmd/docker/docker.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 8 "github.com/Sirupsen/logrus" 9 "github.com/docker/docker/api/types/versions" 10 "github.com/docker/docker/cli" 11 "github.com/docker/docker/cli/command" 12 "github.com/docker/docker/cli/command/commands" 13 cliflags "github.com/docker/docker/cli/flags" 14 "github.com/docker/docker/cliconfig" 15 "github.com/docker/docker/dockerversion" 16 "github.com/docker/docker/pkg/term" 17 "github.com/docker/docker/utils" 18 "github.com/spf13/cobra" 19 "github.com/spf13/pflag" 20 ) 21 22 func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command { 23 fmt.Println("cmd/docker/docker.go newDockerCommand()") 24 opts := cliflags.NewClientOptions() 25 var flags *pflag.FlagSet 26 27 cmd := &cobra.Command{ 28 Use: "docker [OPTIONS] COMMAND [ARG...]", 29 Short: "A self-sufficient runtime for containers", 30 SilenceUsage: true, 31 SilenceErrors: true, 32 TraverseChildren: true, 33 Args: noArgs, 34 RunE: func(cmd *cobra.Command, args []string) error { 35 if opts.Version { 36 showVersion() 37 return nil 38 } 39 return dockerCli.ShowHelp(cmd, args) 40 }, 41 PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 42 // daemon command is special, we redirect directly to another binary 43 if cmd.Name() == "daemon" { 44 return nil 45 } 46 // flags must be the top-level command flags, not cmd.Flags() 47 opts.Common.SetDefaultOptions(flags) 48 dockerPreRun(opts) 49 if err := dockerCli.Initialize(opts); err != nil { 50 return err 51 } 52 return isSupported(cmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()) 53 }, 54 } 55 cli.SetupRootCommand(cmd) 56 57 cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) { 58 if dockerCli.Client() == nil { // when using --help, PersistenPreRun is not called, so initialization is needed. 59 // flags must be the top-level command flags, not cmd.Flags() 60 opts.Common.SetDefaultOptions(flags) 61 dockerPreRun(opts) 62 dockerCli.Initialize(opts) 63 } 64 65 if err := isSupported(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()); err != nil { 66 ccmd.Println(err) 67 return 68 } 69 70 hideUnsupportedFeatures(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental()) 71 72 if err := ccmd.Help(); err != nil { 73 ccmd.Println(err) 74 } 75 }) 76 77 flags = cmd.Flags() 78 flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit") 79 flags.StringVar(&opts.ConfigDir, "config", cliconfig.ConfigDir(), "Location of client config files") 80 opts.Common.InstallFlags(flags) 81 82 cmd.SetOutput(dockerCli.Out()) 83 cmd.AddCommand(newDaemonCommand()) 84 commands.AddCommands(cmd, dockerCli) 85 86 return cmd 87 } 88 89 func noArgs(cmd *cobra.Command, args []string) error { 90 if len(args) == 0 { 91 return nil 92 } 93 return fmt.Errorf( 94 "docker: '%s' is not a docker command.\nSee 'docker --help'", args[0]) 95 } 96 97 func main() { 98 fmt.Println("cmd/docker/docker.go main()") 99 // Set terminal emulation based on platform as required. 100 stdin, stdout, stderr := term.StdStreams() 101 logrus.SetOutput(stderr) 102 103 dockerCli := command.NewDockerCli(stdin, stdout, stderr) 104 cmd := newDockerCommand(dockerCli) 105 fmt.Println("cmd/docker/docker.go main() cmd : ", cmd) 106 107 if err := cmd.Execute(); err != nil { 108 if sterr, ok := err.(cli.StatusError); ok { 109 if sterr.Status != "" { 110 fmt.Fprintln(stderr, sterr.Status) 111 } 112 // StatusError should only be used for errors, and all errors should 113 // have a non-zero exit status, so never exit with 0 114 if sterr.StatusCode == 0 { 115 os.Exit(1) 116 } 117 os.Exit(sterr.StatusCode) 118 } 119 fmt.Fprintln(stderr, err) 120 os.Exit(1) 121 } 122 fmt.Println("cmd/docker/docker.go main() end") 123 } 124 125 func showVersion() { 126 fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit) 127 } 128 129 func dockerPreRun(opts *cliflags.ClientOptions) { 130 cliflags.SetLogLevel(opts.Common.LogLevel) 131 132 if opts.ConfigDir != "" { 133 cliconfig.SetConfigDir(opts.ConfigDir) 134 } 135 136 if opts.Common.Debug { 137 utils.EnableDebug() 138 } 139 } 140 141 func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperimental bool) { 142 cmd.Flags().VisitAll(func(f *pflag.Flag) { 143 // hide experimental flags 144 if !hasExperimental { 145 if _, ok := f.Annotations["experimental"]; ok { 146 f.Hidden = true 147 } 148 } 149 150 // hide flags not supported by the server 151 if flagVersion, ok := f.Annotations["version"]; ok && len(flagVersion) == 1 && versions.LessThan(clientVersion, flagVersion[0]) { 152 f.Hidden = true 153 } 154 155 }) 156 157 for _, subcmd := range cmd.Commands() { 158 // hide experimental subcommands 159 if !hasExperimental { 160 if _, ok := subcmd.Tags["experimental"]; ok { 161 subcmd.Hidden = true 162 } 163 } 164 165 // hide subcommands not supported by the server 166 if subcmdVersion, ok := subcmd.Tags["version"]; ok && versions.LessThan(clientVersion, subcmdVersion) { 167 subcmd.Hidden = true 168 } 169 } 170 } 171 172 func isSupported(cmd *cobra.Command, clientVersion string, hasExperimental bool) error { 173 if !hasExperimental { 174 if _, ok := cmd.Tags["experimental"]; ok { 175 return errors.New("only supported with experimental daemon") 176 } 177 } 178 179 if cmdVersion, ok := cmd.Tags["version"]; ok && versions.LessThan(clientVersion, cmdVersion) { 180 return fmt.Errorf("only supported with daemon version >= %s", cmdVersion) 181 } 182 183 return nil 184 }