diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 607604392f6d3..b26e07186cec4 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -208,14 +208,10 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) { return errors.Wrap(err, "failed to validate authorization plugin") } - // TODO: move into startMetricsServer() - if cli.Config.MetricsAddress != "" { - if !d.HasExperimental() { - return errors.Wrap(err, "metrics-addr is only supported when experimental is enabled") - } - if err := startMetricsServer(cli.Config.MetricsAddress); err != nil { - return err - } + cli.d = d + + if err := cli.startMetricsServer(cli.Config.MetricsAddress); err != nil { + return err } c, err := createAndStartCluster(cli, d) @@ -230,8 +226,6 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) { logrus.Info("Daemon has completed initialization") - cli.d = d - routerOptions, err := newRouterOptions(cli.Config, d) if err != nil { return err diff --git a/cmd/dockerd/metrics.go b/cmd/dockerd/metrics.go index 20ceaf8466612..1bfa37ea824a5 100644 --- a/cmd/dockerd/metrics.go +++ b/cmd/dockerd/metrics.go @@ -5,10 +5,19 @@ import ( "net/http" "github.com/docker/go-metrics" + "github.com/pkg/errors" "github.com/sirupsen/logrus" ) -func startMetricsServer(addr string) error { +func (cli *DaemonCli) startMetricsServer(addr string) error { + if addr == "" { + return nil + } + + if !cli.d.HasExperimental() { + return errors.New("metrics-addr is only supported when experimental is enabled") + } + if err := allocateDaemonPort(addr); err != nil { return err } diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index 8bb1cfea8751e..8213d02053bd9 100644 --- a/integration-cli/check_test.go +++ b/integration-cli/check_test.go @@ -18,13 +18,13 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/integration-cli/environment" - testdaemon "github.com/docker/docker/internal/test/daemon" - ienv "github.com/docker/docker/internal/test/environment" - "github.com/docker/docker/internal/test/fakestorage" - "github.com/docker/docker/internal/test/fixtures/plugin" - "github.com/docker/docker/internal/test/registry" "github.com/docker/docker/internal/test/suite" "github.com/docker/docker/pkg/reexec" + testdaemon "github.com/docker/docker/testutil/daemon" + ienv "github.com/docker/docker/testutil/environment" + "github.com/docker/docker/testutil/fakestorage" + "github.com/docker/docker/testutil/fixtures/plugin" + "github.com/docker/docker/testutil/registry" "gotest.tools/assert" ) diff --git a/integration-cli/cli/build/build.go b/integration-cli/cli/build/build.go index 0b10ea79f81e5..510cd927cdd75 100644 --- a/integration-cli/cli/build/build.go +++ b/integration-cli/cli/build/build.go @@ -4,7 +4,7 @@ import ( "io" "strings" - "github.com/docker/docker/internal/test/fakecontext" + "github.com/docker/docker/testutil/fakecontext" "gotest.tools/icmd" ) diff --git a/integration-cli/daemon/daemon.go b/integration-cli/daemon/daemon.go index 76c307aff8a5a..3aae4edaa884e 100644 --- a/integration-cli/daemon/daemon.go +++ b/integration-cli/daemon/daemon.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "github.com/pkg/errors" "gotest.tools/assert" "gotest.tools/icmd" @@ -31,7 +31,7 @@ type Daemon struct { // New returns a Daemon instance to be used for testing. // This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST. // The daemon will not automatically start. -func New(t testingT, dockerBinary string, dockerdBinary string, ops ...func(*daemon.Daemon)) *Daemon { +func New(t testingT, dockerBinary string, dockerdBinary string, ops ...daemon.Option) *Daemon { ops = append(ops, daemon.WithDockerdBinary(dockerdBinary)) d := daemon.New(t, ops...) return &Daemon{ diff --git a/integration-cli/docker_api_attach_test.go b/integration-cli/docker_api_attach_test.go index b87355223c4f0..e7c751c2e6279 100644 --- a/integration-cli/docker_api_attach_test.go +++ b/integration-cli/docker_api_attach_test.go @@ -15,8 +15,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test/request" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil/request" "github.com/pkg/errors" "golang.org/x/net/websocket" "gotest.tools/assert" diff --git a/integration-cli/docker_api_build_test.go b/integration-cli/docker_api_build_test.go index be96cb9df0a88..f1acaed9d743a 100644 --- a/integration-cli/docker_api_build_test.go +++ b/integration-cli/docker_api_build_test.go @@ -14,10 +14,10 @@ import ( "testing" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/test/fakegit" - "github.com/docker/docker/internal/test/fakestorage" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/fakecontext" + "github.com/docker/docker/testutil/fakegit" + "github.com/docker/docker/testutil/fakestorage" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/integration-cli/docker_api_build_windows_test.go b/integration-cli/docker_api_build_windows_test.go index f19cc7a4e1d85..682de714ac1c2 100644 --- a/integration-cli/docker_api_build_windows_test.go +++ b/integration-cli/docker_api_build_windows_test.go @@ -6,8 +6,8 @@ import ( "net/http" "testing" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/fakecontext" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 30ed6113f5010..79f72b9139609 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -25,10 +25,10 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" - "github.com/docker/docker/internal/test/request" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/testutil/request" "github.com/docker/docker/volume" "github.com/docker/go-connections/nat" "gotest.tools/assert" diff --git a/integration-cli/docker_api_exec_resize_test.go b/integration-cli/docker_api_exec_resize_test.go index 0781fbbb156ba..146552bfbe8e9 100644 --- a/integration-cli/docker_api_exec_resize_test.go +++ b/integration-cli/docker_api_exec_resize_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_api_exec_test.go b/integration-cli/docker_api_exec_test.go index b8c257f80bbc8..6684243fd4dfa 100644 --- a/integration-cli/docker_api_exec_test.go +++ b/integration-cli/docker_api_exec_test.go @@ -16,7 +16,7 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" "gotest.tools/poll" ) diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index 788555d81c24e..e1b8199a121b0 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -14,8 +14,8 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" - "github.com/docker/docker/internal/test/request" "github.com/docker/docker/pkg/parsers/kernel" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_api_logs_test.go b/integration-cli/docker_api_logs_test.go index 8a0d540f9744f..848df4b7f44de 100644 --- a/integration-cli/docker_api_logs_test.go +++ b/integration-cli/docker_api_logs_test.go @@ -15,8 +15,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test/request" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_api_network_test.go b/integration-cli/docker_api_network_test.go index baa43d06b6ea2..4c4be109f9940 100644 --- a/integration-cli/docker_api_network_test.go +++ b/integration-cli/docker_api_network_test.go @@ -13,7 +13,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_api_stats_test.go b/integration-cli/docker_api_stats_test.go index 3c04bdb3ff8dd..e1e34d39c65ab 100644 --- a/integration-cli/docker_api_stats_test.go +++ b/integration-cli/docker_api_stats_test.go @@ -16,7 +16,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_api_swarm_service_test.go b/integration-cli/docker_api_swarm_service_test.go index e0500e6242685..ebf12fb8b6b8b 100644 --- a/integration-cli/docker_api_swarm_service_test.go +++ b/integration-cli/docker_api_swarm_service_test.go @@ -16,7 +16,7 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" + testdaemon "github.com/docker/docker/testutil/daemon" "golang.org/x/sys/unix" "gotest.tools/assert" "gotest.tools/icmd" diff --git a/integration-cli/docker_api_swarm_test.go b/integration-cli/docker_api_swarm_test.go index ac919916dd138..2c7be9e314836 100644 --- a/integration-cli/docker_api_swarm_test.go +++ b/integration-cli/docker_api_swarm_test.go @@ -24,8 +24,8 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/request" + testdaemon "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/request" "github.com/docker/swarmkit/ca" "github.com/pkg/errors" "gotest.tools/assert" diff --git a/integration-cli/docker_api_test.go b/integration-cli/docker_api_test.go index 9ada07e615657..a0ed64d5bc9c6 100644 --- a/integration-cli/docker_api_test.go +++ b/integration-cli/docker_api_test.go @@ -11,7 +11,7 @@ import ( "github.com/docker/docker/api" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 3e6a370816aae..ea9a8d7b4be51 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -19,12 +19,12 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/test/fakegit" - "github.com/docker/docker/internal/test/fakestorage" - "github.com/docker/docker/internal/testutil" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/system" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/fakecontext" + "github.com/docker/docker/testutil/fakegit" + "github.com/docker/docker/testutil/fakestorage" "github.com/moby/buildkit/frontend/dockerfile/command" "github.com/opencontainers/go-digest" "gotest.tools/assert" diff --git a/integration-cli/docker_cli_build_unix_test.go b/integration-cli/docker_cli_build_unix_test.go index ef6da0e623130..2d56e2ac94f78 100644 --- a/integration-cli/docker_cli_build_unix_test.go +++ b/integration-cli/docker_cli_build_unix_test.go @@ -18,7 +18,7 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" - "github.com/docker/docker/internal/test/fakecontext" + "github.com/docker/docker/testutil/fakecontext" "github.com/docker/go-units" "gotest.tools/assert" "gotest.tools/icmd" diff --git a/integration-cli/docker_cli_create_test.go b/integration-cli/docker_cli_create_test.go index d47236590eb57..f5ea3c15e6ee8 100644 --- a/integration-cli/docker_cli_create_test.go +++ b/integration-cli/docker_cli_create_test.go @@ -11,8 +11,8 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" - "github.com/docker/docker/internal/test/fakecontext" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/testutil/fakecontext" "github.com/docker/go-connections/nat" "gotest.tools/assert" is "gotest.tools/assert/cmp" diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index e400c230884f5..dfe4285b5c4df 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -31,9 +31,9 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/mount" + testdaemon "github.com/docker/docker/testutil/daemon" "github.com/docker/go-units" "github.com/docker/libnetwork/iptables" "github.com/docker/libtrust" @@ -427,7 +427,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *testing.T) { s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64", "--default-gateway-v6=2001:db8:2::100") - out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest") + out, err := s.d.Cmd("run", "-d", "--name=ipv6test", "busybox:latest", "top") assert.NilError(c, err, "Could not run container: %s, %v", out, err) out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}", "ipv6test") @@ -454,7 +454,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *testing.T) { s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:1::/64") - out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox") + out, err := s.d.Cmd("run", "-d", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox", "top") assert.NilError(c, err, out) out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}", "ipv6test") @@ -469,7 +469,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6HostMode(c *testing.T) { deleteInterface(c, "docker0") s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64") - out, err := s.d.Cmd("run", "-itd", "--name=hostcnt", "--network=host", "busybox:latest") + out, err := s.d.Cmd("run", "-d", "--name=hostcnt", "--network=host", "busybox:latest", "top") assert.NilError(c, err, "Could not run container: %s, %v", out, err) out, err = s.d.Cmd("exec", "hostcnt", "ip", "-6", "addr", "show", "docker0") @@ -2703,7 +2703,7 @@ func (s *DockerDaemonSuite) TestExecWithUserAfterLiveRestore(c *testing.T) { testRequires(c, DaemonIsLinux) s.d.StartWithBusybox(c, "--live-restore") - out, err := s.d.Cmd("run", "-d", "--name=top", "busybox", "sh", "-c", "addgroup -S test && adduser -S -G test test -D -s /bin/sh && touch /adduser_end && top") + out, err := s.d.Cmd("run", "--init", "-d", "--name=top", "busybox", "sh", "-c", "addgroup -S test && adduser -S -G test test -D -s /bin/sh && touch /adduser_end && exec top") assert.NilError(c, err, "Output: %s", out) s.d.WaitRun("top") diff --git a/integration-cli/docker_cli_external_volume_driver_test.go b/integration-cli/docker_cli_external_volume_driver_test.go index 1a219abe3caed..35a5b0fd3532a 100644 --- a/integration-cli/docker_cli_external_volume_driver_test.go +++ b/integration-cli/docker_cli_external_volume_driver_test.go @@ -16,8 +16,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" "github.com/docker/docker/pkg/stringid" + testdaemon "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/volume" "gotest.tools/assert" ) diff --git a/integration-cli/docker_cli_info_test.go b/integration-cli/docker_cli_info_test.go index 410a00e1432fe..353601f5d2ec1 100644 --- a/integration-cli/docker_cli_info_test.go +++ b/integration-cli/docker_cli_info_test.go @@ -8,7 +8,7 @@ import ( "testing" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" + testdaemon "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" ) diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index babdedb2de19c..e4f9246abb673 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -18,9 +18,9 @@ import ( "github.com/docker/docker/api/types/versions/v1p20" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" + testdaemon "github.com/docker/docker/testutil/daemon" "github.com/docker/libnetwork/driverapi" remoteapi "github.com/docker/libnetwork/drivers/remote/api" "github.com/docker/libnetwork/ipamapi" @@ -956,7 +956,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *testing _, err := s.d.Cmd("network", "create", "-d", dnd, "--subnet", "1.1.1.0/24", "net1") assert.NilError(c, err) - _, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "foo", "--ip", "1.1.1.10", "busybox", "sh") + _, err = s.d.Cmd("run", "-d", "--net", "net1", "--name", "foo", "--ip", "1.1.1.10", "busybox", "top") assert.NilError(c, err) // Kill daemon and restart @@ -980,7 +980,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *testing setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did) // trying to reuse the same ip must succeed - _, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "bar", "--ip", "1.1.1.10", "busybox", "sh") + _, err = s.d.Cmd("run", "-d", "--net", "net1", "--name", "bar", "--ip", "1.1.1.10", "busybox", "top") assert.NilError(c, err) } diff --git a/integration-cli/docker_cli_plugins_test.go b/integration-cli/docker_cli_plugins_test.go index 2be4b320e1380..66b89c56ad1af 100644 --- a/integration-cli/docker_cli_plugins_test.go +++ b/integration-cli/docker_cli_plugins_test.go @@ -15,7 +15,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/daemon" - "github.com/docker/docker/internal/test/fixtures/plugin" + "github.com/docker/docker/testutil/fixtures/plugin" "gotest.tools/assert" ) diff --git a/integration-cli/docker_cli_registry_user_agent_test.go b/integration-cli/docker_cli_registry_user_agent_test.go index 2e5026905aef4..5a0be52664841 100644 --- a/integration-cli/docker_cli_registry_user_agent_test.go +++ b/integration-cli/docker_cli_registry_user_agent_test.go @@ -8,7 +8,7 @@ import ( "regexp" "testing" - "github.com/docker/docker/internal/test/registry" + "github.com/docker/docker/testutil/registry" "gotest.tools/assert" ) diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index b0473a435e80c..c08c47669f64b 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -26,12 +26,12 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/testutil" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/fakecontext" "github.com/docker/go-connections/nat" "github.com/docker/libnetwork/resolvconf" "github.com/docker/libnetwork/types" diff --git a/integration-cli/docker_cli_service_create_test.go b/integration-cli/docker_cli_service_create_test.go index d9ca41b2cbfd6..a5c92c94113bc 100644 --- a/integration-cli/docker_cli_service_create_test.go +++ b/integration-cli/docker_cli_service_create_test.go @@ -362,7 +362,7 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigReferencedTwice(c *testing func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *testing.T) { d := s.AddDaemon(c, true, true) - out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--mount", "type=tmpfs,target=/foo,tmpfs-size=1MB", "busybox", "sh", "-c", "mount | grep foo; tail -f /dev/null") + out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--mount", "type=tmpfs,target=/foo,tmpfs-size=1MB", "busybox", "sh", "-c", "mount | grep foo; exec tail -f /dev/null") assert.NilError(c, err, out) id := strings.TrimSpace(out) diff --git a/integration-cli/docker_cli_service_logs_test.go b/integration-cli/docker_cli_service_logs_test.go index 86683539782af..72f3dbf6ebbb7 100644 --- a/integration-cli/docker_cli_service_logs_test.go +++ b/integration-cli/docker_cli_service_logs_test.go @@ -34,7 +34,7 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *testing.T) { for name, message := range services { out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", - "sh", "-c", fmt.Sprintf("echo %s; tail -f /dev/null", message)) + "sh", "-c", fmt.Sprintf("echo %s; exec tail -f /dev/null", message)) assert.NilError(c, err) assert.Assert(c, strings.TrimSpace(out) != "") } @@ -75,7 +75,7 @@ func (s *DockerSwarmSuite) TestServiceLogsCompleteness(c *testing.T) { name := "TestServiceLogsCompleteness" // make a service that prints 6 lines - out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "for line in $(seq 0 5); do echo log test $line; done; sleep 100000") + out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "for line in $(seq 0 5); do echo log test $line; done; exec tail /dev/null") assert.NilError(c, err) assert.Assert(c, strings.TrimSpace(out) != "") @@ -126,7 +126,7 @@ func (s *DockerSwarmSuite) TestServiceLogsSince(c *testing.T) { name := "TestServiceLogsSince" - out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "for i in $(seq 1 3); do sleep .1; echo log$i; done; sleep 10000000") + out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "for i in $(seq 1 3); do usleep 100000; echo log$i; done; exec tail /dev/null") assert.NilError(c, err) assert.Assert(c, strings.TrimSpace(out) != "") poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -160,7 +160,7 @@ func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) { name := "TestServiceLogsFollow" - out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "while true; do echo log test; sleep 0.1; done") + out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "busybox", "sh", "-c", "trap 'exit 0' TERM; while true; do echo log test; usleep 100000; done") assert.NilError(c, err) assert.Assert(c, strings.TrimSpace(out) != "") @@ -215,7 +215,7 @@ func (s *DockerSwarmSuite) TestServiceLogsTaskLogs(c *testing.T) { // which has this the task id as an environment variable templated in "--env", "TASK={{.Task.ID}}", // and runs this command to print exactly 6 logs lines - "busybox", "sh", "-c", "for line in $(seq 0 5); do echo $TASK log test $line; done; sleep 100000", + "busybox", "sh", "-c", "trap 'exit 0' TERM; for line in $(seq 0 5); do echo $TASK log test $line; done; sleep 100000", )) result.Assert(c, icmd.Expected{}) // ^^ verify that we get no error @@ -323,9 +323,7 @@ func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *testing.T) { result = icmd.RunCmd(d.Command("ps", "-q")) containerID := strings.TrimSpace(result.Stdout()) assert.Assert(c, containerID != "") - result = icmd.RunCmd(d.Command("stop", containerID)) - result.Assert(c, icmd.Expected{Out: containerID}) - result = icmd.RunCmd(d.Command("rm", containerID)) + result = icmd.RunCmd(d.Command("rm", "-f", containerID)) result.Assert(c, icmd.Expected{Out: containerID}) // run logs. use tail 2 to make sure we don't try to get a bunch of logs @@ -360,7 +358,7 @@ func (s *DockerSwarmSuite) TestServiceLogsDetails(c *testing.T) { // busybox image, shell string "busybox", "sh", "-c", // make a log line - "echo LogLine; while true; do sleep 1; done;", + "trap 'exit 0' TERM; echo LogLine; while true; do sleep 1; done;", )) result.Assert(c, icmd.Expected{}) diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go index 17dd4b06a4222..95d02b7f5317c 100644 --- a/integration-cli/docker_cli_update_unix_test.go +++ b/integration-cli/docker_cli_update_unix_test.go @@ -14,8 +14,8 @@ import ( "github.com/creack/pty" "github.com/docker/docker/api/types" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test/request" "github.com/docker/docker/pkg/parsers/kernel" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_cli_userns_test.go b/integration-cli/docker_cli_userns_test.go index b3b68c17c6c48..f61ed27448dab 100644 --- a/integration-cli/docker_cli_userns_test.go +++ b/integration-cli/docker_cli_userns_test.go @@ -46,7 +46,7 @@ func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *testing.T) { // writable by the remapped root UID/GID pair assert.NilError(c, os.Chown(tmpDir, uid, gid)) - out, err := s.d.Cmd("run", "-d", "--name", "userns", "-v", tmpDir+":/goofy", "-v", tmpDirNotExists+":/donald", "busybox", "sh", "-c", "touch /goofy/testfile; top") + out, err := s.d.Cmd("run", "-d", "--name", "userns", "-v", tmpDir+":/goofy", "-v", tmpDirNotExists+":/donald", "busybox", "sh", "-c", "touch /goofy/testfile; exec top") assert.NilError(c, err, "Output: %s", out) user := s.findUser(c, "userns") @@ -79,7 +79,7 @@ func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *testing.T) { assert.Equal(c, stat.GID(), uint32(gid), "Touched file not owned by remapped root GID") // use host usernamespace - out, err = s.d.Cmd("run", "-d", "--name", "userns_skip", "--userns", "host", "busybox", "sh", "-c", "touch /goofy/testfile; top") + out, err = s.d.Cmd("run", "-d", "--name", "userns_skip", "--userns", "host", "busybox", "sh", "-c", "touch /goofy/testfile; exec top") assert.Assert(c, err == nil, "Output: %s", out) user = s.findUser(c, "userns_skip") // userns are skipped, user is root diff --git a/integration-cli/docker_cli_v2_only_test.go b/integration-cli/docker_cli_v2_only_test.go index 299ea5079d042..f985a360f9309 100644 --- a/integration-cli/docker_cli_v2_only_test.go +++ b/integration-cli/docker_cli_v2_only_test.go @@ -7,7 +7,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/registry" + "github.com/docker/docker/testutil/registry" "gotest.tools/assert" ) diff --git a/integration-cli/docker_deprecated_api_v124_test.go b/integration-cli/docker_deprecated_api_v124_test.go index b11e3644fa1e1..f448b8a02a2a9 100644 --- a/integration-cli/docker_deprecated_api_v124_test.go +++ b/integration-cli/docker_deprecated_api_v124_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/integration-cli/docker_deprecated_api_v124_unix_test.go b/integration-cli/docker_deprecated_api_v124_unix_test.go index 06959ebf08062..7e0c0e50ec69a 100644 --- a/integration-cli/docker_deprecated_api_v124_unix_test.go +++ b/integration-cli/docker_deprecated_api_v124_unix_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" ) diff --git a/integration-cli/docker_hub_pull_suite_test.go b/integration-cli/docker_hub_pull_suite_test.go index 476ae17364460..971d20808d3f2 100644 --- a/integration-cli/docker_hub_pull_suite_test.go +++ b/integration-cli/docker_hub_pull_suite_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/docker/docker/integration-cli/daemon" - testdaemon "github.com/docker/docker/internal/test/daemon" + testdaemon "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" ) diff --git a/integration-cli/environment/environment.go b/integration-cli/environment/environment.go index 82cf99652bc8c..0dcf8d929476b 100644 --- a/integration-cli/environment/environment.go +++ b/integration-cli/environment/environment.go @@ -4,7 +4,7 @@ import ( "os" "os/exec" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var ( diff --git a/integration-cli/fixtures_linux_daemon_test.go b/integration-cli/fixtures_linux_daemon_test.go index de401b9dbc142..2f38f3bae7c91 100644 --- a/integration-cli/fixtures_linux_daemon_test.go +++ b/integration-cli/fixtures_linux_daemon_test.go @@ -10,7 +10,7 @@ import ( "strings" "testing" - "github.com/docker/docker/internal/test/fixtures/load" + "github.com/docker/docker/testutil/fixtures/load" "gotest.tools/assert" ) diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go index e469b1bb2b6b7..c7d913d51b35b 100644 --- a/integration-cli/requirements_test.go +++ b/integration-cli/requirements_test.go @@ -16,7 +16,7 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/requirement" - "github.com/docker/docker/internal/test/registry" + "github.com/docker/docker/testutil/registry" ) func ArchitectureIsNot(arch string) bool { diff --git a/integration-cli/utils_test.go b/integration-cli/utils_test.go index 9746f6c873a7e..145857fcf6625 100644 --- a/integration-cli/utils_test.go +++ b/integration-cli/utils_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/docker/docker/internal/testutil" + "github.com/docker/docker/testutil" "github.com/pkg/errors" "gotest.tools/icmd" ) diff --git a/integration/build/build_session_test.go b/integration/build/build_session_test.go index 578ea2102c8bc..ed89bae2bcaf6 100644 --- a/integration/build/build_session_test.go +++ b/integration/build/build_session_test.go @@ -11,8 +11,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" dclient "github.com/docker/docker/client" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/fakecontext" + "github.com/docker/docker/testutil/request" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/filesync" "golang.org/x/sync/errgroup" diff --git a/integration/build/build_squash_test.go b/integration/build/build_squash_test.go index 788589d612cd4..2d7ad911b3ef2 100644 --- a/integration/build/build_squash_test.go +++ b/integration/build/build_squash_test.go @@ -11,9 +11,9 @@ import ( "github.com/docker/docker/api/types" dclient "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/fakecontext" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/fakecontext" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/build/build_test.go b/integration/build/build_test.go index e5f17fe4ad8fd..9f50bd78b0db6 100644 --- a/integration/build/build_test.go +++ b/integration/build/build_test.go @@ -14,8 +14,8 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/errdefs" - "github.com/docker/docker/internal/test/fakecontext" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil/fakecontext" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/build/main_test.go b/integration/build/main_test.go index fef3909fd5666..735f2a49a6a7a 100644 --- a/integration/build/main_test.go +++ b/integration/build/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/config/config_test.go b/integration/config/config_test.go index ec5b060cd2367..a189fe7f84db4 100644 --- a/integration/config/config_test.go +++ b/integration/config/config_test.go @@ -15,8 +15,8 @@ import ( swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/swarm" - "github.com/docker/docker/internal/test/daemon" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/config/main_test.go b/integration/config/main_test.go index 3c8f0483f2372..dc5c8e834d257 100644 --- a/integration/config/main_test.go +++ b/integration/config/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/container/checkpoint_test.go b/integration/container/checkpoint_test.go index 7f7c74e8ccf3a..726fe672c67cf 100644 --- a/integration/container/checkpoint_test.go +++ b/integration/container/checkpoint_test.go @@ -13,7 +13,7 @@ import ( mounttypes "github.com/docker/docker/api/types/mount" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/container_test.go b/integration/container/container_test.go index a4ae31e948451..7365d142e2ddf 100644 --- a/integration/container/container_test.go +++ b/integration/container/container_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/integration/container/copy_test.go b/integration/container/copy_test.go index 0b6123a80b5bf..229fe0a908be5 100644 --- a/integration/container/copy_test.go +++ b/integration/container/copy_test.go @@ -13,8 +13,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/fakecontext" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil/fakecontext" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/container/create_test.go b/integration/container/create_test.go index b4bd23bce8754..7be1cb6eacc72 100644 --- a/integration/container/create_test.go +++ b/integration/container/create_test.go @@ -15,8 +15,8 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/errdefs" ctr "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" "github.com/docker/docker/oci" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/daemon_linux_test.go b/integration/container/daemon_linux_test.go index 32788375a2c07..39f056fabe545 100644 --- a/integration/container/daemon_linux_test.go +++ b/integration/container/daemon_linux_test.go @@ -10,7 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "golang.org/x/sys/unix" "gotest.tools/assert" is "gotest.tools/assert/cmp" diff --git a/integration/container/export_test.go b/integration/container/export_test.go index 98b52456a844a..9058eda8a16f8 100644 --- a/integration/container/export_test.go +++ b/integration/container/export_test.go @@ -9,8 +9,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/inspect_test.go b/integration/container/inspect_test.go index b86508514b458..9c01fba511311 100644 --- a/integration/container/inspect_test.go +++ b/integration/container/inspect_test.go @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/ipcmode_linux_test.go b/integration/container/ipcmode_linux_test.go index 2cb5f9b7100d4..1a4160b374e93 100644 --- a/integration/container/ipcmode_linux_test.go +++ b/integration/container/ipcmode_linux_test.go @@ -14,8 +14,8 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/fs" diff --git a/integration/container/kill_test.go b/integration/container/kill_test.go index b2c98a8a959c7..a2c8f3c6ff81c 100644 --- a/integration/container/kill_test.go +++ b/integration/container/kill_test.go @@ -7,7 +7,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/main_test.go b/integration/container/main_test.go index fb87fddcc260f..bb7b2eb02f5da 100644 --- a/integration/container/main_test.go +++ b/integration/container/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/container/pause_test.go b/integration/container/pause_test.go index 5e91ee3bada05..22a9b568bf071 100644 --- a/integration/container/pause_test.go +++ b/integration/container/pause_test.go @@ -11,7 +11,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/resize_test.go b/integration/container/resize_test.go index 27b5be4c70eb4..2d18a19869dd2 100644 --- a/integration/container/resize_test.go +++ b/integration/container/resize_test.go @@ -9,7 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/integration/internal/container" - req "github.com/docker/docker/internal/test/request" + req "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/restart_test.go b/integration/container/restart_test.go index 3da30c0f3a3b4..7ba120f14cb0f 100644 --- a/integration/container/restart_test.go +++ b/integration/container/restart_test.go @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/container/update_linux_test.go b/integration/container/update_linux_test.go index 3a72aba560e62..426d00950dee7 100644 --- a/integration/container/update_linux_test.go +++ b/integration/container/update_linux_test.go @@ -10,7 +10,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/container/wait_test.go b/integration/container/wait_test.go index 53787d6c69643..57d83d7525f8f 100644 --- a/integration/container/wait_test.go +++ b/integration/container/wait_test.go @@ -6,7 +6,7 @@ import ( "time" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" diff --git a/integration/image/import_test.go b/integration/image/import_test.go index bce55de0cf820..c2b953ae2554f 100644 --- a/integration/image/import_test.go +++ b/integration/image/import_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/testutil" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/image/main_test.go b/integration/image/main_test.go index 1b4270dfc64b7..893e2fdf5dca9 100644 --- a/integration/image/main_test.go +++ b/integration/image/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/image/remove_unix_test.go b/integration/image/remove_unix_test.go new file mode 100644 index 0000000000000..4dbd2eab9409a --- /dev/null +++ b/integration/image/remove_unix_test.go @@ -0,0 +1,93 @@ +// +build !windows + +package image // import "github.com/docker/docker/integration/image" + +import ( + "context" + "io" + "io/ioutil" + "os" + "strconv" + "strings" + "syscall" + "testing" + "unsafe" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/fakecontext" + "gotest.tools/assert" + "gotest.tools/skip" +) + +// This is a regression test for #38488 +// It ensures that orphan layers can be found and cleaned up +// after unsuccessful image removal +func TestRemoveImageGarbageCollector(t *testing.T) { + // This test uses very platform specific way to prevent + // daemon for remove image layer. + skip.If(t, testEnv.DaemonInfo.OSType != "linux") + skip.If(t, os.Getenv("DOCKER_ENGINE_GOARCH") != "amd64") + + // Create daemon with overlay2 graphdriver because vfs uses disk differently + // and this test case would not work with it. + d := daemon.New(t, daemon.WithStorageDriver("overlay2"), daemon.WithImageService) + d.Start(t) + defer d.Stop(t) + + ctx := context.Background() + client := d.NewClientT(t) + i := d.ImageService() + + img := "test-garbage-collector" + + // Build a image with multiple layers + dockerfile := `FROM busybox + RUN echo echo Running... > /run.sh` + source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) + defer source.Close() + resp, err := client.ImageBuild(ctx, + source.AsTarReader(t), + types.ImageBuildOptions{ + Remove: true, + ForceRemove: true, + Tags: []string{img}, + }) + assert.NilError(t, err) + _, err = io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + assert.NilError(t, err) + image, _, err := client.ImageInspectWithRaw(ctx, img) + assert.NilError(t, err) + + // Mark latest image layer to immutable + data := image.GraphDriver.Data + file, _ := os.Open(data["UpperDir"]) + attr := 0x00000010 + fsflags := uintptr(0x40086602) + argp := uintptr(unsafe.Pointer(&attr)) + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), fsflags, argp) + assert.Equal(t, "errno 0", errno.Error()) + + // Try to remove the image, it should generate error + // but marking layer back to mutable before checking errors (so we don't break CI server) + _, err = client.ImageRemove(ctx, img, types.ImageRemoveOptions{}) + attr = 0x00000000 + argp = uintptr(unsafe.Pointer(&attr)) + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, file.Fd(), fsflags, argp) + assert.Equal(t, "errno 0", errno.Error()) + assert.Assert(t, err != nil) + errStr := err.Error() + if !(strings.Contains(errStr, "permission denied") || strings.Contains(errStr, "operation not permitted")) { + t.Errorf("ImageRemove error not an permission error %s", errStr) + } + + // Verify that layer remaining on disk + dir, _ := os.Stat(data["UpperDir"]) + assert.Equal(t, "true", strconv.FormatBool(dir.IsDir())) + + // Run imageService.Cleanup() and make sure that layer was removed from disk + i.Cleanup() + dir, err = os.Stat(data["UpperDir"]) + assert.ErrorContains(t, err, "no such file or directory") +} diff --git a/integration/image/tag_test.go b/integration/image/tag_test.go index d237c480504f1..b2d28569aec2b 100644 --- a/integration/image/tag_test.go +++ b/integration/image/tag_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - "github.com/docker/docker/internal/testutil" + "github.com/docker/docker/testutil" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/internal/swarm/service.go b/integration/internal/swarm/service.go index c1f472c466779..61899d16b3c66 100644 --- a/integration/internal/swarm/service.go +++ b/integration/internal/swarm/service.go @@ -10,8 +10,8 @@ import ( "github.com/docker/docker/api/types/filters" swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/environment" "gotest.tools/assert" "gotest.tools/poll" "gotest.tools/skip" @@ -49,7 +49,7 @@ func ContainerPoll(config *poll.Settings) { } // NewSwarm creates a swarm daemon for testing -func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...func(*daemon.Daemon)) *daemon.Daemon { +func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...daemon.Option) *daemon.Daemon { t.Helper() skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows") diff --git a/integration/network/ipvlan/ipvlan_test.go b/integration/network/ipvlan/ipvlan_test.go index e8cfb14d6eff0..dd0420659706a 100644 --- a/integration/network/ipvlan/ipvlan_test.go +++ b/integration/network/ipvlan/ipvlan_test.go @@ -15,7 +15,7 @@ import ( "github.com/docker/docker/integration/internal/container" net "github.com/docker/docker/integration/internal/network" n "github.com/docker/docker/integration/network" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/network/ipvlan/main_test.go b/integration/network/ipvlan/main_test.go index 0936647959dc8..20d149bbaaba1 100644 --- a/integration/network/ipvlan/main_test.go +++ b/integration/network/ipvlan/main_test.go @@ -7,7 +7,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/network/macvlan/macvlan_test.go b/integration/network/macvlan/macvlan_test.go index b734cad82e8c8..f9d9e676d19fb 100644 --- a/integration/network/macvlan/macvlan_test.go +++ b/integration/network/macvlan/macvlan_test.go @@ -12,7 +12,7 @@ import ( "github.com/docker/docker/integration/internal/container" net "github.com/docker/docker/integration/internal/network" n "github.com/docker/docker/integration/network" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/network/macvlan/main_test.go b/integration/network/macvlan/main_test.go index 15bdc323b5ecf..85e48500c4fa4 100644 --- a/integration/network/macvlan/main_test.go +++ b/integration/network/macvlan/main_test.go @@ -7,7 +7,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/network/main_test.go b/integration/network/main_test.go index 36ed19ca67add..80354dcf0e61b 100644 --- a/integration/network/main_test.go +++ b/integration/network/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/network/network_test.go b/integration/network/network_test.go index b8c9cc43f8849..b0a3afa107aa5 100644 --- a/integration/network/network_test.go +++ b/integration/network/network_test.go @@ -10,8 +10,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/network/service_test.go b/integration/network/service_test.go index e6d417b0c91cd..cdfaba3321c75 100644 --- a/integration/network/service_test.go +++ b/integration/network/service_test.go @@ -11,7 +11,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/network" "github.com/docker/docker/integration/internal/swarm" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/icmd" "gotest.tools/poll" diff --git a/integration/plugin/authz/authz_plugin_test.go b/integration/plugin/authz/authz_plugin_test.go index 108cb837e8ab2..211bf9f6cc8c6 100644 --- a/integration/plugin/authz/authz_plugin_test.go +++ b/integration/plugin/authz/authz_plugin_test.go @@ -22,9 +22,9 @@ import ( eventtypes "github.com/docker/docker/api/types/events" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/environment" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/authorization" + "github.com/docker/docker/testutil/environment" "gotest.tools/assert" "gotest.tools/poll" "gotest.tools/skip" diff --git a/integration/plugin/authz/main_test.go b/integration/plugin/authz/main_test.go index 96c5901073f0f..6edf3260d45f7 100644 --- a/integration/plugin/authz/main_test.go +++ b/integration/plugin/authz/main_test.go @@ -12,10 +12,10 @@ import ( "strings" "testing" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/environment" "github.com/docker/docker/pkg/authorization" "github.com/docker/docker/pkg/plugins" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/environment" "gotest.tools/skip" ) diff --git a/integration/plugin/common/main_test.go b/integration/plugin/common/main_test.go index 47400129b6c2f..5bcbac2a8358a 100644 --- a/integration/plugin/common/main_test.go +++ b/integration/plugin/common/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/plugin/common/plugin_test.go b/integration/plugin/common/plugin_test.go index 5b6bfef76513a..6e2a5e9e90b89 100644 --- a/integration/plugin/common/plugin_test.go +++ b/integration/plugin/common/plugin_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/integration/plugin/graphdriver/external_test.go b/integration/plugin/graphdriver/external_test.go index c89f9961d152a..d72210be3efa1 100644 --- a/integration/plugin/graphdriver/external_test.go +++ b/integration/plugin/graphdriver/external_test.go @@ -19,9 +19,9 @@ import ( "github.com/docker/docker/daemon/graphdriver/vfs" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/integration/internal/requirement" - "github.com/docker/docker/internal/test/daemon" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/plugins" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/plugin/graphdriver/main_test.go b/integration/plugin/graphdriver/main_test.go index 6b6c1a12323aa..21dd9beba0ab0 100644 --- a/integration/plugin/graphdriver/main_test.go +++ b/integration/plugin/graphdriver/main_test.go @@ -5,8 +5,8 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" "github.com/docker/docker/pkg/reexec" + "github.com/docker/docker/testutil/environment" ) var ( diff --git a/integration/plugin/logging/helpers_test.go b/integration/plugin/logging/helpers_test.go index 128bf7d73b939..ec5ae422739b4 100644 --- a/integration/plugin/logging/helpers_test.go +++ b/integration/plugin/logging/helpers_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test/fixtures/plugin" "github.com/docker/docker/pkg/locker" + "github.com/docker/docker/testutil/fixtures/plugin" "github.com/pkg/errors" ) diff --git a/integration/plugin/logging/logging_linux_test.go b/integration/plugin/logging/logging_linux_test.go index 1bb2d9419ba35..3ee66fdc779fb 100644 --- a/integration/plugin/logging/logging_linux_test.go +++ b/integration/plugin/logging/logging_linux_test.go @@ -10,7 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/plugin/logging/main_test.go b/integration/plugin/logging/main_test.go index e1292a5718d80..40a41b9b2c0b0 100644 --- a/integration/plugin/logging/main_test.go +++ b/integration/plugin/logging/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var ( diff --git a/integration/plugin/logging/validation_test.go b/integration/plugin/logging/validation_test.go index dfa50132d20b0..07f8c21ce8f24 100644 --- a/integration/plugin/logging/validation_test.go +++ b/integration/plugin/logging/validation_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/plugin/volumes/helpers_test.go b/integration/plugin/volumes/helpers_test.go index 8d0b06bb9d3b3..1238ae62d5977 100644 --- a/integration/plugin/volumes/helpers_test.go +++ b/integration/plugin/volumes/helpers_test.go @@ -9,8 +9,8 @@ import ( "time" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test/fixtures/plugin" "github.com/docker/docker/pkg/locker" + "github.com/docker/docker/testutil/fixtures/plugin" "github.com/pkg/errors" "gotest.tools/assert" ) diff --git a/integration/plugin/volumes/main_test.go b/integration/plugin/volumes/main_test.go index 5a5678d9c4555..fe0a07938bd30 100644 --- a/integration/plugin/volumes/main_test.go +++ b/integration/plugin/volumes/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var ( diff --git a/integration/plugin/volumes/mounts_test.go b/integration/plugin/volumes/mounts_test.go index ab2d585ca77a0..e3165c22f2a77 100644 --- a/integration/plugin/volumes/mounts_test.go +++ b/integration/plugin/volumes/mounts_test.go @@ -7,8 +7,8 @@ import ( "testing" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/fixtures/plugin" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/fixtures/plugin" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/secret/main_test.go b/integration/secret/main_test.go index abd4eef9f0bde..a0cc4d889c50e 100644 --- a/integration/secret/main_test.go +++ b/integration/secret/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/service/create_test.go b/integration/service/create_test.go index 3e2baaf7cf9c1..40d8c3c27a77e 100644 --- a/integration/service/create_test.go +++ b/integration/service/create_test.go @@ -15,7 +15,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration/internal/network" "github.com/docker/docker/integration/internal/swarm" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/poll" @@ -30,7 +30,7 @@ func TestServiceCreateInit(t *testing.T) { func testServiceCreateInit(daemonEnabled bool) func(t *testing.T) { return func(t *testing.T) { - var ops = []func(*daemon.Daemon){} + var ops = []daemon.Option{} if daemonEnabled { ops = append(ops, daemon.WithInit) diff --git a/integration/service/main_test.go b/integration/service/main_test.go index 28fd19df4debf..939c5ac897065 100644 --- a/integration/service/main_test.go +++ b/integration/service/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/service/plugin_test.go b/integration/service/plugin_test.go index 16f0be567eadb..b7a95d9a51b41 100644 --- a/integration/service/plugin_test.go +++ b/integration/service/plugin_test.go @@ -12,9 +12,9 @@ import ( swarmtypes "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm/runtime" "github.com/docker/docker/integration/internal/swarm" - "github.com/docker/docker/internal/test/daemon" - "github.com/docker/docker/internal/test/fixtures/plugin" - "github.com/docker/docker/internal/test/registry" + "github.com/docker/docker/testutil/daemon" + "github.com/docker/docker/testutil/fixtures/plugin" + "github.com/docker/docker/testutil/registry" "gotest.tools/assert" "gotest.tools/poll" "gotest.tools/skip" diff --git a/integration/session/main_test.go b/integration/session/main_test.go index fc33025efe667..766bd512b3885 100644 --- a/integration/session/main_test.go +++ b/integration/session/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/session/session_test.go b/integration/session/session_test.go index 2f8d79c0e784f..3b16afb86b776 100644 --- a/integration/session/session_test.go +++ b/integration/session/session_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/docker/docker/api/types/versions" - req "github.com/docker/docker/internal/test/request" + req "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/system/cgroupdriver_systemd_test.go b/integration/system/cgroupdriver_systemd_test.go index b277ccaa08a54..1019532397e8a 100644 --- a/integration/system/cgroupdriver_systemd_test.go +++ b/integration/system/cgroupdriver_systemd_test.go @@ -7,7 +7,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" "gotest.tools/skip" diff --git a/integration/system/event_test.go b/integration/system/event_test.go index 61adeedc4b356..162dd80e1312b 100644 --- a/integration/system/event_test.go +++ b/integration/system/event_test.go @@ -15,9 +15,9 @@ import ( "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" - req "github.com/docker/docker/internal/test/request" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil/request" + req "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/system/info_linux_test.go b/integration/system/info_linux_test.go index cb0448e5581bf..434373b3695e3 100644 --- a/integration/system/info_linux_test.go +++ b/integration/system/info_linux_test.go @@ -7,7 +7,7 @@ import ( "net/http" "testing" - req "github.com/docker/docker/internal/test/request" + req "github.com/docker/docker/testutil/request" "gotest.tools/assert" is "gotest.tools/assert/cmp" ) diff --git a/integration/system/info_test.go b/integration/system/info_test.go index 813036198893d..56a735714e723 100644 --- a/integration/system/info_test.go +++ b/integration/system/info_test.go @@ -5,7 +5,7 @@ import ( "fmt" "testing" - "github.com/docker/docker/internal/test/daemon" + "github.com/docker/docker/testutil/daemon" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" diff --git a/integration/system/main_test.go b/integration/system/main_test.go index f19a3157aa393..6dd4761cd5f68 100644 --- a/integration/system/main_test.go +++ b/integration/system/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/system/ping_test.go b/integration/system/ping_test.go index 9858bfd9da387..2bbd7d2ad9ff6 100644 --- a/integration/system/ping_test.go +++ b/integration/system/ping_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "gotest.tools/assert" "gotest.tools/skip" ) diff --git a/integration/volume/main_test.go b/integration/volume/main_test.go index 206f7377ae06f..e3e99352078ce 100644 --- a/integration/volume/main_test.go +++ b/integration/volume/main_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/docker/docker/internal/test/environment" + "github.com/docker/docker/testutil/environment" ) var testEnv *environment.Execution diff --git a/integration/volume/volume_test.go b/integration/volume/volume_test.go index 0336b943bc698..e5f2fba398ebc 100644 --- a/integration/volume/volume_test.go +++ b/integration/volume/volume_test.go @@ -12,7 +12,7 @@ import ( "github.com/docker/docker/api/types/filters" volumetypes "github.com/docker/docker/api/types/volume" "github.com/docker/docker/integration/internal/container" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/testutil/request" "github.com/google/go-cmp/cmp/cmpopts" "gotest.tools/assert" is "gotest.tools/assert/cmp" diff --git a/layer/filestore.go b/layer/filestore.go index 208a0c3a859a4..a1726a5a404c4 100644 --- a/layer/filestore.go +++ b/layer/filestore.go @@ -14,7 +14,7 @@ import ( "github.com/docker/distribution" "github.com/docker/docker/pkg/ioutils" - "github.com/opencontainers/go-digest" + digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -305,6 +305,55 @@ func (fms *fileMetadataStore) GetMountParent(mount string) (ChainID, error) { return ChainID(dgst), nil } +func (fms *fileMetadataStore) getOrphan() ([]roLayer, error) { + var orphanLayers []roLayer + for _, algorithm := range supportedAlgorithms { + fileInfos, err := ioutil.ReadDir(filepath.Join(fms.root, string(algorithm))) + if err != nil { + if os.IsNotExist(err) { + continue + } + return nil, err + } + + for _, fi := range fileInfos { + if !fi.IsDir() || !strings.HasSuffix(fi.Name(), "-removing") { + continue + } + // At this stage, fi.Name value looks like --removing + // Split on '-' to get the digest value. + nameSplit := strings.Split(fi.Name(), "-") + dgst := digest.NewDigestFromEncoded(algorithm, nameSplit[0]) + if err := dgst.Validate(); err != nil { + logrus.WithError(err).WithField("digest", string(algorithm)+":"+nameSplit[0]).Debug("ignoring invalid digest") + continue + } + + chainFile := filepath.Join(fms.root, string(algorithm), fi.Name(), "cache-id") + contentBytes, err := ioutil.ReadFile(chainFile) + if err != nil { + if !os.IsNotExist(err) { + logrus.WithError(err).WithField("digest", dgst).Error("failed to read cache ID") + } + continue + } + cacheID := strings.TrimSpace(string(contentBytes)) + if cacheID == "" { + logrus.Error("invalid cache ID") + continue + } + + l := &roLayer{ + chainID: ChainID(dgst), + cacheID: cacheID, + } + orphanLayers = append(orphanLayers, *l) + } + } + + return orphanLayers, nil +} + func (fms *fileMetadataStore) List() ([]ChainID, []string, error) { var ids []ChainID for _, algorithm := range supportedAlgorithms { @@ -346,8 +395,39 @@ func (fms *fileMetadataStore) List() ([]ChainID, []string, error) { return ids, mounts, nil } -func (fms *fileMetadataStore) Remove(layer ChainID) error { - return os.RemoveAll(fms.getLayerDirectory(layer)) +// Remove layerdb folder if that is marked for removal +func (fms *fileMetadataStore) Remove(layer ChainID, cache string) error { + dgst := digest.Digest(layer) + files, err := ioutil.ReadDir(filepath.Join(fms.root, string(dgst.Algorithm()))) + if err != nil { + return err + } + for _, f := range files { + if !strings.HasSuffix(f.Name(), "-removing") || !strings.HasPrefix(f.Name(), dgst.String()) { + continue + } + + // Make sure that we only remove layerdb folder which points to + // requested cacheID + dir := filepath.Join(fms.root, string(dgst.Algorithm()), f.Name()) + chainFile := filepath.Join(dir, "cache-id") + contentBytes, err := ioutil.ReadFile(chainFile) + if err != nil { + logrus.WithError(err).WithField("file", chainFile).Error("cannot get cache ID") + continue + } + cacheID := strings.TrimSpace(string(contentBytes)) + if cacheID != cache { + continue + } + logrus.Debugf("Removing folder: %s", dir) + err = os.RemoveAll(dir) + if err != nil && !os.IsNotExist(err) { + logrus.WithError(err).WithField("name", f.Name()).Error("cannot remove layer") + continue + } + } + return nil } func (fms *fileMetadataStore) RemoveMount(mount string) error { diff --git a/layer/filestore_test.go b/layer/filestore_test.go index 498379e37fe2e..878dc54e3616e 100644 --- a/layer/filestore_test.go +++ b/layer/filestore_test.go @@ -10,6 +10,7 @@ import ( "syscall" "testing" + "github.com/docker/docker/pkg/stringid" "github.com/opencontainers/go-digest" ) @@ -102,3 +103,50 @@ func TestStartTransactionFailure(t *testing.T) { t.Fatal(err) } } + +func TestGetOrphan(t *testing.T) { + fms, td, cleanup := newFileMetadataStore(t) + defer cleanup() + + layerRoot := filepath.Join(td, "sha256") + if err := os.MkdirAll(layerRoot, 0755); err != nil { + t.Fatal(err) + } + + tx, err := fms.StartTransaction() + if err != nil { + t.Fatal(err) + } + + layerid := randomLayerID(5) + err = tx.Commit(layerid) + if err != nil { + t.Fatal(err) + } + layerPath := fms.getLayerDirectory(layerid) + if err := ioutil.WriteFile(filepath.Join(layerPath, "cache-id"), []byte(stringid.GenerateRandomID()), 0644); err != nil { + t.Fatal(err) + } + + orphanLayers, err := fms.getOrphan() + if err != nil { + t.Fatal(err) + } + if len(orphanLayers) != 0 { + t.Fatalf("Expected to have zero orphan layers") + } + + layeridSplit := strings.Split(layerid.String(), ":") + newPath := filepath.Join(layerRoot, fmt.Sprintf("%s-%s-removing", layeridSplit[1], stringid.GenerateRandomID())) + err = os.Rename(layerPath, newPath) + if err != nil { + t.Fatal(err) + } + orphanLayers, err = fms.getOrphan() + if err != nil { + t.Fatal(err) + } + if len(orphanLayers) != 1 { + t.Fatalf("Expected to have one orphan layer") + } +} diff --git a/layer/layer_store.go b/layer/layer_store.go index 81730e9d92116..7b8c011f4c07c 100644 --- a/layer/layer_store.go +++ b/layer/layer_store.go @@ -5,6 +5,8 @@ import ( "fmt" "io" "io/ioutil" + "os" + "path/filepath" "sync" "github.com/docker/distribution" @@ -415,11 +417,24 @@ func (ls *layerStore) Map() map[ChainID]Layer { } func (ls *layerStore) deleteLayer(layer *roLayer, metadata *Metadata) error { + // Rename layer digest folder first so we detect orphan layer(s) + // if ls.driver.Remove fails + dir := ls.store.getLayerDirectory(layer.chainID) + for { + dgst := digest.Digest(layer.chainID) + tmpID := fmt.Sprintf("%s-%s-removing", dgst.Hex(), stringid.GenerateRandomID()) + dir := filepath.Join(ls.store.root, string(dgst.Algorithm()), tmpID) + err := os.Rename(ls.store.getLayerDirectory(layer.chainID), dir) + if os.IsExist(err) { + continue + } + break + } err := ls.driver.Remove(layer.cacheID) if err != nil { return err } - err = ls.store.Remove(layer.chainID) + err = os.RemoveAll(dir) if err != nil { return err } @@ -452,12 +467,14 @@ func (ls *layerStore) releaseLayer(l *roLayer) ([]Metadata, error) { if l.hasReferences() { panic("cannot delete referenced layer") } + // Remove layer from layer map first so it is not considered to exist + // when if ls.deleteLayer fails. + delete(ls.layerMap, l.chainID) + var metadata Metadata if err := ls.deleteLayer(l, &metadata); err != nil { return nil, err } - - delete(ls.layerMap, l.chainID) removed = append(removed, metadata) if l.parent == nil { @@ -743,6 +760,23 @@ func (ls *layerStore) assembleTarTo(graphID string, metadata io.ReadCloser, size } func (ls *layerStore) Cleanup() error { + orphanLayers, err := ls.store.getOrphan() + if err != nil { + logrus.Errorf("Cannot get orphan layers: %v", err) + } + logrus.Debugf("found %v orphan layers", len(orphanLayers)) + for _, orphan := range orphanLayers { + logrus.Debugf("removing orphan layer, chain ID: %v , cache ID: %v", orphan.chainID, orphan.cacheID) + err = ls.driver.Remove(orphan.cacheID) + if err != nil && !os.IsNotExist(err) { + logrus.WithError(err).WithField("cache-id", orphan.cacheID).Error("cannot remove orphan layer") + continue + } + err = ls.store.Remove(orphan.chainID, orphan.cacheID) + if err != nil { + logrus.WithError(err).WithField("chain-id", orphan.chainID).Error("cannot remove orphan layer metadata") + } + } return ls.driver.Cleanup() } diff --git a/internal/test/daemon/config.go b/testutil/daemon/config.go similarity index 88% rename from internal/test/daemon/config.go rename to testutil/daemon/config.go index ce99222b37eac..4e09df1425eae 100644 --- a/internal/test/daemon/config.go +++ b/testutil/daemon/config.go @@ -5,7 +5,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) @@ -14,7 +14,7 @@ type ConfigConstructor func(*swarm.Config) // CreateConfig creates a config given the specified spec func (d *Daemon) CreateConfig(t assert.TestingT, configSpec swarm.ConfigSpec) string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -27,7 +27,7 @@ func (d *Daemon) CreateConfig(t assert.TestingT, configSpec swarm.ConfigSpec) st // ListConfigs returns the list of the current swarm configs func (d *Daemon) ListConfigs(t assert.TestingT) []swarm.Config { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -40,7 +40,7 @@ func (d *Daemon) ListConfigs(t assert.TestingT) []swarm.Config { // GetConfig returns a swarm config identified by the specified id func (d *Daemon) GetConfig(t assert.TestingT, id string) *swarm.Config { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -53,7 +53,7 @@ func (d *Daemon) GetConfig(t assert.TestingT, id string) *swarm.Config { // DeleteConfig removes the swarm config identified by the specified id func (d *Daemon) DeleteConfig(t assert.TestingT, id string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -66,7 +66,7 @@ func (d *Daemon) DeleteConfig(t assert.TestingT, id string) { // UpdateConfig updates the swarm config identified by the specified id // Currently, only label update is supported. func (d *Daemon) UpdateConfig(t assert.TestingT, id string, f ...ConfigConstructor) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) diff --git a/internal/test/daemon/container.go b/testutil/daemon/container.go similarity index 87% rename from internal/test/daemon/container.go rename to testutil/daemon/container.go index 3aa69e195cdc9..0abc52cc71e71 100644 --- a/internal/test/daemon/container.go +++ b/testutil/daemon/container.go @@ -4,13 +4,13 @@ import ( "context" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) // ActiveContainers returns the list of ids of the currently running containers func (d *Daemon) ActiveContainers(t assert.TestingT) []string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -28,7 +28,7 @@ func (d *Daemon) ActiveContainers(t assert.TestingT) []string { // FindContainerIP returns the ip of the specified container func (d *Daemon) FindContainerIP(t assert.TestingT, id string) string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) diff --git a/internal/test/daemon/daemon.go b/testutil/daemon/daemon.go similarity index 95% rename from internal/test/daemon/daemon.go rename to testutil/daemon/daemon.go index 7ad377347989c..dccfd7697d34c 100644 --- a/internal/test/daemon/daemon.go +++ b/testutil/daemon/daemon.go @@ -1,4 +1,4 @@ -package daemon // import "github.com/docker/docker/internal/test/daemon" +package daemon // import "github.com/docker/docker/testutil/daemon" import ( "context" @@ -16,11 +16,12 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/events" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test" - "github.com/docker/docker/internal/test/request" + "github.com/docker/docker/daemon/images" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/request" "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" "github.com/pkg/errors" @@ -77,6 +78,7 @@ type Daemon struct { init bool dockerdBinary string log logT + imageService *images.ImageService // swarm related field swarmListenAddr string @@ -91,8 +93,8 @@ type Daemon struct { // New returns a Daemon instance to be used for testing. // This will create a directory such as d123456789 in the folder specified by $DOCKER_INTEGRATION_DAEMON_DEST or $DEST. // The daemon will not automatically start. -func New(t testingT, ops ...func(*Daemon)) *Daemon { - if ht, ok := t.(test.HelperT); ok { +func New(t testingT, ops ...Option) *Daemon { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } dest := os.Getenv("DOCKER_INTEGRATION_DAEMON_DEST") @@ -188,7 +190,7 @@ func (d *Daemon) ReadLogFile() ([]byte, error) { // NewClientT creates new client based on daemon's socket path func (d *Daemon) NewClientT(t assert.TestingT) *client.Client { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } c, err := client.NewClientWithOpts( @@ -200,7 +202,7 @@ func (d *Daemon) NewClientT(t assert.TestingT) *client.Client { // Cleanup cleans the daemon files : exec root (network namespaces, ...), swarmkit files func (d *Daemon) Cleanup(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } // Cleanup swarmkit wal files if present @@ -210,7 +212,7 @@ func (d *Daemon) Cleanup(t testingT) { // Start starts the daemon and return once it is ready to receive requests. func (d *Daemon) Start(t testingT, args ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } if err := d.StartWithError(args...); err != nil { @@ -363,7 +365,7 @@ func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error { // StartWithBusybox will first start the daemon with Daemon.Start() // then save the busybox image from the main daemon and load it into this Daemon instance. func (d *Daemon) StartWithBusybox(t testingT, arg ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } d.Start(t, arg...) @@ -422,7 +424,7 @@ func (d *Daemon) DumpStackAndQuit() { // instantiate a new one with NewDaemon. // If an error occurs while starting the daemon, the test will fail. func (d *Daemon) Stop(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } err := d.StopWithError() @@ -510,7 +512,7 @@ out2: // Restart will restart the daemon by first stopping it and the starting it. // If an error occurs while starting the daemon, the test will fail. func (d *Daemon) Restart(t testingT, args ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } d.Stop(t) @@ -586,7 +588,7 @@ func (d *Daemon) ReloadConfig() error { // LoadBusybox image into the daemon func (d *Daemon) LoadBusybox(t assert.TestingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } clientHost, err := client.NewClientWithOpts(client.FromEnv) @@ -700,7 +702,7 @@ func (d *Daemon) queryRootDir() (string, error) { // Info returns the info struct for this daemon func (d *Daemon) Info(t assert.TestingT) types.Info { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } c := d.NewClientT(t) @@ -710,7 +712,7 @@ func (d *Daemon) Info(t assert.TestingT) types.Info { } func cleanupRaftDir(t testingT, rootPath string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } for _, p := range []string{"wal", "wal-v3-encrypted", "snap-v3-encrypted"} { @@ -720,3 +722,8 @@ func cleanupRaftDir(t testingT, rootPath string) { } } } + +// ImageService returns the Daemon's ImageService +func (d *Daemon) ImageService() *images.ImageService { + return d.imageService +} diff --git a/internal/test/daemon/daemon_unix.go b/testutil/daemon/daemon_unix.go similarity index 85% rename from internal/test/daemon/daemon_unix.go rename to testutil/daemon/daemon_unix.go index eb604fec75cac..cd473d1243243 100644 --- a/internal/test/daemon/daemon_unix.go +++ b/testutil/daemon/daemon_unix.go @@ -1,17 +1,17 @@ // +build !windows -package daemon // import "github.com/docker/docker/internal/test/daemon" +package daemon // import "github.com/docker/docker/testutil/daemon" import ( "os" "path/filepath" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "golang.org/x/sys/unix" ) func cleanupNetworkNamespace(t testingT, execRoot string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } // Cleanup network namespaces in the exec root of this diff --git a/internal/test/daemon/daemon_windows.go b/testutil/daemon/daemon_windows.go similarity index 87% rename from internal/test/daemon/daemon_windows.go rename to testutil/daemon/daemon_windows.go index cb6bb6a4cb16c..7eee2d5fff4df 100644 --- a/internal/test/daemon/daemon_windows.go +++ b/testutil/daemon/daemon_windows.go @@ -1,4 +1,4 @@ -package daemon // import "github.com/docker/docker/internal/test/daemon" +package daemon import ( "fmt" diff --git a/testutil/daemon/doc.go b/testutil/daemon/doc.go new file mode 100644 index 0000000000000..add30e3cfb4a4 --- /dev/null +++ b/testutil/daemon/doc.go @@ -0,0 +1,2 @@ +// Package daemon launches dockerd for testing purposes. +package daemon // import "github.com/docker/docker/testutil/daemon" diff --git a/internal/test/daemon/node.go b/testutil/daemon/node.go similarity index 90% rename from internal/test/daemon/node.go rename to testutil/daemon/node.go index d5f6f15263fa4..45ff2b52070ea 100644 --- a/internal/test/daemon/node.go +++ b/testutil/daemon/node.go @@ -7,7 +7,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) @@ -16,7 +16,7 @@ type NodeConstructor func(*swarm.Node) // GetNode returns a swarm node identified by the specified id func (d *Daemon) GetNode(t assert.TestingT, id string, errCheck ...func(error) bool) *swarm.Node { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -37,7 +37,7 @@ func (d *Daemon) GetNode(t assert.TestingT, id string, errCheck ...func(error) b // RemoveNode removes the specified node func (d *Daemon) RemoveNode(t assert.TestingT, id string, force bool) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -52,7 +52,7 @@ func (d *Daemon) RemoveNode(t assert.TestingT, id string, force bool) { // UpdateNode updates a swarm node with the specified node constructor func (d *Daemon) UpdateNode(t assert.TestingT, id string, f ...NodeConstructor) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -76,7 +76,7 @@ func (d *Daemon) UpdateNode(t assert.TestingT, id string, f ...NodeConstructor) // ListNodes returns the list of the current swarm nodes func (d *Daemon) ListNodes(t assert.TestingT) []swarm.Node { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) diff --git a/internal/test/daemon/ops.go b/testutil/daemon/ops.go similarity index 61% rename from internal/test/daemon/ops.go rename to testutil/daemon/ops.go index ff8cd88946f9c..fde82a0a02c45 100644 --- a/internal/test/daemon/ops.go +++ b/testutil/daemon/ops.go @@ -1,6 +1,9 @@ package daemon -import "github.com/docker/docker/internal/test/environment" +import "github.com/docker/docker/testutil/environment" + +// Option is used to configure a daemon. +type Option func(*Daemon) // WithExperimental sets the daemon in experimental mode func WithExperimental(d *Daemon) { @@ -14,52 +17,59 @@ func WithInit(d *Daemon) { } // WithDockerdBinary sets the dockerd binary to the specified one -func WithDockerdBinary(dockerdBinary string) func(*Daemon) { +func WithDockerdBinary(dockerdBinary string) Option { return func(d *Daemon) { d.dockerdBinary = dockerdBinary } } // WithSwarmPort sets the swarm port to use for swarm mode -func WithSwarmPort(port int) func(*Daemon) { +func WithSwarmPort(port int) Option { return func(d *Daemon) { d.SwarmPort = port } } // WithSwarmListenAddr sets the swarm listen addr to use for swarm mode -func WithSwarmListenAddr(listenAddr string) func(*Daemon) { +func WithSwarmListenAddr(listenAddr string) Option { return func(d *Daemon) { d.swarmListenAddr = listenAddr } } // WithSwarmDefaultAddrPool sets the swarm default address pool to use for swarm mode -func WithSwarmDefaultAddrPool(defaultAddrPool []string) func(*Daemon) { +func WithSwarmDefaultAddrPool(defaultAddrPool []string) Option { return func(d *Daemon) { d.DefaultAddrPool = defaultAddrPool } } // WithSwarmDefaultAddrPoolSubnetSize sets the subnet length mask of swarm default address pool to use for swarm mode -func WithSwarmDefaultAddrPoolSubnetSize(subnetSize uint32) func(*Daemon) { +func WithSwarmDefaultAddrPoolSubnetSize(subnetSize uint32) Option { return func(d *Daemon) { d.SubnetSize = subnetSize } } // WithSwarmDataPathPort sets the swarm datapath port to use for swarm mode -func WithSwarmDataPathPort(datapathPort uint32) func(*Daemon) { +func WithSwarmDataPathPort(datapathPort uint32) Option { return func(d *Daemon) { d.DataPathPort = datapathPort } } -// WithEnvironment sets options from internal/test/environment.Execution struct -func WithEnvironment(e environment.Execution) func(*Daemon) { +// WithEnvironment sets options from testutil/environment.Execution struct +func WithEnvironment(e environment.Execution) Option { return func(d *Daemon) { if e.DaemonInfo.ExperimentalBuild { d.experimental = true } } } + +// WithStorageDriver sets store driver option +func WithStorageDriver(driver string) func(d *Daemon) { + return func(d *Daemon) { + d.storageDriver = driver + } +} diff --git a/testutil/daemon/ops_unix.go b/testutil/daemon/ops_unix.go new file mode 100644 index 0000000000000..41011e87c5c09 --- /dev/null +++ b/testutil/daemon/ops_unix.go @@ -0,0 +1,34 @@ +// +build !windows + +package daemon + +import ( + "path/filepath" + "runtime" + + "github.com/docker/docker/daemon/images" + "github.com/docker/docker/layer" + + // register graph drivers + _ "github.com/docker/docker/daemon/graphdriver/register" + "github.com/docker/docker/pkg/idtools" +) + +// WithImageService sets imageService options +func WithImageService(d *Daemon) { + layerStores := make(map[string]layer.Store) + os := runtime.GOOS + layerStores[os], _ = layer.NewStoreFromOptions(layer.StoreOptions{ + Root: d.Root, + MetadataStorePathTemplate: filepath.Join(d.RootDir(), "image", "%s", "layerdb"), + GraphDriver: d.storageDriver, + GraphDriverOptions: nil, + IDMapping: &idtools.IdentityMapping{}, + PluginGetter: nil, + ExperimentalEnabled: false, + OS: os, + }) + d.imageService = images.NewImageService(images.ImageServiceConfig{ + LayerStores: layerStores, + }) +} diff --git a/internal/test/daemon/plugin.go b/testutil/daemon/plugin.go similarity index 100% rename from internal/test/daemon/plugin.go rename to testutil/daemon/plugin.go diff --git a/internal/test/daemon/secret.go b/testutil/daemon/secret.go similarity index 88% rename from internal/test/daemon/secret.go rename to testutil/daemon/secret.go index f3db7a42601da..dedbf3df349af 100644 --- a/internal/test/daemon/secret.go +++ b/testutil/daemon/secret.go @@ -5,7 +5,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) @@ -14,7 +14,7 @@ type SecretConstructor func(*swarm.Secret) // CreateSecret creates a secret given the specified spec func (d *Daemon) CreateSecret(t assert.TestingT, secretSpec swarm.SecretSpec) string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -28,7 +28,7 @@ func (d *Daemon) CreateSecret(t assert.TestingT, secretSpec swarm.SecretSpec) st // ListSecrets returns the list of the current swarm secrets func (d *Daemon) ListSecrets(t assert.TestingT) []swarm.Secret { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -41,7 +41,7 @@ func (d *Daemon) ListSecrets(t assert.TestingT) []swarm.Secret { // GetSecret returns a swarm secret identified by the specified id func (d *Daemon) GetSecret(t assert.TestingT, id string) *swarm.Secret { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -54,7 +54,7 @@ func (d *Daemon) GetSecret(t assert.TestingT, id string) *swarm.Secret { // DeleteSecret removes the swarm secret identified by the specified id func (d *Daemon) DeleteSecret(t assert.TestingT, id string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -67,7 +67,7 @@ func (d *Daemon) DeleteSecret(t assert.TestingT, id string) { // UpdateSecret updates the swarm secret identified by the specified id // Currently, only label update is supported. func (d *Daemon) UpdateSecret(t assert.TestingT, id string, f ...SecretConstructor) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) diff --git a/internal/test/daemon/service.go b/testutil/daemon/service.go similarity index 89% rename from internal/test/daemon/service.go rename to testutil/daemon/service.go index 0f88ca786b32d..a46705d2918d6 100644 --- a/internal/test/daemon/service.go +++ b/testutil/daemon/service.go @@ -7,7 +7,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) @@ -15,7 +15,7 @@ import ( type ServiceConstructor func(*swarm.Service) func (d *Daemon) createServiceWithOptions(t assert.TestingT, opts types.ServiceCreateOptions, f ...ServiceConstructor) string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } var service swarm.Service @@ -36,7 +36,7 @@ func (d *Daemon) createServiceWithOptions(t assert.TestingT, opts types.ServiceC // CreateService creates a swarm service given the specified service constructor func (d *Daemon) CreateService(t assert.TestingT, f ...ServiceConstructor) string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } return d.createServiceWithOptions(t, types.ServiceCreateOptions{}, f...) @@ -44,7 +44,7 @@ func (d *Daemon) CreateService(t assert.TestingT, f ...ServiceConstructor) strin // GetService returns the swarm service corresponding to the specified id func (d *Daemon) GetService(t assert.TestingT, id string) *swarm.Service { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -57,7 +57,7 @@ func (d *Daemon) GetService(t assert.TestingT, id string) *swarm.Service { // GetServiceTasks returns the swarm tasks for the specified service func (d *Daemon) GetServiceTasks(t assert.TestingT, service string) []swarm.Task { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -78,7 +78,7 @@ func (d *Daemon) GetServiceTasks(t assert.TestingT, service string) []swarm.Task // UpdateService updates a swarm service with the specified service constructor func (d *Daemon) UpdateService(t assert.TestingT, service *swarm.Service, f ...ServiceConstructor) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -94,7 +94,7 @@ func (d *Daemon) UpdateService(t assert.TestingT, service *swarm.Service, f ...S // RemoveService removes the specified service func (d *Daemon) RemoveService(t assert.TestingT, id string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -106,7 +106,7 @@ func (d *Daemon) RemoveService(t assert.TestingT, id string) { // ListServices returns the list of the current swarm services func (d *Daemon) ListServices(t assert.TestingT) []swarm.Service { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -119,7 +119,7 @@ func (d *Daemon) ListServices(t assert.TestingT) []swarm.Service { // GetTask returns the swarm task identified by the specified id func (d *Daemon) GetTask(t assert.TestingT, id string) swarm.Task { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) diff --git a/internal/test/daemon/swarm.go b/testutil/daemon/swarm.go similarity index 91% rename from internal/test/daemon/swarm.go rename to testutil/daemon/swarm.go index 20300a1f4a5a4..1bb30e23ae14f 100644 --- a/internal/test/daemon/swarm.go +++ b/testutil/daemon/swarm.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "github.com/pkg/errors" "gotest.tools/assert" ) @@ -22,7 +22,7 @@ var ( // StartNode (re)starts the daemon func (d *Daemon) StartNode(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } d.Start(t, startArgs...) @@ -30,7 +30,7 @@ func (d *Daemon) StartNode(t testingT) { // StartNodeWithBusybox starts daemon to be used as a swarm node, and loads the busybox image func (d *Daemon) StartNodeWithBusybox(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } d.StartWithBusybox(t, startArgs...) @@ -38,7 +38,7 @@ func (d *Daemon) StartNodeWithBusybox(t testingT) { // RestartNode restarts a daemon to be used as a swarm node func (d *Daemon) RestartNode(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } // avoid networking conflicts @@ -54,7 +54,7 @@ func (d *Daemon) StartAndSwarmInit(t testingT) { // StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager func (d *Daemon) StartAndSwarmJoin(t testingT, leader *Daemon, manager bool) { - if th, ok := t.(test.HelperT); ok { + if th, ok := t.(testutil.HelperT); ok { th.Helper() } d.StartNodeWithBusybox(t) @@ -86,7 +86,7 @@ func (d *Daemon) NodeID() string { // SwarmInit initializes a new swarm cluster. func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } if req.ListenAddr == "" { @@ -108,7 +108,7 @@ func (d *Daemon) SwarmInit(t assert.TestingT, req swarm.InitRequest) { // SwarmJoin joins a daemon to an existing cluster. func (d *Daemon) SwarmJoin(t assert.TestingT, req swarm.JoinRequest) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } if req.ListenAddr == "" { @@ -134,7 +134,7 @@ func (d *Daemon) SwarmLeave(t assert.TestingT, force bool) error { // SwarmInfo returns the swarm information of the daemon func (d *Daemon) SwarmInfo(t assert.TestingT) swarm.Info { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -161,7 +161,7 @@ func (d *Daemon) SwarmUnlock(t assert.TestingT, req swarm.UnlockRequest) error { // GetSwarm returns the current swarm object func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -174,7 +174,7 @@ func (d *Daemon) GetSwarm(t assert.TestingT) swarm.Swarm { // UpdateSwarm updates the current swarm object with the specified spec constructors func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -191,7 +191,7 @@ func (d *Daemon) UpdateSwarm(t assert.TestingT, f ...SpecConstructor) { // RotateTokens update the swarm to rotate tokens func (d *Daemon) RotateTokens(t assert.TestingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) @@ -211,7 +211,7 @@ func (d *Daemon) RotateTokens(t assert.TestingT) { // JoinTokens returns the current swarm join tokens func (d *Daemon) JoinTokens(t assert.TestingT) swarm.JoinTokens { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } cli := d.NewClientT(t) diff --git a/testutil/doc.go b/testutil/doc.go new file mode 100644 index 0000000000000..1bf03ef3ff274 --- /dev/null +++ b/testutil/doc.go @@ -0,0 +1,2 @@ +// Package testutil contains common testing tasks like running dockerd. +package testutil // import "github.com/docker/docker/testutil" diff --git a/internal/test/environment/clean.go b/testutil/environment/clean.go similarity index 91% rename from internal/test/environment/clean.go rename to testutil/environment/clean.go index ad6ec93e4ab0a..f3677697a70cd 100644 --- a/internal/test/environment/clean.go +++ b/testutil/environment/clean.go @@ -1,4 +1,4 @@ -package environment // import "github.com/docker/docker/internal/test/environment" +package environment // import "github.com/docker/docker/testutil/environment" import ( "context" @@ -8,7 +8,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) @@ -16,7 +16,7 @@ import ( // and removing everything else. It's meant to run after any tests so that they don't // depend on each others. func (e *Execution) Clean(t assert.TestingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := e.APIClient() @@ -35,7 +35,7 @@ func (e *Execution) Clean(t assert.TestingT) { } func unpauseAllContainers(t assert.TestingT, client client.ContainerAPIClient) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } ctx := context.Background() @@ -49,7 +49,7 @@ func unpauseAllContainers(t assert.TestingT, client client.ContainerAPIClient) { } func getPausedContainers(ctx context.Context, t assert.TestingT, client client.ContainerAPIClient) []types.Container { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } filter := filters.NewArgs() @@ -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, protectedContainers map[string]struct{}) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } ctx := context.Background() @@ -91,7 +91,7 @@ func deleteAllContainers(t assert.TestingT, apiclient client.ContainerAPIClient, } func getAllContainers(ctx context.Context, t assert.TestingT, client client.ContainerAPIClient) []types.Container { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } containers, err := client.ContainerList(ctx, types.ContainerListOptions{ @@ -103,7 +103,7 @@ func getAllContainers(ctx context.Context, t assert.TestingT, client client.Cont } func deleteAllImages(t assert.TestingT, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{}) @@ -125,7 +125,7 @@ func deleteAllImages(t assert.TestingT, apiclient client.ImageAPIClient, protect } func removeImage(ctx context.Context, t assert.TestingT, apiclient client.ImageAPIClient, ref string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } _, err := apiclient.ImageRemove(ctx, ref, types.ImageRemoveOptions{ @@ -138,7 +138,7 @@ func removeImage(ctx context.Context, t assert.TestingT, apiclient client.ImageA } func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } volumes, err := c.VolumeList(context.Background(), filters.Args{}) @@ -158,7 +158,7 @@ func deleteAllVolumes(t assert.TestingT, c client.VolumeAPIClient, protectedVolu } func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) @@ -181,7 +181,7 @@ func deleteAllNetworks(t assert.TestingT, c client.NetworkAPIClient, daemonPlatf } func deleteAllPlugins(t assert.TestingT, c client.PluginAPIClient, protectedPlugins map[string]struct{}) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } plugins, err := c.PluginList(context.Background(), filters.Args{}) diff --git a/internal/test/environment/environment.go b/testutil/environment/environment.go similarity index 90% rename from internal/test/environment/environment.go rename to testutil/environment/environment.go index 9bec84483f78d..61f165e509989 100644 --- a/internal/test/environment/environment.go +++ b/testutil/environment/environment.go @@ -1,4 +1,4 @@ -package environment // import "github.com/docker/docker/internal/test/environment" +package environment // import "github.com/docker/docker/testutil/environment" import ( "context" @@ -10,8 +10,8 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test" - "github.com/docker/docker/internal/test/fixtures/load" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/fixtures/load" "github.com/pkg/errors" "gotest.tools/assert" ) @@ -34,13 +34,18 @@ type PlatformDefaults struct { } // New creates a new Execution struct +// This is configured useing the env client (see client.FromEnv) func New() (*Execution, error) { - client, err := client.NewClientWithOpts(client.FromEnv) + c, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return nil, errors.Wrapf(err, "failed to create client") } + return FromClient(c) +} - info, err := client.Info(context.Background()) +// FromClient creates a new Execution environment from the passed in client +func FromClient(c *client.Client) (*Execution, error) { + info, err := c.Info(context.Background()) if err != nil { return nil, errors.Wrapf(err, "failed to get info from daemon") } @@ -48,7 +53,7 @@ func New() (*Execution, error) { osType := getOSType(info) return &Execution{ - client: client, + client: c, DaemonInfo: info, OSType: osType, PlatformDefaults: getPlatformDefaults(info, osType), @@ -161,7 +166,7 @@ func (e *Execution) IsUserNamespace() bool { // Note that this is done by filtering and then checking whether there were any // results -- so ambiguous references might result in false-positives. func (e *Execution) HasExistingImage(t assert.TestingT, reference string) bool { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := e.APIClient() diff --git a/internal/test/environment/protect.go b/testutil/environment/protect.go similarity index 89% rename from internal/test/environment/protect.go rename to testutil/environment/protect.go index a47ea3c2fd846..9fda6f5aa0b33 100644 --- a/internal/test/environment/protect.go +++ b/testutil/environment/protect.go @@ -1,4 +1,4 @@ -package environment // import "github.com/docker/docker/internal/test/environment" +package environment import ( "context" @@ -6,7 +6,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" dclient "github.com/docker/docker/client" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) @@ -34,7 +34,7 @@ func newProtectedElements() protectedElements { // volumes, and, on Linux, plugins) from being cleaned up at the end of test // runs func ProtectAll(t assert.TestingT, testEnv *Execution) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } ProtectContainers(t, testEnv) @@ -49,7 +49,7 @@ func ProtectAll(t assert.TestingT, testEnv *Execution) { // ProtectContainer adds the specified container(s) to be protected in case of // clean func (e *Execution) ProtectContainer(t assert.TestingT, containers ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } for _, container := range containers { @@ -60,7 +60,7 @@ func (e *Execution) ProtectContainer(t assert.TestingT, containers ...string) { // ProtectContainers protects existing containers from being cleaned up at the // end of test runs func ProtectContainers(t assert.TestingT, testEnv *Execution) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } containers := getExistingContainers(t, testEnv) @@ -68,7 +68,7 @@ func ProtectContainers(t assert.TestingT, testEnv *Execution) { } func getExistingContainers(t assert.TestingT, testEnv *Execution) []string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := testEnv.APIClient() @@ -86,7 +86,7 @@ func getExistingContainers(t assert.TestingT, testEnv *Execution) []string { // ProtectImage adds the specified image(s) to be protected in case of clean func (e *Execution) ProtectImage(t assert.TestingT, images ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } for _, image := range images { @@ -97,7 +97,7 @@ func (e *Execution) ProtectImage(t assert.TestingT, images ...string) { // ProtectImages protects existing images and on linux frozen images from being // cleaned up at the end of test runs func ProtectImages(t assert.TestingT, testEnv *Execution) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } images := getExistingImages(t, testEnv) @@ -109,7 +109,7 @@ func ProtectImages(t assert.TestingT, testEnv *Execution) { } func getExistingImages(t assert.TestingT, testEnv *Execution) []string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := testEnv.APIClient() @@ -146,7 +146,7 @@ func tagsFromImageSummary(image types.ImageSummary) []string { // ProtectNetwork adds the specified network(s) to be protected in case of // clean func (e *Execution) ProtectNetwork(t assert.TestingT, networks ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } for _, network := range networks { @@ -157,7 +157,7 @@ func (e *Execution) ProtectNetwork(t assert.TestingT, networks ...string) { // ProtectNetworks protects existing networks from being cleaned up at the end // of test runs func ProtectNetworks(t assert.TestingT, testEnv *Execution) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } networks := getExistingNetworks(t, testEnv) @@ -165,7 +165,7 @@ func ProtectNetworks(t assert.TestingT, testEnv *Execution) { } func getExistingNetworks(t assert.TestingT, testEnv *Execution) []string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := testEnv.APIClient() @@ -181,7 +181,7 @@ func getExistingNetworks(t assert.TestingT, testEnv *Execution) []string { // ProtectPlugin adds the specified plugin(s) to be protected in case of clean func (e *Execution) ProtectPlugin(t assert.TestingT, plugins ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } for _, plugin := range plugins { @@ -192,7 +192,7 @@ func (e *Execution) ProtectPlugin(t assert.TestingT, plugins ...string) { // ProtectPlugins protects existing plugins from being cleaned up at the end of // test runs func ProtectPlugins(t assert.TestingT, testEnv *Execution) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } plugins := getExistingPlugins(t, testEnv) @@ -200,7 +200,7 @@ func ProtectPlugins(t assert.TestingT, testEnv *Execution) { } func getExistingPlugins(t assert.TestingT, testEnv *Execution) []string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := testEnv.APIClient() @@ -220,7 +220,7 @@ func getExistingPlugins(t assert.TestingT, testEnv *Execution) []string { // ProtectVolume adds the specified volume(s) to be protected in case of clean func (e *Execution) ProtectVolume(t assert.TestingT, volumes ...string) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } for _, volume := range volumes { @@ -231,7 +231,7 @@ func (e *Execution) ProtectVolume(t assert.TestingT, volumes ...string) { // ProtectVolumes protects existing volumes from being cleaned up at the end of // test runs func ProtectVolumes(t assert.TestingT, testEnv *Execution) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } volumes := getExistingVolumes(t, testEnv) @@ -239,7 +239,7 @@ func ProtectVolumes(t assert.TestingT, testEnv *Execution) { } func getExistingVolumes(t assert.TestingT, testEnv *Execution) []string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } client := testEnv.APIClient() diff --git a/internal/test/fakecontext/context.go b/testutil/fakecontext/context.go similarity index 93% rename from internal/test/fakecontext/context.go rename to testutil/fakecontext/context.go index 8b11da207ed05..88eda5448682c 100644 --- a/internal/test/fakecontext/context.go +++ b/testutil/fakecontext/context.go @@ -1,4 +1,4 @@ -package fakecontext // import "github.com/docker/docker/internal/test/fakecontext" +package fakecontext // import "github.com/docker/docker/testutil/fakecontext" import ( "bytes" @@ -7,8 +7,8 @@ import ( "os" "path/filepath" - "github.com/docker/docker/internal/test" "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/testutil" ) type testingT interface { @@ -18,7 +18,7 @@ type testingT interface { // New creates a fake build context func New(t testingT, dir string, modifiers ...func(*Fake) error) *Fake { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } fakeContext := &Fake{Dir: dir} @@ -120,7 +120,7 @@ func (f *Fake) Close() error { // AsTarReader returns a ReadCloser with the contents of Dir as a tar archive. func (f *Fake) AsTarReader(t testingT) io.ReadCloser { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } reader, err := archive.TarWithOptions(f.Dir, &archive.TarOptions{}) diff --git a/internal/test/fakegit/fakegit.go b/testutil/fakegit/fakegit.go similarity index 92% rename from internal/test/fakegit/fakegit.go rename to testutil/fakegit/fakegit.go index 30de769743a75..dde0127c60f76 100644 --- a/internal/test/fakegit/fakegit.go +++ b/testutil/fakegit/fakegit.go @@ -1,4 +1,4 @@ -package fakegit // import "github.com/docker/docker/internal/test/fakegit" +package fakegit // import "github.com/docker/docker/testutil/fakegit" import ( "fmt" @@ -9,9 +9,9 @@ import ( "os/exec" "path/filepath" - "github.com/docker/docker/internal/test" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/test/fakestorage" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/fakecontext" + "github.com/docker/docker/testutil/fakestorage" "gotest.tools/assert" ) @@ -64,7 +64,7 @@ func (g *FakeGit) Close() { // New create a fake git server that can be used for git related tests func New(c testingT, name string, files map[string]string, enforceLocalServer bool) *FakeGit { - if ht, ok := c.(test.HelperT); ok { + if ht, ok := c.(testutil.HelperT); ok { ht.Helper() } ctx := fakecontext.New(c, "", fakecontext.WithFiles(files)) diff --git a/internal/test/fakestorage/fixtures.go b/testutil/fakestorage/fixtures.go similarity index 93% rename from internal/test/fakestorage/fixtures.go rename to testutil/fakestorage/fixtures.go index ad8f76314338a..fa1f0081fc323 100644 --- a/internal/test/fakestorage/fixtures.go +++ b/testutil/fakestorage/fixtures.go @@ -1,4 +1,4 @@ -package fakestorage // import "github.com/docker/docker/internal/test/fakestorage" +package fakestorage // import "github.com/docker/docker/testutil/fakestorage" import ( "context" @@ -10,15 +10,15 @@ import ( "sync" "github.com/docker/docker/api/types" - "github.com/docker/docker/internal/test" "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/testutil" "gotest.tools/assert" ) var ensureHTTPServerOnce sync.Once func ensureHTTPServerImage(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } var doIt bool diff --git a/internal/test/fakestorage/storage.go b/testutil/fakestorage/storage.go similarity index 93% rename from internal/test/fakestorage/storage.go rename to testutil/fakestorage/storage.go index e229fd0813284..4175908b8587f 100644 --- a/internal/test/fakestorage/storage.go +++ b/testutil/fakestorage/storage.go @@ -1,4 +1,4 @@ -package fakestorage // import "github.com/docker/docker/internal/test/fakestorage" +package fakestorage // import "github.com/docker/docker/testutil/fakestorage" import ( "context" @@ -14,11 +14,10 @@ import ( "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test" - "github.com/docker/docker/internal/test/environment" - "github.com/docker/docker/internal/test/fakecontext" - "github.com/docker/docker/internal/test/request" - "github.com/docker/docker/internal/testutil" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/environment" + "github.com/docker/docker/testutil/fakecontext" + "github.com/docker/docker/testutil/request" "github.com/docker/go-connections/nat" "gotest.tools/assert" ) @@ -57,7 +56,7 @@ func SetTestEnvironment(env *environment.Execution) { // New returns a static file server that will be use as build context. func New(t testingT, dir string, modifiers ...func(*fakecontext.Fake) error) Fake { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } if testEnv == nil { diff --git a/internal/test/fixtures/load/frozen.go b/testutil/fixtures/load/frozen.go similarity index 98% rename from internal/test/fixtures/load/frozen.go rename to testutil/fixtures/load/frozen.go index 94f3680f954d3..4e8589e44239a 100644 --- a/internal/test/fixtures/load/frozen.go +++ b/testutil/fixtures/load/frozen.go @@ -1,4 +1,4 @@ -package load // import "github.com/docker/docker/internal/test/fixtures/load" +package load // import "github.com/docker/docker/testutil/fixtures/load" import ( "bufio" diff --git a/internal/test/fixtures/plugin/basic/basic.go b/testutil/fixtures/plugin/basic/basic.go similarity index 100% rename from internal/test/fixtures/plugin/basic/basic.go rename to testutil/fixtures/plugin/basic/basic.go diff --git a/internal/test/fixtures/plugin/plugin.go b/testutil/fixtures/plugin/plugin.go similarity index 97% rename from internal/test/fixtures/plugin/plugin.go rename to testutil/fixtures/plugin/plugin.go index 93f5f99fed3de..8517b37afbdfd 100644 --- a/internal/test/fixtures/plugin/plugin.go +++ b/testutil/fixtures/plugin/plugin.go @@ -1,4 +1,4 @@ -package plugin // import "github.com/docker/docker/internal/test/fixtures/plugin" +package plugin // import "github.com/docker/docker/testutil/fixtures/plugin" import ( "context" @@ -206,7 +206,7 @@ func ensureBasicPluginBin() (string, error) { return "", err } installPath := filepath.Join(os.Getenv("GOPATH"), "bin", name) - sourcePath := filepath.Join("github.com", "docker", "docker", "internal", "test", "fixtures", "plugin", "basic") + sourcePath := filepath.Join("github.com", "docker", "docker", "testutil", "fixtures", "plugin", "basic") cmd := exec.Command(goBin, "build", "-o", installPath, sourcePath) cmd.Env = append(os.Environ(), "CGO_ENABLED=0") if out, err := cmd.CombinedOutput(); err != nil { diff --git a/internal/test/helper.go b/testutil/helper.go similarity index 86% rename from internal/test/helper.go rename to testutil/helper.go index 1b9fd75090eb0..a8a70e4dfbbfa 100644 --- a/internal/test/helper.go +++ b/testutil/helper.go @@ -1,4 +1,4 @@ -package test +package testutil // HelperT is a subset of testing.T that implements the Helper function type HelperT interface { diff --git a/internal/testutil/helpers.go b/testutil/helpers.go similarity index 77% rename from internal/testutil/helpers.go rename to testutil/helpers.go index 38cd1693f5f2c..e522b5a9a4ecc 100644 --- a/internal/testutil/helpers.go +++ b/testutil/helpers.go @@ -1,4 +1,4 @@ -package testutil // import "github.com/docker/docker/internal/testutil" +package testutil // import "github.com/docker/docker/testutil" import ( "io" diff --git a/internal/test/registry/ops.go b/testutil/registry/ops.go similarity index 100% rename from internal/test/registry/ops.go rename to testutil/registry/ops.go diff --git a/internal/test/registry/registry.go b/testutil/registry/registry.go similarity index 95% rename from internal/test/registry/registry.go rename to testutil/registry/registry.go index b6128d3ba4d3c..59af456a70b50 100644 --- a/internal/test/registry/registry.go +++ b/testutil/registry/registry.go @@ -1,4 +1,4 @@ -package registry // import "github.com/docker/docker/internal/test/registry" +package registry // import "github.com/docker/docker/testutil/registry" import ( "fmt" @@ -9,7 +9,7 @@ import ( "path/filepath" "time" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" "github.com/opencontainers/go-digest" "gotest.tools/assert" ) @@ -55,7 +55,7 @@ type Config struct { // NewV2 creates a v2 registry server func NewV2(t testingT, ops ...func(*Config)) *V2 { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } c := &Config{ @@ -139,7 +139,7 @@ http: // WaitReady waits for the registry to be ready to serve requests (or fail after a while) func (r *V2) WaitReady(t testingT) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } var err error @@ -190,7 +190,7 @@ func (r *V2) getBlobFilename(blobDigest digest.Digest) string { // ReadBlobContents read the file corresponding to the specified digest func (r *V2) ReadBlobContents(t assert.TestingT, blobDigest digest.Digest) []byte { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } // Load the target manifest blob. @@ -201,7 +201,7 @@ func (r *V2) ReadBlobContents(t assert.TestingT, blobDigest digest.Digest) []byt // WriteBlobContents write the file corresponding to the specified digest with the given content func (r *V2) WriteBlobContents(t assert.TestingT, blobDigest digest.Digest, data []byte) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } err := ioutil.WriteFile(r.getBlobFilename(blobDigest), data, os.FileMode(0644)) @@ -211,7 +211,7 @@ func (r *V2) WriteBlobContents(t assert.TestingT, blobDigest digest.Digest, data // TempMoveBlobData moves the existing data file aside, so that we can replace it with a // malicious blob of data for example. func (r *V2) TempMoveBlobData(t testingT, blobDigest digest.Digest) (undo func()) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } tempFile, err := ioutil.TempFile("", "registry-temp-blob-") diff --git a/internal/test/registry/registry_mock.go b/testutil/registry/registry_mock.go similarity index 89% rename from internal/test/registry/registry_mock.go rename to testutil/registry/registry_mock.go index d139401a62036..cb0498a8abbb1 100644 --- a/internal/test/registry/registry_mock.go +++ b/testutil/registry/registry_mock.go @@ -1,4 +1,4 @@ -package registry // import "github.com/docker/docker/internal/test/registry" +package registry // import "github.com/docker/docker/testutil/registry" import ( "net/http" @@ -7,7 +7,7 @@ import ( "strings" "sync" - "github.com/docker/docker/internal/test" + "github.com/docker/docker/testutil" ) type handlerFunc func(w http.ResponseWriter, r *http.Request) @@ -29,7 +29,7 @@ func (tr *Mock) RegisterHandler(path string, h handlerFunc) { // NewMock creates a registry mock func NewMock(t testingT) (*Mock, error) { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } testReg := &Mock{handlers: make(map[string]handlerFunc)} diff --git a/internal/test/request/npipe.go b/testutil/request/npipe.go similarity index 100% rename from internal/test/request/npipe.go rename to testutil/request/npipe.go diff --git a/internal/test/request/npipe_windows.go b/testutil/request/npipe_windows.go similarity index 100% rename from internal/test/request/npipe_windows.go rename to testutil/request/npipe_windows.go diff --git a/internal/test/request/ops.go b/testutil/request/ops.go similarity index 100% rename from internal/test/request/ops.go rename to testutil/request/ops.go diff --git a/internal/test/request/request.go b/testutil/request/request.go similarity index 95% rename from internal/test/request/request.go rename to testutil/request/request.go index 6bf70c74379cd..5ee2c73c75a50 100644 --- a/internal/test/request/request.go +++ b/testutil/request/request.go @@ -1,4 +1,4 @@ -package request // import "github.com/docker/docker/internal/test/request" +package request // import "github.com/docker/docker/testutil/request" import ( "context" @@ -14,10 +14,10 @@ import ( "time" "github.com/docker/docker/client" - "github.com/docker/docker/internal/test" - "github.com/docker/docker/internal/test/environment" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/ioutils" + "github.com/docker/docker/testutil" + "github.com/docker/docker/testutil/environment" "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" "github.com/pkg/errors" @@ -26,7 +26,7 @@ import ( // NewAPIClient returns a docker API client configured from environment variables func NewAPIClient(t assert.TestingT, ops ...client.Opt) client.APIClient { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } ops = append([]client.Opt{client.FromEnv}, ops...) @@ -37,7 +37,7 @@ func NewAPIClient(t assert.TestingT, ops ...client.Opt) client.APIClient { // DaemonTime provides the current time on the daemon host func DaemonTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) time.Time { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } if testEnv.IsLocalDaemon() { @@ -55,7 +55,7 @@ func DaemonTime(ctx context.Context, t assert.TestingT, client client.APIClient, // DaemonUnixTime returns the current time on the daemon host with nanoseconds precision. // It return the time formatted how the client sends timestamps to the server. func DaemonUnixTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) string { - if ht, ok := t.(test.HelperT); ok { + if ht, ok := t.(testutil.HelperT); ok { ht.Helper() } dt := DaemonTime(ctx, t, client, testEnv) diff --git a/internal/testutil/stringutils.go b/testutil/stringutils.go similarity index 83% rename from internal/testutil/stringutils.go rename to testutil/stringutils.go index 574aeb51f2a82..62092faa36a7c 100644 --- a/internal/testutil/stringutils.go +++ b/testutil/stringutils.go @@ -1,4 +1,4 @@ -package testutil // import "github.com/docker/docker/internal/testutil" +package testutil // import "github.com/docker/docker/testutil" import "math/rand" diff --git a/internal/testutil/stringutils_test.go b/testutil/stringutils_test.go similarity index 91% rename from internal/testutil/stringutils_test.go rename to testutil/stringutils_test.go index 753aac966dc2e..ee95997768144 100644 --- a/internal/testutil/stringutils_test.go +++ b/testutil/stringutils_test.go @@ -1,4 +1,4 @@ -package testutil // import "github.com/docker/docker/internal/testutil" +package testutil // import "github.com/docker/docker/testutil" import ( "testing"