Browse code

Merge pull request #34805 from chris-crone/containerize-integration-tests

Containerize integration tests

Vincent Demeester authored on 2017/09/19 04:11:06
Showing 38 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,70 @@
0
+## Step 1: Build tests
1
+FROM golang:1.8.3-alpine3.6 as builder
2
+
3
+RUN apk add --update \
4
+    bash \
5
+    build-base \
6
+    curl \
7
+    lvm2-dev \
8
+    jq \
9
+    && rm -rf /var/cache/apk/*
10
+
11
+RUN mkdir -p /go/src/github.com/docker/docker/
12
+WORKDIR /go/src/github.com/docker/docker/
13
+
14
+# Generate frozen images
15
+COPY contrib/download-frozen-image-v2.sh contrib/download-frozen-image-v2.sh
16
+RUN contrib/download-frozen-image-v2.sh /output/docker-frozen-images \
17
+  buildpack-deps:jessie@sha256:85b379ec16065e4fe4127eb1c5fb1bcc03c559bd36dbb2e22ff496de55925fa6 \
18
+  busybox:latest@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f \
19
+  debian:jessie@sha256:72f784399fd2719b4cb4e16ef8e369a39dc67f53d978cd3e2e7bf4e502c7b793 \
20
+  hello-world:latest@sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
21
+
22
+# Download Docker CLI binary
23
+COPY hack/dockerfile hack/dockerfile
24
+RUN hack/dockerfile/install-binaries.sh dockercli
25
+
26
+# Set tag and add sources
27
+ARG DOCKER_GITCOMMIT
28
+ENV DOCKER_GITCOMMIT=$DOCKER_GITCOMMIT
29
+ADD . .
30
+
31
+# Build DockerSuite.TestBuild* dependency
32
+RUN CGO_ENABLED=0 go build -o /output/httpserver github.com/docker/docker/contrib/httpserver
33
+
34
+# Build the integration tests and copy the resulting binaries to /output/tests
35
+RUN hack/make.sh build-integration-test-binary
36
+RUN mkdir -p /output/tests && find . -name test.main -exec cp --parents '{}' /output/tests \;
37
+
38
+## Step 2: Generate testing image
39
+FROM alpine:3.6 as runner
40
+
41
+# GNU tar is used for generating the emptyfs image
42
+RUN apk add --update \
43
+    bash \
44
+    ca-certificates \
45
+    g++ \
46
+    git \
47
+    iptables \
48
+    tar \
49
+    xz \
50
+    && rm -rf /var/cache/apk/*
51
+
52
+# Add an unprivileged user to be used for tests which need it
53
+RUN addgroup docker && adduser -D -G docker unprivilegeduser -s /bin/ash
54
+
55
+COPY contrib/httpserver/Dockerfile /tests/contrib/httpserver/Dockerfile
56
+COPY contrib/syscall-test /tests/contrib/syscall-test
57
+COPY integration-cli/fixtures /tests/integration-cli/fixtures
58
+
59
+COPY hack/test/e2e-run.sh /scripts/run.sh
60
+COPY hack/make/.ensure-emptyfs /scripts/ensure-emptyfs.sh
61
+
62
+COPY --from=builder /output/docker-frozen-images /docker-frozen-images
63
+COPY --from=builder /output/httpserver /tests/contrib/httpserver/httpserver
64
+COPY --from=builder /output/tests /tests
65
+COPY --from=builder /usr/local/bin/docker /usr/bin/docker
66
+
67
+ENV DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/
68
+
69
+ENTRYPOINT ["/scripts/run.sh"]
0 70
new file mode 100755
... ...
@@ -0,0 +1,41 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+TESTFLAGS=${TESTFLAGS:-""}
4
+# Currently only DockerSuite and DockerNetworkSuite have been adapted for E2E testing
5
+TESTFLAGS_LEGACY=${TESTFLAGS_LEGACY:-""}
6
+TIMEOUT=${TIMEOUT:-60m}
7
+
8
+SCRIPTDIR="$(dirname ${BASH_SOURCE[0]})"
9
+
10
+export DOCKER_ENGINE_GOARCH=${DOCKER_ENGINE_GOARCH:-amd64}
11
+
12
+run_test_integration() {
13
+  run_test_integration_suites
14
+  run_test_integration_legacy_suites
15
+}
16
+
17
+run_test_integration_suites() {
18
+  local flags="-test.v -test.timeout=${TIMEOUT} $TESTFLAGS"
19
+  for dir in /tests/integration/*; do
20
+    if ! (
21
+      cd $dir
22
+      echo "Running $PWD"
23
+      ./test.main $flags
24
+    ); then exit 1; fi
25
+  done
26
+}
27
+
28
+run_test_integration_legacy_suites() {
29
+  (
30
+    flags="-check.v -check.timeout=${TIMEOUT} -test.timeout=360m $TESTFLAGS_LEGACY"
31
+    cd /tests/integration-cli
32
+    echo "Running $PWD"
33
+    ./test.main $flags
34
+  )
35
+}
36
+
37
+bash $SCRIPTDIR/ensure-emptyfs.sh
38
+
39
+echo "Run integration tests"
40
+run_test_integration
... ...
@@ -67,7 +67,7 @@ func TestMain(m *testing.M) {
67 67
 func Test(t *testing.T) {
68 68
 	cli.SetTestEnvironment(testEnv)
69 69
 	fakestorage.SetTestEnvironment(&testEnv.Execution)
70
-	ienv.ProtectImages(t, &testEnv.Execution)
70
+	ienv.ProtectAll(t, &testEnv.Execution)
71 71
 	check.TestingT(t)
72 72
 }
73 73
 
... ...
@@ -120,7 +120,7 @@ func (s *DockerRegistrySuite) OnTimeout(c *check.C) {
120 120
 }
121 121
 
122 122
 func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
123
-	testRequires(c, DaemonIsLinux, registry.Hosting)
123
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
124 124
 	s.reg = setupRegistry(c, false, "", "")
125 125
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
126 126
 		Experimental: testEnv.ExperimentalDaemon(),
... ...
@@ -154,7 +154,7 @@ func (s *DockerSchema1RegistrySuite) OnTimeout(c *check.C) {
154 154
 }
155 155
 
156 156
 func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
157
-	testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64)
157
+	testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64, SameHostDaemon)
158 158
 	s.reg = setupRegistry(c, true, "", "")
159 159
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
160 160
 		Experimental: testEnv.ExperimentalDaemon(),
... ...
@@ -188,7 +188,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(c *check.C) {
188 188
 }
189 189
 
190 190
 func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *check.C) {
191
-	testRequires(c, DaemonIsLinux, registry.Hosting)
191
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
192 192
 	s.reg = setupRegistry(c, false, "htpasswd", "")
193 193
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
194 194
 		Experimental: testEnv.ExperimentalDaemon(),
... ...
@@ -224,7 +224,7 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *check.C) {
224 224
 }
225 225
 
226 226
 func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *check.C) {
227
-	testRequires(c, DaemonIsLinux, registry.Hosting)
227
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
228 228
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
229 229
 		Experimental: testEnv.ExperimentalDaemon(),
230 230
 	})
... ...
@@ -319,7 +319,7 @@ func (s *DockerSwarmSuite) OnTimeout(c *check.C) {
319 319
 }
320 320
 
321 321
 func (s *DockerSwarmSuite) SetUpTest(c *check.C) {
322
-	testRequires(c, DaemonIsLinux)
322
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
323 323
 }
324 324
 
325 325
 func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemon.Swarm {
... ...
@@ -471,7 +471,7 @@ func (ps *DockerPluginSuite) getPluginRepoWithTag() string {
471 471
 }
472 472
 
473 473
 func (ps *DockerPluginSuite) SetUpSuite(c *check.C) {
474
-	testRequires(c, DaemonIsLinux)
474
+	testRequires(c, DaemonIsLinux, registry.Hosting)
475 475
 	ps.registry = setupRegistry(c, false, "", "")
476 476
 
477 477
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
... ...
@@ -39,27 +39,34 @@ func ensureHTTPServerImage(t testingT) {
39 39
 		goarch = "amd64"
40 40
 	}
41 41
 
42
-	goCmd, lookErr := exec.LookPath("go")
42
+	cpCmd, lookErr := exec.LookPath("cp")
43 43
 	if lookErr != nil {
44 44
 		t.Fatalf("could not build http server: %v", lookErr)
45 45
 	}
46 46
 
47
-	cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
48
-	cmd.Env = append(os.Environ(), []string{
49
-		"CGO_ENABLED=0",
50
-		"GOOS=" + goos,
51
-		"GOARCH=" + goarch,
52
-	}...)
53
-	var out []byte
54
-	if out, err = cmd.CombinedOutput(); err != nil {
55
-		t.Fatalf("could not build http server: %s", string(out))
56
-	}
47
+	if _, err = os.Stat("../contrib/httpserver/httpserver"); os.IsNotExist(err) {
48
+		goCmd, lookErr := exec.LookPath("go")
49
+		if lookErr != nil {
50
+			t.Fatalf("could not build http server: %v", lookErr)
51
+		}
57 52
 
58
-	cpCmd, lookErr := exec.LookPath("cp")
59
-	if lookErr != nil {
60
-		t.Fatalf("could not build http server: %v", lookErr)
53
+		cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
54
+		cmd.Env = append(os.Environ(), []string{
55
+			"CGO_ENABLED=0",
56
+			"GOOS=" + goos,
57
+			"GOARCH=" + goarch,
58
+		}...)
59
+		var out []byte
60
+		if out, err = cmd.CombinedOutput(); err != nil {
61
+			t.Fatalf("could not build http server: %s", string(out))
62
+		}
63
+	} else {
64
+		if out, err := exec.Command(cpCmd, "../contrib/httpserver/httpserver", filepath.Join(tmp, "httpserver")).CombinedOutput(); err != nil {
65
+			t.Fatalf("could not copy http server: %v", string(out))
66
+		}
61 67
 	}
62
-	if out, err = exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil {
68
+
69
+	if out, err := exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil {
63 70
 		t.Fatalf("could not build http server: %v", string(out))
64 71
 	}
65 72
 
... ...
@@ -28,6 +28,7 @@ import (
28 28
 
29 29
 func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) {
30 30
 	testRequires(c, NotUserNamespace)
31
+
31 32
 	var testD string
32 33
 	if testEnv.DaemonPlatform() == "windows" {
33 34
 		testD = `FROM busybox
... ...
@@ -71,7 +71,6 @@ func (s *DockerSuite) TestContainerAPIGetJSONNoFieldsOmitted(c *check.C) {
71 71
 	c.Assert(err, checker.IsNil)
72 72
 	c.Assert(containers, checker.HasLen, startCount+1)
73 73
 	actual := fmt.Sprintf("%+v", containers[0])
74
-	fmt.Println(actual)
75 74
 
76 75
 	// empty Labels field triggered this bug, make sense to check for everything
77 76
 	// cause even Ports for instance can trigger this bug
... ...
@@ -1372,8 +1371,7 @@ func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *check.C) {
1372 1372
 		Image: "busybox",
1373 1373
 	}
1374 1374
 
1375
-	var httpClient *http.Client
1376
-	cli, err := client.NewClient(daemonHost(), "v1.18", httpClient, map[string]string{})
1375
+	cli, err := request.NewEnvClientWithVersion("v1.18")
1377 1376
 
1378 1377
 	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
1379 1378
 	c.Assert(err, checker.IsNil)
... ...
@@ -1409,16 +1407,6 @@ func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs(
1409 1409
 	c.Assert(err.Error(), checker.Contains, "container rootfs is marked read-only")
1410 1410
 }
1411 1411
 
1412
-func (s *DockerSuite) TestContainerAPIGetContainersJSONEmpty(c *check.C) {
1413
-	cli, err := client.NewEnvClient()
1414
-	c.Assert(err, checker.IsNil)
1415
-	defer cli.Close()
1416
-
1417
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
1418
-	c.Assert(err, checker.IsNil)
1419
-	c.Assert(containers, checker.HasLen, 0)
1420
-}
1421
-
1422 1412
 func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) {
1423 1413
 	// Not supported on Windows
1424 1414
 	testRequires(c, DaemonIsLinux)
... ...
@@ -119,7 +119,7 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) {
119 119
 }
120 120
 
121 121
 func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) {
122
-	testRequires(c, Network)
122
+	testRequires(c, Network, SameHostDaemon)
123 123
 
124 124
 	server := httptest.NewServer(http.NewServeMux())
125 125
 	defer server.Close()
... ...
@@ -179,8 +179,7 @@ func (s *DockerSuite) TestAPIImagesSizeCompatibility(c *check.C) {
179 179
 		Labels      map[string]string
180 180
 	}
181 181
 
182
-	var httpClient *http.Client
183
-	cli, err = client.NewClient(daemonHost(), "v1.24", httpClient, nil)
182
+	cli, err = request.NewEnvClientWithVersion("v1.24")
184 183
 	c.Assert(err, checker.IsNil)
185 184
 	defer cli.Close()
186 185
 
... ...
@@ -4,10 +4,9 @@ package main
4 4
 
5 5
 import (
6 6
 	"encoding/json"
7
-	"net/http"
8 7
 
9
-	"github.com/docker/docker/client"
10 8
 	"github.com/docker/docker/integration-cli/checker"
9
+	"github.com/docker/docker/integration-cli/request"
11 10
 	"github.com/go-check/check"
12 11
 	"golang.org/x/net/context"
13 12
 )
... ...
@@ -19,8 +18,7 @@ func (s *DockerSuite) TestInspectAPICpusetInConfigPre120(c *check.C) {
19 19
 
20 20
 	name := "cpusetinconfig-pre120"
21 21
 	dockerCmd(c, "run", "--name", name, "--cpuset-cpus", "0", "busybox", "true")
22
-	var httpClient *http.Client
23
-	cli, err := client.NewClient(daemonHost(), "v1.19", httpClient, nil)
22
+	cli, err := request.NewEnvClientWithVersion("v1.19")
24 23
 	c.Assert(err, checker.IsNil)
25 24
 	defer cli.Close()
26 25
 	_, body, err := cli.ContainerInspectWithRaw(context.Background(), name, false)
... ...
@@ -76,7 +76,7 @@ func (s *DockerSuite) TestAPINetworkFilter(c *check.C) {
76 76
 	c.Assert(nr.Name, checker.Equals, "bridge")
77 77
 }
78 78
 
79
-func (s *DockerSuite) TestAPINetworkInspect(c *check.C) {
79
+func (s *DockerSuite) TestAPINetworkInspectBridge(c *check.C) {
80 80
 	testRequires(c, DaemonIsLinux)
81 81
 	// Inspect default bridge network
82 82
 	nr := getNetworkResource(c, "bridge")
... ...
@@ -94,13 +94,15 @@ func (s *DockerSuite) TestAPINetworkInspect(c *check.C) {
94 94
 	c.Assert(nr.Internal, checker.Equals, false)
95 95
 	c.Assert(nr.EnableIPv6, checker.Equals, false)
96 96
 	c.Assert(nr.IPAM.Driver, checker.Equals, "default")
97
-	c.Assert(len(nr.Containers), checker.Equals, 1)
98 97
 	c.Assert(nr.Containers[containerID], checker.NotNil)
99 98
 
100 99
 	ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
101 100
 	c.Assert(err, checker.IsNil)
102 101
 	c.Assert(ip.String(), checker.Equals, containerIP)
102
+}
103 103
 
104
+func (s *DockerSuite) TestAPINetworkInspectUserDefinedNetwork(c *check.C) {
105
+	testRequires(c, DaemonIsLinux)
104 106
 	// IPAM configuration inspect
105 107
 	ipam := &network.IPAM{
106 108
 		Driver: "default",
... ...
@@ -117,7 +119,7 @@ func (s *DockerSuite) TestAPINetworkInspect(c *check.C) {
117 117
 	id0 := createNetwork(c, config, true)
118 118
 	c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, true)
119 119
 
120
-	nr = getNetworkResource(c, id0)
120
+	nr := getNetworkResource(c, id0)
121 121
 	c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
122 122
 	c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
123 123
 	c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
... ...
@@ -291,9 +293,16 @@ func getNetworkIDByName(c *check.C, name string) string {
291 291
 	nJSON := []types.NetworkResource{}
292 292
 	err = json.NewDecoder(body).Decode(&nJSON)
293 293
 	c.Assert(err, checker.IsNil)
294
-	c.Assert(len(nJSON), checker.Equals, 1)
294
+	var res string
295
+	for _, n := range nJSON {
296
+		// Find exact match
297
+		if n.Name == name {
298
+			res = n.ID
299
+		}
300
+	}
301
+	c.Assert(res, checker.Not(checker.Equals), "")
295 302
 
296
-	return nJSON[0].ID
303
+	return res
297 304
 }
298 305
 
299 306
 func getNetworkResource(c *check.C, id string) *types.NetworkResource {
... ...
@@ -16,16 +16,27 @@ import (
16 16
 
17 17
 func (s *DockerSuite) TestVolumesAPIList(c *check.C) {
18 18
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
19
-	dockerCmd(c, "run", "-v", prefix+"/foo", "busybox")
19
+	cid, _ := dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "busybox")
20 20
 
21 21
 	cli, err := client.NewEnvClient()
22 22
 	c.Assert(err, checker.IsNil)
23 23
 	defer cli.Close()
24 24
 
25
+	container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
26
+	c.Assert(err, checker.IsNil)
27
+	vname := container.Mounts[0].Name
28
+
25 29
 	volumes, err := cli.VolumeList(context.Background(), filters.Args{})
26 30
 	c.Assert(err, checker.IsNil)
27 31
 
28
-	c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
32
+	found := false
33
+	for _, vol := range volumes.Volumes {
34
+		if vol.Name == vname {
35
+			found = true
36
+			break
37
+		}
38
+	}
39
+	c.Assert(found, checker.Equals, true)
29 40
 }
30 41
 
31 42
 func (s *DockerSuite) TestVolumesAPICreate(c *check.C) {
... ...
@@ -45,21 +56,21 @@ func (s *DockerSuite) TestVolumesAPICreate(c *check.C) {
45 45
 
46 46
 func (s *DockerSuite) TestVolumesAPIRemove(c *check.C) {
47 47
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
48
-	dockerCmd(c, "run", "-v", prefix+"/foo", "--name=test", "busybox")
48
+	cid, _ := dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "--name=test", "busybox")
49 49
 
50 50
 	cli, err := client.NewEnvClient()
51 51
 	c.Assert(err, checker.IsNil)
52 52
 	defer cli.Close()
53 53
 
54
-	volumes, err := cli.VolumeList(context.Background(), filters.Args{})
54
+	container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
55 55
 	c.Assert(err, checker.IsNil)
56
+	vname := container.Mounts[0].Name
56 57
 
57
-	v := volumes.Volumes[0]
58
-	err = cli.VolumeRemove(context.Background(), v.Name, false)
58
+	err = cli.VolumeRemove(context.Background(), vname, false)
59 59
 	c.Assert(err.Error(), checker.Contains, "volume is in use")
60 60
 
61 61
 	dockerCmd(c, "rm", "-f", "test")
62
-	err = cli.VolumeRemove(context.Background(), v.Name, false)
62
+	err = cli.VolumeRemove(context.Background(), vname, false)
63 63
 	c.Assert(err, checker.IsNil)
64 64
 }
65 65
 
... ...
@@ -78,10 +89,6 @@ func (s *DockerSuite) TestVolumesAPIInspect(c *check.C) {
78 78
 	_, err = cli.VolumeCreate(context.Background(), config)
79 79
 	c.Assert(err, check.IsNil)
80 80
 
81
-	volumes, err := cli.VolumeList(context.Background(), filters.Args{})
82
-	c.Assert(err, checker.IsNil)
83
-	c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
84
-
85 81
 	vol, err := cli.VolumeInspect(context.Background(), config.Name)
86 82
 	c.Assert(err, checker.IsNil)
87 83
 	c.Assert(vol.Name, checker.Equals, config.Name)
... ...
@@ -173,7 +173,7 @@ func (s *DockerSuite) TestAttachDetach(c *check.C) {
173 173
 	c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
174 174
 
175 175
 	go func() {
176
-		dockerCmd(c, "kill", id)
176
+		dockerCmdWithResult("kill", id)
177 177
 	}()
178 178
 
179 179
 	select {
... ...
@@ -225,7 +225,7 @@ func (s *DockerSuite) TestAttachDetachTruncatedID(c *check.C) {
225 225
 	c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
226 226
 
227 227
 	go func() {
228
-		dockerCmd(c, "kill", id)
228
+		dockerCmdWithResult("kill", id)
229 229
 	}()
230 230
 
231 231
 	select {
... ...
@@ -4,7 +4,6 @@ package main
4 4
 
5 5
 import (
6 6
 	"fmt"
7
-	"strings"
8 7
 
9 8
 	"github.com/docker/docker/integration-cli/checker"
10 9
 	"github.com/docker/docker/integration-cli/daemon"
... ...
@@ -31,7 +30,7 @@ type DockerAuthzV2Suite struct {
31 31
 }
32 32
 
33 33
 func (s *DockerAuthzV2Suite) SetUpTest(c *check.C) {
34
-	testRequires(c, DaemonIsLinux, Network)
34
+	testRequires(c, DaemonIsLinux, Network, SameHostDaemon)
35 35
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
36 36
 		Experimental: testEnv.ExperimentalDaemon(),
37 37
 	})
... ...
@@ -47,6 +46,7 @@ func (s *DockerAuthzV2Suite) TearDownTest(c *check.C) {
47 47
 
48 48
 func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) {
49 49
 	testRequires(c, DaemonIsLinux, IsAmd64, Network)
50
+
50 51
 	// Install authz plugin
51 52
 	_, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", authzPluginNameWithTag)
52 53
 	c.Assert(err, checker.IsNil)
... ...
@@ -65,14 +65,8 @@ func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) {
65 65
 	}()
66 66
 
67 67
 	// Ensure docker run command and accompanying docker ps are successful
68
-	out, err := s.d.Cmd("run", "-d", "busybox", "top")
69
-	c.Assert(err, check.IsNil)
70
-
71
-	id := strings.TrimSpace(out)
72
-
73
-	out, err = s.d.Cmd("ps")
68
+	_, err = s.d.Cmd("run", "-d", "busybox", "top")
74 69
 	c.Assert(err, check.IsNil)
75
-	c.Assert(assertContainerList(out, []string{id}), check.Equals, true)
76 70
 }
77 71
 
78 72
 func (s *DockerAuthzV2Suite) TestAuthZPluginDisable(c *check.C) {
... ...
@@ -64,6 +64,7 @@ type authorizationController struct {
64 64
 }
65 65
 
66 66
 func (s *DockerAuthzSuite) SetUpTest(c *check.C) {
67
+	testRequires(c, SameHostDaemon)
67 68
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
68 69
 		Experimental: testEnv.ExperimentalDaemon(),
69 70
 	})
... ...
@@ -218,12 +219,6 @@ func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) {
218 218
 	id := strings.TrimSpace(out)
219 219
 	assertURIRecorded(c, s.ctrl.requestsURIs, "/containers/create")
220 220
 	assertURIRecorded(c, s.ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", id))
221
-
222
-	out, err = s.d.Cmd("ps")
223
-	c.Assert(err, check.IsNil)
224
-	c.Assert(assertContainerList(out, []string{id}), check.Equals, true)
225
-	c.Assert(s.ctrl.psRequestCnt, check.Equals, 1)
226
-	c.Assert(s.ctrl.psResponseCnt, check.Equals, 1)
227 221
 }
228 222
 
229 223
 func (s *DockerAuthzSuite) TestAuthZPluginTls(c *check.C) {
... ...
@@ -27,17 +27,18 @@ import (
27 27
 func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) {
28 28
 	testRequires(c, cpuCfsQuota)
29 29
 	name := "testbuildresourceconstraints"
30
+	buildLabel := "DockerSuite.TestBuildResourceConstraintsAreUsed"
30 31
 
31 32
 	ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(`
32 33
 	FROM hello-world:frozen
33 34
 	RUN ["/hello"]
34 35
 	`))
35 36
 	cli.Docker(
36
-		cli.Args("build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "--ulimit", "nofile=42", "-t", name, "."),
37
+		cli.Args("build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "--ulimit", "nofile=42", "--label="+buildLabel, "-t", name, "."),
37 38
 		cli.InDir(ctx.Dir),
38 39
 	).Assert(c, icmd.Success)
39 40
 
40
-	out := cli.DockerCmd(c, "ps", "-lq").Combined()
41
+	out := cli.DockerCmd(c, "ps", "-lq", "--filter", "label="+buildLabel).Combined()
41 42
 	cID := strings.TrimSpace(out)
42 43
 
43 44
 	type hostConfig struct {
... ...
@@ -407,6 +407,8 @@ func (s *DockerRegistrySuite) TestInspectImageWithDigests(c *check.C) {
407 407
 }
408 408
 
409 409
 func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c *check.C) {
410
+	existingContainers := ExistingContainerIDs(c)
411
+
410 412
 	digest, err := setupImage(c)
411 413
 	c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
412 414
 
... ...
@@ -438,7 +440,7 @@ func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c
438 438
 
439 439
 	// Valid imageReference
440 440
 	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageReference)
441
-	checkPsAncestorFilterOutput(c, out, imageReference, expectedIDs)
441
+	checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageReference, expectedIDs)
442 442
 }
443 443
 
444 444
 func (s *DockerRegistrySuite) TestDeleteImageByIDOnlyPulledByDigest(c *check.C) {
... ...
@@ -11,6 +11,7 @@ import (
11 11
 )
12 12
 
13 13
 func (s *DockerSwarmSuite) TestConfigList(c *check.C) {
14
+	testRequires(c, SameHostDaemon)
14 15
 	d := s.AddDaemon(c, true, true)
15 16
 
16 17
 	testName0 := "test0"
... ...
@@ -50,6 +50,7 @@ type DockerExternalVolumeSuite struct {
50 50
 }
51 51
 
52 52
 func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) {
53
+	testRequires(c, SameHostDaemon)
53 54
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
54 55
 		Experimental: testEnv.ExperimentalDaemon(),
55 56
 	})
... ...
@@ -39,6 +39,8 @@ func getHealth(c *check.C, name string) *types.Health {
39 39
 func (s *DockerSuite) TestHealth(c *check.C) {
40 40
 	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows
41 41
 
42
+	existingContainers := ExistingContainerIDs(c)
43
+
42 44
 	imageName := "testhealth"
43 45
 	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
44 46
 		RUN echo OK > /status
... ...
@@ -49,9 +51,10 @@ func (s *DockerSuite) TestHealth(c *check.C) {
49 49
 
50 50
 	// No health status before starting
51 51
 	name := "test_health"
52
-	dockerCmd(c, "create", "--name", name, imageName)
53
-	out, _ := dockerCmd(c, "ps", "-a", "--format={{.Status}}")
54
-	c.Check(out, checker.Equals, "Created\n")
52
+	cid, _ := dockerCmd(c, "create", "--name", name, imageName)
53
+	out, _ := dockerCmd(c, "ps", "-a", "--format={{.ID}} {{.Status}}")
54
+	out = RemoveOutputForExistingElements(out, existingContainers)
55
+	c.Check(out, checker.Equals, cid[:12]+" Created\n")
55 56
 
56 57
 	// Inspect the options
57 58
 	out, _ = dockerCmd(c, "inspect",
... ...
@@ -135,42 +135,48 @@ func (s *DockerSuite) TestInfoDiscoveryAdvertiseInterfaceName(c *check.C) {
135 135
 func (s *DockerSuite) TestInfoDisplaysRunningContainers(c *check.C) {
136 136
 	testRequires(c, DaemonIsLinux)
137 137
 
138
+	existing := existingContainerStates(c)
139
+
138 140
 	dockerCmd(c, "run", "-d", "busybox", "top")
139 141
 	out, _ := dockerCmd(c, "info")
140
-	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
141
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 1))
142
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 0))
143
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 0))
142
+	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", existing["Containers"]+1))
143
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", existing["ContainersRunning"]+1))
144
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", existing["ContainersPaused"]))
145
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", existing["ContainersStopped"]))
144 146
 }
145 147
 
146 148
 func (s *DockerSuite) TestInfoDisplaysPausedContainers(c *check.C) {
147 149
 	testRequires(c, IsPausable)
148 150
 
151
+	existing := existingContainerStates(c)
152
+
149 153
 	out := runSleepingContainer(c, "-d")
150 154
 	cleanedContainerID := strings.TrimSpace(out)
151 155
 
152 156
 	dockerCmd(c, "pause", cleanedContainerID)
153 157
 
154 158
 	out, _ = dockerCmd(c, "info")
155
-	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
156
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 0))
157
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 1))
158
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 0))
159
+	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", existing["Containers"]+1))
160
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", existing["ContainersRunning"]))
161
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", existing["ContainersPaused"]+1))
162
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", existing["ContainersStopped"]))
159 163
 }
160 164
 
161 165
 func (s *DockerSuite) TestInfoDisplaysStoppedContainers(c *check.C) {
162 166
 	testRequires(c, DaemonIsLinux)
163 167
 
168
+	existing := existingContainerStates(c)
169
+
164 170
 	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
165 171
 	cleanedContainerID := strings.TrimSpace(out)
166 172
 
167 173
 	dockerCmd(c, "stop", cleanedContainerID)
168 174
 
169 175
 	out, _ = dockerCmd(c, "info")
170
-	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
171
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 0))
172
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 0))
173
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 1))
176
+	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", existing["Containers"]+1))
177
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", existing["ContainersRunning"]))
178
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", existing["ContainersPaused"]))
179
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", existing["ContainersStopped"]+1))
174 180
 }
175 181
 
176 182
 func (s *DockerSuite) TestInfoDebug(c *check.C) {
... ...
@@ -237,3 +243,16 @@ func (s *DockerDaemonSuite) TestInfoLabels(c *check.C) {
237 237
 	c.Assert(err, checker.IsNil)
238 238
 	c.Assert(out, checker.Contains, "WARNING: labels with duplicate keys and conflicting values have been deprecated")
239 239
 }
240
+
241
+func existingContainerStates(c *check.C) map[string]int {
242
+	out, _ := dockerCmd(c, "info", "--format", "{{json .}}")
243
+	var m map[string]interface{}
244
+	err := json.Unmarshal([]byte(out), &m)
245
+	c.Assert(err, checker.IsNil)
246
+	res := map[string]int{}
247
+	res["Containers"] = int(m["Containers"].(float64))
248
+	res["ContainersRunning"] = int(m["ContainersRunning"].(float64))
249
+	res["ContainersPaused"] = int(m["ContainersPaused"].(float64))
250
+	res["ContainersStopped"] = int(m["ContainersStopped"].(float64))
251
+	return res
252
+}
... ...
@@ -1,13 +1,12 @@
1 1
 package main
2 2
 
3 3
 import (
4
-	"net/http"
5 4
 	"strings"
6 5
 	"time"
7 6
 
8
-	"github.com/docker/docker/client"
9 7
 	"github.com/docker/docker/integration-cli/checker"
10 8
 	"github.com/docker/docker/integration-cli/cli"
9
+	"github.com/docker/docker/integration-cli/request"
11 10
 	"github.com/go-check/check"
12 11
 	"github.com/gotestyourself/gotestyourself/icmd"
13 12
 	"golang.org/x/net/context"
... ...
@@ -131,8 +130,7 @@ func (s *DockerSuite) TestKillStoppedContainerAPIPre120(c *check.C) {
131 131
 	testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later
132 132
 	runSleepingContainer(c, "--name", "docker-kill-test-api", "-d")
133 133
 	dockerCmd(c, "stop", "docker-kill-test-api")
134
-	var httpClient *http.Client
135
-	cli, err := client.NewClient(daemonHost(), "v1.19", httpClient, nil)
134
+	cli, err := request.NewEnvClientWithVersion("v1.19")
136 135
 	c.Assert(err, check.IsNil)
137 136
 	defer cli.Close()
138 137
 	err = cli.ContainerKill(context.Background(), "docker-kill-test-api", "SIGKILL")
... ...
@@ -10,7 +10,6 @@ import (
10 10
 	"net/http"
11 11
 	"net/http/httptest"
12 12
 	"os"
13
-	"path/filepath"
14 13
 	"strings"
15 14
 	"time"
16 15
 
... ...
@@ -288,39 +287,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) {
288 288
 	}
289 289
 }
290 290
 
291
-func (s *DockerSuite) TestNetworkLsFormat(c *check.C) {
292
-	testRequires(c, DaemonIsLinux)
293
-	out, _ := dockerCmd(c, "network", "ls", "--format", "{{.Name}}")
294
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
295
-
296
-	expected := []string{"bridge", "host", "none"}
297
-	var names []string
298
-	names = append(names, lines...)
299
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
300
-}
301
-
302
-func (s *DockerSuite) TestNetworkLsFormatDefaultFormat(c *check.C) {
303
-	testRequires(c, DaemonIsLinux)
304
-
305
-	config := `{
306
-		"networksFormat": "{{ .Name }} default"
307
-}`
308
-	d, err := ioutil.TempDir("", "integration-cli-")
309
-	c.Assert(err, checker.IsNil)
310
-	defer os.RemoveAll(d)
311
-
312
-	err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
313
-	c.Assert(err, checker.IsNil)
314
-
315
-	out, _ := dockerCmd(c, "--config", d, "network", "ls")
316
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
317
-
318
-	expected := []string{"bridge default", "host default", "none default"}
319
-	var names []string
320
-	names = append(names, lines...)
321
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
322
-}
323
-
324 291
 func (s *DockerNetworkSuite) TestDockerNetworkCreatePredefined(c *check.C) {
325 292
 	predefined := []string{"bridge", "host", "none", "default"}
326 293
 	for _, net := range predefined {
... ...
@@ -351,6 +317,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) {
351 351
 }
352 352
 
353 353
 func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
354
+	testRequires(c, OnlyDefaultNetworks)
354 355
 	testNet := "testnet1"
355 356
 	testLabel := "foo"
356 357
 	testValue := "bar"
... ...
@@ -624,6 +591,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
624 624
 }
625 625
 
626 626
 func (s *DockerNetworkSuite) TestDockerNetworkIPAMMultipleNetworks(c *check.C) {
627
+	testRequires(c, SameHostDaemon)
627 628
 	// test0 bridge network
628 629
 	dockerCmd(c, "network", "create", "--subnet=192.168.0.0/16", "test1")
629 630
 	assertNwIsAvailable(c, "test1")
... ...
@@ -664,6 +632,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIPAMMultipleNetworks(c *check.C) {
664 664
 }
665 665
 
666 666
 func (s *DockerNetworkSuite) TestDockerNetworkCustomIPAM(c *check.C) {
667
+	testRequires(c, SameHostDaemon)
667 668
 	// Create a bridge network using custom ipam driver
668 669
 	dockerCmd(c, "network", "create", "--ipam-driver", dummyIPAMDriver, "br0")
669 670
 	assertNwIsAvailable(c, "br0")
... ...
@@ -679,6 +648,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkCustomIPAM(c *check.C) {
679 679
 }
680 680
 
681 681
 func (s *DockerNetworkSuite) TestDockerNetworkIPAMOptions(c *check.C) {
682
+	testRequires(c, SameHostDaemon)
682 683
 	// Create a bridge network using custom ipam driver and options
683 684
 	dockerCmd(c, "network", "create", "--ipam-driver", dummyIPAMDriver, "--ipam-opt", "opt1=drv1", "--ipam-opt", "opt2=drv2", "br0")
684 685
 	assertNwIsAvailable(c, "br0")
... ...
@@ -691,6 +661,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIPAMOptions(c *check.C) {
691 691
 }
692 692
 
693 693
 func (s *DockerNetworkSuite) TestDockerNetworkNullIPAMDriver(c *check.C) {
694
+	testRequires(c, SameHostDaemon)
694 695
 	// Create a network with null ipam driver
695 696
 	_, _, err := dockerCmdWithError("network", "create", "-d", dummyNetworkDriver, "--ipam-driver", "null", "test000")
696 697
 	c.Assert(err, check.IsNil)
... ...
@@ -796,6 +767,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIPAMInvalidCombinations(c *check.C
796 796
 }
797 797
 
798 798
 func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
799
+	testRequires(c, SameHostDaemon)
799 800
 	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt")
800 801
 	assertNwIsAvailable(c, "testopt")
801 802
 	gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData]
... ...
@@ -981,6 +953,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkLinkOnDefaultNetworkOnly(c *check.
981 981
 }
982 982
 
983 983
 func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
984
+	testRequires(c, SameHostDaemon)
984 985
 	// Verify exposed ports are present in ps output when running a container on
985 986
 	// a network managed by a driver which does not provide the default gateway
986 987
 	// for the container
... ...
@@ -1007,7 +980,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
1007 1007
 }
1008 1008
 
1009 1009
 func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C) {
1010
-	testRequires(c, DaemonIsLinux, NotUserNamespace)
1010
+	testRequires(c, DaemonIsLinux, NotUserNamespace, SameHostDaemon)
1011 1011
 	dnd := "dnd"
1012 1012
 	did := "did"
1013 1013
 
... ...
@@ -1048,6 +1021,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C
1048 1048
 }
1049 1049
 
1050 1050
 func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) {
1051
+	testRequires(c, SameHostDaemon)
1051 1052
 	// Verify endpoint MAC address is correctly populated in container's network settings
1052 1053
 	nwn := "ov"
1053 1054
 	ctn := "bb"
... ...
@@ -1113,6 +1087,7 @@ func verifyContainerIsConnectedToNetworks(c *check.C, d *daemon.Daemon, cName st
1113 1113
 }
1114 1114
 
1115 1115
 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *check.C) {
1116
+	testRequires(c, SameHostDaemon)
1116 1117
 	cName := "bb"
1117 1118
 	nwList := []string{"nw1", "nw2", "nw3"}
1118 1119
 
... ...
@@ -1131,6 +1106,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRest
1131 1131
 }
1132 1132
 
1133 1133
 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) {
1134
+	testRequires(c, SameHostDaemon)
1134 1135
 	cName := "cc"
1135 1136
 	nwList := []string{"nw1", "nw2", "nw3"}
1136 1137
 
... ...
@@ -1157,7 +1133,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *check.C) {
1157 1157
 }
1158 1158
 
1159 1159
 func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *check.C) {
1160
-	testRequires(c, DaemonIsLinux, NotUserNamespace)
1160
+	testRequires(c, DaemonIsLinux, NotUserNamespace, SameHostDaemon)
1161 1161
 	s.d.StartWithBusybox(c)
1162 1162
 
1163 1163
 	// Run a few containers on host network
... ...
@@ -1283,6 +1259,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRestartWithMultipleNetworks(c *che
1283 1283
 }
1284 1284
 
1285 1285
 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContainer(c *check.C) {
1286
+	testRequires(c, SameHostDaemon)
1286 1287
 	dockerCmd(c, "network", "create", "test")
1287 1288
 	dockerCmd(c, "create", "--name=foo", "busybox", "top")
1288 1289
 	dockerCmd(c, "network", "connect", "test", "foo")
... ...
@@ -1810,7 +1787,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromBridge(c *check.C) {
1810 1810
 // TestConntrackFlowsLeak covers the failure scenario of ticket: https://github.com/docker/docker/issues/8795
1811 1811
 // Validates that conntrack is correctly cleaned once a container is destroyed
1812 1812
 func (s *DockerNetworkSuite) TestConntrackFlowsLeak(c *check.C) {
1813
-	testRequires(c, IsAmd64, DaemonIsLinux, Network)
1813
+	testRequires(c, IsAmd64, DaemonIsLinux, Network, SameHostDaemon)
1814 1814
 
1815 1815
 	// Create a new network
1816 1816
 	cli.DockerCmd(c, "network", "create", "--subnet=192.168.10.0/24", "--gateway=192.168.10.1", "-o", "com.docker.network.bridge.host_binding_ipv4=192.168.10.1", "testbind")
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"net"
6 6
 	"regexp"
7 7
 	"sort"
8
+	"strconv"
8 9
 	"strings"
9 10
 
10 11
 	"github.com/docker/docker/integration-cli/checker"
... ...
@@ -148,9 +149,8 @@ func (s *DockerSuite) TestPortList(c *check.C) {
148 148
 
149 149
 	out, _ = dockerCmd(c, "port", ID)
150 150
 
151
-	err = assertPortList(c, out, []string{
152
-		"80/tcp -> 0.0.0.0:8000",
153
-		"80/udp -> 0.0.0.0:8000"})
151
+	// Running this test multiple times causes the TCP port to increment.
152
+	err = assertPortRange(c, out, []int{8000, 8080}, []int{8000, 8080})
154 153
 	// Port list is not correct
155 154
 	c.Assert(err, checker.IsNil)
156 155
 	dockerCmd(c, "rm", "-f", ID)
... ...
@@ -173,6 +173,38 @@ func assertPortList(c *check.C, out string, expected []string) error {
173 173
 	return nil
174 174
 }
175 175
 
176
+func assertPortRange(c *check.C, out string, expectedTcp, expectedUdp []int) error {
177
+	lines := strings.Split(strings.Trim(out, "\n "), "\n")
178
+
179
+	var validTcp, validUdp bool
180
+	for _, l := range lines {
181
+		// 80/tcp -> 0.0.0.0:8015
182
+		port, err := strconv.Atoi(strings.Split(l, ":")[1])
183
+		if err != nil {
184
+			return err
185
+		}
186
+		if strings.Contains(l, "tcp") && expectedTcp != nil {
187
+			if port < expectedTcp[0] || port > expectedTcp[1] {
188
+				return fmt.Errorf("tcp port (%d) not in range expected range %d-%d", port, expectedTcp[0], expectedTcp[1])
189
+			}
190
+			validTcp = true
191
+		}
192
+		if strings.Contains(l, "udp") && expectedUdp != nil {
193
+			if port < expectedUdp[0] || port > expectedUdp[1] {
194
+				return fmt.Errorf("udp port (%d) not in range expected range %d-%d", port, expectedUdp[0], expectedUdp[1])
195
+			}
196
+			validUdp = true
197
+		}
198
+	}
199
+	if !validTcp {
200
+		return fmt.Errorf("tcp port not found")
201
+	}
202
+	if !validUdp {
203
+		return fmt.Errorf("udp port not found")
204
+	}
205
+	return nil
206
+}
207
+
176 208
 func stopRemoveContainer(id string, c *check.C) {
177 209
 	dockerCmd(c, "rm", "-f", id)
178 210
 }
... ...
@@ -19,6 +19,8 @@ import (
19 19
 )
20 20
 
21 21
 func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
22
+	existingContainers := ExistingContainerIDs(c)
23
+
22 24
 	out := runSleepingContainer(c, "-d")
23 25
 	firstID := strings.TrimSpace(out)
24 26
 
... ...
@@ -43,79 +45,79 @@ func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
43 43
 
44 44
 	// all
45 45
 	out, _ = dockerCmd(c, "ps", "-a")
46
-	c.Assert(assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}), checker.Equals, true, check.Commentf("ALL: Container list is not in the correct order: \n%s", out))
46
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{fourthID, thirdID, secondID, firstID}), checker.Equals, true, check.Commentf("ALL: Container list is not in the correct order: \n%s", out))
47 47
 
48 48
 	// running
49 49
 	out, _ = dockerCmd(c, "ps")
50
-	c.Assert(assertContainerList(out, []string{fourthID, secondID, firstID}), checker.Equals, true, check.Commentf("RUNNING: Container list is not in the correct order: \n%s", out))
50
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{fourthID, secondID, firstID}), checker.Equals, true, check.Commentf("RUNNING: Container list is not in the correct order: \n%s", out))
51 51
 
52 52
 	// limit
53 53
 	out, _ = dockerCmd(c, "ps", "-n=2", "-a")
54 54
 	expected := []string{fourthID, thirdID}
55
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
55
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
56 56
 
57 57
 	out, _ = dockerCmd(c, "ps", "-n=2")
58
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
58
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
59 59
 
60 60
 	// filter since
61 61
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-a")
62 62
 	expected = []string{fourthID, thirdID, secondID}
63
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out))
63
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out))
64 64
 
65 65
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID)
66 66
 	expected = []string{fourthID, secondID}
67
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
67
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
68 68
 
69 69
 	out, _ = dockerCmd(c, "ps", "-f", "since="+thirdID)
70 70
 	expected = []string{fourthID}
71
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
71
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
72 72
 
73 73
 	// filter before
74 74
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-a")
75 75
 	expected = []string{thirdID, secondID, firstID}
76
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
76
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
77 77
 
78 78
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID)
79 79
 	expected = []string{secondID, firstID}
80
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Container list is not in the correct order: \n%s", out))
80
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("BEFORE filter: Container list is not in the correct order: \n%s", out))
81 81
 
82 82
 	out, _ = dockerCmd(c, "ps", "-f", "before="+thirdID)
83 83
 	expected = []string{secondID, firstID}
84
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
84
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
85 85
 
86 86
 	// filter since & before
87 87
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-a")
88 88
 	expected = []string{thirdID, secondID}
89
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
89
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
90 90
 
91 91
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID)
92 92
 	expected = []string{secondID}
93
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter: Container list is not in the correct order: \n%s", out))
93
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter: Container list is not in the correct order: \n%s", out))
94 94
 
95 95
 	// filter since & limit
96 96
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a")
97 97
 	expected = []string{fourthID, thirdID}
98 98
 
99
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
99
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
100 100
 
101 101
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2")
102
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out))
102
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out))
103 103
 
104 104
 	// filter before & limit
105 105
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a")
106 106
 	expected = []string{thirdID}
107
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
107
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
108 108
 
109 109
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1")
110
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
110
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
111 111
 
112 112
 	// filter since & filter before & limit
113 113
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a")
114 114
 	expected = []string{thirdID}
115
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
115
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT & ALL: Container list is not in the correct order: \n%s", out))
116 116
 
117 117
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1")
118
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
118
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("SINCE filter, BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
119 119
 
120 120
 }
121 121
 
... ...
@@ -185,6 +187,8 @@ func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
185 185
 }
186 186
 
187 187
 func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
188
+	existingContainers := ExistingContainerIDs(c)
189
+
188 190
 	// start exited container
189 191
 	out := cli.DockerCmd(c, "run", "-d", "busybox").Combined()
190 192
 	firstID := strings.TrimSpace(out)
... ...
@@ -199,11 +203,11 @@ func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
199 199
 	// filter containers by exited
200 200
 	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited").Combined()
201 201
 	containerOut := strings.TrimSpace(out)
202
-	c.Assert(containerOut, checker.Equals, firstID)
202
+	c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, firstID)
203 203
 
204 204
 	out = cli.DockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running").Combined()
205 205
 	containerOut = strings.TrimSpace(out)
206
-	c.Assert(containerOut, checker.Equals, secondID)
206
+	c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, secondID)
207 207
 
208 208
 	result := cli.Docker(cli.Args("ps", "-a", "-q", "--filter=status=rubbish"), cli.WithTimeout(time.Second*60))
209 209
 	result.Assert(c, icmd.Expected{
... ...
@@ -222,11 +226,12 @@ func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
222 222
 
223 223
 		out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused").Combined()
224 224
 		containerOut = strings.TrimSpace(out)
225
-		c.Assert(containerOut, checker.Equals, pausedID)
225
+		c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, pausedID)
226 226
 	}
227 227
 }
228 228
 
229 229
 func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) {
230
+	existingContainers := ExistingContainerIDs(c)
230 231
 	// Test legacy no health check
231 232
 	out := runSleepingContainer(c, "--name=none_legacy")
232 233
 	containerID := strings.TrimSpace(out)
... ...
@@ -264,7 +269,7 @@ func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) {
264 264
 	waitForHealthStatus(c, "passing_container", "starting", "healthy")
265 265
 
266 266
 	out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy").Combined()
267
-	containerOut = strings.TrimSpace(out)
267
+	containerOut = strings.TrimSpace(RemoveOutputForExistingElements(out, existingContainers))
268 268
 	c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out))
269 269
 }
270 270
 
... ...
@@ -305,6 +310,8 @@ func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
305 305
 // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
306 306
 // - Filter them out :P
307 307
 func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
308
+	existingContainers := ExistingContainerIDs(c)
309
+
308 310
 	// Build images
309 311
 	imageName1 := "images_ps_filter_test1"
310 312
 	buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
... ...
@@ -367,12 +374,12 @@ func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
367 367
 	var out string
368 368
 	for _, filter := range filterTestSuite {
369 369
 		out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
370
-		checkPsAncestorFilterOutput(c, out, filter.filterName, filter.expectedIDs)
370
+		checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), filter.filterName, filter.expectedIDs)
371 371
 	}
372 372
 
373 373
 	// Multiple ancestor filter
374 374
 	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
375
-	checkPsAncestorFilterOutput(c, out, imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
375
+	checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
376 376
 }
377 377
 
378 378
 func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
... ...
@@ -469,6 +476,9 @@ func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
469 469
 func (s *DockerSuite) TestPsRightTagName(c *check.C) {
470 470
 	// TODO Investigate further why this fails on Windows to Windows CI
471 471
 	testRequires(c, DaemonIsLinux)
472
+
473
+	existingContainers := ExistingContainerNames(c)
474
+
472 475
 	tag := "asybox:shmatest"
473 476
 	dockerCmd(c, "tag", "busybox", tag)
474 477
 
... ...
@@ -490,6 +500,7 @@ func (s *DockerSuite) TestPsRightTagName(c *check.C) {
490 490
 
491 491
 	out, _ = dockerCmd(c, "ps", "--no-trunc")
492 492
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
493
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
493 494
 	// skip header
494 495
 	lines = lines[1:]
495 496
 	c.Assert(lines, checker.HasLen, 3, check.Commentf("There should be 3 running container, got %d", len(lines)))
... ...
@@ -511,6 +522,7 @@ func (s *DockerSuite) TestPsRightTagName(c *check.C) {
511 511
 func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
512 512
 	// Problematic on Windows as it doesn't support links as of Jan 2016
513 513
 	testRequires(c, DaemonIsLinux)
514
+	existingContainers := ExistingContainerIDs(c)
514 515
 	runSleepingContainer(c, "--name=first")
515 516
 	runSleepingContainer(c, "--name=second", "--link=first:first")
516 517
 
... ...
@@ -518,6 +530,7 @@ func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
518 518
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
519 519
 	// strip header
520 520
 	lines = lines[1:]
521
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
521 522
 	expected := []string{"second", "first,second/first"}
522 523
 	var names []string
523 524
 	for _, l := range lines {
... ...
@@ -581,12 +594,14 @@ func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
581 581
 func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
582 582
 	// Problematic on Windows as it doesn't support link as of Jan 2016
583 583
 	testRequires(c, DaemonIsLinux)
584
+	existingContainers := ExistingContainerNames(c)
584 585
 	//create 2 containers and link them
585 586
 	dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
586 587
 	dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
587 588
 
588 589
 	//use the new format capabilities to only list the names and --no-trunc to get all names
589 590
 	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
591
+	out = RemoveOutputForExistingElements(out, existingContainers)
590 592
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
591 593
 	expected := []string{"parent", "child,parent/linkedone"}
592 594
 	var names []string
... ...
@@ -595,6 +610,7 @@ func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
595 595
 
596 596
 	//now list without turning off truncation and make sure we only get the non-link names
597 597
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
598
+	out = RemoveOutputForExistingElements(out, existingContainers)
598 599
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
599 600
 	expected = []string{"parent", "child"}
600 601
 	var truncNames []string
... ...
@@ -604,30 +620,22 @@ func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
604 604
 
605 605
 // Test for GitHub issue #21772
606 606
 func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) {
607
+	existingContainers := ExistingContainerNames(c)
607 608
 	runSleepingContainer(c, "--name=test1")
608 609
 	runSleepingContainer(c, "--name=test2")
609 610
 
610 611
 	//use the new format capabilities to list the names twice
611 612
 	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Names}}")
612 613
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
614
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
613 615
 	expected := []string{"test2 test2", "test1 test1"}
614 616
 	var names []string
615 617
 	names = append(names, lines...)
616 618
 	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with names displayed twice: %v, got: %v", expected, names))
617 619
 }
618 620
 
619
-func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
620
-	// make sure no-container "docker ps" still prints the header row
621
-	out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
622
-	c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out))
623
-
624
-	// verify that "docker ps" with a container still prints the header row also
625
-	runSleepingContainer(c, "--name=test")
626
-	out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
627
-	c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out))
628
-}
629
-
630 621
 func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
622
+	existingContainers := ExistingContainerIDs(c)
631 623
 	config := `{
632 624
 		"psFormat": "default {{ .ID }}"
633 625
 }`
... ...
@@ -642,6 +650,7 @@ func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
642 642
 	id := strings.TrimSpace(out)
643 643
 
644 644
 	out, _ = dockerCmd(c, "--config", d, "ps", "-q")
645
+	out = RemoveOutputForExistingElements(out, existingContainers)
645 646
 	c.Assert(id, checker.HasPrefix, strings.TrimSpace(out), check.Commentf("Expected to print only the container id, got %v\n", out))
646 647
 }
647 648
 
... ...
@@ -652,6 +661,8 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
652 652
 	originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
653 653
 	updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
654 654
 
655
+	existingContainers := ExistingContainerIDs(c)
656
+
655 657
 	icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success)
656 658
 
657 659
 	originalImageID := getIDByName(c, originalImageName)
... ...
@@ -664,6 +675,7 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
664 664
 	result.Assert(c, icmd.Success)
665 665
 
666 666
 	lines := strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
667
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
667 668
 	// skip header
668 669
 	lines = lines[1:]
669 670
 	c.Assert(len(lines), checker.Equals, 1)
... ...
@@ -680,6 +692,7 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
680 680
 	result.Assert(c, icmd.Success)
681 681
 
682 682
 	lines = strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
683
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
683 684
 	// skip header
684 685
 	lines = lines[1:]
685 686
 	c.Assert(len(lines), checker.Equals, 1)
... ...
@@ -710,6 +723,8 @@ func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
710 710
 }
711 711
 
712 712
 func (s *DockerSuite) TestPsShowMounts(c *check.C) {
713
+	existingContainers := ExistingContainerNames(c)
714
+
713 715
 	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
714 716
 
715 717
 	mp := prefix + slash + "test"
... ...
@@ -736,6 +751,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
736 736
 	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
737 737
 
738 738
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
739
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
739 740
 	c.Assert(lines, checker.HasLen, 3)
740 741
 
741 742
 	fields := strings.Fields(lines[0])
... ...
@@ -755,6 +771,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
755 755
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
756 756
 
757 757
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
758
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
758 759
 	c.Assert(lines, checker.HasLen, 1)
759 760
 
760 761
 	fields = strings.Fields(lines[0])
... ...
@@ -768,6 +785,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
768 768
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
769 769
 
770 770
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
771
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
771 772
 	c.Assert(lines, checker.HasLen, 2)
772 773
 
773 774
 	fields = strings.Fields(lines[0])
... ...
@@ -779,6 +797,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
779 779
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource)
780 780
 
781 781
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
782
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
782 783
 	c.Assert(lines, checker.HasLen, 1)
783 784
 
784 785
 	fields = strings.Fields(lines[0])
... ...
@@ -790,6 +809,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
790 790
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination)
791 791
 
792 792
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
793
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
793 794
 	c.Assert(lines, checker.HasLen, 1)
794 795
 
795 796
 	fields = strings.Fields(lines[0])
... ...
@@ -820,6 +840,8 @@ func (s *DockerSuite) TestPsFormatSize(c *check.C) {
820 820
 }
821 821
 
822 822
 func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
823
+	existing := ExistingContainerIDs(c)
824
+
823 825
 	// TODO default network on Windows is not called "bridge", and creating a
824 826
 	// custom network fails on Windows fails with "Error response from daemon: plugin not found")
825 827
 	testRequires(c, DaemonIsLinux)
... ...
@@ -837,7 +859,7 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
837 837
 	lines = lines[1:]
838 838
 
839 839
 	// ps output should have no containers
840
-	c.Assert(lines, checker.HasLen, 0)
840
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 0)
841 841
 
842 842
 	// Filter docker ps on network bridge
843 843
 	out, _ = dockerCmd(c, "ps", "--filter", "network=bridge")
... ...
@@ -849,7 +871,7 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
849 849
 	lines = lines[1:]
850 850
 
851 851
 	// ps output should have only one container
852
-	c.Assert(lines, checker.HasLen, 1)
852
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
853 853
 
854 854
 	// Making sure onbridgenetwork is on the output
855 855
 	c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
... ...
@@ -864,7 +886,7 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
864 864
 	lines = lines[1:]
865 865
 
866 866
 	//ps output should have both the containers
867
-	c.Assert(lines, checker.HasLen, 2)
867
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 2)
868 868
 
869 869
 	// Making sure onbridgenetwork and onnonenetwork is on the output
870 870
 	c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n"))
... ...
@@ -885,11 +907,12 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
885 885
 	containerOut = strings.TrimSpace(string(out))
886 886
 
887 887
 	lines = strings.Split(containerOut, "\n")
888
+
888 889
 	// skip header
889 890
 	lines = lines[1:]
890 891
 
891 892
 	// ps output should have only one container
892
-	c.Assert(lines, checker.HasLen, 1)
893
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
893 894
 
894 895
 	// Making sure onbridgenetwork is on the output
895 896
 	c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n"))
... ...
@@ -927,13 +950,16 @@ func (s *DockerSuite) TestPsFilterMissingArgErrorCode(c *check.C) {
927 927
 
928 928
 // Test case for 30291
929 929
 func (s *DockerSuite) TestPsFormatTemplateWithArg(c *check.C) {
930
+	existingContainers := ExistingContainerNames(c)
930 931
 	runSleepingContainer(c, "-d", "--name", "top", "--label", "some.label=label.foo-bar")
931 932
 	out, _ := dockerCmd(c, "ps", "--format", `{{.Names}} {{.Label "some.label"}}`)
933
+	out = RemoveOutputForExistingElements(out, existingContainers)
932 934
 	c.Assert(strings.TrimSpace(out), checker.Equals, "top label.foo-bar")
933 935
 }
934 936
 
935 937
 func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
936 938
 	testRequires(c, DaemonIsLinux)
939
+	existingContainers := ExistingContainerIDs(c)
937 940
 
938 941
 	out, _ := dockerCmd(c, "run", "-d", "--publish=80", "busybox", "top")
939 942
 	id1 := strings.TrimSpace(out)
... ...
@@ -962,6 +988,7 @@ func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
962 962
 	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
963 963
 
964 964
 	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp")
965
+	out = RemoveOutputForExistingElements(out, existingContainers)
965 966
 	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
966 967
 	c.Assert(strings.TrimSpace(out), checker.Equals, id2)
967 968
 }
... ...
@@ -969,11 +996,14 @@ func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
969 969
 func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *check.C) {
970 970
 	testRequires(c, DaemonIsLinux)
971 971
 
972
+	existingContainers := ExistingContainerNames(c)
973
+
972 974
 	dockerCmd(c, "create", "--name=aaa", "busybox", "top")
973 975
 	dockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top")
974 976
 
975 977
 	out, _ := dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
976 978
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
979
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
977 980
 	expected := []string{"bbb", "aaa,bbb/aaa"}
978 981
 	var names []string
979 982
 	names = append(names, lines...)
... ...
@@ -982,5 +1012,6 @@ func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *check.C) {
982 982
 	dockerCmd(c, "rm", "bbb")
983 983
 
984 984
 	out, _ = dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
985
+	out = RemoveOutputForExistingElements(out, existingContainers)
985 986
 	c.Assert(strings.TrimSpace(out), checker.Equals, "aaa")
986 987
 }
... ...
@@ -21,6 +21,7 @@ import (
21 21
 	"sync"
22 22
 	"time"
23 23
 
24
+	"github.com/docker/docker/client"
24 25
 	"github.com/docker/docker/integration-cli/checker"
25 26
 	"github.com/docker/docker/integration-cli/cli"
26 27
 	"github.com/docker/docker/integration-cli/cli/build"
... ...
@@ -35,6 +36,7 @@ import (
35 35
 	"github.com/go-check/check"
36 36
 	"github.com/gotestyourself/gotestyourself/icmd"
37 37
 	libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
38
+	"golang.org/x/net/context"
38 39
 )
39 40
 
40 41
 // "test123" should be printed by docker run
... ...
@@ -2813,23 +2815,27 @@ func (s *DockerSuite) TestRunVolumesFromRestartAfterRemoved(c *check.C) {
2813 2813
 
2814 2814
 // run container with --rm should remove container if exit code != 0
2815 2815
 func (s *DockerSuite) TestRunContainerWithRmFlagExitCodeNotEqualToZero(c *check.C) {
2816
+	existingContainers := ExistingContainerIDs(c)
2816 2817
 	name := "flowers"
2817 2818
 	cli.Docker(cli.Args("run", "--name", name, "--rm", "busybox", "ls", "/notexists")).Assert(c, icmd.Expected{
2818 2819
 		ExitCode: 1,
2819 2820
 	})
2820 2821
 
2821 2822
 	out := cli.DockerCmd(c, "ps", "-q", "-a").Combined()
2823
+	out = RemoveOutputForExistingElements(out, existingContainers)
2822 2824
 	if out != "" {
2823 2825
 		c.Fatal("Expected not to have containers", out)
2824 2826
 	}
2825 2827
 }
2826 2828
 
2827 2829
 func (s *DockerSuite) TestRunContainerWithRmFlagCannotStartContainer(c *check.C) {
2830
+	existingContainers := ExistingContainerIDs(c)
2828 2831
 	name := "sparkles"
2829 2832
 	cli.Docker(cli.Args("run", "--name", name, "--rm", "busybox", "commandNotFound")).Assert(c, icmd.Expected{
2830 2833
 		ExitCode: 127,
2831 2834
 	})
2832 2835
 	out := cli.DockerCmd(c, "ps", "-q", "-a").Combined()
2836
+	out = RemoveOutputForExistingElements(out, existingContainers)
2833 2837
 	if out != "" {
2834 2838
 		c.Fatal("Expected not to have containers", out)
2835 2839
 	}
... ...
@@ -3963,29 +3969,44 @@ func (s *DockerSuite) TestRunNamedVolumeNotRemoved(c *check.C) {
3963 3963
 	dockerCmd(c, "run", "--rm", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3964 3964
 	dockerCmd(c, "volume", "inspect", "test")
3965 3965
 	out, _ := dockerCmd(c, "volume", "ls", "-q")
3966
-	c.Assert(strings.TrimSpace(out), checker.Equals, "test")
3966
+	c.Assert(strings.TrimSpace(out), checker.Contains, "test")
3967 3967
 
3968 3968
 	dockerCmd(c, "run", "--name=test", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3969 3969
 	dockerCmd(c, "rm", "-fv", "test")
3970 3970
 	dockerCmd(c, "volume", "inspect", "test")
3971 3971
 	out, _ = dockerCmd(c, "volume", "ls", "-q")
3972
-	c.Assert(strings.TrimSpace(out), checker.Equals, "test")
3972
+	c.Assert(strings.TrimSpace(out), checker.Contains, "test")
3973 3973
 }
3974 3974
 
3975 3975
 func (s *DockerSuite) TestRunNamedVolumesFromNotRemoved(c *check.C) {
3976 3976
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
3977 3977
 
3978 3978
 	dockerCmd(c, "volume", "create", "test")
3979
-	dockerCmd(c, "run", "--name=parent", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3979
+	cid, _ := dockerCmd(c, "run", "-d", "--name=parent", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
3980 3980
 	dockerCmd(c, "run", "--name=child", "--volumes-from=parent", "busybox", "true")
3981 3981
 
3982
+	cli, err := client.NewEnvClient()
3983
+	c.Assert(err, checker.IsNil)
3984
+	defer cli.Close()
3985
+
3986
+	container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
3987
+	c.Assert(err, checker.IsNil)
3988
+	var vname string
3989
+	for _, v := range container.Mounts {
3990
+		if v.Name != "test" {
3991
+			vname = v.Name
3992
+		}
3993
+	}
3994
+	c.Assert(vname, checker.Not(checker.Equals), "")
3995
+
3982 3996
 	// Remove the parent so there are not other references to the volumes
3983 3997
 	dockerCmd(c, "rm", "-f", "parent")
3984 3998
 	// now remove the child and ensure the named volume (and only the named volume) still exists
3985 3999
 	dockerCmd(c, "rm", "-fv", "child")
3986 4000
 	dockerCmd(c, "volume", "inspect", "test")
3987 4001
 	out, _ := dockerCmd(c, "volume", "ls", "-q")
3988
-	c.Assert(strings.TrimSpace(out), checker.Equals, "test")
4002
+	c.Assert(strings.TrimSpace(out), checker.Contains, "test")
4003
+	c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), vname)
3989 4004
 }
3990 4005
 
3991 4006
 func (s *DockerSuite) TestRunAttachFailedNoLeak(c *check.C) {
... ...
@@ -4123,7 +4144,7 @@ func (s *DockerSuite) TestRunRm(c *check.C) {
4123 4123
 // Test that auto-remove is performed by the client on API versions that do not support daemon-side api-remove (API < 1.25)
4124 4124
 func (s *DockerSuite) TestRunRmPre125Api(c *check.C) {
4125 4125
 	name := "miss-me-when-im-gone"
4126
-	envs := appendBaseEnv(false, "DOCKER_API_VERSION=1.24")
4126
+	envs := appendBaseEnv(os.Getenv("DOCKER_TLS_VERIFY") != "", "DOCKER_API_VERSION=1.24")
4127 4127
 	cli.Docker(cli.Args("run", "--name="+name, "--rm", "busybox"), cli.WithEnvironmentVariables(envs...)).Assert(c, icmd.Success)
4128 4128
 
4129 4129
 	cli.Docker(cli.Inspect(name), cli.Format(".name")).Assert(c, icmd.Expected{
... ...
@@ -677,7 +677,7 @@ func (s *DockerSuite) TestRunWithSwappinessInvalid(c *check.C) {
677 677
 }
678 678
 
679 679
 func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) {
680
-	testRequires(c, memoryReservationSupport)
680
+	testRequires(c, SameHostDaemon, memoryReservationSupport)
681 681
 
682 682
 	file := "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"
683 683
 	out, _ := dockerCmd(c, "run", "--memory-reservation", "200M", "--name", "test", "busybox", "cat", file)
... ...
@@ -689,7 +689,7 @@ func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) {
689 689
 
690 690
 func (s *DockerSuite) TestRunWithMemoryReservationInvalid(c *check.C) {
691 691
 	testRequires(c, memoryLimitSupport)
692
-	testRequires(c, memoryReservationSupport)
692
+	testRequires(c, SameHostDaemon, memoryReservationSupport)
693 693
 	out, _, err := dockerCmdWithError("run", "-m", "500M", "--memory-reservation", "800M", "busybox", "true")
694 694
 	c.Assert(err, check.NotNil)
695 695
 	expected := "Minimum memory limit can not be less than memory reservation limit"
... ...
@@ -1401,7 +1401,7 @@ func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) {
1401 1401
 
1402 1402
 // TestRunPIDsLimit makes sure the pids cgroup is set with --pids-limit
1403 1403
 func (s *DockerSuite) TestRunPIDsLimit(c *check.C) {
1404
-	testRequires(c, pidsLimit)
1404
+	testRequires(c, SameHostDaemon, pidsLimit)
1405 1405
 
1406 1406
 	file := "/sys/fs/cgroup/pids/pids.max"
1407 1407
 	out, _ := dockerCmd(c, "run", "--name", "skittles", "--pids-limit", "4", "busybox", "cat", file)
... ...
@@ -139,7 +139,7 @@ func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) {
139 139
 func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
140 140
 	testRequires(c, DaemonIsLinux, kernelMemorySupport)
141 141
 
142
-	isNewKernel := kernel.CheckKernelVersion(4, 6, 0)
142
+	isNewKernel := CheckKernelVersion(4, 6, 0)
143 143
 	name := "test-update-container"
144 144
 	dockerCmd(c, "run", "-d", "--name", name, "busybox", "top")
145 145
 	_, _, err := dockerCmdWithError("update", "--kernel-memory", "100M", name)
... ...
@@ -171,6 +171,18 @@ func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
171 171
 	c.Assert(strings.TrimSpace(out), checker.Equals, "314572800")
172 172
 }
173 173
 
174
+// GetKernelVersion gets the current kernel version.
175
+func GetKernelVersion() *kernel.VersionInfo {
176
+	v, _ := kernel.ParseRelease(testEnv.DaemonInfo.KernelVersion)
177
+	return v
178
+}
179
+
180
+// CheckKernelVersion checks if current kernel is newer than (or equal to)
181
+// the given version.
182
+func CheckKernelVersion(k, major, minor int) bool {
183
+	return kernel.CompareKernelVersion(*GetKernelVersion(), kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) > 0
184
+}
185
+
174 186
 func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) {
175 187
 	testRequires(c, DaemonIsLinux)
176 188
 	testRequires(c, memoryLimitSupport)
... ...
@@ -64,9 +64,6 @@ func (s *DockerSuite) TestVolumeCLIInspectMulti(c *check.C) {
64 64
 	})
65 65
 
66 66
 	out := result.Stdout()
67
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
68
-	c.Assert(len(outArr), check.Equals, 3, check.Commentf("\n%s", out))
69
-
70 67
 	c.Assert(out, checker.Contains, "test1")
71 68
 	c.Assert(out, checker.Contains, "test2")
72 69
 	c.Assert(out, checker.Contains, "test3")
... ...
@@ -81,11 +78,8 @@ func (s *DockerSuite) TestVolumeCLILs(c *check.C) {
81 81
 	dockerCmd(c, "volume", "create", "soo")
82 82
 	dockerCmd(c, "run", "-v", "soo:"+prefix+"/foo", "busybox", "ls", "/")
83 83
 
84
-	out, _ := dockerCmd(c, "volume", "ls")
85
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
86
-	c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
87
-
88
-	assertVolList(c, out, []string{"aaa", "soo", "test"})
84
+	out, _ := dockerCmd(c, "volume", "ls", "-q")
85
+	assertVolumesInList(c, out, []string{"aaa", "soo", "test"})
89 86
 }
90 87
 
91 88
 func (s *DockerSuite) TestVolumeLsFormat(c *check.C) {
... ...
@@ -94,12 +88,7 @@ func (s *DockerSuite) TestVolumeLsFormat(c *check.C) {
94 94
 	dockerCmd(c, "volume", "create", "soo")
95 95
 
96 96
 	out, _ := dockerCmd(c, "volume", "ls", "--format", "{{.Name}}")
97
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
98
-
99
-	expected := []string{"aaa", "soo", "test"}
100
-	var names []string
101
-	names = append(names, lines...)
102
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
97
+	assertVolumesInList(c, out, []string{"aaa", "soo", "test"})
103 98
 }
104 99
 
105 100
 func (s *DockerSuite) TestVolumeLsFormatDefaultFormat(c *check.C) {
... ...
@@ -118,12 +107,7 @@ func (s *DockerSuite) TestVolumeLsFormatDefaultFormat(c *check.C) {
118 118
 	c.Assert(err, checker.IsNil)
119 119
 
120 120
 	out, _ := dockerCmd(c, "--config", d, "volume", "ls")
121
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
122
-
123
-	expected := []string{"aaa default", "soo default", "test default"}
124
-	var names []string
125
-	names = append(names, lines...)
126
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
121
+	assertVolumesInList(c, out, []string{"aaa default", "soo default", "test default"})
127 122
 }
128 123
 
129 124
 // assertVolList checks volume retrieved with ls command
... ...
@@ -142,6 +126,20 @@ func assertVolList(c *check.C, out string, expectVols []string) {
142 142
 	c.Assert(volList, checker.DeepEquals, expectVols)
143 143
 }
144 144
 
145
+func assertVolumesInList(c *check.C, out string, expected []string) {
146
+	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
147
+	for _, expect := range expected {
148
+		found := false
149
+		for _, v := range lines {
150
+			found = v == expect
151
+			if found {
152
+				break
153
+			}
154
+		}
155
+		c.Assert(found, checker.Equals, true, check.Commentf("Expected volume not found: %v, got: %v", expect, lines))
156
+	}
157
+}
158
+
145 159
 func (s *DockerSuite) TestVolumeCLILsFilterDangling(c *check.C) {
146 160
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
147 161
 	dockerCmd(c, "volume", "create", "testnotinuse1")
... ...
@@ -213,10 +211,6 @@ func (s *DockerSuite) TestVolumeCLIRm(c *check.C) {
213 213
 	dockerCmd(c, "volume", "rm", id)
214 214
 	dockerCmd(c, "volume", "rm", "test")
215 215
 
216
-	out, _ = dockerCmd(c, "volume", "ls")
217
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
218
-	c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
219
-
220 216
 	volumeID := "testing"
221 217
 	dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar")
222 218
 
... ...
@@ -407,10 +401,6 @@ func (s *DockerSuite) TestVolumeCLIRmForceUsage(c *check.C) {
407 407
 
408 408
 	dockerCmd(c, "volume", "rm", "-f", id)
409 409
 	dockerCmd(c, "volume", "rm", "--force", "nonexist")
410
-
411
-	out, _ = dockerCmd(c, "volume", "ls")
412
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
413
-	c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
414 410
 }
415 411
 
416 412
 func (s *DockerSuite) TestVolumeCLIRmForce(c *check.C) {
... ...
@@ -39,7 +39,7 @@ func newDockerHubPullSuite() *DockerHubPullSuite {
39 39
 
40 40
 // SetUpSuite starts the suite daemon.
41 41
 func (s *DockerHubPullSuite) SetUpSuite(c *check.C) {
42
-	testRequires(c, DaemonIsLinux)
42
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
43 43
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
44 44
 		Experimental: testEnv.ExperimentalDaemon(),
45 45
 	})
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"fmt"
7 7
 	"io"
8 8
 	"io/ioutil"
9
-	"net/http"
10 9
 	"os"
11 10
 	"path"
12 11
 	"path/filepath"
... ...
@@ -373,8 +372,7 @@ func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg
373 373
 }
374 374
 
375 375
 func getInspectBody(c *check.C, version, id string) []byte {
376
-	var httpClient *http.Client
377
-	cli, err := client.NewClient(daemonHost(), version, httpClient, nil)
376
+	cli, err := request.NewEnvClientWithVersion(version)
378 377
 	c.Assert(err, check.IsNil)
379 378
 	defer cli.Close()
380 379
 	_, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false)
... ...
@@ -129,7 +129,11 @@ func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.R
129 129
 		return nil, fmt.Errorf("could not create new request: %v", err)
130 130
 	}
131 131
 
132
-	req.URL.Scheme = "http"
132
+	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
133
+		req.URL.Scheme = "https"
134
+	} else {
135
+		req.URL.Scheme = "http"
136
+	}
133 137
 	req.URL.Host = addr
134 138
 
135 139
 	for _, config := range modifiers {
... ...
@@ -319,3 +323,35 @@ func DaemonHost() string {
319 319
 	}
320 320
 	return daemonURLStr
321 321
 }
322
+
323
+// NewEnvClientWithVersion returns a docker client with a specified version.
324
+// See: github.com/docker/docker/client `NewEnvClient()`
325
+func NewEnvClientWithVersion(version string) (*dclient.Client, error) {
326
+	if version == "" {
327
+		return nil, errors.New("version not specified")
328
+	}
329
+
330
+	var httpClient *http.Client
331
+	if os.Getenv("DOCKER_CERT_PATH") != "" {
332
+		tlsConfig, err := getTLSConfig()
333
+		if err != nil {
334
+			return nil, err
335
+		}
336
+		httpClient = &http.Client{
337
+			Transport: &http.Transport{
338
+				TLSClientConfig: tlsConfig,
339
+			},
340
+		}
341
+	}
342
+
343
+	host := os.Getenv("DOCKER_HOST")
344
+	if host == "" {
345
+		host = dclient.DefaultDockerHost
346
+	}
347
+
348
+	cli, err := dclient.NewClient(host, version, httpClient, nil)
349
+	if err != nil {
350
+		return cli, err
351
+	}
352
+	return cli, nil
353
+}
... ...
@@ -1,6 +1,7 @@
1 1
 package main
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"fmt"
5 6
 	"io/ioutil"
6 7
 	"net/http"
... ...
@@ -10,6 +11,8 @@ import (
10 10
 	"strings"
11 11
 	"time"
12 12
 
13
+	"github.com/docker/docker/api/types"
14
+	"github.com/docker/docker/client"
13 15
 	"github.com/docker/docker/integration-cli/requirement"
14 16
 )
15 17
 
... ...
@@ -36,6 +39,18 @@ func DaemonIsLinux() bool {
36 36
 	return testEnv.DaemonInfo.OSType == "linux"
37 37
 }
38 38
 
39
+func OnlyDefaultNetworks() bool {
40
+	cli, err := client.NewEnvClient()
41
+	if err != nil {
42
+		return false
43
+	}
44
+	networks, err := cli.NetworkList(context.TODO(), types.NetworkListOptions{})
45
+	if err != nil || len(networks) > 0 {
46
+		return false
47
+	}
48
+	return true
49
+}
50
+
39 51
 // Deprecated: use skip.IfCondition(t, !testEnv.DaemonInfo.ExperimentalBuild)
40 52
 func ExperimentalDaemon() bool {
41 53
 	return testEnv.DaemonInfo.ExperimentalBuild
... ...
@@ -18,19 +18,19 @@ var (
18 18
 )
19 19
 
20 20
 func cpuCfsPeriod() bool {
21
-	return SysInfo.CPUCfsPeriod
21
+	return testEnv.DaemonInfo.CPUCfsPeriod
22 22
 }
23 23
 
24 24
 func cpuCfsQuota() bool {
25
-	return SysInfo.CPUCfsQuota
25
+	return testEnv.DaemonInfo.CPUCfsQuota
26 26
 }
27 27
 
28 28
 func cpuShare() bool {
29
-	return SysInfo.CPUShares
29
+	return testEnv.DaemonInfo.CPUShares
30 30
 }
31 31
 
32 32
 func oomControl() bool {
33
-	return SysInfo.OomKillDisable
33
+	return testEnv.DaemonInfo.OomKillDisable
34 34
 }
35 35
 
36 36
 func pidsLimit() bool {
... ...
@@ -38,11 +38,11 @@ func pidsLimit() bool {
38 38
 }
39 39
 
40 40
 func kernelMemorySupport() bool {
41
-	return SysInfo.KernelMemory
41
+	return testEnv.DaemonInfo.KernelMemory
42 42
 }
43 43
 
44 44
 func memoryLimitSupport() bool {
45
-	return SysInfo.MemoryLimit
45
+	return testEnv.DaemonInfo.MemoryLimit
46 46
 }
47 47
 
48 48
 func memoryReservationSupport() bool {
... ...
@@ -50,19 +50,19 @@ func memoryReservationSupport() bool {
50 50
 }
51 51
 
52 52
 func swapMemorySupport() bool {
53
-	return SysInfo.SwapLimit
53
+	return testEnv.DaemonInfo.SwapLimit
54 54
 }
55 55
 
56 56
 func memorySwappinessSupport() bool {
57
-	return SysInfo.MemorySwappiness
57
+	return SameHostDaemon() && SysInfo.MemorySwappiness
58 58
 }
59 59
 
60 60
 func blkioWeight() bool {
61
-	return SysInfo.BlkioWeight
61
+	return SameHostDaemon() && SysInfo.BlkioWeight
62 62
 }
63 63
 
64 64
 func cgroupCpuset() bool {
65
-	return SysInfo.Cpuset
65
+	return testEnv.DaemonInfo.CPUSet
66 66
 }
67 67
 
68 68
 func seccompEnabled() bool {
... ...
@@ -111,5 +111,7 @@ func overlay2Supported() bool {
111 111
 }
112 112
 
113 113
 func init() {
114
-	SysInfo = sysinfo.New(true)
114
+	if SameHostDaemon() {
115
+		SysInfo = sysinfo.New(true)
116
+	}
115 117
 }
... ...
@@ -8,6 +8,7 @@ import (
8 8
 	"strings"
9 9
 
10 10
 	"github.com/docker/docker/pkg/stringutils"
11
+	"github.com/go-check/check"
11 12
 	"github.com/gotestyourself/gotestyourself/icmd"
12 13
 	"github.com/pkg/errors"
13 14
 )
... ...
@@ -112,3 +113,71 @@ func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, err error)
112 112
 	out, err := cmds[len(cmds)-1].CombinedOutput()
113 113
 	return string(out), err
114 114
 }
115
+
116
+type elementListOptions struct {
117
+	element, format string
118
+}
119
+
120
+func existingElements(c *check.C, opts elementListOptions) []string {
121
+	args := []string{}
122
+	switch opts.element {
123
+	case "container":
124
+		args = append(args, "ps", "-a")
125
+	case "image":
126
+		args = append(args, "images", "-a")
127
+	case "network":
128
+		args = append(args, "network", "ls")
129
+	case "plugin":
130
+		args = append(args, "plugin", "ls")
131
+	case "volume":
132
+		args = append(args, "volume", "ls")
133
+	}
134
+	if opts.format != "" {
135
+		args = append(args, "--format", opts.format)
136
+	}
137
+	out, _ := dockerCmd(c, args...)
138
+	lines := []string{}
139
+	for _, l := range strings.Split(out, "\n") {
140
+		if l != "" {
141
+			lines = append(lines, l)
142
+		}
143
+	}
144
+	return lines
145
+}
146
+
147
+// ExistingContainerIDs returns a list of currently existing container IDs.
148
+func ExistingContainerIDs(c *check.C) []string {
149
+	return existingElements(c, elementListOptions{element: "container", format: "{{.ID}}"})
150
+}
151
+
152
+// ExistingContainerNames returns a list of existing container names.
153
+func ExistingContainerNames(c *check.C) []string {
154
+	return existingElements(c, elementListOptions{element: "container", format: "{{.Names}}"})
155
+}
156
+
157
+// RemoveLinesForExistingElements removes existing elements from the output of a
158
+// docker command.
159
+// This function takes an output []string and returns a []string.
160
+func RemoveLinesForExistingElements(output, existing []string) []string {
161
+	for _, e := range existing {
162
+		index := -1
163
+		for i, line := range output {
164
+			if strings.Contains(line, e) {
165
+				index = i
166
+				break
167
+			}
168
+		}
169
+		if index != -1 {
170
+			output = append(output[:index], output[index+1:]...)
171
+		}
172
+	}
173
+	return output
174
+}
175
+
176
+// RemoveOutputForExistingElements removes existing elements from the output of
177
+// a docker command.
178
+// This function takes an output string and returns a string.
179
+func RemoveOutputForExistingElements(output string, existing []string) string {
180
+	res := RemoveLinesForExistingElements(strings.Split(output, "\n"), existing)
181
+	return strings.Join(res, "\n")
182
+}
... ...
@@ -23,6 +23,6 @@ func TestMain(m *testing.M) {
23 23
 }
24 24
 
25 25
 func setupTest(t *testing.T) func() {
26
-	environment.ProtectImages(t, testEnv)
26
+	environment.ProtectAll(t, testEnv)
27 27
 	return func() { testEnv.Clean(t) }
28 28
 }
... ...
@@ -12,12 +12,14 @@ import (
12 12
 	"github.com/docker/docker/integration-cli/daemon"
13 13
 	"github.com/docker/docker/integration-cli/request"
14 14
 	"github.com/gotestyourself/gotestyourself/poll"
15
+	"github.com/gotestyourself/gotestyourself/skip"
15 16
 	"github.com/stretchr/testify/assert"
16 17
 	"github.com/stretchr/testify/require"
17 18
 	"golang.org/x/net/context"
18 19
 )
19 20
 
20 21
 func TestInspect(t *testing.T) {
22
+	skip.IfCondition(t, !testEnv.IsLocalDaemon())
21 23
 	defer setupTest(t)()
22 24
 	d := newSwarm(t)
23 25
 	defer d.Stop(t)
... ...
@@ -25,6 +25,6 @@ func TestMain(m *testing.M) {
25 25
 }
26 26
 
27 27
 func setupTest(t *testing.T) func() {
28
-	environment.ProtectImages(t, testEnv)
28
+	environment.ProtectAll(t, testEnv)
29 29
 	return func() { testEnv.Clean(t) }
30 30
 }
... ...
@@ -32,12 +32,12 @@ func (e *Execution) Clean(t testingT) {
32 32
 	if (platform != "windows") || (platform == "windows" && e.DaemonInfo.Isolation == "hyperv") {
33 33
 		unpauseAllContainers(t, client)
34 34
 	}
35
-	deleteAllContainers(t, client)
35
+	deleteAllContainers(t, client, e.protectedElements.containers)
36 36
 	deleteAllImages(t, client, e.protectedElements.images)
37
-	deleteAllVolumes(t, client)
38
-	deleteAllNetworks(t, client, platform)
37
+	deleteAllVolumes(t, client, e.protectedElements.volumes)
38
+	deleteAllNetworks(t, client, platform, e.protectedElements.networks)
39 39
 	if platform == "linux" {
40
-		deleteAllPlugins(t, client)
40
+		deleteAllPlugins(t, client, e.protectedElements.plugins)
41 41
 	}
42 42
 }
43 43
 
... ...
@@ -66,7 +66,7 @@ func getPausedContainers(ctx context.Context, t assert.TestingT, client client.C
66 66
 
67 67
 var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`)
68 68
 
69
-func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient) {
69
+func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient, protectedContainers map[string]struct{}) {
70 70
 	ctx := context.Background()
71 71
 	containers := getAllContainers(ctx, t, apiclient)
72 72
 	if len(containers) == 0 {
... ...
@@ -74,6 +74,9 @@ func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient)
74 74
 	}
75 75
 
76 76
 	for _, container := range containers {
77
+		if _, ok := protectedContainers[container.ID]; ok {
78
+			continue
79
+		}
77 80
 		err := apiclient.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{
78 81
 			Force:         true,
79 82
 			RemoveVolumes: true,
... ...
@@ -126,17 +129,20 @@ func removeImage(ctx context.Context, t assert.TestingT, apiclient client.ImageA
126 126
 	assert.NoError(t, err, "failed to remove image %s", ref)
127 127
 }
128 128
 
129
-func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient) {
129
+func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) {
130 130
 	volumes, err := c.VolumeList(context.Background(), filters.Args{})
131 131
 	assert.NoError(t, err, "failed to list volumes")
132 132
 
133 133
 	for _, v := range volumes.Volumes {
134
+		if _, ok := protectedVolumes[v.Name]; ok {
135
+			continue
136
+		}
134 137
 		err := c.VolumeRemove(context.Background(), v.Name, true)
135 138
 		assert.NoError(t, err, "failed to remove volume %s", v.Name)
136 139
 	}
137 140
 }
138 141
 
139
-func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatform string) {
142
+func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) {
140 143
 	networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{})
141 144
 	assert.NoError(t, err, "failed to list networks")
142 145
 
... ...
@@ -144,6 +150,9 @@ func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatf
144 144
 		if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
145 145
 			continue
146 146
 		}
147
+		if _, ok := protectedNetworks[n.ID]; ok {
148
+			continue
149
+		}
147 150
 		if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
148 151
 			// nat is a pre-defined network on Windows and cannot be removed
149 152
 			continue
... ...
@@ -153,11 +162,14 @@ func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatf
153 153
 	}
154 154
 }
155 155
 
156
-func deleteAllPlugins(t assert.TestingT, c client.PluginAPIClient) {
156
+func deleteAllPlugins(t assert.TestingT, c client.PluginAPIClient, protectedPlugins map[string]struct{}) {
157 157
 	plugins, err := c.PluginList(context.Background(), filters.Args{})
158 158
 	assert.NoError(t, err, "failed to list plugins")
159 159
 
160 160
 	for _, p := range plugins {
161
+		if _, ok := protectedPlugins[p.Name]; ok {
162
+			continue
163
+		}
161 164
 		err := c.PluginRemove(context.Background(), p.Name, types.PluginRemoveOptions{Force: true})
162 165
 		assert.NoError(t, err, "failed to remove plugin %s", p.ID)
163 166
 	}
... ...
@@ -10,7 +10,63 @@ import (
10 10
 )
11 11
 
12 12
 type protectedElements struct {
13
-	images map[string]struct{}
13
+	containers map[string]struct{}
14
+	images     map[string]struct{}
15
+	networks   map[string]struct{}
16
+	plugins    map[string]struct{}
17
+	volumes    map[string]struct{}
18
+}
19
+
20
+func newProtectedElements() protectedElements {
21
+	return protectedElements{
22
+		containers: map[string]struct{}{},
23
+		images:     map[string]struct{}{},
24
+		networks:   map[string]struct{}{},
25
+		plugins:    map[string]struct{}{},
26
+		volumes:    map[string]struct{}{},
27
+	}
28
+}
29
+
30
+// ProtectAll protects the existing environment (containers, images, networks,
31
+// volumes, and, on Linux, plugins) from being cleaned up at the end of test
32
+// runs
33
+func ProtectAll(t testingT, testEnv *Execution) {
34
+	ProtectContainers(t, testEnv)
35
+	ProtectImages(t, testEnv)
36
+	ProtectNetworks(t, testEnv)
37
+	ProtectVolumes(t, testEnv)
38
+	if testEnv.DaemonInfo.OSType == "linux" {
39
+		ProtectPlugins(t, testEnv)
40
+	}
41
+}
42
+
43
+// ProtectContainer adds the specified container(s) to be protected in case of
44
+// clean
45
+func (e *Execution) ProtectContainer(t testingT, containers ...string) {
46
+	for _, container := range containers {
47
+		e.protectedElements.containers[container] = struct{}{}
48
+	}
49
+}
50
+
51
+// ProtectContainers protects existing containers from being cleaned up at the
52
+// end of test runs
53
+func ProtectContainers(t testingT, testEnv *Execution) {
54
+	containers := getExistingContainers(t, testEnv)
55
+	testEnv.ProtectContainer(t, containers...)
56
+}
57
+
58
+func getExistingContainers(t require.TestingT, testEnv *Execution) []string {
59
+	client := testEnv.APIClient()
60
+	containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{
61
+		All: true,
62
+	})
63
+	require.NoError(t, err, "failed to list containers")
64
+
65
+	containers := []string{}
66
+	for _, container := range containerList {
67
+		containers = append(containers, container.ID)
68
+	}
69
+	return containers
14 70
 }
15 71
 
16 72
 // ProtectImage adds the specified image(s) to be protected in case of clean
... ...
@@ -20,12 +76,6 @@ func (e *Execution) ProtectImage(t testingT, images ...string) {
20 20
 	}
21 21
 }
22 22
 
23
-func newProtectedElements() protectedElements {
24
-	return protectedElements{
25
-		images: map[string]struct{}{},
26
-	}
27
-}
28
-
29 23
 // ProtectImages protects existing images and on linux frozen images from being
30 24
 // cleaned up at the end of test runs
31 25
 func ProtectImages(t testingT, testEnv *Execution) {
... ...
@@ -42,6 +92,7 @@ func getExistingImages(t require.TestingT, testEnv *Execution) []string {
42 42
 	filter := filters.NewArgs()
43 43
 	filter.Add("dangling", "false")
44 44
 	imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
45
+		All:     true,
45 46
 		Filters: filter,
46 47
 	})
47 48
 	require.NoError(t, err, "failed to list images")
... ...
@@ -76,3 +127,82 @@ func ensureFrozenImagesLinux(t testingT, testEnv *Execution) []string {
76 76
 	}
77 77
 	return images
78 78
 }
79
+
80
+// ProtectNetwork adds the specified network(s) to be protected in case of
81
+// clean
82
+func (e *Execution) ProtectNetwork(t testingT, networks ...string) {
83
+	for _, network := range networks {
84
+		e.protectedElements.networks[network] = struct{}{}
85
+	}
86
+}
87
+
88
+// ProtectNetworks protects existing networks from being cleaned up at the end
89
+// of test runs
90
+func ProtectNetworks(t testingT, testEnv *Execution) {
91
+	networks := getExistingNetworks(t, testEnv)
92
+	testEnv.ProtectNetwork(t, networks...)
93
+}
94
+
95
+func getExistingNetworks(t require.TestingT, testEnv *Execution) []string {
96
+	client := testEnv.APIClient()
97
+	networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{})
98
+	require.NoError(t, err, "failed to list networks")
99
+
100
+	networks := []string{}
101
+	for _, network := range networkList {
102
+		networks = append(networks, network.ID)
103
+	}
104
+	return networks
105
+}
106
+
107
+// ProtectPlugin adds the specified plugin(s) to be protected in case of clean
108
+func (e *Execution) ProtectPlugin(t testingT, plugins ...string) {
109
+	for _, plugin := range plugins {
110
+		e.protectedElements.plugins[plugin] = struct{}{}
111
+	}
112
+}
113
+
114
+// ProtectPlugins protects existing plugins from being cleaned up at the end of
115
+// test runs
116
+func ProtectPlugins(t testingT, testEnv *Execution) {
117
+	plugins := getExistingPlugins(t, testEnv)
118
+	testEnv.ProtectPlugin(t, plugins...)
119
+}
120
+
121
+func getExistingPlugins(t require.TestingT, testEnv *Execution) []string {
122
+	client := testEnv.APIClient()
123
+	pluginList, err := client.PluginList(context.Background(), filters.Args{})
124
+	require.NoError(t, err, "failed to list plugins")
125
+
126
+	plugins := []string{}
127
+	for _, plugin := range pluginList {
128
+		plugins = append(plugins, plugin.Name)
129
+	}
130
+	return plugins
131
+}
132
+
133
+// ProtectVolume adds the specified volume(s) to be protected in case of clean
134
+func (e *Execution) ProtectVolume(t testingT, volumes ...string) {
135
+	for _, volume := range volumes {
136
+		e.protectedElements.volumes[volume] = struct{}{}
137
+	}
138
+}
139
+
140
+// ProtectVolumes protects existing volumes from being cleaned up at the end of
141
+// test runs
142
+func ProtectVolumes(t testingT, testEnv *Execution) {
143
+	volumes := getExistingVolumes(t, testEnv)
144
+	testEnv.ProtectVolume(t, volumes...)
145
+}
146
+
147
+func getExistingVolumes(t require.TestingT, testEnv *Execution) []string {
148
+	client := testEnv.APIClient()
149
+	volumeList, err := client.VolumeList(context.Background(), filters.Args{})
150
+	require.NoError(t, err, "failed to list volumes")
151
+
152
+	volumes := []string{}
153
+	for _, volume := range volumeList.Volumes {
154
+		volumes = append(volumes, volume.Name)
155
+	}
156
+	return volumes
157
+}