version.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package system
  2. import (
  3. "fmt"
  4. "runtime"
  5. "time"
  6. "golang.org/x/net/context"
  7. "github.com/docker/docker/api/types"
  8. "github.com/docker/docker/cli"
  9. "github.com/docker/docker/cli/command"
  10. "github.com/docker/docker/dockerversion"
  11. "github.com/docker/docker/utils/templates"
  12. "github.com/spf13/cobra"
  13. )
  14. var versionTemplate = `Client:
  15. Version: {{.Client.Version}}
  16. API version: {{.Client.APIVersion}}
  17. Go version: {{.Client.GoVersion}}
  18. Git commit: {{.Client.GitCommit}}
  19. Built: {{.Client.BuildTime}}
  20. OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .ServerOK}}
  21. Server:
  22. Version: {{.Server.Version}}
  23. API version: {{.Server.APIVersion}} (minimum version {{.Server.MinAPIVersion}})
  24. Go version: {{.Server.GoVersion}}
  25. Git commit: {{.Server.GitCommit}}
  26. Built: {{.Server.BuildTime}}
  27. OS/Arch: {{.Server.Os}}/{{.Server.Arch}}
  28. Experimental: {{.Server.Experimental}}{{end}}`
  29. type versionOptions struct {
  30. format string
  31. }
  32. // NewVersionCommand creates a new cobra.Command for `docker version`
  33. func NewVersionCommand(dockerCli *command.DockerCli) *cobra.Command {
  34. var opts versionOptions
  35. cmd := &cobra.Command{
  36. Use: "version [OPTIONS]",
  37. Short: "Show the Docker version information",
  38. Args: cli.NoArgs,
  39. RunE: func(cmd *cobra.Command, args []string) error {
  40. return runVersion(dockerCli, &opts)
  41. },
  42. }
  43. flags := cmd.Flags()
  44. flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
  45. return cmd
  46. }
  47. func runVersion(dockerCli *command.DockerCli, opts *versionOptions) error {
  48. ctx := context.Background()
  49. templateFormat := versionTemplate
  50. if opts.format != "" {
  51. templateFormat = opts.format
  52. }
  53. tmpl, err := templates.Parse(templateFormat)
  54. if err != nil {
  55. return cli.StatusError{StatusCode: 64,
  56. Status: "Template parsing error: " + err.Error()}
  57. }
  58. APIVersion := dockerCli.Client().ClientVersion()
  59. if defaultAPIVersion := dockerCli.DefaultVersion(); APIVersion != defaultAPIVersion {
  60. APIVersion = fmt.Sprintf("%s (downgraded from %s)", APIVersion, defaultAPIVersion)
  61. }
  62. vd := types.VersionResponse{
  63. Client: &types.Version{
  64. Version: dockerversion.Version,
  65. APIVersion: APIVersion,
  66. GoVersion: runtime.Version(),
  67. GitCommit: dockerversion.GitCommit,
  68. BuildTime: dockerversion.BuildTime,
  69. Os: runtime.GOOS,
  70. Arch: runtime.GOARCH,
  71. },
  72. }
  73. serverVersion, err := dockerCli.Client().ServerVersion(ctx)
  74. if err == nil {
  75. vd.Server = &serverVersion
  76. }
  77. // first we need to make BuildTime more human friendly
  78. t, errTime := time.Parse(time.RFC3339Nano, vd.Client.BuildTime)
  79. if errTime == nil {
  80. vd.Client.BuildTime = t.Format(time.ANSIC)
  81. }
  82. if vd.ServerOK() {
  83. t, errTime = time.Parse(time.RFC3339Nano, vd.Server.BuildTime)
  84. if errTime == nil {
  85. vd.Server.BuildTime = t.Format(time.ANSIC)
  86. }
  87. }
  88. if err2 := tmpl.Execute(dockerCli.Out(), vd); err2 != nil && err == nil {
  89. err = err2
  90. }
  91. dockerCli.Out().Write([]byte{'\n'})
  92. return err
  93. }