Browse code

waitAndAssert -> poll.WaitOn

go get -d golang.org/x/tools/cmd/eg && \
dir=$(go env GOPATH)/src/golang.org/x/tools && \
git -C "$dir" fetch https://github.com/tiborvass/tools handle-variadic && \
git -C "$dir" checkout 61a94b82347c29b3289e83190aa3dda74d47abbb && \
go install golang.org/x/tools/cmd/eg

eg -w -t template.waitAndAssert.go ./integration-cli 2>&1 \
| awk '{print $2}' | while read file; do
# removing vendor/ in import paths
# not sure why eg adds them
sed -E -i 's#^([\t]+").*/vendor/([^"]+)#\1\2#g' "$file"
sed -E -i 's#\.\(eg_compareFunc\)##g' "$file"
goimports -w "$file"
done

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit ac2f24e72a312da8836480f80cc191c44db7d199)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Tibor Vass authored on 2019/08/27 00:51:40
Showing 12 changed files
... ...
@@ -18,6 +18,7 @@ import (
18 18
 	"github.com/docker/docker/integration-cli/checker"
19 19
 	"github.com/docker/docker/internal/test/request"
20 20
 	"gotest.tools/assert"
21
+	"gotest.tools/poll"
21 22
 )
22 23
 
23 24
 // Regression test for #9414
... ...
@@ -229,13 +230,13 @@ func (s *DockerSuite) TestExecStateCleanup(c *testing.T) {
229 229
 	startExec(c, id, http.StatusOK)
230 230
 	waitForExec(c, id)
231 231
 
232
-	waitAndAssert(c, 5*time.Second, checkReadDir, checker.Equals, len(fi))
232
+	poll.WaitOn(c, pollCheck(c, checkReadDir, checker.Equals(len(fi))), poll.WithTimeout(5*time.Second))
233 233
 
234 234
 	id = createExecCmd(c, name, "invalid")
235 235
 	startExec(c, id, http.StatusBadRequest)
236 236
 	waitForExec(c, id)
237 237
 
238
-	waitAndAssert(c, 5*time.Second, checkReadDir, checker.Equals, len(fi))
238
+	poll.WaitOn(c, pollCheck(c, checkReadDir, checker.Equals(len(fi))), poll.WithTimeout(5*time.Second))
239 239
 
240 240
 	dockerCmd(c, "stop", name)
241 241
 	_, err = os.Stat(stateDir)
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/docker/docker/integration-cli/checker"
12 12
 	"github.com/docker/docker/integration-cli/daemon"
13 13
 	"gotest.tools/assert"
14
+	"gotest.tools/poll"
14 15
 )
15 16
 
16 17
 func (s *DockerSwarmSuite) TestAPISwarmListNodes(c *testing.T) {
... ...
@@ -84,16 +85,16 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *testing.T) {
84 84
 	instances := 2
85 85
 	id := d1.CreateService(c, simpleTestService, setInstances(instances))
86 86
 
87
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0)
88
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0)
89
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
87
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
88
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
89
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
90 90
 
91 91
 	// drain d2, all containers should move to d1
92 92
 	d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
93 93
 		n.Spec.Availability = swarm.NodeAvailabilityDrain
94 94
 	})
95
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
96
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0)
95
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
96
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
97 97
 
98 98
 	// set d2 back to active
99 99
 	d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
... ...
@@ -102,15 +103,15 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *testing.T) {
102 102
 
103 103
 	instances = 1
104 104
 	d1.UpdateService(c, d1.GetService(c, id), setInstances(instances))
105
-	waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
105
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout*2))
106 106
 
107 107
 	instances = 2
108 108
 	d1.UpdateService(c, d1.GetService(c, id), setInstances(instances))
109 109
 
110 110
 	// drained node first so we don't get any old containers
111
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0)
112
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0)
113
-	waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
111
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
112
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
113
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout*2))
114 114
 
115 115
 	d2ContainerCount := len(d2.ActiveContainers(c))
116 116
 
... ...
@@ -121,7 +122,7 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *testing.T) {
121 121
 
122 122
 	instances = 4
123 123
 	d1.UpdateService(c, d1.GetService(c, id), setInstances(instances))
124
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances-d2ContainerCount)
125
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, d2ContainerCount)
124
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances-d2ContainerCount)), poll.WithTimeout(defaultReconciliationTimeout))
125
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(d2ContainerCount)), poll.WithTimeout(defaultReconciliationTimeout))
126 126
 
127 127
 }
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	"golang.org/x/sys/unix"
21 21
 	"gotest.tools/assert"
22 22
 	"gotest.tools/icmd"
23
+	"gotest.tools/poll"
23 24
 )
24 25
 
25 26
 func setPortConfig(portConfig []swarm.PortConfig) testdaemon.ServiceConstructor {
... ...
@@ -37,7 +38,7 @@ func (s *DockerSwarmSuite) TestAPIServiceUpdatePort(c *testing.T) {
37 37
 	// Create a service with a port mapping of 8080:8081.
38 38
 	portConfig := []swarm.PortConfig{{TargetPort: 8081, PublishedPort: 8080}}
39 39
 	serviceID := d.CreateService(c, simpleTestService, setInstances(1), setPortConfig(portConfig))
40
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
40
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
41 41
 
42 42
 	// Update the service: changed the port mapping from 8080:8081 to 8082:8083.
43 43
 	updatedPortConfig := []swarm.PortConfig{{TargetPort: 8083, PublishedPort: 8082}}
... ...
@@ -65,7 +66,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *testing.T) {
65 65
 
66 66
 	instances := 2
67 67
 	id := d.CreateService(c, simpleTestService, setInstances(instances))
68
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
68
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
69 69
 
70 70
 	client := d.NewClientT(c)
71 71
 	defer client.Close()
... ...
@@ -87,10 +88,10 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *testing.T) {
87 87
 	service := d.GetService(c, id)
88 88
 	instances = 5
89 89
 	d.UpdateService(c, service, setInstances(instances))
90
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
90
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
91 91
 
92 92
 	d.RemoveService(c, service.ID)
93
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 0)
93
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
94 94
 }
95 95
 
96 96
 func (s *DockerSwarmSuite) TestAPISwarmServicesMultipleAgents(c *testing.T) {
... ...
@@ -103,21 +104,21 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesMultipleAgents(c *testing.T) {
103 103
 	instances := 9
104 104
 	id := d1.CreateService(c, simpleTestService, setInstances(instances))
105 105
 
106
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0)
107
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.GreaterThan, 0)
108
-	waitAndAssert(c, defaultReconciliationTimeout, d3.CheckActiveContainerCount, checker.GreaterThan, 0)
106
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
107
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
108
+	poll.WaitOn(c, pollCheck(c, d3.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
109 109
 
110
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
110
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
111 111
 
112 112
 	// reconciliation on d2 node down
113 113
 	d2.Stop(c)
114 114
 
115
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
115
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
116 116
 
117 117
 	// test downscaling
118 118
 	instances = 5
119 119
 	d1.UpdateService(c, d1.GetService(c, id), setInstances(instances))
120
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
120
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
121 121
 
122 122
 }
123 123
 
... ...
@@ -128,15 +129,15 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesCreateGlobal(c *testing.T) {
128 128
 
129 129
 	d1.CreateService(c, simpleTestService, setGlobalMode)
130 130
 
131
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, 1)
132
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1)
133
-	waitAndAssert(c, defaultReconciliationTimeout, d3.CheckActiveContainerCount, checker.Equals, 1)
131
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
132
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
133
+	poll.WaitOn(c, pollCheck(c, d3.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
134 134
 
135 135
 	d4 := s.AddDaemon(c, true, false)
136 136
 	d5 := s.AddDaemon(c, true, false)
137 137
 
138
-	waitAndAssert(c, defaultReconciliationTimeout, d4.CheckActiveContainerCount, checker.Equals, 1)
139
-	waitAndAssert(c, defaultReconciliationTimeout, d5.CheckActiveContainerCount, checker.Equals, 1)
138
+	poll.WaitOn(c, pollCheck(c, d4.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
139
+	poll.WaitOn(c, pollCheck(c, d5.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
140 140
 }
141 141
 
142 142
 func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) {
... ...
@@ -146,7 +147,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) {
146 146
 		daemons[i] = s.AddDaemon(c, true, i == 0)
147 147
 	}
148 148
 	// wait for nodes ready
149
-	waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount)
149
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second))
150 150
 
151 151
 	// service image at start
152 152
 	image1 := "busybox:latest"
... ...
@@ -166,24 +167,20 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) {
166 166
 	id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances))
167 167
 
168 168
 	// wait for tasks ready
