version.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package system
  2. import (
  3. "runtime"
  4. "time"
  5. "golang.org/x/net/context"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/cli"
  8. "github.com/docker/docker/cli/command"
  9. "github.com/docker/docker/dockerversion"
  10. "github.com/docker/docker/utils/templates"
  11. "github.com/spf13/cobra"
  12. )
  13. var versionTemplate = `Client:
  14. Version: {{.Client.Version}}
  15. API version: {{.Client.APIVersion}}
  16. Go version: {{.Client.GoVersion}}
  17. Git commit: {{.Client.GitCommit}}
  18. Built: {{.Client.BuildTime}}
  19. OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .ServerOK}}
  20. Server:
  21. Version: {{.Server.Version}}
  22. API version: {{.Server.APIVersion}}
  23. Minimum API 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. vd := types.VersionResponse{
  59. Client: &types.Version{
  60. Version: dockerversion.Version,
  61. APIVersion: dockerCli.Client().ClientVersion(),
  62. GoVersion: runtime.Version(),
  63. GitCommit: dockerversion.GitCommit,
  64. BuildTime: dockerversion.BuildTime,
  65. Os: runtime.GOOS,
  66. Arch: runtime.GOARCH,
  67. },
  68. }
  69. serverVersion, err := dockerCli.Client().ServerVersion(ctx)
  70. if err == nil {
  71. vd.Server = &serverVersion
  72. }
  73. // first we need to make BuildTime more human friendly
  74. t, errTime := time.Parse(time.RFC3339Nano, vd.Client.BuildTime)
  75. if errTime == nil {
  76. vd.Client.BuildTime = t.Format(time.ANSIC)
  77. }
  78. if vd.ServerOK() {
  79. t, errTime = time.Parse(time.RFC3339Nano, vd.Server.BuildTime)
  80. if errTime == nil {
  81. vd.Server.BuildTime = t.Format(time.ANSIC)
  82. }
  83. }
  84. if err2 := tmpl.Execute(dockerCli.Out(), vd); err2 != nil && err == nil {
  85. err = err2
  86. }
  87. dockerCli.Out().Write([]byte{'\n'})
  88. return err
  89. }