github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/orchestrator/replicated/drain_test.go (about) 1 package replicated 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/docker/swarmkit/api" 8 "github.com/docker/swarmkit/manager/orchestrator/testutils" 9 "github.com/docker/swarmkit/manager/state" 10 "github.com/docker/swarmkit/manager/state/store" 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func TestDrain(t *testing.T) { 15 ctx := context.Background() 16 initialService := &api.Service{ 17 ID: "id1", 18 Spec: api.ServiceSpec{ 19 Annotations: api.Annotations{ 20 Name: "name1", 21 }, 22 Task: api.TaskSpec{ 23 Runtime: &api.TaskSpec_Container{ 24 Container: &api.ContainerSpec{}, 25 }, 26 Restart: &api.RestartPolicy{ 27 Condition: api.RestartOnNone, 28 }, 29 }, 30 Mode: &api.ServiceSpec_Replicated{ 31 Replicated: &api.ReplicatedService{ 32 Replicas: 6, 33 }, 34 }, 35 }, 36 } 37 initialNodeSet := []*api.Node{ 38 { 39 ID: "id1", 40 Spec: api.NodeSpec{ 41 Annotations: api.Annotations{ 42 Name: "name1", 43 }, 44 Availability: api.NodeAvailabilityActive, 45 }, 46 Status: api.NodeStatus{ 47 State: api.NodeStatus_READY, 48 }, 49 }, 50 { 51 ID: "id2", 52 Spec: api.NodeSpec{ 53 Annotations: api.Annotations{ 54 Name: "name2", 55 }, 56 Availability: api.NodeAvailabilityActive, 57 }, 58 Status: api.NodeStatus{ 59 State: api.NodeStatus_DOWN, 60 }, 61 }, 62 // We should NOT kick out tasks on UNKNOWN nodes. 63 { 64 ID: "id3", 65 Spec: api.NodeSpec{ 66 Annotations: api.Annotations{ 67 Name: "name3", 68 }, 69 Availability: api.NodeAvailabilityActive, 70 }, 71 Status: api.NodeStatus{ 72 State: api.NodeStatus_UNKNOWN, 73 }, 74 }, 75 { 76 ID: "id4", 77 Spec: api.NodeSpec{ 78 Annotations: api.Annotations{ 79 Name: "name4", 80 }, 81 Availability: api.NodeAvailabilityPause, 82 }, 83 Status: api.NodeStatus{ 84 State: api.NodeStatus_READY, 85 }, 86 }, 87 { 88 ID: "id5", 89 Spec: api.NodeSpec{ 90 Annotations: api.Annotations{ 91 Name: "name5", 92 }, 93 Availability: api.NodeAvailabilityDrain, 94 }, 95 Status: api.NodeStatus{ 96 State: api.NodeStatus_READY, 97 }, 98 }, 99 } 100 101 initialTaskSet := []*api.Task{ 102 // Task not assigned to any node 103 { 104 ID: "id0", 105 DesiredState: api.TaskStateRunning, 106 Spec: initialService.Spec.Task, 107 Status: api.TaskStatus{ 108 State: api.TaskStateNew, 109 }, 110 Slot: 1, 111 ServiceAnnotations: api.Annotations{ 112 Name: "name0", 113 }, 114 ServiceID: "id1", 115 }, 116 // Tasks assigned to the nodes defined above 117 { 118 ID: "id1", 119 DesiredState: api.TaskStateRunning, 120 Spec: initialService.Spec.Task, 121 Status: api.TaskStatus{ 122 State: api.TaskStateNew, 123 }, 124 Slot: 2, 125 ServiceAnnotations: api.Annotations{ 126 Name: "name1", 127 }, 128 ServiceID: "id1", 129 NodeID: "id1", 130 }, 131 { 132 ID: "id2", 133 DesiredState: api.TaskStateRunning, 134 Spec: initialService.Spec.Task, 135 Status: api.TaskStatus{ 136 State: api.TaskStateNew, 137 }, 138 Slot: 3, 139 ServiceAnnotations: api.Annotations{ 140 Name: "name2", 141 }, 142 ServiceID: "id1", 143 NodeID: "id2", 144 }, 145 { 146 ID: "id3", 147 DesiredState: api.TaskStateRunning, 148 Spec: initialService.Spec.Task, 149 Status: api.TaskStatus{ 150 State: api.TaskStateNew, 151 }, 152 Slot: 4, 153 ServiceAnnotations: api.Annotations{ 154 Name: "name3", 155 }, 156 ServiceID: "id1", 157 NodeID: "id3", 158 }, 159 { 160 ID: "id4", 161 DesiredState: api.TaskStateRunning, 162 Spec: initialService.Spec.Task, 163 Status: api.TaskStatus{ 164 State: api.TaskStateNew, 165 }, 166 Slot: 5, 167 ServiceAnnotations: api.Annotations{ 168 Name: "name4", 169 }, 170 ServiceID: "id1", 171 NodeID: "id4", 172 }, 173 { 174 ID: "id5", 175 DesiredState: api.TaskStateRunning, 176 Spec: initialService.Spec.Task, 177 Status: api.TaskStatus{ 178 State: api.TaskStateNew, 179 }, 180 Slot: 6, 181 ServiceAnnotations: api.Annotations{ 182 Name: "name5", 183 }, 184 ServiceID: "id1", 185 NodeID: "id5", 186 }, 187 } 188 189 s := store.NewMemoryStore(nil) 190 assert.NotNil(t, s) 191 defer s.Close() 192 193 err := s.Update(func(tx store.Tx) error { 194 // Prepopulate service 195 assert.NoError(t, store.CreateService(tx, initialService)) 196 // Prepoulate nodes 197 for _, n := range initialNodeSet { 198 assert.NoError(t, store.CreateNode(tx, n)) 199 } 200 201 // Prepopulate tasks 202 for _, task := range initialTaskSet { 203 assert.NoError(t, store.CreateTask(tx, task)) 204 } 205 return nil 206 }) 207 assert.NoError(t, err) 208 209 watch, cancel := state.Watch(s.WatchQueue(), api.EventUpdateTask{}) 210 defer cancel() 211 212 orchestrator := NewReplicatedOrchestrator(s) 213 defer orchestrator.Stop() 214 215 go func() { 216 assert.NoError(t, orchestrator.Run(ctx)) 217 }() 218 219 // id2 and id5 should be killed immediately 220 deletion1 := testutils.WatchShutdownTask(t, watch) 221 deletion2 := testutils.WatchShutdownTask(t, watch) 222 223 assert.Regexp(t, "id(2|5)", deletion1.ID) 224 assert.Regexp(t, "id(2|5)", deletion1.NodeID) 225 assert.Regexp(t, "id(2|5)", deletion2.ID) 226 assert.Regexp(t, "id(2|5)", deletion2.NodeID) 227 228 // Create a new task, assigned to node id2 229 err = s.Update(func(tx store.Tx) error { 230 task := initialTaskSet[2].Copy() 231 task.ID = "newtask" 232 task.NodeID = "id2" 233 assert.NoError(t, store.CreateTask(tx, task)) 234 return nil 235 }) 236 assert.NoError(t, err) 237 238 deletion3 := testutils.WatchShutdownTask(t, watch) 239 assert.Equal(t, "newtask", deletion3.ID) 240 assert.Equal(t, "id2", deletion3.NodeID) 241 242 // Set node id4 to the DRAINED state 243 err = s.Update(func(tx store.Tx) error { 244 n := initialNodeSet[3].Copy() 245 n.Spec.Availability = api.NodeAvailabilityDrain 246 assert.NoError(t, store.UpdateNode(tx, n)) 247 return nil 248 }) 249 assert.NoError(t, err) 250 251 deletion4 := testutils.WatchShutdownTask(t, watch) 252 assert.Equal(t, "id4", deletion4.ID) 253 assert.Equal(t, "id4", deletion4.NodeID) 254 255 // Delete node id1 256 err = s.Update(func(tx store.Tx) error { 257 assert.NoError(t, store.DeleteNode(tx, "id1")) 258 return nil 259 }) 260 assert.NoError(t, err) 261 262 deletion5 := testutils.WatchShutdownTask(t, watch) 263 assert.Equal(t, "id1", deletion5.ID) 264 assert.Equal(t, "id1", deletion5.NodeID) 265 }