169
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
170
-		map[string]int{image1: instances})
169
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
171 170
 
172 171
 	// issue service update
173 172
 	service := daemons[0].GetService(c, id)
174 173
 	daemons[0].UpdateService(c, service, setImage(image2))
175 174
 
176 175
 	// first batch
177
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
178
-		map[string]int{image1: instances - parallelism, image2: parallelism})
176
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout))
179 177
 
180 178
 	// 2nd batch
181
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
182
-		map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})
179
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout))
183 180
 
184 181
 	// 3nd batch
185
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
186
-		map[string]int{image2: instances})
182
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances})), poll.WithTimeout(defaultReconciliationTimeout))
187 183
 
188 184
 	// Roll back to the previous version. This uses the CLI because
189 185
 	// rollback used to be a client-side operation.
... ...
@@ -191,12 +188,11 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) {
191 191
 	assert.NilError(c, err, out)
192 192
 
193 193
 	// first batch
194
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
195
-		map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})
194
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})), poll.WithTimeout(defaultReconciliationTimeout))
196 195
 
197 196
 	// 2nd batch
198
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
199
-		map[string]int{image1: instances})
197
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
198
+
200 199
 }
201 200
 
202 201
 func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) {
... ...
@@ -223,7 +219,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) {
223 223
 
224 224
 	checkStartingTasks := func(expected int) []swarm.Task {
225 225
 		var startingTasks []swarm.Task
226
-		waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
226
+		poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
227 227
 			tasks := d.GetServiceTasks(c, id)
228 228
 			startingTasks = nil
229 229
 			for _, t := range tasks {
... ...
@@ -232,7 +228,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) {
232 232
 				}
233 233
 			}
234 234
 			return startingTasks, ""
235
-		}, checker.HasLen, expected)
235
+		}, checker.HasLen(expected)), poll.WithTimeout(defaultReconciliationTimeout))
236 236
 
237 237
 		return startingTasks
238 238
 	}
... ...
@@ -245,8 +241,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) {
245 245
 	}
246 246
 
247 247
 	// wait for tasks ready
248
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
249
-		map[string]int{image1: instances})
248
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
250 249
 
251 250
 	// issue service update
252 251
 	service := d.GetService(c, id)
... ...
@@ -257,42 +252,36 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) {
257 257
 	// The old tasks should be running, and the new ones should be starting.
258 258
 	startingTasks := checkStartingTasks(parallelism)
259 259
 
260
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
261
-		map[string]int{image1: instances})
260
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
262 261
 
263 262
 	// make it healthy
264 263
 	makeTasksHealthy(startingTasks)
265 264
 
266
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
267
-		map[string]int{image1: instances - parallelism, image2: parallelism})
265
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout))
268 266
 
269 267
 	// 2nd batch
270 268
 
271 269
 	// The old tasks should be running, and the new ones should be starting.
272 270
 	startingTasks = checkStartingTasks(parallelism)
273 271
 
274
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
275
-		map[string]int{image1: instances - parallelism, image2: parallelism})
272
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout))
276 273
 
277 274
 	// make it healthy
278 275
 	makeTasksHealthy(startingTasks)
279 276
 
280
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
281
-		map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})
277
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout))
282 278
 
283 279
 	// 3nd batch
284 280
 
285 281
 	// The old tasks should be running, and the new ones should be starting.
286 282
 	startingTasks = checkStartingTasks(1)
287 283
 
288
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
289
-		map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})
284
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout))
290 285
 
291 286
 	// make it healthy
292 287
 	makeTasksHealthy(startingTasks)
293 288
 
294
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
295
-		map[string]int{image2: instances})
289
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances})), poll.WithTimeout(defaultReconciliationTimeout))
296 290
 
297 291
 	// Roll back to the previous version. This uses the CLI because
298 292
 	// rollback is a client-side operation.
... ...
@@ -300,12 +289,11 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) {
300 300
 	assert.NilError(c, err, out)
301 301
 
302 302
 	// first batch
303
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
304
-		map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})
303
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})), poll.WithTimeout(defaultReconciliationTimeout))
305 304
 
306 305
 	// 2nd batch
307
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskImages, checker.DeepEquals,
308
-		map[string]int{image1: instances})
306
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
307
+
309 308
 }
310 309
 
311 310
 func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) {
... ...
@@ -315,7 +303,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) {
315 315
 		daemons[i] = s.AddDaemon(c, true, i == 0)
316 316
 	}
317 317
 	// wait for nodes ready
318
-	waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount)
318
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second))
319 319
 
320 320
 	// service image at start
321 321
 	image1 := "busybox:latest"
... ...
@@ -327,15 +315,14 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) {
327 327
 	id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances))
328 328
 
329 329
 	// wait for tasks ready
330
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
331
-		map[string]int{image1: instances})
330
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
332 331
 
333 332
 	// issue service update
334 333
 	service := daemons[0].GetService(c, id)
335 334
 	daemons[0].UpdateService(c, service, setImage(image2), setFailureAction(swarm.UpdateFailureActionPause), setMaxFailureRatio(0.25), setParallelism(1))
336 335
 
337 336
 	// should update 2 tasks and then pause
338
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceUpdateState(id), checker.Equals, swarm.UpdateStatePaused)
337
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceUpdateState(id), checker.Equals(swarm.UpdateStatePaused)), poll.WithTimeout(defaultReconciliationTimeout))
339 338
 	v, _ := daemons[0].CheckServiceRunningTasks(id)(c)
340 339
 	assert.Assert(c, v == instances-2)
341 340
 
... ...
@@ -344,8 +331,8 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) {
344 344
 	out, err := daemons[0].Cmd("service", "update", "--detach", "--rollback", id)
345 345
 	assert.NilError(c, err, out)
346 346
 
347
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckRunningTaskImages, checker.DeepEquals,
348
-		map[string]int{image1: instances})
347
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout))
348
+
349 349
 }
350 350
 
351 351
 func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *testing.T) {
... ...
@@ -355,14 +342,14 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *testing.T) {
355 355
 		daemons[i] = s.AddDaemon(c, true, i == 0)
356 356
 	}
357 357
 	// wait for nodes ready
358
-	waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount)
358
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second))
359 359
 
360 360
 	// create service
361 361
 	constraints := []string{"node.role==worker"}
362 362
 	instances := 3
363 363
 	id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
364 364
 	// wait for tasks ready
365
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances)
365
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
366 366
 	// validate tasks are running on worker nodes
367 367
 	tasks := daemons[0].GetServiceTasks(c, id)
368 368
 	for _, task := range tasks {
... ...
@@ -376,7 +363,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *testing.T) {
376 376
 	constraints = []string{"node.role!=worker"}
377 377
 	id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
378 378
 	// wait for tasks ready
379
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances)
379
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
380 380
 	tasks = daemons[0].GetServiceTasks(c, id)
381 381
 	// validate tasks are running on manager nodes
382 382
 	for _, task := range tasks {
... ...
@@ -390,7 +377,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *testing.T) {
390 390
 	constraints = []string{"node.role==nosuchrole"}
391 391
 	id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
392 392
 	// wait for tasks created
393
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances)
393
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
394 394
 	// let scheduler try
395 395
 	time.Sleep(250 * time.Millisecond)
396 396
 	// validate tasks are not assigned to any node
... ...
@@ -407,7 +394,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) {
407 407
 		daemons[i] = s.AddDaemon(c, true, i == 0)
408 408
 	}
409 409
 	// wait for nodes ready
410
-	waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount)
410
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second))
411 411
 	nodes := daemons[0].ListNodes(c)
412 412
 	assert.Equal(c, len(nodes), nodeCount)
413 413
 
... ...
@@ -430,7 +417,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) {
430 430
 	constraints := []string{"node.labels.security==high"}
431 431
 	id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
432 432
 	// wait for tasks ready
433
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances)
433
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
434 434
 	tasks := daemons[0].GetServiceTasks(c, id)
435 435
 	// validate all tasks are running on nodes[0]
436 436
 	for _, task := range tasks {
... ...
@@ -443,7 +430,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) {
443 443
 	constraints = []string{"node.labels.security!=high"}
444 444
 	id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
445 445
 	// wait for tasks ready
446
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances)
446
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
447 447
 	tasks = daemons[0].GetServiceTasks(c, id)
448 448
 	// validate all tasks are NOT running on nodes[0]
449 449
 	for _, task := range tasks {
... ...
@@ -455,7 +442,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) {
455 455
 	constraints = []string{"node.labels.security==medium"}
456 456
 	id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
457 457
 	// wait for tasks created
458
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances)
458
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
459 459
 	// let scheduler try
