diff --git a/cli/command/system/testdata/TestVersionFormat/json.golden b/cli/command/system/testdata/TestVersionFormat/json.golden index 3d3de4a37..5cc9fd2ed 100644 --- a/cli/command/system/testdata/TestVersionFormat/json.golden +++ b/cli/command/system/testdata/TestVersionFormat/json.golden @@ -1 +1 @@ -{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Version":"","APIVersion":"","MinAPIVersion":"","Os":"","Arch":"","Experimental":false,"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}]}} +{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Version":"18.99.5-ce","ApiVersion":"1.30","MinAPIVersion":"1.12","Os":"linux","Arch":"amd64","Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"GitCommit":"64ddfa6","GoVersion":"go1.8.7","KernelVersion":"v1.0.0","BuildTime":"Mon Jul 9 23:38:38 2018"}} diff --git a/cli/command/system/testdata/TestVersionFormat/json_template.golden b/cli/command/system/testdata/TestVersionFormat/json_template.golden index 3d3de4a37..5cc9fd2ed 100644 --- a/cli/command/system/testdata/TestVersionFormat/json_template.golden +++ b/cli/command/system/testdata/TestVersionFormat/json_template.golden @@ -1 +1 @@ -{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Version":"","APIVersion":"","MinAPIVersion":"","Os":"","Arch":"","Experimental":false,"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}]}} +{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Version":"18.99.5-ce","ApiVersion":"1.30","MinAPIVersion":"1.12","Os":"linux","Arch":"amd64","Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"GitCommit":"64ddfa6","GoVersion":"go1.8.7","KernelVersion":"v1.0.0","BuildTime":"Mon Jul 9 23:38:38 2018"}} diff --git a/cli/command/system/version.go b/cli/command/system/version.go index 6d89885bf..1dda9489a 100644 --- a/cli/command/system/version.go +++ b/cli/command/system/version.go @@ -6,6 +6,7 @@ import ( "io" "runtime" "sort" + "strconv" "text/template" "time" @@ -63,7 +64,7 @@ type versionOptions struct { // versionInfo contains version information of both the Client, and Server type versionInfo struct { Client clientVersion - Server *client.ServerVersionResult + Server *serverVersion } type platformInfo struct { @@ -83,6 +84,26 @@ type clientVersion struct { Context string `json:"Context"` } +// serverVersion contains information about the Docker server host. +// it's the client-side presentation of [client.ServerVersionResult]. +type serverVersion struct { + Platform client.PlatformInfo `json:",omitempty"` // Platform is the platform (product name) the server is running on. + Version string `json:"Version"` // Version is the version of the daemon. + APIVersion string `json:"ApiVersion"` // APIVersion is the highest API version supported by the server. + MinAPIVersion string `json:"MinAPIVersion,omitempty"` // MinAPIVersion is the minimum API version the server supports. + Os string `json:"Os"` // Os is the operating system the server runs on. + Arch string `json:"Arch"` // Arch is the hardware architecture the server runs on. + Components []system.ComponentVersion `json:"Components,omitempty"` // Components contains version information for the components making up the server. + + // The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility + + GitCommit string `json:"GitCommit,omitempty"` + GoVersion string `json:"GoVersion,omitempty"` + KernelVersion string `json:"KernelVersion,omitempty"` + Experimental bool `json:"Experimental,omitempty"` + BuildTime string `json:"BuildTime,omitempty"` +} + // newClientVersion constructs a new clientVersion. If a dockerCLI is // passed as argument, additional information is included (API version), // which may invoke an API connection. Pass nil to omit the additional @@ -107,6 +128,47 @@ func newClientVersion(contextName string, dockerCli command.Cli) clientVersion { return v } +func newServerVersion(sv client.ServerVersionResult) *serverVersion { + out := &serverVersion{ + Platform: sv.Platform, + Version: sv.Version, + APIVersion: sv.APIVersion, + MinAPIVersion: sv.MinAPIVersion, + Os: sv.Os, + Arch: sv.Arch, + Experimental: sv.Experimental, //nolint:staticcheck // ignore deprecated field. + } + foundEngine := false + for _, component := range sv.Components { + if component.Name == "Engine" { + foundEngine = true + buildTime, ok := component.Details["BuildTime"] + if ok { + component.Details["BuildTime"] = reformatDate(buildTime) + } + out.GitCommit = component.Details["GitCommit"] + out.GoVersion = component.Details["GoVersion"] + out.KernelVersion = component.Details["KernelVersion"] + out.Experimental = func() bool { b, _ := strconv.ParseBool(component.Details["Experimental"]); return b }() + out.BuildTime = reformatDate(component.Details["BuildTime"]) + } + } + + if !foundEngine { + out.Components = append(out.Components, system.ComponentVersion{ + Name: "Engine", + Version: sv.Version, + Details: map[string]string{ + "ApiVersion": sv.APIVersion, + "MinAPIVersion": sv.MinAPIVersion, + "Os": sv.Os, + "Arch": sv.Arch, + }, + }) + } + return out +} + // newVersionCommand creates a new cobra.Command for `docker version` func newVersionCommand(dockerCLI command.Cli) *cobra.Command { var opts versionOptions @@ -138,14 +200,14 @@ func reformatDate(buildTime string) string { } func arch() string { - arch := runtime.GOARCH + out := runtime.GOARCH if rosetta.Enabled() { - arch += " (rosetta)" + out += " (rosetta)" } - return arch + return out } -func runVersion(ctx context.Context, dockerCli command.Cli, opts *versionOptions) error { +func runVersion(ctx context.Context, dockerCLI command.Cli, opts *versionOptions) error { var err error tmpl, err := newVersionTemplate(opts.format) if err != nil { @@ -153,36 +215,13 @@ func runVersion(ctx context.Context, dockerCli command.Cli, opts *versionOptions } vd := versionInfo{ - Client: newClientVersion(dockerCli.CurrentContext(), dockerCli), + Client: newClientVersion(dockerCLI.CurrentContext(), dockerCLI), } - sv, err := dockerCli.Client().ServerVersion(ctx, client.ServerVersionOptions{}) + sv, err := dockerCLI.Client().ServerVersion(ctx, client.ServerVersionOptions{}) if err == nil { - vd.Server = &sv - foundEngine := false - for _, component := range sv.Components { - if component.Name == "Engine" { - foundEngine = true - buildTime, ok := component.Details["BuildTime"] - if ok { - component.Details["BuildTime"] = reformatDate(buildTime) - } - } - } - - if !foundEngine { - vd.Server.Components = append(vd.Server.Components, system.ComponentVersion{ - Name: "Engine", - Version: sv.Version, - Details: map[string]string{ - "ApiVersion": sv.APIVersion, - "MinAPIVersion": sv.MinAPIVersion, - "Os": sv.Os, - "Arch": sv.Arch, - }, - }) - } + vd.Server = newServerVersion(sv) } - if err2 := prettyPrintVersion(dockerCli.Out(), vd, tmpl); err2 != nil && err == nil { + if err2 := prettyPrintVersion(dockerCLI.Out(), vd, tmpl); err2 != nil && err == nil { err = err2 } return err diff --git a/cli/command/system/version_test.go b/cli/command/system/version_test.go index eeb60cc29..e1fcefdc6 100644 --- a/cli/command/system/version_test.go +++ b/cli/command/system/version_test.go @@ -47,8 +47,18 @@ func TestVersionFormat(t *testing.T) { BuildTime: "Wed May 30 22:21:05 2018", Context: "my-context", }, - Server: &client.ServerVersionResult{ - Platform: client.PlatformInfo{Name: "Docker Enterprise Edition (EE) 2.0"}, + Server: &serverVersion{ + Platform: client.PlatformInfo{Name: "Docker Enterprise Edition (EE) 2.0"}, + Version: "18.99.5-ce", + APIVersion: "1.30", + MinAPIVersion: "1.12", + Os: "linux", + Arch: "amd64", + GitCommit: "64ddfa6", + GoVersion: "go1.8.7", + KernelVersion: "v1.0.0", + Experimental: false, + BuildTime: "Mon Jul 9 23:38:38 2018", Components: []system.ComponentVersion{ { Name: "Engine",