diff --git a/daemon/cluster/cluster.go b/daemon/cluster/cluster.go index 39728b0e47..2b03c48f10 100644 --- a/daemon/cluster/cluster.go +++ b/daemon/cluster/cluster.go @@ -446,11 +446,24 @@ func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error { c.mu.RLock() state := c.currentNodeState() - nr := c.nr - c.mu.RUnlock() - if nr == nil || errors.Cause(state.err) != errSwarmLocked { + + if !state.IsActiveManager() { + // when manager is not active, + // unless it is locked, otherwise return error. + if err := c.errNoManager(state); err != errSwarmLocked { + c.mu.RUnlock() + return err + } + } else { + // when manager is active, return an error of "not locked" + c.mu.RUnlock() return errors.New("swarm is not locked") } + + // only when swarm is locked, code running reaches here + nr := c.nr + c.mu.RUnlock() + key, err := encryption.ParseHumanReadableKey(req.UnlockKey) if err != nil { return err diff --git a/integration-cli/docker_cli_swarm_test.go b/integration-cli/docker_cli_swarm_test.go index 7044df5734..4dc78d93a0 100644 --- a/integration-cli/docker_cli_swarm_test.go +++ b/integration-cli/docker_cli_swarm_test.go @@ -835,6 +835,29 @@ func checkSwarmUnlockedToLocked(c *check.C, d *daemon.Swarm) { c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) } +func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *check.C) { + d := s.AddDaemon(c, false, false) + + // unlocking a normal engine should return an error + cmd := d.Command("swarm", "unlock") + cmd.Stdin = bytes.NewBufferString("wrong-secret-key") + outs, err := cmd.CombinedOutput() + + c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(outs))) + c.Assert(string(outs), checker.Contains, "This node is not a swarm manager.") + + _, err = d.Cmd("swarm", "init") + c.Assert(err, checker.IsNil) + + // unlocking an unlocked swarm should return an error + cmd = d.Command("swarm", "unlock") + cmd.Stdin = bytes.NewBufferString("wrong-secret-key") + outs, err = cmd.CombinedOutput() + + c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(outs))) + c.Assert(string(outs), checker.Contains, "swarm is not locked") +} + func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) { d := s.AddDaemon(c, false, false)