github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/role_manager_test.go (about) 1 package manager 2 3 import ( 4 "errors" 5 "testing" 6 7 "github.com/docker/swarmkit/api" 8 cautils "github.com/docker/swarmkit/ca/testutils" 9 raftutils "github.com/docker/swarmkit/manager/state/raft/testutils" 10 "github.com/docker/swarmkit/manager/state/store" 11 "github.com/docker/swarmkit/testutils" 12 "github.com/stretchr/testify/require" 13 ) 14 15 // While roleManager is running, if a node is demoted, it is removed from the raft cluster. If a node is 16 // promoted, it is not added to the cluster but its observed role will change to manager. 17 func TestRoleManagerRemovesDemotedNodesAndAddsPromotedNodes(t *testing.T) { 18 t.Parallel() 19 20 tc := cautils.NewTestCA(t) 21 defer tc.Stop() 22 23 nodes, fc := raftutils.NewRaftCluster(t, tc) 24 defer raftutils.TeardownCluster(nodes) 25 26 // nodes is not a list, but a map. The IDs are 1, 2, 3 27 require.Len(t, nodes[1].GetMemberlist(), 3) 28 29 // create node objects in the memory store 30 for _, node := range nodes { 31 s := raftutils.Leader(nodes).MemoryStore() 32 // Create a new node object 33 require.NoError(t, s.Update(func(tx store.Tx) error { 34 return store.CreateNode(tx, &api.Node{ 35 Role: api.NodeRoleManager, 36 ID: node.SecurityConfig.ClientTLSCreds.NodeID(), 37 Spec: api.NodeSpec{ 38 DesiredRole: api.NodeRoleManager, 39 Membership: api.NodeMembershipAccepted, 40 Availability: api.NodeAvailabilityActive, 41 }, 42 }) 43 })) 44 } 45 46 lead := raftutils.Leader(nodes) 47 var nonLead *raftutils.TestNode 48 for _, n := range nodes { 49 if n != lead { 50 nonLead = n 51 break 52 } 53 } 54 rm := newRoleManager(lead.MemoryStore(), lead.Node) 55 rm.clocksource = fc 56 go rm.Run(tc.Context) 57 defer rm.Stop() 58 59 // demote the node 60 require.NoError(t, lead.MemoryStore().Update(func(tx store.Tx) error { 61 n := store.GetNode(tx, nonLead.SecurityConfig.ClientTLSCreds.NodeID()) 62 n.Spec.DesiredRole = api.NodeRoleWorker 63 return store.UpdateNode(tx, n) 64 })) 65 require.NoError(t, testutils.PollFuncWithTimeout(fc, func() error { 66 memberlist := lead.GetMemberlist() 67 if len(memberlist) != 2 { 68 return errors.New("raft node hasn't been removed yet") 69 } 70 for _, m := range memberlist { 71 if m.NodeID == nonLead.SecurityConfig.ClientTLSCreds.NodeID() { 72 return errors.New("wrong member was removed") 73 } 74 } 75 // use Update just because it returns an error 76 return lead.MemoryStore().Update(func(tx store.Tx) error { 77 if n := store.GetNode(tx, nonLead.SecurityConfig.ClientTLSCreds.NodeID()); n.Role != api.NodeRoleWorker { 78 return errors.New("raft node hasn't been marked as a worker yet") 79 } 80 return nil 81 }) 82 }, roleReconcileInterval/2)) 83 84 // now promote the node 85 require.NoError(t, lead.MemoryStore().Update(func(tx store.Tx) error { 86 n := store.GetNode(tx, nonLead.SecurityConfig.ClientTLSCreds.NodeID()) 87 n.Spec.DesiredRole = api.NodeRoleManager 88 return store.UpdateNode(tx, n) 89 })) 90 require.NoError(t, testutils.PollFuncWithTimeout(fc, func() error { 91 if len(lead.GetMemberlist()) != 2 { 92 return errors.New("raft nodes in membership should not have changed") 93 } 94 // use Update just because it returns an error 95 return lead.MemoryStore().Update(func(tx store.Tx) error { 96 if n := store.GetNode(tx, nonLead.SecurityConfig.ClientTLSCreds.NodeID()); n.Role != api.NodeRoleManager { 97 return errors.New("raft node hasn't been marked as a manager yet") 98 } 99 return nil 100 }) 101 }, roleReconcileInterval/2)) 102 } 103 104 // If a node was demoted before the roleManager starts up, roleManger will remove 105 // the node from the cluster membership. 106 func TestRoleManagerRemovesDemotedNodesOnStartup(t *testing.T) { 107 t.Parallel() 108 109 tc := cautils.NewTestCA(t) 110 defer tc.Stop() 111 112 nodes, fc := raftutils.NewRaftCluster(t, tc) 113 defer raftutils.TeardownCluster(nodes) 114 115 // nodes is not a list, but a map. The IDs are 1, 2, 3 116 require.Len(t, nodes[1].GetMemberlist(), 3) 117 118 // create node objects in the memory store 119 for i, node := range nodes { 120 s := raftutils.Leader(nodes).MemoryStore() 121 desired := api.NodeRoleManager 122 if i == 3 { 123 desired = api.NodeRoleWorker 124 } 125 // Create a new node object 126 require.NoError(t, s.Update(func(tx store.Tx) error { 127 return store.CreateNode(tx, &api.Node{ 128 Role: api.NodeRoleManager, 129 ID: node.SecurityConfig.ClientTLSCreds.NodeID(), 130 Spec: api.NodeSpec{ 131 DesiredRole: desired, 132 Membership: api.NodeMembershipAccepted, 133 Availability: api.NodeAvailabilityActive, 134 }, 135 }) 136 })) 137 } 138 demoted := nodes[3] 139 140 lead := raftutils.Leader(nodes) 141 rm := newRoleManager(lead.MemoryStore(), lead.Node) 142 rm.clocksource = fc 143 go rm.Run(tc.Context) 144 defer rm.Stop() 145 146 require.NoError(t, testutils.PollFuncWithTimeout(fc, func() error { 147 memberlist := lead.GetMemberlist() 148 if len(memberlist) != 2 { 149 return errors.New("raft node hasn't been removed yet") 150 } 151 for _, m := range memberlist { 152 if m.NodeID == demoted.SecurityConfig.ClientTLSCreds.NodeID() { 153 return errors.New("wrong member was removed") 154 } 155 } 156 // use Update just because it returns an error 157 return lead.MemoryStore().Update(func(tx store.Tx) error { 158 if n := store.GetNode(tx, demoted.SecurityConfig.ClientTLSCreds.NodeID()); n.Role != api.NodeRoleWorker { 159 return errors.New("raft node hasn't been marked as a worker yet") 160 } 161 return nil 162 }) 163 }, roleReconcileInterval/2)) 164 } 165 166 // While roleManager is running, if a node is deleted, it is removed from the raft cluster. 167 func TestRoleManagerRemovesDeletedNodes(t *testing.T) { 168 t.Parallel() 169 170 tc := cautils.NewTestCA(t) 171 defer tc.Stop() 172 173 nodes, fc := raftutils.NewRaftCluster(t, tc) 174 defer raftutils.TeardownCluster(nodes) 175 176 // nodes is not a list, but a map. The IDs are 1, 2, 3 177 require.Len(t, nodes[1].GetMemberlist(), 3) 178 179 // create node objects in the memory store 180 for _, node := range nodes { 181 s := raftutils.Leader(nodes).MemoryStore() 182 // Create a new node object 183 require.NoError(t, s.Update(func(tx store.Tx) error { 184 return store.CreateNode(tx, &api.Node{ 185 Role: api.NodeRoleManager, 186 ID: node.SecurityConfig.ClientTLSCreds.NodeID(), 187 Spec: api.NodeSpec{ 188 DesiredRole: api.NodeRoleManager, 189 Membership: api.NodeMembershipAccepted, 190 Availability: api.NodeAvailabilityActive, 191 }, 192 }) 193 })) 194 } 195 196 lead := raftutils.Leader(nodes) 197 var nonLead *raftutils.TestNode 198 for _, n := range nodes { 199 if n != lead { 200 nonLead = n 201 break 202 } 203 } 204 rm := newRoleManager(lead.MemoryStore(), lead.Node) 205 rm.clocksource = fc 206 go rm.Run(tc.Context) 207 defer rm.Stop() 208 209 // delete the node 210 require.NoError(t, lead.MemoryStore().Update(func(tx store.Tx) error { 211 return store.DeleteNode(tx, nonLead.SecurityConfig.ClientTLSCreds.NodeID()) 212 })) 213 require.NoError(t, testutils.PollFuncWithTimeout(fc, func() error { 214 memberlist := lead.GetMemberlist() 215 if len(memberlist) != 2 { 216 return errors.New("raft node hasn't been removed yet") 217 } 218 for _, m := range memberlist { 219 if m.NodeID == nonLead.SecurityConfig.ClientTLSCreds.NodeID() { 220 return errors.New("wrong member was removed") 221 } 222 } 223 return nil 224 }, roleReconcileInterval/2)) 225 226 } 227 228 // If a node was removed before the roleManager starts up, roleManger will remove 229 // the node from the cluster membership. 230 func TestRoleManagerRemovesDeletedNodesOnStartup(t *testing.T) { 231 t.Parallel() 232 233 tc := cautils.NewTestCA(t) 234 defer tc.Stop() 235 236 nodes, fc := raftutils.NewRaftCluster(t, tc) 237 defer raftutils.TeardownCluster(nodes) 238 239 // nodes is not a list, but a map. The IDs are 1, 2, 3 240 require.Len(t, nodes[1].GetMemberlist(), 3) 241 242 // create node objects in the memory store 243 for i, node := range nodes { 244 s := raftutils.Leader(nodes).MemoryStore() 245 if i == 3 { 246 continue 247 } 248 // Create a new node object 249 require.NoError(t, s.Update(func(tx store.Tx) error { 250 return store.CreateNode(tx, &api.Node{ 251 Role: api.NodeRoleManager, 252 ID: node.SecurityConfig.ClientTLSCreds.NodeID(), 253 Spec: api.NodeSpec{ 254 DesiredRole: api.NodeRoleManager, 255 Membership: api.NodeMembershipAccepted, 256 Availability: api.NodeAvailabilityActive, 257 }, 258 }) 259 })) 260 } 261 262 lead := raftutils.Leader(nodes) 263 rm := newRoleManager(lead.MemoryStore(), lead.Node) 264 rm.clocksource = fc 265 go rm.Run(tc.Context) 266 defer rm.Stop() 267 268 require.NoError(t, testutils.PollFuncWithTimeout(fc, func() error { 269 memberlist := lead.GetMemberlist() 270 if len(memberlist) != 2 { 271 return errors.New("raft node hasn't been removed yet") 272 } 273 for _, m := range memberlist { 274 if m.NodeID == nodes[3].SecurityConfig.ClientTLSCreds.NodeID() { 275 return errors.New("wrong member was removed") 276 } 277 } 278 return nil 279 }, roleReconcileInterval/2)) 280 }