version.go 2.9 KB

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