docker.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "github.com/Sirupsen/logrus"
  6. "github.com/docker/docker/api/types/versions"
  7. "github.com/docker/docker/cli"
  8. "github.com/docker/docker/cli/command"
  9. "github.com/docker/docker/cli/command/commands"
  10. cliflags "github.com/docker/docker/cli/flags"
  11. "github.com/docker/docker/cliconfig"
  12. "github.com/docker/docker/dockerversion"
  13. "github.com/docker/docker/pkg/term"
  14. "github.com/docker/docker/utils"
  15. "github.com/spf13/cobra"
  16. "github.com/spf13/pflag"
  17. )
  18. func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command {
  19. opts := cliflags.NewClientOptions()
  20. var flags *pflag.FlagSet
  21. cmd := &cobra.Command{
  22. Use: "docker [OPTIONS] COMMAND [ARG...]",
  23. Short: "A self-sufficient runtime for containers",
  24. SilenceUsage: true,
  25. SilenceErrors: true,
  26. TraverseChildren: true,
  27. Args: noArgs,
  28. RunE: func(cmd *cobra.Command, args []string) error {
  29. if opts.Version {
  30. showVersion()
  31. return nil
  32. }
  33. cmd.SetOutput(dockerCli.Err())
  34. cmd.HelpFunc()(cmd, args)
  35. return nil
  36. },
  37. PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
  38. // flags must be the top-level command flags, not cmd.Flags()
  39. opts.Common.SetDefaultOptions(flags)
  40. dockerPreRun(opts)
  41. return dockerCli.Initialize(opts)
  42. },
  43. }
  44. cli.SetupRootCommand(cmd)
  45. cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
  46. if dockerCli.Client() == nil {
  47. // flags must be the top-level command flags, not cmd.Flags()
  48. opts.Common.SetDefaultOptions(flags)
  49. dockerPreRun(opts)
  50. dockerCli.Initialize(opts)
  51. }
  52. hideUnsupportedFeatures(ccmd, dockerCli.Client().ClientVersion(), dockerCli.HasExperimental())
  53. if err := ccmd.Help(); err != nil {
  54. ccmd.Println(err)
  55. }
  56. })
  57. flags = cmd.Flags()
  58. flags.BoolVarP(&opts.Version, "version", "v", false, "Print version information and quit")
  59. flags.StringVar(&opts.ConfigDir, "config", cliconfig.ConfigDir(), "Location of client config files")
  60. opts.Common.InstallFlags(flags)
  61. cmd.SetOutput(dockerCli.Out())
  62. cmd.AddCommand(newDaemonCommand())
  63. commands.AddCommands(cmd, dockerCli)
  64. return cmd
  65. }
  66. func noArgs(cmd *cobra.Command, args []string) error {
  67. if len(args) == 0 {
  68. return nil
  69. }
  70. return fmt.Errorf(
  71. "docker: '%s' is not a docker command.\nSee 'docker --help'.", args[0])
  72. }
  73. func main() {
  74. // Set terminal emulation based on platform as required.
  75. stdin, stdout, stderr := term.StdStreams()
  76. logrus.SetOutput(stderr)
  77. dockerCli := command.NewDockerCli(stdin, stdout, stderr)
  78. cmd := newDockerCommand(dockerCli)
  79. if err := cmd.Execute(); err != nil {
  80. if sterr, ok := err.(cli.StatusError); ok {
  81. if sterr.Status != "" {
  82. fmt.Fprintln(stderr, sterr.Status)
  83. }
  84. // StatusError should only be used for errors, and all errors should
  85. // have a non-zero exit status, so never exit with 0
  86. if sterr.StatusCode == 0 {
  87. os.Exit(1)
  88. }
  89. os.Exit(sterr.StatusCode)
  90. }
  91. fmt.Fprintln(stderr, err)
  92. os.Exit(1)
  93. }
  94. }
  95. func showVersion() {
  96. fmt.Printf("Docker version %s, build %s\n", dockerversion.Version, dockerversion.GitCommit)
  97. }
  98. func dockerPreRun(opts *cliflags.ClientOptions) {
  99. cliflags.SetLogLevel(opts.Common.LogLevel)
  100. if opts.ConfigDir != "" {
  101. cliconfig.SetConfigDir(opts.ConfigDir)
  102. }
  103. if opts.Common.Debug {
  104. utils.EnableDebug()
  105. }
  106. }
  107. func hideUnsupportedFeatures(cmd *cobra.Command, clientVersion string, hasExperimental bool) {
  108. cmd.Flags().VisitAll(func(f *pflag.Flag) {
  109. // hide experimental flags
  110. if !hasExperimental {
  111. if _, ok := f.Annotations["experimental"]; ok {
  112. f.Hidden = true
  113. }
  114. }
  115. // hide flags not supported by the server
  116. if flagVersion, ok := f.Annotations["version"]; ok && len(flagVersion) == 1 && versions.LessThan(clientVersion, flagVersion[0]) {
  117. f.Hidden = true
  118. }
  119. })
  120. for _, subcmd := range cmd.Commands() {
  121. // hide experimental subcommands
  122. if !hasExperimental {
  123. if _, ok := subcmd.Tags["experimental"]; ok {
  124. subcmd.Hidden = true
  125. }
  126. }
  127. // hide subcommands not supported by the server
  128. if subcmdVersion, ok := subcmd.Tags["version"]; ok && versions.LessThan(clientVersion, subcmdVersion) {
  129. subcmd.Hidden = true
  130. }
  131. }
  132. }