Skip to content

Commit a3d4238

Browse files
committed
Add "Warnings" to /info endpoint, and move detection to the daemon
When requesting information about the daemon's configuration through the `/info` endpoint, missing features (or non-recommended settings) may have to be presented to the user. Detecting these situations, and printing warnings currently is handled by the cli, which results in some complications: - duplicated effort: each client has to re-implement detection and warnings. - it's not possible to generate warnings for reasons outside of the information returned in the `/info` response. - cli-side detection has to be updated for new conditions. This means that an older cli connecting to a new daemon may not print all warnings (due to it not detecting the new conditions) - some warnings (in particular, warnings about storage-drivers) depend on driver-status (`DriverStatus`) information. The format of the information returned in this field is not part of the API specification and can change over time, resulting in cli-side detection no longer being functional. This patch adds a new `Warnings` field to the `/info` response. This field is to return warnings to be presented by the user. Existing warnings that are currently handled by the CLI are copied to the daemon as part of this patch; This change is backward-compatible with existing clients; old client can continue to use the client-side warnings, whereas new clients can skip client-side detection, and print warnings that are returned by the daemon. Example response with this patch applied; ```bash curl --unix-socket /var/run/docker.sock http://localhost/info | jq .Warnings ``` ```json [ "WARNING: bridge-nf-call-iptables is disabled", "WARNING: bridge-nf-call-ip6tables is disabled" ] ``` Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 1800883 commit a3d4238

6 files changed

Lines changed: 96 additions & 0 deletions

File tree

api/swagger.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3904,6 +3904,19 @@ definitions:
39043904
such as number of nodes, and expiration are included.
39053905
type: "string"
39063906
example: "Community Engine"
3907+
Warnings:
3908+
description: |
3909+
List of warnings / informational messages about missing features, or
3910+
issues related to the daemon configuration.
3911+
3912+
These messages can be printed by the client as information to the user.
3913+
type: "array"
3914+
items:
3915+
type: "string"
3916+
example:
3917+
- "WARNING: No memory limit support"
3918+
- "WARNING: bridge-nf-call-iptables is disabled"
3919+
- "WARNING: bridge-nf-call-ip6tables is disabled"
39073920

39083921

39093922
# PluginsInfo is a temp struct holding Plugins name

api/types/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ type Info struct {
206206
InitCommit Commit
207207
SecurityOptions []string
208208
ProductLicense string `json:",omitempty"`
209+
Warnings []string
209210
}
210211

211212
// KeyValue holds a key/value pair

daemon/info.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ func (daemon *Daemon) fillDriverInfo(v *types.Info) {
134134

135135
v.Driver = drivers
136136
v.DriverStatus = ds
137+
138+
fillDriverWarnings(v)
137139
}
138140

139141
func (daemon *Daemon) fillPluginsInfo(v *types.Info) {

daemon/info_unix.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package daemon // import "github.com/docker/docker/daemon"
44

55
import (
66
"context"
7+
"fmt"
78
"os/exec"
89
"strings"
910

@@ -68,6 +69,80 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
6869
logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err)
6970
v.InitCommit.ID = "N/A"
7071
}
72+
73+
if !v.MemoryLimit {
74+
v.Warnings = append(v.Warnings, "WARNING: No memory limit support")
75+
}
76+
if !v.SwapLimit {
77+
v.Warnings = append(v.Warnings, "WARNING: No swap limit support")
78+
}
79+
if !v.KernelMemory {
80+
v.Warnings = append(v.Warnings, "WARNING: No kernel memory limit support")
81+
}
82+
if !v.OomKillDisable {
83+
v.Warnings = append(v.Warnings, "WARNING: No oom kill disable support")
84+
}
85+
if !v.CPUCfsQuota {
86+
v.Warnings = append(v.Warnings, "WARNING: No cpu cfs quota support")
87+
}
88+
if !v.CPUCfsPeriod {
89+
v.Warnings = append(v.Warnings, "WARNING: No cpu cfs period support")
90+
}
91+
if !v.CPUShares {
92+
v.Warnings = append(v.Warnings, "WARNING: No cpu shares support")
93+
}
94+
if !v.CPUSet {
95+
v.Warnings = append(v.Warnings, "WARNING: No cpuset support")
96+
}
97+
if !v.IPv4Forwarding {
98+
v.Warnings = append(v.Warnings, "WARNING: IPv4 forwarding is disabled")
99+
}
100+
if !v.BridgeNfIptables {
101+
v.Warnings = append(v.Warnings, "WARNING: bridge-nf-call-iptables is disabled")
102+
}
103+
if !v.BridgeNfIP6tables {
104+
v.Warnings = append(v.Warnings, "WARNING: bridge-nf-call-ip6tables is disabled")
105+
}
106+
}
107+
108+
func fillDriverWarnings(v *types.Info) {
109+
if v.DriverStatus == nil {
110+
return
111+
}
112+
for _, pair := range v.DriverStatus {
113+
if pair[0] == "Data loop file" {
114+
msg := fmt.Sprintf("WARNING: %s: usage of loopback devices is "+
115+
"strongly discouraged for production use.\n "+
116+
"Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.", v.Driver)
117+
118+
v.Warnings = append(v.Warnings, msg)
119+
continue
120+
}
121+
if pair[0] == "Supports d_type" && pair[1] == "false" {
122+
backingFs := getBackingFs(v)
123+
124+
msg := fmt.Sprintf("WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n", v.Driver, backingFs)
125+
if backingFs == "xfs" {
126+
msg += " Reformat the filesystem with ftype=1 to enable d_type support.\n"
127+
}
128+
msg += " Running without d_type support will not be supported in future releases."
129+
130+
v.Warnings = append(v.Warnings, msg)
131+
continue
132+
}
133+
}
134+
}
135+
136+
func getBackingFs(v *types.Info) string {
137+
if v.DriverStatus == nil {
138+
return ""
139+
}
140+
for _, pair := range v.DriverStatus {
141+
if pair[0] == "Backing Filesystem" {
142+
return pair[1]
143+
}
144+
}
145+
return ""
71146
}
72147

73148
// parseInitVersion parses a Tini version string, and extracts the version.

daemon/info_windows.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ import (
88
// fillPlatformInfo fills the platform related info.
99
func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo) {
1010
}
11+
12+
func fillDriverWarnings(v *types.Info) {
13+
}

docs/api/version-history.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ keywords: "API, Docker, rcli, REST, documentation"
2121
and `OperatingSystem` if the daemon was unable to obtain this information.
2222
* `GET /info` now returns information about the product license, if a license
2323
has been applied to the daemon.
24+
* `GET /info` now returns a `Warnings` field, containing warnings and informational
25+
messages about missing features, or issues related to the daemon configuration.
2426
* `POST /swarm/init` now accepts a `DefaultAddrPool` property to set global scope default address pool
2527
* `POST /swarm/init` now accepts a `SubnetSize` property to set global scope networks by giving the
2628
length of the subnet masks for every such network

0 commit comments

Comments
 (0)