Skip to content

Commit d3b615a

Browse files
committed
docker info: include Client Version and "platform name"
This patch adds additional information to the Client section of the output. We were already outputting versions of CLI Plugins, and the Server, but not for the Client. Adding this information can help with bug-reports where the reporter only provided the `docker info` output, or (e.g.) only `docker --version`. The platform name helps identify what kind of builds the user has installed (e.g. docker's docker-ce packages have "Docker Engine - Community" set for this), although we should consider including "packager" information as a more formalized field for this information. Before this patch: $ docker info Client: Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc.) Version: v0.10.4 Path: /usr/libexec/docker/cli-plugins/docker-buildx ... With this patch applied: $ docker info Client: Docker Engine - Community Version: 24.0.0-dev Context: default Debug Mode: false Plugins: buildx: Docker Buildx (Docker Inc.) Version: v0.10.4 Path: /usr/libexec/docker/cli-plugins/docker-buildx ... Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 8a3aa0e commit d3b615a

File tree

8 files changed

+58
-24
lines changed

8 files changed

+58
-24
lines changed

cli/command/system/info.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ type infoOptions struct {
2828
}
2929

3030
type clientInfo struct {
31-
Debug bool
32-
Context string
31+
Debug bool
32+
clientVersion
3333
Plugins []pluginmanager.Plugin
3434
Warnings []string
3535
}
@@ -46,6 +46,13 @@ type info struct {
4646
ClientErrors []string `json:",omitempty"`
4747
}
4848

49+
func (i *info) clientPlatform() string {
50+
if i.ClientInfo != nil && i.ClientInfo.Platform != nil {
51+
return i.ClientInfo.Platform.Name
52+
}
53+
return ""
54+
}
55+
4956
// NewInfoCommand creates a new cobra.Command for `docker info`
5057
func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
5158
var opts infoOptions
@@ -71,8 +78,11 @@ func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
7178
func runInfo(cmd *cobra.Command, dockerCli command.Cli, opts *infoOptions) error {
7279
info := info{
7380
ClientInfo: &clientInfo{
74-
Context: dockerCli.CurrentContext(),
75-
Debug: debug.IsEnabled(),
81+
// Don't pass a dockerCLI to newClientVersion(), because we currently
82+
// don't include negotiated API version, and want to avoid making an
83+
// API connection when only printing the Client section.
84+
clientVersion: newClientVersion(dockerCli.CurrentContext(), nil),
85+
Debug: debug.IsEnabled(),
7686
},
7787
Info: &types.Info{},
7888
}
@@ -147,7 +157,12 @@ func needsServerInfo(template string, info info) bool {
147157
}
148158

149159
func prettyPrintInfo(dockerCli command.Cli, info info) error {
150-
fmt.Fprintln(dockerCli.Out(), "Client:")
160+
// Only append the platform info if it's not empty, to prevent printing a trailing space.
161+
if p := info.clientPlatform(); p != "" {
162+
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:", p)
163+
} else {
164+
_, _ = fmt.Fprintln(dockerCli.Out(), "Client:")
165+
}
151166
if info.ClientInfo != nil {
152167
prettyPrintClientInfo(dockerCli, *info.ClientInfo)
153168
}
@@ -173,6 +188,7 @@ func prettyPrintInfo(dockerCli command.Cli, info info) error {
173188
}
174189

175190
func prettyPrintClientInfo(dockerCli command.Cli, info clientInfo) {
191+
fprintlnNonEmpty(dockerCli.Out(), " Version: ", info.Version)
176192
fmt.Fprintln(dockerCli.Out(), " Context: ", info.Context)
177193
fmt.Fprintln(dockerCli.Out(), " Debug Mode:", info.Debug)
178194

cli/command/system/info_test.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,12 @@ func TestPrettyPrintInfo(t *testing.T) {
278278
dockerInfo: info{
279279
Info: &sampleInfoNoSwarm,
280280
ClientInfo: &clientInfo{
281-
Context: "default",
282-
Debug: true,
281+
clientVersion: clientVersion{
282+
Platform: &platformInfo{Name: "Docker Engine - Community"},
283+
Version: "24.0.0",
284+
Context: "default",
285+
},
286+
Debug: true,
283287
},
284288
},
285289
prettyGolden: "docker-info-no-swarm",
@@ -290,8 +294,8 @@ func TestPrettyPrintInfo(t *testing.T) {
290294
dockerInfo: info{
291295
Info: &sampleInfoNoSwarm,
292296
ClientInfo: &clientInfo{
293-
Context: "default",
294-
Plugins: samplePluginsInfo,
297+
clientVersion: clientVersion{Context: "default"},
298+
Plugins: samplePluginsInfo,
295299
},
296300
},
297301
prettyGolden: "docker-info-plugins",
@@ -302,15 +306,15 @@ func TestPrettyPrintInfo(t *testing.T) {
302306
doc: "info with nil labels",
303307
dockerInfo: info{
304308
Info: &sampleInfoLabelsNil,
305-
ClientInfo: &clientInfo{Context: "default"},
309+
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
306310
},
307311
prettyGolden: "docker-info-with-labels-nil",
308312
},
309313
{
310314
doc: "info with empty labels",
311315
dockerInfo: info{
312316
Info: &sampleInfoLabelsEmpty,
313-
ClientInfo: &clientInfo{Context: "default"},
317+
ClientInfo: &clientInfo{clientVersion: clientVersion{Context: "default"}},
314318
},
315319
prettyGolden: "docker-info-with-labels-empty",
316320
},
@@ -319,8 +323,8 @@ func TestPrettyPrintInfo(t *testing.T) {
319323
dockerInfo: info{
320324
Info: &infoWithSwarm,
321325
ClientInfo: &clientInfo{
322-
Context: "default",
323-
Debug: false,
326+
clientVersion: clientVersion{Context: "default"},
327+
Debug: false,
324328
},
325329
},
326330
prettyGolden: "docker-info-with-swarm",
@@ -331,8 +335,12 @@ func TestPrettyPrintInfo(t *testing.T) {
331335
dockerInfo: info{
332336
Info: &infoWithWarningsLinux,
333337
ClientInfo: &clientInfo{
334-
Context: "default",
335-
Debug: true,
338+
clientVersion: clientVersion{
339+
Platform: &platformInfo{Name: "Docker Engine - Community"},
340+
Version: "24.0.0",
341+
Context: "default",
342+
},
343+
Debug: true,
336344
},
337345
},
338346
prettyGolden: "docker-info-no-swarm",
@@ -344,8 +352,12 @@ func TestPrettyPrintInfo(t *testing.T) {
344352
dockerInfo: info{
345353
Info: &sampleInfoDaemonWarnings,
346354
ClientInfo: &clientInfo{
347-
Context: "default",
348-
Debug: true,
355+
clientVersion: clientVersion{
356+
Platform: &platformInfo{Name: "Docker Engine - Community"},
357+
Version: "24.0.0",
358+
Context: "default",
359+
},
360+
Debug: true,
349361
},
350362
},
351363
prettyGolden: "docker-info-no-swarm",
@@ -376,6 +388,7 @@ func TestPrettyPrintInfo(t *testing.T) {
376388
expectedError: "errors pretty printing info",
377389
},
378390
} {
391+
tc := tc
379392
t.Run(tc.doc, func(t *testing.T) {
380393
cli := test.NewFakeCli(&fakeClient{})
381394
err := prettyPrintInfo(cli, tc.dockerInfo)
@@ -429,6 +442,7 @@ func TestFormatInfo(t *testing.T) {
429442
expectedError: `template: :1:2: executing "" at <.badString>: can't evaluate field badString in type system.info`,
430443
},
431444
} {
445+
tc := tc
432446
t.Run(tc.doc, func(t *testing.T) {
433447
cli := test.NewFakeCli(&fakeClient{})
434448
info := info{
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
1+
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":true,"SwapLimit":true,"KernelMemory":true,"CpuCfsPeriod":true,"CpuCfsQuota":true,"CPUShares":true,"CPUSet":true,"PidsLimit":false,"IPv4Forwarding":true,"BridgeNfIptables":true,"BridgeNfIp6tables":true,"Debug":true,"NFd":33,"OomKillDisable":true,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":["WARNING: No memory limit support","WARNING: No swap limit support","WARNING: No oom kill disable support","WARNING: No cpu cfs quota support","WARNING: No cpu cfs period support","WARNING: No cpu shares support","WARNING: No cpuset support","WARNING: IPv4 forwarding is disabled","WARNING: bridge-nf-call-iptables is disabled","WARNING: bridge-nf-call-ip6tables is disabled"],"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":true,"NFd":33,"OomKillDisable":false,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Context":"default","Plugins":[],"Warnings":null}}
1+
{"ID":"EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX","Containers":0,"ContainersRunning":0,"ContainersPaused":0,"ContainersStopped":0,"Images":0,"Driver":"aufs","DriverStatus":[["Root Dir","/var/lib/docker/aufs"],["Backing Filesystem","extfs"],["Dirs","0"],["Dirperm1 Supported","true"]],"Plugins":{"Volume":["local"],"Network":["bridge","host","macvlan","null","overlay"],"Authorization":null,"Log":["awslogs","fluentd","gcplogs","gelf","journald","json-file","logentries","splunk","syslog"]},"MemoryLimit":false,"SwapLimit":false,"CpuCfsPeriod":false,"CpuCfsQuota":false,"CPUShares":false,"CPUSet":false,"PidsLimit":false,"IPv4Forwarding":false,"BridgeNfIptables":false,"BridgeNfIp6tables":false,"Debug":true,"NFd":33,"OomKillDisable":false,"NGoroutines":135,"SystemTime":"2017-08-24T17:44:34.077811894Z","LoggingDriver":"json-file","CgroupDriver":"cgroupfs","NEventsListener":0,"KernelVersion":"4.4.0-87-generic","OperatingSystem":"Ubuntu 16.04.3 LTS","OSVersion":"","OSType":"linux","Architecture":"x86_64","IndexServerAddress":"https://index.docker.io/v1/","RegistryConfig":{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"InsecureRegistryCIDRs":["127.0.0.0/8"],"IndexConfigs":{"docker.io":{"Name":"docker.io","Mirrors":null,"Secure":true,"Official":true}},"Mirrors":null},"NCPU":2,"MemTotal":2097356800,"GenericResources":null,"DockerRootDir":"/var/lib/docker","HttpProxy":"","HttpsProxy":"","NoProxy":"","Name":"system-sample","Labels":["provider=digitalocean"],"ExperimentalBuild":false,"ServerVersion":"17.06.1-ce","Runtimes":{"runc":{"path":"docker-runc"}},"DefaultRuntime":"runc","Swarm":{"NodeID":"","NodeAddr":"","LocalNodeState":"inactive","ControlAvailable":false,"Error":"","RemoteManagers":null},"LiveRestoreEnabled":false,"Isolation":"","InitBinary":"docker-init","ContainerdCommit":{"ID":"6e23458c129b551d5c9871e5174f6b1b7f6d1170","Expected":"6e23458c129b551d5c9871e5174f6b1b7f6d1170"},"RuncCommit":{"ID":"810190ceaa507aa2727d7ae6f4790c76ec150bd2","Expected":"810190ceaa507aa2727d7ae6f4790c76ec150bd2"},"InitCommit":{"ID":"949e6fa","Expected":"949e6fa"},"SecurityOptions":["name=apparmor","name=seccomp,profile=default"],"DefaultAddressPools":[{"Base":"10.123.0.0/16","Size":24}],"Warnings":null,"ClientInfo":{"Debug":true,"Platform":{"Name":"Docker Engine - Community"},"Version":"24.0.0","Context":"default","Plugins":[],"Warnings":null}}

cli/command/system/testdata/docker-info-no-swarm.golden

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Client:
1+
Client: Docker Engine - Community
2+
Version: 24.0.0
23
Context: default
34
Debug Mode: true
45

0 commit comments

Comments
 (0)