Check if a swarm is locked before asking a user to enter their unlock key
| ... | ... |
@@ -2,6 +2,7 @@ package swarm |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 | 4 |
"bufio" |
| 5 |
+ "errors" |
|
| 5 | 6 |
"fmt" |
| 6 | 7 |
"io" |
| 7 | 8 |
"strings" |
| ... | ... |
@@ -24,6 +25,22 @@ func newUnlockCommand(dockerCli *command.DockerCli) *cobra.Command {
|
| 24 | 24 |
client := dockerCli.Client() |
| 25 | 25 |
ctx := context.Background() |
| 26 | 26 |
|
| 27 |
+ // First see if the node is actually part of a swarm, and if it's is actually locked first. |
|
| 28 |
+ // If it's in any other state than locked, don't ask for the key. |
|
| 29 |
+ info, err := client.Info(ctx) |
|
| 30 |
+ if err != nil {
|
|
| 31 |
+ return err |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ switch info.Swarm.LocalNodeState {
|
|
| 35 |
+ case swarm.LocalNodeStateInactive: |
|
| 36 |
+ return errors.New("Error: This node is not part of a swarm")
|
|
| 37 |
+ case swarm.LocalNodeStateLocked: |
|
| 38 |
+ break |
|
| 39 |
+ default: |
|
| 40 |
+ return errors.New("Error: swarm is not locked")
|
|
| 41 |
+ } |
|
| 42 |
+ |
|
| 27 | 43 |
key, err := readKey(dockerCli.In(), "Please enter unlock key: ") |
| 28 | 44 |
if err != nil {
|
| 29 | 45 |
return err |
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/api/types/swarm" |
| 13 | 13 |
"github.com/docker/docker/pkg/integration/checker" |
| 14 | 14 |
"github.com/go-check/check" |
| 15 |
+ "github.com/pkg/errors" |
|
| 15 | 16 |
) |
| 16 | 17 |
|
| 17 | 18 |
// Swarm is a test daemon with helpers for participating in a swarm. |
| ... | ... |
@@ -96,6 +97,18 @@ func (d *Swarm) SwarmInfo() (swarm.Info, error) {
|
| 96 | 96 |
return info.Swarm, nil |
| 97 | 97 |
} |
| 98 | 98 |
|
| 99 |
+// Unlock tries to unlock a locked swarm |
|
| 100 |
+func (d *Swarm) Unlock(req swarm.UnlockRequest) error {
|
|
| 101 |
+ status, out, err := d.SockRequest("POST", "/swarm/unlock", req)
|
|
| 102 |
+ if status != http.StatusOK {
|
|
| 103 |
+ return fmt.Errorf("unlocking swarm: invalid statuscode %v, %q", status, out)
|
|
| 104 |
+ } |
|
| 105 |
+ if err != nil {
|
|
| 106 |
+ err = errors.Wrap(err, "unlocking swarm") |
|
| 107 |
+ } |
|
| 108 |
+ return err |
|
| 109 |
+} |
|
| 110 |
+ |
|
| 99 | 111 |
// ServiceConstructor defines a swarm service constructor function |
| 100 | 112 |
type ServiceConstructor func(*swarm.Service) |
| 101 | 113 |
|
| ... | ... |
@@ -1309,3 +1309,11 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
|
| 1309 | 1309 |
c.Assert(err, checker.IsNil) |
| 1310 | 1310 |
c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf("secret delete: %s", string(out)))
|
| 1311 | 1311 |
} |
| 1312 |
+ |
|
| 1313 |
+// Unlocking an unlocked swarm results in an error |
|
| 1314 |
+func (s *DockerSwarmSuite) TestAPISwarmUnlockNotLocked(c *check.C) {
|
|
| 1315 |
+ d := s.AddDaemon(c, true, true) |
|
| 1316 |
+ err := d.Unlock(swarm.UnlockRequest{UnlockKey: "wrong-key"})
|
|
| 1317 |
+ c.Assert(err, checker.NotNil) |
|
| 1318 |
+ c.Assert(err.Error(), checker.Contains, "swarm is not locked") |
|
| 1319 |
+} |
| ... | ... |
@@ -866,24 +866,24 @@ func checkSwarmUnlockedToLocked(c *check.C, d *daemon.Swarm) {
|
| 866 | 866 |
func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *check.C) {
|
| 867 | 867 |
d := s.AddDaemon(c, false, false) |
| 868 | 868 |
|
| 869 |
- // unlocking a normal engine should return an error |
|
| 869 |
+ // unlocking a normal engine should return an error - it does not even ask for the key |
|
| 870 | 870 |
cmd := d.Command("swarm", "unlock")
|
| 871 |
- cmd.Stdin = bytes.NewBufferString("wrong-secret-key")
|
|
| 872 | 871 |
outs, err := cmd.CombinedOutput() |
| 873 | 872 |
|
| 874 | 873 |
c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(outs)))
|
| 875 |
- c.Assert(string(outs), checker.Contains, "This node is not a swarm manager.") |
|
| 874 |
+ c.Assert(string(outs), checker.Contains, "Error: This node is not part of a swarm") |
|
| 875 |
+ c.Assert(string(outs), checker.Not(checker.Contains), "Please enter unlock key") |
|
| 876 | 876 |
|
| 877 | 877 |
_, err = d.Cmd("swarm", "init")
|
| 878 | 878 |
c.Assert(err, checker.IsNil) |
| 879 | 879 |
|
| 880 |
- // unlocking an unlocked swarm should return an error |
|
| 880 |
+ // unlocking an unlocked swarm should return an error - it does not even ask for the key |
|
| 881 | 881 |
cmd = d.Command("swarm", "unlock")
|
| 882 |
- cmd.Stdin = bytes.NewBufferString("wrong-secret-key")
|
|
| 883 | 882 |
outs, err = cmd.CombinedOutput() |
| 884 | 883 |
|
| 885 | 884 |
c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(outs)))
|
| 886 |
- c.Assert(string(outs), checker.Contains, "swarm is not locked") |
|
| 885 |
+ c.Assert(string(outs), checker.Contains, "Error: swarm is not locked") |
|
| 886 |
+ c.Assert(string(outs), checker.Not(checker.Contains), "Please enter unlock key") |
|
| 887 | 887 |
} |
| 888 | 888 |
|
| 889 | 889 |
func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) {
|