Bladeren bron

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

Containerize integration tests
Vincent Demeester 7 jaren geleden
bovenliggende
commit
9be245f438
38 gewijzigde bestanden met toevoegingen van 707 en 246 verwijderingen
  1. 70 0
      Dockerfile.e2e
  2. 41 0
      hack/test/e2e-run.sh
  3. 7 7
      integration-cli/check_test.go
  4. 22 15
      integration-cli/cli/build/fakestorage/fixtures.go
  5. 1 0
      integration-cli/docker_api_build_test.go
  6. 1 13
      integration-cli/docker_api_containers_test.go
  7. 2 3
      integration-cli/docker_api_images_test.go
  8. 2 4
      integration-cli/docker_api_inspect_unix_test.go
  9. 14 5
      integration-cli/docker_api_network_test.go
  10. 18 11
      integration-cli/docker_api_volumes_test.go
  11. 2 2
      integration-cli/docker_cli_attach_unix_test.go
  12. 3 9
      integration-cli/docker_cli_authz_plugin_v2_test.go
  13. 1 6
      integration-cli/docker_cli_authz_unix_test.go
  14. 3 2
      integration-cli/docker_cli_build_unix_test.go
  15. 3 1
      integration-cli/docker_cli_by_digest_test.go
  16. 1 0
      integration-cli/docker_cli_config_ls_test.go
  17. 1 0
      integration-cli/docker_cli_external_volume_driver_unix_test.go
  18. 6 3
      integration-cli/docker_cli_health_test.go
  19. 31 12
      integration-cli/docker_cli_info_test.go
  20. 2 4
      integration-cli/docker_cli_kill_test.go
  21. 14 37
      integration-cli/docker_cli_network_unix_test.go
  22. 35 3
      integration-cli/docker_cli_port_test.go
  23. 70 39
      integration-cli/docker_cli_ps_test.go
  24. 26 5
      integration-cli/docker_cli_run_test.go
  25. 3 3
      integration-cli/docker_cli_run_unix_test.go
  26. 13 1
      integration-cli/docker_cli_update_unix_test.go
  27. 18 28
      integration-cli/docker_cli_volume_test.go
  28. 1 1
      integration-cli/docker_hub_pull_suite_test.go
  29. 1 3
      integration-cli/docker_utils_test.go
  30. 37 1
      integration-cli/request/request.go
  31. 15 0
      integration-cli/requirements_test.go
  32. 13 11
      integration-cli/requirements_unix_test.go
  33. 69 0
      integration-cli/utils_test.go
  34. 1 1
      integration/container/main_test.go
  35. 2 0
      integration/service/inspect_test.go
  36. 1 1
      integration/service/main_test.go
  37. 20 8
      internal/test/environment/clean.go
  38. 137 7
      internal/test/environment/protect.go

+ 70 - 0
Dockerfile.e2e