460 460
 	time.Sleep(250 * time.Millisecond)
461 461
 	tasks = daemons[0].GetServiceTasks(c, id)
... ...
@@ -473,7 +460,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) {
473 473
 	}
474 474
 	id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances))
475 475
 	// wait for tasks created
476
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceTasks(id), checker.Equals, instances)
476
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
477 477
 	// let scheduler try
478 478
 	time.Sleep(250 * time.Millisecond)
479 479
 	tasks = daemons[0].GetServiceTasks(c, id)
... ...
@@ -488,7 +475,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) {
488 488
 		}
489 489
 	})
490 490
 	// wait for tasks ready
491
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances)
491
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
492 492
 	tasks = daemons[0].GetServiceTasks(c, id)
493 493
 	for _, task := range tasks {
494 494
 		assert.Assert(c, task.NodeID == nodes[1].ID)
... ...
@@ -502,7 +489,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *testing.T) {
502 502
 		daemons[i] = s.AddDaemon(c, true, i == 0)
503 503
 	}
504 504
 	// wait for nodes ready
505
-	waitAndAssert(c, 5*time.Second, daemons[0].CheckNodeReadyCount, checker.Equals, nodeCount)
505
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second))
506 506
 	nodes := daemons[0].ListNodes(c)
507 507
 	assert.Equal(c, len(nodes), nodeCount)
508 508
 
... ...
@@ -525,7 +512,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *testing.T) {
525 525
 	prefs := []swarm.PlacementPreference{{Spread: &swarm.SpreadOver{SpreadDescriptor: "node.labels.rack"}}}
526 526
 	id := daemons[0].CreateService(c, simpleTestService, setPlacementPrefs(prefs), setInstances(instances))
527 527
 	// wait for tasks ready
528
-	waitAndAssert(c, defaultReconciliationTimeout, daemons[0].CheckServiceRunningTasks(id), checker.Equals, instances)
528
+	poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
529 529
 	tasks := daemons[0].GetServiceTasks(c, id)
530 530
 	// validate all tasks are running on nodes[0]
531 531
 	tasksOnNode := make(map[string]int)
... ...
@@ -550,7 +537,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *testing.T) {
550 550
 	instances := 9
551 551
 	d1.CreateService(c, simpleTestService, setInstances(instances))
552 552
 
553
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
553
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
554 554
 
555 555
 	getContainers := func() map[string]*daemon.Daemon {
556 556
 		m := make(map[string]*daemon.Daemon)
... ...
@@ -572,7 +559,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *testing.T) {
572 572
 	_, err := containers[toRemove].Cmd("stop", toRemove)
573 573
 	assert.NilError(c, err)
574 574
 
575
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
575
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
576 576
 
577 577
 	containers2 := getContainers()
578 578
 	assert.Assert(c, len(containers2) == instances)
... ...
@@ -598,7 +585,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *testing.T) {
598 598
 
599 599
 	time.Sleep(time.Second) // give some time to handle the signal
600 600
 
601
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
601
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
602 602
 
603 603
 	containers2 = getContainers()
604 604
 	assert.Assert(c, len(containers2) == instances)
... ...
@@ -30,6 +30,7 @@ import (
30 30
 	"github.com/pkg/errors"
31 31
 	"gotest.tools/assert"
32 32
 	is "gotest.tools/assert/cmp"
33
+	"gotest.tools/poll"
33 34
 )
34 35
 
35 36
 var defaultReconciliationTimeout = 30 * time.Second
... ...
@@ -208,13 +209,13 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) {
208 208
 		n.Spec.Role = swarm.NodeRoleManager
209 209
 	})
210 210
 
211
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True)
211
+	poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable, checker.True()), poll.WithTimeout(defaultReconciliationTimeout))
212 212
 
213 213
 	d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
214 214
 		n.Spec.Role = swarm.NodeRoleWorker
215 215
 	})
216 216
 
217
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.False)
217
+	poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable, checker.False()), poll.WithTimeout(defaultReconciliationTimeout))
218 218
 
219 219
 	// Wait for the role to change to worker in the cert. This is partially
220 220
 	// done because it's something worth testing in its own right, and
... ...
@@ -222,7 +223,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) {
222 222
 	// back to manager quickly might cause the node to pause for awhile
223 223
 	// while waiting for the role to change to worker, and the test can
224 224
 	// time out during this interval.
225
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
225
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
226 226
 		certBytes, err := ioutil.ReadFile(filepath.Join(d2.Folder, "root", "swarm", "certificates", "swarm-node.crt"))
227 227
 		if err != nil {
228 228
 			return "", fmt.Sprintf("error: %v", err)
... ...
@@ -232,7 +233,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) {
232 232
 			return certs[0].Subject.OrganizationalUnit[0], ""
233 233
 		}
234 234
 		return "", "could not get organizational unit from certificate"
235
-	}, checker.Equals, "swarm-worker")
235
+	}, checker.Equals("swarm-worker")), poll.WithTimeout(defaultReconciliationTimeout))
236 236
 
237 237
 	// Demoting last node should fail
238 238
 	node := d1.GetNode(c, d1.NodeID())
... ...
@@ -262,7 +263,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) {
262 262
 		n.Spec.Role = swarm.NodeRoleManager
263 263
 	})
264 264
 
265
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckControlAvailable, checker.True)
265
+	poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable, checker.True()), poll.WithTimeout(defaultReconciliationTimeout))
266 266
 }
267 267
 
268 268
 func (s *DockerSwarmSuite) TestAPISwarmLeaderProxy(c *testing.T) {
... ...
@@ -348,7 +349,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *testing.T) {
348 348
 
349 349
 	// wait for an election to occur
350 350
 	c.Logf("Waiting for election to occur...")
351
-	waitAndAssert(c, defaultReconciliationTimeout, checkLeader(d2, d3), checker.True)
351
+	poll.WaitOn(c, pollCheck(c, checkLeader(d2, d3), checker.True()), poll.WithTimeout(defaultReconciliationTimeout))
352 352
 
353 353
 	// assert that we have a new leader
354 354
 	assert.Assert(c, leader != nil)
... ...
@@ -361,7 +362,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *testing.T) {
361 361
 
362 362
 	// wait for possible election
363 363
 	c.Logf("Waiting for possible election...")
364
-	waitAndAssert(c, defaultReconciliationTimeout, checkLeader(d1, d2, d3), checker.True)
364
+	poll.WaitOn(c, pollCheck(c, checkLeader(d1, d2, d3), checker.True()), poll.WithTimeout(defaultReconciliationTimeout))
365 365
 	// pick out the leader and the followers again
366 366
 
367 367
 	// verify that we still only have 1 leader and 2 followers
... ...
@@ -388,7 +389,7 @@ func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *testing.T) {
388 388
 	d2.Stop(c)
389 389
 
390 390
 	// make sure there is a leader
391
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckLeader, checker.IsNil)
391
+	poll.WaitOn(c, pollCheck(c, d1.CheckLeader, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout))
392 392
 
393 393
 	d1.CreateService(c, simpleTestService, func(s *swarm.Service) {
394 394
 		s.Spec.Name = "top1"
... ...
@@ -403,15 +404,15 @@ func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *testing.T) {
403 403
 	defer cli.Close()
404 404
 
405 405
 	// d1 will eventually step down from leader because there is no longer an active quorum, wait for that to happen
406
-	waitAndAssert(c, defaultReconciliationTimeout*2, func(c *testing.T) (interface{}, string) {
406
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
407 407
 		_, err := cli.ServiceCreate(context.Background(), service.Spec, types.ServiceCreateOptions{})
408 408
 		return err.Error(), ""
409
-	}, checker.Contains, "Make sure more than half of the managers are online.")
409
+	}, checker.Contains("Make sure more than half of the managers are online.")), poll.WithTimeout(defaultReconciliationTimeout*2))
410 410
 
411 411
 	d2.StartNode(c)
412 412
 
413 413
 	// make sure there is a leader
414
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckLeader, checker.IsNil)
414
+	poll.WaitOn(c, pollCheck(c, d1.CheckLeader, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout))
415 415
 
416 416
 	d1.CreateService(c, simpleTestService, func(s *swarm.Service) {
417 417
 		s.Spec.Name = "top3"
... ...
@@ -428,12 +429,12 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveRemovesContainer(c *testing.T) {
428 428
 	assert.NilError(c, err, id)
429 429
 	id = strings.TrimSpace(id)
430 430
 
431
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances+1)
431
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances+1)), poll.WithTimeout(defaultReconciliationTimeout))
432 432
 
433 433
 	assert.ErrorContains(c, d.SwarmLeave(c, false), "")
