Signed-off-by: cyli <cyli@twistedmatrix.com>
| ... | ... |
@@ -849,6 +849,12 @@ func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *check.C) {
|
| 849 | 849 |
c.Assert(strings.TrimSpace(out), checker.Equals, "{[1.2.3.4] [example.com] [timeout:3]}")
|
| 850 | 850 |
} |
| 851 | 851 |
|
| 852 |
+func getNodeStatus(c *check.C, d *SwarmDaemon) swarm.LocalNodeState {
|
|
| 853 |
+ info, err := d.info() |
|
| 854 |
+ c.Assert(err, checker.IsNil) |
|
| 855 |
+ return info.LocalNodeState |
|
| 856 |
+} |
|
| 857 |
+ |
|
| 852 | 858 |
func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) {
|
| 853 | 859 |
d := s.AddDaemon(c, false, false) |
| 854 | 860 |
|
| ... | ... |
@@ -870,15 +876,11 @@ func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) {
|
| 870 | 870 |
outs, err = d.Cmd("swarm", "unlock-key", "-q")
|
| 871 | 871 |
c.Assert(outs, checker.Equals, unlockKey+"\n") |
| 872 | 872 |
|
| 873 |
- info, err := d.info() |
|
| 874 |
- c.Assert(err, checker.IsNil) |
|
| 875 |
- c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) |
|
| 873 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 876 | 874 |
|
| 877 | 875 |
c.Assert(d.Restart(), checker.IsNil) |
| 878 | 876 |
|
| 879 |
- info, err = d.info() |
|
| 880 |
- c.Assert(err, checker.IsNil) |
|
| 881 |
- c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked) |
|
| 877 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 882 | 878 |
|
| 883 | 879 |
cmd := d.command("swarm", "unlock")
|
| 884 | 880 |
cmd.Stdin = bytes.NewBufferString("wrong-secret-key")
|
| ... | ... |
@@ -886,14 +888,14 @@ func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) {
|
| 886 | 886 |
c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(out)))
|
| 887 | 887 |
c.Assert(string(out), checker.Contains, "invalid key") |
| 888 | 888 |
|
| 889 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 890 |
+ |
|
| 889 | 891 |
cmd = d.command("swarm", "unlock")
|
| 890 | 892 |
cmd.Stdin = bytes.NewBufferString(unlockKey) |
| 891 | 893 |
out, err = cmd.CombinedOutput() |
| 892 | 894 |
c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
| 893 | 895 |
|
| 894 |
- info, err = d.info() |
|
| 895 |
- c.Assert(err, checker.IsNil) |
|
| 896 |
- c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) |
|
| 896 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 897 | 897 |
|
| 898 | 898 |
outs, err = d.Cmd("node", "ls")
|
| 899 | 899 |
c.Assert(err, checker.IsNil) |
| ... | ... |
@@ -903,13 +905,22 @@ func (s *DockerSwarmSuite) TestSwarmInitLocked(c *check.C) {
|
| 903 | 903 |
c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
| 904 | 904 |
|
| 905 | 905 |
// Wait for autolock to be turned off |
| 906 |
- time.Sleep(time.Second) |
|
| 907 |
- |
|
| 908 | 906 |
c.Assert(d.Restart(), checker.IsNil) |
| 907 |
+ status := getNodeStatus(c, d) |
|
| 908 |
+ if status == swarm.LocalNodeStateLocked {
|
|
| 909 |
+ // it must not have updated in time - unlock, wait 3 seconds, and try again |
|
| 910 |
+ cmd := d.command("swarm", "unlock")
|
|
| 911 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 912 |
+ out, err := cmd.CombinedOutput() |
|
| 913 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 909 | 914 |
|
| 910 |
- info, err = d.info() |
|
| 911 |
- c.Assert(err, checker.IsNil) |
|
| 912 |
- c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) |
|
| 915 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 916 |
+ |
|
| 917 |
+ time.Sleep(3 * time.Second) |
|
| 918 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 919 |
+ } |
|
| 920 |
+ |
|
| 921 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 913 | 922 |
|
| 914 | 923 |
outs, err = d.Cmd("node", "ls")
|
| 915 | 924 |
c.Assert(err, checker.IsNil) |
| ... | ... |
@@ -946,6 +957,191 @@ func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *check.C) {
|
| 946 | 946 |
c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) |
| 947 | 947 |
} |
| 948 | 948 |
|
| 949 |
+func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *check.C) {
|
|
| 950 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 951 |
+ d2 := s.AddDaemon(c, true, true) |
|
| 952 |
+ d3 := s.AddDaemon(c, true, true) |
|
| 953 |
+ |
|
| 954 |
+ // they start off unlocked |
|
| 955 |
+ c.Assert(d2.Restart(), checker.IsNil) |
|
| 956 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive) |
|
| 957 |
+ |
|
| 958 |
+ // stop this one so it does not get autolock info |
|
| 959 |
+ c.Assert(d2.Stop(), checker.IsNil) |
|
| 960 |
+ |
|
| 961 |
+ // enable autolock |
|
| 962 |
+ outs, err := d1.Cmd("swarm", "update", "--autolock")
|
|
| 963 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 964 |
+ |
|
| 965 |
+ c.Assert(outs, checker.Contains, "docker swarm unlock") |
|
| 966 |
+ |
|
| 967 |
+ var unlockKey string |
|
| 968 |
+ for _, line := range strings.Split(outs, "\n") {
|
|
| 969 |
+ if strings.Contains(line, "SWMKEY") {
|
|
| 970 |
+ unlockKey = strings.TrimSpace(line) |
|
| 971 |
+ break |
|
| 972 |
+ } |
|
| 973 |
+ } |
|
| 974 |
+ |
|
| 975 |
+ c.Assert(unlockKey, checker.Not(checker.Equals), "") |
|
| 976 |
+ |
|
| 977 |
+ outs, err = d1.Cmd("swarm", "unlock-key", "-q")
|
|
| 978 |
+ c.Assert(outs, checker.Equals, unlockKey+"\n") |
|
| 979 |
+ |
|
| 980 |
+ // The ones that got the cluster update should be set to locked |
|
| 981 |
+ for _, d := range []*SwarmDaemon{d1, d3} {
|
|
| 982 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 983 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 984 |
+ |
|
| 985 |
+ cmd := d.command("swarm", "unlock")
|
|
| 986 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 987 |
+ out, err := cmd.CombinedOutput() |
|
| 988 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 989 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 990 |
+ } |
|
| 991 |
+ |
|
| 992 |
+ // d2 never got the cluster update, so it is still set to unlocked |
|
| 993 |
+ c.Assert(d2.Start(), checker.IsNil) |
|
| 994 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive) |
|
| 995 |
+ |
|
| 996 |
+ // d2 is now set to lock |
|
| 997 |
+ c.Assert(d2.Restart(), checker.IsNil) |
|
| 998 |
+ status := getNodeStatus(c, d2) |
|
| 999 |
+ if status == swarm.LocalNodeStateActive {
|
|
| 1000 |
+ // it must not have updated in time - wait 3 seconds, and try again |
|
| 1001 |
+ time.Sleep(3 * time.Second) |
|
| 1002 |
+ c.Assert(d2.Restart(), checker.IsNil) |
|
| 1003 |
+ } |
|
| 1004 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 1005 |
+ |
|
| 1006 |
+ // leave it locked, and set the cluster to no longer autolock |
|
| 1007 |
+ outs, err = d1.Cmd("swarm", "update", "--autolock=false")
|
|
| 1008 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 1009 |
+ |
|
| 1010 |
+ // the ones that got the update are now set to unlocked |
|
| 1011 |
+ for _, d := range []*SwarmDaemon{d1, d3} {
|
|
| 1012 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1013 |
+ status := getNodeStatus(c, d) |
|
| 1014 |
+ if status == swarm.LocalNodeStateLocked {
|
|
| 1015 |
+ // it must not have updated to be unlocked in time - unlock, wait 3 seconds, and try again |
|
| 1016 |
+ cmd := d.command("swarm", "unlock")
|
|
| 1017 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1018 |
+ out, err := cmd.CombinedOutput() |
|
| 1019 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1020 |
+ |
|
| 1021 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1022 |
+ |
|
| 1023 |
+ time.Sleep(3 * time.Second) |
|
| 1024 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1025 |
+ } |
|
| 1026 |
+ |
|
| 1027 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1028 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1029 |
+ } |
|
| 1030 |
+ |
|
| 1031 |
+ // d2 still locked |
|
| 1032 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 1033 |
+ |
|
| 1034 |
+ // unlock it |
|
| 1035 |
+ cmd := d2.command("swarm", "unlock")
|
|
| 1036 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1037 |
+ out, err := cmd.CombinedOutput() |
|
| 1038 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1039 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1040 |
+ |
|
| 1041 |
+ // once it's caught up, d2 is set to not be locked |
|
| 1042 |
+ c.Assert(d2.Restart(), checker.IsNil) |
|
| 1043 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1044 |
+ |
|
| 1045 |
+ // managers who join now are also unlocked |
|
| 1046 |
+ d4 := s.AddDaemon(c, true, true) |
|
| 1047 |
+ c.Assert(d4.Restart(), checker.IsNil) |
|
| 1048 |
+ c.Assert(getNodeStatus(c, d4), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1049 |
+} |
|
| 1050 |
+ |
|
| 1051 |
+func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *check.C) {
|
|
| 1052 |
+ d1 := s.AddDaemon(c, true, true) |
|
| 1053 |
+ |
|
| 1054 |
+ // enable autolock |
|
| 1055 |
+ outs, err := d1.Cmd("swarm", "update", "--autolock")
|
|
| 1056 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 1057 |
+ |
|
| 1058 |
+ c.Assert(outs, checker.Contains, "docker swarm unlock") |
|
| 1059 |
+ |
|
| 1060 |
+ var unlockKey string |
|
| 1061 |
+ for _, line := range strings.Split(outs, "\n") {
|
|
| 1062 |
+ if strings.Contains(line, "SWMKEY") {
|
|
| 1063 |
+ unlockKey = strings.TrimSpace(line) |
|
| 1064 |
+ break |
|
| 1065 |
+ } |
|
| 1066 |
+ } |
|
| 1067 |
+ |
|
| 1068 |
+ c.Assert(unlockKey, checker.Not(checker.Equals), "") |
|
| 1069 |
+ |
|
| 1070 |
+ outs, err = d1.Cmd("swarm", "unlock-key", "-q")
|
|
| 1071 |
+ c.Assert(outs, checker.Equals, unlockKey+"\n") |
|
| 1072 |
+ |
|
| 1073 |
+ // joined workers start off unlocked |
|
| 1074 |
+ d2 := s.AddDaemon(c, true, false) |
|
| 1075 |
+ c.Assert(d2.Restart(), checker.IsNil) |
|
| 1076 |
+ c.Assert(getNodeStatus(c, d2), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1077 |
+ |
|
| 1078 |
+ // promote worker |
|
| 1079 |
+ outs, err = d1.Cmd("node", "promote", d2.Info.NodeID)
|
|
| 1080 |
+ c.Assert(err, checker.IsNil) |
|
| 1081 |
+ c.Assert(outs, checker.Contains, "promoted to a manager in the swarm") |
|
| 1082 |
+ |
|
| 1083 |
+ // join new manager node |
|
| 1084 |
+ d3 := s.AddDaemon(c, true, true) |
|
| 1085 |
+ |
|
| 1086 |
+ // both new nodes are locked |
|
| 1087 |
+ for _, d := range []*SwarmDaemon{d2, d3} {
|
|
| 1088 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1089 |
+ status := getNodeStatus(c, d) |
|
| 1090 |
+ if status == swarm.LocalNodeStateActive {
|
|
| 1091 |
+ // it must not have updated in time - wait 3 seconds, and try again |
|
| 1092 |
+ time.Sleep(3 * time.Second) |
|
| 1093 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1094 |
+ } |
|
| 1095 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 1096 |
+ |
|
| 1097 |
+ cmd := d.command("swarm", "unlock")
|
|
| 1098 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1099 |
+ out, err := cmd.CombinedOutput() |
|
| 1100 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1101 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1102 |
+ } |
|
| 1103 |
+ |
|
| 1104 |
+ // demote manager back to worker - workers are not locked |
|
| 1105 |
+ outs, err = d1.Cmd("node", "demote", d3.Info.NodeID)
|
|
| 1106 |
+ c.Assert(err, checker.IsNil) |
|
| 1107 |
+ c.Assert(outs, checker.Contains, "demoted in the swarm") |
|
| 1108 |
+ |
|
| 1109 |
+ // verify that it's been demoted |
|
| 1110 |
+ out, err := d1.Cmd("node", "ls", "--filter", "id="+d3.Info.NodeID)
|
|
| 1111 |
+ c.Assert(err, checker.IsNil) |
|
| 1112 |
+ lines := strings.Split(strings.TrimSpace(out), "\n") |
|
| 1113 |
+ c.Assert(len(lines), checker.GreaterThan, 0) |
|
| 1114 |
+ columns := strings.Fields(lines[len(lines)-1]) |
|
| 1115 |
+ c.Assert(columns, checker.HasLen, 4) // if it was a manager it'd have a manager status field |
|
| 1116 |
+ |
|
| 1117 |
+ c.Assert(d3.Restart(), checker.IsNil) |
|
| 1118 |
+ status := getNodeStatus(c, d3) |
|
| 1119 |
+ if status == swarm.LocalNodeStateLocked {
|
|
| 1120 |
+ // it must not have updated in time - unlock, wait 3 seconds, and try again |
|
| 1121 |
+ cmd := d3.command("swarm", "unlock")
|
|
| 1122 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1123 |
+ out, err := cmd.CombinedOutput() |
|
| 1124 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1125 |
+ |
|
| 1126 |
+ c.Assert(getNodeStatus(c, d3), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1127 |
+ |
|
| 1128 |
+ time.Sleep(3 * time.Second) |
|
| 1129 |
+ c.Assert(d3.Restart(), checker.IsNil) |
|
| 1130 |
+ } |
|
| 1131 |
+ c.Assert(getNodeStatus(c, d3), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1132 |
+} |
|
| 1133 |
+ |
|
| 949 | 1134 |
func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *check.C) {
|
| 950 | 1135 |
d := s.AddDaemon(c, true, true) |
| 951 | 1136 |
|
| ... | ... |
@@ -977,10 +1173,7 @@ func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *check.C) {
|
| 977 | 977 |
c.Assert(newUnlockKey, checker.Not(checker.Equals), unlockKey) |
| 978 | 978 |
|
| 979 | 979 |
c.Assert(d.Restart(), checker.IsNil) |
| 980 |
- |
|
| 981 |
- info, err := d.info() |
|
| 982 |
- c.Assert(err, checker.IsNil) |
|
| 983 |
- c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateLocked) |
|
| 980 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 984 | 981 |
|
| 985 | 982 |
outs, _ = d.Cmd("node", "ls")
|
| 986 | 983 |
c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlocked") |
| ... | ... |
@@ -1017,9 +1210,7 @@ func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *check.C) {
|
| 1017 | 1017 |
out, err = cmd.CombinedOutput() |
| 1018 | 1018 |
c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
| 1019 | 1019 |
|
| 1020 |
- info, err = d.info() |
|
| 1021 |
- c.Assert(err, checker.IsNil) |
|
| 1022 |
- c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive) |
|
| 1020 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1023 | 1021 |
|
| 1024 | 1022 |
outs, err = d.Cmd("node", "ls")
|
| 1025 | 1023 |
c.Assert(err, checker.IsNil) |
| ... | ... |
@@ -1029,6 +1220,151 @@ func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *check.C) {
|
| 1029 | 1029 |
} |
| 1030 | 1030 |
} |
| 1031 | 1031 |
|
| 1032 |
+// This differs from `TestSwarmRotateUnlockKey` because that one rotates a single node, which is the leader. |
|
| 1033 |
+// This one keeps the leader up, and asserts that other manager nodes in the cluster also have their unlock |
|
| 1034 |
+// key rotated. |
|
| 1035 |
+func (s *DockerSwarmSuite) TestSwarmClusterRotateUnlockKey(c *check.C) {
|
|
| 1036 |
+ d1 := s.AddDaemon(c, true, true) // leader - don't restart this one, we don't want leader election delays |
|
| 1037 |
+ d2 := s.AddDaemon(c, true, true) |
|
| 1038 |
+ d3 := s.AddDaemon(c, true, true) |
|
| 1039 |
+ |
|
| 1040 |
+ outs, err := d1.Cmd("swarm", "update", "--autolock")
|
|
| 1041 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 1042 |
+ |
|
| 1043 |
+ c.Assert(outs, checker.Contains, "docker swarm unlock") |
|
| 1044 |
+ |
|
| 1045 |
+ var unlockKey string |
|
| 1046 |
+ for _, line := range strings.Split(outs, "\n") {
|
|
| 1047 |
+ if strings.Contains(line, "SWMKEY") {
|
|
| 1048 |
+ unlockKey = strings.TrimSpace(line) |
|
| 1049 |
+ break |
|
| 1050 |
+ } |
|
| 1051 |
+ } |
|
| 1052 |
+ |
|
| 1053 |
+ c.Assert(unlockKey, checker.Not(checker.Equals), "") |
|
| 1054 |
+ |
|
| 1055 |
+ outs, err = d1.Cmd("swarm", "unlock-key", "-q")
|
|
| 1056 |
+ c.Assert(outs, checker.Equals, unlockKey+"\n") |
|
| 1057 |
+ |
|
| 1058 |
+ // Rotate multiple times |
|
| 1059 |
+ for i := 0; i != 3; i++ {
|
|
| 1060 |
+ outs, err = d1.Cmd("swarm", "unlock-key", "-q", "--rotate")
|
|
| 1061 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 1062 |
+ // Strip \n |
|
| 1063 |
+ newUnlockKey := outs[:len(outs)-1] |
|
| 1064 |
+ c.Assert(newUnlockKey, checker.Not(checker.Equals), "") |
|
| 1065 |
+ c.Assert(newUnlockKey, checker.Not(checker.Equals), unlockKey) |
|
| 1066 |
+ |
|
| 1067 |
+ c.Assert(d2.Restart(), checker.IsNil) |
|
| 1068 |
+ c.Assert(d3.Restart(), checker.IsNil) |
|
| 1069 |
+ |
|
| 1070 |
+ for _, d := range []*SwarmDaemon{d2, d3} {
|
|
| 1071 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateLocked) |
|
| 1072 |
+ |
|
| 1073 |
+ outs, _ := d.Cmd("node", "ls")
|
|
| 1074 |
+ c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlocked") |
|
| 1075 |
+ |
|
| 1076 |
+ cmd := d.command("swarm", "unlock")
|
|
| 1077 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1078 |
+ out, err := cmd.CombinedOutput() |
|
| 1079 |
+ |
|
| 1080 |
+ if err == nil {
|
|
| 1081 |
+ // On occasion, the daemon may not have finished |
|
| 1082 |
+ // rotating the KEK before restarting. The test is |
|
| 1083 |
+ // intentionally written to explore this behavior. |
|
| 1084 |
+ // When this happens, unlocking with the old key will |
|
| 1085 |
+ // succeed. If we wait for the rotation to happen and |
|
| 1086 |
+ // restart again, the new key should be required this |
|
| 1087 |
+ // time. |
|
| 1088 |
+ |
|
| 1089 |
+ time.Sleep(3 * time.Second) |
|
| 1090 |
+ |
|
| 1091 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1092 |
+ |
|
| 1093 |
+ cmd = d.command("swarm", "unlock")
|
|
| 1094 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1095 |
+ out, err = cmd.CombinedOutput() |
|
| 1096 |
+ } |
|
| 1097 |
+ c.Assert(err, checker.NotNil, check.Commentf("out: %v", string(out)))
|
|
| 1098 |
+ c.Assert(string(out), checker.Contains, "invalid key") |
|
| 1099 |
+ |
|
| 1100 |
+ outs, _ = d.Cmd("node", "ls")
|
|
| 1101 |
+ c.Assert(outs, checker.Contains, "Swarm is encrypted and needs to be unlocked") |
|
| 1102 |
+ |
|
| 1103 |
+ cmd = d.command("swarm", "unlock")
|
|
| 1104 |
+ cmd.Stdin = bytes.NewBufferString(newUnlockKey) |
|
| 1105 |
+ out, err = cmd.CombinedOutput() |
|
| 1106 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1107 |
+ |
|
| 1108 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1109 |
+ |
|
| 1110 |
+ outs, err = d.Cmd("node", "ls")
|
|
| 1111 |
+ c.Assert(err, checker.IsNil) |
|
| 1112 |
+ c.Assert(outs, checker.Not(checker.Contains), "Swarm is encrypted and needs to be unlocked") |
|
| 1113 |
+ } |
|
| 1114 |
+ |
|
| 1115 |
+ unlockKey = newUnlockKey |
|
| 1116 |
+ } |
|
| 1117 |
+} |
|
| 1118 |
+ |
|
| 1119 |
+func (s *DockerSwarmSuite) TestSwarmAlternateLockUnlock(c *check.C) {
|
|
| 1120 |
+ d := s.AddDaemon(c, true, true) |
|
| 1121 |
+ |
|
| 1122 |
+ var unlockKey string |
|
| 1123 |
+ for i := 0; i < 2; i++ {
|
|
| 1124 |
+ // set to lock |
|
| 1125 |
+ outs, err := d.Cmd("swarm", "update", "--autolock")
|
|
| 1126 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 1127 |
+ c.Assert(outs, checker.Contains, "docker swarm unlock") |
|
| 1128 |
+ |
|
| 1129 |
+ for _, line := range strings.Split(outs, "\n") {
|
|
| 1130 |
+ if strings.Contains(line, "SWMKEY") {
|
|
| 1131 |
+ unlockKey = strings.TrimSpace(line) |
|
| 1132 |
+ break |
|
| 1133 |
+ } |
|
| 1134 |
+ } |
|
| 1135 |
+ |
|
| 1136 |
+ c.Assert(unlockKey, checker.Not(checker.Equals), "") |
|
| 1137 |
+ |
|
| 1138 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1139 |
+ status := getNodeStatus(c, d) |
|
| 1140 |
+ if status == swarm.LocalNodeStateActive {
|
|
| 1141 |
+ // hasn't updated yet - wait and try again |
|
| 1142 |
+ time.Sleep(3 * time.Second) |
|
| 1143 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1144 |
+ status = getNodeStatus(c, d) |
|
| 1145 |
+ } |
|
| 1146 |
+ c.Assert(status, checker.Equals, swarm.LocalNodeStateLocked) |
|
| 1147 |
+ |
|
| 1148 |
+ cmd := d.command("swarm", "unlock")
|
|
| 1149 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1150 |
+ out, err := cmd.CombinedOutput() |
|
| 1151 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1152 |
+ |
|
| 1153 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1154 |
+ |
|
| 1155 |
+ outs, err = d.Cmd("swarm", "update", "--autolock=false")
|
|
| 1156 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", outs))
|
|
| 1157 |
+ |
|
| 1158 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1159 |
+ status = getNodeStatus(c, d) |
|
| 1160 |
+ if status == swarm.LocalNodeStateLocked {
|
|
| 1161 |
+ // it must not have updated to be unlocked in time - unlock, wait 3 seconds, and try again |
|
| 1162 |
+ cmd := d.command("swarm", "unlock")
|
|
| 1163 |
+ cmd.Stdin = bytes.NewBufferString(unlockKey) |
|
| 1164 |
+ out, err := cmd.CombinedOutput() |
|
| 1165 |
+ c.Assert(err, checker.IsNil, check.Commentf("out: %v", string(out)))
|
|
| 1166 |
+ |
|
| 1167 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1168 |
+ |
|
| 1169 |
+ time.Sleep(3 * time.Second) |
|
| 1170 |
+ c.Assert(d.Restart(), checker.IsNil) |
|
| 1171 |
+ status = getNodeStatus(c, d) |
|
| 1172 |
+ } |
|
| 1173 |
+ c.Assert(getNodeStatus(c, d), checker.Equals, swarm.LocalNodeStateActive) |
|
| 1174 |
+ } |
|
| 1175 |
+} |
|
| 1176 |
+ |
|
| 1032 | 1177 |
func (s *DockerSwarmSuite) TestExtraHosts(c *check.C) {
|
| 1033 | 1178 |
d := s.AddDaemon(c, true, true) |
| 1034 | 1179 |
|