github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/watchapi/watch_test.go (about) 1 package watchapi 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/docker/swarmkit/api" 8 "github.com/docker/swarmkit/manager/state/store" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestWatch(t *testing.T) { 14 ts := newTestServer(t) 15 defer ts.Stop() 16 17 ctx := context.Background() 18 19 // Watch for node creates 20 watch, err := ts.Client.Watch(ctx, &api.WatchRequest{ 21 Entries: []*api.WatchRequest_WatchEntry{ 22 { 23 Kind: "node", 24 Action: api.WatchActionKindCreate, 25 }, 26 }, 27 }) 28 assert.NoError(t, err) 29 30 // Should receive an initial message that indicates the watch is ready 31 msg, err := watch.Recv() 32 assert.NoError(t, err) 33 assert.Equal(t, &api.WatchMessage{}, msg) 34 35 createNode(t, ts, "id1", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 36 msg, err = watch.Recv() 37 assert.NoError(t, err) 38 assert.Equal(t, api.WatchActionKindCreate, msg.Events[0].Action) 39 require.NotNil(t, msg.Events[0].Object.GetNode()) 40 assert.Equal(t, "id1", msg.Events[0].Object.GetNode().ID) 41 42 watch.CloseSend() 43 44 // Watch for node creates that match a name prefix and a custom index, or 45 // are managers 46 watch, err = ts.Client.Watch(ctx, &api.WatchRequest{ 47 Entries: []*api.WatchRequest_WatchEntry{ 48 { 49 Kind: "node", 50 Action: api.WatchActionKindCreate, 51 Filters: []*api.SelectBy{ 52 { 53 By: &api.SelectBy_NamePrefix{ 54 NamePrefix: "east", 55 }, 56 }, 57 { 58 By: &api.SelectBy_Custom{ 59 Custom: &api.SelectByCustom{ 60 Index: "myindex", 61 Value: "myval", 62 }, 63 }, 64 }, 65 }, 66 }, 67 { 68 Kind: "node", 69 Action: api.WatchActionKindCreate, 70 Filters: []*api.SelectBy{ 71 { 72 By: &api.SelectBy_Role{ 73 Role: api.NodeRoleManager, 74 }, 75 }, 76 }, 77 }, 78 }, 79 }) 80 assert.NoError(t, err) 81 82 // Should receive an initial message that indicates the watch is ready 83 msg, err = watch.Recv() 84 assert.NoError(t, err) 85 assert.Equal(t, &api.WatchMessage{}, msg) 86 87 createNode(t, ts, "id2", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 88 msg, err = watch.Recv() 89 assert.NoError(t, err) 90 assert.Equal(t, api.WatchActionKindCreate, msg.Events[0].Action) 91 require.NotNil(t, msg.Events[0].Object.GetNode()) 92 assert.Equal(t, "id2", msg.Events[0].Object.GetNode().ID) 93 94 // Shouldn't be seen by the watch 95 createNode(t, ts, "id3", api.NodeRoleWorker, api.NodeMembershipAccepted, api.NodeStatus_READY) 96 97 // Shouldn't be seen either - no hostname 98 node := &api.Node{ 99 ID: "id4", 100 Spec: api.NodeSpec{ 101 Annotations: api.Annotations{ 102 Indices: []api.IndexEntry{ 103 {Key: "myindex", Val: "myval"}, 104 }, 105 }, 106 }, 107 Role: api.NodeRoleWorker, 108 } 109 err = ts.Store.Update(func(tx store.Tx) error { 110 return store.CreateNode(tx, node) 111 }) 112 assert.NoError(t, err) 113 114 // Shouldn't be seen either - hostname doesn't match filter 115 node = &api.Node{ 116 ID: "id5", 117 Description: &api.NodeDescription{ 118 Hostname: "west-40", 119 }, 120 Spec: api.NodeSpec{ 121 Annotations: api.Annotations{ 122 Indices: []api.IndexEntry{ 123 {Key: "myindex", Val: "myval"}, 124 }, 125 }, 126 }, 127 Role: api.NodeRoleWorker, 128 } 129 err = ts.Store.Update(func(tx store.Tx) error { 130 return store.CreateNode(tx, node) 131 }) 132 assert.NoError(t, err) 133 134 // This one should be seen 135 node = &api.Node{ 136 ID: "id6", 137 Description: &api.NodeDescription{ 138 Hostname: "east-95", 139 }, 140 Spec: api.NodeSpec{ 141 Annotations: api.Annotations{ 142 Indices: []api.IndexEntry{ 143 {Key: "myindex", Val: "myval"}, 144 }, 145 }, 146 }, 147 Role: api.NodeRoleWorker, 148 } 149 err = ts.Store.Update(func(tx store.Tx) error { 150 return store.CreateNode(tx, node) 151 }) 152 assert.NoError(t, err) 153 154 msg, err = watch.Recv() 155 assert.NoError(t, err) 156 assert.Equal(t, api.WatchActionKindCreate, msg.Events[0].Action) 157 require.NotNil(t, msg.Events[0].Object.GetNode()) 158 assert.Equal(t, "id6", msg.Events[0].Object.GetNode().ID) 159 160 watch.CloseSend() 161 } 162 163 func TestWatchMultipleActions(t *testing.T) { 164 ts := newTestServer(t) 165 defer ts.Stop() 166 167 ctx := context.Background() 168 169 // Watch for node creates 170 watch, err := ts.Client.Watch(ctx, &api.WatchRequest{ 171 Entries: []*api.WatchRequest_WatchEntry{ 172 { 173 Kind: "node", 174 Action: api.WatchActionKindCreate | api.WatchActionKindRemove, 175 }, 176 }, 177 }) 178 assert.NoError(t, err) 179 180 // Should receive an initial message that indicates the watch is ready 181 msg, err := watch.Recv() 182 assert.NoError(t, err) 183 assert.Equal(t, &api.WatchMessage{}, msg) 184 185 createNode(t, ts, "id1", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 186 msg, err = watch.Recv() 187 assert.NoError(t, err) 188 assert.Equal(t, api.WatchActionKindCreate, msg.Events[0].Action) 189 require.NotNil(t, msg.Events[0].Object.GetNode()) 190 assert.Equal(t, "id1", msg.Events[0].Object.GetNode().ID) 191 192 // Update should not be seen 193 err = ts.Store.Update(func(tx store.Tx) error { 194 node := store.GetNode(tx, "id1") 195 require.NotNil(t, node) 196 node.Role = api.NodeRoleWorker 197 return store.UpdateNode(tx, node) 198 }) 199 assert.NoError(t, err) 200 201 // Delete should be seen 202 err = ts.Store.Update(func(tx store.Tx) error { 203 return store.DeleteNode(tx, "id1") 204 }) 205 assert.NoError(t, err) 206 msg, err = watch.Recv() 207 assert.NoError(t, err) 208 assert.Equal(t, api.WatchActionKindRemove, msg.Events[0].Action) 209 require.NotNil(t, msg.Events[0].Object.GetNode()) 210 assert.Equal(t, "id1", msg.Events[0].Object.GetNode().ID) 211 212 watch.CloseSend() 213 } 214 215 func TestWatchIncludeOldObject(t *testing.T) { 216 ts := newTestServer(t) 217 defer ts.Stop() 218 219 ctx := context.Background() 220 221 // Watch for node updates 222 watch, err := ts.Client.Watch(ctx, &api.WatchRequest{ 223 Entries: []*api.WatchRequest_WatchEntry{ 224 { 225 Kind: "node", 226 Action: api.WatchActionKindUpdate, 227 }, 228 }, 229 IncludeOldObject: true, 230 }) 231 assert.NoError(t, err) 232 233 // Should receive an initial message that indicates the watch is ready 234 msg, err := watch.Recv() 235 assert.NoError(t, err) 236 assert.Equal(t, &api.WatchMessage{}, msg) 237 238 createNode(t, ts, "id1", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 239 240 err = ts.Store.Update(func(tx store.Tx) error { 241 node := store.GetNode(tx, "id1") 242 require.NotNil(t, node) 243 node.Role = api.NodeRoleWorker 244 return store.UpdateNode(tx, node) 245 }) 246 assert.NoError(t, err) 247 248 msg, err = watch.Recv() 249 assert.NoError(t, err) 250 assert.Equal(t, api.WatchActionKindUpdate, msg.Events[0].Action) 251 require.NotNil(t, msg.Events[0].Object.GetNode()) 252 assert.Equal(t, "id1", msg.Events[0].Object.GetNode().ID) 253 assert.Equal(t, api.NodeRoleWorker, msg.Events[0].Object.GetNode().Role) 254 require.NotNil(t, msg.Events[0].OldObject.GetNode()) 255 assert.Equal(t, "id1", msg.Events[0].OldObject.GetNode().ID) 256 assert.Equal(t, api.NodeRoleManager, msg.Events[0].OldObject.GetNode().Role) 257 258 watch.CloseSend() 259 } 260 261 func TestWatchResumeFrom(t *testing.T) { 262 ts := newTestServer(t) 263 defer ts.Stop() 264 265 ctx := context.Background() 266 267 createNode(t, ts, "id1", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 268 node2 := createNode(t, ts, "id2", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 269 270 // Watch for node creates, starting from after the first node creation. 271 watch, err := ts.Client.Watch(ctx, &api.WatchRequest{ 272 Entries: []*api.WatchRequest_WatchEntry{ 273 { 274 Kind: "node", 275 Action: api.WatchActionKindCreate, 276 }, 277 }, 278 ResumeFrom: &node2.Meta.Version, 279 }) 280 assert.NoError(t, err) 281 282 // Should receive an initial message that indicates the watch is ready 283 msg, err := watch.Recv() 284 assert.NoError(t, err) 285 assert.Equal(t, &api.WatchMessage{}, msg) 286 287 msg, err = watch.Recv() 288 assert.NoError(t, err) 289 assert.Equal(t, api.WatchActionKindCreate, msg.Events[0].Action) 290 require.NotNil(t, msg.Events[0].Object.GetNode()) 291 assert.Equal(t, "id2", msg.Events[0].Object.GetNode().ID) 292 assert.Equal(t, node2.Meta.Version.Index+3, msg.Version.Index) 293 294 // Create a new node 295 node3 := createNode(t, ts, "id3", api.NodeRoleManager, api.NodeMembershipAccepted, api.NodeStatus_READY) 296 297 msg, err = watch.Recv() 298 assert.NoError(t, err) 299 assert.Equal(t, api.WatchActionKindCreate, msg.Events[0].Action) 300 require.NotNil(t, msg.Events[0].Object.GetNode()) 301 assert.Equal(t, "id3", msg.Events[0].Object.GetNode().ID) 302 assert.Equal(t, node3.Meta.Version.Index+3, msg.Version.Index) 303 304 watch.CloseSend() 305 }