434 434
 	assert.NilError(c, d.SwarmLeave(c, true))
435 435
 
436
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
436
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
437 437
 
438 438
 	id2, err := d.Cmd("ps", "-q")
439 439
 	assert.NilError(c, err, id2)
... ...
@@ -462,7 +463,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveOnPendingJoin(c *testing.T) {
462 462
 
463 463
 	assert.NilError(c, d2.SwarmLeave(c, true))
464 464
 
465
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 1)
465
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
466 466
 
467 467
 	id2, err := d2.Cmd("ps", "-q")
468 468
 	assert.NilError(c, err, id2)
... ...
@@ -480,7 +481,7 @@ func (s *DockerSwarmSuite) TestAPISwarmRestoreOnPendingJoin(c *testing.T) {
480 480
 	})
481 481
 	assert.ErrorContains(c, err, "Timeout was reached")
482 482
 
483
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckLocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
483
+	poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStatePending)), poll.WithTimeout(defaultReconciliationTimeout))
484 484
 
485 485
 	d.RestartNode(c)
486 486
 
... ...
@@ -521,11 +522,11 @@ func (s *DockerSwarmSuite) TestAPISwarmScaleNoRollingUpdate(c *testing.T) {
521 521
 	instances := 2
522 522
 	id := d.CreateService(c, simpleTestService, setInstances(instances))
523 523
 
524
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
524
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
525 525
 	containers := d.ActiveContainers(c)
526 526
 	instances = 4
527 527
 	d.UpdateService(c, d.GetService(c, id), setInstances(instances))
528
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
528
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
529 529
 	containers2 := d.ActiveContainers(c)
530 530
 
531 531
 loop0:
... ...
@@ -563,14 +564,14 @@ func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *testing.T) {
563 563
 
564 564
 	instances := 2
565 565
 	id := d1.CreateService(c, simpleTestService, setInstances(instances))
566
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
566
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
567 567
 
568 568
 	// drain d2, all containers should move to d1
569 569
 	d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {
570 570
 		n.Spec.Availability = swarm.NodeAvailabilityDrain
571 571
 	})
572
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
573
-	waitAndAssert(c, defaultReconciliationTimeout, d2.CheckActiveContainerCount, checker.Equals, 0)
572
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
573
+	poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
574 574
 
575 575
 	d2.Stop(c)
576 576
 
... ...
@@ -579,7 +580,7 @@ func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *testing.T) {
579 579
 		Spec:            swarm.Spec{},
580 580
 	})
581 581
 
582
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.Equals, instances)
582
+	poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
583 583
 
584 584
 	d3 := s.AddDaemon(c, true, true)
585 585
 	info := d3.SwarmInfo(c)
... ...
@@ -589,7 +590,7 @@ func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *testing.T) {
589 589
 	instances = 4
590 590
 	d3.UpdateService(c, d3.GetService(c, id), setInstances(instances))
591 591
 
592
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals, instances)
592
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
593 593
 }
594 594
 
595 595
 func simpleTestService(s *swarm.Service) {
... ...
@@ -743,7 +744,7 @@ func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerC
743 743
 			info = daemonInfo.Swarm
744 744
 			return err, "cluster not ready in time"
745 745
 		}
746
-		waitAndAssert(c, defaultReconciliationTimeout, checkInfo, checker.IsNil)
746
+		poll.WaitOn(c, pollCheck(c, checkInfo, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout))
747 747
 		if !info.ControlAvailable {
748 748
 			totalWCount++
749 749
 			continue
... ...
@@ -762,7 +763,7 @@ func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerC
762 762
 				n = *nn
763 763
 				return n.Status.State == swarm.NodeStateReady, fmt.Sprintf("state of node %s, reported by %s", n.ID, d.NodeID())
764 764
 			}
765
-			waitAndAssert(c, defaultReconciliationTimeout, waitReady, checker.True)
765
+			poll.WaitOn(c, pollCheck(c, waitReady, checker.True()), poll.WithTimeout(defaultReconciliationTimeout))
766 766
 
767 767
 			waitActive := func(c *testing.T) (interface{}, string) {
768 768
 				if n.Spec.Availability == swarm.NodeAvailabilityActive {
... ...
@@ -772,7 +773,7 @@ func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerC
772 772
 				n = *nn
773 773
 				return n.Spec.Availability == swarm.NodeAvailabilityActive, fmt.Sprintf("availability of node %s, reported by %s", n.ID, d.NodeID())
774 774
 			}
775
-			waitAndAssert(c, defaultReconciliationTimeout, waitActive, checker.True)
775
+			poll.WaitOn(c, pollCheck(c, waitActive, checker.True()), poll.WithTimeout(defaultReconciliationTimeout))
776 776
 
777 777
 			if n.Spec.Role == swarm.NodeRoleManager {
778 778
 				assert.Assert(c, n.ManagerStatus != nil, "manager status of node %s (manager), reported by %s", n.ID, d.NodeID())
... ...
@@ -863,7 +864,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *testing.T) {
863 863
 
864 864
 	instances := 2
865 865
 	id := d.CreateService(c, simpleTestService, setInstances(instances))
866
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
866
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
867 867
 
868 868
 	service := d.GetService(c, id)
869 869
 	instances = 5
... ...
@@ -873,7 +874,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *testing.T) {
873 873
 	defer cli.Close()
874 874
 	_, err := cli.ServiceUpdate(context.Background(), service.Spec.Name, service.Version, service.Spec, types.ServiceUpdateOptions{})
875 875
 	assert.NilError(c, err)
876
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
876
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
877 877
 }
878 878
 
879 879
 // Unlocking an unlocked swarm results in an error
... ...
@@ -948,7 +949,7 @@ func (s *DockerSwarmSuite) TestAPISwarmHealthcheckNone(c *testing.T) {
948 948
 		}
949 949
 	})
950 950
 
951
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
951
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout))
952 952
 
953 953
 	containers := d.ActiveContainers(c)
954 954
 
... ...
@@ -40,6 +40,7 @@ import (
40 40
 	"golang.org/x/sys/unix"
41 41
 	"gotest.tools/assert"
42 42
 	"gotest.tools/icmd"
43
+	"gotest.tools/poll"
43 44
 )
44 45
 
45 46
 const containerdSocket = "/var/run/docker/containerd/containerd.sock"
... ...
@@ -2071,10 +2072,10 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *tes
2071 2071
 
2072 2072
 	// Give time to containerd to process the command if we don't
2073 2073
 	// the resume event might be received after we do the inspect
2074
-	waitAndAssert(t, defaultReconciliationTimeout, func(*testing.T) (interface{}, string) {
2074
+	poll.WaitOn(t, pollCheck(t, func(*testing.T) (interface{}, string) {
2075 2075
 		result := icmd.RunCommand("kill", "-0", strings.TrimSpace(pid))
2076 2076
 		return result.ExitCode, ""
2077
-	}, checker.Equals, 0)
2077
+	}, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
2078 2078
 
2079 2079
 	// restart the daemon
2080 2080
 	s.d.Start(t, "--live-restore")
... ...
@@ -17,6 +17,7 @@ import (
17 17
 	"github.com/docker/docker/integration-cli/daemon"
18 18
 	"gotest.tools/assert"
19 19
 	"gotest.tools/icmd"
20
+	"gotest.tools/poll"
20 21
 )
21 22
 
22 23
 func pruneNetworkAndVerify(c *testing.T, d *daemon.Daemon, kept, pruned []string) {
... ...
@@ -24,19 +25,21 @@ func pruneNetworkAndVerify(c *testing.T, d *daemon.Daemon, kept, pruned []string
24 24
 	assert.NilError(c, err)
25 25
 
26 26
 	for _, s := range kept {
27
-		waitAndAssert(c, defaultReconciliationTimeout, func(*testing.T) (interface{}, string) {
27
+		poll.WaitOn(c, pollCheck(c, func(*testing.T) (interface{}, string) {
28 28
 			out, err := d.Cmd("network", "ls", "--format", "{{.Name}}")
29 29
 			assert.NilError(c, err)
30 30
 			return out, ""
31
-		}, checker.Contains, s)
31
+		}, checker.Contains(s)), poll.WithTimeout(defaultReconciliationTimeout))
32
+
32 33
 	}
33 34
 
34 35
 	for _, s := range pruned {
35
-		waitAndAssert(c, defaultReconciliationTimeout, func(*testing.T) (interface{}, string) {
36
+		poll.WaitOn(c, pollCheck(c, func(*testing.T) (interface{}, string) {
36 37
 			out, err := d.Cmd("network", "ls", "--format", "{{.Name}}")
37 38
 			assert.NilError(c, err)
38 39
 			return out, ""
39
-		}, checker.Not(checker.Contains(s)))
40
+		}, checker.Not(checker.Contains(s))()), poll.WithTimeout(defaultReconciliationTimeout))
41
+
40 42
 	}
41 43
 }
42 44
 
... ...
@@ -64,7 +67,7 @@ func (s *DockerSwarmSuite) TestPruneNetwork(c *testing.T) {
64 64
 		"busybox", "top")
65 65
 	assert.NilError(c, err)
66 66
 	assert.Assert(c, strings.TrimSpace(out) != "")
67
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, replicas+1)
67
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(replicas+1)), poll.WithTimeout(defaultReconciliationTimeout))
68 68
 
