From 0520581523caeacdf718a2dd1db2958c24b47cf6 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 8 Sep 2017 16:41:02 +0200 Subject: [PATCH 01/18] Allow protection of entire environment during tests Signed-off-by: Christopher Crone --- internal/test/environment/clean.go | 28 ++++-- internal/test/environment/protect.go | 144 +++++++++++++++++++++++++-- 2 files changed, 157 insertions(+), 15 deletions(-) diff --git a/internal/test/environment/clean.go b/internal/test/environment/clean.go index c6392dc1bc..702d10711b 100644 --- a/internal/test/environment/clean.go +++ b/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) } diff --git a/internal/test/environment/protect.go b/internal/test/environment/protect.go index 5821863298..2e882c8470 100644 --- a/internal/test/environment/protect.go +++ b/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 +} From 063c89c71fd1fbeb7ef7c46f43ee805b620e7136 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 8 Sep 2017 16:42:10 +0200 Subject: [PATCH 02/18] Protect entire environment when testing Signed-off-by: Christopher Crone --- integration-cli/check_test.go | 2 +- integration/container/main_test.go | 2 +- integration/service/main_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index 87517e7db7..3ee1a56245 100644 --- a/integration-cli/check_test.go +++ b/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) } diff --git a/integration/container/main_test.go b/integration/container/main_test.go index 1c4e078400..fbfed2ae40 100644 --- a/integration/container/main_test.go +++ b/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) } } diff --git a/integration/service/main_test.go b/integration/service/main_test.go index 4d6af81895..4cad6ed975 100644 --- a/integration/service/main_test.go +++ b/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) } } From 07f10d8e2e2214000635c32d23f9435fa3fb48b8 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 8 Sep 2017 16:43:04 +0200 Subject: [PATCH 03/18] Containerize integration tests Signed-off-by: Christopher Crone --- Dockerfile.e2e | 61 +++++++++++++++++++++++++++++++++++++++++++++ internal/e2e/run.sh | 13 ++++++++++ 2 files changed, 74 insertions(+) create mode 100644 Dockerfile.e2e create mode 100755 internal/e2e/run.sh diff --git a/Dockerfile.e2e b/Dockerfile.e2e new file mode 100644 index 0000000000..6d8e5dfbd6 --- /dev/null +++ b/Dockerfile.e2e @@ -0,0 +1,61 @@ +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/ + +COPY contrib contrib +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 + +ARG DOCKER_GITCOMMIT + +ENV DOCKER_GITCOMMIT=$DOCKER_GITCOMMIT + +# integration-cli tests are frozen to 17.06 +# Newer CLI tests can be found in the docker/cli repository +RUN curl https://download.docker.com/linux/static/stable/x86_64/docker-17.06.2-ce.tgz | tar xzf - -C /output + +ADD . . + +RUN hack/make.sh build-integration-test-binary +RUN mkdir -p /output/tests && find . -name test.main -exec cp --parents '{}' /output/tests \; + +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 + +ENV DOCKER_E2E=1 DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/ + +COPY --from=builder /output/docker/docker /usr/bin/docker +COPY --from=builder /output/docker-frozen-images /docker-frozen-images +COPY --from=builder /output/tests /tests + +COPY contrib /tests/contrib +COPY hack/make/.ensure-emptyfs /ensure-emptyfs.sh +COPY integration-cli/fixtures /tests/integration-cli/fixtures +COPY internal/e2e/run.sh /run.sh + +ENTRYPOINT ["/run.sh"] diff --git a/internal/e2e/run.sh b/internal/e2e/run.sh new file mode 100755 index 0000000000..83b88ae509 --- /dev/null +++ b/internal/e2e/run.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +echo "Ensure emptyfs image is loaded" +bash /ensure-emptyfs.sh + +echo "Run integration/container tests" +cd /tests/integration/container +./test.main -test.v + +echo "Run integration-cli DockerSuite tests" +cd /tests/integration-cli +./test.main -test.v -check.v -check.f DockerSuite From d622e81af50f4690d5867a89b430d1b94707fd26 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 8 Sep 2017 16:44:19 +0200 Subject: [PATCH 04/18] Add E2E requirement for integration tests Signed-off-by: Christopher Crone --- integration-cli/requirements_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go index 0b10969996..c41a71fa29 100644 --- a/integration-cli/requirements_test.go +++ b/integration-cli/requirements_test.go @@ -36,6 +36,14 @@ func DaemonIsLinux() bool { return testEnv.DaemonInfo.OSType == "linux" } +func E2E() bool { + return os.Getenv("DOCKER_E2E") != "" +} + +func NotE2E() bool { + return !E2E() +} + // Deprecated: use skip.IfCondition(t, !testEnv.DaemonInfo.ExperimentalBuild) func ExperimentalDaemon() bool { return testEnv.DaemonInfo.ExperimentalBuild From dc6ddfa8415d90e9a9788d5cfd5a10c17449bbc9 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 8 Sep 2017 17:16:15 +0200 Subject: [PATCH 05/18] Fix tests that depend on clean environment Signed-off-by: Christopher Crone --- integration-cli/docker_api_network_test.go | 14 ++- .../docker_cli_authz_plugin_v2_test.go | 5 +- integration-cli/docker_cli_authz_unix_test.go | 4 +- integration-cli/docker_cli_by_digest_test.go | 4 +- integration-cli/docker_cli_health_test.go | 3 + integration-cli/docker_cli_info_test.go | 43 ++++++--- integration-cli/docker_cli_port_test.go | 37 +++++++- integration-cli/docker_cli_ps_test.go | 91 +++++++++++++------ integration-cli/docker_cli_run_test.go | 4 + integration-cli/utils_test.go | 71 +++++++++++++++ 10 files changed, 228 insertions(+), 48 deletions(-) diff --git a/integration-cli/docker_api_network_test.go b/integration-cli/docker_api_network_test.go index 129ec7ea69..e9fbf0426c 100644 --- a/integration-cli/docker_api_network_test.go +++ b/integration-cli/docker_api_network_test.go @@ -81,6 +81,7 @@ func (s *DockerSuite) TestAPINetworkInspect(c *check.C) { // Inspect default bridge network nr := getNetworkResource(c, "bridge") c.Assert(nr.Name, checker.Equals, "bridge") + connCount := len(nr.Containers) // run a container and attach it to the default bridge network out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top") @@ -94,7 +95,7 @@ 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(len(nr.Containers), checker.Equals, connCount+1) c.Assert(nr.Containers[containerID], checker.NotNil) ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address) @@ -291,9 +292,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 { diff --git a/integration-cli/docker_cli_authz_plugin_v2_test.go b/integration-cli/docker_cli_authz_plugin_v2_test.go index b8bbcc75e1..025d5aeb7f 100644 --- a/integration-cli/docker_cli_authz_plugin_v2_test.go +++ b/integration-cli/docker_cli_authz_plugin_v2_test.go @@ -47,6 +47,9 @@ func (s *DockerAuthzV2Suite) TearDownTest(c *check.C) { func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) { testRequires(c, DaemonIsLinux, IsAmd64, Network) + + existingContainers := ExistingContainerIDs(c) + // Install authz plugin _, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", authzPluginNameWithTag) c.Assert(err, checker.IsNil) @@ -72,7 +75,7 @@ func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) { out, err = s.d.Cmd("ps") c.Assert(err, check.IsNil) - c.Assert(assertContainerList(out, []string{id}), check.Equals, true) + c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{id}), check.Equals, true) } func (s *DockerAuthzV2Suite) TestAuthZPluginDisable(c *check.C) { diff --git a/integration-cli/docker_cli_authz_unix_test.go b/integration-cli/docker_cli_authz_unix_test.go index f46ab806ca..cf3d88e12a 100644 --- a/integration-cli/docker_cli_authz_unix_test.go +++ b/integration-cli/docker_cli_authz_unix_test.go @@ -204,6 +204,8 @@ func (s *DockerAuthzSuite) TearDownSuite(c *check.C) { } func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) { + existingContainers := ExistingContainerIDs(c) + // start the daemon and load busybox, --net=none build fails otherwise // cause it needs to pull busybox s.d.Start(c, "--authorization-plugin="+testAuthZPlugin) @@ -221,7 +223,7 @@ func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) { out, err = s.d.Cmd("ps") c.Assert(err, check.IsNil) - c.Assert(assertContainerList(out, []string{id}), check.Equals, true) + c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{id}), check.Equals, true) c.Assert(s.ctrl.psRequestCnt, check.Equals, 1) c.Assert(s.ctrl.psResponseCnt, check.Equals, 1) } diff --git a/integration-cli/docker_cli_by_digest_test.go b/integration-cli/docker_cli_by_digest_test.go index c7115c88c6..0c682719a4 100644 --- a/integration-cli/docker_cli_by_digest_test.go +++ b/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) { diff --git a/integration-cli/docker_cli_health_test.go b/integration-cli/docker_cli_health_test.go index 0f78a41d87..f6228075be 100644 --- a/integration-cli/docker_cli_health_test.go +++ b/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 := ExistingContainerNames(c) + imageName := "testhealth" buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox RUN echo OK > /status @@ -51,6 +53,7 @@ func (s *DockerSuite) TestHealth(c *check.C) { name := "test_health" dockerCmd(c, "create", "--name", name, imageName) out, _ := dockerCmd(c, "ps", "-a", "--format={{.Status}}") + out = RemoveOutputForExistingElements(out, existingContainers) c.Check(out, checker.Equals, "Created\n") // Inspect the options diff --git a/integration-cli/docker_cli_info_test.go b/integration-cli/docker_cli_info_test.go index d75974dfc9..b6f867373b 100644 --- a/integration-cli/docker_cli_info_test.go +++ b/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 +} diff --git a/integration-cli/docker_cli_port_test.go b/integration-cli/docker_cli_port_test.go index bcb87f5f33..7450dd4837 100644 --- a/integration-cli/docker_cli_port_test.go +++ b/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,7 @@ 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"}) + 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 +172,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) } diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go index 736103e776..2572535e30 100644 --- a/integration-cli/docker_cli_ps_test.go +++ b/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,7 +226,7 @@ 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) } } @@ -305,6 +309,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 +373,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 +475,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 +499,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))) @@ -581,12 +591,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 +607,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,12 +617,14 @@ 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...) @@ -628,6 +643,7 @@ func (s *DockerSuite) TestPsFormatHeaders(c *check.C) { } func (s *DockerSuite) TestPsDefaultFormatAndQuiet(c *check.C) { + existingContainers := ExistingContainerIDs(c) config := `{ "psFormat": "default {{ .ID }}" }` @@ -642,6 +658,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 +669,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 +683,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 +700,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 +731,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 +759,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 +779,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 +793,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 +805,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 +817,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 +848,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 +867,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 +879,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 +894,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 +915,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,8 +958,10 @@ 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") } @@ -969,11 +1002,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 +1018,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") } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 03996b3047..485d718f17 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -2813,23 +2813,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) } diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index e09fb80643..26b0b3106c 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -7,7 +7,10 @@ import ( "path/filepath" "strings" + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" "github.com/docker/docker/pkg/stringutils" + "github.com/go-check/check" "github.com/gotestyourself/gotestyourself/icmd" "github.com/pkg/errors" ) @@ -112,3 +115,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") +} From 0bdba0e91a072ee2cdecb4e632c13f187eb88e9c Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 8 Sep 2017 17:17:28 +0200 Subject: [PATCH 06/18] Use TLS for tests if needed Signed-off-by: Christopher Crone --- integration-cli/docker_api_containers_test.go | 3 +-- integration-cli/docker_api_images_test.go | 3 +-- integration-cli/docker_api_inspect_unix_test.go | 5 +---- integration-cli/docker_cli_kill_test.go | 5 +---- integration-cli/docker_cli_run_test.go | 2 +- integration-cli/docker_utils_test.go | 4 +--- integration-cli/request/request.go | 6 +++++- integration-cli/utils_test.go | 11 +++++++++++ 8 files changed, 22 insertions(+), 17 deletions(-) diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 4a7e363d1c..f60436766a 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1372,8 +1372,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 := NewEnvClientWithVersion("v1.18") _, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "") c.Assert(err, checker.IsNil) diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index 8ad12fb77d..4b3fb059cf 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -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 = NewEnvClientWithVersion("v1.24") c.Assert(err, checker.IsNil) defer cli.Close() diff --git a/integration-cli/docker_api_inspect_unix_test.go b/integration-cli/docker_api_inspect_unix_test.go index 93c40947af..7fc4cb0b45 100644 --- a/integration-cli/docker_api_inspect_unix_test.go +++ b/integration-cli/docker_api_inspect_unix_test.go @@ -4,9 +4,7 @@ package main import ( "encoding/json" - "net/http" - "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" "github.com/go-check/check" "golang.org/x/net/context" @@ -19,8 +17,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 := NewEnvClientWithVersion("v1.19") c.Assert(err, checker.IsNil) defer cli.Close() _, body, err := cli.ContainerInspectWithRaw(context.Background(), name, false) diff --git a/integration-cli/docker_cli_kill_test.go b/integration-cli/docker_cli_kill_test.go index ea1c269812..a949bdb37f 100644 --- a/integration-cli/docker_cli_kill_test.go +++ b/integration-cli/docker_cli_kill_test.go @@ -1,11 +1,9 @@ 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/go-check/check" @@ -131,8 +129,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 := NewEnvClientWithVersion("v1.19") c.Assert(err, check.IsNil) defer cli.Close() err = cli.ContainerKill(context.Background(), "docker-kill-test-api", "SIGKILL") diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 485d718f17..45a56bcfed 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -4127,7 +4127,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{ diff --git a/integration-cli/docker_utils_test.go b/integration-cli/docker_utils_test.go index 95d2e93cfe..194e0660f2 100644 --- a/integration-cli/docker_utils_test.go +++ b/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 := NewEnvClientWithVersion(version) c.Assert(err, check.IsNil) defer cli.Close() _, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false) diff --git a/integration-cli/request/request.go b/integration-cli/request/request.go index 72632f3f76..f2b0320bd0 100644 --- a/integration-cli/request/request.go +++ b/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 { diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index 26b0b3106c..5a7e566d87 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -183,3 +183,14 @@ func RemoveOutputForExistingElements(output string, existing []string) string { res := RemoveLinesForExistingElements(strings.Split(output, "\n"), existing) return strings.Join(res, "\n") } + +// NewEnvClientWithVersion returns a docker client with a specified version. +// See: github.com/docker/docker/client `NewEnvClient()` +func NewEnvClientWithVersion(version string) (*client.Client, error) { + cli, err := client.NewEnvClient() + if err != nil { + return nil, err + } + cli.NegotiateAPIVersionPing(types.Ping{APIVersion: version}) + return cli, nil +} From b1fb41988dc1b7071a58f76f6ad2730fc1a02eca Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Mon, 11 Sep 2017 16:23:59 +0200 Subject: [PATCH 07/18] Check integration test requirements using daemon When running against a remote daemon, we cannot use the local filesystem to determine configuration. Signed-off-by: Christopher Crone --- integration-cli/docker_cli_run_unix_test.go | 6 ++--- .../docker_cli_update_unix_test.go | 3 +-- integration-cli/requirements_unix_test.go | 24 ++++++++++--------- integration-cli/utils_test.go | 17 +++++++++++++ 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index 2176f0b020..b6f70f6cbd 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/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) diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go index 2b759412ec..7f1cd8dd79 100644 --- a/integration-cli/docker_cli_update_unix_test.go +++ b/integration-cli/docker_cli_update_unix_test.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/request" - "github.com/docker/docker/pkg/parsers/kernel" "github.com/go-check/check" "github.com/kr/pty" ) @@ -139,7 +138,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) diff --git a/integration-cli/requirements_unix_test.go b/integration-cli/requirements_unix_test.go index 6ef900fc18..7c594f7db4 100644 --- a/integration-cli/requirements_unix_test.go +++ b/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) + } } diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index 5a7e566d87..9d8ec60812 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" + "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/stringutils" "github.com/go-check/check" "github.com/gotestyourself/gotestyourself/icmd" @@ -194,3 +195,19 @@ func NewEnvClientWithVersion(version string) (*client.Client, error) { cli.NegotiateAPIVersionPing(types.Ping{APIVersion: version}) return cli, nil } + +// 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 { + v := GetKernelVersion() + if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 { + return false + } + return true +} From f089a1df393228085c4895b8db0fa95128173398 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Mon, 11 Sep 2017 16:34:08 +0200 Subject: [PATCH 08/18] Skip some tests for E2E Signed-off-by: Christopher Crone --- integration-cli/docker_api_build_test.go | 21 +++++++++++++-- integration-cli/docker_api_containers_test.go | 3 +++ integration-cli/docker_api_images_test.go | 3 ++- .../docker_cli_attach_unix_test.go | 4 +-- integration-cli/docker_cli_build_test.go | 27 +++++++++++++++++-- integration-cli/docker_cli_build_unix_test.go | 3 ++- .../docker_cli_network_unix_test.go | 6 +++-- integration-cli/docker_cli_ps_test.go | 6 ++++- 8 files changed, 62 insertions(+), 11 deletions(-) diff --git a/integration-cli/docker_api_build_test.go b/integration-cli/docker_api_build_test.go index 59b451024e..22b6e5c501 100644 --- a/integration-cli/docker_api_build_test.go +++ b/integration-cli/docker_api_build_test.go @@ -27,7 +27,9 @@ import ( ) func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) { - testRequires(c, NotUserNamespace) + // E2E: Requires built httpserver. + testRequires(c, NotUserNamespace, NotE2E) + var testD string if testEnv.DaemonPlatform() == "windows" { testD = `FROM busybox @@ -57,6 +59,9 @@ RUN find /tmp/` } func (s *DockerSuite) TestBuildAPIRemoteTarballContext(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() @@ -88,6 +93,9 @@ func (s *DockerSuite) TestBuildAPIRemoteTarballContext(c *check.C) { } func (s *DockerSuite) TestBuildAPIRemoteTarballContextWithCustomDockerfile(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() @@ -142,6 +150,8 @@ RUN echo 'right' } func (s *DockerSuite) TestBuildAPILowerDockerfile(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) git := fakegit.New(c, "repo", map[string]string{ "dockerfile": `FROM busybox RUN echo from dockerfile`, @@ -160,6 +170,9 @@ RUN echo from dockerfile`, } func (s *DockerSuite) TestBuildAPIBuildGitWithF(c *check.C) { + // E2E: Test requires go and contrib source. + testRequires(c, NotE2E) + git := fakegit.New(c, "repo", map[string]string{ "baz": `FROM busybox RUN echo from baz`, @@ -181,7 +194,8 @@ RUN echo from Dockerfile`, } func (s *DockerSuite) TestBuildAPIDoubleDockerfile(c *check.C) { - testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows + // E2E: Requires built httpserver. + testRequires(c, UnixCli, NotE2E) // dockerfile overwrites Dockerfile on Windows git := fakegit.New(c, "repo", map[string]string{ "Dockerfile": `FROM busybox RUN echo from Dockerfile`, @@ -366,6 +380,9 @@ func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *check.C) { } func (s *DockerSuite) TestBuildAddRemoteNoDecompress(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) dt := []byte("contents") diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index f60436766a..ddc5a43603 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1409,6 +1409,9 @@ func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs( } func (s *DockerSuite) TestContainerAPIGetContainersJSONEmpty(c *check.C) { + // E2E: Test assumes no other containers running. + testRequires(c, NotE2E) + cli, err := client.NewEnvClient() c.Assert(err, checker.IsNil) defer cli.Close() diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index 4b3fb059cf..e380543210 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -119,7 +119,8 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) { } func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) { - testRequires(c, Network) + // E2E: Test runs local HTTP server. + testRequires(c, Network, NotE2E) server := httptest.NewServer(http.NewServeMux()) defer server.Close() diff --git a/integration-cli/docker_cli_attach_unix_test.go b/integration-cli/docker_cli_attach_unix_test.go index 78f55e043d..e40d7cf39c 100644 --- a/integration-cli/docker_cli_attach_unix_test.go +++ b/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 { diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 59213e5404..3d0b49dcf9 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -368,7 +368,8 @@ ONBUILD ENTRYPOINT ["echo"]`)) } func (s *DockerSuite) TestBuildCacheAdd(c *check.C) { - testRequires(c, DaemonIsLinux) // Windows doesn't have httpserver image yet + // E2E: Requires built httpserver. + testRequires(c, DaemonIsLinux, NotE2E) // Windows doesn't have httpserver image yet name := "testbuildtwoimageswithadd" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "robots.txt": "hello", @@ -388,6 +389,9 @@ func (s *DockerSuite) TestBuildCacheAdd(c *check.C) { } func (s *DockerSuite) TestBuildLastModified(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + // Temporary fix for #30890. TODO @jhowardmsft figure out what // has changed in the master busybox image. testRequires(c, DaemonIsLinux) @@ -517,7 +521,8 @@ RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' } func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) { - testRequires(c, DaemonIsLinux) // Linux specific test + // E2E: Requires built httpserver. + testRequires(c, DaemonIsLinux, NotE2E) // Linux specific test server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "robots.txt": "hello", })) @@ -632,6 +637,9 @@ RUN find "test6" "C:/test dir/test_file6"` } func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + name := "testcopywildcard" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "robots.txt": "hello", @@ -1927,6 +1935,9 @@ func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) { } func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + name := "testbuildaddremotefilewithcache" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "baz": "hello", @@ -1952,6 +1963,9 @@ func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) { } func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + name := "testbuildaddremotefilemtime" name2 := name + "2" name3 := name + "3" @@ -1995,6 +2009,9 @@ func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) { // FIXME(vdemeester) this really seems to test the same thing as before (combined) func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithAndWithoutCache(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + name := "testbuildaddlocalandremotefilewithcache" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "baz": "hello", @@ -3095,6 +3112,9 @@ func (s *DockerSuite) TestBuildFromGitWithF(c *check.C) { } func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + name := "testbuildfromremotetarball" buffer := new(bytes.Buffer) @@ -3761,6 +3781,9 @@ func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) { } func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) { + // E2E: Requires built httpserver. + testRequires(c, NotE2E) + server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{"baz": `FROM busybox RUN echo from baz COPY * /tmp/ diff --git a/integration-cli/docker_cli_build_unix_test.go b/integration-cli/docker_cli_build_unix_test.go index dbcf00b5d4..06c4d276e9 100644 --- a/integration-cli/docker_cli_build_unix_test.go +++ b/integration-cli/docker_cli_build_unix_test.go @@ -25,7 +25,8 @@ import ( ) func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { - testRequires(c, cpuCfsQuota) + // E2E: Test assumes no other containers running. + testRequires(c, cpuCfsQuota, NotE2E) name := "testbuildresourceconstraints" ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(` diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index 2fc0724171..bdb184fa79 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -289,7 +289,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) { } func (s *DockerSuite) TestNetworkLsFormat(c *check.C) { - testRequires(c, DaemonIsLinux) + // E2E: Test assumes only default networks. + testRequires(c, DaemonIsLinux, NotE2E) out, _ := dockerCmd(c, "network", "ls", "--format", "{{.Name}}") lines := strings.Split(strings.TrimSpace(string(out)), "\n") @@ -300,7 +301,8 @@ func (s *DockerSuite) TestNetworkLsFormat(c *check.C) { } func (s *DockerSuite) TestNetworkLsFormatDefaultFormat(c *check.C) { - testRequires(c, DaemonIsLinux) + // E2E: Test assumes only default networks. + testRequires(c, DaemonIsLinux, NotE2E) config := `{ "networksFormat": "{{ .Name }} default" diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go index 2572535e30..61241dd12c 100644 --- a/integration-cli/docker_cli_ps_test.go +++ b/integration-cli/docker_cli_ps_test.go @@ -519,8 +519,9 @@ func (s *DockerSuite) TestPsRightTagName(c *check.C) { } func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) { + // E2E: Test assumes no other containers. // Problematic on Windows as it doesn't support links as of Jan 2016 - testRequires(c, DaemonIsLinux) + testRequires(c, DaemonIsLinux, NotE2E) runSleepingContainer(c, "--name=first") runSleepingContainer(c, "--name=second", "--link=first:first") @@ -632,6 +633,9 @@ func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) { } func (s *DockerSuite) TestPsFormatHeaders(c *check.C) { + // E2E: Test assumes no other containers. + testRequires(c, NotE2E) + // 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)) From 86f9eb4a085a61b3355dc38452c47def806bf7c9 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Tue, 12 Sep 2017 14:53:20 +0200 Subject: [PATCH 09/18] Fixes for dnephin review Signed-off-by: Christopher Crone --- Dockerfile.e2e | 38 ++++++++++------- internal/e2e/run.sh => hack/test/e2e-run.sh | 2 + .../cli/build/fakestorage/fixtures.go | 41 +++++++++++-------- integration-cli/docker_api_build_test.go | 20 +-------- integration-cli/docker_api_containers_test.go | 2 +- integration-cli/docker_api_images_test.go | 2 +- .../docker_api_inspect_unix_test.go | 3 +- .../docker_cli_authz_plugin_v2_test.go | 11 +---- integration-cli/docker_cli_authz_unix_test.go | 8 ---- integration-cli/docker_cli_build_test.go | 27 +----------- integration-cli/docker_cli_health_test.go | 8 ++-- integration-cli/docker_cli_kill_test.go | 3 +- integration-cli/docker_cli_port_test.go | 1 + integration-cli/docker_utils_test.go | 2 +- integration-cli/request/request.go | 12 ++++++ integration-cli/utils_test.go | 19 +-------- 16 files changed, 79 insertions(+), 120 deletions(-) rename internal/e2e/run.sh => hack/test/e2e-run.sh (83%) diff --git a/Dockerfile.e2e b/Dockerfile.e2e index 6d8e5dfbd6..6ce92dd1fc 100644 --- a/Dockerfile.e2e +++ b/Dockerfile.e2e @@ -1,3 +1,4 @@ +## Step 1: Build tests FROM golang:1.8.3-alpine3.6 as builder RUN apk add --update \ @@ -11,26 +12,31 @@ RUN apk add --update \ RUN mkdir -p /go/src/github.com/docker/docker/ WORKDIR /go/src/github.com/docker/docker/ -COPY contrib contrib +# 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 - -# integration-cli tests are frozen to 17.06 -# Newer CLI tests can be found in the docker/cli repository -RUN curl https://download.docker.com/linux/static/stable/x86_64/docker-17.06.2-ce.tgz | tar xzf - -C /output - 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 @@ -47,15 +53,17 @@ RUN apk add --update \ # Add an unprivileged user to be used for tests which need it RUN addgroup docker && adduser -D -G docker unprivilegeduser -s /bin/ash -ENV DOCKER_E2E=1 DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/ - -COPY --from=builder /output/docker/docker /usr/bin/docker -COPY --from=builder /output/docker-frozen-images /docker-frozen-images -COPY --from=builder /output/tests /tests - -COPY contrib /tests/contrib +COPY contrib/httpserver/Dockerfile /tests/contrib/httpserver/Dockerfile +COPY contrib/syscall-test /tests/contrib/syscall-test +COPY hack/test/e2e-run.sh /run.sh COPY hack/make/.ensure-emptyfs /ensure-emptyfs.sh COPY integration-cli/fixtures /tests/integration-cli/fixtures -COPY internal/e2e/run.sh /run.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_E2E=1 DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/ ENTRYPOINT ["/run.sh"] diff --git a/internal/e2e/run.sh b/hack/test/e2e-run.sh similarity index 83% rename from internal/e2e/run.sh rename to hack/test/e2e-run.sh index 83b88ae509..e7a2c5420b 100755 --- a/internal/e2e/run.sh +++ b/hack/test/e2e-run.sh @@ -1,6 +1,8 @@ #!/usr/bin/env bash set -e +export DOCKER_ENGINE_GOARCH=${DOCKER_ENGINE_GOARCH:-amd64} + echo "Ensure emptyfs image is loaded" bash /ensure-emptyfs.sh diff --git a/integration-cli/cli/build/fakestorage/fixtures.go b/integration-cli/cli/build/fakestorage/fixtures.go index 8a6bb137ad..b76a7d9207 100644 --- a/integration-cli/cli/build/fakestorage/fixtures.go +++ b/integration-cli/cli/build/fakestorage/fixtures.go @@ -39,27 +39,34 @@ func ensureHTTPServerImage(t testingT) { goarch = "amd64" } - goCmd, lookErr := exec.LookPath("go") - 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)) - } - cpCmd, lookErr := exec.LookPath("cp") if lookErr != nil { t.Fatalf("could not build http server: %v", lookErr) } - if out, err = exec.Command(cpCmd, "../contrib/httpserver/Dockerfile", filepath.Join(tmp, "Dockerfile")).CombinedOutput(); err != nil { + + 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) + } + + 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 { t.Fatalf("could not build http server: %v", string(out)) } diff --git a/integration-cli/docker_api_build_test.go b/integration-cli/docker_api_build_test.go index 22b6e5c501..d428d78f0a 100644 --- a/integration-cli/docker_api_build_test.go +++ b/integration-cli/docker_api_build_test.go @@ -27,8 +27,7 @@ import ( ) func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotUserNamespace, NotE2E) + testRequires(c, NotUserNamespace) var testD string if testEnv.DaemonPlatform() == "windows" { @@ -59,9 +58,6 @@ RUN find /tmp/` } func (s *DockerSuite) TestBuildAPIRemoteTarballContext(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() @@ -93,9 +89,6 @@ func (s *DockerSuite) TestBuildAPIRemoteTarballContext(c *check.C) { } func (s *DockerSuite) TestBuildAPIRemoteTarballContextWithCustomDockerfile(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() @@ -150,8 +143,6 @@ RUN echo 'right' } func (s *DockerSuite) TestBuildAPILowerDockerfile(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) git := fakegit.New(c, "repo", map[string]string{ "dockerfile": `FROM busybox RUN echo from dockerfile`, @@ -170,9 +161,6 @@ RUN echo from dockerfile`, } func (s *DockerSuite) TestBuildAPIBuildGitWithF(c *check.C) { - // E2E: Test requires go and contrib source. - testRequires(c, NotE2E) - git := fakegit.New(c, "repo", map[string]string{ "baz": `FROM busybox RUN echo from baz`, @@ -194,8 +182,7 @@ RUN echo from Dockerfile`, } func (s *DockerSuite) TestBuildAPIDoubleDockerfile(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, UnixCli, NotE2E) // dockerfile overwrites Dockerfile on Windows + testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows git := fakegit.New(c, "repo", map[string]string{ "Dockerfile": `FROM busybox RUN echo from Dockerfile`, @@ -380,9 +367,6 @@ func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *check.C) { } func (s *DockerSuite) TestBuildAddRemoteNoDecompress(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) dt := []byte("contents") diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index ddc5a43603..dbec3dc76c 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1372,7 +1372,7 @@ func (s *DockerSuite) TestContainerAPICreateNoHostConfig118(c *check.C) { Image: "busybox", } - cli, err := NewEnvClientWithVersion("v1.18") + cli, err := request.NewEnvClientWithVersion("v1.18") _, err = cli.ContainerCreate(context.Background(), &config, &containertypes.HostConfig{}, &networktypes.NetworkingConfig{}, "") c.Assert(err, checker.IsNil) diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index e380543210..b9dae7aab7 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -180,7 +180,7 @@ func (s *DockerSuite) TestAPIImagesSizeCompatibility(c *check.C) { Labels map[string]string } - cli, err = NewEnvClientWithVersion("v1.24") + cli, err = request.NewEnvClientWithVersion("v1.24") c.Assert(err, checker.IsNil) defer cli.Close() diff --git a/integration-cli/docker_api_inspect_unix_test.go b/integration-cli/docker_api_inspect_unix_test.go index 7fc4cb0b45..dae64be2a7 100644 --- a/integration-cli/docker_api_inspect_unix_test.go +++ b/integration-cli/docker_api_inspect_unix_test.go @@ -6,6 +6,7 @@ import ( "encoding/json" "github.com/docker/docker/integration-cli/checker" + "github.com/docker/docker/integration-cli/request" "github.com/go-check/check" "golang.org/x/net/context" ) @@ -17,7 +18,7 @@ func (s *DockerSuite) TestInspectAPICpusetInConfigPre120(c *check.C) { name := "cpusetinconfig-pre120" dockerCmd(c, "run", "--name", name, "--cpuset-cpus", "0", "busybox", "true") - cli, err := NewEnvClientWithVersion("v1.19") + cli, err := request.NewEnvClientWithVersion("v1.19") c.Assert(err, checker.IsNil) defer cli.Close() _, body, err := cli.ContainerInspectWithRaw(context.Background(), name, false) diff --git a/integration-cli/docker_cli_authz_plugin_v2_test.go b/integration-cli/docker_cli_authz_plugin_v2_test.go index 025d5aeb7f..bdc3f15e5b 100644 --- a/integration-cli/docker_cli_authz_plugin_v2_test.go +++ b/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" @@ -48,8 +47,6 @@ func (s *DockerAuthzV2Suite) TearDownTest(c *check.C) { func (s *DockerAuthzV2Suite) TestAuthZPluginAllowNonVolumeRequest(c *check.C) { testRequires(c, DaemonIsLinux, IsAmd64, Network) - existingContainers := ExistingContainerIDs(c) - // Install authz plugin _, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", authzPluginNameWithTag) c.Assert(err, checker.IsNil) @@ -68,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") + _, err = s.d.Cmd("run", "-d", "busybox", "top") c.Assert(err, check.IsNil) - - id := strings.TrimSpace(out) - - out, err = s.d.Cmd("ps") - c.Assert(err, check.IsNil) - c.Assert(assertContainerList(RemoveOutputForExistingElements(out, existingContainers), []string{id}), check.Equals, true) } func (s *DockerAuthzV2Suite) TestAuthZPluginDisable(c *check.C) { diff --git a/integration-cli/docker_cli_authz_unix_test.go b/integration-cli/docker_cli_authz_unix_test.go index cf3d88e12a..5b7b9fab14 100644 --- a/integration-cli/docker_cli_authz_unix_test.go +++ b/integration-cli/docker_cli_authz_unix_test.go @@ -204,8 +204,6 @@ func (s *DockerAuthzSuite) TearDownSuite(c *check.C) { } func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) { - existingContainers := ExistingContainerIDs(c) - // start the daemon and load busybox, --net=none build fails otherwise // cause it needs to pull busybox s.d.Start(c, "--authorization-plugin="+testAuthZPlugin) @@ -220,12 +218,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(RemoveOutputForExistingElements(out, existingContainers), []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) { diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 3d0b49dcf9..59213e5404 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -368,8 +368,7 @@ ONBUILD ENTRYPOINT ["echo"]`)) } func (s *DockerSuite) TestBuildCacheAdd(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, DaemonIsLinux, NotE2E) // Windows doesn't have httpserver image yet + testRequires(c, DaemonIsLinux) // Windows doesn't have httpserver image yet name := "testbuildtwoimageswithadd" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "robots.txt": "hello", @@ -389,9 +388,6 @@ func (s *DockerSuite) TestBuildCacheAdd(c *check.C) { } func (s *DockerSuite) TestBuildLastModified(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - // Temporary fix for #30890. TODO @jhowardmsft figure out what // has changed in the master busybox image. testRequires(c, DaemonIsLinux) @@ -521,8 +517,7 @@ RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' } func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, DaemonIsLinux, NotE2E) // Linux specific test + testRequires(c, DaemonIsLinux) // Linux specific test server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "robots.txt": "hello", })) @@ -637,9 +632,6 @@ RUN find "test6" "C:/test dir/test_file6"` } func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - name := "testcopywildcard" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "robots.txt": "hello", @@ -1935,9 +1927,6 @@ func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) { } func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - name := "testbuildaddremotefilewithcache" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "baz": "hello", @@ -1963,9 +1952,6 @@ func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) { } func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - name := "testbuildaddremotefilemtime" name2 := name + "2" name3 := name + "3" @@ -2009,9 +1995,6 @@ func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) { // FIXME(vdemeester) this really seems to test the same thing as before (combined) func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithAndWithoutCache(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - name := "testbuildaddlocalandremotefilewithcache" server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{ "baz": "hello", @@ -3112,9 +3095,6 @@ func (s *DockerSuite) TestBuildFromGitWithF(c *check.C) { } func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - name := "testbuildfromremotetarball" buffer := new(bytes.Buffer) @@ -3781,9 +3761,6 @@ func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) { } func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) { - // E2E: Requires built httpserver. - testRequires(c, NotE2E) - server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{"baz": `FROM busybox RUN echo from baz COPY * /tmp/ diff --git a/integration-cli/docker_cli_health_test.go b/integration-cli/docker_cli_health_test.go index f6228075be..20b2bc255d 100644 --- a/integration-cli/docker_cli_health_test.go +++ b/integration-cli/docker_cli_health_test.go @@ -39,7 +39,7 @@ 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 := ExistingContainerNames(c) + existingContainers := ExistingContainerIDs(c) imageName := "testhealth" buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox @@ -51,10 +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}}") + cid, _ := dockerCmd(c, "create", "--name", name, imageName) + out, _ := dockerCmd(c, "ps", "-a", "--format={{.ID}} {{.Status}}") out = RemoveOutputForExistingElements(out, existingContainers) - c.Check(out, checker.Equals, "Created\n") + c.Check(out, checker.Equals, cid[:12]+" Created\n") // Inspect the options out, _ = dockerCmd(c, "inspect", diff --git a/integration-cli/docker_cli_kill_test.go b/integration-cli/docker_cli_kill_test.go index a949bdb37f..0a5aac5f8c 100644 --- a/integration-cli/docker_cli_kill_test.go +++ b/integration-cli/docker_cli_kill_test.go @@ -6,6 +6,7 @@ import ( "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" @@ -129,7 +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") - cli, err := NewEnvClientWithVersion("v1.19") + cli, err := request.NewEnvClientWithVersion("v1.19") c.Assert(err, check.IsNil) defer cli.Close() err = cli.ContainerKill(context.Background(), "docker-kill-test-api", "SIGKILL") diff --git a/integration-cli/docker_cli_port_test.go b/integration-cli/docker_cli_port_test.go index 7450dd4837..84058cda10 100644 --- a/integration-cli/docker_cli_port_test.go +++ b/integration-cli/docker_cli_port_test.go @@ -149,6 +149,7 @@ func (s *DockerSuite) TestPortList(c *check.C) { out, _ = dockerCmd(c, "port", ID) + // 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) diff --git a/integration-cli/docker_utils_test.go b/integration-cli/docker_utils_test.go index 194e0660f2..1bda2c7239 100644 --- a/integration-cli/docker_utils_test.go +++ b/integration-cli/docker_utils_test.go @@ -372,7 +372,7 @@ func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg } func getInspectBody(c *check.C, version, id string) []byte { - cli, err := NewEnvClientWithVersion(version) + cli, err := request.NewEnvClientWithVersion(version) c.Assert(err, check.IsNil) defer cli.Close() _, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false) diff --git a/integration-cli/request/request.go b/integration-cli/request/request.go index f2b0320bd0..495a1b0eae 100644 --- a/integration-cli/request/request.go +++ b/integration-cli/request/request.go @@ -18,6 +18,7 @@ import ( "time" "github.com/docker/docker/api" + "github.com/docker/docker/api/types" dclient "github.com/docker/docker/client" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/ioutils" @@ -323,3 +324,14 @@ 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) { + cli, err := dclient.NewEnvClient() + if err != nil { + return nil, err + } + cli.NegotiateAPIVersionPing(types.Ping{APIVersion: version}) + return cli, nil +} diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index 9d8ec60812..f6f111ec25 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -7,8 +7,6 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/stringutils" "github.com/go-check/check" @@ -185,17 +183,6 @@ func RemoveOutputForExistingElements(output string, existing []string) string { return strings.Join(res, "\n") } -// NewEnvClientWithVersion returns a docker client with a specified version. -// See: github.com/docker/docker/client `NewEnvClient()` -func NewEnvClientWithVersion(version string) (*client.Client, error) { - cli, err := client.NewEnvClient() - if err != nil { - return nil, err - } - cli.NegotiateAPIVersionPing(types.Ping{APIVersion: version}) - return cli, nil -} - // GetKernelVersion gets the current kernel version. func GetKernelVersion() *kernel.VersionInfo { v, _ := kernel.ParseRelease(testEnv.DaemonInfo.KernelVersion) @@ -205,9 +192,5 @@ func GetKernelVersion() *kernel.VersionInfo { // CheckKernelVersion checks if current kernel is newer than (or equal to) // the given version. func CheckKernelVersion(k, major, minor int) bool { - v := GetKernelVersion() - if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) < 0 { - return false - } - return true + return kernel.CompareKernelVersion(*GetKernelVersion(), kernel.VersionInfo{Kernel: k, Major: major, Minor: minor}) > 0 } From 6936ce3b65f149ba6ab1cd5c257358c06eb9cdbb Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Tue, 12 Sep 2017 17:18:02 +0200 Subject: [PATCH 10/18] Remove race and split TestAPINetworkInspect test Signed-off-by: Christopher Crone --- integration-cli/docker_api_network_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/integration-cli/docker_api_network_test.go b/integration-cli/docker_api_network_test.go index e9fbf0426c..a49fbae3d4 100644 --- a/integration-cli/docker_api_network_test.go +++ b/integration-cli/docker_api_network_test.go @@ -76,12 +76,11 @@ 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") c.Assert(nr.Name, checker.Equals, "bridge") - connCount := len(nr.Containers) // run a container and attach it to the default bridge network out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top") @@ -95,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, connCount+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", @@ -118,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") From 42d812df0a12d92fad1f327f0b0f5d9eb7a9f107 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Tue, 12 Sep 2017 17:18:36 +0200 Subject: [PATCH 11/18] Bring up DockerNetworkSuite Signed-off-by: Christopher Crone --- hack/test/e2e-run.sh | 2 +- integration-cli/docker_cli_network_unix_test.go | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hack/test/e2e-run.sh b/hack/test/e2e-run.sh index e7a2c5420b..4328837127 100755 --- a/hack/test/e2e-run.sh +++ b/hack/test/e2e-run.sh @@ -12,4 +12,4 @@ cd /tests/integration/container echo "Run integration-cli DockerSuite tests" cd /tests/integration-cli -./test.main -test.v -check.v -check.f DockerSuite +./test.main -test.v -check.v -check.f "DockerSuite|DockerNetworkSuite" diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index bdb184fa79..c4da8ae2e2 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -353,6 +353,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) { } func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) { + // E2E: Test assumes clean network environment. + testRequires(c, NotE2E) testNet := "testnet1" testLabel := "foo" testValue := "bar" @@ -626,6 +628,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") @@ -666,6 +669,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") @@ -681,6 +685,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") @@ -693,6 +698,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) @@ -798,6 +804,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] @@ -983,6 +990,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 @@ -1009,7 +1017,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" @@ -1050,6 +1058,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" @@ -1115,6 +1124,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"} @@ -1133,6 +1143,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRest } func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) { + testRequires(c, SameHostDaemon) cName := "cc" nwList := []string{"nw1", "nw2", "nw3"} @@ -1159,7 +1170,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 @@ -1285,6 +1296,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") From 85431566a81792e3612df3b6b858f7b0c3506883 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Wed, 13 Sep 2017 11:30:10 +0200 Subject: [PATCH 12/18] Set client version instead of negotiating it Signed-off-by: Christopher Crone --- integration-cli/request/request.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/integration-cli/request/request.go b/integration-cli/request/request.go index 495a1b0eae..f22b08d768 100644 --- a/integration-cli/request/request.go +++ b/integration-cli/request/request.go @@ -18,7 +18,6 @@ import ( "time" "github.com/docker/docker/api" - "github.com/docker/docker/api/types" dclient "github.com/docker/docker/client" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/ioutils" @@ -328,10 +327,31 @@ func DaemonHost() string { // NewEnvClientWithVersion returns a docker client with a specified version. // See: github.com/docker/docker/client `NewEnvClient()` func NewEnvClientWithVersion(version string) (*dclient.Client, error) { - cli, err := dclient.NewEnvClient() - if err != nil { - return nil, err + 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 } - cli.NegotiateAPIVersionPing(types.Ping{APIVersion: version}) return cli, nil } From 5eab08930c9c2d39bb76fd6320e9979b504750a6 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Wed, 13 Sep 2017 11:30:52 +0200 Subject: [PATCH 13/18] Correct log message Signed-off-by: Christopher Crone --- hack/test/e2e-run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/test/e2e-run.sh b/hack/test/e2e-run.sh index 4328837127..0587148fb3 100755 --- a/hack/test/e2e-run.sh +++ b/hack/test/e2e-run.sh @@ -10,6 +10,6 @@ echo "Run integration/container tests" cd /tests/integration/container ./test.main -test.v -echo "Run integration-cli DockerSuite tests" +echo "Run integration-cli tests (DockerSuite, DockerNetworkSuite)" cd /tests/integration-cli ./test.main -test.v -check.v -check.f "DockerSuite|DockerNetworkSuite" From 61b13ba0d12aeeadc1c08eae62ba83f62208a6d3 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Wed, 13 Sep 2017 11:36:31 +0200 Subject: [PATCH 14/18] Test requires SameHostDaemon Signed-off-by: Christopher Crone --- integration-cli/docker_cli_network_unix_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index c4da8ae2e2..c9eef72326 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -1824,7 +1824,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") From 81f69a593146f61d3f6568403168ba28b1714f97 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Wed, 13 Sep 2017 14:49:32 +0200 Subject: [PATCH 15/18] Fix Windows build Signed-off-by: Christopher Crone --- integration-cli/utils_test.go | 13 ------------- integration-cli/utils_unix_test.go | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 integration-cli/utils_unix_test.go diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index f6f111ec25..d176c7f062 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -7,7 +7,6 @@ import ( "path/filepath" "strings" - "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/stringutils" "github.com/go-check/check" "github.com/gotestyourself/gotestyourself/icmd" @@ -182,15 +181,3 @@ func RemoveOutputForExistingElements(output string, existing []string) string { res := RemoveLinesForExistingElements(strings.Split(output, "\n"), existing) return strings.Join(res, "\n") } - -// 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 -} diff --git a/integration-cli/utils_unix_test.go b/integration-cli/utils_unix_test.go new file mode 100644 index 0000000000..b32e3baf3d --- /dev/null +++ b/integration-cli/utils_unix_test.go @@ -0,0 +1,19 @@ +// +build linux freebsd solaris openbsd + +package main + +import ( + "github.com/docker/docker/pkg/parsers/kernel" +) + +// 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 +} From 7dabed019a7aac9b317b586d582431eef3b65e33 Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Thu, 14 Sep 2017 19:17:49 +0200 Subject: [PATCH 16/18] Fixes after dnephin review Signed-off-by: Christopher Crone --- Dockerfile.e2e | 9 ++-- hack/test/e2e-run.sh | 42 +++++++++++++++---- integration-cli/check_test.go | 12 +++--- integration-cli/docker_api_containers_test.go | 13 ------ integration-cli/docker_api_images_test.go | 3 +- .../docker_cli_authz_plugin_v2_test.go | 2 +- integration-cli/docker_cli_authz_unix_test.go | 1 + integration-cli/docker_cli_build_unix_test.go | 8 ++-- integration-cli/docker_cli_config_ls_test.go | 1 + ...er_cli_external_volume_driver_unix_test.go | 1 + .../docker_cli_network_unix_test.go | 39 +---------------- integration-cli/docker_cli_ps_test.go | 19 ++------- .../docker_cli_update_unix_test.go | 13 ++++++ integration-cli/docker_hub_pull_suite_test.go | 2 +- integration-cli/requirements_test.go | 19 ++++++--- integration-cli/utils_unix_test.go | 19 --------- integration/service/inspect_test.go | 2 + 17 files changed, 87 insertions(+), 118 deletions(-) delete mode 100644 integration-cli/utils_unix_test.go diff --git a/Dockerfile.e2e b/Dockerfile.e2e index 6ce92dd1fc..3d700fab51 100644 --- a/Dockerfile.e2e +++ b/Dockerfile.e2e @@ -55,15 +55,16 @@ 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 hack/test/e2e-run.sh /run.sh -COPY hack/make/.ensure-emptyfs /ensure-emptyfs.sh 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_E2E=1 DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/ +ENV DOCKER_REMOTE_DAEMON=1 DOCKER_INTEGRATION_DAEMON_DEST=/ -ENTRYPOINT ["/run.sh"] +ENTRYPOINT ["/scripts/run.sh"] diff --git a/hack/test/e2e-run.sh b/hack/test/e2e-run.sh index 0587148fb3..bfcc03f628 100755 --- a/hack/test/e2e-run.sh +++ b/hack/test/e2e-run.sh @@ -1,15 +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} -echo "Ensure emptyfs image is loaded" -bash /ensure-emptyfs.sh +run_test_integration() { + run_test_integration_suites + run_test_integration_legacy_suites +} -echo "Run integration/container tests" -cd /tests/integration/container -./test.main -test.v +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 +} -echo "Run integration-cli tests (DockerSuite, DockerNetworkSuite)" -cd /tests/integration-cli -./test.main -test.v -check.v -check.f "DockerSuite|DockerNetworkSuite" +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 diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index 3ee1a56245..2dfb696ab7 100644 --- a/integration-cli/check_test.go +++ b/integration-cli/check_test.go @@ -117,7 +117,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(), @@ -151,7 +151,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(), @@ -185,7 +185,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(), @@ -221,7 +221,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(), }) @@ -316,7 +316,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 { @@ -468,7 +468,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) diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index dbec3dc76c..139a1b8ff8 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -1408,19 +1408,6 @@ func (s *DockerSuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRootfs( c.Assert(err.Error(), checker.Contains, "container rootfs is marked read-only") } -func (s *DockerSuite) TestContainerAPIGetContainersJSONEmpty(c *check.C) { - // E2E: Test assumes no other containers running. - testRequires(c, NotE2E) - - 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) diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index b9dae7aab7..fba69dc682 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -119,8 +119,7 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) { } func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) { - // E2E: Test runs local HTTP server. - testRequires(c, Network, NotE2E) + testRequires(c, Network, SameHostDaemon) server := httptest.NewServer(http.NewServeMux()) defer server.Close() diff --git a/integration-cli/docker_cli_authz_plugin_v2_test.go b/integration-cli/docker_cli_authz_plugin_v2_test.go index bdc3f15e5b..30026f7fcd 100644 --- a/integration-cli/docker_cli_authz_plugin_v2_test.go +++ b/integration-cli/docker_cli_authz_plugin_v2_test.go @@ -30,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(), }) diff --git a/integration-cli/docker_cli_authz_unix_test.go b/integration-cli/docker_cli_authz_unix_test.go index 5b7b9fab14..8a1bd023ea 100644 --- a/integration-cli/docker_cli_authz_unix_test.go +++ b/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(), }) diff --git a/integration-cli/docker_cli_build_unix_test.go b/integration-cli/docker_cli_build_unix_test.go index 06c4d276e9..91a329fae8 100644 --- a/integration-cli/docker_cli_build_unix_test.go +++ b/integration-cli/docker_cli_build_unix_test.go @@ -25,20 +25,20 @@ import ( ) func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) { - // E2E: Test assumes no other containers running. - testRequires(c, cpuCfsQuota, NotE2E) + 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 { diff --git a/integration-cli/docker_cli_config_ls_test.go b/integration-cli/docker_cli_config_ls_test.go index 5c07012614..5f002bcab6 100644 --- a/integration-cli/docker_cli_config_ls_test.go +++ b/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" diff --git a/integration-cli/docker_cli_external_volume_driver_unix_test.go b/integration-cli/docker_cli_external_volume_driver_unix_test.go index 5fe417c2c8..2e2de972d5 100644 --- a/integration-cli/docker_cli_external_volume_driver_unix_test.go +++ b/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(), }) diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index c9eef72326..4762e3993c 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -10,7 +10,6 @@ import ( "net/http" "net/http/httptest" "os" - "path/filepath" "strings" "time" @@ -288,41 +287,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) { } } -func (s *DockerSuite) TestNetworkLsFormat(c *check.C) { - // E2E: Test assumes only default networks. - testRequires(c, DaemonIsLinux, NotE2E) - 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) { - // E2E: Test assumes only default networks. - testRequires(c, DaemonIsLinux, NotE2E) - - 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 { @@ -353,8 +317,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) { } func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) { - // E2E: Test assumes clean network environment. - testRequires(c, NotE2E) + testRequires(c, OnlyDefaultNetworks) testNet := "testnet1" testLabel := "foo" testValue := "bar" diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go index 61241dd12c..12e7957bf3 100644 --- a/integration-cli/docker_cli_ps_test.go +++ b/integration-cli/docker_cli_ps_test.go @@ -519,9 +519,9 @@ func (s *DockerSuite) TestPsRightTagName(c *check.C) { } func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) { - // E2E: Test assumes no other containers. // Problematic on Windows as it doesn't support links as of Jan 2016 - testRequires(c, DaemonIsLinux, NotE2E) + testRequires(c, DaemonIsLinux) + existingContainers := ExistingContainerIDs(c) runSleepingContainer(c, "--name=first") runSleepingContainer(c, "--name=second", "--link=first:first") @@ -529,6 +529,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 { @@ -632,20 +633,6 @@ func (s *DockerSuite) TestPsNamesMultipleTime(c *check.C) { 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) { - // E2E: Test assumes no other containers. - testRequires(c, NotE2E) - - // 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 := `{ diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go index 7f1cd8dd79..c3dfbcc9c5 100644 --- a/integration-cli/docker_cli_update_unix_test.go +++ b/integration-cli/docker_cli_update_unix_test.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/request" + "github.com/docker/docker/pkg/parsers/kernel" "github.com/go-check/check" "github.com/kr/pty" ) @@ -170,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) diff --git a/integration-cli/docker_hub_pull_suite_test.go b/integration-cli/docker_hub_pull_suite_test.go index 263372087c..286a3913ce 100644 --- a/integration-cli/docker_hub_pull_suite_test.go +++ b/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(), }) diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go index c41a71fa29..411248195b 100644 --- a/integration-cli/requirements_test.go +++ b/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,12 +39,16 @@ func DaemonIsLinux() bool { return testEnv.DaemonInfo.OSType == "linux" } -func E2E() bool { - return os.Getenv("DOCKER_E2E") != "" -} - -func NotE2E() bool { - return !E2E() +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) diff --git a/integration-cli/utils_unix_test.go b/integration-cli/utils_unix_test.go deleted file mode 100644 index b32e3baf3d..0000000000 --- a/integration-cli/utils_unix_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build linux freebsd solaris openbsd - -package main - -import ( - "github.com/docker/docker/pkg/parsers/kernel" -) - -// 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 -} diff --git a/integration/service/inspect_test.go b/integration/service/inspect_test.go index 239075a0fd..61831b72f1 100644 --- a/integration/service/inspect_test.go +++ b/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) From eb396e8984ce64ea6ee9c04905780d74ed7d8d8b Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 15 Sep 2017 11:37:54 +0200 Subject: [PATCH 17/18] Remove erroneous Println Signed-off-by: Christopher Crone --- integration-cli/docker_api_containers_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 139a1b8ff8..173d5f80b0 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/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 From b7d8d2c4ab709f072cbdc4f89a8c80065648757e Mon Sep 17 00:00:00 2001 From: Christopher Crone Date: Fri, 15 Sep 2017 15:16:38 +0200 Subject: [PATCH 18/18] Various fixes Signed-off-by: Christopher Crone --- integration-cli/docker_api_volumes_test.go | 29 ++++++++------ integration-cli/docker_cli_ps_test.go | 5 ++- integration-cli/docker_cli_run_test.go | 25 ++++++++++-- integration-cli/docker_cli_volume_test.go | 46 +++++++++------------- 4 files changed, 61 insertions(+), 44 deletions(-) diff --git a/integration-cli/docker_api_volumes_test.go b/integration-cli/docker_api_volumes_test.go index 5e3d6a929a..65a9652092 100644 --- a/integration-cli/docker_api_volumes_test.go +++ b/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) diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go index 12e7957bf3..bea1261202 100644 --- a/integration-cli/docker_cli_ps_test.go +++ b/integration-cli/docker_cli_ps_test.go @@ -231,6 +231,7 @@ func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) { } 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) @@ -268,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)) } @@ -958,6 +959,7 @@ func (s *DockerSuite) TestPsFormatTemplateWithArg(c *check.C) { 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) @@ -986,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) } diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 45a56bcfed..1ad5ce7ebd 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/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 @@ -3967,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) { diff --git a/integration-cli/docker_cli_volume_test.go b/integration-cli/docker_cli_volume_test.go index 3ca0834806..fc930d319c 100644 --- a/integration-cli/docker_cli_volume_test.go +++ b/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) {