diff --git a/cli/command/system/info.go b/cli/command/system/info.go index 85b89ad369..a99354abbd 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 600e79ac3e..942a645b2e 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())) + } + }) } }