69 69
 	// prune and verify
70 70
 	pruneNetworkAndVerify(c, d, []string{"n1", "n3"}, []string{"n2", "n4"})
... ...
@@ -74,7 +77,7 @@ func (s *DockerSwarmSuite) TestPruneNetwork(c *testing.T) {
74 74
 	assert.NilError(c, err)
75 75
 	_, err = d.Cmd("service", "rm", serviceName)
76 76
 	assert.NilError(c, err)
77
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 0)
77
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
78 78
 
79 79
 	pruneNetworkAndVerify(c, d, []string{}, []string{"n1", "n3"})
80 80
 }
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/docker/docker/integration-cli/checker"
11 11
 	"gotest.tools/assert"
12 12
 	is "gotest.tools/assert/cmp"
13
+	"gotest.tools/poll"
13 14
 )
14 15
 
15 16
 func (s *DockerSuite) TestRestartStoppedContainer(c *testing.T) {
... ...
@@ -42,13 +43,13 @@ func (s *DockerSuite) TestRestartRunningContainer(c *testing.T) {
42 42
 	}
43 43
 
44 44
 	// Wait 10 seconds for the 'echo' to appear in the logs
45
-	waitAndAssert(c, 10*time.Second, getLogs, checker.Equals, "foobar\n")
45
+	poll.WaitOn(c, pollCheck(c, getLogs, checker.Equals("foobar\n")), poll.WithTimeout(10*time.Second))
46 46
 
47 47
 	dockerCmd(c, "restart", "-t", "1", cleanedContainerID)
48 48
 	assert.NilError(c, waitRun(cleanedContainerID))
49 49
 
50 50
 	// Wait 10 seconds for first 'echo' appear (again) in the logs
51
-	waitAndAssert(c, 10*time.Second, getLogs, checker.Equals, "foobar\nfoobar\n")
51
+	poll.WaitOn(c, pollCheck(c, getLogs, checker.Equals("foobar\nfoobar\n")), poll.WithTimeout(10*time.Second))
52 52
 }
53 53
 
54 54
 // Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	"github.com/docker/docker/api/types/swarm"
15 15
 	"github.com/docker/docker/integration-cli/checker"
16 16
 	"gotest.tools/assert"
17
+	"gotest.tools/poll"
17 18
 )
18 19
 
19 20
 func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *testing.T) {
... ...
@@ -23,18 +24,18 @@ func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *testing.T) {
23 23
 	id := strings.TrimSpace(out)
24 24
 
25 25
 	var tasks []swarm.Task
26
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
26
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
27 27
 		tasks = d.GetServiceTasks(c, id)
28 28
 		return len(tasks) > 0, ""
29
-	}, checker.Equals, true)
29
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
30 30
 
31 31
 	task := tasks[0]
32
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
32
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
33 33
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
34 34
 			task = d.GetTask(c, task.ID)
35 35
 		}
36 36
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
37
-	}, checker.Equals, true)
37
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
38 38
 
39 39
 	// check container mount config
40 40
 	out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .HostConfig.Mounts}}", task.Status.ContainerStatus.ContainerID)
... ...
@@ -137,18 +138,18 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTargetPaths(c *testi
137 137
 	assert.Equal(c, len(refs), len(testPaths))
138 138
 
139 139
 	var tasks []swarm.Task
140
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
140
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
141 141
 		tasks = d.GetServiceTasks(c, serviceName)
142 142
 		return len(tasks) > 0, ""
143
-	}, checker.Equals, true)
143
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
144 144
 
145 145
 	task := tasks[0]
146
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
146
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
147 147
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
148 148
 			task = d.GetTask(c, task.ID)
149 149
 		}
150 150
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
151
-	}, checker.Equals, true)
151
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
152 152
 
153 153
 	for testName, testTarget := range testPaths {
154 154
 		path := testTarget
... ...
@@ -187,18 +188,18 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretReferencedTwice(c *testing
187 187
 	assert.Equal(c, len(refs), 2)
188 188
 
189 189
 	var tasks []swarm.Task
190
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
190
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
191 191
 		tasks = d.GetServiceTasks(c, serviceName)
192 192
 		return len(tasks) > 0, ""
193
-	}, checker.Equals, true)
193
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
194 194
 
195 195
 	task := tasks[0]
196
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
196
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
197 197
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
198 198
 			task = d.GetTask(c, task.ID)
199 199
 		}
200 200
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
201
-	}, checker.Equals, true)
201
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
202 202
 
203 203
 	for _, target := range []string{"target1", "target2"} {
204 204
 		assert.NilError(c, err, out)
... ...
@@ -284,18 +285,18 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigSourceTargetPaths(c *testi
284 284
 	assert.Equal(c, len(refs), len(testPaths))
285 285
 
286 286
 	var tasks []swarm.Task
287
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
287
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
288 288
 		tasks = d.GetServiceTasks(c, serviceName)
289 289
 		return len(tasks) > 0, ""
290
-	}, checker.Equals, true)
290
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
291 291
 
292 292
 	task := tasks[0]
293
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
293
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
294 294
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
295 295
 			task = d.GetTask(c, task.ID)
296 296
 		}
297 297
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
298
-	}, checker.Equals, true)
298
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
299 299
 
300 300
 	for testName, testTarget := range testPaths {
301 301
 		path := testTarget
... ...
@@ -334,18 +335,18 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigReferencedTwice(c *testing
334 334
 	assert.Equal(c, len(refs), 2)
335 335
 
336 336
 	var tasks []swarm.Task
337
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
337
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
338 338
 		tasks = d.GetServiceTasks(c, serviceName)
339 339
 		return len(tasks) > 0, ""
340
-	}, checker.Equals, true)
340
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
341 341
 
342 342
 	task := tasks[0]
343
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
343
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
344 344
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
345 345
 			task = d.GetTask(c, task.ID)
346 346
 		}
347 347
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
348
-	}, checker.Equals, true)
348
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
349 349
 
350 350
 	for _, target := range []string{"target1", "target2"} {
351 351
 		assert.NilError(c, err, out)
... ...
@@ -366,18 +367,18 @@ func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *testing.T) {
366 366
 	id := strings.TrimSpace(out)
367 367
 
368 368
 	var tasks []swarm.Task
369
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
369
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
370 370
 		tasks = d.GetServiceTasks(c, id)
371 371
 		return len(tasks) > 0, ""
372
-	}, checker.Equals, true)
372
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
373 373
 
374 374
 	task := tasks[0]
375
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
375
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
376 376
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
377 377
 			task = d.GetTask(c, task.ID)
378 378
 		}
379 379
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
380
-	}, checker.Equals, true)
380
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
381 381
 
382 382
 	// check container mount config
383 383
 	out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .HostConfig.Mounts}}", task.Status.ContainerStatus.ContainerID)
... ...
@@ -422,18 +423,18 @@ func (s *DockerSwarmSuite) TestServiceCreateWithNetworkAlias(c *testing.T) {
422 422
 	id := strings.TrimSpace(out)
423 423
 
424 424
 	var tasks []swarm.Task
425
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
425
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
426 426
 		tasks = d.GetServiceTasks(c, id)
427 427
 		return len(tasks) > 0, ""
428
-	}, checker.Equals, true)
428
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
429 429
 
430 430
 	task := tasks[0]
431
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
431
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
432 432
 		if task.NodeID == "" || task.Status.ContainerStatus == nil {
433 433
 			task = d.GetTask(c, task.ID)
434 434
 		}
435 435
 		return task.NodeID != "" && task.Status.ContainerStatus != nil, ""
436
-	}, checker.Equals, true)
436
+	}, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
437 437
 
438 438
 	// check container alias config
439 439
 	out, err = s.nodeCmd(c, task.NodeID, "inspect", "--format", "{{json .NetworkSettings.Networks.test_swarm_br.Aliases}}", task.Status.ContainerStatus.ContainerID)
