diff --git a/cli/command/system/info.go b/cli/command/system/info.go index 85b89ad3695a..a99354abbdf6 100644 --- a/cli/command/system/info.go +++ b/cli/command/system/info.go @@ -206,45 +206,7 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error { fmt.Fprintln(dockerCli.Out(), "Live Restore Enabled:", info.LiveRestoreEnabled) fmt.Fprint(dockerCli.Out(), "\n") - // Only output these warnings if the server does not support these features - if info.OSType != "windows" { - printStorageDriverWarnings(dockerCli, info) - - if !info.MemoryLimit { - fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support") - } - if !info.SwapLimit { - fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support") - } - if !info.KernelMemory { - fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support") - } - if !info.OomKillDisable { - fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support") - } - if !info.CPUCfsQuota { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support") - } - if !info.CPUCfsPeriod { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support") - } - if !info.CPUShares { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support") - } - if !info.CPUSet { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support") - } - if !info.IPv4Forwarding { - fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled") - } - if !info.BridgeNfIptables { - fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled") - } - if !info.BridgeNfIP6tables { - fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled") - } - } - + printWarnings(dockerCli, info) return nil } @@ -315,11 +277,73 @@ func printSwarmInfo(dockerCli command.Cli, info types.Info) { } } +func printWarnings(dockerCli command.Cli, info types.Info) { + if len(info.Warnings) > 0 { + fmt.Fprintln(dockerCli.Err(), strings.Join(info.Warnings, "\n")) + return + } + // daemon didn't return warnings. Fallback to old behavior + printStorageDriverWarnings(dockerCli, info) + printWarningsLegacy(dockerCli, info) +} + +// printWarningsLegacy generates warnings based on information returned by the daemon. +// DEPRECATED: warnings are now generated by the daemon, and returned in +// info.Warnings. This function is used to provide backward compatibility with +// daemons that do not provide these warnings. No new warnings should be added +// here. +func printWarningsLegacy(dockerCli command.Cli, info types.Info) { + if info.OSType == "windows" { + return + } + if !info.MemoryLimit { + fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support") + } + if !info.SwapLimit { + fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support") + } + if !info.KernelMemory { + fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support") + } + if !info.OomKillDisable { + fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support") + } + if !info.CPUCfsQuota { + fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support") + } + if !info.CPUCfsPeriod { + fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support") + } + if !info.CPUShares { + fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support") + } + if !info.CPUSet { + fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support") + } + if !info.IPv4Forwarding { + fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled") + } + if !info.BridgeNfIptables { + fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled") + } + if !info.BridgeNfIP6tables { + fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled") + } +} + +// printStorageDriverWarnings generates warnings based on storage-driver information +// returned by the daemon. +// DEPRECATED: warnings are now generated by the daemon, and returned in +// info.Warnings. This function is used to provide backward compatibility with +// daemons that do not provide these warnings. No new warnings should be added +// here. func printStorageDriverWarnings(dockerCli command.Cli, info types.Info) { + if info.OSType == "windows" { + return + } if info.DriverStatus == nil { return } - for _, pair := range info.DriverStatus { if pair[0] == "Data loop file" { fmt.Fprintf(dockerCli.Err(), "WARNING: %s: usage of loopback devices is "+ diff --git a/cli/command/system/info_test.go b/cli/command/system/info_test.go index 600e79ac3e0d..942a645b2e02 100644 --- a/cli/command/system/info_test.go +++ b/cli/command/system/info_test.go @@ -207,32 +207,59 @@ func TestPrettyPrintInfo(t *testing.T) { infoWithWarningsLinux.BridgeNfIptables = false infoWithWarningsLinux.BridgeNfIP6tables = false + sampleInfoDaemonWarnings := sampleInfoNoSwarm + sampleInfoDaemonWarnings.Warnings = []string{ + "WARNING: No memory limit support", + "WARNING: No swap limit support", + "WARNING: No kernel memory 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", + } + for _, tc := range []struct { + doc string dockerInfo types.Info expectedGolden string warningsGolden string }{ { + doc: "info without swarm", dockerInfo: sampleInfoNoSwarm, expectedGolden: "docker-info-no-swarm", }, { + doc: "info with swarm", dockerInfo: infoWithSwarm, expectedGolden: "docker-info-with-swarm", }, { + doc: "info with legacy warnings", dockerInfo: infoWithWarningsLinux, expectedGolden: "docker-info-no-swarm", warningsGolden: "docker-info-warnings", }, + { + doc: "info with daemon warnings", + dockerInfo: sampleInfoDaemonWarnings, + expectedGolden: "docker-info-no-swarm", + warningsGolden: "docker-info-warnings", + }, } { - cli := test.NewFakeCli(&fakeClient{}) - assert.NilError(t, prettyPrintInfo(cli, tc.dockerInfo)) - golden.Assert(t, cli.OutBuffer().String(), tc.expectedGolden+".golden") - if tc.warningsGolden != "" { - golden.Assert(t, cli.ErrBuffer().String(), tc.warningsGolden+".golden") - } else { - assert.Check(t, is.Equal("", cli.ErrBuffer().String())) - } + t.Run(tc.doc, func(t *testing.T) { + cli := test.NewFakeCli(&fakeClient{}) + assert.NilError(t, prettyPrintInfo(cli, tc.dockerInfo)) + golden.Assert(t, cli.OutBuffer().String(), tc.expectedGolden+".golden") + if tc.warningsGolden != "" { + golden.Assert(t, cli.ErrBuffer().String(), tc.warningsGolden+".golden") + } else { + assert.Check(t, is.Equal("", cli.ErrBuffer().String())) + } + }) } } diff --git a/vendor.conf b/vendor.conf index 34ba3f0502f8..681f041c7cc1 100755 --- a/vendor.conf +++ b/vendor.conf @@ -12,7 +12,7 @@ github.com/cpuguy83/go-md2man v1.0.8 github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 # v1.1.0 github.com/dgrijalva/jwt-go a2c85815a77d0f951e33ba4db5ae93629a1530af github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5 -github.com/docker/docker 1800883bd16664846db1572b8c8fbe8c85892cee +github.com/docker/docker 2629fe93266e82751af4f1c7568e21060f065b73 github.com/docker/docker-credential-helpers 5241b46610f2491efdf9d1c85f1ddf5b02f6d962 # the docker/go package contains a customized version of canonical/json # and is used by Notary. The package is periodically rebased on current Go versions. diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go index ae9e27dca112..ed62fd41e57c 100644 --- a/vendor/github.com/docker/docker/api/types/types.go +++ b/vendor/github.com/docker/docker/api/types/types.go @@ -206,6 +206,7 @@ type Info struct { InitCommit Commit SecurityOptions []string ProductLicense string `json:",omitempty"` + Warnings []string } // KeyValue holds a key/value pair