@@ -0,0 +1,70 @@
+## Step 1: Build tests
+FROM golang:1.8.3-alpine3.6 as builder
+
+RUN apk add --update \
+    bash \
+    build-base \
+    curl \
+    lvm2-dev \
+    jq \
+    && rm -rf /var/cache/apk/*
+
+RUN mkdir -p /go/src/github.com/docker/docker/
+WORKDIR /go/src/github.com/docker/docker/
+
+# Generate frozen images
+COPY contrib/download-frozen-image-v2.sh contrib/download-frozen-image-v2.sh
+RUN contrib/download-frozen-image-v2.sh /output/docker-frozen-images \
+  buildpack-deps:jessie@sha256:85b379ec16065e4fe4127eb1c5fb1bcc03c559bd36dbb2e22ff496de55925fa6 \
+  busybox:latest@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f \
+  debian:jessie@sha256:72f784399fd2719b4cb4e16ef8e369a39dc67f53d978cd3e2e7bf4e502c7b793 \
+  hello-world:latest@sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
+
+# Download Docker CLI binary
+COPY hack/dockerfile hack/dockerfile
+RUN hack/dockerfile/install-binaries.sh dockercli
+
+# Set tag and add sources
+ARG DOCKER_GITCOMMIT
+ENV DOCKER_GITCOMMIT=$DOCKER_GITCOMMIT
+ADD . .
+
+# Build DockerSuite.TestBuild* dependency
+RUN CGO_ENABLED=0 go build -o /output/httpserver github.com/docker/docker/contrib/httpserver
+
+# Build the integration tests and copy the resulting binaries to /output/tests
+RUN hack/make.sh build-integration-test-binary
+RUN mkdir -p /output/tests && find . -name test.main -exec cp --parents '{}' /output/tests \;
+
+## Step 2: Generate testing image
+FROM alpine:3.6 as runner
+
+# GNU tar is used for generating the emptyfs image
+RUN apk add --update \
+    bash \
+    ca-certificates \
+    g++ \
+    git \
+    iptables \
+    tar \
+    xz \
+    && rm -rf /var/cache/apk/*
+
+# Add an unprivileged user to be used for tests which need it
+RUN addgroup docker && adduser -D -G docker unprivilegeduser -s /bin/ash
+
+COPY contrib/httpserver/Dockerfile /tests/contrib/httpserver/Dockerfile
+COPY contrib/syscall-test /tests/contrib/syscall-test
+COPY integration-cli/fixtures /tests/integration-cli/fixtures
+
+COPY hack/test/e2e-run.sh /scripts/run.sh
+COPY hack/make/.ensure-emptyfs /scripts/ensure-emptyfs.sh
+
+COPY --from=builder /output/docker-frozen-images /docker-frozen-images
+COPY --from=builder /output/httpserver /tests/contrib/httpserver/httpserver
+COPY --from=builder /output/tests /tests
+COPY --from=builder /usr/local/bin/docker /usr/bin/docker
+
+ENV DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/
+
+ENTRYPOINT ["/scripts/run.sh"]

+ 41 - 0
hack/test/e2e-run.sh

@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+set -e
+
+TESTFLAGS=${TESTFLAGS:-""}
+# Currently only DockerSuite and DockerNetworkSuite have been adapted for E2E testing
+TESTFLAGS_LEGACY=${TESTFLAGS_LEGACY:-""}
+TIMEOUT=${TIMEOUT:-60m}
+
+SCRIPTDIR="$(dirname ${BASH_SOURCE[0]})"
+
+export DOCKER_ENGINE_GOARCH=${DOCKER_ENGINE_GOARCH:-amd64}
+
+run_test_integration() {
+  run_test_integration_suites
+  run_test_integration_legacy_suites
+}
+
+run_test_integration_suites() {
+  local flags="-test.v -test.timeout=${TIMEOUT} $TESTFLAGS"
+  for dir in /tests/integration/*; do
+    if ! (
+      cd $dir
+      echo "Running $PWD"
+      ./test.main $flags
+    ); then exit 1; fi
+  done
+}
+
+run_test_integration_legacy_suites() {
+  (
+    flags="-check.v -check.timeout=${TIMEOUT} -test.timeout=360m $TESTFLAGS_LEGACY"
+    cd /tests/integration-cli
+    echo "Running $PWD"
+    ./test.main $flags
+  )
+}
+
+bash $SCRIPTDIR/ensure-emptyfs.sh
+
+echo "Run integration tests"
+run_test_integration

+ 7 - 7
integration-cli/check_test.go

@@ -67,7 +67,7 @@ func TestMain(m *testing.M) {
 func Test(t *testing.T) {
 	cli.SetTestEnvironment(testEnv)
 	fakestorage.SetTestEnvironment(&testEnv.Execution)
-	ienv.ProtectImages(t, &testEnv.Execution)
+	ienv.ProtectAll(t, &testEnv.Execution)
 	check.TestingT(t)
 }
 
@@ -120,7 +120,7 @@ func (s *DockerRegistrySuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting)
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
 	s.reg = setupRegistry(c, false, "", "")
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
@@ -154,7 +154,7 @@ func (s *DockerSchema1RegistrySuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64)
+	testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64, SameHostDaemon)
 	s.reg = setupRegistry(c, true, "", "")
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
@@ -188,7 +188,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting)
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
 	s.reg = setupRegistry(c, false, "htpasswd", "")
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
@@ -224,7 +224,7 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, registry.Hosting)
+	testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
@@ -319,7 +319,7 @@ func (s *DockerSwarmSuite) OnTimeout(c *check.C) {
 }
 
 func (s *DockerSwarmSuite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux)
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
 }
 
 func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemon.Swarm {
@@ -471,7 +471,7 @@ func (ps *DockerPluginSuite) getPluginRepoWithTag() string {
 }
 
 func (ps *DockerPluginSuite) SetUpSuite(c *check.C) {
-	testRequires(c, DaemonIsLinux)
+	testRequires(c, DaemonIsLinux, registry.Hosting)
 	ps.registry = setupRegistry(c, false, "", "")
 
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)

+ 22 - 15
integration-cli/cli/build/fakestorage/fixtures.go

@@ -39,27 +39,34 @@ func ensureHTTPServerImage(t testingT) {
 		goarch = "amd64"
 	}
 
-	goCmd, lookErr := exec.LookPath("go")
+	cpCmd, lookErr := exec.LookPath("cp")
 	if lookErr != nil {
 		t.Fatalf("could not build http server: %v", lookErr)
 	}
 
-	cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
-	cmd.Env = append(os.Environ(), []string{
-		"CGO_ENABLED=0",
-		"GOOS=" + goos,
-		"GOARCH=" + goarch,
-	}...)
-	var out []byte
-	if out, err = cmd.CombinedOutput(); err != nil {
-		t.Fatalf("could not build http server: %s", string(out))
-	}
+	if _, err = os.Stat("../contrib/httpserver/httpserver"); os.IsNotExist(err) {
+		goCmd, lookErr := exec.LookPath("go")
+		if lookErr != nil {
+			t.Fatalf("could not build http server: %v", lookErr)
+		}
 
-	cpCmd, lookErr := exec.LookPath("cp")
-	if lookErr != nil {
-		t.Fatalf("could not build http server: %v", lookErr)
+		cmd := exec.Command(goCmd, "build", "-o", filepath.Join(tmp, "httpserver"), "github.com/docker/docker/contrib/httpserver")
+		cmd.Env = append(os.Environ(), []string{
+			"CGO_ENABLED=0",
+			"GOOS=" + goos,
+			"GOARCH=" + goarch,
+		}...)
+		var out []byte
+		if out, err = cmd.CombinedOutput(); err != nil {
+			t.Fatalf("could not build http server: %s", string(out))
+		}
+	} else {
+		if out, err := exec.Command(cpCmd, "../contrib/httpserver/httpserver", filepath.Join(tmp, "httpserver")).CombinedOutput(); err != nil {
+			t.Fatalf("could not copy http server: %v", string(out))
+		}
 	}
-	if out, err = exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil {
+
+	if out, err := exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil {
 		t.Fatalf("could not build http server: %v", string(out))
 	}
 

+ 1 - 0
integration-cli/docker_api_build_test.go

@@ -28,6 +28,7 @@ import (
 
 func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) {
 	testRequires(c, NotUserNamespace)
+
 	var testD string
 	if testEnv.DaemonPlatform() == "windows" {
 		testD = `FROM busybox

+ 1 - 13
integration-cli/docker_api_containers_test.go

@@ -71,7 +71,6 @@ func (s *DockerSuite) TestContainerAPIGetJSONNoFieldsOmitted(c *check.C) {
 	c.Assert(err, checker.IsNil)
 	c.Assert(containers, checker.HasLen, startCount+1)
 	actual := fmt.Sprintf("%+v", containers[0])
-	fmt.Println(actual)
 
 	// empty Labels field triggered this bug, make sense to check for everything
 	// cause even Ports for instance can trigger this bug
@@ -1372,8 +1371,7 @@ func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *check.C) {
 		Image: "busybox",
 	}
 
-	var httpClient *http.Client
-	cli, err := client.NewClient(daemonHost(), "v1.18", httpClient, map[string]string{})
+	cli, err := request.NewEnvClientWithVersion("v1.18")
 
 	_, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "")
 	c.Assert(err, checker.IsNil)
@@ -1409,16 +1407,6 @@ func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs(
 	c.Assert(err.Error(), checker.Contains, "container rootfs is marked read-only")
 }
 
-func (s *DockerSuite) TestContainerAPIGetContainersJSONEmpty(c *check.C) {
-	cli, err := client.NewEnvClient()
-	c.Assert(err, checker.IsNil)
-	defer cli.Close()
-
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
-	c.Assert(err, checker.IsNil)
-	c.Assert(containers, checker.HasLen, 0)
-}
-
 func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) {
 	// Not supported on Windows
 	testRequires(c, DaemonIsLinux)

+ 2 - 3
integration-cli/docker_api_images_test.go

@@ -119,7 +119,7 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) {
 }
 
 func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) {
-	testRequires(c, Network)
+	testRequires(c, Network, SameHostDaemon)
 
 	server := httptest.NewServer(http.NewServeMux())
 	defer server.Close()
@@ -179,8 +179,7 @@ func (s *DockerSuite) TestAPIImagesSizeCompatibility(c *check.C) {
 		Labels      map[string]string
 	}
 
-	var httpClient *http.Client
-	cli, err = client.NewClient(daemonHost(), "v1.24", httpClient, nil)
+	cli, err = request.NewEnvClientWithVersion("v1.24")
 	c.Assert(err, checker.IsNil)
 	defer cli.Close()
 

+ 2 - 4
integration-cli/docker_api_inspect_unix_test.go

@@ -4,10 +4,9 @@ package main
 
 import (
 	"encoding/json"
-	"net/http"
 
-	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/request"
 	"github.com/go-check/check"
 	"golang.org/x/net/context"
 )
@@ -19,8 +18,7 @@ func (s *DockerSuite) TestInspectAPICpusetInConfigPre120(c *check.C) {
 
 	name := "cpusetinconfig-pre120"
 	dockerCmd(c, "run", "--name", name, "--cpuset-cpus", "0", "busybox", "true")
-	var httpClient *http.Client
-	cli, err := client.NewClient(daemonHost(), "v1.19", httpClient, nil)
+	cli, err := request.NewEnvClientWithVersion("v1.19")
 	c.Assert(err, checker.IsNil)
 	defer cli.Close()
 	_, body, err := cli.ContainerInspectWithRaw(context.Background(), name, false)

+ 14 - 5
integration-cli/docker_api_network_test.go

@@ -76,7 +76,7 @@ func (s *DockerSuite) TestAPINetworkFilter(c *check.C) {
 	c.Assert(nr.Name, checker.Equals, "bridge")
 }
 
-func (s *DockerSuite) TestAPINetworkInspect(c *check.C) {
+func (s *DockerSuite) TestAPINetworkInspectBridge(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	// Inspect default bridge network
 	nr := getNetworkResource(c, "bridge")
@@ -94,13 +94,15 @@ func (s *DockerSuite) TestAPINetworkInspect(c *check.C) {
 	c.Assert(nr.Internal, checker.Equals, false)
 	c.Assert(nr.EnableIPv6, checker.Equals, false)
 	c.Assert(nr.IPAM.Driver, checker.Equals, "default")
-	c.Assert(len(nr.Containers), checker.Equals, 1)
 	c.Assert(nr.Containers[containerID], checker.NotNil)
 
 	ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
 	c.Assert(err, checker.IsNil)
 	c.Assert(ip.String(), checker.Equals, containerIP)
+}
 
+func (s *DockerSuite) TestAPINetworkInspectUserDefinedNetwork(c *check.C) {
+	testRequires(c, DaemonIsLinux)
 	// IPAM configuration inspect
 	ipam := &network.IPAM{
 		Driver: "default",
@@ -117,7 +119,7 @@ func (s *DockerSuite) TestAPINetworkInspect(c *check.C) {
 	id0 := createNetwork(c, config, true)
 	c.Assert(isNetworkAvailable(c, "br0"), checker.Equals, true)
 
-	nr = getNetworkResource(c, id0)
+	nr := getNetworkResource(c, id0)
 	c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
 	c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
 	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 {
 	nJSON := []types.NetworkResource{}
 	err = json.NewDecoder(body).Decode(&nJSON)
 	c.Assert(err, checker.IsNil)
-	c.Assert(len(nJSON), checker.Equals, 1)
+	var res string
+	for _, n := range nJSON {
+		// Find exact match
+		if n.Name == name {
+			res = n.ID
+		}
+	}
+	c.Assert(res, checker.Not(checker.Equals), "")
 
-	return nJSON[0].ID
+	return res
 }
 
 func getNetworkResource(c *check.C, id string) *types.NetworkResource {

+ 18 - 11
integration-cli/docker_api_volumes_test.go

@@ -16,16 +16,27 @@ import (
 
 func (s *DockerSuite) TestVolumesAPIList(c *check.C) {
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
-	dockerCmd(c, "run", "-v", prefix+"/foo", "busybox")
+	cid, _ := dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "busybox")
 
 	cli, err := client.NewEnvClient()
 	c.Assert(err, checker.IsNil)
 	defer cli.Close()
 
+	container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
+	c.Assert(err, checker.IsNil)
+	vname := container.Mounts[0].Name
+
 	volumes, err := cli.VolumeList(context.Background(), filters.Args{})
 	c.Assert(err, checker.IsNil)
 
-	c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
+	found := false
+	for _, vol := range volumes.Volumes {
+		if vol.Name == vname {
+			found = true
+			break
+		}
+	}
+	c.Assert(found, checker.Equals, true)
 }
 
 func (s *DockerSuite) TestVolumesAPICreate(c *check.C) {
@@ -45,21 +56,21 @@ func (s *DockerSuite) TestVolumesAPICreate(c *check.C) {
 
 func (s *DockerSuite) TestVolumesAPIRemove(c *check.C) {
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
-	dockerCmd(c, "run", "-v", prefix+"/foo", "--name=test", "busybox")
+	cid, _ := dockerCmd(c, "run", "-d", "-v", prefix+"/foo", "--name=test", "busybox")
 
 	cli, err := client.NewEnvClient()
 	c.Assert(err, checker.IsNil)
 	defer cli.Close()
 
-	volumes, err := cli.VolumeList(context.Background(), filters.Args{})
+	container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
 	c.Assert(err, checker.IsNil)
+	vname := container.Mounts[0].Name
 
-	v := volumes.Volumes[0]
-	err = cli.VolumeRemove(context.Background(), v.Name, false)
+	err = cli.VolumeRemove(context.Background(), vname, false)
 	c.Assert(err.Error(), checker.Contains, "volume is in use")
 
 	dockerCmd(c, "rm", "-f", "test")
-	err = cli.VolumeRemove(context.Background(), v.Name, false)
+	err = cli.VolumeRemove(context.Background(), vname, false)
 	c.Assert(err, checker.IsNil)
 }
 
@@ -78,10 +89,6 @@ func (s *DockerSuite) TestVolumesAPIInspect(c *check.C) {
 	_, err = cli.VolumeCreate(context.Background(), config)
 	c.Assert(err, check.IsNil)
 
-	volumes, err := cli.VolumeList(context.Background(), filters.Args{})
-	c.Assert(err, checker.IsNil)
-	c.Assert(len(volumes.Volumes), checker.Equals, 1, check.Commentf("\n%v", volumes.Volumes))
-
 	vol, err := cli.VolumeInspect(context.Background(), config.Name)
 	c.Assert(err, checker.IsNil)
 	c.Assert(vol.Name, checker.Equals, config.Name)

+ 2 - 2
integration-cli/docker_cli_attach_unix_test.go

@@ -173,7 +173,7 @@ func (s *DockerSuite) TestAttachDetach(c *check.C) {
 	c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
 
 	go func() {
-		dockerCmd(c, "kill", id)
+		dockerCmdWithResult("kill", id)
 	}()
 
 	select {
@@ -225,7 +225,7 @@ func (s *DockerSuite) TestAttachDetachTruncatedID(c *check.C) {
 	c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
 
 	go func() {
-		dockerCmd(c, "kill", id)
+		dockerCmdWithResult("kill", id)
 	}()
 
 	select {

+ 3 - 9
integration-cli/docker_cli_authz_plugin_v2_test.go

@@ -4,7 +4,6 @@ package main
 
 import (
 	"fmt"
-	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/daemon"
@@ -31,7 +30,7 @@ type DockerAuthzV2Suite struct {
 }
 
 func (s *DockerAuthzV2Suite) SetUpTest(c *check.C) {
-	testRequires(c, DaemonIsLinux, Network)
+	testRequires(c, DaemonIsLinux, Network, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
@@ -47,6 +46,7 @@ func (s *DockerAuthzV2Suite) TearDownTest(c *check.C) {
 
 func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) {
 	testRequires(c, DaemonIsLinux, IsAmd64, Network)
+
 	// Install authz plugin
 	_, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", authzPluginNameWithTag)
 	c.Assert(err, checker.IsNil)
@@ -65,14 +65,8 @@ func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) {
 	}()
 
 	// Ensure docker run command and accompanying docker ps are successful
-	out, err := s.d.Cmd("run", "-d", "busybox", "top")
-	c.Assert(err, check.IsNil)
-
-	id := strings.TrimSpace(out)
-
-	out, err = s.d.Cmd("ps")
+	_, err = s.d.Cmd("run", "-d", "busybox", "top")
 	c.Assert(err, check.IsNil)
-	c.Assert(assertContainerList(out, []string{id}), check.Equals, true)
 }
 
 func (s *DockerAuthzV2Suite) TestAuthZPluginDisable(c *check.C) {

+ 1 - 6
integration-cli/docker_cli_authz_unix_test.go

@@ -64,6 +64,7 @@ type authorizationController struct {
 }
 
 func (s *DockerAuthzSuite) SetUpTest(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})
@@ -218,12 +219,6 @@ func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) {
 	id := strings.TrimSpace(out)
 	assertURIRecorded(c, s.ctrl.requestsURIs, "/containers/create")
 	assertURIRecorded(c, s.ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", id))
-
-	out, err = s.d.Cmd("ps")
-	c.Assert(err, check.IsNil)
-	c.Assert(assertContainerList(out, []string{id}), check.Equals, true)
-	c.Assert(s.ctrl.psRequestCnt, check.Equals, 1)
-	c.Assert(s.ctrl.psResponseCnt, check.Equals, 1)
 }
 
 func (s *DockerAuthzSuite) TestAuthZPluginTls(c *check.C) {

+ 3 - 2
integration-cli/docker_cli_build_unix_test.go

@@ -27,17 +27,18 @@ import (
 func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) {
 	testRequires(c, cpuCfsQuota)
 	name := "testbuildresourceconstraints"
+	buildLabel := "DockerSuite.TestBuildResourceConstraintsAreUsed"
 
 	ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(`
 	FROM hello-world:frozen
 	RUN ["/hello"]
 	`))
 	cli.Docker(
-		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, "."),
+		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, "."),
 		cli.InDir(ctx.Dir),
 	).Assert(c, icmd.Success)
 
-	out := cli.DockerCmd(c, "ps", "-lq").Combined()
+	out := cli.DockerCmd(c, "ps", "-lq", "--filter", "label="+buildLabel).Combined()
 	cID := strings.TrimSpace(out)
 
 	type hostConfig struct {

+ 3 - 1
integration-cli/docker_cli_by_digest_test.go

@@ -407,6 +407,8 @@ func (s *DockerRegistrySuite) TestInspectImageWithDigests(c *check.C) {
 }
 
 func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
+
 	digest, err := setupImage(c)
 	c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
 
@@ -438,7 +440,7 @@ func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c
 
 	// Valid imageReference
 	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageReference)
-	checkPsAncestorFilterOutput(c, out, imageReference, expectedIDs)
+	checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageReference, expectedIDs)
 }
 
 func (s *DockerRegistrySuite) TestDeleteImageByIDOnlyPulledByDigest(c *check.C) {

+ 1 - 0
integration-cli/docker_cli_config_ls_test.go

@@ -11,6 +11,7 @@ import (
 )
 
 func (s *DockerSwarmSuite) TestConfigList(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	d := s.AddDaemon(c, true, true)
 
 	testName0 := "test0"

+ 1 - 0
integration-cli/docker_cli_external_volume_driver_unix_test.go

@@ -50,6 +50,7 @@ type DockerExternalVolumeSuite struct {
 }
 
 func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})

+ 6 - 3
integration-cli/docker_cli_health_test.go

@@ -39,6 +39,8 @@ func getHealth(c *check.C, name string) *types.Health {
 func (s *DockerSuite) TestHealth(c *check.C) {
 	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows
 
+	existingContainers := ExistingContainerIDs(c)
+
 	imageName := "testhealth"
 	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
 		RUN echo OK > /status
@@ -49,9 +51,10 @@ func (s *DockerSuite) TestHealth(c *check.C) {
 
 	// No health status before starting
 	name := "test_health"
-	dockerCmd(c, "create", "--name", name, imageName)
-	out, _ := dockerCmd(c, "ps", "-a", "--format={{.Status}}")
-	c.Check(out, checker.Equals, "Created\n")
+	cid, _ := dockerCmd(c, "create", "--name", name, imageName)
+	out, _ := dockerCmd(c, "ps", "-a", "--format={{.ID}} {{.Status}}")
+	out = RemoveOutputForExistingElements(out, existingContainers)
+	c.Check(out, checker.Equals, cid[:12]+" Created\n")
 
 	// Inspect the options
 	out, _ = dockerCmd(c, "inspect",

+ 31 - 12
integration-cli/docker_cli_info_test.go

@@ -135,42 +135,48 @@ func (s *DockerSuite) TestInfoDiscoveryAdvertiseInterfaceName(c *check.C) {
 func (s *DockerSuite) TestInfoDisplaysRunningContainers(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 
+	existing := existingContainerStates(c)
+
 	dockerCmd(c, "run", "-d", "busybox", "top")
 	out, _ := dockerCmd(c, "info")
-	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 1))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 0))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 0))
+	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", existing["Containers"]+1))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", existing["ContainersRunning"]+1))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", existing["ContainersPaused"]))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", existing["ContainersStopped"]))
 }
 
 func (s *DockerSuite) TestInfoDisplaysPausedContainers(c *check.C) {
 	testRequires(c, IsPausable)
 
+	existing := existingContainerStates(c)
+
 	out := runSleepingContainer(c, "-d")
 	cleanedContainerID := strings.TrimSpace(out)
 
 	dockerCmd(c, "pause", cleanedContainerID)
 
 	out, _ = dockerCmd(c, "info")
-	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 0))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 1))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 0))
+	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", existing["Containers"]+1))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", existing["ContainersRunning"]))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", existing["ContainersPaused"]+1))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", existing["ContainersStopped"]))
 }
 
 func (s *DockerSuite) TestInfoDisplaysStoppedContainers(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 
+	existing := existingContainerStates(c)
+
 	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
 	cleanedContainerID := strings.TrimSpace(out)
 
 	dockerCmd(c, "stop", cleanedContainerID)
 
 	out, _ = dockerCmd(c, "info")
-	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", 1))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", 0))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", 0))
-	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", 1))
+	c.Assert(out, checker.Contains, fmt.Sprintf("Containers: %d\n", existing["Containers"]+1))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Running: %d\n", existing["ContainersRunning"]))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Paused: %d\n", existing["ContainersPaused"]))
+	c.Assert(out, checker.Contains, fmt.Sprintf(" Stopped: %d\n", existing["ContainersStopped"]+1))
 }
 
 func (s *DockerSuite) TestInfoDebug(c *check.C) {
@@ -237,3 +243,16 @@ func (s *DockerDaemonSuite) TestInfoLabels(c *check.C) {
 	c.Assert(err, checker.IsNil)
 	c.Assert(out, checker.Contains, "WARNING: labels with duplicate keys and conflicting values have been deprecated")
 }
+
+func existingContainerStates(c *check.C) map[string]int {
+	out, _ := dockerCmd(c, "info", "--format", "{{json .}}")
+	var m map[string]interface{}
+	err := json.Unmarshal([]byte(out), &m)
+	c.Assert(err, checker.IsNil)
+	res := map[string]int{}
+	res["Containers"] = int(m["Containers"].(float64))
+	res["ContainersRunning"] = int(m["ContainersRunning"].(float64))
+	res["ContainersPaused"] = int(m["ContainersPaused"].(float64))
+	res["ContainersStopped"] = int(m["ContainersStopped"].(float64))
+	return res
+}

+ 2 - 4
integration-cli/docker_cli_kill_test.go

@@ -1,13 +1,12 @@
 package main
 
 import (
-	"net/http"
 	"strings"
 	"time"
 
-	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/cli"
+	"github.com/docker/docker/integration-cli/request"
 	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/icmd"
 	"golang.org/x/net/context"
@@ -131,8 +130,7 @@ func (s *DockerSuite) TestKillStoppedContainerAPIPre120(c *check.C) {
 	testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later
 	runSleepingContainer(c, "--name", "docker-kill-test-api", "-d")
 	dockerCmd(c, "stop", "docker-kill-test-api")
-	var httpClient *http.Client
-	cli, err := client.NewClient(daemonHost(), "v1.19", httpClient, nil)
+	cli, err := request.NewEnvClientWithVersion("v1.19")
 	c.Assert(err, check.IsNil)
 	defer cli.Close()
 	err = cli.ContainerKill(context.Background(), "docker-kill-test-api", "SIGKILL")

+ 14 - 37
integration-cli/docker_cli_network_unix_test.go

@@ -10,7 +10,6 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"os"
-	"path/filepath"
 	"strings"
 	"time"
 
@@ -288,39 +287,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) {
 	}
 }
 
-func (s *DockerSuite) TestNetworkLsFormat(c *check.C) {
-	testRequires(c, DaemonIsLinux)
-	out, _ := dockerCmd(c, "network", "ls", "--format", "{{.Name}}")
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
-
-	expected := []string{"bridge", "host", "none"}
-	var names []string
-	names = append(names, lines...)
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
-}
-
-func (s *DockerSuite) TestNetworkLsFormatDefaultFormat(c *check.C) {
-	testRequires(c, DaemonIsLinux)
-
-	config := `{
-		"networksFormat": "{{ .Name }} default"
-}`
-	d, err := ioutil.TempDir("", "integration-cli-")
-	c.Assert(err, checker.IsNil)
-	defer os.RemoveAll(d)
-
-	err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
-	c.Assert(err, checker.IsNil)
-
-	out, _ := dockerCmd(c, "--config", d, "network", "ls")
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
-
-	expected := []string{"bridge default", "host default", "none default"}
-	var names []string
-	names = append(names, lines...)
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
-}
-
 func (s *DockerNetworkSuite) TestDockerNetworkCreatePredefined(c *check.C) {
 	predefined := []string{"bridge", "host", "none", "default"}
 	for _, net := range predefined {
@@ -351,6 +317,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
+	testRequires(c, OnlyDefaultNetworks)
 	testNet := "testnet1"
 	testLabel := "foo"
 	testValue := "bar"
@@ -624,6 +591,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkIPAMMultipleNetworks(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	// test0 bridge network
 	dockerCmd(c, "network", "create", "--subnet=192.168.0.0/16", "test1")
 	assertNwIsAvailable(c, "test1")
@@ -664,6 +632,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIPAMMultipleNetworks(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkCustomIPAM(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	// Create a bridge network using custom ipam driver
 	dockerCmd(c, "network", "create", "--ipam-driver", dummyIPAMDriver, "br0")
 	assertNwIsAvailable(c, "br0")
@@ -679,6 +648,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkCustomIPAM(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkIPAMOptions(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	// Create a bridge network using custom ipam driver and options
 	dockerCmd(c, "network", "create", "--ipam-driver", dummyIPAMDriver, "--ipam-opt", "opt1=drv1", "--ipam-opt", "opt2=drv2", "br0")
 	assertNwIsAvailable(c, "br0")
@@ -691,6 +661,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIPAMOptions(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkNullIPAMDriver(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	// Create a network with null ipam driver
 	_, _, err := dockerCmdWithError("network", "create", "-d", dummyNetworkDriver, "--ipam-driver", "null", "test000")
 	c.Assert(err, check.IsNil)
@@ -796,6 +767,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIPAMInvalidCombinations(c *check.C
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt")
 	assertNwIsAvailable(c, "testopt")
 	gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData]
@@ -981,6 +953,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkLinkOnDefaultNetworkOnly(c *check.
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	// Verify exposed ports are present in ps output when running a container on
 	// a network managed by a driver which does not provide the default gateway
 	// for the container
@@ -1007,7 +980,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C) {
-	testRequires(c, DaemonIsLinux, NotUserNamespace)
+	testRequires(c, DaemonIsLinux, NotUserNamespace, SameHostDaemon)
 	dnd := "dnd"
 	did := "did"
 
@@ -1048,6 +1021,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	// Verify endpoint MAC address is correctly populated in container's network settings
 	nwn := "ov"
 	ctn := "bb"
@@ -1113,6 +1087,7 @@ func verifyContainerIsConnectedToNetworks(c *check.C, d *daemon.Daemon, cName st
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	cName := "bb"
 	nwList := []string{"nw1", "nw2", "nw3"}
 
@@ -1131,6 +1106,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRest
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	cName := "cc"
 	nwList := []string{"nw1", "nw2", "nw3"}
 
@@ -1157,7 +1133,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *check.C) {
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *check.C) {
-	testRequires(c, DaemonIsLinux, NotUserNamespace)
+	testRequires(c, DaemonIsLinux, NotUserNamespace, SameHostDaemon)
 	s.d.StartWithBusybox(c)
 
 	// Run a few containers on host network
@@ -1283,6 +1259,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRestartWithMultipleNetworks(c *che
 }
 
 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContainer(c *check.C) {
+	testRequires(c, SameHostDaemon)
 	dockerCmd(c, "network", "create", "test")
 	dockerCmd(c, "create", "--name=foo", "busybox", "top")
 	dockerCmd(c, "network", "connect", "test", "foo")
@@ -1810,7 +1787,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromBridge(c *check.C) {
 // TestConntrackFlowsLeak covers the failure scenario of ticket: https://github.com/docker/docker/issues/8795
 // Validates that conntrack is correctly cleaned once a container is destroyed
 func (s *DockerNetworkSuite) TestConntrackFlowsLeak(c *check.C) {
-	testRequires(c, IsAmd64, DaemonIsLinux, Network)
+	testRequires(c, IsAmd64, DaemonIsLinux, Network, SameHostDaemon)
 
 	// Create a new network
 	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")

+ 35 - 3
integration-cli/docker_cli_port_test.go

@@ -5,6 +5,7 @@ import (
 	"net"
 	"regexp"
 	"sort"
+	"strconv"
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
@@ -148,9 +149,8 @@ func (s *DockerSuite) TestPortList(c *check.C) {
 
 	out, _ = dockerCmd(c, "port", ID)
 
-	err = assertPortList(c, out, []string{
-		"80/tcp -> 0.0.0.0:8000",
-		"80/udp -> 0.0.0.0:8000"})
+	// Running this test multiple times causes the TCP port to increment.
+	err = assertPortRange(c, out, []int{8000, 8080}, []int{8000, 8080})
 	// Port list is not correct
 	c.Assert(err, checker.IsNil)
 	dockerCmd(c, "rm", "-f", ID)
@@ -173,6 +173,38 @@ func assertPortList(c *check.C, out string, expected []string) error {
 	return nil
 }
 
+func assertPortRange(c *check.C, out string, expectedTcp, expectedUdp []int) error {
+	lines := strings.Split(strings.Trim(out, "\n "), "\n")
+
+	var validTcp, validUdp bool
+	for _, l := range lines {
+		// 80/tcp -> 0.0.0.0:8015
+		port, err := strconv.Atoi(strings.Split(l, ":")[1])
+		if err != nil {
+			return err
+		}
+		if strings.Contains(l, "tcp") && expectedTcp != nil {
+			if port < expectedTcp[0] || port > expectedTcp[1] {
+				return fmt.Errorf("tcp port (%d) not in range expected range %d-%d", port, expectedTcp[0], expectedTcp[1])
+			}
+			validTcp = true
+		}
+		if strings.Contains(l, "udp") && expectedUdp != nil {
+			if port < expectedUdp[0] || port > expectedUdp[1] {
+				return fmt.Errorf("udp port (%d) not in range expected range %d-%d", port, expectedUdp[0], expectedUdp[1])
+			}
+			validUdp = true
+		}
+	}
+	if !validTcp {
+		return fmt.Errorf("tcp port not found")
+	}
+	if !validUdp {
+		return fmt.Errorf("udp port not found")
+	}
+	return nil
+}
+
 func stopRemoveContainer(id string, c *check.C) {
 	dockerCmd(c, "rm", "-f", id)
 }

+ 70 - 39
integration-cli/docker_cli_ps_test.go

@@ -19,6 +19,8 @@ import (
 )
 
 func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
+
 	out := runSleepingContainer(c, "-d")
 	firstID := strings.TrimSpace(out)
 
@@ -43,79 +45,79 @@ func (s *DockerSuite) TestPsListContainersBase(c *check.C) {
 
 	// all
 	out, _ = dockerCmd(c, "ps", "-a")
-	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))
+	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))
 
 	// running
 	out, _ = dockerCmd(c, "ps")
-	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))
+	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))
 
 	// limit
 	out, _ = dockerCmd(c, "ps", "-n=2", "-a")
 	expected := []string{fourthID, thirdID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT & ALL: Container list is not in the correct order: \n%s", out))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-n=2")
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
+	c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), expected), checker.Equals, true, check.Commentf("LIMIT: Container list is not in the correct order: \n%s", out))
 
 	// filter since
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-a")
 	expected = []string{fourthID, thirdID, secondID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter & ALL: Container list is not in the correct order: \n%s", out))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID)
 	expected = []string{fourthID, secondID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "since="+thirdID)
 	expected = []string{fourthID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
+	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))
 
 	// filter before
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-a")
 	expected = []string{thirdID, secondID, firstID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter & ALL: Container list is not in the correct order: \n%s", out))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID)
 	expected = []string{secondID, firstID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter: Container list is not in the correct order: \n%s", out))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "before="+thirdID)
 	expected = []string{secondID, firstID}
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter: Container list is not in the correct order: \n%s", out))
+	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))
 
 	// filter since & before
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-a")
 	expected = []string{thirdID, secondID}
-	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))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID)
 	expected = []string{secondID}
-	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))
+	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))
 
 	// filter since & limit
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2", "-a")
 	expected = []string{fourthID, thirdID}
 
-	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))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-n=2")
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("SINCE filter, LIMIT: Container list is not in the correct order: \n%s", out))
+	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))
 
 	// filter before & limit
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1", "-a")
 	expected = []string{thirdID}
-	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))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "before="+fourthID, "-n=1")
-	c.Assert(assertContainerList(out, expected), checker.Equals, true, check.Commentf("BEFORE filter, LIMIT: Container list is not in the correct order: \n%s", out))
+	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))
 
 	// filter since & filter before & limit
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1", "-a")
 	expected = []string{thirdID}
-	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))
+	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))
 
 	out, _ = dockerCmd(c, "ps", "-f", "since="+firstID, "-f", "before="+fourthID, "-n=1")
-	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))
+	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))
 
 }
 
@@ -185,6 +187,8 @@ func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
 }
 
 func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
+
 	// start exited container
 	out := cli.DockerCmd(c, "run", "-d", "busybox").Combined()
 	firstID := strings.TrimSpace(out)
@@ -199,11 +203,11 @@ func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
 	// filter containers by exited
 	out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=exited").Combined()
 	containerOut := strings.TrimSpace(out)
-	c.Assert(containerOut, checker.Equals, firstID)
+	c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, firstID)
 
 	out = cli.DockerCmd(c, "ps", "-a", "--no-trunc", "-q", "--filter=status=running").Combined()
 	containerOut = strings.TrimSpace(out)
-	c.Assert(containerOut, checker.Equals, secondID)
+	c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, secondID)
 
 	result := cli.Docker(cli.Args("ps", "-a", "-q", "--filter=status=rubbish"), cli.WithTimeout(time.Second*60))
 	result.Assert(c, icmd.Expected{
@@ -222,11 +226,12 @@ func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
 
 		out = cli.DockerCmd(c, "ps", "--no-trunc", "-q", "--filter=status=paused").Combined()
 		containerOut = strings.TrimSpace(out)
-		c.Assert(containerOut, checker.Equals, pausedID)
+		c.Assert(RemoveOutputForExistingElements(containerOut, existingContainers), checker.Equals, pausedID)
 	}
 }
 
 func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
 	// Test legacy no health check
 	out := runSleepingContainer(c, "--name=none_legacy")
 	containerID := strings.TrimSpace(out)
@@ -264,7 +269,7 @@ func (s *DockerSuite) TestPsListContainersFilterHealth(c *check.C) {
 	waitForHealthStatus(c, "passing_container", "starting", "healthy")
 
 	out = cli.DockerCmd(c, "ps", "-q", "--no-trunc", "--filter=health=healthy").Combined()
-	containerOut = strings.TrimSpace(out)
+	containerOut = strings.TrimSpace(RemoveOutputForExistingElements(out, existingContainers))
 	c.Assert(containerOut, checker.Equals, containerID, check.Commentf("Expected containerID %s, got %s for healthy filter, output: %q", containerID, containerOut, out))
 }
 
@@ -305,6 +310,8 @@ func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
 // - Run containers for each of those image (busybox, images_ps_filter_test1, images_ps_filter_test2)
 // - Filter them out :P
 func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
+
 	// Build images
 	imageName1 := "images_ps_filter_test1"
 	buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
@@ -367,12 +374,12 @@ func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
 	var out string
 	for _, filter := range filterTestSuite {
 		out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+filter.filterName)
-		checkPsAncestorFilterOutput(c, out, filter.filterName, filter.expectedIDs)
+		checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), filter.filterName, filter.expectedIDs)
 	}
 
 	// Multiple ancestor filter
 	out, _ = dockerCmd(c, "ps", "-a", "-q", "--no-trunc", "--filter=ancestor="+imageName2, "--filter=ancestor="+imageName1Tagged)
-	checkPsAncestorFilterOutput(c, out, imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
+	checkPsAncestorFilterOutput(c, RemoveOutputForExistingElements(out, existingContainers), imageName2+","+imageName1Tagged, []string{fourthID, fifthID})
 }
 
 func checkPsAncestorFilterOutput(c *check.C, out string, filterName string, expectedIDs []string) {
@@ -469,6 +476,9 @@ func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
 func (s *DockerSuite) TestPsRightTagName(c *check.C) {
 	// TODO Investigate further why this fails on Windows to Windows CI
 	testRequires(c, DaemonIsLinux)
+
+	existingContainers := ExistingContainerNames(c)
+
 	tag := "asybox:shmatest"
 	dockerCmd(c, "tag", "busybox", tag)
 
@@ -490,6 +500,7 @@ func (s *DockerSuite) TestPsRightTagName(c *check.C) {
 
 	out, _ = dockerCmd(c, "ps", "--no-trunc")
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	// skip header
 	lines = lines[1:]
 	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) {
 func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
 	// Problematic on Windows as it doesn't support links as of Jan 2016
 	testRequires(c, DaemonIsLinux)
+	existingContainers := ExistingContainerIDs(c)
 	runSleepingContainer(c, "--name=first")
 	runSleepingContainer(c, "--name=second", "--link=first:first")
 
@@ -518,6 +530,7 @@ func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
 	// strip header
 	lines = lines[1:]
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	expected := []string{"second", "first,second/first"}
 	var names []string
 	for _, l := range lines {
@@ -581,12 +594,14 @@ func (s *DockerSuite) TestPsListContainersFilterCreated(c *check.C) {
 func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
 	// Problematic on Windows as it doesn't support link as of Jan 2016
 	testRequires(c, DaemonIsLinux)
+	existingContainers := ExistingContainerNames(c)
 	//create 2 containers and link them
 	dockerCmd(c, "run", "--name=child", "-d", "busybox", "top")
 	dockerCmd(c, "run", "--name=parent", "--link=child:linkedone", "-d", "busybox", "top")
 
 	//use the new format capabilities to only list the names and --no-trunc to get all names
 	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}}", "--no-trunc")
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
 	expected := []string{"parent", "child,parent/linkedone"}
 	var names []string
@@ -595,6 +610,7 @@ func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
 
 	//now list without turning off truncation and make sure we only get the non-link names
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}}")
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
 	expected = []string{"parent", "child"}
 	var truncNames []string
@@ -604,30 +620,22 @@ func (s *DockerSuite) TestPsFormatMultiNames(c *check.C) {
 
 // Test for GitHub issue #21772
 func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) {
+	existingContainers := ExistingContainerNames(c)
 	runSleepingContainer(c, "--name=test1")
 	runSleepingContainer(c, "--name=test2")
 
 	//use the new format capabilities to list the names twice
 	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Names}}")
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	expected := []string{"test2 test2", "test1 test1"}
 	var names []string
 	names = append(names, lines...)
 	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with names displayed twice: %v, got: %v", expected, names))
 }
 
-func (s *DockerSuite) TestPsFormatHeaders(c *check.C) {
-	// make sure no-container "docker ps" still prints the header row
-	out, _ := dockerCmd(c, "ps", "--format", "table {{.ID}}")
-	c.Assert(out, checker.Equals, "CONTAINER ID\n", check.Commentf(`Expected 'CONTAINER ID\n', got %v`, out))
-
-	// verify that "docker ps" with a container still prints the header row also
-	runSleepingContainer(c, "--name=test")
-	out, _ = dockerCmd(c, "ps", "--format", "table {{.Names}}")
-	c.Assert(out, checker.Equals, "NAMES\ntest\n", check.Commentf(`Expected 'NAMES\ntest\n', got %v`, out))
-}
-
 func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
 	config := `{
 		"psFormat": "default {{ .ID }}"
 }`
@@ -642,6 +650,7 @@ func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) {
 	id := strings.TrimSpace(out)
 
 	out, _ = dockerCmd(c, "--config", d, "ps", "-q")
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	c.Assert(id, checker.HasPrefix, strings.TrimSpace(out), check.Commentf("Expected to print only the container id, got %v\n", out))
 }
 
@@ -652,6 +661,8 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
 	originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
 	updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
 
+	existingContainers := ExistingContainerIDs(c)
+
 	icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success)
 
 	originalImageID := getIDByName(c, originalImageName)
@@ -664,6 +675,7 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
 	result.Assert(c, icmd.Success)
 
 	lines := strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	// skip header
 	lines = lines[1:]
 	c.Assert(len(lines), checker.Equals, 1)
@@ -680,6 +692,7 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
 	result.Assert(c, icmd.Success)
 
 	lines = strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	// skip header
 	lines = lines[1:]
 	c.Assert(len(lines), checker.Equals, 1)
@@ -710,6 +723,8 @@ func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
 }
 
 func (s *DockerSuite) TestPsShowMounts(c *check.C) {
+	existingContainers := ExistingContainerNames(c)
+
 	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
 
 	mp := prefix + slash + "test"
@@ -736,6 +751,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
 
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	c.Assert(lines, checker.HasLen, 3)
 
 	fields := strings.Fields(lines[0])
@@ -755,6 +771,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
 
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	c.Assert(lines, checker.HasLen, 1)
 
 	fields = strings.Fields(lines[0])
@@ -768,6 +785,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
 
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	c.Assert(lines, checker.HasLen, 2)
 
 	fields = strings.Fields(lines[0])
@@ -779,6 +797,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountSource)
 
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	c.Assert(lines, checker.HasLen, 1)
 
 	fields = strings.Fields(lines[0])
@@ -790,6 +809,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+bindMountDestination)
 
 	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	c.Assert(lines, checker.HasLen, 1)
 
 	fields = strings.Fields(lines[0])
@@ -820,6 +840,8 @@ func (s *DockerSuite) TestPsFormatSize(c *check.C) {
 }
 
 func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
+	existing := ExistingContainerIDs(c)
+
 	// TODO default network on Windows is not called "bridge", and creating a
 	// custom network fails on Windows fails with "Error response from daemon: plugin not found")
 	testRequires(c, DaemonIsLinux)
@@ -837,7 +859,7 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
 	lines = lines[1:]
 
 	// ps output should have no containers
-	c.Assert(lines, checker.HasLen, 0)
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 0)
 
 	// Filter docker ps on network bridge
 	out, _ = dockerCmd(c, "ps", "--filter", "network=bridge")
@@ -849,7 +871,7 @@ func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) {
 	lines = lines[1:]
 
 	// ps output should have only one container
-	c.Assert(lines, checker.HasLen, 1)
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
 
 	// Making sure onbridgenetwork is on the output
 	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) {
 	lines = lines[1:]
 
 	//ps output should have both the containers
-	c.Assert(lines, checker.HasLen, 2)
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 2)
 
 	// Making sure onbridgenetwork and onnonenetwork is on the output
 	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) {
 	containerOut = strings.TrimSpace(string(out))
 
 	lines = strings.Split(containerOut, "\n")
+
 	// skip header
 	lines = lines[1:]
 
 	// ps output should have only one container
-	c.Assert(lines, checker.HasLen, 1)
+	c.Assert(RemoveLinesForExistingElements(lines, existing), checker.HasLen, 1)
 
 	// Making sure onbridgenetwork is on the output
 	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) {
 
 // Test case for 30291
 func (s *DockerSuite) TestPsFormatTemplateWithArg(c *check.C) {
+	existingContainers := ExistingContainerNames(c)
 	runSleepingContainer(c, "-d", "--name", "top", "--label", "some.label=label.foo-bar")
 	out, _ := dockerCmd(c, "ps", "--format", `{{.Names}} {{.Label "some.label"}}`)
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	c.Assert(strings.TrimSpace(out), checker.Equals, "top label.foo-bar")
 }
 
 func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
 	testRequires(c, DaemonIsLinux)
+	existingContainers := ExistingContainerIDs(c)
 
 	out, _ := dockerCmd(c, "run", "-d", "--publish=80", "busybox", "top")
 	id1 := strings.TrimSpace(out)
@@ -962,6 +988,7 @@ func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
 	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id2)
 
 	out, _ = dockerCmd(c, "ps", "--no-trunc", "-q", "--filter", "expose=8080/tcp")
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), id1)
 	c.Assert(strings.TrimSpace(out), checker.Equals, id2)
 }
@@ -969,11 +996,14 @@ func (s *DockerSuite) TestPsListContainersFilterPorts(c *check.C) {
 func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 
+	existingContainers := ExistingContainerNames(c)
+
 	dockerCmd(c, "create", "--name=aaa", "busybox", "top")
 	dockerCmd(c, "create", "--name=bbb", "--link=aaa", "busybox", "top")
 
 	out, _ := dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
 	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
+	lines = RemoveLinesForExistingElements(lines, existingContainers)
 	expected := []string{"bbb", "aaa,bbb/aaa"}
 	var names []string
 	names = append(names, lines...)
@@ -982,5 +1012,6 @@ func (s *DockerSuite) TestPsNotShowLinknamesOfDeletedContainer(c *check.C) {
 	dockerCmd(c, "rm", "bbb")
 
 	out, _ = dockerCmd(c, "ps", "--no-trunc", "-a", "--format", "{{.Names}}")
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	c.Assert(strings.TrimSpace(out), checker.Equals, "aaa")
 }

+ 26 - 5
integration-cli/docker_cli_run_test.go

@@ -21,6 +21,7 @@ import (
 	"sync"
 	"time"
 
+	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/cli"
 	"github.com/docker/docker/integration-cli/cli/build"
@@ -35,6 +36,7 @@ import (
 	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/icmd"
 	libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
+	"golang.org/x/net/context"
 )
 
 // "test123" should be printed by docker run
@@ -2813,23 +2815,27 @@ func (s *DockerSuite) TestRunVolumesFromRestartAfterRemoved(c *check.C) {
 
 // run container with --rm should remove container if exit code != 0
 func (s *DockerSuite) TestRunContainerWithRmFlagExitCodeNotEqualToZero(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
 	name := "flowers"
 	cli.Docker(cli.Args("run", "--name", name, "--rm", "busybox", "ls", "/notexists")).Assert(c, icmd.Expected{
 		ExitCode: 1,
 	})
 
 	out := cli.DockerCmd(c, "ps", "-q", "-a").Combined()
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	if out != "" {
 		c.Fatal("Expected not to have containers", out)
 	}
 }
 
 func (s *DockerSuite) TestRunContainerWithRmFlagCannotStartContainer(c *check.C) {
+	existingContainers := ExistingContainerIDs(c)
 	name := "sparkles"
 	cli.Docker(cli.Args("run", "--name", name, "--rm", "busybox", "commandNotFound")).Assert(c, icmd.Expected{
 		ExitCode: 127,
 	})
 	out := cli.DockerCmd(c, "ps", "-q", "-a").Combined()
+	out = RemoveOutputForExistingElements(out, existingContainers)
 	if out != "" {
 		c.Fatal("Expected not to have containers", out)
 	}
@@ -3963,29 +3969,44 @@ func (s *DockerSuite) TestRunNamedVolumeNotRemoved(c *check.C) {
 	dockerCmd(c, "run", "--rm", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
 	dockerCmd(c, "volume", "inspect", "test")
 	out, _ := dockerCmd(c, "volume", "ls", "-q")
-	c.Assert(strings.TrimSpace(out), checker.Equals, "test")
+	c.Assert(strings.TrimSpace(out), checker.Contains, "test")
 
 	dockerCmd(c, "run", "--name=test", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
 	dockerCmd(c, "rm", "-fv", "test")
 	dockerCmd(c, "volume", "inspect", "test")
 	out, _ = dockerCmd(c, "volume", "ls", "-q")
-	c.Assert(strings.TrimSpace(out), checker.Equals, "test")
+	c.Assert(strings.TrimSpace(out), checker.Contains, "test")
 }
 
 func (s *DockerSuite) TestRunNamedVolumesFromNotRemoved(c *check.C) {
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
 
 	dockerCmd(c, "volume", "create", "test")
-	dockerCmd(c, "run", "--name=parent", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
+	cid, _ := dockerCmd(c, "run", "-d", "--name=parent", "-v", "test:"+prefix+"/foo", "-v", prefix+"/bar", "busybox", "true")
 	dockerCmd(c, "run", "--name=child", "--volumes-from=parent", "busybox", "true")
 
+	cli, err := client.NewEnvClient()
+	c.Assert(err, checker.IsNil)
+	defer cli.Close()
+
+	container, err := cli.ContainerInspect(context.Background(), strings.TrimSpace(cid))
+	c.Assert(err, checker.IsNil)
+	var vname string
+	for _, v := range container.Mounts {
+		if v.Name != "test" {
+			vname = v.Name
+		}
+	}
+	c.Assert(vname, checker.Not(checker.Equals), "")
+
 	// Remove the parent so there are not other references to the volumes
 	dockerCmd(c, "rm", "-f", "parent")
 	// now remove the child and ensure the named volume (and only the named volume) still exists
 	dockerCmd(c, "rm", "-fv", "child")
 	dockerCmd(c, "volume", "inspect", "test")
 	out, _ := dockerCmd(c, "volume", "ls", "-q")
-	c.Assert(strings.TrimSpace(out), checker.Equals, "test")
+	c.Assert(strings.TrimSpace(out), checker.Contains, "test")
+	c.Assert(strings.TrimSpace(out), checker.Not(checker.Contains), vname)
 }
 
 func (s *DockerSuite) TestRunAttachFailedNoLeak(c *check.C) {
@@ -4123,7 +4144,7 @@ func (s *DockerSuite) TestRunRm(c *check.C) {
 // Test that auto-remove is performed by the client on API versions that do not support daemon-side api-remove (API < 1.25)
 func (s *DockerSuite) TestRunRmPre125Api(c *check.C) {
 	name := "miss-me-when-im-gone"
-	envs := appendBaseEnv(false, "DOCKER_API_VERSION=1.24")
+	envs := appendBaseEnv(os.Getenv("DOCKER_TLS_VERIFY") != "", "DOCKER_API_VERSION=1.24")
 	cli.Docker(cli.Args("run", "--name="+name, "--rm", "busybox"), cli.WithEnvironmentVariables(envs...)).Assert(c, icmd.Success)
 
 	cli.Docker(cli.Inspect(name), cli.Format(".name")).Assert(c, icmd.Expected{

+ 3 - 3
integration-cli/docker_cli_run_unix_test.go

@@ -677,7 +677,7 @@ func (s *DockerSuite) TestRunWithSwappinessInvalid(c *check.C) {
 }
 
 func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) {
-	testRequires(c, memoryReservationSupport)
+	testRequires(c, SameHostDaemon, memoryReservationSupport)
 
 	file := "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes"
 	out, _ := dockerCmd(c, "run", "--memory-reservation", "200M", "--name", "test", "busybox", "cat", file)
@@ -689,7 +689,7 @@ func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) {
 
 func (s *DockerSuite) TestRunWithMemoryReservationInvalid(c *check.C) {
 	testRequires(c, memoryLimitSupport)
-	testRequires(c, memoryReservationSupport)
+	testRequires(c, SameHostDaemon, memoryReservationSupport)
 	out, _, err := dockerCmdWithError("run", "-m", "500M", "--memory-reservation", "800M", "busybox", "true")
 	c.Assert(err, check.NotNil)
 	expected := "Minimum memory limit can not be less than memory reservation limit"
@@ -1401,7 +1401,7 @@ func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) {
 
 // TestRunPIDsLimit makes sure the pids cgroup is set with --pids-limit
 func (s *DockerSuite) TestRunPIDsLimit(c *check.C) {
-	testRequires(c, pidsLimit)
+	testRequires(c, SameHostDaemon, pidsLimit)
 
 	file := "/sys/fs/cgroup/pids/pids.max"
 	out, _ := dockerCmd(c, "run", "--name", "skittles", "--pids-limit", "4", "busybox", "cat", file)

+ 13 - 1
integration-cli/docker_cli_update_unix_test.go

@@ -139,7 +139,7 @@ func (s *DockerSuite) TestUpdateKernelMemory(c *check.C) {
 func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
 	testRequires(c, DaemonIsLinux, kernelMemorySupport)
 
-	isNewKernel := kernel.CheckKernelVersion(4, 6, 0)
+	isNewKernel := CheckKernelVersion(4, 6, 0)
 	name := "test-update-container"
 	dockerCmd(c, "run", "-d", "--name", name, "busybox", "top")
 	_, _, err := dockerCmdWithError("update", "--kernel-memory", "100M", name)
@@ -171,6 +171,18 @@ func (s *DockerSuite) TestUpdateKernelMemoryUninitialized(c *check.C) {
 	c.Assert(strings.TrimSpace(out), checker.Equals, "314572800")
 }
 
+// GetKernelVersion gets the current kernel version.
+func GetKernelVersion() *kernel.VersionInfo {
+	v, _ := kernel.ParseRelease(testEnv.DaemonInfo.KernelVersion)
+	return v
+}
+
+// CheckKernelVersion checks if current kernel is newer than (or equal to)
+// the given version.
+func CheckKernelVersion(k, major, minor int) bool {
+	return kernel.CompareKernelVersion(*GetKernelVersion(), kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) > 0
+}
+
 func (s *DockerSuite) TestUpdateSwapMemoryOnly(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, memoryLimitSupport)

+ 18 - 28
integration-cli/docker_cli_volume_test.go

@@ -64,9 +64,6 @@ func (s *DockerSuite) TestVolumeCLIInspectMulti(c *check.C) {
 	})
 
 	out := result.Stdout()
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
-	c.Assert(len(outArr), check.Equals, 3, check.Commentf("\n%s", out))
-
 	c.Assert(out, checker.Contains, "test1")
 	c.Assert(out, checker.Contains, "test2")
 	c.Assert(out, checker.Contains, "test3")
@@ -81,11 +78,8 @@ func (s *DockerSuite) TestVolumeCLILs(c *check.C) {
 	dockerCmd(c, "volume", "create", "soo")
 	dockerCmd(c, "run", "-v", "soo:"+prefix+"/foo", "busybox", "ls", "/")
 
-	out, _ := dockerCmd(c, "volume", "ls")
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
-	c.Assert(len(outArr), check.Equals, 4, check.Commentf("\n%s", out))
-
-	assertVolList(c, out, []string{"aaa", "soo", "test"})
+	out, _ := dockerCmd(c, "volume", "ls", "-q")
+	assertVolumesInList(c, out, []string{"aaa", "soo", "test"})
 }
 
 func (s *DockerSuite) TestVolumeLsFormat(c *check.C) {
@@ -94,12 +88,7 @@ func (s *DockerSuite) TestVolumeLsFormat(c *check.C) {
 	dockerCmd(c, "volume", "create", "soo")
 
 	out, _ := dockerCmd(c, "volume", "ls", "--format", "{{.Name}}")
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
-
-	expected := []string{"aaa", "soo", "test"}
-	var names []string
-	names = append(names, lines...)
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
+	assertVolumesInList(c, out, []string{"aaa", "soo", "test"})
 }
 
 func (s *DockerSuite) TestVolumeLsFormatDefaultFormat(c *check.C) {
@@ -118,12 +107,7 @@ func (s *DockerSuite) TestVolumeLsFormatDefaultFormat(c *check.C) {
 	c.Assert(err, checker.IsNil)
 
 	out, _ := dockerCmd(c, "--config", d, "volume", "ls")
-	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
-
-	expected := []string{"aaa default", "soo default", "test default"}
-	var names []string
-	names = append(names, lines...)
-	c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
+	assertVolumesInList(c, out, []string{"aaa default", "soo default", "test default"})
 }
 
 // assertVolList checks volume retrieved with ls command
@@ -142,6 +126,20 @@ func assertVolList(c *check.C, out string, expectVols []string) {
 	c.Assert(volList, checker.DeepEquals, expectVols)
 }
 
+func assertVolumesInList(c *check.C, out string, expected []string) {
+	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
+	for _, expect := range expected {
+		found := false
+		for _, v := range lines {
+			found = v == expect
+			if found {
+				break
+			}
+		}
+		c.Assert(found, checker.Equals, true, check.Commentf("Expected volume not found: %v, got: %v", expect, lines))
+	}
+}
+
 func (s *DockerSuite) TestVolumeCLILsFilterDangling(c *check.C) {
 	prefix, _ := getPrefixAndSlashFromDaemonPlatform()
 	dockerCmd(c, "volume", "create", "testnotinuse1")
@@ -213,10 +211,6 @@ func (s *DockerSuite) TestVolumeCLIRm(c *check.C) {
 	dockerCmd(c, "volume", "rm", id)
 	dockerCmd(c, "volume", "rm", "test")
 
-	out, _ = dockerCmd(c, "volume", "ls")
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
-	c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
-
 	volumeID := "testing"
 	dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar")
 
@@ -407,10 +401,6 @@ func (s *DockerSuite) TestVolumeCLIRmForceUsage(c *check.C) {
 
 	dockerCmd(c, "volume", "rm", "-f", id)
 	dockerCmd(c, "volume", "rm", "--force", "nonexist")
-
-	out, _ = dockerCmd(c, "volume", "ls")
-	outArr := strings.Split(strings.TrimSpace(out), "\n")
-	c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
 }
 
 func (s *DockerSuite) TestVolumeCLIRmForce(c *check.C) {

+ 1 - 1
integration-cli/docker_hub_pull_suite_test.go

@@ -39,7 +39,7 @@ func newDockerHubPullSuite() *DockerHubPullSuite {
 
 // SetUpSuite starts the suite daemon.
 func (s *DockerHubPullSuite) SetUpSuite(c *check.C) {
-	testRequires(c, DaemonIsLinux)
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
 	s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
 		Experimental: testEnv.ExperimentalDaemon(),
 	})

+ 1 - 3
integration-cli/docker_utils_test.go

@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"net/http"
 	"os"
 	"path"
 	"path/filepath"
@@ -373,8 +372,7 @@ func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg
 }
 
 func getInspectBody(c *check.C, version, id string) []byte {
-	var httpClient *http.Client
-	cli, err := client.NewClient(daemonHost(), version, httpClient, nil)
+	cli, err := request.NewEnvClientWithVersion(version)
 	c.Assert(err, check.IsNil)
 	defer cli.Close()
 	_, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false)

+ 37 - 1
integration-cli/request/request.go

@@ -129,7 +129,11 @@ func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.R
 		return nil, fmt.Errorf("could not create new request: %v", err)
 	}
 
-	req.URL.Scheme = "http"
+	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
+		req.URL.Scheme = "https"
+	} else {
+		req.URL.Scheme = "http"
+	}
 	req.URL.Host = addr
 
 	for _, config := range modifiers {
@@ -319,3 +323,35 @@ func DaemonHost() string {
 	}
 	return daemonURLStr
 }
+
+// NewEnvClientWithVersion returns a docker client with a specified version.
+// See: github.com/docker/docker/client `NewEnvClient()`
+func NewEnvClientWithVersion(version string) (*dclient.Client, error) {
+	if version == "" {
+		return nil, errors.New("version not specified")
+	}
+
+	var httpClient *http.Client
+	if os.Getenv("DOCKER_CERT_PATH") != "" {
+		tlsConfig, err := getTLSConfig()
+		if err != nil {
+			return nil, err
+		}
+		httpClient = &http.Client{
+			Transport: &http.Transport{
+				TLSClientConfig: tlsConfig,
+			},
+		}
+	}
+
+	host := os.Getenv("DOCKER_HOST")
+	if host == "" {
+		host = dclient.DefaultDockerHost
+	}
+
+	cli, err := dclient.NewClient(host, version, httpClient, nil)
+	if err != nil {
+		return cli, err
+	}
+	return cli, nil
+}

+ 15 - 0
integration-cli/requirements_test.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"context"
 	"fmt"
 	"io/ioutil"
 	"net/http"
@@ -10,6 +11,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/requirement"
 )
 
@@ -36,6 +39,18 @@ func DaemonIsLinux() bool {
 	return testEnv.DaemonInfo.OSType == "linux"
 }
 
+func OnlyDefaultNetworks() bool {
+	cli, err := client.NewEnvClient()
+	if err != nil {
+		return false
+	}
+	networks, err := cli.NetworkList(context.TODO(), types.NetworkListOptions{})
+	if err != nil || len(networks) > 0 {
+		return false
+	}
+	return true
+}
+
 // Deprecated: use skip.IfCondition(t, !testEnv.DaemonInfo.ExperimentalBuild)
 func ExperimentalDaemon() bool {
 	return testEnv.DaemonInfo.ExperimentalBuild

+ 13 - 11
integration-cli/requirements_unix_test.go

@@ -18,19 +18,19 @@ var (
 )
 
 func cpuCfsPeriod() bool {
-	return SysInfo.CPUCfsPeriod
+	return testEnv.DaemonInfo.CPUCfsPeriod
 }
 
 func cpuCfsQuota() bool {
-	return SysInfo.CPUCfsQuota
+	return testEnv.DaemonInfo.CPUCfsQuota
 }
 
 func cpuShare() bool {
-	return SysInfo.CPUShares
+	return testEnv.DaemonInfo.CPUShares
 }
 
 func oomControl() bool {
-	return SysInfo.OomKillDisable
+	return testEnv.DaemonInfo.OomKillDisable
 }
 
 func pidsLimit() bool {
@@ -38,11 +38,11 @@ func pidsLimit() bool {
 }
 
 func kernelMemorySupport() bool {
-	return SysInfo.KernelMemory
+	return testEnv.DaemonInfo.KernelMemory
 }
 
 func memoryLimitSupport() bool {
-	return SysInfo.MemoryLimit
+	return testEnv.DaemonInfo.MemoryLimit
 }
 
 func memoryReservationSupport() bool {
@@ -50,19 +50,19 @@ func memoryReservationSupport() bool {
 }
 
 func swapMemorySupport() bool {
-	return SysInfo.SwapLimit
+	return testEnv.DaemonInfo.SwapLimit
 }
 
 func memorySwappinessSupport() bool {
-	return SysInfo.MemorySwappiness
+	return SameHostDaemon() && SysInfo.MemorySwappiness
 }
 
 func blkioWeight() bool {
-	return SysInfo.BlkioWeight
+	return SameHostDaemon() && SysInfo.BlkioWeight
 }
 
 func cgroupCpuset() bool {
-	return SysInfo.Cpuset
+	return testEnv.DaemonInfo.CPUSet
 }
 
 func seccompEnabled() bool {
@@ -111,5 +111,7 @@ func overlay2Supported() bool {
 }
 
 func init() {
-	SysInfo = sysinfo.New(true)
+	if SameHostDaemon() {
+		SysInfo = sysinfo.New(true)
+	}
 }

+ 69 - 0
integration-cli/utils_test.go

@@ -8,6 +8,7 @@ import (
 	"strings"
 
 	"github.com/docker/docker/pkg/stringutils"
+	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/icmd"
 	"github.com/pkg/errors"
 )
@@ -112,3 +113,71 @@ func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, err error)
 	out, err := cmds[len(cmds)-1].CombinedOutput()
 	return string(out), err
 }
+
+type elementListOptions struct {
+	element, format string
+}
+
+func existingElements(c *check.C, opts elementListOptions) []string {
+	args := []string{}
+	switch opts.element {
+	case "container":
+		args = append(args, "ps", "-a")
+	case "image":
+		args = append(args, "images", "-a")
+	case "network":
+		args = append(args, "network", "ls")
+	case "plugin":
+		args = append(args, "plugin", "ls")
+	case "volume":
+		args = append(args, "volume", "ls")
+	}
+	if opts.format != "" {
+		args = append(args, "--format", opts.format)
+	}
+	out, _ := dockerCmd(c, args...)
+	lines := []string{}
+	for _, l := range strings.Split(out, "\n") {
+		if l != "" {
+			lines = append(lines, l)
+		}
+	}
+	return lines
+}
+
+// ExistingContainerIDs returns a list of currently existing container IDs.
+func ExistingContainerIDs(c *check.C) []string {
+	return existingElements(c, elementListOptions{element: "container", format: "{{.ID}}"})
+}
+
+// ExistingContainerNames returns a list of existing container names.
+func ExistingContainerNames(c *check.C) []string {
+	return existingElements(c, elementListOptions{element: "container", format: "{{.Names}}"})
+}
+
+// RemoveLinesForExistingElements removes existing elements from the output of a
+// docker command.
+// This function takes an output []string and returns a []string.
+func RemoveLinesForExistingElements(output, existing []string) []string {
+	for _, e := range existing {
+		index := -1
+		for i, line := range output {
+			if strings.Contains(line, e) {
+				index = i
+				break
+			}
+		}
+		if index != -1 {
+			output = append(output[:index], output[index+1:]...)
+		}
+	}
+	return output
+}
+
+// RemoveOutputForExistingElements removes existing elements from the output of
+// a docker command.
+// This function takes an output string and returns a string.
+func RemoveOutputForExistingElements(output string, existing []string) string {
+	res := RemoveLinesForExistingElements(strings.Split(output, "\n"), existing)
+	return strings.Join(res, "\n")
+}

+ 1 - 1
integration/container/main_test.go

@@ -23,6 +23,6 @@ func TestMain(m *testing.M) {
 }
 
 func setupTest(t *testing.T) func() {
-	environment.ProtectImages(t, testEnv)
+	environment.ProtectAll(t, testEnv)
 	return func() { testEnv.Clean(t) }
 }

+ 2 - 0
integration/service/inspect_test.go

@@ -12,12 +12,14 @@ import (
 	"github.com/docker/docker/integration-cli/daemon"
 	"github.com/docker/docker/integration-cli/request"
 	"github.com/gotestyourself/gotestyourself/poll"
+	"github.com/gotestyourself/gotestyourself/skip"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"golang.org/x/net/context"
 )
 
 func TestInspect(t *testing.T) {
+	skip.IfCondition(t, !testEnv.IsLocalDaemon())
 	defer setupTest(t)()
 	d := newSwarm(t)
 	defer d.Stop(t)

+ 1 - 1
integration/service/main_test.go

@@ -25,6 +25,6 @@ func TestMain(m *testing.M) {
 }
 
 func setupTest(t *testing.T) func() {
-	environment.ProtectImages(t, testEnv)
+	environment.ProtectAll(t, testEnv)
 	return func() { testEnv.Clean(t) }
 }

+ 20 - 8
internal/test/environment/clean.go

@@ -32,12 +32,12 @@ func (e *Execution) Clean(t testingT) {
 	if (platform != "windows") || (platform == "windows" && e.DaemonInfo.Isolation == "hyperv") {
 		unpauseAllContainers(t, client)
 	}
-	deleteAllContainers(t, client)
+	deleteAllContainers(t, client, e.protectedElements.containers)
 	deleteAllImages(t, client, e.protectedElements.images)
-	deleteAllVolumes(t, client)
-	deleteAllNetworks(t, client, platform)
+	deleteAllVolumes(t, client, e.protectedElements.volumes)
+	deleteAllNetworks(t, client, platform, e.protectedElements.networks)
 	if platform == "linux" {
-		deleteAllPlugins(t, client)
+		deleteAllPlugins(t, client, e.protectedElements.plugins)
 	}
 }
 
@@ -66,7 +66,7 @@ func getPausedContainers(ctx context.Context, t assert.TestingT, client client.C
 
 var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`)
 
-func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient) {
+func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient, protectedContainers map[string]struct{}) {
 	ctx := context.Background()
 	containers := getAllContainers(ctx, t, apiclient)
 	if len(containers) == 0 {
@@ -74,6 +74,9 @@ func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient)
 	}
 
 	for _, container := range containers {
+		if _, ok := protectedContainers[container.ID]; ok {
+			continue
+		}
 		err := apiclient.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{
 			Force:         true,
 			RemoveVolumes: true,
@@ -126,17 +129,20 @@ func removeImage(ctx context.Context, t assert.TestingT, apiclient client.ImageA
 	assert.NoError(t, err, "failed to remove image %s", ref)
 }
 
-func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient) {
+func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) {
 	volumes, err := c.VolumeList(context.Background(), filters.Args{})
 	assert.NoError(t, err, "failed to list volumes")
 
 	for _, v := range volumes.Volumes {
+		if _, ok := protectedVolumes[v.Name]; ok {
+			continue
+		}
 		err := c.VolumeRemove(context.Background(), v.Name, true)
 		assert.NoError(t, err, "failed to remove volume %s", v.Name)
 	}
 }
 
-func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatform string) {
+func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) {
 	networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{})
 	assert.NoError(t, err, "failed to list networks")
 
@@ -144,6 +150,9 @@ func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatf
 		if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
 			continue
 		}
+		if _, ok := protectedNetworks[n.ID]; ok {
+			continue
+		}
 		if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
 			// nat is a pre-defined network on Windows and cannot be removed
 			continue
@@ -153,11 +162,14 @@ func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatf
 	}
 }
 
-func deleteAllPlugins(t assert.TestingT, c client.PluginAPIClient) {
+func deleteAllPlugins(t assert.TestingT, c client.PluginAPIClient, protectedPlugins map[string]struct{}) {
 	plugins, err := c.PluginList(context.Background(), filters.Args{})
 	assert.NoError(t, err, "failed to list plugins")
 
 	for _, p := range plugins {
+		if _, ok := protectedPlugins[p.Name]; ok {
+			continue
+		}
 		err := c.PluginRemove(context.Background(), p.Name, types.PluginRemoveOptions{Force: true})
 		assert.NoError(t, err, "failed to remove plugin %s", p.ID)
 	}

+ 137 - 7
internal/test/environment/protect.go

@@ -10,7 +10,63 @@ import (
 )
 
 type protectedElements struct {
-	images map[string]struct{}
+	containers map[string]struct{}
+	images     map[string]struct{}
+	networks   map[string]struct{}
+	plugins    map[string]struct{}
+	volumes    map[string]struct{}
+}
+
+func newProtectedElements() protectedElements {
+	return protectedElements{
+		containers: map[string]struct{}{},
+		images:     map[string]struct{}{},
+		networks:   map[string]struct{}{},
+		plugins:    map[string]struct{}{},
+		volumes:    map[string]struct{}{},
+	}
+}
+
+// ProtectAll protects the existing environment (containers, images, networks,
+// volumes, and, on Linux, plugins) from being cleaned up at the end of test
+// runs
+func ProtectAll(t testingT, testEnv *Execution) {
+	ProtectContainers(t, testEnv)
+	ProtectImages(t, testEnv)
+	ProtectNetworks(t, testEnv)
+	ProtectVolumes(t, testEnv)
+	if testEnv.DaemonInfo.OSType == "linux" {
+		ProtectPlugins(t, testEnv)
+	}
+}
+
+// ProtectContainer adds the specified container(s) to be protected in case of
+// clean
+func (e *Execution) ProtectContainer(t testingT, containers ...string) {
+	for _, container := range containers {
+		e.protectedElements.containers[container] = struct{}{}
+	}
+}
+
+// ProtectContainers protects existing containers from being cleaned up at the
+// end of test runs
+func ProtectContainers(t testingT, testEnv *Execution) {
+	containers := getExistingContainers(t, testEnv)
+	testEnv.ProtectContainer(t, containers...)
+}
+
+func getExistingContainers(t require.TestingT, testEnv *Execution) []string {
+	client := testEnv.APIClient()
+	containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{
+		All: true,
+	})
+	require.NoError(t, err, "failed to list containers")
+
+	containers := []string{}
+	for _, container := range containerList {
+		containers = append(containers, container.ID)
+	}
+	return containers
 }
 
 // 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) {
 	}
 }
 
-func newProtectedElements() protectedElements {
-	return protectedElements{
-		images: map[string]struct{}{},
-	}
-}
-
 // ProtectImages protects existing images and on linux frozen images from being
 // cleaned up at the end of test runs
 func ProtectImages(t testingT, testEnv *Execution) {
@@ -42,6 +92,7 @@ func getExistingImages(t require.TestingT, testEnv *Execution) []string {
 	filter := filters.NewArgs()
 	filter.Add("dangling", "false")
 	imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
+		All:     true,
 		Filters: filter,
 	})
 	require.NoError(t, err, "failed to list images")
@@ -76,3 +127,82 @@ func ensureFrozenImagesLinux(t testingT, testEnv *Execution) []string {
 	}
 	return images
 }
+
+// ProtectNetwork adds the specified network(s) to be protected in case of
+// clean
+func (e *Execution) ProtectNetwork(t testingT, networks ...string) {
+	for _, network := range networks {
+		e.protectedElements.networks[network] = struct{}{}
+	}
+}
+
+// ProtectNetworks protects existing networks from being cleaned up at the end
+// of test runs
+func ProtectNetworks(t testingT, testEnv *Execution) {
+	networks := getExistingNetworks(t, testEnv)
+	testEnv.ProtectNetwork(t, networks...)
+}
+
+func getExistingNetworks(t require.TestingT, testEnv *Execution) []string {
+	client := testEnv.APIClient()
+	networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{})
+	require.NoError(t, err, "failed to list networks")
+
+	networks := []string{}
+	for _, network := range networkList {
+		networks = append(networks, network.ID)
+	}
+	return networks
+}
+
+// ProtectPlugin adds the specified plugin(s) to be protected in case of clean
+func (e *Execution) ProtectPlugin(t testingT, plugins ...string) {
+	for _, plugin := range plugins {
+		e.protectedElements.plugins[plugin] = struct{}{}
+	}
+}
+
+// ProtectPlugins protects existing plugins from being cleaned up at the end of
+// test runs
+func ProtectPlugins(t testingT, testEnv *Execution) {
+	plugins := getExistingPlugins(t, testEnv)
+	testEnv.ProtectPlugin(t, plugins...)
+}
+
+func getExistingPlugins(t require.TestingT, testEnv *Execution) []string {
+	client := testEnv.APIClient()
+	pluginList, err := client.PluginList(context.Background(), filters.Args{})
+	require.NoError(t, err, "failed to list plugins")
+
+	plugins := []string{}
+	for _, plugin := range pluginList {
+		plugins = append(plugins, plugin.Name)
+	}
+	return plugins
+}
+
+// ProtectVolume adds the specified volume(s) to be protected in case of clean
+func (e *Execution) ProtectVolume(t testingT, volumes ...string) {
+	for _, volume := range volumes {
+		e.protectedElements.volumes[volume] = struct{}{}
+	}
+}
+
+// ProtectVolumes protects existing volumes from being cleaned up at the end of
+// test runs
+func ProtectVolumes(t testingT, testEnv *Execution) {
+	volumes := getExistingVolumes(t, testEnv)
+	testEnv.ProtectVolume(t, volumes...)
+}
+
+func getExistingVolumes(t require.TestingT, testEnv *Execution) []string {
+	client := testEnv.APIClient()
+	volumeList, err := client.VolumeList(context.Background(), filters.Args{})
+	require.NoError(t, err, "failed to list volumes")
+
+	volumes := []string{}
+	for _, volume := range volumeList.Volumes {
+		volumes = append(volumes, volume.Name)
+	}
+	return volumes
+}