... ...
@@ -14,6 +14,7 @@ import (
14 14
 	"github.com/docker/docker/integration-cli/cli/build"
15 15
 	"gotest.tools/assert"
16 16
 	"gotest.tools/icmd"
17
+	"gotest.tools/poll"
17 18
 )
18 19
 
19 20
 // start a service, and then make its task unhealthy during running
... ...
@@ -39,39 +40,40 @@ func (s *DockerSwarmSuite) TestServiceHealthRun(c *testing.T) {
39 39
 	id := strings.TrimSpace(out)
40 40
 
41 41
 	var tasks []swarm.Task
42
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
42
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
43 43
 		tasks = d.GetServiceTasks(c, id)
44 44
 		return tasks, ""
45
-	}, checker.HasLen, 1)
45
+	}, checker.HasLen(1)), poll.WithTimeout(defaultReconciliationTimeout))
46 46
 
47 47
 	task := tasks[0]
48 48
 
49 49
 	// wait for task to start
50
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
50
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
51 51
 		task = d.GetTask(c, task.ID)
52 52
 		return task.Status.State, ""
53
-	}, checker.Equals, swarm.TaskStateRunning)
53
+	}, checker.Equals(swarm.TaskStateRunning)), poll.WithTimeout(defaultReconciliationTimeout))
54
+
54 55
 	containerID := task.Status.ContainerStatus.ContainerID
55 56
 
56 57
 	// wait for container to be healthy
57
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
58
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
58 59
 		out, _ := d.Cmd("inspect", "--format={{.State.Health.Status}}", containerID)
59 60
 		return strings.TrimSpace(out), ""
60
-	}, checker.Equals, "healthy")
61
+	}, checker.Equals("healthy")), poll.WithTimeout(defaultReconciliationTimeout))
61 62
 
62 63
 	// make it fail
63 64
 	d.Cmd("exec", containerID, "rm", "/status")
64 65
 	// wait for container to be unhealthy
65
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
66
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
66 67
 		out, _ := d.Cmd("inspect", "--format={{.State.Health.Status}}", containerID)
67 68
 		return strings.TrimSpace(out), ""
68
-	}, checker.Equals, "unhealthy")
69
+	}, checker.Equals("unhealthy")), poll.WithTimeout(defaultReconciliationTimeout))
69 70
 
70 71
 	// Task should be terminated
71
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
72
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
72 73
 		task = d.GetTask(c, task.ID)
73 74
 		return task.Status.State, ""
74
-	}, checker.Equals, swarm.TaskStateFailed)
75
+	}, checker.Equals(swarm.TaskStateFailed)), poll.WithTimeout(defaultReconciliationTimeout))
75 76
 
76 77
 	if !strings.Contains(task.Status.Err, container.ErrContainerUnhealthy.Error()) {
77 78
 		c.Fatal("unhealthy task exits because of other error")
... ...
@@ -100,27 +102,27 @@ func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) {
100 100
 	id := strings.TrimSpace(out)
101 101
 
102 102
 	var tasks []swarm.Task
103
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
103
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
104 104
 		tasks = d.GetServiceTasks(c, id)
105 105
 		return tasks, ""
106
-	}, checker.HasLen, 1)
106
+	}, checker.HasLen(1)), poll.WithTimeout(defaultReconciliationTimeout))
107 107
 
108 108
 	task := tasks[0]
109 109
 
110 110
 	// wait for task to start
111
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
111
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
112 112
 		task = d.GetTask(c, task.ID)
113 113
 		return task.Status.State, ""
114
-	}, checker.Equals, swarm.TaskStateStarting)
114
+	}, checker.Equals(swarm.TaskStateStarting)), poll.WithTimeout(defaultReconciliationTimeout))
115 115
 
116 116
 	containerID := task.Status.ContainerStatus.ContainerID
117 117
 
118 118
 	// wait for health check to work
119
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
119
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
120 120
 		out, _ := d.Cmd("inspect", "--format={{.State.Health.FailingStreak}}", containerID)
121 121
 		failingStreak, _ := strconv.Atoi(strings.TrimSpace(out))
122 122
 		return failingStreak, ""
123
-	}, checker.GreaterThan, 0)
123
+	}, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout))
124 124
 
125 125
 	// task should be blocked at starting status
126 126
 	task = d.GetTask(c, task.ID)
... ...
@@ -130,8 +132,9 @@ func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) {
130 130
 	d.Cmd("exec", containerID, "touch", "/status")
131 131
 
132 132
 	// Task should be at running status
133
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
133
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
134 134
 		task = d.GetTask(c, task.ID)
135 135
 		return task.Status.State, ""
136
-	}, checker.Equals, swarm.TaskStateRunning)
136
+	}, checker.Equals(swarm.TaskStateRunning)), poll.WithTimeout(defaultReconciliationTimeout))
137
+
137 138
 }
... ...
@@ -15,6 +15,7 @@ import (
15 15
 	"github.com/docker/docker/integration-cli/daemon"
16 16
 	"gotest.tools/assert"
17 17
 	"gotest.tools/icmd"
18
+	"gotest.tools/poll"
18 19
 )
19 20
 
20 21
 type logMessage struct {
... ...
@@ -39,9 +40,8 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *testing.T) {
39 39
 	}
40 40
 
41 41
 	// make sure task has been deployed.
42
-	waitAndAssert(c, defaultReconciliationTimeout,
43
-		d.CheckRunningTaskImages, checker.DeepEquals,
44
-		map[string]int{"busybox:latest": len(services)})
42
+	poll.WaitOn(c, pollCheck(c,
43
+		d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{"busybox:latest": len(services)})), poll.WithTimeout(defaultReconciliationTimeout))
45 44
 
46 45
 	for name, message := range services {
47 46
 		out, err := d.Cmd("service", "logs", name)
... ...
@@ -80,9 +80,9 @@ func (s *DockerSwarmSuite) TestServiceLogsCompleteness(c *testing.T) {
80 80
 	assert.Assert(c, strings.TrimSpace(out) != "")
81 81
 
82 82
 	// make sure task has been deployed.
83
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
83
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
84 84
 	// and make sure we have all the log lines
85
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 6)
85
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(6)), poll.WithTimeout(defaultReconciliationTimeout))
86 86
 
87 87
 	out, err = d.Cmd("service", "logs", name)
88 88
 	assert.NilError(c, err)
... ...
@@ -107,8 +107,8 @@ func (s *DockerSwarmSuite) TestServiceLogsTail(c *testing.T) {
107 107
 	assert.Assert(c, strings.TrimSpace(out) != "")
108 108
 
109 109
 	// make sure task has been deployed.
110
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
111
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 6)
110
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
111
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(6)), poll.WithTimeout(defaultReconciliationTimeout))
112 112
 
113 113
 	out, err = d.Cmd("service", "logs", "--tail=2", name)
114 114
 	assert.NilError(c, err)
... ...
@@ -129,9 +129,9 @@ func (s *DockerSwarmSuite) TestServiceLogsSince(c *testing.T) {
129 129
 	out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "for i in $(seq 1 3); do sleep .1; echo log$i; done; sleep 10000000")
130 130
 	assert.NilError(c, err)
131 131
 	assert.Assert(c, strings.TrimSpace(out) != "")
132
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
132
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
133 133
 	// wait a sec for the logs to come in
134
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 3)
134
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(3)), poll.WithTimeout(defaultReconciliationTimeout))
135 135
 
136 136
 	out, err = d.Cmd("service", "logs", "-t", name)
137 137
 	assert.NilError(c, err)
... ...
@@ -165,7 +165,7 @@ func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) {
165 165
 	assert.Assert(c, strings.TrimSpace(out) != "")
166 166
 
167 167
 	// make sure task has been deployed.
168
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
168
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
169 169
 
170 170
 	args := []string{"service", "logs", "-f", name}
171 171
 	cmd := exec.Command(dockerBinary, d.PrependHostArg(args)...)
... ...
@@ -228,8 +228,8 @@ func (s *DockerSwarmSuite) TestServiceLogsTaskLogs(c *testing.T) {
228 228
 	result.Assert(c, icmd.Expected{Out: id})
229 229
 
230 230
 	// make sure task has been deployed.
231
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, replicas)
232
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 6*replicas)
231
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(replicas)), poll.WithTimeout(defaultReconciliationTimeout))
232
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(6*replicas)), poll.WithTimeout(defaultReconciliationTimeout))
233 233
 
234 234
 	// get the task ids
235 235
 	result = icmd.RunCmd(d.Command("service", "ps", "-q", name))
... ...
@@ -281,9 +281,9 @@ func (s *DockerSwarmSuite) TestServiceLogsTTY(c *testing.T) {
281 281
 	result.Assert(c, icmd.Expected{Out: id})
282 282
 
283 283
 	// make sure task has been deployed.
284
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
284
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
285 285
 	// and make sure we have all the log lines
286
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 2)
286
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout))
287 287
 
