diff --git a/api/server/router/system/system_routes.go b/api/server/router/system/system_routes.go index 365095159aa06fd9ab782058cf7c306059168201..2d496a189ce11153dee812e6d0d90a5cb72640f9 100644 --- a/api/server/router/system/system_routes.go +++ b/api/server/router/system/system_routes.go @@ -50,6 +50,7 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht } if s.cluster != nil { info.Swarm = s.cluster.Info() + info.Warnings = append(info.Warnings, info.Swarm.Warnings...) } if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") { diff --git a/api/types/swarm/swarm.go b/api/types/swarm/swarm.go index 484cd0be7f2acf317ca53e5ad7f2951541e24582..b25f9996462e05a64d8e1f0fdff2ec0608c664f8 100644 --- a/api/types/swarm/swarm.go +++ b/api/types/swarm/swarm.go @@ -209,6 +209,8 @@ type Info struct { Managers int `json:",omitempty"` Cluster *ClusterInfo `json:",omitempty"` + + Warnings []string `json:",omitempty"` } // Peer represents a peer. diff --git a/daemon/cluster/swarm.go b/daemon/cluster/swarm.go index 8cc172e9ce54fccea4b24584b6335c1f503d3427..18a909199a1e06c1e6cf60ed2d91a908a1b1096a 100644 --- a/daemon/cluster/swarm.go +++ b/daemon/cluster/swarm.go @@ -459,6 +459,20 @@ func (c *Cluster) Info() types.Info { } } } + + switch info.LocalNodeState { + case types.LocalNodeStateInactive, types.LocalNodeStateLocked, types.LocalNodeStateError: + // nothing to do + default: + if info.Managers == 2 { + const warn string = `WARNING: Running Swarm in a two-manager configuration. This configuration provides + no fault tolerance, and poses a high risk to loose control over the cluster. + Refer to https://docs.docker.com/engine/swarm/admin_guide/ to configure the + Swarm for fault-tolerance.` + + info.Warnings = append(info.Warnings, warn) + } + } } if state.swarmNode != nil {