288 288
 	cmd := d.Command("service", "logs", "--raw", name)
289 289
 	result = icmd.RunCmd(cmd)
... ...
@@ -315,9 +315,9 @@ func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *testing.T) {
315 315
 	assert.Assert(c, id != "")
316 316
 
317 317
 	// make sure task has been deployed.
318
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
318
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
319 319
 	// and make sure we have all the log lines
320
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 2)
320
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout))
321 321
 
322 322
 	// now find and nuke the container
323 323
 	result = icmd.RunCmd(d.Command("ps", "-q"))
... ...
@@ -368,9 +368,9 @@ func (s *DockerSwarmSuite) TestServiceLogsDetails(c *testing.T) {
368 368
 	assert.Assert(c, id != "")
369 369
 
370 370
 	// make sure task has been deployed
371
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
371
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
372 372
 	// and make sure we have all the log lines
373
-	waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 1)
373
+	poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
374 374
 
375 375
 	// First, test without pretty printing
376 376
 	// call service logs with details. set raw to skip pretty printing
... ...
@@ -32,6 +32,7 @@ import (
32 32
 	"gotest.tools/assert"
33 33
 	"gotest.tools/fs"
34 34
 	"gotest.tools/icmd"
35
+	"gotest.tools/poll"
35 36
 )
36 37
 
37 38
 func (s *DockerSwarmSuite) TestSwarmUpdate(c *testing.T) {
... ...
@@ -176,7 +177,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *testing.T) {
176 176
 	assert.NilError(c, err, out)
177 177
 
178 178
 	// make sure task has been deployed.
179
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
179
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
180 180
 
181 181
 	containers := d.ActiveContainers(c)
182 182
 	out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.Hostname}}", containers[0])
... ...
@@ -251,7 +252,7 @@ func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *testing.T) {
251 251
 	assert.Assert(c, strings.TrimSpace(out) != "")
252 252
 
253 253
 	// make sure task has been deployed.
254
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 3)
254
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(3)), poll.WithTimeout(defaultReconciliationTimeout))
255 255
 
256 256
 	filter := "name=redis-cluster"
257 257
 
... ...
@@ -303,7 +304,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *testing.T) {
303 303
 	assert.Assert(c, strings.TrimSpace(out) != "")
304 304
 
305 305
 	// make sure task has been deployed.
306
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
306
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
307 307
 
308 308
 	out, err = d.Cmd("ps", "-q")
309 309
 	assert.NilError(c, err, out)
... ...
@@ -388,7 +389,7 @@ func (s *DockerSwarmSuite) TestSwarmContainerAttachByNetworkId(c *testing.T) {
388 388
 		return out, ""
389 389
 	}
390 390
 
391
-	waitAndAssert(c, 3*time.Second, checkNetwork, checker.Not(checker.Contains("testnet")))
391
+	poll.WaitOn(c, pollCheck(c, checkNetwork, checker.Not(checker.Contains("testnet"))()), poll.WithTimeout(3*time.Second))
392 392
 }
393 393
 
394 394
 func (s *DockerSwarmSuite) TestOverlayAttachable(c *testing.T) {
... ...
@@ -550,7 +551,7 @@ func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *testing.T) {
550 550
 	}
551 551
 
552 552
 	// wait until all tasks have been created
553
-	waitAndAssert(c, defaultReconciliationTimeout, checkNumTasks, checker.Equals, 3)
553
+	poll.WaitOn(c, pollCheck(c, checkNumTasks, checker.Equals(3)), poll.WithTimeout(defaultReconciliationTimeout))
554 554
 
555 555
 	out, err = d.Cmd("service", "ps", "--filter", filter, name)
556 556
 	assert.NilError(c, err, out)
... ...
@@ -572,7 +573,7 @@ func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *testing.T) {
572 572
 	assert.NilError(c, err, out)
573 573
 	assert.Assert(c, strings.TrimSpace(out) != "")
574 574
 
575
-	waitAndAssert(c, defaultReconciliationTimeout, checkNumTasks, checker.Equals, 1)
575
+	poll.WaitOn(c, pollCheck(c, checkNumTasks, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
576 576
 
577 577
 	filter = "name=redis-cluster"
578 578
 	out, err = d.Cmd("service", "ps", "--filter", filter, name)
... ...
@@ -600,7 +601,7 @@ func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *testing.T) {
600 600
 	assert.Assert(c, strings.TrimSpace(out) != "")
601 601
 
602 602
 	// make sure task has been deployed.
603
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckServiceRunningTasks(name), checker.Equals, 1)
603
+	poll.WaitOn(c, pollCheck(c, d.CheckServiceRunningTasks(name), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
604 604
 
605 605
 	// Filter non-tasks
606 606
 	out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=false")
... ...
@@ -837,7 +838,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) {
837 837
 	assert.NilError(c, err, out)
838 838
 
839 839
 	// Make sure task has been deployed.
840
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
840
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
841 841
 
842 842
 	// We need to get the container id.
843 843
 	out, err = d.Cmd("ps", "-q", "--no-trunc")
... ...
@@ -851,7 +852,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) {
851 851
 	out, err = d.Cmd("service", "rm", name)
852 852
 	assert.NilError(c, err, out)
853 853
 	// Make sure container has been destroyed.
854
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 0)
854
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
855 855
 
856 856
 	// With --tty
857 857
 	expectedOutput = "TTY"
... ...
@@ -859,7 +860,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) {
859 859
 	assert.NilError(c, err, out)
860 860
 
861 861
 	// Make sure task has been deployed.
862
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
862
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
863 863
 
864 864
 	// We need to get the container id.
865 865
 	out, err = d.Cmd("ps", "-q", "--no-trunc")
... ...
@@ -880,7 +881,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *testing.T) {
880 880
 	assert.NilError(c, err, out)
881 881
 
882 882
 	// Make sure task has been deployed.
883
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
883
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
884 884
 
885 885
 	out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.TTY }}", name)
886 886
 	assert.NilError(c, err, out)
... ...
@@ -915,22 +916,20 @@ func (s *DockerSwarmSuite) TestSwarmServiceNetworkUpdate(c *testing.T) {
915 915
 	result.Assert(c, icmd.Success)
916 916
 
917 917
 	// Make sure task has been deployed.
918
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskNetworks, checker.DeepEquals,
919
-		map[string]int{fooNetwork: 1, barNetwork: 1})
918
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEquals(map[string]int{fooNetwork: 1, barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout))
920 919
 
921 920
 	// Remove a network
922 921
 	result = icmd.RunCmd(d.Command("service", "update", "--detach", "--network-rm", "foo", name))
923 922
 	result.Assert(c, icmd.Success)
924 923
 
925
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskNetworks, checker.DeepEquals,
926
-		map[string]int{barNetwork: 1})
924
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEquals(map[string]int{barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout))
927 925
 
928 926
 	// Add a network
929 927
 	result = icmd.RunCmd(d.Command("service", "update", "--detach", "--network-add", "baz", name))
930 928
 	result.Assert(c, icmd.Success)
931 929
 
932
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckRunningTaskNetworks, checker.DeepEquals,
933
-		map[string]int{barNetwork: 1, bazNetwork: 1})
930
+	poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEquals(map[string]int{barNetwork: 1, bazNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout))
931
+
934 932
 }
935 933
 
936 934
 func (s *DockerSwarmSuite) TestDNSConfig(c *testing.T) {
... ...
@@ -942,7 +941,7 @@ func (s *DockerSwarmSuite) TestDNSConfig(c *testing.T) {
942 942
 	assert.NilError(c, err, out)
943 943
 
944 944
 	// Make sure task has been deployed.
945
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
945
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
946 946
 
947 947
 	// We need to get the container id.
948 948
 	out, err = d.Cmd("ps", "-a", "-q", "--no-trunc")
... ...
@@ -969,7 +968,7 @@ func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *testing.T) {
969 969
 	assert.NilError(c, err, out)
970 970
 
971 971
 	// Make sure task has been deployed.
972
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
972
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
973 973
 
974 974
 	out, err = d.Cmd("service", "update", "--detach", "--dns-add=1.2.3.4", "--dns-search-add=example.com", "--dns-option-add=timeout:3", name)
975 975
 	assert.NilError(c, err, out)
... ...
@@ -1002,18 +1001,18 @@ func checkKeyIsEncrypted(d *daemon.Daemon) func(*testing.T) (interface{}, string
1002 1002
 
1003 1003
 func checkSwarmLockedToUnlocked(c *testing.T, d *daemon.Daemon) {
1004 1004
 	// Wait for the PEM file to become unencrypted
1005
-	waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), checker.Equals, false)
1005
+	poll.WaitOn(c, pollCheck(c, checkKeyIsEncrypted(d), checker.Equals(false)), poll.WithTimeout(defaultReconciliationTimeout))
1006 1006
 
1007 1007
 	d.RestartNode(c)
1008
-	waitAndAssert(c, time.Second, d.CheckLocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
1008
+	poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second))
1009 1009
 }
1010 1010
 
1011 1011
 func checkSwarmUnlockedToLocked(c *testing.T, d *daemon.Daemon) {
1012 1012
 	// Wait for the PEM file to become encrypted
1013
-	waitAndAssert(c, defaultReconciliationTimeout, checkKeyIsEncrypted(d), checker.Equals, true)
1013
+	poll.WaitOn(c, pollCheck(c, checkKeyIsEncrypted(d), checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout))
1014 1014
 
1015 1015
 	d.RestartNode(c)
1016
-	waitAndAssert(c, time.Second, d.CheckLocalNodeState, checker.Equals, swarm.LocalNodeStateLocked)
1016
+	poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateLocked)), poll.WithTimeout(time.Second))
1017 1017
 }
1018 1018
 
1019 1019
 func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *testing.T) {
... ...
@@ -1184,7 +1183,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) {
1184 1184
 	// joined workers start off unlocked
1185 1185
 	d2 := s.AddDaemon(c, true, false)
1186 1186
 	d2.RestartNode(c)
1187
-	waitAndAssert(c, time.Second, d2.CheckLocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
1187
+	poll.WaitOn(c, pollCheck(c, d2.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second))
1188 1188
 
1189 1189
 	// promote worker
1190 1190
 	outs, err = d1.Cmd("node", "promote", d2.NodeID())
... ...
@@ -1212,8 +1211,8 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) {
1212 1212
 	// to be replaced, then the node still has the manager TLS key which is still locked
1213 1213
 	// (because we never want a manager TLS key to be on disk unencrypted if the cluster
1214 1214
 	// is set to autolock)
1215
-	waitAndAssert(c, defaultReconciliationTimeout, d3.CheckControlAvailable, checker.False)
1216
-	waitAndAssert(c, defaultReconciliationTimeout, func(c *testing.T) (interface{}, string) {
1215
+	poll.WaitOn(c, pollCheck(c, d3.CheckControlAvailable, checker.False()), poll.WithTimeout(defaultReconciliationTimeout))
1216
+	poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) {
1217 1217
 		certBytes, err := ioutil.ReadFile(filepath.Join(d3.Folder, "root", "swarm", "certificates", "swarm-node.crt"))
1218 1218
 		if err != nil {
1219 1219
 			return "", fmt.Sprintf("error: %v", err)
... ...
@@ -1223,11 +1222,11 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) {
1223 1223
 			return certs[0].Subject.OrganizationalUnit[0], ""
1224 1224
 		}
1225 1225
 		return "", "could not get organizational unit from certificate"
1226
-	}, checker.Equals, "swarm-worker")
1226
+	}, checker.Equals("swarm-worker")), poll.WithTimeout(defaultReconciliationTimeout))
1227 1227
 
1228 1228
 	// by now, it should *never* be locked on restart
1229 1229
 	d3.RestartNode(c)
1230
-	waitAndAssert(c, time.Second, d3.CheckLocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
1230
+	poll.WaitOn(c, pollCheck(c, d3.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second))
1231 1231
 }
1232 1232
 
1233 1233
 func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *testing.T) {
... ...
@@ -1430,7 +1429,7 @@ func (s *DockerSwarmSuite) TestExtraHosts(c *testing.T) {
1430 1430
 	assert.NilError(c, err, out)
1431 1431
 
1432 1432
 	// Make sure task has been deployed.
1433
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
1433
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
1434 1434
 
1435 1435
 	// We need to get the container id.
1436 1436
 	out, err = d.Cmd("ps", "-a", "-q", "--no-trunc")
... ...
@@ -1480,7 +1479,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *testing.T) {
1480 1480
 	assert.NilError(c, err, out)
1481 1481
 
1482 1482
 	// make sure task has been deployed.
1483
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
1483
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
1484 1484
 
1485 1485
 	out, err = d.Cmd("network", "inspect", "--format", "{{.IPAM.Options}}", "foo")
1486 1486
 	assert.NilError(c, err, out)
... ...
@@ -1542,7 +1541,7 @@ func (s *DockerSwarmSuite) TestSwarmPublishDuplicatePorts(c *testing.T) {
1542 1542
 	id := strings.TrimSpace(out)
1543 1543
 
1544 1544
 	// make sure task has been deployed.
1545
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
1545
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
1546 1546
 
1547 1547
 	// Total len = 4, with 2 dynamic ports and 2 non-dynamic ports
1548 1548
 	// Dynamic ports are likely to be 30000 and 30001 but doesn't matter
... ...
@@ -1599,7 +1598,7 @@ func (s *DockerSwarmSuite) TestSwarmReadonlyRootfs(c *testing.T) {
1599 1599
 	assert.NilError(c, err, out)
1600 1600
 
1601 1601
 	// make sure task has been deployed.
1602
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
1602
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
1603 1603
 
1604 1604
 	out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.ReadOnly }}", "top")
1605 1605
 	assert.NilError(c, err, out)
... ...
@@ -1684,7 +1683,7 @@ func (s *DockerSwarmSuite) TestSwarmStopSignal(c *testing.T) {
1684 1684
 	assert.NilError(c, err, out)
1685 1685
 
1686 1686
 	// make sure task has been deployed.
1687
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
1687
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
1688 1688
 
1689 1689
 	out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.StopSignal }}", "top")
1690 1690
 	assert.NilError(c, err, out)
... ...
@@ -1715,7 +1714,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *testing.T) {
1715 1715
 	assert.Assert(c, strings.TrimSpace(out) != "")
1716 1716
 
1717 1717
 	// make sure task has been deployed.
1718
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 2)
1718
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout))
1719 1719
 
1720 1720
 	out, err = d.Cmd("service", "ls")
1721 1721
 	assert.NilError(c, err, out)
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/docker/docker/api/types/swarm"
12 12
 	"github.com/docker/docker/integration-cli/checker"
13 13
 	"gotest.tools/assert"
14
+	"gotest.tools/poll"
14 15
 )
15 16
 
16 17
 func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *testing.T) {
... ...
@@ -20,7 +21,7 @@ func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *testing.T) {
20 20
 	assert.NilError(c, err, out)
21 21
 
22 22
 	// Make sure task stays pending before plugin is available
23
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckServiceTasksInStateWithError("top", swarm.TaskStatePending, "missing plugin on 1 node"), checker.Equals, 1)
23
+	poll.WaitOn(c, pollCheck(c, d.CheckServiceTasksInStateWithError("top", swarm.TaskStatePending, "missing plugin on 1 node"), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
24 24
 
25 25
 	plugin := newVolumePlugin(c, "customvolumedriver")
26 26
 	defer plugin.Close()
... ...
@@ -34,7 +35,7 @@ func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *testing.T) {
34 34
 	// this long delay.
35 35
 
36 36
 	// make sure task has been deployed.
37
-	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
37
+	poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout))
38 38
 
39 39
 	out, err = d.Cmd("ps", "-q")
40 40
 	assert.NilError(c, err)
... ...
@@ -80,7 +81,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) {
80 80
 	assert.NilError(c, err)
81 81
 
82 82
 	// wait for tasks ready
83
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, 2)
83
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout))
84 84
 
85 85
 	// remove service
86 86
 	_, err = d1.Cmd("service", "rm", serviceName)
... ...
@@ -88,7 +89,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) {
88 88
 
89 89
 	// wait to ensure all containers have exited before removing the plugin. Else there's a
90 90
 	// possibility of container exits erroring out due to plugins being unavailable.
91
-	waitAndAssert(c, defaultReconciliationTimeout, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, 0)
91
+	poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout))
92 92
 
93 93
 	// disable plugin on worker
94 94
 	_, err = d2.Cmd("plugin", "disable", "-f", pluginName)
... ...
@@ -101,6 +102,6 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) {
101 101
 	_, err = d1.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", serviceName, "--mode=global", "--network", networkName, image, "top")
102 102
 	assert.NilError(c, err)
103 103
 
104
-	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckRunningTaskImages, checker.DeepEquals,
105
-		map[string]int{image: 1})
104
+	poll.WaitOn(c, pollCheck(c, d1.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image: 1})), poll.WithTimeout(defaultReconciliationTimeout))
105
+
106 106
 }