diff --git a/Makefile b/Makefile index 50edcd8eba..8ffdf4221c 100644 --- a/Makefile +++ b/Makefile @@ -75,7 +75,10 @@ DOCKER_ENVS := \ -e PLATFORM \ -e DEFAULT_PRODUCT_LICENSE \ -e PRODUCT \ - -e PACKAGER_NAME + -e PACKAGER_NAME \ + -e OTEL_EXPORTER_OTLP_ENDPOINT \ + -e OTEL_EXPORTER_OTLP_PROTOCOL \ + -e OTEL_SERVICE_NAME # note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds # to allow `make BIND_DIR=. shell` or `make BIND_DIR= test` diff --git a/hack/make/.integration-test-helpers b/hack/make/.integration-test-helpers index 8dfae12957..8af00197f5 100644 --- a/hack/make/.integration-test-helpers +++ b/hack/make/.integration-test-helpers @@ -197,6 +197,8 @@ test_env() { TEMP="$TEMP" \ TEST_CLIENT_BINARY="$TEST_CLIENT_BINARY" \ TEST_INTEGRATION_USE_SNAPSHOTTER="$TEST_INTEGRATION_USE_SNAPSHOTTER" \ + OTEL_EXPORTER_OTLP_ENDPOINT="$OTEL_EXPORTER_OTLP_ENDPOINT" \ + OTEL_SERVICE_NAME="$OTEL_SERVICE_NAME" \ "$@" ) } diff --git a/integration-cli/benchmark_test.go b/integration-cli/benchmark_test.go index ae93cf30de..1f9fc2abcb 100644 --- a/integration-cli/benchmark_test.go +++ b/integration-cli/benchmark_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "os" "runtime" @@ -16,8 +17,8 @@ type DockerBenchmarkSuite struct { ds *DockerSuite } -func (s *DockerBenchmarkSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerBenchmarkSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerBenchmarkSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index af321bf07c..9148f6e37d 100644 --- a/integration-cli/check_test.go +++ b/integration-cli/check_test.go @@ -18,11 +18,15 @@ import ( "github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/integration-cli/environment" "github.com/docker/docker/internal/test/suite" + "github.com/docker/docker/testutil" 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" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" "gotest.tools/v3/assert" ) @@ -38,37 +42,64 @@ const ( ) var ( - testEnv *environment.Execution + testEnvOnce sync.Once + testEnv *environment.Execution // the docker client binary to use dockerBinary = "" - testEnvOnce sync.Once + baseContext context.Context ) -func init() { - var err error - - testEnv, err = environment.New() - if err != nil { - panic(err) - } -} - func TestMain(m *testing.M) { flag.Parse() + os.Exit(testRun(m)) +} + +func testRun(m *testing.M) (ret int) { // Global set up - dockerBinary = testEnv.DockerBinary() - err := ienv.EnsureFrozenImagesLinux(&testEnv.Execution) + + var err error + + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration-cli/TestMain") + defer func() { + if err != nil { + span.SetStatus(codes.Error, err.Error()) + ret = 255 + } else { + if ret != 0 { + span.SetAttributes(attribute.Int("exitCode", ret)) + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + } + span.End() + shutdown(ctx) + }() + + baseContext = ctx + + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + return + } + + if testEnv.IsLocalDaemon() { + setupLocalInfo() + } + + dockerBinary = testEnv.DockerBinary() + + err = ienv.EnsureFrozenImagesLinux(ctx, &testEnv.Execution) + if err != nil { + return } testEnv.Print() printCliVersion() - os.Exit(m.Run()) + + return m.Run() } func printCliVersion() { @@ -84,262 +115,311 @@ func printCliVersion() { fmt.Println(cmd.Stdout()) } -func ensureTestEnvSetup(t *testing.T) { +func ensureTestEnvSetup(ctx context.Context, t *testing.T) { testEnvOnce.Do(func() { cli.SetTestEnvironment(testEnv) fakestorage.SetTestEnvironment(&testEnv.Execution) - ienv.ProtectAll(t, &testEnv.Execution) + ienv.ProtectAll(ctx, t, &testEnv.Execution) }) } func TestDockerAPISuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerAPISuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerAPISuite{ds: &DockerSuite{}}) } func TestDockerBenchmarkSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerBenchmarkSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerBenchmarkSuite{ds: &DockerSuite{}}) } func TestDockerCLIAttachSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIAttachSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIAttachSuite{ds: &DockerSuite{}}) } func TestDockerCLIBuildSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIBuildSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIBuildSuite{ds: &DockerSuite{}}) } func TestDockerCLICommitSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLICommitSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLICommitSuite{ds: &DockerSuite{}}) } func TestDockerCLICpSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLICpSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLICpSuite{ds: &DockerSuite{}}) } func TestDockerCLICreateSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLICreateSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLICreateSuite{ds: &DockerSuite{}}) } func TestDockerCLIEventSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIEventSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIEventSuite{ds: &DockerSuite{}}) } func TestDockerCLIExecSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIExecSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIExecSuite{ds: &DockerSuite{}}) } func TestDockerCLIHealthSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIHealthSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIHealthSuite{ds: &DockerSuite{}}) } func TestDockerCLIHistorySuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIHistorySuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIHistorySuite{ds: &DockerSuite{}}) } func TestDockerCLIImagesSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIImagesSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIImagesSuite{ds: &DockerSuite{}}) } func TestDockerCLIImportSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIImportSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIImportSuite{ds: &DockerSuite{}}) } func TestDockerCLIInfoSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIInfoSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIInfoSuite{ds: &DockerSuite{}}) } func TestDockerCLIInspectSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIInspectSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIInspectSuite{ds: &DockerSuite{}}) } func TestDockerCLILinksSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLILinksSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLILinksSuite{ds: &DockerSuite{}}) } func TestDockerCLILoginSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLILoginSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLILoginSuite{ds: &DockerSuite{}}) } func TestDockerCLILogsSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLILogsSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLILogsSuite{ds: &DockerSuite{}}) } func TestDockerCLINetmodeSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLINetmodeSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLINetmodeSuite{ds: &DockerSuite{}}) } func TestDockerCLINetworkSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLINetworkSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLINetworkSuite{ds: &DockerSuite{}}) } func TestDockerCLIPluginLogDriverSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPluginLogDriverSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPluginLogDriverSuite{ds: &DockerSuite{}}) } func TestDockerCLIPluginsSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPluginsSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPluginsSuite{ds: &DockerSuite{}}) } func TestDockerCLIPortSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPortSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPortSuite{ds: &DockerSuite{}}) } func TestDockerCLIProxySuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIProxySuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIProxySuite{ds: &DockerSuite{}}) } func TestDockerCLIPruneSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPruneSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPruneSuite{ds: &DockerSuite{}}) } func TestDockerCLIPsSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPsSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPsSuite{ds: &DockerSuite{}}) } func TestDockerCLIPullSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPullSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPullSuite{ds: &DockerSuite{}}) } func TestDockerCLIPushSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIPushSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIPushSuite{ds: &DockerSuite{}}) } func TestDockerCLIRestartSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIRestartSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIRestartSuite{ds: &DockerSuite{}}) } func TestDockerCLIRmiSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIRmiSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIRmiSuite{ds: &DockerSuite{}}) } func TestDockerCLIRunSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIRunSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIRunSuite{ds: &DockerSuite{}}) } func TestDockerCLISaveLoadSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLISaveLoadSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLISaveLoadSuite{ds: &DockerSuite{}}) } func TestDockerCLISearchSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLISearchSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLISearchSuite{ds: &DockerSuite{}}) } func TestDockerCLISNISuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLISNISuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLISNISuite{ds: &DockerSuite{}}) } func TestDockerCLIStartSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIStartSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIStartSuite{ds: &DockerSuite{}}) } func TestDockerCLIStatsSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIStatsSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIStatsSuite{ds: &DockerSuite{}}) } func TestDockerCLITopSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLITopSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLITopSuite{ds: &DockerSuite{}}) } func TestDockerCLIUpdateSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIUpdateSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIUpdateSuite{ds: &DockerSuite{}}) } func TestDockerCLIVolumeSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerCLIVolumeSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerCLIVolumeSuite{ds: &DockerSuite{}}) } func TestDockerRegistrySuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerRegistrySuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerRegistrySuite{ds: &DockerSuite{}}) } func TestDockerSchema1RegistrySuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerSchema1RegistrySuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerSchema1RegistrySuite{ds: &DockerSuite{}}) } func TestDockerRegistryAuthHtpasswdSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerRegistryAuthHtpasswdSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerRegistryAuthHtpasswdSuite{ds: &DockerSuite{}}) } func TestDockerRegistryAuthTokenSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerRegistryAuthTokenSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerRegistryAuthTokenSuite{ds: &DockerSuite{}}) } func TestDockerDaemonSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerDaemonSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerDaemonSuite{ds: &DockerSuite{}}) } func TestDockerSwarmSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerSwarmSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerSwarmSuite{ds: &DockerSuite{}}) } func TestDockerPluginSuite(t *testing.T) { - ensureTestEnvSetup(t) - suite.Run(t, &DockerPluginSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerPluginSuite{ds: &DockerSuite{}}) } func TestDockerExternalVolumeSuite(t *testing.T) { - ensureTestEnvSetup(t) testRequires(t, DaemonIsLinux) - suite.Run(t, &DockerExternalVolumeSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerExternalVolumeSuite{ds: &DockerSuite{}}) } func TestDockerNetworkSuite(t *testing.T) { - ensureTestEnvSetup(t) testRequires(t, DaemonIsLinux) - suite.Run(t, &DockerNetworkSuite{ds: &DockerSuite{}}) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) + suite.Run(ctx, t, &DockerNetworkSuite{ds: &DockerSuite{}}) } func TestDockerHubPullSuite(t *testing.T) { - ensureTestEnvSetup(t) + ctx := testutil.StartSpan(baseContext, t) + ensureTestEnvSetup(ctx, t) // FIXME. Temporarily turning this off for Windows as GH16039 was breaking // Windows to Linux CI @icecrime testRequires(t, DaemonIsLinux) - suite.Run(t, newDockerHubPullSuite()) + suite.Run(ctx, t, newDockerHubPullSuite()) } type DockerSuite struct{} @@ -365,8 +445,8 @@ func (s *DockerSuite) OnTimeout(c *testing.T) { } } -func (s *DockerSuite) TearDownTest(c *testing.T) { - testEnv.Clean(c) +func (s *DockerSuite) TearDownTest(ctx context.Context, c *testing.T) { + testEnv.Clean(ctx, c) } type DockerRegistrySuite struct { @@ -379,21 +459,21 @@ func (s *DockerRegistrySuite) OnTimeout(c *testing.T) { s.d.DumpStackAndQuit() } -func (s *DockerRegistrySuite) SetUpTest(c *testing.T) { +func (s *DockerRegistrySuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, RegistryHosting, testEnv.IsLocalDaemon) s.reg = registry.NewV2(c) s.reg.WaitReady(c) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) } -func (s *DockerRegistrySuite) TearDownTest(c *testing.T) { +func (s *DockerRegistrySuite) TearDownTest(ctx context.Context, c *testing.T) { if s.reg != nil { s.reg.Close() } if s.d != nil { s.d.Stop(c) } - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } type DockerSchema1RegistrySuite struct { @@ -406,21 +486,21 @@ func (s *DockerSchema1RegistrySuite) OnTimeout(c *testing.T) { s.d.DumpStackAndQuit() } -func (s *DockerSchema1RegistrySuite) SetUpTest(c *testing.T) { +func (s *DockerSchema1RegistrySuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, RegistryHosting, NotArm64, testEnv.IsLocalDaemon) s.reg = registry.NewV2(c, registry.Schema1) s.reg.WaitReady(c) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) } -func (s *DockerSchema1RegistrySuite) TearDownTest(c *testing.T) { +func (s *DockerSchema1RegistrySuite) TearDownTest(ctx context.Context, c *testing.T) { if s.reg != nil { s.reg.Close() } if s.d != nil { s.d.Stop(c) } - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } type DockerRegistryAuthHtpasswdSuite struct { @@ -433,14 +513,14 @@ func (s *DockerRegistryAuthHtpasswdSuite) OnTimeout(c *testing.T) { s.d.DumpStackAndQuit() } -func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *testing.T) { +func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, RegistryHosting, testEnv.IsLocalDaemon) s.reg = registry.NewV2(c, registry.Htpasswd) s.reg.WaitReady(c) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) } -func (s *DockerRegistryAuthHtpasswdSuite) TearDownTest(c *testing.T) { +func (s *DockerRegistryAuthHtpasswdSuite) TearDownTest(ctx context.Context, c *testing.T) { if s.reg != nil { out, err := s.d.Cmd("logout", privateRegistryURL) assert.NilError(c, err, out) @@ -449,7 +529,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TearDownTest(c *testing.T) { if s.d != nil { s.d.Stop(c) } - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } type DockerRegistryAuthTokenSuite struct { @@ -462,12 +542,12 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *testing.T) { s.d.DumpStackAndQuit() } -func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *testing.T) { +func (s *DockerRegistryAuthTokenSuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, RegistryHosting, testEnv.IsLocalDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) } -func (s *DockerRegistryAuthTokenSuite) TearDownTest(c *testing.T) { +func (s *DockerRegistryAuthTokenSuite) TearDownTest(ctx context.Context, c *testing.T) { if s.reg != nil { out, err := s.d.Cmd("logout", privateRegistryURL) assert.NilError(c, err, out) @@ -476,7 +556,7 @@ func (s *DockerRegistryAuthTokenSuite) TearDownTest(c *testing.T) { if s.d != nil { s.d.Stop(c) } - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } func (s *DockerRegistryAuthTokenSuite) setupRegistryWithTokenService(c *testing.T, tokenURL string) { @@ -496,20 +576,20 @@ func (s *DockerDaemonSuite) OnTimeout(c *testing.T) { s.d.DumpStackAndQuit() } -func (s *DockerDaemonSuite) SetUpTest(c *testing.T) { +func (s *DockerDaemonSuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) } -func (s *DockerDaemonSuite) TearDownTest(c *testing.T) { +func (s *DockerDaemonSuite) TearDownTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) if s.d != nil { s.d.Stop(c) } - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } -func (s *DockerDaemonSuite) TearDownSuite(c *testing.T) { +func (s *DockerDaemonSuite) TearDownSuite(ctx context.Context, c *testing.T) { filepath.Walk(testdaemon.SockRoot, func(path string, fi os.FileInfo, err error) error { if err != nil { // ignore errors here @@ -542,11 +622,11 @@ func (s *DockerSwarmSuite) OnTimeout(c *testing.T) { } } -func (s *DockerSwarmSuite) SetUpTest(c *testing.T) { +func (s *DockerSwarmSuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) } -func (s *DockerSwarmSuite) AddDaemon(c *testing.T, joinSwarm, manager bool) *daemon.Daemon { +func (s *DockerSwarmSuite) AddDaemon(ctx context.Context, c *testing.T, joinSwarm, manager bool) *daemon.Daemon { c.Helper() d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution), @@ -554,12 +634,12 @@ func (s *DockerSwarmSuite) AddDaemon(c *testing.T, joinSwarm, manager bool) *dae ) if joinSwarm { if len(s.daemons) > 0 { - d.StartAndSwarmJoin(c, s.daemons[0].Daemon, manager) + d.StartAndSwarmJoin(ctx, c, s.daemons[0].Daemon, manager) } else { - d.StartAndSwarmInit(c) + d.StartAndSwarmInit(ctx, c) } } else { - d.StartNodeWithBusybox(c) + d.StartNodeWithBusybox(ctx, c) } s.daemonsLock.Lock() @@ -570,7 +650,7 @@ func (s *DockerSwarmSuite) AddDaemon(c *testing.T, joinSwarm, manager bool) *dae return d } -func (s *DockerSwarmSuite) TearDownTest(c *testing.T) { +func (s *DockerSwarmSuite) TearDownTest(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux) s.daemonsLock.Lock() for _, d := range s.daemons { @@ -582,7 +662,7 @@ func (s *DockerSwarmSuite) TearDownTest(c *testing.T) { s.daemons = nil s.portIndex = 0 s.daemonsLock.Unlock() - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } type DockerPluginSuite struct { @@ -602,26 +682,26 @@ func (ps *DockerPluginSuite) getPluginRepoWithTag() string { return ps.getPluginRepo() + ":" + "latest" } -func (ps *DockerPluginSuite) SetUpSuite(c *testing.T) { +func (ps *DockerPluginSuite) SetUpSuite(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, RegistryHosting) ps.registry = registry.NewV2(c) ps.registry.WaitReady(c) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(ctx, 60*time.Second) defer cancel() err := plugin.CreateInRegistry(ctx, ps.getPluginRepo(), nil) assert.NilError(c, err, "failed to create plugin") } -func (ps *DockerPluginSuite) TearDownSuite(c *testing.T) { +func (ps *DockerPluginSuite) TearDownSuite(ctx context.Context, c *testing.T) { if ps.registry != nil { ps.registry.Close() } } -func (ps *DockerPluginSuite) TearDownTest(c *testing.T) { - ps.ds.TearDownTest(c) +func (ps *DockerPluginSuite) TearDownTest(ctx context.Context, c *testing.T) { + ps.ds.TearDownTest(ctx, c) } func (ps *DockerPluginSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/daemon/daemon.go b/integration-cli/daemon/daemon.go index fecc516c98..9bf6b18f41 100644 --- a/integration-cli/daemon/daemon.go +++ b/integration-cli/daemon/daemon.go @@ -1,6 +1,7 @@ package daemon // import "github.com/docker/docker/integration-cli/daemon" import ( + "context" "fmt" "strings" "testing" @@ -79,14 +80,16 @@ func (d *Daemon) inspectFieldWithError(name, field string) (string, error) { // CheckActiveContainerCount returns the number of active containers // FIXME(vdemeester) should re-use ActivateContainers in some way -func (d *Daemon) CheckActiveContainerCount(t *testing.T) (interface{}, string) { - t.Helper() - out, err := d.Cmd("ps", "-q") - assert.NilError(t, err) - if len(strings.TrimSpace(out)) == 0 { - return 0, "" +func (d *Daemon) CheckActiveContainerCount(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + t.Helper() + out, err := d.Cmd("ps", "-q") + assert.NilError(t, err) + if len(strings.TrimSpace(out)) == 0 { + return 0, "" + } + return len(strings.Split(strings.TrimSpace(out), "\n")), fmt.Sprintf("output: %q", out) } - return len(strings.Split(strings.TrimSpace(out), "\n")), fmt.Sprintf("output: %q", out) } // WaitRun waits for a container to be running for 10s diff --git a/integration-cli/daemon/daemon_swarm.go b/integration-cli/daemon/daemon_swarm.go index 8ac72cef0a..e118ebda36 100644 --- a/integration-cli/daemon/daemon_swarm.go +++ b/integration-cli/daemon/daemon_swarm.go @@ -15,9 +15,9 @@ import ( // CheckServiceTasksInState returns the number of tasks with a matching state, // and optional message substring. -func (d *Daemon) CheckServiceTasksInState(service string, state swarm.TaskState, message string) func(*testing.T) (interface{}, string) { +func (d *Daemon) CheckServiceTasksInState(ctx context.Context, service string, state swarm.TaskState, message string) func(*testing.T) (interface{}, string) { return func(c *testing.T) (interface{}, string) { - tasks := d.GetServiceTasks(c, service) + tasks := d.GetServiceTasks(ctx, c, service) var count int for _, task := range tasks { if task.Status.State == state { @@ -32,9 +32,9 @@ func (d *Daemon) CheckServiceTasksInState(service string, state swarm.TaskState, // CheckServiceTasksInStateWithError returns the number of tasks with a matching state, // and optional message substring. -func (d *Daemon) CheckServiceTasksInStateWithError(service string, state swarm.TaskState, errorMessage string) func(*testing.T) (interface{}, string) { +func (d *Daemon) CheckServiceTasksInStateWithError(ctx context.Context, service string, state swarm.TaskState, errorMessage string) func(*testing.T) (interface{}, string) { return func(c *testing.T) (interface{}, string) { - tasks := d.GetServiceTasks(c, service) + tasks := d.GetServiceTasks(ctx, c, service) var count int for _, task := range tasks { if task.Status.State == state { @@ -48,14 +48,14 @@ func (d *Daemon) CheckServiceTasksInStateWithError(service string, state swarm.T } // CheckServiceRunningTasks returns the number of running tasks for the specified service -func (d *Daemon) CheckServiceRunningTasks(service string) func(*testing.T) (interface{}, string) { - return d.CheckServiceTasksInState(service, swarm.TaskStateRunning, "") +func (d *Daemon) CheckServiceRunningTasks(ctx context.Context, service string) func(*testing.T) (interface{}, string) { + return d.CheckServiceTasksInState(ctx, service, swarm.TaskStateRunning, "") } // CheckServiceUpdateState returns the current update state for the specified service -func (d *Daemon) CheckServiceUpdateState(service string) func(*testing.T) (interface{}, string) { +func (d *Daemon) CheckServiceUpdateState(ctx context.Context, service string) func(*testing.T) (interface{}, string) { return func(c *testing.T) (interface{}, string) { - service := d.GetService(c, service) + service := d.GetService(ctx, c, service) if service.UpdateStatus == nil { return "", "" } @@ -64,10 +64,10 @@ func (d *Daemon) CheckServiceUpdateState(service string) func(*testing.T) (inter } // CheckPluginRunning returns the runtime state of the plugin -func (d *Daemon) CheckPluginRunning(plugin string) func(c *testing.T) (interface{}, string) { +func (d *Daemon) CheckPluginRunning(ctx context.Context, plugin string) func(c *testing.T) (interface{}, string) { return func(c *testing.T) (interface{}, string) { apiclient := d.NewClientT(c) - resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin) + resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin) if errdefs.IsNotFound(err) { return false, fmt.Sprintf("%v", err) } @@ -77,10 +77,10 @@ func (d *Daemon) CheckPluginRunning(plugin string) func(c *testing.T) (interface } // CheckPluginImage returns the runtime state of the plugin -func (d *Daemon) CheckPluginImage(plugin string) func(c *testing.T) (interface{}, string) { +func (d *Daemon) CheckPluginImage(ctx context.Context, plugin string) func(c *testing.T) (interface{}, string) { return func(c *testing.T) (interface{}, string) { apiclient := d.NewClientT(c) - resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin) + resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin) if errdefs.IsNotFound(err) { return false, fmt.Sprintf("%v", err) } @@ -90,94 +90,106 @@ func (d *Daemon) CheckPluginImage(plugin string) func(c *testing.T) (interface{} } // CheckServiceTasks returns the number of tasks for the specified service -func (d *Daemon) CheckServiceTasks(service string) func(*testing.T) (interface{}, string) { +func (d *Daemon) CheckServiceTasks(ctx context.Context, service string) func(*testing.T) (interface{}, string) { return func(c *testing.T) (interface{}, string) { - tasks := d.GetServiceTasks(c, service) + tasks := d.GetServiceTasks(ctx, c, service) return len(tasks), "" } } // CheckRunningTaskNetworks returns the number of times each network is referenced from a task. -func (d *Daemon) CheckRunningTaskNetworks(c *testing.T) (interface{}, string) { - cli := d.NewClientT(c) - defer cli.Close() +func (d *Daemon) CheckRunningTaskNetworks(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + cli := d.NewClientT(t) + defer cli.Close() - tasks, err := cli.TaskList(context.Background(), types.TaskListOptions{ - Filters: filters.NewArgs(filters.Arg("desired-state", "running")), - }) - assert.NilError(c, err) + tasks, err := cli.TaskList(ctx, types.TaskListOptions{ + Filters: filters.NewArgs(filters.Arg("desired-state", "running")), + }) + assert.NilError(t, err) - result := make(map[string]int) - for _, task := range tasks { - for _, network := range task.Spec.Networks { - result[network.Target]++ + result := make(map[string]int) + for _, task := range tasks { + for _, network := range task.Spec.Networks { + result[network.Target]++ + } } + return result, "" } - return result, "" } // CheckRunningTaskImages returns the times each image is running as a task. -func (d *Daemon) CheckRunningTaskImages(c *testing.T) (interface{}, string) { - cli := d.NewClientT(c) - defer cli.Close() +func (d *Daemon) CheckRunningTaskImages(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + cli := d.NewClientT(t) + defer cli.Close() - tasks, err := cli.TaskList(context.Background(), types.TaskListOptions{ - Filters: filters.NewArgs(filters.Arg("desired-state", "running")), - }) - assert.NilError(c, err) + tasks, err := cli.TaskList(ctx, types.TaskListOptions{ + Filters: filters.NewArgs(filters.Arg("desired-state", "running")), + }) + assert.NilError(t, err) - result := make(map[string]int) - for _, task := range tasks { - if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil { - result[task.Spec.ContainerSpec.Image]++ + result := make(map[string]int) + for _, task := range tasks { + if task.Status.State == swarm.TaskStateRunning && task.Spec.ContainerSpec != nil { + result[task.Spec.ContainerSpec.Image]++ + } } + return result, "" } - return result, "" } // CheckNodeReadyCount returns the number of ready node on the swarm -func (d *Daemon) CheckNodeReadyCount(c *testing.T) (interface{}, string) { - nodes := d.ListNodes(c) - var readyCount int - for _, node := range nodes { - if node.Status.State == swarm.NodeStateReady { - readyCount++ +func (d *Daemon) CheckNodeReadyCount(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + nodes := d.ListNodes(ctx, t) + var readyCount int + for _, node := range nodes { + if node.Status.State == swarm.NodeStateReady { + readyCount++ + } } + return readyCount, "" } - return readyCount, "" } // CheckLocalNodeState returns the current swarm node state -func (d *Daemon) CheckLocalNodeState(c *testing.T) (interface{}, string) { - info := d.SwarmInfo(c) - return info.LocalNodeState, "" +func (d *Daemon) CheckLocalNodeState(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + info := d.SwarmInfo(ctx, t) + return info.LocalNodeState, "" + } } // CheckControlAvailable returns the current swarm control available -func (d *Daemon) CheckControlAvailable(c *testing.T) (interface{}, string) { - info := d.SwarmInfo(c) - assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) - return info.ControlAvailable, "" +func (d *Daemon) CheckControlAvailable(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + info := d.SwarmInfo(ctx, t) + assert.Equal(t, info.LocalNodeState, swarm.LocalNodeStateActive) + return info.ControlAvailable, "" + } } // CheckLeader returns whether there is a leader on the swarm or not -func (d *Daemon) CheckLeader(c *testing.T) (interface{}, string) { - cli := d.NewClientT(c) - defer cli.Close() +func (d *Daemon) CheckLeader(ctx context.Context) func(t *testing.T) (interface{}, string) { + return func(t *testing.T) (interface{}, string) { + cli := d.NewClientT(t) + defer cli.Close() - errList := "could not get node list" + errList := "could not get node list" - ls, err := cli.NodeList(context.Background(), types.NodeListOptions{}) - if err != nil { - return err, errList - } - - for _, node := range ls { - if node.ManagerStatus != nil && node.ManagerStatus.Leader { - return nil, "" + ls, err := cli.NodeList(ctx, types.NodeListOptions{}) + if err != nil { + return err, errList } + + for _, node := range ls { + if node.ManagerStatus != nil && node.ManagerStatus.Leader { + return nil, "" + } + } + return fmt.Errorf("no leader"), "could not find leader" } - return fmt.Errorf("no leader"), "could not find leader" } // CmdRetryOutOfSequence tries the specified command against the current daemon diff --git a/integration-cli/docker_api_attach_test.go b/integration-cli/docker_api_attach_test.go index 401087ab2e..9cf6645d60 100644 --- a/integration-cli/docker_api_attach_test.go +++ b/integration-cli/docker_api_attach_test.go @@ -3,7 +3,6 @@ package main import ( "bufio" "bytes" - "context" "io" "net" "net/http" @@ -14,6 +13,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "github.com/docker/go-connections/sockets" "github.com/pkg/errors" @@ -75,7 +75,8 @@ func (s *DockerAPISuite) TestGetContainersAttachWebsocket(c *testing.T) { // regression gh14320 func (s *DockerAPISuite) TestPostContainersAttachContainerNotFound(c *testing.T) { - resp, _, err := request.Post("/containers/doesnotexist/attach") + ctx := testutil.GetContext(c) + resp, _, err := request.Post(ctx, "/containers/doesnotexist/attach") assert.NilError(c, err) // connection will shutdown, err should be "persistent connection closed" assert.Equal(c, resp.StatusCode, http.StatusNotFound) @@ -86,7 +87,8 @@ func (s *DockerAPISuite) TestPostContainersAttachContainerNotFound(c *testing.T) } func (s *DockerAPISuite) TestGetContainersWsAttachContainerNotFound(c *testing.T) { - res, body, err := request.Get("/containers/doesnotexist/attach/ws") + ctx := testutil.GetContext(c) + res, body, err := request.Get(ctx, "/containers/doesnotexist/attach/ws") assert.Equal(c, res.StatusCode, http.StatusNotFound) assert.NilError(c, err) b, err := request.ReadBody(body) @@ -190,7 +192,7 @@ func (s *DockerAPISuite) TestPostContainersAttach(c *testing.T) { Logs: false, } - resp, err := apiClient.ContainerAttach(context.Background(), cid, attachOpts) + resp, err := apiClient.ContainerAttach(testutil.GetContext(c), cid, attachOpts) assert.NilError(c, err) mediaType, b := resp.MediaType() assert.Check(c, b) @@ -199,7 +201,7 @@ func (s *DockerAPISuite) TestPostContainersAttach(c *testing.T) { // Make sure we do see "hello" if Logs is true attachOpts.Logs = true - resp, err = apiClient.ContainerAttach(context.Background(), cid, attachOpts) + resp, err = apiClient.ContainerAttach(testutil.GetContext(c), cid, attachOpts) assert.NilError(c, err) defer resp.Conn.Close() diff --git a/integration-cli/docker_api_build_test.go b/integration-cli/docker_api_build_test.go index deb3764aa3..2359d24873 100644 --- a/integration-cli/docker_api_build_test.go +++ b/integration-cli/docker_api_build_test.go @@ -3,7 +3,6 @@ package main import ( "archive/tar" "bytes" - "context" "encoding/json" "fmt" "io" @@ -13,6 +12,7 @@ import ( "testing" "github.com/docker/docker/api/types" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/fakecontext" "github.com/docker/docker/testutil/fakegit" "github.com/docker/docker/testutil/fakestorage" @@ -23,6 +23,7 @@ import ( func (s *DockerAPISuite) TestBuildAPIDockerFileRemote(c *testing.T) { testRequires(c, NotUserNamespace) + ctx := testutil.GetContext(c) // -xdev is required because sysfs can cause EPERM testD := `FROM busybox @@ -31,7 +32,7 @@ RUN find /tmp/` server := fakestorage.New(c, "", fakecontext.WithFiles(map[string]string{"testD": testD})) defer server.Close() - res, body, err := request.Post("/build?dockerfile=baz&remote="+server.URL()+"/testD", request.JSON) + res, body, err := request.Post(ctx, "/build?dockerfile=baz&remote="+server.URL()+"/testD", request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -46,6 +47,8 @@ RUN find /tmp/` } func (s *DockerAPISuite) TestBuildAPIRemoteTarballContext(c *testing.T) { + ctx := testutil.GetContext(c) + buffer := new(bytes.Buffer) tw := tar.NewWriter(buffer) defer tw.Close() @@ -66,7 +69,7 @@ func (s *DockerAPISuite) TestBuildAPIRemoteTarballContext(c *testing.T) { })) defer server.Close() - res, b, err := request.Post("/build?remote="+server.URL()+"/testT.tar", request.ContentType("application/tar")) + res, b, err := request.Post(ctx, "/build?remote="+server.URL()+"/testT.tar", request.ContentType("application/tar")) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) b.Close() @@ -113,8 +116,9 @@ RUN echo 'right' })) defer server.Close() + ctx := testutil.GetContext(c) url := "/build?dockerfile=custom&remote=" + server.URL() + "/testT.tar" - res, body, err := request.Post(url, request.ContentType("application/tar")) + res, body, err := request.Post(ctx, url, request.ContentType("application/tar")) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -133,7 +137,8 @@ RUN echo from dockerfile`, }, false) defer git.Close() - res, body, err := request.Post("/build?remote="+git.RepoURL, request.JSON) + ctx := testutil.GetContext(c) + res, body, err := request.Post(ctx, "/build?remote="+git.RepoURL, request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -153,8 +158,9 @@ RUN echo from Dockerfile`, }, false) defer git.Close() + ctx := testutil.GetContext(c) // Make sure it tries to 'dockerfile' query param value - res, body, err := request.Post("/build?dockerfile=baz&remote="+git.RepoURL, request.JSON) + res, body, err := request.Post(ctx, "/build?dockerfile=baz&remote="+git.RepoURL, request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -175,8 +181,10 @@ RUN echo from dockerfile`, }, false) defer git.Close() + ctx := testutil.GetContext(c) + // Make sure it tries to 'dockerfile' query param value - res, body, err := request.Post("/build?remote="+git.RepoURL, request.JSON) + res, body, err := request.Post(ctx, "/build?remote="+git.RepoURL, request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -218,7 +226,9 @@ func (s *DockerAPISuite) TestBuildAPIUnnormalizedTarPaths(c *testing.T) { assert.NilError(c, tw.Close(), "failed to close tar archive") - res, body, err := request.Post("/build", request.RawContent(io.NopCloser(buffer)), request.ContentType("application/x-tar")) + ctx := testutil.GetContext(c) + + res, body, err := request.Post(ctx, "/build", request.RawContent(io.NopCloser(buffer)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -248,15 +258,17 @@ func (s *DockerAPISuite) TestBuildOnBuildWithCopy(c *testing.T) { FROM onbuildbase ` - ctx := fakecontext.New(c, "", + bCtx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), fakecontext.WithFile("file", "some content"), ) - defer ctx.Close() + defer bCtx.Close() + ctx := testutil.GetContext(c) res, body, err := request.Post( + ctx, "/build", - request.RawContent(ctx.AsTarReader(c)), + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -268,14 +280,16 @@ func (s *DockerAPISuite) TestBuildOnBuildWithCopy(c *testing.T) { func (s *DockerAPISuite) TestBuildOnBuildCache(c *testing.T) { build := func(dockerfile string) []byte { - ctx := fakecontext.New(c, "", + bCtx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), ) - defer ctx.Close() + defer bCtx.Close() + ctx := testutil.GetContext(c) res, body, err := request.Post( + ctx, "/build", - request.RawContent(ctx.AsTarReader(c)), + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Check(c, is.DeepEqual(http.StatusOK, res.StatusCode)) @@ -301,11 +315,12 @@ func (s *DockerAPISuite) TestBuildOnBuildCache(c *testing.T) { parentID, childID := imageIDs[0], imageIDs[1] client := testEnv.APIClient() + ctx := testutil.GetContext(c) // check parentID is correct // Parent is graphdriver-only if !testEnv.UsingSnapshotter() { - image, _, err := client.ImageInspectWithRaw(context.Background(), childID) + image, _, err := client.ImageInspectWithRaw(ctx, childID) assert.NilError(c, err) assert.Check(c, is.Equal(parentID, image.Parent)) @@ -317,10 +332,11 @@ func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *testing.T) { repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) // tag the image to upload it to the private registry - err := client.ImageTag(context.TODO(), "busybox", repoName) + ctx := testutil.GetContext(c) + err := client.ImageTag(ctx, "busybox", repoName) assert.Check(c, err) // push the image to the registry - rc, err := client.ImagePush(context.TODO(), repoName, types.ImagePushOptions{RegistryAuth: "{}"}) + rc, err := client.ImagePush(ctx, repoName, types.ImagePushOptions{RegistryAuth: "{}"}) assert.Check(c, err) _, err = io.Copy(io.Discard, rc) assert.Check(c, err) @@ -332,14 +348,15 @@ func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *testing.T) { COPY --from=foo /abc / `, repoName, repoName) - ctx := fakecontext.New(c, "", + bCtx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), ) - defer ctx.Close() + defer bCtx.Close() res, body, err := request.Post( + ctx, "/build?pull=1", - request.RawContent(ctx.AsTarReader(c)), + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Check(c, is.DeepEqual(http.StatusOK, res.StatusCode)) @@ -376,14 +393,16 @@ func (s *DockerAPISuite) TestBuildAddRemoteNoDecompress(c *testing.T) { RUN [ -f test.tar ] `, server.URL()) - ctx := fakecontext.New(c, "", + bCtx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), ) - defer ctx.Close() + defer bCtx.Close() + ctx := testutil.GetContext(c) res, body, err := request.Post( + ctx, "/build", - request.RawContent(ctx.AsTarReader(c)), + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Check(c, is.DeepEqual(http.StatusOK, res.StatusCode)) @@ -405,15 +424,17 @@ func (s *DockerAPISuite) TestBuildChownOnCopy(c *testing.T) { RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'test1:test2' ] RUN [ $(ls -nl / | grep new_dir | awk '{print $3":"$4}') = '1001:1002' ] ` - ctx := fakecontext.New(c, "", + bCtx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), fakecontext.WithFile("test_file1", "some test content"), ) - defer ctx.Close() + defer bCtx.Close() + ctx := testutil.GetContext(c) res, body, err := request.Post( + ctx, "/build", - request.RawContent(ctx.AsTarReader(c)), + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -434,9 +455,10 @@ COPY file /file` fakecontext.WithDockerfile(dockerfile), fakecontext.WithFile("file", "bar")) - build := func(ctx *fakecontext.Fake) string { - res, body, err := request.Post("/build", - request.RawContent(ctx.AsTarReader(c)), + ctx := testutil.GetContext(c) + build := func(bCtx *fakecontext.Fake) string { + res, body, err := request.Post(ctx, "/build", + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) @@ -474,9 +496,10 @@ ADD file /file` fakecontext.WithDockerfile(dockerfile), fakecontext.WithFile("file", "bar")) - build := func(ctx *fakecontext.Fake) string { - res, body, err := request.Post("/build", - request.RawContent(ctx.AsTarReader(c)), + ctx := testutil.GetContext(c) + build := func(bCtx *fakecontext.Fake) string { + res, body, err := request.Post(ctx, "/build", + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) @@ -508,14 +531,16 @@ func (s *DockerAPISuite) TestBuildScratchCopy(c *testing.T) { dockerfile := `FROM scratch ADD Dockerfile / ENV foo bar` - ctx := fakecontext.New(c, "", + bCtx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), ) - defer ctx.Close() + defer bCtx.Close() + ctx := testutil.GetContext(c) res, body, err := request.Post( + ctx, "/build", - request.RawContent(ctx.AsTarReader(c)), + request.RawContent(bCtx.AsTarReader(c)), request.ContentType("application/x-tar")) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) diff --git a/integration-cli/docker_api_build_windows_test.go b/integration-cli/docker_api_build_windows_test.go index 397657620a..5ff7226ad4 100644 --- a/integration-cli/docker_api_build_windows_test.go +++ b/integration-cli/docker_api_build_windows_test.go @@ -6,6 +6,7 @@ import ( "net/http" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/fakecontext" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" @@ -24,7 +25,7 @@ func (s *DockerAPISuite) TestBuildWithRecycleBin(c *testing.T) { ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile)) defer ctx.Close() - res, body, err := request.Post( + res, body, err := request.Post(testutil.GetContext(c), "/build", request.RawContent(ctx.AsTarReader(c)), request.ContentType("application/x-tar")) diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 316bbbae85..bde7bd328d 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -27,6 +27,7 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "github.com/docker/docker/volume" "github.com/docker/go-connections/nat" @@ -47,7 +48,8 @@ func (s *DockerAPISuite) TestContainerAPIGetAll(c *testing.T) { options := types.ContainerListOptions{ All: true, } - containers, err := apiClient.ContainerList(context.Background(), options) + ctx := testutil.GetContext(c) + containers, err := apiClient.ContainerList(ctx, options) assert.NilError(c, err) assert.Equal(c, len(containers), startCount+1) actual := containers[0].Names[0] @@ -66,7 +68,8 @@ func (s *DockerAPISuite) TestContainerAPIGetJSONNoFieldsOmitted(c *testing.T) { options := types.ContainerListOptions{ All: true, } - containers, err := apiClient.ContainerList(context.Background(), options) + ctx := testutil.GetContext(c) + containers, err := apiClient.ContainerList(ctx, options) assert.NilError(c, err) assert.Equal(c, len(containers), startCount+1) actual := fmt.Sprintf("%+v", containers[0]) @@ -105,7 +108,7 @@ func (s *DockerAPISuite) TestContainerAPIGetExport(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - body, err := apiClient.ContainerExport(context.Background(), name) + body, err := apiClient.ContainerExport(testutil.GetContext(c), name) assert.NilError(c, err) defer body.Close() found := false @@ -132,7 +135,7 @@ func (s *DockerAPISuite) TestContainerAPIGetChanges(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - changes, err := apiClient.ContainerDiff(context.Background(), name) + changes, err := apiClient.ContainerDiff(testutil.GetContext(c), name) assert.NilError(c, err) // Check the changelog for removal of /etc/passwd @@ -160,7 +163,7 @@ func (s *DockerAPISuite) TestGetContainerStats(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - stats, err := apiClient.ContainerStats(context.Background(), name, true) + stats, err := apiClient.ContainerStats(testutil.GetContext(c), name, true) assert.NilError(c, err) bc <- b{stats, err} }() @@ -194,7 +197,7 @@ func (s *DockerAPISuite) TestGetContainerStatsRmRunning(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - stats, err := apiClient.ContainerStats(context.Background(), id, true) + stats, err := apiClient.ContainerStats(testutil.GetContext(c), id, true) assert.NilError(c, err) defer stats.Body.Close() @@ -265,7 +268,7 @@ func (s *DockerAPISuite) TestGetContainerStatsStream(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - stats, err := apiClient.ContainerStats(context.Background(), name, true) + stats, err := apiClient.ContainerStats(testutil.GetContext(c), name, true) assert.NilError(c, err) bc <- b{stats, err} }() @@ -307,7 +310,7 @@ func (s *DockerAPISuite) TestGetContainerStatsNoStream(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - stats, err := apiClient.ContainerStats(context.Background(), name, false) + stats, err := apiClient.ContainerStats(testutil.GetContext(c), name, false) assert.NilError(c, err) bc <- b{stats, err} }() @@ -344,7 +347,7 @@ func (s *DockerAPISuite) TestGetStoppedContainerStats(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - resp, err := apiClient.ContainerStats(context.Background(), name, false) + resp, err := apiClient.ContainerStats(testutil.GetContext(c), name, false) assert.NilError(c, err) defer resp.Body.Close() chResp <- err @@ -373,7 +376,7 @@ func (s *DockerAPISuite) TestContainerAPIPause(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerPause(context.Background(), ContainerID) + err = apiClient.ContainerPause(testutil.GetContext(c), ContainerID) assert.NilError(c, err) pausedContainers := getPaused(c) @@ -382,7 +385,7 @@ func (s *DockerAPISuite) TestContainerAPIPause(c *testing.T) { c.Fatalf("there should be one paused container and not %d", len(pausedContainers)) } - err = apiClient.ContainerUnpause(context.Background(), ContainerID) + err = apiClient.ContainerUnpause(testutil.GetContext(c), ContainerID) assert.NilError(c, err) pausedContainers = getPaused(c) @@ -400,7 +403,7 @@ func (s *DockerAPISuite) TestContainerAPITop(c *testing.T) { defer apiClient.Close() // sort by comm[andline] to make sure order stays the same in case of PID rollover - top, err := apiClient.ContainerTop(context.Background(), id, []string{"aux", "--sort=comm"}) + top, err := apiClient.ContainerTop(testutil.GetContext(c), id, []string{"aux", "--sort=comm"}) assert.NilError(c, err) assert.Equal(c, len(top.Titles), 11, fmt.Sprintf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)) @@ -422,7 +425,7 @@ func (s *DockerAPISuite) TestContainerAPITopWindows(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - top, err := apiClient.ContainerTop(context.Background(), id, nil) + top, err := apiClient.ContainerTop(testutil.GetContext(c), id, nil) assert.NilError(c, err) assert.Equal(c, len(top.Titles), 4, "expected 4 titles, found %d: %v", len(top.Titles), top.Titles) @@ -455,7 +458,7 @@ func (s *DockerAPISuite) TestContainerAPICommit(c *testing.T) { Reference: "testcontainerapicommit:testtag", } - img, err := apiClient.ContainerCommit(context.Background(), cName, options) + img, err := apiClient.ContainerCommit(testutil.GetContext(c), cName, options) assert.NilError(c, err) cmd := inspectField(c, img.ID, "Config.Cmd") @@ -482,7 +485,7 @@ func (s *DockerAPISuite) TestContainerAPICommitWithLabelInConfig(c *testing.T) { Config: &config, } - img, err := apiClient.ContainerCommit(context.Background(), cName, options) + img, err := apiClient.ContainerCommit(testutil.GetContext(c), cName, options) assert.NilError(c, err) label1 := inspectFieldMap(c, img.ID, "Config.Labels", "key1") @@ -522,7 +525,7 @@ func (s *DockerAPISuite) TestContainerAPIBadPort(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") assert.ErrorContains(c, err, `invalid port specification: "aa80"`) } @@ -536,7 +539,7 @@ func (s *DockerAPISuite) TestContainerAPICreate(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) out, _ := dockerCmd(c, "start", "-a", ctr.ID) @@ -548,7 +551,7 @@ func (s *DockerAPISuite) TestContainerAPICreateEmptyConfig(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &container.Config{}, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &container.Config{}, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") assert.ErrorContains(c, err, "no command specified") } @@ -571,7 +574,7 @@ func (s *DockerAPISuite) TestContainerAPICreateMultipleNetworksConfig(c *testing assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &networkingConfig, nil, "") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &networkingConfig, nil, "") msg := err.Error() // network name order in error message is not deterministic assert.Assert(c, strings.Contains(msg, "container cannot be connected to network endpoints")) @@ -606,10 +609,10 @@ func UtilCreateNetworkMode(c *testing.T, networkMode container.NetworkMode) { assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) - containerJSON, err := apiClient.ContainerInspect(context.Background(), ctr.ID) + containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) assert.NilError(c, err) assert.Equal(c, containerJSON.HostConfig.NetworkMode, networkMode, "Mismatched NetworkMode") @@ -633,10 +636,10 @@ func (s *DockerAPISuite) TestContainerAPICreateWithCpuSharesCpuset(c *testing.T) assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) - containerJSON, err := apiClient.ContainerInspect(context.Background(), ctr.ID) + containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) assert.NilError(c, err) out := inspectField(c, containerJSON.ID, "HostConfig.CpuShares") @@ -654,7 +657,7 @@ func (s *DockerAPISuite) TestContainerAPIVerifyHeader(c *testing.T) { create := func(ct string) (*http.Response, io.ReadCloser, error) { jsonData := bytes.NewBuffer(nil) assert.Assert(c, json.NewEncoder(jsonData).Encode(config) == nil) - return request.Post("/containers/create", request.RawContent(io.NopCloser(jsonData)), request.ContentType(ct)) + return request.Post(testutil.GetContext(c), "/containers/create", request.RawContent(io.NopCloser(jsonData)), request.ContentType(ct)) } // Try with no content-type @@ -700,7 +703,7 @@ func (s *DockerAPISuite) TestContainerAPIInvalidPortSyntax(c *testing.T) { } }` - res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) if versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusBadRequest) @@ -724,7 +727,7 @@ func (s *DockerAPISuite) TestContainerAPIRestartPolicyInvalidPolicyName(c *testi } }` - res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) if versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusBadRequest) @@ -748,7 +751,7 @@ func (s *DockerAPISuite) TestContainerAPIRestartPolicyRetryMismatch(c *testing.T } }` - res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) if versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusBadRequest) @@ -772,7 +775,7 @@ func (s *DockerAPISuite) TestContainerAPIRestartPolicyNegativeRetryCount(c *test } }` - res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) if versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusBadRequest) @@ -796,7 +799,7 @@ func (s *DockerAPISuite) TestContainerAPIRestartPolicyDefaultRetryCount(c *testi } }` - res, _, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, _, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusCreated) } @@ -827,7 +830,7 @@ func (s *DockerAPISuite) TestContainerAPIPostCreateNull(c *testing.T) { "NetworkDisabled":false, "OnBuild":null}` - res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusCreated) @@ -858,7 +861,7 @@ func (s *DockerAPISuite) TestCreateWithTooLowMemoryLimit(c *testing.T) { "Memory": 524287 }` - res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.RawString(config), request.JSON) assert.NilError(c, err) b, err2 := request.ReadBody(body) assert.Assert(c, err2 == nil) @@ -881,7 +884,7 @@ func (s *DockerAPISuite) TestContainerAPIRename(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRename(context.Background(), containerID, newName) + err = apiClient.ContainerRename(testutil.GetContext(c), containerID, newName) assert.NilError(c, err) name := inspectField(c, containerID, "Name") @@ -896,7 +899,7 @@ func (s *DockerAPISuite) TestContainerAPIKill(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerKill(context.Background(), name, "SIGKILL") + err = apiClient.ContainerKill(testutil.GetContext(c), name, "SIGKILL") assert.NilError(c, err) state := inspectField(c, name, "State.Running") @@ -911,7 +914,7 @@ func (s *DockerAPISuite) TestContainerAPIRestart(c *testing.T) { defer apiClient.Close() timeout := 1 - err = apiClient.ContainerRestart(context.Background(), name, container.StopOptions{Timeout: &timeout}) + err = apiClient.ContainerRestart(testutil.GetContext(c), name, container.StopOptions{Timeout: &timeout}) assert.NilError(c, err) assert.Assert(c, waitInspect(name, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 15*time.Second) == nil) @@ -927,7 +930,7 @@ func (s *DockerAPISuite) TestContainerAPIRestartNotimeoutParam(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRestart(context.Background(), name, container.StopOptions{}) + err = apiClient.ContainerRestart(testutil.GetContext(c), name, container.StopOptions{}) assert.NilError(c, err) assert.Assert(c, waitInspect(name, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 15*time.Second) == nil) @@ -945,15 +948,15 @@ func (s *DockerAPISuite) TestContainerAPIStart(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name) assert.NilError(c, err) - err = apiClient.ContainerStart(context.Background(), name, types.ContainerStartOptions{}) + err = apiClient.ContainerStart(testutil.GetContext(c), name, types.ContainerStartOptions{}) assert.NilError(c, err) // second call to start should give 304 // maybe add ContainerStartWithRaw to test it - err = apiClient.ContainerStart(context.Background(), name, types.ContainerStartOptions{}) + err = apiClient.ContainerStart(testutil.GetContext(c), name, types.ContainerStartOptions{}) assert.NilError(c, err) // TODO(tibor): figure out why this doesn't work on windows @@ -968,7 +971,7 @@ func (s *DockerAPISuite) TestContainerAPIStop(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerStop(context.Background(), name, container.StopOptions{ + err = apiClient.ContainerStop(testutil.GetContext(c), name, container.StopOptions{ Timeout: &timeout, }) assert.NilError(c, err) @@ -976,7 +979,7 @@ func (s *DockerAPISuite) TestContainerAPIStop(c *testing.T) { // second call to start should give 304 // maybe add ContainerStartWithRaw to test it - err = apiClient.ContainerStop(context.Background(), name, container.StopOptions{ + err = apiClient.ContainerStop(testutil.GetContext(c), name, container.StopOptions{ Timeout: &timeout, }) assert.NilError(c, err) @@ -995,7 +998,7 @@ func (s *DockerAPISuite) TestContainerAPIWait(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - waitResC, errC := apiClient.ContainerWait(context.Background(), name, "") + waitResC, errC := apiClient.ContainerWait(testutil.GetContext(c), name, "") select { case err = <-errC: @@ -1013,7 +1016,7 @@ func (s *DockerAPISuite) TestContainerAPICopyNotExistsAnyMore(c *testing.T) { Resource: "/test.txt", } // no copy in client/ - res, _, err := request.Post("/containers/"+name+"/copy", request.JSONBody(postData)) + res, _, err := request.Post(testutil.GetContext(c), "/containers/"+name+"/copy", request.JSONBody(postData)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNotFound) } @@ -1027,7 +1030,7 @@ func (s *DockerAPISuite) TestContainerAPICopyPre124(c *testing.T) { Resource: "/test.txt", } - res, body, err := request.Post("/v1.23/containers/"+name+"/copy", request.JSONBody(postData)) + res, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/"+name+"/copy", request.JSONBody(postData)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -1057,7 +1060,7 @@ func (s *DockerAPISuite) TestContainerAPICopyResourcePathEmptyPre124(c *testing. Resource: "", } - res, body, err := request.Post("/v1.23/containers/"+name+"/copy", request.JSONBody(postData)) + res, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/"+name+"/copy", request.JSONBody(postData)) assert.NilError(c, err) if versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusBadRequest) @@ -1078,7 +1081,7 @@ func (s *DockerAPISuite) TestContainerAPICopyResourcePathNotFoundPre124(c *testi Resource: "/notexist", } - res, body, err := request.Post("/v1.23/containers/"+name+"/copy", request.JSONBody(postData)) + res, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/"+name+"/copy", request.JSONBody(postData)) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusInternalServerError) @@ -1096,7 +1099,7 @@ func (s *DockerAPISuite) TestContainerAPICopyContainerNotFoundPr124(c *testing.T Resource: "/something", } - res, _, err := request.Post("/v1.23/containers/notexists/copy", request.JSONBody(postData)) + res, _, err := request.Post(testutil.GetContext(c), "/v1.23/containers/notexists/copy", request.JSONBody(postData)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNotFound) } @@ -1113,7 +1116,7 @@ func (s *DockerAPISuite) TestContainerAPIDelete(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRemove(context.Background(), id, types.ContainerRemoveOptions{}) + err = apiClient.ContainerRemove(testutil.GetContext(c), id, types.ContainerRemoveOptions{}) assert.NilError(c, err) } @@ -1122,7 +1125,7 @@ func (s *DockerAPISuite) TestContainerAPIDeleteNotExist(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRemove(context.Background(), "doesnotexist", types.ContainerRemoveOptions{}) + err = apiClient.ContainerRemove(testutil.GetContext(c), "doesnotexist", types.ContainerRemoveOptions{}) assert.ErrorContains(c, err, "No such container: doesnotexist") } @@ -1139,7 +1142,7 @@ func (s *DockerAPISuite) TestContainerAPIDeleteForce(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRemove(context.Background(), id, removeOptions) + err = apiClient.ContainerRemove(testutil.GetContext(c), id, removeOptions) assert.NilError(c, err) } @@ -1167,7 +1170,7 @@ func (s *DockerAPISuite) TestContainerAPIDeleteRemoveLinks(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRemove(context.Background(), "tlink2/tlink1", removeOptions) + err = apiClient.ContainerRemove(testutil.GetContext(c), "tlink2/tlink1", removeOptions) assert.NilError(c, err) linksPostRm := inspectFieldJSON(c, id2, "HostConfig.Links") @@ -1201,7 +1204,7 @@ func (s *DockerAPISuite) TestContainerAPIDeleteRemoveVolume(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRemove(context.Background(), id, removeOptions) + err = apiClient.ContainerRemove(testutil.GetContext(c), id, removeOptions) assert.NilError(c, err) _, err = os.Stat(source) @@ -1216,7 +1219,7 @@ func (s *DockerAPISuite) TestContainerAPIChunkedEncoding(c *testing.T) { "OpenStdin": true, } - resp, _, err := request.Post("/containers/create", request.JSONBody(config), request.With(func(req *http.Request) error { + resp, _, err := request.Post(testutil.GetContext(c), "/containers/create", request.JSONBody(config), request.With(func(req *http.Request) error { // This is a cheat to make the http request do chunked encoding // Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite // https://golang.org/src/pkg/net/http/request.go?s=11980:12172 @@ -1238,7 +1241,7 @@ func (s *DockerAPISuite) TestContainerAPIPostContainerStop(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerStop(context.Background(), containerID, container.StopOptions{}) + err = apiClient.ContainerStop(testutil.GetContext(c), containerID, container.StopOptions{}) assert.NilError(c, err) assert.Assert(c, waitInspect(containerID, "{{ .State.Running }}", "false", 60*time.Second) == nil) } @@ -1255,7 +1258,7 @@ func (s *DockerAPISuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "echotest") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "echotest") assert.NilError(c, err) out, _ := dockerCmd(c, "start", "-a", "echotest") assert.Equal(c, strings.TrimSpace(out), "hello world") @@ -1265,7 +1268,7 @@ func (s *DockerAPISuite) TestPostContainerAPICreateWithStringOrSliceEntrypoint(c Entrypoint string Cmd []string }{"busybox", "echo", []string{"hello", "world"}} - _, _, err = request.Post("/containers/create?name=echotest2", request.JSONBody(config2)) + _, _, err = request.Post(testutil.GetContext(c), "/containers/create?name=echotest2", request.JSONBody(config2)) assert.NilError(c, err) out, _ = dockerCmd(c, "start", "-a", "echotest2") assert.Equal(c, strings.TrimSpace(out), "hello world") @@ -1282,7 +1285,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithStringOrSliceCmd(c *testing assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "echotest") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "echotest") assert.NilError(c, err) out, _ := dockerCmd(c, "start", "-a", "echotest") assert.Equal(c, strings.TrimSpace(out), "hello world") @@ -1292,7 +1295,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithStringOrSliceCmd(c *testing Entrypoint string Cmd string }{"busybox", "echo", "hello world"} - _, _, err = request.Post("/containers/create?name=echotest2", request.JSONBody(config2)) + _, _, err = request.Post(testutil.GetContext(c), "/containers/create?name=echotest2", request.JSONBody(config2)) assert.NilError(c, err) out, _ = dockerCmd(c, "start", "-a", "echotest2") assert.Equal(c, strings.TrimSpace(out), "hello world") @@ -1309,7 +1312,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c * CapAdd string CapDrop string }{"busybox", "NET_ADMIN", "cap_sys_admin"} - res, _, err := request.Post("/containers/create?name=capaddtest0", request.JSONBody(config)) + res, _, err := request.Post(testutil.GetContext(c), "/containers/create?name=capaddtest0", request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusCreated) @@ -1325,7 +1328,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c * assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config2, &hostConfig, &network.NetworkingConfig{}, nil, "capaddtest1") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config2, &hostConfig, &network.NetworkingConfig{}, nil, "capaddtest1") assert.NilError(c, err) } @@ -1339,7 +1342,7 @@ func (s *DockerAPISuite) TestContainerAPICreateNoHostConfig118(c *testing.T) { apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.18")) assert.NilError(c, err) - _, err = apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) } @@ -1368,7 +1371,7 @@ func (s *DockerAPISuite) TestPutContainerArchiveErrSymlinkInVolumeToReadOnlyRoot apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.20")) assert.NilError(c, err) - err = apiClient.CopyToContainer(context.Background(), cID, "/vol2/symlinkToAbsDir", nil, types.CopyToContainerOptions{}) + err = apiClient.CopyToContainer(testutil.GetContext(c), cID, "/vol2/symlinkToAbsDir", nil, types.CopyToContainerOptions{}) assert.ErrorContains(c, err, "container rootfs is marked read-only") } @@ -1390,7 +1393,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithWrongCpusetValues(c *testin } name := "wrong-cpuset-cpus" - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig1, &network.NetworkingConfig{}, nil, name) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig1, &network.NetworkingConfig{}, nil, name) expected := "Invalid value 1-42,, for cpuset cpus" assert.ErrorContains(c, err, expected) @@ -1400,7 +1403,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithWrongCpusetValues(c *testin }, } name = "wrong-cpuset-mems" - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig2, &network.NetworkingConfig{}, nil, name) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig2, &network.NetworkingConfig{}, nil, name) expected = "Invalid value 42-3,1-- for cpuset mems" assert.ErrorContains(c, err, expected) } @@ -1419,7 +1422,7 @@ func (s *DockerAPISuite) TestPostContainersCreateShmSizeNegative(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") assert.ErrorContains(c, err, "SHM size can not be less than 0") } @@ -1436,10 +1439,10 @@ func (s *DockerAPISuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *tes assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) - containerJSON, err := apiClient.ContainerInspect(context.Background(), ctr.ID) + containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) assert.NilError(c, err) assert.Equal(c, containerJSON.HostConfig.ShmSize, dconfig.DefaultShmSize) @@ -1463,10 +1466,10 @@ func (s *DockerAPISuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) - containerJSON, err := apiClient.ContainerInspect(context.Background(), ctr.ID) + containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) assert.NilError(c, err) assert.Equal(c, containerJSON.HostConfig.ShmSize, int64(67108864)) @@ -1494,10 +1497,10 @@ func (s *DockerAPISuite) TestPostContainersCreateWithShmSize(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) - containerJSON, err := apiClient.ContainerInspect(context.Background(), ctr.ID) + containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) assert.NilError(c, err) assert.Equal(c, containerJSON.HostConfig.ShmSize, int64(1073741824)) @@ -1520,10 +1523,10 @@ func (s *DockerAPISuite) TestPostContainersCreateMemorySwappinessHostConfigOmitt assert.NilError(c, err) defer apiClient.Close() - ctr, err := apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") + ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "") assert.NilError(c, err) - containerJSON, err := apiClient.ContainerInspect(context.Background(), ctr.ID) + containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.31") { @@ -1551,7 +1554,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c * defer apiClient.Close() name := "oomscoreadj-over" - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, name) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, name) expected := "Invalid value 1001, range for oom score adj is [-1000, 1000]" assert.ErrorContains(c, err, expected) @@ -1561,7 +1564,7 @@ func (s *DockerAPISuite) TestPostContainersCreateWithOomScoreAdjInvalidRange(c * } name = "oomscoreadj-low" - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, name) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, name) expected = "Invalid value -1001, range for oom score adj is [-1000, 1000]" assert.ErrorContains(c, err, expected) @@ -1573,7 +1576,7 @@ func (s *DockerAPISuite) TestContainerAPIDeleteWithEmptyName(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - err = apiClient.ContainerRemove(context.Background(), "", types.ContainerRemoveOptions{}) + err = apiClient.ContainerRemove(testutil.GetContext(c), "", types.ContainerRemoveOptions{}) assert.Check(c, errdefs.IsNotFound(err)) } @@ -1593,10 +1596,10 @@ func (s *DockerAPISuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, name) assert.NilError(c, err) - err = apiClient.ContainerStart(context.Background(), name, types.ContainerStartOptions{}) + err = apiClient.ContainerStart(testutil.GetContext(c), name, types.ContainerStartOptions{}) assert.NilError(c, err) assert.Assert(c, waitRun(name) == nil) @@ -1607,7 +1610,7 @@ func (s *DockerAPISuite) TestContainerAPIStatsWithNetworkDisabled(c *testing.T) } bc := make(chan b, 1) go func() { - stats, err := apiClient.ContainerStats(context.Background(), name, false) + stats, err := apiClient.ContainerStats(testutil.GetContext(c), name, false) bc <- b{stats, err} }() @@ -1931,7 +1934,7 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsValidation(c *testing.T) { for i, x := range cases { x := x c.Run(fmt.Sprintf("case %d", i), func(c *testing.T) { - _, err = apiClient.ContainerCreate(context.Background(), &x.config, &x.hostConfig, &network.NetworkingConfig{}, nil, "") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &x.config, &x.hostConfig, &network.NetworkingConfig{}, nil, "") if len(x.msg) > 0 { assert.ErrorContains(c, err, x.msg, "%v", cases[i].config) } else { @@ -1964,7 +1967,7 @@ func (s *DockerAPISuite) TestContainerAPICreateMountsBindRead(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "test") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "test") assert.NilError(c, err) out, _ := dockerCmd(c, "start", "-a", "test") @@ -2099,7 +2102,7 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsCreate(c *testing.T) { }...) } - ctx := context.Background() + ctx := testutil.GetContext(c) apiclient := testEnv.APIClient() for i, x := range cases { x := x @@ -2138,7 +2141,7 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsCreate(c *testing.T) { err = apiclient.ContainerStart(ctx, ctr.ID, types.ContainerStartOptions{}) assert.NilError(c, err) - poll.WaitOn(c, containerExit(apiclient, ctr.ID), poll.WithDelay(time.Second)) + poll.WaitOn(c, containerExit(ctx, apiclient, ctr.ID), poll.WithDelay(time.Second)) err = apiclient.ContainerRemove(ctx, ctr.ID, types.ContainerRemoveOptions{ RemoveVolumes: true, @@ -2164,9 +2167,9 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsCreate(c *testing.T) { } } -func containerExit(apiclient client.APIClient, name string) func(poll.LogT) poll.Result { +func containerExit(ctx context.Context, apiclient client.APIClient, name string) func(poll.LogT) poll.Result { return func(logT poll.LogT) poll.Result { - ctr, err := apiclient.ContainerInspect(context.Background(), name) + ctr, err := apiclient.ContainerInspect(ctx, name) if err != nil { return poll.Error(err) } @@ -2219,7 +2222,7 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsTmpfs(c *testing.T) { Mounts: []mount.Mount{x.cfg}, } - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, cName) + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, cName) assert.NilError(c, err) out, _ := dockerCmd(c, "start", "-a", cName) for _, option := range x.expectedOptions { @@ -2233,7 +2236,7 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsTmpfs(c *testing.T) { // gets killed (with SIGKILL) by the kill API, that the restart policy is cancelled. func (s *DockerAPISuite) TestContainerKillCustomStopSignal(c *testing.T) { id := strings.TrimSpace(runSleepingContainer(c, "--stop-signal=SIGTERM", "--restart=always")) - res, _, err := request.Post("/containers/" + id + "/kill") + res, _, err := request.Post(testutil.GetContext(c), "/containers/"+id+"/kill") assert.NilError(c, err) defer res.Body.Close() diff --git a/integration-cli/docker_api_containers_windows_test.go b/integration-cli/docker_api_containers_windows_test.go index 4512992d39..d19865265c 100644 --- a/integration-cli/docker_api_containers_windows_test.go +++ b/integration-cli/docker_api_containers_windows_test.go @@ -3,7 +3,6 @@ package main import ( - "context" "fmt" "io" "math/rand" @@ -14,6 +13,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/mount" + "github.com/docker/docker/testutil" "github.com/pkg/errors" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -48,7 +48,7 @@ func (s *DockerAPISuite) TestContainersAPICreateMountsBindNamedPipe(c *testing.T cmd := fmt.Sprintf("echo %s > %s", text, containerPipeName) name := "test-bind-npipe" - ctx := context.Background() + ctx := testutil.GetContext(c) client := testEnv.APIClient() _, err = client.ContainerCreate(ctx, &container.Config{ diff --git a/integration-cli/docker_api_exec_resize_test.go b/integration-cli/docker_api_exec_resize_test.go index 21eddc4e11..c1d5edf2fd 100644 --- a/integration-cli/docker_api_exec_resize_test.go +++ b/integration-cli/docker_api_exec_resize_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "github.com/pkg/errors" "gotest.tools/v3/assert" @@ -22,7 +23,7 @@ func (s *DockerAPISuite) TestExecResizeAPIHeightWidthNoInt(c *testing.T) { cleanedContainerID := strings.TrimSpace(out) endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar" - res, _, err := request.Post(endpoint) + res, _, err := request.Post(testutil.GetContext(c), endpoint) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusInternalServerError) @@ -42,7 +43,7 @@ func (s *DockerAPISuite) TestExecResizeImmediatelyAfterExecStart(c *testing.T) { "Cmd": []string{"/bin/sh"}, } uri := fmt.Sprintf("/containers/%s/exec", name) - res, body, err := request.Post(uri, request.JSONBody(data)) + res, body, err := request.Post(testutil.GetContext(c), uri, request.JSONBody(data)) if err != nil { return err } @@ -71,7 +72,7 @@ func (s *DockerAPISuite) TestExecResizeImmediatelyAfterExecStart(c *testing.T) { } defer wc.Close() - _, rc, err := request.Post(fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), request.ContentType("text/plain")) + _, rc, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), request.ContentType("text/plain")) if err != nil { // It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned. if err == io.ErrUnexpectedEOF { diff --git a/integration-cli/docker_api_exec_test.go b/integration-cli/docker_api_exec_test.go index 131061b04d..6a015e6645 100644 --- a/integration-cli/docker_api_exec_test.go +++ b/integration-cli/docker_api_exec_test.go @@ -16,6 +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/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -27,7 +28,7 @@ func (s *DockerAPISuite) TestExecAPICreateNoCmd(c *testing.T) { name := "exec_test" dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh") - res, body, err := request.Post(fmt.Sprintf("/containers/%s/exec", name), request.JSONBody(map[string]interface{}{"Cmd": nil})) + res, body, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/containers/%s/exec", name), request.JSONBody(map[string]interface{}{"Cmd": nil})) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusInternalServerError) @@ -48,7 +49,7 @@ func (s *DockerAPISuite) TestExecAPICreateNoValidContentType(c *testing.T) { c.Fatalf("Can not encode data to json %s", err) } - res, body, err := request.Post(fmt.Sprintf("/containers/%s/exec", name), request.RawContent(io.NopCloser(jsonData)), request.ContentType("test/plain")) + res, body, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/containers/%s/exec", name), request.RawContent(io.NopCloser(jsonData)), request.ContentType("test/plain")) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, res.StatusCode, http.StatusInternalServerError) @@ -75,7 +76,7 @@ func (s *DockerAPISuite) TestExecAPICreateContainerPaused(c *testing.T) { config := types.ExecConfig{ Cmd: []string{"true"}, } - _, err = apiClient.ContainerExecCreate(context.Background(), name, config) + _, err = apiClient.ContainerExecCreate(testutil.GetContext(c), name, config) assert.ErrorContains(c, err, "Container "+name+" is paused, unpause the container before exec", "Expected message when creating exec command with Container %s is paused", name) } @@ -87,7 +88,7 @@ func (s *DockerAPISuite) TestExecAPIStart(c *testing.T) { startExec(c, id, http.StatusOK) var execJSON struct{ PID int } - inspectExec(c, id, &execJSON) + inspectExec(testutil.GetContext(c), c, id, &execJSON) assert.Assert(c, execJSON.PID > 1) id = createExec(c, "test") @@ -111,7 +112,7 @@ func (s *DockerAPISuite) TestExecAPIStartEnsureHeaders(c *testing.T) { dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top") id := createExec(c, "test") - resp, _, err := request.Post(fmt.Sprintf("/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.JSON) + resp, _, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.JSON) assert.NilError(c, err) assert.Assert(c, resp.Header.Get("Server") != "") } @@ -121,7 +122,7 @@ func (s *DockerAPISuite) TestExecAPIStartBackwardsCompatible(c *testing.T) { runSleepingContainer(c, "-d", "--name", "test") id := createExec(c, "test") - resp, body, err := request.Post(fmt.Sprintf("/v1.20/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.ContentType("text/plain")) + resp, body, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/v1.20/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.ContentType("text/plain")) assert.NilError(c, err) b, err := request.ReadBody(body) @@ -135,7 +136,7 @@ func (s *DockerAPISuite) TestExecAPIStartMultipleTimesError(c *testing.T) { runSleepingContainer(c, "-d", "--name", "test") execID := createExec(c, "test") startExec(c, execID, http.StatusOK) - waitForExec(c, execID) + waitForExec(testutil.GetContext(c), c, execID) startExec(c, execID, http.StatusConflict) } @@ -145,6 +146,8 @@ func (s *DockerAPISuite) TestExecAPIStartWithDetach(c *testing.T) { name := "foo" runSleepingContainer(c, "-d", "-t", "--name", name) + ctx := testutil.GetContext(c) + config := types.ExecConfig{ Cmd: []string{"true"}, AttachStderr: true, @@ -154,17 +157,17 @@ func (s *DockerAPISuite) TestExecAPIStartWithDetach(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - createResp, err := apiClient.ContainerExecCreate(context.Background(), name, config) + createResp, err := apiClient.ContainerExecCreate(ctx, name, config) assert.NilError(c, err) - _, body, err := request.Post(fmt.Sprintf("/exec/%s/start", createResp.ID), request.RawString(`{"Detach": true}`), request.JSON) + _, body, err := request.Post(ctx, fmt.Sprintf("/exec/%s/start", createResp.ID), request.RawString(`{"Detach": true}`), request.JSON) assert.NilError(c, err) b, err := request.ReadBody(body) comment := fmt.Sprintf("response body: %s", b) assert.NilError(c, err, comment) - resp, _, err := request.Get("/_ping") + resp, _, err := request.Get(ctx, "/_ping") assert.NilError(c, err) if resp.StatusCode != http.StatusOK { c.Fatal("daemon is down, it should alive") @@ -179,10 +182,11 @@ func (s *DockerAPISuite) TestExecAPIStartValidCommand(c *testing.T) { id := createExecCmd(c, name, "true") startExec(c, id, http.StatusOK) - waitForExec(c, id) + ctx := testutil.GetContext(c) + waitForExec(ctx, c, id) var inspectJSON struct{ ExecIDs []string } - inspectContainer(c, name, &inspectJSON) + inspectContainer(ctx, c, name, &inspectJSON) assert.Assert(c, inspectJSON.ExecIDs == nil) } @@ -198,10 +202,11 @@ func (s *DockerAPISuite) TestExecAPIStartInvalidCommand(c *testing.T) { } else { startExec(c, id, http.StatusBadRequest) } - waitForExec(c, id) + ctx := testutil.GetContext(c) + waitForExec(ctx, c, id) var inspectJSON struct{ ExecIDs []string } - inspectContainer(c, name, &inspectJSON) + inspectContainer(ctx, c, name, &inspectJSON) assert.Assert(c, inspectJSON.ExecIDs == nil) } @@ -229,13 +234,15 @@ func (s *DockerAPISuite) TestExecStateCleanup(c *testing.T) { id := createExecCmd(c, name, "ls") startExec(c, id, http.StatusOK) - waitForExec(c, id) + + ctx := testutil.GetContext(c) + waitForExec(ctx, c, id) poll.WaitOn(c, pollCheck(c, checkReadDir, checker.Equals(len(fi))), poll.WithTimeout(5*time.Second)) id = createExecCmd(c, name, "invalid") startExec(c, id, http.StatusBadRequest) - waitForExec(c, id) + waitForExec(ctx, c, id) poll.WaitOn(c, pollCheck(c, checkReadDir, checker.Equals(len(fi))), poll.WithTimeout(5*time.Second)) @@ -250,7 +257,7 @@ func createExec(c *testing.T, name string) string { } func createExecCmd(c *testing.T, name string, cmd string) string { - _, reader, err := request.Post(fmt.Sprintf("/containers/%s/exec", name), request.JSONBody(map[string]interface{}{"Cmd": []string{cmd}})) + _, reader, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/containers/%s/exec", name), request.JSONBody(map[string]interface{}{"Cmd": []string{cmd}})) assert.NilError(c, err) b, err := io.ReadAll(reader) assert.NilError(c, err) @@ -263,7 +270,7 @@ func createExecCmd(c *testing.T, name string, cmd string) string { } func startExec(c *testing.T, id string, code int) { - resp, body, err := request.Post(fmt.Sprintf("/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.JSON) + resp, body, err := request.Post(testutil.GetContext(c), fmt.Sprintf("/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.JSON) assert.NilError(c, err) b, err := request.ReadBody(body) @@ -271,8 +278,8 @@ func startExec(c *testing.T, id string, code int) { assert.Equal(c, resp.StatusCode, code, "response body: %s", b) } -func inspectExec(c *testing.T, id string, out interface{}) { - resp, body, err := request.Get(fmt.Sprintf("/exec/%s/json", id)) +func inspectExec(ctx context.Context, c *testing.T, id string, out interface{}) { + resp, body, err := request.Get(ctx, fmt.Sprintf("/exec/%s/json", id)) assert.NilError(c, err) defer body.Close() assert.Equal(c, resp.StatusCode, http.StatusOK) @@ -280,7 +287,7 @@ func inspectExec(c *testing.T, id string, out interface{}) { assert.NilError(c, err) } -func waitForExec(c *testing.T, id string) { +func waitForExec(ctx context.Context, c *testing.T, id string) { timeout := time.After(60 * time.Second) var execJSON struct{ Running bool } for { @@ -290,15 +297,15 @@ func waitForExec(c *testing.T, id string) { default: } - inspectExec(c, id, &execJSON) + inspectExec(ctx, c, id, &execJSON) if !execJSON.Running { break } } } -func inspectContainer(c *testing.T, id string, out interface{}) { - resp, body, err := request.Get("/containers/" + id + "/json") +func inspectContainer(ctx context.Context, c *testing.T, id string, out interface{}) { + resp, body, err := request.Get(ctx, "/containers/"+id+"/json") assert.NilError(c, err) defer body.Close() assert.Equal(c, resp.StatusCode, http.StatusOK) diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index f22afb4034..8846761c84 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -1,7 +1,6 @@ package main import ( - "context" "net/http" "net/http/httptest" "strings" @@ -11,6 +10,7 @@ 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/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" ) @@ -20,14 +20,15 @@ func (s *DockerAPISuite) TestAPIImagesSaveAndLoad(c *testing.T) { buildImageSuccessfully(c, "saveandload", build.WithDockerfile("FROM busybox\nENV FOO bar")) id := getIDByName(c, "saveandload") - res, body, err := request.Get("/images/" + id + "/get") + ctx := testutil.GetContext(c) + res, body, err := request.Get(ctx, "/images/"+id+"/get") assert.NilError(c, err) defer body.Close() assert.Equal(c, res.StatusCode, http.StatusOK) dockerCmd(c, "rmi", id) - res, loadBody, err := request.Post("/images/load", request.RawContent(body), request.ContentType("application/x-tar")) + res, loadBody, err := request.Post(ctx, "/images/load", request.RawContent(body), request.ContentType("application/x-tar")) assert.NilError(c, err) defer loadBody.Close() assert.Equal(c, res.StatusCode, http.StatusOK) @@ -50,13 +51,13 @@ func (s *DockerAPISuite) TestAPIImagesDelete(c *testing.T) { dockerCmd(c, "tag", name, "test:tag1") - _, err = apiClient.ImageRemove(context.Background(), id, types.ImageRemoveOptions{}) + _, err = apiClient.ImageRemove(testutil.GetContext(c), id, types.ImageRemoveOptions{}) assert.ErrorContains(c, err, "unable to delete") - _, err = apiClient.ImageRemove(context.Background(), "test:noexist", types.ImageRemoveOptions{}) + _, err = apiClient.ImageRemove(testutil.GetContext(c), "test:noexist", types.ImageRemoveOptions{}) assert.ErrorContains(c, err, "No such image") - _, err = apiClient.ImageRemove(context.Background(), "test:tag1", types.ImageRemoveOptions{}) + _, err = apiClient.ImageRemove(testutil.GetContext(c), "test:tag1", types.ImageRemoveOptions{}) assert.NilError(c, err) } @@ -72,7 +73,7 @@ func (s *DockerAPISuite) TestAPIImagesHistory(c *testing.T) { buildImageSuccessfully(c, name, build.WithDockerfile("FROM busybox\nENV FOO bar")) id := getIDByName(c, name) - historydata, err := apiClient.ImageHistory(context.Background(), id) + historydata, err := apiClient.ImageHistory(testutil.GetContext(c), id) assert.NilError(c, err) assert.Assert(c, len(historydata) != 0) @@ -102,8 +103,9 @@ func (s *DockerAPISuite) TestAPIImagesImportBadSrc(c *testing.T) { {http.StatusInternalServerError, "%2Fdata%2Ffile.tar"}, } + ctx := testutil.GetContext(c) for _, te := range tt { - res, _, err := request.Post(strings.Join([]string{"/images/create?fromSrc=", te.fromSrc}, ""), request.JSON) + res, _, err := request.Post(ctx, strings.Join([]string{"/images/create?fromSrc=", te.fromSrc}, ""), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, te.statusExp) assert.Equal(c, res.Header.Get("Content-Type"), "application/json") @@ -114,7 +116,7 @@ func (s *DockerAPISuite) TestAPIImagesImportBadSrc(c *testing.T) { func (s *DockerAPISuite) TestAPIImagesSearchJSONContentType(c *testing.T) { testRequires(c, Network) - res, b, err := request.Get("/images/search?term=test", request.JSON) + res, b, err := request.Get(testutil.GetContext(c), "/images/search?term=test", request.JSON) assert.NilError(c, err) b.Close() assert.Equal(c, res.StatusCode, http.StatusOK) @@ -127,7 +129,7 @@ func (s *DockerAPISuite) TestAPIImagesSizeCompatibility(c *testing.T) { apiclient := testEnv.APIClient() defer apiclient.Close() - images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{}) + images, err := apiclient.ImageList(testutil.GetContext(c), types.ImageListOptions{}) assert.NilError(c, err) assert.Assert(c, len(images) != 0) for _, image := range images { @@ -138,7 +140,7 @@ func (s *DockerAPISuite) TestAPIImagesSizeCompatibility(c *testing.T) { assert.NilError(c, err) defer apiclient.Close() - v124Images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{}) + v124Images, err := apiclient.ImageList(testutil.GetContext(c), types.ImageListOptions{}) assert.NilError(c, err) assert.Assert(c, len(v124Images) != 0) for _, image := range v124Images { diff --git a/integration-cli/docker_api_inspect_test.go b/integration-cli/docker_api_inspect_test.go index 77727bd78c..a946afe404 100644 --- a/integration-cli/docker_api_inspect_test.go +++ b/integration-cli/docker_api_inspect_test.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/json" "strings" "testing" @@ -9,6 +8,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions/v1p20" "github.com/docker/docker/client" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -111,7 +111,7 @@ func (s *DockerAPISuite) TestInspectAPIImageResponse(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - imageJSON, _, err := apiClient.ImageInspectWithRaw(context.Background(), "busybox") + imageJSON, _, err := apiClient.ImageInspectWithRaw(testutil.GetContext(c), "busybox") assert.NilError(c, err) assert.Check(c, len(imageJSON.RepoTags) == 2) diff --git a/integration-cli/docker_api_logs_test.go b/integration-cli/docker_api_logs_test.go index 2fdd60719f..69fbe73de8 100644 --- a/integration-cli/docker_api_logs_test.go +++ b/integration-cli/docker_api_logs_test.go @@ -3,7 +3,6 @@ package main import ( "bufio" "bytes" - "context" "fmt" "io" "net/http" @@ -15,6 +14,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" ) @@ -30,7 +30,7 @@ func (s *DockerAPISuite) TestLogsAPIWithStdout(c *testing.T) { } chLog := make(chan logOut, 1) - res, body, err := request.Get(fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1×tamps=1", id)) + res, body, err := request.Get(testutil.GetContext(c), fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1×tamps=1", id)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) @@ -62,7 +62,7 @@ func (s *DockerAPISuite) TestLogsAPINoStdoutNorStderr(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{}) + _, err = apiClient.ContainerLogs(testutil.GetContext(c), name, types.ContainerLogsOptions{}) assert.ErrorContains(c, err, "Bad parameters: you must choose at least one stream") } @@ -72,7 +72,7 @@ func (s *DockerAPISuite) TestLogsAPIFollowEmptyOutput(c *testing.T) { t0 := time.Now() dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "sleep", "10") - _, body, err := request.Get(fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name)) + _, body, err := request.Get(testutil.GetContext(c), fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name)) t1 := time.Now() assert.NilError(c, err) body.Close() @@ -84,7 +84,7 @@ func (s *DockerAPISuite) TestLogsAPIFollowEmptyOutput(c *testing.T) { func (s *DockerAPISuite) TestLogsAPIContainerNotFound(c *testing.T) { name := "nonExistentContainer" - resp, _, err := request.Get(fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name)) + resp, _, err := request.Get(testutil.GetContext(c), fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&stderr=1&tail=all", name)) assert.NilError(c, err) assert.Equal(c, resp.StatusCode, http.StatusNotFound) } @@ -106,7 +106,7 @@ func (s *DockerAPISuite) TestLogsAPIUntilFutureFollow(c *testing.T) { } cfg := types.ContainerLogsOptions{Until: until.Format(time.RFC3339Nano), Follow: true, ShowStdout: true, Timestamps: true} - reader, err := client.ContainerLogs(context.Background(), name, cfg) + reader, err := client.ContainerLogs(testutil.GetContext(c), name, cfg) assert.NilError(c, err) type logOut struct { @@ -168,7 +168,7 @@ func (s *DockerAPISuite) TestLogsAPIUntil(c *testing.T) { } extractBody := func(c *testing.T, cfg types.ContainerLogsOptions) []string { - reader, err := client.ContainerLogs(context.Background(), name, cfg) + reader, err := client.ContainerLogs(testutil.GetContext(c), name, cfg) assert.NilError(c, err) actualStdout := new(bytes.Buffer) @@ -205,7 +205,7 @@ func (s *DockerAPISuite) TestLogsAPIUntilDefaultValue(c *testing.T) { } extractBody := func(c *testing.T, cfg types.ContainerLogsOptions) []string { - reader, err := client.ContainerLogs(context.Background(), name, cfg) + reader, err := client.ContainerLogs(testutil.GetContext(c), name, cfg) assert.NilError(c, err) actualStdout := new(bytes.Buffer) diff --git a/integration-cli/docker_api_network_test.go b/integration-cli/docker_api_network_test.go index 12a492a5a5..a485ba2aae 100644 --- a/integration-cli/docker_api_network_test.go +++ b/integration-cli/docker_api_network_test.go @@ -13,6 +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/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" ) @@ -268,7 +269,7 @@ func createDeletePredefinedNetwork(c *testing.T, name string) { } func isNetworkAvailable(c *testing.T, name string) bool { - resp, body, err := request.Get("/networks") + resp, body, err := request.Get(testutil.GetContext(c), "/networks") assert.NilError(c, err) defer resp.Body.Close() assert.Equal(c, resp.StatusCode, http.StatusOK) @@ -291,7 +292,7 @@ func getNetworkIDByName(c *testing.T, name string) string { v := url.Values{} v.Set("filters", filterJSON) - resp, body, err := request.Get("/networks?" + v.Encode()) + resp, body, err := request.Get(testutil.GetContext(c), "/networks?"+v.Encode()) assert.Equal(c, resp.StatusCode, http.StatusOK) assert.NilError(c, err) @@ -311,7 +312,7 @@ func getNetworkIDByName(c *testing.T, name string) string { } func getNetworkResource(c *testing.T, id string) *types.NetworkResource { - _, obj, err := request.Get("/networks/" + id) + _, obj, err := request.Get(testutil.GetContext(c), "/networks/"+id) assert.NilError(c, err) nr := types.NetworkResource{} @@ -322,7 +323,7 @@ func getNetworkResource(c *testing.T, id string) *types.NetworkResource { } func createNetwork(c *testing.T, config types.NetworkCreateRequest, expectedStatusCode int) string { - resp, body, err := request.Post("/networks/create", request.JSONBody(config)) + resp, body, err := request.Post(testutil.GetContext(c), "/networks/create", request.JSONBody(config)) assert.NilError(c, err) defer resp.Body.Close() @@ -347,7 +348,7 @@ func connectNetwork(c *testing.T, nid, cid string) { Container: cid, } - resp, _, err := request.Post("/networks/"+nid+"/connect", request.JSONBody(config)) + resp, _, err := request.Post(testutil.GetContext(c), "/networks/"+nid+"/connect", request.JSONBody(config)) assert.Equal(c, resp.StatusCode, http.StatusOK) assert.NilError(c, err) } @@ -357,13 +358,13 @@ func disconnectNetwork(c *testing.T, nid, cid string) { Container: cid, } - resp, _, err := request.Post("/networks/"+nid+"/disconnect", request.JSONBody(config)) + resp, _, err := request.Post(testutil.GetContext(c), "/networks/"+nid+"/disconnect", request.JSONBody(config)) assert.Equal(c, resp.StatusCode, http.StatusOK) assert.NilError(c, err) } func deleteNetwork(c *testing.T, id string, shouldSucceed bool) { - resp, _, err := request.Delete("/networks/" + id) + resp, _, err := request.Delete(testutil.GetContext(c), "/networks/"+id) assert.NilError(c, err) defer resp.Body.Close() if !shouldSucceed { diff --git a/integration-cli/docker_api_stats_test.go b/integration-cli/docker_api_stats_test.go index deccac6734..f85160cdc4 100644 --- a/integration-cli/docker_api_stats_test.go +++ b/integration-cli/docker_api_stats_test.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/json" "fmt" "net/http" @@ -17,6 +16,7 @@ import ( "github.com/docker/docker/api/types/system" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" "gotest.tools/v3/skip" @@ -30,7 +30,7 @@ func (s *DockerAPISuite) TestAPIStatsNoStreamGetCpu(c *testing.T) { id := strings.TrimSpace(out) assert.NilError(c, waitRun(id)) - resp, body, err := request.Get(fmt.Sprintf("/containers/%s/stats?stream=false", id)) + resp, body, err := request.Get(testutil.GetContext(c), fmt.Sprintf("/containers/%s/stats?stream=false", id)) assert.NilError(c, err) assert.Equal(c, resp.StatusCode, http.StatusOK) assert.Equal(c, resp.Header.Get("Content-Type"), "application/json") @@ -70,7 +70,7 @@ func (s *DockerAPISuite) TestAPIStatsStoppedContainerInGoroutines(c *testing.T) id := strings.TrimSpace(out) getGoRoutines := func() int { - _, body, err := request.Get("/info") + _, body, err := request.Get(testutil.GetContext(c), "/info") assert.NilError(c, err) info := system.Info{} err = json.NewDecoder(body).Decode(&info) @@ -81,7 +81,7 @@ func (s *DockerAPISuite) TestAPIStatsStoppedContainerInGoroutines(c *testing.T) // When the HTTP connection is closed, the number of goroutines should not increase. routines := getGoRoutines() - _, body, err := request.Get("/containers/" + id + "/stats") + _, body, err := request.Get(testutil.GetContext(c), "/containers/"+id+"/stats") assert.NilError(c, err) body.Close() @@ -194,7 +194,7 @@ func (s *DockerAPISuite) TestAPIStatsNetworkStatsVersioning(c *testing.T) { func getNetworkStats(c *testing.T, id string) map[string]types.NetworkStats { var st *types.StatsJSON - _, body, err := request.Get("/containers/" + id + "/stats?stream=false") + _, body, err := request.Get(testutil.GetContext(c), "/containers/"+id+"/stats?stream=false") assert.NilError(c, err) err = json.NewDecoder(body).Decode(&st) @@ -211,7 +211,7 @@ func getNetworkStats(c *testing.T, id string) map[string]types.NetworkStats { func getVersionedStats(c *testing.T, id string, apiVersion string) map[string]interface{} { stats := make(map[string]interface{}) - _, body, err := request.Get("/" + apiVersion + "/containers/" + id + "/stats?stream=false") + _, body, err := request.Get(testutil.GetContext(c), "/"+apiVersion+"/containers/"+id+"/stats?stream=false") assert.NilError(c, err) defer body.Close() @@ -269,9 +269,9 @@ func (s *DockerAPISuite) TestAPIStatsContainerNotFound(c *testing.T) { expected := "No such container: nonexistent" - _, err = apiClient.ContainerStats(context.Background(), "nonexistent", true) + _, err = apiClient.ContainerStats(testutil.GetContext(c), "nonexistent", true) assert.ErrorContains(c, err, expected) - _, err = apiClient.ContainerStats(context.Background(), "nonexistent", false) + _, err = apiClient.ContainerStats(testutil.GetContext(c), "nonexistent", false) assert.ErrorContains(c, err, expected) } @@ -288,7 +288,7 @@ func (s *DockerAPISuite) TestAPIStatsNoStreamConnectedContainers(c *testing.T) { ch := make(chan error, 1) go func() { - resp, body, err := request.Get("/containers/" + id2 + "/stats?stream=false") + resp, body, err := request.Get(testutil.GetContext(c), "/containers/"+id2+"/stats?stream=false") defer body.Close() if err != nil { ch <- err diff --git a/integration-cli/docker_api_swarm_node_test.go b/integration-cli/docker_api_swarm_node_test.go index 925b08dda5..dc9f5c712d 100644 --- a/integration-cli/docker_api_swarm_node_test.go +++ b/integration-cli/docker_api_swarm_node_test.go @@ -10,16 +10,18 @@ import ( "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" ) func (s *DockerSwarmSuite) TestAPISwarmListNodes(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) - d3 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) + d3 := s.AddDaemon(ctx, c, true, false) - nodes := d1.ListNodes(c) + nodes := d1.ListNodes(ctx, c) assert.Equal(c, len(nodes), 3, fmt.Sprintf("nodes: %#v", nodes)) loop0: @@ -34,34 +36,39 @@ loop0: } func (s *DockerSwarmSuite) TestAPISwarmNodeUpdate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) - nodes := d.ListNodes(c) + d := s.AddDaemon(ctx, c, true, true) - d.UpdateNode(c, nodes[0].ID, func(n *swarm.Node) { + nodes := d.ListNodes(ctx, c) + + d.UpdateNode(ctx, c, nodes[0].ID, func(n *swarm.Node) { n.Spec.Availability = swarm.NodeAvailabilityPause }) - n := d.GetNode(c, nodes[0].ID) + n := d.GetNode(ctx, c, nodes[0].ID) assert.Equal(c, n.Spec.Availability, swarm.NodeAvailabilityPause) } func (s *DockerSwarmSuite) TestAPISwarmNodeRemove(c *testing.T) { testRequires(c, Network) - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) - _ = s.AddDaemon(c, true, false) - nodes := d1.ListNodes(c) + ctx := testutil.GetContext(c) + + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) + _ = s.AddDaemon(ctx, c, true, false) + + nodes := d1.ListNodes(ctx, c) assert.Equal(c, len(nodes), 3, fmt.Sprintf("nodes: %#v", nodes)) // Getting the info so we can take the NodeID - d2Info := d2.SwarmInfo(c) + d2Info := d2.SwarmInfo(ctx, c) // forceful removal of d2 should work - d1.RemoveNode(c, d2Info.NodeID, true) + d1.RemoveNode(ctx, c, d2Info.NodeID, true) - nodes = d1.ListNodes(c) + nodes = d1.ListNodes(ctx, c) assert.Equal(c, len(nodes), 2, fmt.Sprintf("nodes: %#v", nodes)) // Restart the node that was removed @@ -71,57 +78,58 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeRemove(c *testing.T) { time.Sleep(1 * time.Second) // Make sure the node didn't rejoin - nodes = d1.ListNodes(c) + nodes = d1.ListNodes(ctx, c) assert.Equal(c, len(nodes), 2, fmt.Sprintf("nodes: %#v", nodes)) } func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks // start a service, expect balanced distribution instances := 2 - id := d1.CreateService(c, simpleTestService, setInstances(instances)) + id := d1.CreateService(ctx, c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // drain d2, all containers should move to d1 - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Availability = swarm.NodeAvailabilityDrain }) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) // set d2 back to active - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Availability = swarm.NodeAvailabilityActive }) instances = 1 - d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout*2)) + d1.UpdateService(ctx, c, d1.GetService(ctx, c, id), setInstances(instances)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout*2)) instances = 2 - d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) + d1.UpdateService(ctx, c, d1.GetService(ctx, c, id), setInstances(instances)) // drained node first so we don't get any old containers - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout*2)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout*2)) - d2ContainerCount := len(d2.ActiveContainers(c)) + d2ContainerCount := len(d2.ActiveContainers(testutil.GetContext(c), c)) // set d2 to paused, scale service up, only d1 gets new tasks - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Availability = swarm.NodeAvailabilityPause }) instances = 4 - d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances-d2ContainerCount)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(d2ContainerCount)), poll.WithTimeout(defaultReconciliationTimeout)) + d1.UpdateService(ctx, c, d1.GetService(ctx, c, id), setInstances(instances)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.Equals(instances-d2ContainerCount)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.Equals(d2ContainerCount)), poll.WithTimeout(defaultReconciliationTimeout)) } diff --git a/integration-cli/docker_api_swarm_service_test.go b/integration-cli/docker_api_swarm_service_test.go index a87ba4c942..d02a1a0291 100644 --- a/integration-cli/docker_api_swarm_service_test.go +++ b/integration-cli/docker_api_swarm_service_test.go @@ -3,7 +3,6 @@ package main import ( - "context" "fmt" "strconv" "strings" @@ -16,6 +15,7 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" testdaemon "github.com/docker/docker/testutil/daemon" "golang.org/x/sys/unix" "gotest.tools/v3/assert" @@ -33,20 +33,21 @@ func setPortConfig(portConfig []swarm.PortConfig) testdaemon.ServiceConstructor } func (s *DockerSwarmSuite) TestAPIServiceUpdatePort(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create a service with a port mapping of 8080:8081. portConfig := []swarm.PortConfig{{TargetPort: 8081, PublishedPort: 8080}} - serviceID := d.CreateService(c, simpleTestService, setInstances(1), setPortConfig(portConfig)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + serviceID := d.CreateService(ctx, c, simpleTestService, setInstances(1), setPortConfig(portConfig)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // Update the service: changed the port mapping from 8080:8081 to 8082:8083. updatedPortConfig := []swarm.PortConfig{{TargetPort: 8083, PublishedPort: 8082}} - remoteService := d.GetService(c, serviceID) - d.UpdateService(c, remoteService, setPortConfig(updatedPortConfig)) + remoteService := d.GetService(ctx, c, serviceID) + d.UpdateService(ctx, c, remoteService, setPortConfig(updatedPortConfig)) // Inspect the service and verify port mapping. - updatedService := d.GetService(c, serviceID) + updatedService := d.GetService(ctx, c, serviceID) assert.Assert(c, updatedService.Spec.EndpointSpec != nil) assert.Equal(c, len(updatedService.Spec.EndpointSpec.Ports), 1) assert.Equal(c, updatedService.Spec.EndpointSpec.Ports[0].TargetPort, uint32(8083)) @@ -54,19 +55,21 @@ func (s *DockerSwarmSuite) TestAPIServiceUpdatePort(c *testing.T) { } func (s *DockerSwarmSuite) TestAPISwarmServicesEmptyList(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) - services := d.ListServices(c) + services := d.ListServices(ctx, c) assert.Assert(c, services != nil) assert.Assert(c, len(services) == 0, "services: %#v", services) } func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) instances := 2 - id := d.CreateService(c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + id := d.CreateService(ctx, c, simpleTestService, setInstances(instances)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) client := d.NewClientT(c) defer client.Close() @@ -74,79 +77,82 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesCreate(c *testing.T) { options := types.ServiceInspectOptions{InsertDefaults: true} // insertDefaults inserts UpdateConfig when service is fetched by ID - resp, _, err := client.ServiceInspectWithRaw(context.Background(), id, options) + resp, _, err := client.ServiceInspectWithRaw(ctx, id, options) out := fmt.Sprintf("%+v", resp) assert.NilError(c, err) assert.Assert(c, strings.Contains(out, "UpdateConfig")) // insertDefaults inserts UpdateConfig when service is fetched by ID - resp, _, err = client.ServiceInspectWithRaw(context.Background(), "top", options) + resp, _, err = client.ServiceInspectWithRaw(ctx, "top", options) out = fmt.Sprintf("%+v", resp) assert.NilError(c, err) assert.Assert(c, strings.Contains(out, "UpdateConfig")) - service := d.GetService(c, id) + service := d.GetService(ctx, c, id) instances = 5 - d.UpdateService(c, service, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + d.UpdateService(ctx, c, service, setInstances(instances)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - d.RemoveService(c, service.ID) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) + d.RemoveService(ctx, c, service.ID) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmServicesMultipleAgents(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) - d3 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) + d3 := s.AddDaemon(ctx, c, true, false) time.Sleep(1 * time.Second) // make sure all daemons are ready to accept tasks instances := 9 - id := d1.CreateService(c, simpleTestService, setInstances(instances)) + id := d1.CreateService(ctx, c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d3.CheckActiveContainerCount, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d3.CheckActiveContainerCount(ctx), checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // reconciliation on d2 node down d2.Stop(c) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // test downscaling instances = 5 - d1.UpdateService(c, d1.GetService(c, id), setInstances(instances)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + d1.UpdateService(ctx, c, d1.GetService(ctx, c, id), setInstances(instances)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmServicesCreateGlobal(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) - d3 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) + d3 := s.AddDaemon(ctx, c, true, false) - d1.CreateService(c, simpleTestService, setGlobalMode) + d1.CreateService(ctx, c, simpleTestService, setGlobalMode) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d3.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d3.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) - d4 := s.AddDaemon(c, true, false) - d5 := s.AddDaemon(c, true, false) + d4 := s.AddDaemon(ctx, c, true, false) + d5 := s.AddDaemon(ctx, c, true, false) - poll.WaitOn(c, pollCheck(c, d4.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d5.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d4.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d5.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) { + ctx := testutil.GetContext(c) const nodeCount = 3 var daemons [nodeCount]*daemon.Daemon for i := 0; i < nodeCount; i++ { - daemons[i] = s.AddDaemon(c, true, i == 0) + daemons[i] = s.AddDaemon(ctx, c, true, i == 0) } // wait for nodes ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount(ctx), checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) // service image at start image1 := "busybox:latest" @@ -163,23 +169,23 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) { instances := 5 parallelism := 2 rollbackParallelism := 3 - id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances)) + id := daemons[0].CreateService(ctx, c, serviceForUpdate, setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) // issue service update - service := daemons[0].GetService(c, id) - daemons[0].UpdateService(c, service, setImage(image2)) + service := daemons[0].GetService(ctx, c, id) + daemons[0].UpdateService(ctx, c, service, setImage(image2)) // first batch - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // 2nd batch - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // 3nd batch - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image2: instances})), poll.WithTimeout(defaultReconciliationTimeout)) // Roll back to the previous version. This uses the CLI because // rollback used to be a client-side operation. @@ -187,14 +193,15 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdate(c *testing.T) { assert.NilError(c, err, out) // first batch - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // 2nd batch - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // service image at start image1 := "busybox:latest" @@ -213,12 +220,12 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) { instances := 5 parallelism := 2 rollbackParallelism := 3 - id := d.CreateService(c, serviceForUpdate, setInstances(instances), setUpdateOrder(swarm.UpdateOrderStartFirst), setRollbackOrder(swarm.UpdateOrderStartFirst)) + id := d.CreateService(ctx, c, serviceForUpdate, setInstances(instances), setUpdateOrder(swarm.UpdateOrderStartFirst), setRollbackOrder(swarm.UpdateOrderStartFirst)) checkStartingTasks := func(expected int) []swarm.Task { var startingTasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks := d.GetServiceTasks(c, id) + tasks := d.GetServiceTasks(ctx, c, id) startingTasks = nil for _, t := range tasks { if t.Status.State == swarm.TaskStateStarting { @@ -239,47 +246,47 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) { } // wait for tasks ready - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) // issue service update - service := d.GetService(c, id) - d.UpdateService(c, service, setImage(image2)) + service := d.GetService(ctx, c, id) + d.UpdateService(ctx, c, service, setImage(image2)) // first batch // The old tasks should be running, and the new ones should be starting. startingTasks := checkStartingTasks(parallelism) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) // make it healthy makeTasksHealthy(startingTasks) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // 2nd batch // The old tasks should be running, and the new ones should be starting. startingTasks = checkStartingTasks(parallelism) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances - parallelism, image2: parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // make it healthy makeTasksHealthy(startingTasks) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // 3nd batch // The old tasks should be running, and the new ones should be starting. startingTasks = checkStartingTasks(1) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances - 2*parallelism, image2: 2 * parallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // make it healthy makeTasksHealthy(startingTasks) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image2: instances})), poll.WithTimeout(defaultReconciliationTimeout)) // Roll back to the previous version. This uses the CLI because // rollback is a client-side operation. @@ -287,20 +294,21 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateStartFirst(c *testing.T) { assert.NilError(c, err, out) // first batch - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image2: instances - rollbackParallelism, image1: rollbackParallelism})), poll.WithTimeout(defaultReconciliationTimeout)) // 2nd batch - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) { + ctx := testutil.GetContext(c) const nodeCount = 3 var daemons [nodeCount]*daemon.Daemon for i := 0; i < nodeCount; i++ { - daemons[i] = s.AddDaemon(c, true, i == 0) + daemons[i] = s.AddDaemon(ctx, c, true, i == 0) } // wait for nodes ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount(ctx), checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) // service image at start image1 := "busybox:latest" @@ -309,18 +317,18 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) { // create service instances := 5 - id := daemons[0].CreateService(c, serviceForUpdate, setInstances(instances)) + id := daemons[0].CreateService(ctx, c, serviceForUpdate, setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) // issue service update - service := daemons[0].GetService(c, id) - daemons[0].UpdateService(c, service, setImage(image2), setFailureAction(swarm.UpdateFailureActionPause), setMaxFailureRatio(0.25), setParallelism(1)) + service := daemons[0].GetService(ctx, c, id) + daemons[0].UpdateService(ctx, c, service, setImage(image2), setFailureAction(swarm.UpdateFailureActionPause), setMaxFailureRatio(0.25), setParallelism(1)) // should update 2 tasks and then pause - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceUpdateState(id), checker.Equals(swarm.UpdateStatePaused)), poll.WithTimeout(defaultReconciliationTimeout)) - v, _ := daemons[0].CheckServiceRunningTasks(id)(c) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceUpdateState(ctx, id), checker.Equals(swarm.UpdateStatePaused)), poll.WithTimeout(defaultReconciliationTimeout)) + v, _ := daemons[0].CheckServiceRunningTasks(ctx, id)(c) assert.Assert(c, v == instances-2) // Roll back to the previous version. This uses the CLI because @@ -328,80 +336,82 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesFailedUpdate(c *testing.T) { out, err := daemons[0].Cmd("service", "update", "--detach", "--rollback", id) assert.NilError(c, err, out) - poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages, checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image1: instances})), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintRole(c *testing.T) { + ctx := testutil.GetContext(c) const nodeCount = 3 var daemons [nodeCount]*daemon.Daemon for i := 0; i < nodeCount; i++ { - daemons[i] = s.AddDaemon(c, true, i == 0) + daemons[i] = s.AddDaemon(ctx, c, true, i == 0) } // wait for nodes ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount(ctx), checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) // create service constraints := []string{"node.role==worker"} instances := 3 - id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id := daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // validate tasks are running on worker nodes - tasks := daemons[0].GetServiceTasks(c, id) + tasks := daemons[0].GetServiceTasks(ctx, c, id) for _, task := range tasks { - node := daemons[0].GetNode(c, task.NodeID) + node := daemons[0].GetNode(ctx, c, task.NodeID) assert.Equal(c, node.Spec.Role, swarm.NodeRoleWorker) } // remove service - daemons[0].RemoveService(c, id) + daemons[0].RemoveService(ctx, c, id) // create service constraints = []string{"node.role!=worker"} - id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id = daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - tasks = daemons[0].GetServiceTasks(c, id) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + tasks = daemons[0].GetServiceTasks(ctx, c, id) // validate tasks are running on manager nodes for _, task := range tasks { - node := daemons[0].GetNode(c, task.NodeID) + node := daemons[0].GetNode(ctx, c, task.NodeID) assert.Equal(c, node.Spec.Role, swarm.NodeRoleManager) } // remove service - daemons[0].RemoveService(c, id) + daemons[0].RemoveService(ctx, c, id) // create service constraints = []string{"node.role==nosuchrole"} - id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id = daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks created - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // let scheduler try time.Sleep(250 * time.Millisecond) // validate tasks are not assigned to any node - tasks = daemons[0].GetServiceTasks(c, id) + tasks = daemons[0].GetServiceTasks(ctx, c, id) for _, task := range tasks { assert.Equal(c, task.NodeID, "") } } func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) { + ctx := testutil.GetContext(c) const nodeCount = 3 var daemons [nodeCount]*daemon.Daemon for i := 0; i < nodeCount; i++ { - daemons[i] = s.AddDaemon(c, true, i == 0) + daemons[i] = s.AddDaemon(ctx, c, true, i == 0) } // wait for nodes ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) - nodes := daemons[0].ListNodes(c) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount(ctx), checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) + nodes := daemons[0].ListNodes(ctx, c) assert.Equal(c, len(nodes), nodeCount) // add labels to nodes - daemons[0].UpdateNode(c, nodes[0].ID, func(n *swarm.Node) { + daemons[0].UpdateNode(ctx, c, nodes[0].ID, func(n *swarm.Node) { n.Spec.Annotations.Labels = map[string]string{ "security": "high", } }) for i := 1; i < nodeCount; i++ { - daemons[0].UpdateNode(c, nodes[i].ID, func(n *swarm.Node) { + daemons[0].UpdateNode(ctx, c, nodes[i].ID, func(n *swarm.Node) { n.Spec.Annotations.Labels = map[string]string{ "security": "low", } @@ -411,92 +421,94 @@ func (s *DockerSwarmSuite) TestAPISwarmServiceConstraintLabel(c *testing.T) { // create service instances := 3 constraints := []string{"node.labels.security==high"} - id := daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id := daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - tasks := daemons[0].GetServiceTasks(c, id) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + tasks := daemons[0].GetServiceTasks(ctx, c, id) // validate all tasks are running on nodes[0] for _, task := range tasks { assert.Assert(c, task.NodeID == nodes[0].ID) } // remove service - daemons[0].RemoveService(c, id) + daemons[0].RemoveService(ctx, c, id) // create service constraints = []string{"node.labels.security!=high"} - id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id = daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - tasks = daemons[0].GetServiceTasks(c, id) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + tasks = daemons[0].GetServiceTasks(ctx, c, id) // validate all tasks are NOT running on nodes[0] for _, task := range tasks { assert.Assert(c, task.NodeID != nodes[0].ID) } // remove service - daemons[0].RemoveService(c, id) + daemons[0].RemoveService(ctx, c, id) constraints = []string{"node.labels.security==medium"} - id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id = daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks created - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // let scheduler try time.Sleep(250 * time.Millisecond) - tasks = daemons[0].GetServiceTasks(c, id) + tasks = daemons[0].GetServiceTasks(ctx, c, id) // validate tasks are not assigned for _, task := range tasks { assert.Assert(c, task.NodeID == "") } // remove service - daemons[0].RemoveService(c, id) + daemons[0].RemoveService(ctx, c, id) // multiple constraints constraints = []string{ "node.labels.security==high", fmt.Sprintf("node.id==%s", nodes[1].ID), } - id = daemons[0].CreateService(c, simpleTestService, setConstraints(constraints), setInstances(instances)) + id = daemons[0].CreateService(ctx, c, simpleTestService, setConstraints(constraints), setInstances(instances)) // wait for tasks created - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // let scheduler try time.Sleep(250 * time.Millisecond) - tasks = daemons[0].GetServiceTasks(c, id) + tasks = daemons[0].GetServiceTasks(ctx, c, id) // validate tasks are not assigned for _, task := range tasks { assert.Assert(c, task.NodeID == "") } // make nodes[1] fulfills the constraints - daemons[0].UpdateNode(c, nodes[1].ID, func(n *swarm.Node) { + daemons[0].UpdateNode(ctx, c, nodes[1].ID, func(n *swarm.Node) { n.Spec.Annotations.Labels = map[string]string{ "security": "high", } }) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - tasks = daemons[0].GetServiceTasks(c, id) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + tasks = daemons[0].GetServiceTasks(ctx, c, id) for _, task := range tasks { assert.Assert(c, task.NodeID == nodes[1].ID) } } func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *testing.T) { + ctx := testutil.GetContext(c) + const nodeCount = 3 var daemons [nodeCount]*daemon.Daemon for i := 0; i < nodeCount; i++ { - daemons[i] = s.AddDaemon(c, true, i == 0) + daemons[i] = s.AddDaemon(ctx, c, true, i == 0) } // wait for nodes ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount, checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) - nodes := daemons[0].ListNodes(c) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckNodeReadyCount(ctx), checker.Equals(nodeCount)), poll.WithTimeout(5*time.Second)) + nodes := daemons[0].ListNodes(ctx, c) assert.Equal(c, len(nodes), nodeCount) // add labels to nodes - daemons[0].UpdateNode(c, nodes[0].ID, func(n *swarm.Node) { + daemons[0].UpdateNode(ctx, c, nodes[0].ID, func(n *swarm.Node) { n.Spec.Annotations.Labels = map[string]string{ "rack": "a", } }) for i := 1; i < nodeCount; i++ { - daemons[0].UpdateNode(c, nodes[i].ID, func(n *swarm.Node) { + daemons[0].UpdateNode(ctx, c, nodes[i].ID, func(n *swarm.Node) { n.Spec.Annotations.Labels = map[string]string{ "rack": "b", } @@ -506,10 +518,10 @@ func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *testing.T) { // create service instances := 4 prefs := []swarm.PlacementPreference{{Spread: &swarm.SpreadOver{SpreadDescriptor: "node.labels.rack"}}} - id := daemons[0].CreateService(c, simpleTestService, setPlacementPrefs(prefs), setInstances(instances)) + id := daemons[0].CreateService(ctx, c, simpleTestService, setPlacementPrefs(prefs), setInstances(instances)) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - tasks := daemons[0].GetServiceTasks(c, id) + poll.WaitOn(c, pollCheck(c, daemons[0].CheckServiceRunningTasks(ctx, id), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + tasks := daemons[0].GetServiceTasks(ctx, c, id) // validate all tasks are running on nodes[0] tasksOnNode := make(map[string]int) for _, task := range tasks { @@ -523,22 +535,23 @@ func (s *DockerSwarmSuite) TestAPISwarmServicePlacementPrefs(c *testing.T) { func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon) testRequires(c, DaemonIsLinux) + ctx := testutil.GetContext(c) - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, false) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, false) time.Sleep(1 * time.Second) // make sure all daemons are ready to accept instances := 9 - d1.CreateService(c, simpleTestService, setInstances(instances)) + d1.CreateService(ctx, c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) getContainers := func() map[string]*daemon.Daemon { m := make(map[string]*daemon.Daemon) for _, d := range []*daemon.Daemon{d1, d2, d3} { - for _, id := range d.ActiveContainers(c) { + for _, id := range d.ActiveContainers(testutil.GetContext(c), c) { m[id] = d } } @@ -555,7 +568,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *testing.T) { _, err := containers[toRemove].Cmd("stop", toRemove) assert.NilError(c, err) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) containers2 := getContainers() assert.Assert(c, len(containers2) == instances) @@ -581,7 +594,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *testing.T) { time.Sleep(time.Second) // give some time to handle the signal - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) containers2 = getContainers() assert.Assert(c, len(containers2) == instances) diff --git a/integration-cli/docker_api_swarm_test.go b/integration-cli/docker_api_swarm_test.go index a7b0e50063..c7be7dd4da 100644 --- a/integration-cli/docker_api_swarm_test.go +++ b/integration-cli/docker_api_swarm_test.go @@ -24,6 +24,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" testdaemon "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/request" "github.com/moby/swarmkit/v2/ca" @@ -35,32 +36,33 @@ import ( var defaultReconciliationTimeout = 30 * time.Second func (s *DockerSwarmSuite) TestAPISwarmInit(c *testing.T) { + ctx := testutil.GetContext(c) // todo: should find a better way to verify that components are running than /info - d1 := s.AddDaemon(c, true, true) - info := d1.SwarmInfo(c) + d1 := s.AddDaemon(ctx, c, true, true) + info := d1.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, true) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) assert.Equal(c, info.Cluster.RootRotationInProgress, false) - d2 := s.AddDaemon(c, true, false) - info = d2.SwarmInfo(c) + d2 := s.AddDaemon(ctx, c, true, false) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, false) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) // Leaving cluster - assert.NilError(c, d2.SwarmLeave(c, false)) + assert.NilError(c, d2.SwarmLeave(ctx, c, false)) - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, false) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) - d2.SwarmJoin(c, swarm.JoinRequest{ + d2.SwarmJoin(ctx, c, swarm.JoinRequest{ ListenAddr: d1.SwarmListenAddr(), JoinToken: d1.JoinTokens(c).Worker, RemoteAddrs: []string{d1.SwarmListenAddr()}, }) - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, false) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) @@ -71,96 +73,98 @@ func (s *DockerSwarmSuite) TestAPISwarmInit(c *testing.T) { d1.StartNode(c) d2.StartNode(c) - info = d1.SwarmInfo(c) + info = d1.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, true) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, false) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) } func (s *DockerSwarmSuite) TestAPISwarmJoinToken(c *testing.T) { - d1 := s.AddDaemon(c, false, false) - d1.SwarmInit(c, swarm.InitRequest{}) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, false, false) + d1.SwarmInit(ctx, c, swarm.InitRequest{}) // todo: error message differs depending if some components of token are valid - d2 := s.AddDaemon(c, false, false) + d2 := s.AddDaemon(ctx, c, false, false) c2 := d2.NewClientT(c) - err := c2.SwarmJoin(context.Background(), swarm.JoinRequest{ + err := c2.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), RemoteAddrs: []string{d1.SwarmListenAddr()}, }) assert.ErrorContains(c, err, "join token is necessary") - info := d2.SwarmInfo(c) + info := d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) - err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{ + err = c2.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), JoinToken: "foobaz", RemoteAddrs: []string{d1.SwarmListenAddr()}, }) assert.ErrorContains(c, err, "invalid join token") - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) workerToken := d1.JoinTokens(c).Worker - d2.SwarmJoin(c, swarm.JoinRequest{ + d2.SwarmJoin(ctx, c, swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}, }) - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) - assert.NilError(c, d2.SwarmLeave(c, false)) - info = d2.SwarmInfo(c) + assert.NilError(c, d2.SwarmLeave(ctx, c, false)) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) // change tokens d1.RotateTokens(c) - err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{ + err = c2.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}, }) assert.ErrorContains(c, err, "join token is necessary") - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) workerToken = d1.JoinTokens(c).Worker - d2.SwarmJoin(c, swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}}) - info = d2.SwarmInfo(c) + d2.SwarmJoin(ctx, c, swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}}) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) - assert.NilError(c, d2.SwarmLeave(c, false)) - info = d2.SwarmInfo(c) + assert.NilError(c, d2.SwarmLeave(ctx, c, false)) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) // change spec, don't change tokens d1.UpdateSwarm(c, func(s *swarm.Spec) {}) - err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{ + err = c2.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), RemoteAddrs: []string{d1.SwarmListenAddr()}, }) assert.ErrorContains(c, err, "join token is necessary") - info = d2.SwarmInfo(c) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) - d2.SwarmJoin(c, swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}}) - info = d2.SwarmInfo(c) + d2.SwarmJoin(ctx, c, swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.SwarmListenAddr()}}) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) - assert.NilError(c, d2.SwarmLeave(c, false)) - info = d2.SwarmInfo(c) + assert.NilError(c, d2.SwarmLeave(ctx, c, false)) + info = d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) } func (s *DockerSwarmSuite) TestUpdateSwarmAddExternalCA(c *testing.T) { - d1 := s.AddDaemon(c, false, false) - d1.SwarmInit(c, swarm.InitRequest{}) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, false, false) + d1.SwarmInit(ctx, c, swarm.InitRequest{}) d1.UpdateSwarm(c, func(s *swarm.Spec) { s.CAConfig.ExternalCAs = []*swarm.ExternalCA{ { @@ -174,20 +178,21 @@ func (s *DockerSwarmSuite) TestUpdateSwarmAddExternalCA(c *testing.T) { }, } }) - info := d1.SwarmInfo(c) + info := d1.SwarmInfo(ctx, c) assert.Equal(c, len(info.Cluster.Spec.CAConfig.ExternalCAs), 2) assert.Equal(c, info.Cluster.Spec.CAConfig.ExternalCAs[0].CACert, "") assert.Equal(c, info.Cluster.Spec.CAConfig.ExternalCAs[1].CACert, "cacert") } func (s *DockerSwarmSuite) TestAPISwarmCAHash(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, false, false) splitToken := strings.Split(d1.JoinTokens(c).Worker, "-") splitToken[2] = "1kxftv4ofnc6mt30lmgipg6ngf9luhwqopfk1tz6bdmnkubg0e" replacementToken := strings.Join(splitToken, "-") c2 := d2.NewClientT(c) - err := c2.SwarmJoin(context.Background(), swarm.JoinRequest{ + err := c2.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), JoinToken: replacementToken, RemoteAddrs: []string{d1.SwarmListenAddr()}, @@ -196,25 +201,26 @@ func (s *DockerSwarmSuite) TestAPISwarmCAHash(c *testing.T) { } func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) { - d1 := s.AddDaemon(c, false, false) - d1.SwarmInit(c, swarm.InitRequest{}) - d2 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, false, false) + d1.SwarmInit(ctx, c, swarm.InitRequest{}) + d2 := s.AddDaemon(ctx, c, true, false) - info := d2.SwarmInfo(c) + info := d2.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, false) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Role = swarm.NodeRoleManager }) - poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable, checker.True()), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable(ctx), checker.True()), poll.WithTimeout(defaultReconciliationTimeout)) - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Role = swarm.NodeRoleWorker }) - poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable, checker.False()), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable(ctx), checker.False()), poll.WithTimeout(defaultReconciliationTimeout)) // Wait for the role to change to worker in the cert. This is partially // done because it's something worth testing in its own right, and @@ -235,10 +241,10 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) { }, checker.Equals("swarm-worker")), poll.WithTimeout(defaultReconciliationTimeout)) // Demoting last node should fail - node := d1.GetNode(c, d1.NodeID()) + node := d1.GetNode(ctx, c, d1.NodeID()) node.Spec.Role = swarm.NodeRoleWorker url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index) - res, body, err := request.Post(url, request.Host(d1.Sock()), request.JSONBody(node.Spec)) + res, body, err := request.Post(testutil.GetContext(c), url, request.Host(d1.Sock()), request.JSONBody(node.Spec)) assert.NilError(c, err) b, err := request.ReadBody(body) assert.NilError(c, err) @@ -253,44 +259,46 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *testing.T) { if !strings.Contains(string(b), "last manager of the swarm") { assert.Assert(c, strings.Contains(string(b), "this would result in a loss of quorum")) } - info = d1.SwarmInfo(c) + info = d1.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) assert.Equal(c, info.ControlAvailable, true) // Promote already demoted node - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Role = swarm.NodeRoleManager }) - poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable, checker.True()), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckControlAvailable(ctx), checker.True()), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestAPISwarmLeaderProxy(c *testing.T) { + ctx := testutil.GetContext(c) // add three managers, one of these is leader - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, true) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) // start a service by hitting each of the 3 managers - d1.CreateService(c, simpleTestService, func(s *swarm.Service) { + d1.CreateService(ctx, c, simpleTestService, func(s *swarm.Service) { s.Spec.Name = "test1" }) - d2.CreateService(c, simpleTestService, func(s *swarm.Service) { + d2.CreateService(ctx, c, simpleTestService, func(s *swarm.Service) { s.Spec.Name = "test2" }) - d3.CreateService(c, simpleTestService, func(s *swarm.Service) { + d3.CreateService(ctx, c, simpleTestService, func(s *swarm.Service) { s.Spec.Name = "test3" }) // 3 services should be started now, because the requests were proxied to leader // query each node and make sure it returns 3 services for _, d := range []*daemon.Daemon{d1, d2, d3} { - services := d.ListServices(c) + services := d.ListServices(ctx, c) assert.Equal(c, len(services), 3) } } func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *testing.T) { + ctx := testutil.GetContext(c) if runtime.GOARCH == "s390x" { c.Skip("Disabled on s390x") } @@ -299,14 +307,14 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *testing.T) { } // Create 3 nodes - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, true) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) // assert that the first node we made is the leader, and the other two are followers - assert.Equal(c, d1.GetNode(c, d1.NodeID()).ManagerStatus.Leader, true) - assert.Equal(c, d1.GetNode(c, d2.NodeID()).ManagerStatus.Leader, false) - assert.Equal(c, d1.GetNode(c, d3.NodeID()).ManagerStatus.Leader, false) + assert.Equal(c, d1.GetNode(ctx, c, d1.NodeID()).ManagerStatus.Leader, true) + assert.Equal(c, d1.GetNode(ctx, c, d2.NodeID()).ManagerStatus.Leader, false) + assert.Equal(c, d1.GetNode(ctx, c, d3.NodeID()).ManagerStatus.Leader, false) d1.Stop(c) @@ -321,7 +329,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *testing.T) { leader = nil followers = nil for _, d := range nodes { - n := d.GetNode(c, d.NodeID(), func(err error) bool { + n := d.GetNode(ctx, c, d.NodeID(), func(err error) bool { if strings.Contains(err.Error(), context.DeadlineExceeded.Error()) || strings.Contains(err.Error(), "swarm does not have a leader") { lastErr = err return true @@ -372,6 +380,7 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaderElection(c *testing.T) { } func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *testing.T) { + ctx := testutil.GetContext(c) if runtime.GOARCH == "s390x" { c.Skip("Disabled on s390x") } @@ -379,18 +388,18 @@ func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *testing.T) { c.Skip("Disabled on ppc64le") } - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, true) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) - d1.CreateService(c, simpleTestService) + d1.CreateService(ctx, c, simpleTestService) d2.Stop(c) // make sure there is a leader - poll.WaitOn(c, pollCheck(c, d1.CheckLeader, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckLeader(ctx), checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout)) - d1.CreateService(c, simpleTestService, func(s *swarm.Service) { + d1.CreateService(ctx, c, simpleTestService, func(s *swarm.Service) { s.Spec.Name = "top1" }) @@ -404,36 +413,37 @@ func (s *DockerSwarmSuite) TestAPISwarmRaftQuorum(c *testing.T) { // d1 will eventually step down from leader because there is no longer an active quorum, wait for that to happen poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - _, err := cli.ServiceCreate(context.Background(), service.Spec, types.ServiceCreateOptions{}) + _, err := cli.ServiceCreate(testutil.GetContext(c), service.Spec, types.ServiceCreateOptions{}) return err.Error(), "" }, checker.Contains("Make sure more than half of the managers are online.")), poll.WithTimeout(defaultReconciliationTimeout*2)) d2.StartNode(c) // make sure there is a leader - poll.WaitOn(c, pollCheck(c, d1.CheckLeader, checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckLeader(ctx), checker.IsNil()), poll.WithTimeout(defaultReconciliationTimeout)) - d1.CreateService(c, simpleTestService, func(s *swarm.Service) { + d1.CreateService(ctx, c, simpleTestService, func(s *swarm.Service) { s.Spec.Name = "top3" }) } func (s *DockerSwarmSuite) TestAPISwarmLeaveRemovesContainer(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) instances := 2 - d.CreateService(c, simpleTestService, setInstances(instances)) + d.CreateService(ctx, c, simpleTestService, setInstances(instances)) id, err := d.Cmd("run", "-d", "busybox", "top") assert.NilError(c, err, id) id = strings.TrimSpace(id) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances+1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances+1)), poll.WithTimeout(defaultReconciliationTimeout)) - assert.ErrorContains(c, d.SwarmLeave(c, false), "") - assert.NilError(c, d.SwarmLeave(c, true)) + assert.ErrorContains(c, d.SwarmLeave(ctx, c, false), "") + assert.NilError(c, d.SwarmLeave(ctx, c, true)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) id2, err := d.Cmd("ps", "-q") assert.NilError(c, err, id2) @@ -443,26 +453,28 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveRemovesContainer(c *testing.T) { // #23629 func (s *DockerSwarmSuite) TestAPISwarmLeaveOnPendingJoin(c *testing.T) { testRequires(c, Network) - s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, false, false) + + ctx := testutil.GetContext(c) + s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, false, false) id, err := d2.Cmd("run", "-d", "busybox", "top") assert.NilError(c, err, id) id = strings.TrimSpace(id) c2 := d2.NewClientT(c) - err = c2.SwarmJoin(context.Background(), swarm.JoinRequest{ + err = c2.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d2.SwarmListenAddr(), RemoteAddrs: []string{"123.123.123.123:1234"}, }) assert.ErrorContains(c, err, "Timeout was reached") - info := d2.SwarmInfo(c) + info := d2.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStatePending) - assert.NilError(c, d2.SwarmLeave(c, true)) + assert.NilError(c, d2.SwarmLeave(ctx, c, true)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) id2, err := d2.Cmd("ps", "-q") assert.NilError(c, err, id2) @@ -472,61 +484,65 @@ func (s *DockerSwarmSuite) TestAPISwarmLeaveOnPendingJoin(c *testing.T) { // #23705 func (s *DockerSwarmSuite) TestAPISwarmRestoreOnPendingJoin(c *testing.T) { testRequires(c, Network) - d := s.AddDaemon(c, false, false) + + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) client := d.NewClientT(c) - err := client.SwarmJoin(context.Background(), swarm.JoinRequest{ + err := client.SwarmJoin(testutil.GetContext(c), swarm.JoinRequest{ ListenAddr: d.SwarmListenAddr(), RemoteAddrs: []string{"123.123.123.123:1234"}, }) assert.ErrorContains(c, err, "Timeout was reached") - poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStatePending)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState(ctx), checker.Equals(swarm.LocalNodeStatePending)), poll.WithTimeout(defaultReconciliationTimeout)) d.RestartNode(c) - info := d.SwarmInfo(c) + info := d.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) } func (s *DockerSwarmSuite) TestAPISwarmManagerRestore(c *testing.T) { - d1 := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) instances := 2 - id := d1.CreateService(c, simpleTestService, setInstances(instances)) + id := d1.CreateService(ctx, c, simpleTestService, setInstances(instances)) - d1.GetService(c, id) + d1.GetService(ctx, c, id) d1.RestartNode(c) - d1.GetService(c, id) + d1.GetService(ctx, c, id) - d2 := s.AddDaemon(c, true, true) - d2.GetService(c, id) + d2 := s.AddDaemon(ctx, c, true, true) + d2.GetService(ctx, c, id) d2.RestartNode(c) - d2.GetService(c, id) + d2.GetService(ctx, c, id) - d3 := s.AddDaemon(c, true, true) - d3.GetService(c, id) + d3 := s.AddDaemon(ctx, c, true, true) + d3.GetService(ctx, c, id) d3.RestartNode(c) - d3.GetService(c, id) + d3.GetService(ctx, c, id) err := d3.Kill() assert.NilError(c, err) time.Sleep(1 * time.Second) // time to handle signal d3.StartNode(c) - d3.GetService(c, id) + d3.GetService(ctx, c, id) } func (s *DockerSwarmSuite) TestAPISwarmScaleNoRollingUpdate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) instances := 2 - id := d.CreateService(c, simpleTestService, setInstances(instances)) + id := d.CreateService(ctx, c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - containers := d.ActiveContainers(c) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + containers := d.ActiveContainers(ctx, c) instances = 4 - d.UpdateService(c, d.GetService(c, id), setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - containers2 := d.ActiveContainers(c) + d.UpdateService(ctx, c, d.GetService(ctx, c, id), setInstances(instances)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + containers2 := d.ActiveContainers(ctx, c) loop0: for _, c1 := range containers { @@ -540,11 +556,12 @@ loop0: } func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) req := swarm.InitRequest{ ListenAddr: "", } - res, _, err := request.Post("/swarm/init", request.Host(d.Sock()), request.JSONBody(req)) + res, _, err := request.Post(testutil.GetContext(c), "/swarm/init", request.Host(d.Sock()), request.JSONBody(req)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusBadRequest) @@ -552,44 +569,45 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *testing.T) { ListenAddr: "0.0.0.0:2377", RemoteAddrs: []string{""}, } - res, _, err = request.Post("/swarm/join", request.Host(d.Sock()), request.JSONBody(req2)) + res, _, err = request.Post(testutil.GetContext(c), "/swarm/join", request.Host(d.Sock()), request.JSONBody(req2)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusBadRequest) } func (s *DockerSwarmSuite) TestAPISwarmForceNewCluster(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) instances := 2 - id := d1.CreateService(c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + id := d1.CreateService(ctx, c, simpleTestService, setInstances(instances)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) // drain d2, all containers should move to d1 - d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) { + d1.UpdateNode(ctx, c, d2.NodeID(), func(n *swarm.Node) { n.Spec.Availability = swarm.NodeAvailabilityDrain }) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d2.CheckActiveContainerCount(ctx), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) d2.Stop(c) - d1.SwarmInit(c, swarm.InitRequest{ + d1.SwarmInit(ctx, c, swarm.InitRequest{ ForceNewCluster: true, Spec: swarm.Spec{}, }) - poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - d3 := s.AddDaemon(c, true, true) - info := d3.SwarmInfo(c) + d3 := s.AddDaemon(ctx, c, true, true) + info := d3.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, true) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) instances = 4 - d3.UpdateService(c, d3.GetService(c, id), setInstances(instances)) + d3.UpdateService(ctx, c, d3.GetService(ctx, c, id), setInstances(instances)) - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d3.CheckActiveContainerCount), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d3.CheckActiveContainerCount(ctx)), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) } func simpleTestService(s *swarm.Service) { @@ -731,13 +749,14 @@ func setGlobalMode(s *swarm.Service) { func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerCount int) { var totalMCount, totalWCount int + ctx := testutil.GetContext(c) for _, d := range cl { var info swarm.Info // check info in a poll.WaitOn(), because if the cluster doesn't have a leader, `info` will return an error checkInfo := func(c *testing.T) (interface{}, string) { client := d.NewClientT(c) - daemonInfo, err := client.Info(context.Background()) + daemonInfo, err := client.Info(ctx) info = daemonInfo.Swarm return err, "cluster not ready in time" } @@ -751,12 +770,12 @@ func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerC totalMCount++ var mCount, wCount int - for _, n := range d.ListNodes(c) { + for _, n := range d.ListNodes(ctx, c) { waitReady := func(c *testing.T) (interface{}, string) { if n.Status.State == swarm.NodeStateReady { return true, "" } - nn := d.GetNode(c, n.ID) + nn := d.GetNode(ctx, c, n.ID) n = *nn return n.Status.State == swarm.NodeStateReady, fmt.Sprintf("state of node %s, reported by %s", n.ID, d.NodeID()) } @@ -766,7 +785,7 @@ func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerC if n.Spec.Availability == swarm.NodeAvailabilityActive { return true, "" } - nn := d.GetNode(c, n.ID) + nn := d.GetNode(ctx, c, n.ID) n = *nn return n.Spec.Availability == swarm.NodeAvailabilityActive, fmt.Sprintf("availability of node %s, reported by %s", n.ID, d.NodeID()) } @@ -792,20 +811,21 @@ func checkClusterHealth(c *testing.T, cl []*daemon.Daemon, managerCount, workerC } func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *testing.T) { + ctx := testutil.GetContext(c) mCount, wCount := 5, 1 var nodes []*daemon.Daemon for i := 0; i < mCount; i++ { - manager := s.AddDaemon(c, true, true) - info := manager.SwarmInfo(c) + manager := s.AddDaemon(ctx, c, true, true) + info := manager.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, true) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) nodes = append(nodes, manager) } for i := 0; i < wCount; i++ { - worker := s.AddDaemon(c, true, false) - info := worker.SwarmInfo(c) + worker := s.AddDaemon(ctx, c, true, false) + info := worker.SwarmInfo(ctx, c) assert.Equal(c, info.ControlAvailable, false) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) nodes = append(nodes, worker) @@ -857,38 +877,41 @@ func (s *DockerSwarmSuite) TestAPISwarmRestartCluster(c *testing.T) { } func (s *DockerSwarmSuite) TestAPISwarmServicesUpdateWithName(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) instances := 2 - id := d.CreateService(c, simpleTestService, setInstances(instances)) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + id := d.CreateService(ctx, c, simpleTestService, setInstances(instances)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - service := d.GetService(c, id) + service := d.GetService(ctx, c, id) instances = 5 setInstances(instances)(service) cli := d.NewClientT(c) defer cli.Close() - _, err := cli.ServiceUpdate(context.Background(), service.Spec.Name, service.Version, service.Spec, types.ServiceUpdateOptions{}) + _, err := cli.ServiceUpdate(ctx, service.Spec.Name, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(c, err) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) } // Unlocking an unlocked swarm results in an error func (s *DockerSwarmSuite) TestAPISwarmUnlockNotLocked(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) err := d.SwarmUnlock(c, swarm.UnlockRequest{UnlockKey: "wrong-key"}) assert.ErrorContains(c, err, "swarm is not locked") } // #29885 func (s *DockerSwarmSuite) TestAPISwarmErrorHandling(c *testing.T) { + ctx := testutil.GetContext(c) ln, err := net.Listen("tcp", fmt.Sprintf(":%d", defaultSwarmPort)) assert.NilError(c, err) defer ln.Close() - d := s.AddDaemon(c, false, false) + d := s.AddDaemon(ctx, c, false, false) client := d.NewClientT(c) - _, err = client.SwarmInit(context.Background(), swarm.InitRequest{ + _, err = client.SwarmInit(testutil.GetContext(c), swarm.InitRequest{ ListenAddr: d.SwarmListenAddr(), }) assert.ErrorContains(c, err, "address already in use") @@ -898,7 +921,8 @@ func (s *DockerSwarmSuite) TestAPISwarmErrorHandling(c *testing.T) { // caused both scopes to be `swarm` for `docker network inspect` and `docker network ls`. // This test makes sure the fixes correctly output scopes instead. func (s *DockerSwarmSuite) TestAPIDuplicateNetworks(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) cli := d.NewClientT(c) defer cli.Close() @@ -909,19 +933,19 @@ func (s *DockerSwarmSuite) TestAPIDuplicateNetworks(c *testing.T) { networkCreate.Driver = "bridge" - n1, err := cli.NetworkCreate(context.Background(), name, networkCreate) + n1, err := cli.NetworkCreate(testutil.GetContext(c), name, networkCreate) assert.NilError(c, err) networkCreate.Driver = "overlay" - n2, err := cli.NetworkCreate(context.Background(), name, networkCreate) + n2, err := cli.NetworkCreate(testutil.GetContext(c), name, networkCreate) assert.NilError(c, err) - r1, err := cli.NetworkInspect(context.Background(), n1.ID, types.NetworkInspectOptions{}) + r1, err := cli.NetworkInspect(testutil.GetContext(c), n1.ID, types.NetworkInspectOptions{}) assert.NilError(c, err) assert.Equal(c, r1.Scope, "local") - r2, err := cli.NetworkInspect(context.Background(), n2.ID, types.NetworkInspectOptions{}) + r2, err := cli.NetworkInspect(testutil.GetContext(c), n2.ID, types.NetworkInspectOptions{}) assert.NilError(c, err) assert.Equal(c, r2.Scope, "swarm") } @@ -930,13 +954,14 @@ func (s *DockerSwarmSuite) TestAPIDuplicateNetworks(c *testing.T) { func (s *DockerSwarmSuite) TestAPISwarmHealthcheckNone(c *testing.T) { // Issue #36386 can be a independent one, which is worth further investigation. c.Skip("Root cause of Issue #36386 is needed") - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "-d", "overlay", "lb") assert.NilError(c, err, out) instances := 1 - d.CreateService(c, simpleTestService, setInstances(instances), func(s *swarm.Service) { + d.CreateService(ctx, c, simpleTestService, setInstances(instances), func(s *swarm.Service) { if s.Spec.TaskTemplate.ContainerSpec == nil { s.Spec.TaskTemplate.ContainerSpec = &swarm.ContainerSpec{} } @@ -946,19 +971,20 @@ func (s *DockerSwarmSuite) TestAPISwarmHealthcheckNone(c *testing.T) { } }) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(instances)), poll.WithTimeout(defaultReconciliationTimeout)) - containers := d.ActiveContainers(c) + containers := d.ActiveContainers(testutil.GetContext(c), c) out, err = d.Cmd("exec", containers[0], "ping", "-c1", "-W3", "top") assert.NilError(c, err, out) } func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *testing.T) { - m := s.AddDaemon(c, true, true) - w := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + m := s.AddDaemon(ctx, c, true, true) + w := s.AddDaemon(ctx, c, true, false) - info := m.SwarmInfo(c) + info := m.SwarmInfo(ctx, c) currentTrustRoot := info.Cluster.TLSInfo.TrustRoot @@ -984,7 +1010,7 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *testing.T) { // poll to make sure update succeeds var clusterTLSInfo swarm.TLSInfo for j := 0; j < 18; j++ { - info := m.SwarmInfo(c) + info := m.SwarmInfo(ctx, c) // the desired CA cert and key is always redacted assert.Equal(c, info.Cluster.Spec.CAConfig.SigningCAKey, "") @@ -1006,8 +1032,8 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *testing.T) { // could take another second or two for the nodes to trust the new roots after they've all gotten // new TLS certificates for j := 0; j < 18; j++ { - mInfo := m.GetNode(c, m.NodeID()).Description.TLSInfo - wInfo := m.GetNode(c, w.NodeID()).Description.TLSInfo + mInfo := m.GetNode(ctx, c, m.NodeID()).Description.TLSInfo + wInfo := m.GetNode(ctx, c, w.NodeID()).Description.TLSInfo if mInfo.TrustRoot == clusterTLSInfo.TrustRoot && wInfo.TrustRoot == clusterTLSInfo.TrustRoot { break @@ -1017,17 +1043,17 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *testing.T) { time.Sleep(250 * time.Millisecond) } - assert.DeepEqual(c, m.GetNode(c, m.NodeID()).Description.TLSInfo, clusterTLSInfo) - assert.DeepEqual(c, m.GetNode(c, w.NodeID()).Description.TLSInfo, clusterTLSInfo) + assert.DeepEqual(c, m.GetNode(ctx, c, m.NodeID()).Description.TLSInfo, clusterTLSInfo) + assert.DeepEqual(c, m.GetNode(ctx, c, w.NodeID()).Description.TLSInfo, clusterTLSInfo) currentTrustRoot = clusterTLSInfo.TrustRoot } } func (s *DockerSwarmSuite) TestAPINetworkInspectWithScope(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "test-scoped-network" - ctx := context.Background() apiclient := d.NewClientT(c) resp, err := apiclient.NetworkCreate(ctx, name, types.NetworkCreate{Driver: "overlay"}) diff --git a/integration-cli/docker_api_test.go b/integration-cli/docker_api_test.go index 5b6e97836c..a63770b84c 100644 --- a/integration-cli/docker_api_test.go +++ b/integration-cli/docker_api_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "io" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/docker/docker/api" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" ) @@ -19,8 +21,8 @@ type DockerAPISuite struct { ds *DockerSuite } -func (s *DockerAPISuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerAPISuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerAPISuite) OnTimeout(c *testing.T) { @@ -28,13 +30,13 @@ func (s *DockerAPISuite) OnTimeout(c *testing.T) { } func (s *DockerAPISuite) TestAPIOptionsRoute(c *testing.T) { - resp, _, err := request.Do("/", request.Method(http.MethodOptions)) + resp, _, err := request.Do(testutil.GetContext(c), "/", request.Method(http.MethodOptions)) assert.NilError(c, err) assert.Equal(c, resp.StatusCode, http.StatusOK) } func (s *DockerAPISuite) TestAPIGetEnabledCORS(c *testing.T) { - res, body, err := request.Get("/version") + res, body, err := request.Get(testutil.GetContext(c), "/version") assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusOK) body.Close() @@ -59,7 +61,7 @@ func (s *DockerAPISuite) TestAPIClientVersionOldNotSupported(c *testing.T) { v[1] = strconv.Itoa(vMinInt) version := strings.Join(v, ".") - resp, body, err := request.Get("/v" + version + "/version") + resp, body, err := request.Get(testutil.GetContext(c), "/v"+version+"/version") assert.NilError(c, err) defer body.Close() assert.Equal(c, resp.StatusCode, http.StatusBadRequest) @@ -70,7 +72,7 @@ func (s *DockerAPISuite) TestAPIClientVersionOldNotSupported(c *testing.T) { } func (s *DockerAPISuite) TestAPIErrorJSON(c *testing.T) { - httpResp, body, err := request.Post("/containers/create", request.JSONBody(struct{}{})) + httpResp, body, err := request.Post(testutil.GetContext(c), "/containers/create", request.JSONBody(struct{}{})) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, httpResp.StatusCode, http.StatusInternalServerError) @@ -87,7 +89,7 @@ func (s *DockerAPISuite) TestAPIErrorPlainText(c *testing.T) { // Windows requires API 1.25 or later. This test is validating a behaviour which was present // in v1.23, but changed in 1.24, hence not applicable on Windows. See apiVersionSupportsJSONErrors testRequires(c, DaemonIsLinux) - httpResp, body, err := request.Post("/v1.23/containers/create", request.JSONBody(struct{}{})) + httpResp, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/create", request.JSONBody(struct{}{})) assert.NilError(c, err) if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { assert.Equal(c, httpResp.StatusCode, http.StatusInternalServerError) @@ -102,7 +104,7 @@ func (s *DockerAPISuite) TestAPIErrorPlainText(c *testing.T) { func (s *DockerAPISuite) TestAPIErrorNotFoundJSON(c *testing.T) { // 404 is a different code path to normal errors, so test separately - httpResp, body, err := request.Get("/notfound", request.JSON) + httpResp, body, err := request.Get(testutil.GetContext(c), "/notfound", request.JSON) assert.NilError(c, err) assert.Equal(c, httpResp.StatusCode, http.StatusNotFound) assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "application/json")) @@ -112,7 +114,7 @@ func (s *DockerAPISuite) TestAPIErrorNotFoundJSON(c *testing.T) { } func (s *DockerAPISuite) TestAPIErrorNotFoundPlainText(c *testing.T) { - httpResp, body, err := request.Get("/v1.23/notfound", request.JSON) + httpResp, body, err := request.Get(testutil.GetContext(c), "/v1.23/notfound", request.JSON) assert.NilError(c, err) assert.Equal(c, httpResp.StatusCode, http.StatusNotFound) assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "text/plain")) diff --git a/integration-cli/docker_cli_attach_test.go b/integration-cli/docker_cli_attach_test.go index bd33bb4ded..9bd7410e4d 100644 --- a/integration-cli/docker_cli_attach_test.go +++ b/integration-cli/docker_cli_attach_test.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "context" "fmt" "io" "os/exec" @@ -22,8 +23,8 @@ type DockerCLIAttachSuite struct { ds *DockerSuite } -func (s *DockerCLIAttachSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIAttachSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIAttachSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 49863c0c27..07184cfd1e 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -3,6 +3,7 @@ package main import ( "archive/tar" "bytes" + "context" "encoding/json" "fmt" "os" @@ -34,8 +35,8 @@ type DockerCLIBuildSuite struct { ds *DockerSuite } -func (s *DockerCLIBuildSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIBuildSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIBuildSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_commit_test.go b/integration-cli/docker_cli_commit_test.go index e46d4f35e7..14ad01b560 100644 --- a/integration-cli/docker_cli_commit_test.go +++ b/integration-cli/docker_cli_commit_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "strings" "testing" @@ -14,8 +15,8 @@ type DockerCLICommitSuite struct { ds *DockerSuite } -func (s *DockerCLICommitSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLICommitSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLICommitSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_cp_test.go b/integration-cli/docker_cli_cp_test.go index d3be41d665..1252ca85e8 100644 --- a/integration-cli/docker_cli_cp_test.go +++ b/integration-cli/docker_cli_cp_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "context" "fmt" "io" "os" @@ -30,8 +31,8 @@ type DockerCLICpSuite struct { ds *DockerSuite } -func (s *DockerCLICpSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLICpSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLICpSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_create_test.go b/integration-cli/docker_cli_create_test.go index 60ee3639d5..ce888cec7d 100644 --- a/integration-cli/docker_cli_create_test.go +++ b/integration-cli/docker_cli_create_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "os" @@ -21,8 +22,8 @@ type DockerCLICreateSuite struct { ds *DockerSuite } -func (s *DockerCLICreateSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLICreateSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLICreateSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index b0d7528cc5..e46ca44691 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -32,6 +32,7 @@ import ( "github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/libnetwork/iptables" "github.com/docker/docker/opts" + "github.com/docker/docker/testutil" testdaemon "github.com/docker/docker/testutil/daemon" "github.com/moby/sys/mount" "golang.org/x/sys/unix" @@ -54,7 +55,7 @@ func (s *DockerDaemonSuite) TestLegacyDaemonCommand(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) cli.Docker( cli.Args("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"), @@ -88,7 +89,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *testi } func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) if out, err := s.d.Cmd("run", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { c.Fatal(err, out) @@ -111,7 +112,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *testing.T) { // #11008 func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top") assert.NilError(c, err, "run top1: %v", out) @@ -169,7 +170,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartOnFailure(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "-d", "--name", "test1", "--restart", "on-failure:3", "busybox:latest", "false") assert.NilError(c, err, "run top1: %v", out) @@ -221,7 +222,7 @@ func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *testing } func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { c.Fatalf("Could not run top: %s, %v", out, err) @@ -239,7 +240,7 @@ func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { c.Fatalf("Could not run top: %s, %v", out, err) @@ -288,7 +289,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6Enabled(c *testing.T) { setupV6(c) defer teardownV6(c) - s.d.StartWithBusybox(c, "--ipv6") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--ipv6") iface, err := net.InterfaceByName("docker0") if err != nil { @@ -348,7 +349,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *testing.T) { // ipv6 enabled deleteInterface(c, "docker0") - s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64", "--default-gateway-v6=2001:db8:2::100") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64", "--default-gateway-v6=2001:db8:2::100") out, err := s.d.Cmd("run", "-d", "--name=ipv6test", "busybox:latest", "top") assert.NilError(c, err, "Could not run container: %s, %v", out, err) @@ -375,7 +376,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *testing.T) { // ipv6 enabled deleteInterface(c, "docker0") - s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:1::/64") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--ipv6", "--fixed-cidr-v6=2001:db8:1::/64") out, err := s.d.Cmd("run", "-d", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox", "top") assert.NilError(c, err, out) @@ -391,7 +392,7 @@ func (s *DockerDaemonSuite) TestDaemonIPv6HostMode(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon) deleteInterface(c, "docker0") - s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64") 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) @@ -467,7 +468,7 @@ func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *testing.T) { cmdArgs = append(cmdArgs, "--tls=false", "--host", "tcp://"+net.JoinHostPort(l.daemon, l.port)) } - s.d.StartWithBusybox(c, cmdArgs...) + s.d.StartWithBusybox(testutil.GetContext(c), c, cmdArgs...) for _, l := range listeningPorts { output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", l.client, l.port), "busybox", "true") @@ -514,7 +515,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *testing.T) { createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - d.StartWithBusybox(c, "--bridge", bridgeName) + d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName) ipTablesSearchString := bridgeIPNet.String() icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{ @@ -532,7 +533,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *testing.T) { func (s *DockerDaemonSuite) TestDaemonBridgeNone(c *testing.T) { // start with bridge none d := s.d - d.StartWithBusybox(c, "--bridge", "none") + d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", "none") defer d.Restart(c) // verify docker0 iface is not there @@ -577,7 +578,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *testing.T) { bridgeIP := "192.169.1.1/24" ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) - d.StartWithBusybox(c, "--bip", bridgeIP) + d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIP) defer d.Restart(c) ifconfigSearchString := ip.String() @@ -633,7 +634,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *testing.T) { defer deleteInterface(c, bridgeName) args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} - d.StartWithBusybox(c, args...) + d.StartWithBusybox(testutil.GetContext(c), c, args...) defer d.Restart(c) for i := 0; i < 4; i++ { @@ -658,7 +659,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *testing.T) { createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - d.StartWithBusybox(c, "--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24") + d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24") defer s.d.Restart(c) out, err := d.Cmd("run", "-d", "--name", "bb", "busybox", "top") @@ -687,7 +688,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *testi createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - d.StartWithBusybox(c, "--bridge", bridgeName, "--fixed-cidr", bridgeIP) + d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--fixed-cidr", bridgeIP) defer s.d.Restart(c) out, err := d.Cmd("run", "-d", "busybox", "top") @@ -705,7 +706,7 @@ func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *testing.T) { bridgeIP := "192.169.1.1" bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) - d.StartWithBusybox(c, "--bip", bridgeIPNet) + d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIPNet) defer d.Restart(c) expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) @@ -725,7 +726,7 @@ func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *testing.T) { bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) gatewayIP := "192.169.1.254" - d.StartWithBusybox(c, "--bip", bridgeIPNet, "--default-gateway", gatewayIP) + d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeIPNet, "--default-gateway", gatewayIP) defer d.Restart(c) expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) @@ -740,7 +741,7 @@ func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainer deleteInterface(c, defaultNetworkBridge) // Program a custom default gateway outside of the container subnet, daemon should accept it and start - s.d.StartWithBusybox(c, "--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") deleteInterface(c, defaultNetworkBridge) s.d.Restart(c) @@ -756,7 +757,7 @@ func (s *DockerDaemonSuite) TestDaemonIP(c *testing.T) { ipStr := "192.170.1.1/24" ip, _, _ := net.ParseCIDR(ipStr) args := []string{"--ip", ip.String()} - d.StartWithBusybox(c, args...) + d.StartWithBusybox(testutil.GetContext(c), c, args...) defer d.Restart(c) out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") @@ -791,7 +792,7 @@ func (s *DockerDaemonSuite) TestDaemonICCPing(c *testing.T) { createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") + d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--icc=false") defer d.Restart(c) result := icmd.RunCommand("iptables", "-nvL", "FORWARD") @@ -829,7 +830,7 @@ func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *testing.T) { createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") + d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--icc=false") defer d.Restart(c) result := icmd.RunCommand("iptables", "-nvL", "FORWARD") @@ -855,7 +856,7 @@ func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *tes createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - s.d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--bridge", bridgeName, "--icc=false") defer s.d.Restart(c) out, err := s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") @@ -883,7 +884,7 @@ func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *tes } func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *testing.T) { - s.d.StartWithBusybox(c, "--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024") out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -u)") if err != nil { @@ -929,7 +930,7 @@ func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *testing.T) { // #11315 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { c.Fatal(err, out) @@ -947,7 +948,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") assert.NilError(c, err, out) @@ -985,7 +986,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "--name=test", "--log-driver=none", "busybox", "echo", "testline") if err != nil { @@ -1002,7 +1003,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *testing.T) } func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *testing.T) { - s.d.StartWithBusybox(c, "--log-driver=none") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--log-driver=none") out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") if err != nil { @@ -1019,7 +1020,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *testing.T) { - s.d.StartWithBusybox(c, "--log-driver=none") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--log-driver=none") out, err := s.d.Cmd("run", "--name=test", "--log-driver=json-file", "busybox", "echo", "testline") if err != nil { @@ -1059,7 +1060,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *testing.T) { - s.d.StartWithBusybox(c, "--log-driver=none") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--log-driver=none") out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") assert.NilError(c, err, out) @@ -1071,7 +1072,7 @@ func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonLoggingDriverShouldBeIgnoredForBuild(c *testing.T) { - s.d.StartWithBusybox(c, "--log-driver=splunk") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--log-driver=splunk") result := cli.BuildCmd(c, "busyboxs", cli.Daemon(s.d), build.WithDockerfile(` @@ -1107,7 +1108,7 @@ func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") if err != nil { @@ -1173,7 +1174,7 @@ func (s *DockerDaemonSuite) TestHTTPSRun(c *testing.T) { testDaemonHTTPSAddr = "tcp://localhost:4271" ) - s.d.StartWithBusybox(c, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", + s.d.StartWithBusybox(testutil.GetContext(c), c, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr) args := []string{ @@ -1283,7 +1284,7 @@ func pingContainers(c *testing.T, d *daemon.Daemon, expectFailure bool) { } func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) socket := filepath.Join(s.d.Folder, "docker.sock") @@ -1296,7 +1297,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *testing.T) { // A subsequent daemon restart should clean up said mounts. func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *testing.T) { d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) - d.StartWithBusybox(c) + d.StartWithBusybox(testutil.GetContext(c), c) out, err := d.Cmd("run", "-d", "busybox", "top") assert.NilError(c, err, "Output: %s", out) @@ -1334,7 +1335,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *test // os.Interrupt should perform a graceful daemon shutdown and hence cleanup mounts. func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *testing.T) { d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) - d.StartWithBusybox(c) + d.StartWithBusybox(testutil.GetContext(c), c) out, err := d.Cmd("run", "-d", "busybox", "top") assert.NilError(c, err, "Output: %s", out) @@ -1352,7 +1353,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *testing.T) } func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *testing.T) { - s.d.StartWithBusybox(t) + s.d.StartWithBusybox(testutil.GetContext(t), t) if out, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top"); err != nil { t.Fatal(out, err) } @@ -1365,7 +1366,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *testing.T) } func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") if err != nil { c.Fatal(out, err) @@ -1426,7 +1427,7 @@ func teardownV6(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") assert.NilError(c, err, out) @@ -1449,7 +1450,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlway } func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *testing.T) { - s.d.StartWithBusybox(c, "--log-opt=max-size=1k") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--log-opt=max-size=1k") name := "logtest" out, err := s.d.Cmd("run", "-d", "--log-opt=max-file=5", "--name", name, "busybox", "top") assert.NilError(c, err, "Output: %s, err: %v", out, err) @@ -1465,7 +1466,7 @@ func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil { c.Fatal(err, out) } @@ -1500,7 +1501,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox") assert.NilError(c, err, out) @@ -1594,7 +1595,7 @@ func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *testing.T bridgeIP := "192.169.1.1" bridgeRange := bridgeIP + "/30" - s.d.StartWithBusybox(c, "--bip", bridgeRange) + s.d.StartWithBusybox(testutil.GetContext(c), c, "--bip", bridgeRange) defer s.d.Restart(c) var cont int @@ -1642,7 +1643,7 @@ func (s *DockerDaemonSuite) TestDaemonNoSpaceLeftOnDeviceError(c *testing.T) { // Test daemon restart with container links + auto restart func (s *DockerDaemonSuite) TestDaemonRestartContainerLinksRestart(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) var parent1Args []string var parent2Args []string @@ -1705,7 +1706,7 @@ func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *testing.T) { cgroupParent := "test" name := "cgroup-test" - s.d.StartWithBusybox(c, "--cgroup-parent", cgroupParent) + s.d.StartWithBusybox(testutil.GetContext(c), c, "--cgroup-parent", cgroupParent) defer s.d.Restart(c) out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup") @@ -1728,7 +1729,7 @@ func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *testing.T) { func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *testing.T) { testRequires(c, DaemonIsLinux) // Windows does not support links - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") assert.NilError(c, err, out) @@ -1751,7 +1752,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *testing.T) { func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *testing.T) { testRequires(c, DaemonIsLinux) // Windows does not support links - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("create", "--name=test", "busybox") assert.NilError(c, err, out) @@ -1799,7 +1800,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *testing.T) { // TestDaemonRestartWithKilledRunningContainer requires live restore of running containers func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *testing.T) { testRequires(t, DaemonIsLinux) - s.d.StartWithBusybox(t) + s.d.StartWithBusybox(testutil.GetContext(t), t) cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") defer s.d.Stop(t) @@ -1848,7 +1849,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *testi // them now, should remove the mounts. func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *testing.T) { testRequires(c, DaemonIsLinux) - s.d.StartWithBusybox(c, "--live-restore") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--live-restore") out, err := s.d.Cmd("run", "-d", "busybox", "top") assert.NilError(c, err, "Output: %s", out) @@ -1895,7 +1896,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *testing.T) { // TestDaemonRestartWithUnpausedRunningContainer requires live restore of running containers. func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *testing.T) { testRequires(t, DaemonIsLinux) - s.d.StartWithBusybox(t, "--live-restore") + s.d.StartWithBusybox(testutil.GetContext(t), t, "--live-restore") cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") defer s.d.Stop(t) @@ -1952,7 +1953,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *tes // this ensures that the old, pre gh#16032 functionality continues on func (s *DockerDaemonSuite) TestRunLinksChanged(c *testing.T) { testRequires(c, DaemonIsLinux) // Windows does not support links - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") assert.NilError(c, err, out) @@ -2045,7 +2046,7 @@ func (s *DockerDaemonSuite) TestDaemonDebugLog(c *testing.T) { // Test for #21956 func (s *DockerDaemonSuite) TestDaemonLogOptions(c *testing.T) { - s.d.StartWithBusybox(c, "--log-driver=syslog", "--log-opt=syslog-address=udp://127.0.0.1:514") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--log-driver=syslog", "--log-opt=syslog-address=udp://127.0.0.1:514") out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "top") assert.NilError(c, err, out) @@ -2165,7 +2166,7 @@ func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFileReload(c *test } func (s *DockerDaemonSuite) TestBuildOnDisabledBridgeNetworkDaemon(c *testing.T) { - s.d.StartWithBusybox(c, "-b=none", "--iptables=false") + s.d.StartWithBusybox(testutil.GetContext(c), c, "-b=none", "--iptables=false") result := cli.BuildCmd(c, "busyboxs", cli.Daemon(s.d), build.WithDockerfile(` @@ -2182,7 +2183,7 @@ func (s *DockerDaemonSuite) TestBuildOnDisabledBridgeNetworkDaemon(c *testing.T) func (s *DockerDaemonSuite) TestDaemonDNSFlagsInHostMode(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) - s.d.StartWithBusybox(c, "--dns", "1.2.3.4", "--dns-search", "example.com", "--dns-opt", "timeout:3") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--dns", "1.2.3.4", "--dns-search", "example.com", "--dns-opt", "timeout:3") expectedOutput := "nameserver 1.2.3.4" out, _ := s.d.Cmd("run", "--net=host", "busybox", "cat", "/etc/resolv.conf") @@ -2216,7 +2217,7 @@ func (s *DockerDaemonSuite) TestRunWithRuntimeFromConfigFile(c *testing.T) { } ` os.WriteFile(configName, []byte(config), 0o644) - s.d.StartWithBusybox(c, "--config-file", configName) + s.d.StartWithBusybox(testutil.GetContext(c), c, "--config-file", configName) // Run with default runtime out, err := s.d.Cmd("run", "--rm", "busybox", "ls") @@ -2307,7 +2308,7 @@ func (s *DockerDaemonSuite) TestRunWithRuntimeFromConfigFile(c *testing.T) { } func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *testing.T) { - s.d.StartWithBusybox(c, "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") // Run with default runtime out, err := s.d.Cmd("run", "--rm", "busybox", "ls") @@ -2327,7 +2328,7 @@ func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *testing.T) { assert.Assert(c, is.Contains(out, "/usr/local/bin/vm-manager: no such file or directory")) // Start a daemon without any extra runtimes s.d.Stop(c) - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) // Run with default runtime out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") @@ -2350,7 +2351,7 @@ func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *testing.T) { assert.Assert(c, is.Contains(string(content), `runtime name 'runc' is reserved`)) // Check that we can select a default runtime s.d.Stop(c) - s.d.StartWithBusybox(c, "--default-runtime=vm", "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--default-runtime=vm", "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") out, err = s.d.Cmd("run", "--rm", "busybox", "ls") assert.ErrorContains(c, err, "", out) @@ -2361,7 +2362,7 @@ func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *testing.T) { } func (s *DockerDaemonSuite) TestDaemonRestartWithAutoRemoveContainer(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) // top1 will exist after daemon restarts out, err := s.d.Cmd("run", "-d", "--name", "top1", "busybox:latest", "top") @@ -2384,7 +2385,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithAutoRemoveContainer(c *testing. } func (s *DockerDaemonSuite) TestDaemonRestartSaveContainerExitCode(c *testing.T) { - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(testutil.GetContext(c), c) containerName := "error-values" // Make a container with both a non 0 exit code and an error message @@ -2436,7 +2437,7 @@ func (s *DockerDaemonSuite) TestDaemonWithUserlandProxyPath(c *testing.T) { assert.NilError(c, cmd.Run()) // custom one - s.d.StartWithBusybox(c, "--userland-proxy-path", newProxyPath) + s.d.StartWithBusybox(testutil.GetContext(c), c, "--userland-proxy-path", newProxyPath) out, err := s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") assert.NilError(c, err, out) @@ -2456,7 +2457,7 @@ func (s *DockerDaemonSuite) TestDaemonWithUserlandProxyPath(c *testing.T) { // Test case for #22471 func (s *DockerDaemonSuite) TestDaemonShutdownTimeout(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon) - s.d.StartWithBusybox(c, "--shutdown-timeout=3") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--shutdown-timeout=3") _, err := s.d.Cmd("run", "-d", "busybox", "top") assert.NilError(c, err) @@ -2511,7 +2512,7 @@ func (s *DockerDaemonSuite) TestDaemonShutdownTimeoutWithConfigFile(c *testing.T // Test case for 29342 func (s *DockerDaemonSuite) TestExecWithUserAfterLiveRestore(c *testing.T) { testRequires(c, DaemonIsLinux) - s.d.StartWithBusybox(c, "--live-restore") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--live-restore") 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) @@ -2539,7 +2540,7 @@ func (s *DockerDaemonSuite) TestExecWithUserAfterLiveRestore(c *testing.T) { func (s *DockerDaemonSuite) TestRemoveContainerAfterLiveRestore(c *testing.T) { testRequires(c, DaemonIsLinux, overlayFSSupported, testEnv.IsLocalDaemon) - s.d.StartWithBusybox(c, "--live-restore", "--storage-driver", "overlay2") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--live-restore", "--storage-driver", "overlay2") out, err := s.d.Cmd("run", "-d", "--name=top", "busybox", "top") assert.NilError(c, err, "Output: %s", out) @@ -2572,7 +2573,7 @@ func (s *DockerDaemonSuite) TestRemoveContainerAfterLiveRestore(c *testing.T) { // #29598 func (s *DockerDaemonSuite) TestRestartPolicyWithLiveRestore(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - s.d.StartWithBusybox(c, "--live-restore") + s.d.StartWithBusybox(testutil.GetContext(c), c, "--live-restore") out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") assert.NilError(c, err, "Output: %s", out) @@ -2633,7 +2634,7 @@ func (s *DockerDaemonSuite) TestShmSize(c *testing.T) { size := 67108864 * 2 pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) - s.d.StartWithBusybox(c, "--default-shm-size", fmt.Sprintf("%v", size)) + s.d.StartWithBusybox(testutil.GetContext(c), c, "--default-shm-size", fmt.Sprintf("%v", size)) name := "shm1" out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") @@ -2657,7 +2658,7 @@ func (s *DockerDaemonSuite) TestShmSizeReload(c *testing.T) { assert.Assert(c, os.WriteFile(configFile, configData, 0o666) == nil, "could not write temp file for config reload") pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024)) - s.d.StartWithBusybox(c, "--config-file", configFile) + s.d.StartWithBusybox(testutil.GetContext(c), c, "--config-file", configFile) name := "shm1" out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") @@ -2749,7 +2750,7 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) { d.Start(c) cli := d.NewClientT(c) - ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second) + ctx, cancel := context.WithTimeout(testutil.GetContext(c), 300*time.Second) defer cancel() name := "test-plugin-rm-fail" @@ -2762,7 +2763,7 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) { defer out.Close() io.Copy(io.Discard, out) - ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + ctx, cancel = context.WithTimeout(testutil.GetContext(c), 30*time.Second) defer cancel() p, _, err := cli.PluginInspectWithRaw(ctx, name) assert.NilError(c, err) @@ -2772,7 +2773,7 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) { assert.NilError(c, os.Remove(configPath)) d.Restart(c) - ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) + ctx, cancel = context.WithTimeout(testutil.GetContext(c), 30*time.Second) defer cancel() _, err = cli.Ping(ctx) assert.NilError(c, err) diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go index 7a7a9a88a8..b76f609b3d 100644 --- a/integration-cli/docker_cli_events_test.go +++ b/integration-cli/docker_cli_events_test.go @@ -19,6 +19,7 @@ import ( eventstestutils "github.com/docker/docker/daemon/events/testutils" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/icmd" @@ -28,8 +29,8 @@ type DockerCLIEventSuite struct { ds *DockerSuite } -func (s *DockerCLIEventSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIEventSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIEventSuite) OnTimeout(c *testing.T) { @@ -462,7 +463,7 @@ func (s *DockerCLIEventSuite) TestEventsResize(c *testing.T) { Height: 80, Width: 24, } - err = apiClient.ContainerResize(context.Background(), cID, options) + err = apiClient.ContainerResize(testutil.GetContext(c), cID, options) assert.NilError(c, err) dockerCmd(c, "stop", cID) diff --git a/integration-cli/docker_cli_exec_test.go b/integration-cli/docker_cli_exec_test.go index 7b5b139665..c3da7ffab4 100644 --- a/integration-cli/docker_cli_exec_test.go +++ b/integration-cli/docker_cli_exec_test.go @@ -17,6 +17,7 @@ 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/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/icmd" @@ -26,8 +27,8 @@ type DockerCLIExecSuite struct { ds *DockerSuite } -func (s *DockerCLIExecSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIExecSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIExecSuite) OnTimeout(c *testing.T) { @@ -90,8 +91,9 @@ func (s *DockerCLIExecSuite) TestExecAfterContainerRestart(c *testing.T) { } func (s *DockerDaemonSuite) TestExecAfterDaemonRestart(c *testing.T) { + ctx := testutil.GetContext(c) // TODO Windows CI: DockerDaemonSuite doesn't run on Windows, and requires a little work to get this ported. - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top") assert.NilError(c, err, "Could not run top: %s", out) @@ -363,7 +365,7 @@ func (s *DockerCLIExecSuite) TestExecInspectID(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - _, err = apiClient.ContainerExecInspect(context.Background(), execID) + _, err = apiClient.ContainerExecInspect(testutil.GetContext(c), execID) assert.NilError(c, err) // Now delete the container and then an 'inspect' on the exec should @@ -371,7 +373,7 @@ func (s *DockerCLIExecSuite) TestExecInspectID(c *testing.T) { out, ec := dockerCmd(c, "rm", "-f", id) assert.Equal(c, ec, 0, "error removing container: %s", out) - _, err = apiClient.ContainerExecInspect(context.Background(), execID) + _, err = apiClient.ContainerExecInspect(testutil.GetContext(c), execID) assert.ErrorContains(c, err, "No such exec instance") } diff --git a/integration-cli/docker_cli_external_volume_driver_test.go b/integration-cli/docker_cli_external_volume_driver_test.go index ba623e4a56..a20c03920f 100644 --- a/integration-cli/docker_cli_external_volume_driver_test.go +++ b/integration-cli/docker_cli_external_volume_driver_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "io" @@ -18,6 +19,7 @@ import ( "github.com/docker/docker/integration-cli/daemon" "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/testutil" testdaemon "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/volume" "gotest.tools/v3/assert" @@ -43,20 +45,20 @@ type DockerExternalVolumeSuite struct { *volumePlugin } -func (s *DockerExternalVolumeSuite) SetUpTest(c *testing.T) { +func (s *DockerExternalVolumeSuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, testEnv.IsLocalDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) s.ec = &eventCounter{} } -func (s *DockerExternalVolumeSuite) TearDownTest(c *testing.T) { +func (s *DockerExternalVolumeSuite) TearDownTest(ctx context.Context, c *testing.T) { if s.d != nil { s.d.Stop(c) - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } } -func (s *DockerExternalVolumeSuite) SetUpSuite(c *testing.T) { +func (s *DockerExternalVolumeSuite) SetUpSuite(ctx context.Context, c *testing.T) { s.volumePlugin = newVolumePlugin(c, volumePluginName) } @@ -267,7 +269,7 @@ func newVolumePlugin(c *testing.T, name string) *volumePlugin { return s } -func (s *DockerExternalVolumeSuite) TearDownSuite(c *testing.T) { +func (s *DockerExternalVolumeSuite) TearDownSuite(ctx context.Context, c *testing.T) { s.volumePlugin.Close() err := os.RemoveAll("/etc/docker/plugins") @@ -286,7 +288,8 @@ func (s *DockerExternalVolumeSuite) TestVolumeCLICreateOptionConflict(c *testing } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverNamed(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", volumePluginName, "busybox:latest", "cat", "/tmp/external-volume-test/test") assert.NilError(c, err, out) @@ -307,7 +310,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverNamed(c *testing.T) } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverUnnamed(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "/tmp/external-volume-test", "--volume-driver", volumePluginName, "busybox:latest", "cat", "/tmp/external-volume-test/test") assert.NilError(c, err, out) @@ -320,7 +324,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverUnnamed(c *testing.T } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverVolumesFrom(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("run", "--name", "vol-test1", "-v", "/foo", "--volume-driver", volumePluginName, "busybox:latest") assert.NilError(c, err, out) @@ -339,7 +344,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverVolumesFrom(c *testi } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverDeleteContainer(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("run", "--name", "vol-test1", "-v", "/foo", "--volume-driver", volumePluginName, "busybox:latest") assert.NilError(c, err, out) @@ -396,7 +402,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverLookupNotBlocked(c * } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverRetryNotImmediatelyExists(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) driverName := "test-external-volume-driver-retry" errchan := make(chan error, 1) @@ -522,7 +529,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverPathCalls(c *testing } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverMountID(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("run", "--rm", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", volumePluginName, "busybox:latest", "cat", "/tmp/external-volume-test/test") assert.NilError(c, err, out) @@ -545,11 +553,12 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverCapabilities(c *test } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverOutOfBandDelete(c *testing.T) { + ctx := testutil.GetContext(c) driverName := stringid.GenerateRandomID() p := newVolumePlugin(c, driverName) defer p.Close() - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) out, err := s.d.Cmd("volume", "create", "-d", driverName, "--name", "test") assert.NilError(c, err, out) @@ -593,7 +602,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverOutOfBandDelete(c *t } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverUnmountOnMountFail(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) s.d.Cmd("volume", "create", "-d", "test-external-volume-driver", "--opt=invalidOption=1", "--name=testumount") out, _ := s.d.Cmd("run", "-v", "testumount:/foo", "busybox", "true") @@ -603,7 +613,8 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverUnmountOnMountFail(c } func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverUnmountOnCp(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) s.d.Cmd("volume", "create", "-d", "test-external-volume-driver", "--name=test") out, _ := s.d.Cmd("run", "-d", "--name=test", "-v", "test:/foo", "busybox", "/bin/sh", "-c", "touch /test && top") diff --git a/integration-cli/docker_cli_health_test.go b/integration-cli/docker_cli_health_test.go index 42f942576b..e7818df2b6 100644 --- a/integration-cli/docker_cli_health_test.go +++ b/integration-cli/docker_cli_health_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "strconv" "strings" @@ -16,8 +17,8 @@ type DockerCLIHealthSuite struct { ds *DockerSuite } -func (s *DockerCLIHealthSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIHealthSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIHealthSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_history_test.go b/integration-cli/docker_cli_history_test.go index bc98d77650..ef6e7439f4 100644 --- a/integration-cli/docker_cli_history_test.go +++ b/integration-cli/docker_cli_history_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "regexp" "strconv" @@ -16,8 +17,8 @@ type DockerCLIHistorySuite struct { ds *DockerSuite } -func (s *DockerCLIHistorySuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIHistorySuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIHistorySuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_images_test.go b/integration-cli/docker_cli_images_test.go index 61d890cc96..29e20a3e61 100644 --- a/integration-cli/docker_cli_images_test.go +++ b/integration-cli/docker_cli_images_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "os" "path/filepath" @@ -21,8 +22,8 @@ type DockerCLIImagesSuite struct { ds *DockerSuite } -func (s *DockerCLIImagesSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIImagesSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIImagesSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_import_test.go b/integration-cli/docker_cli_import_test.go index 71e9c56116..36b40cd3df 100644 --- a/integration-cli/docker_cli_import_test.go +++ b/integration-cli/docker_cli_import_test.go @@ -3,6 +3,7 @@ package main import ( "bufio" "compress/gzip" + "context" "os" "os/exec" "regexp" @@ -18,8 +19,8 @@ type DockerCLIImportSuite struct { ds *DockerSuite } -func (s *DockerCLIImportSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIImportSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIImportSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_info_test.go b/integration-cli/docker_cli_info_test.go index af65b24535..4c95d134ff 100644 --- a/integration-cli/docker_cli_info_test.go +++ b/integration-cli/docker_cli_info_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "strings" @@ -13,8 +14,8 @@ type DockerCLIInfoSuite struct { ds *DockerSuite } -func (s *DockerCLIInfoSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIInfoSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIInfoSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_info_unix_test.go b/integration-cli/docker_cli_info_unix_test.go index b8cfc39187..70bd1e81be 100644 --- a/integration-cli/docker_cli_info_unix_test.go +++ b/integration-cli/docker_cli_info_unix_test.go @@ -3,11 +3,11 @@ package main import ( - "context" "testing" "github.com/docker/docker/client" "github.com/docker/docker/daemon/config" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -21,7 +21,7 @@ func (s *DockerCLIInfoSuite) TestInfoSecurityOptions(c *testing.T) { apiClient, err := client.NewClientWithOpts(client.FromEnv) assert.NilError(c, err) defer apiClient.Close() - info, err := apiClient.Info(context.Background()) + info, err := apiClient.Info(testutil.GetContext(c)) assert.NilError(c, err) if Apparmor() { diff --git a/integration-cli/docker_cli_inspect_test.go b/integration-cli/docker_cli_inspect_test.go index 436da0f01e..7b2aebfbbe 100644 --- a/integration-cli/docker_cli_inspect_test.go +++ b/integration-cli/docker_cli_inspect_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "os" @@ -19,8 +20,8 @@ type DockerCLIInspectSuite struct { ds *DockerSuite } -func (s *DockerCLIInspectSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIInspectSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIInspectSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_links_test.go b/integration-cli/docker_cli_links_test.go index 5d1f9e7fa1..300a8f2f7d 100644 --- a/integration-cli/docker_cli_links_test.go +++ b/integration-cli/docker_cli_links_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "fmt" "regexp" @@ -17,8 +18,8 @@ type DockerCLILinksSuite struct { ds *DockerSuite } -func (s *DockerCLILinksSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLILinksSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLILinksSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_login_test.go b/integration-cli/docker_cli_login_test.go index fb77f8de19..83eefe8973 100644 --- a/integration-cli/docker_cli_login_test.go +++ b/integration-cli/docker_cli_login_test.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "context" "os/exec" "strings" "testing" @@ -13,8 +14,8 @@ type DockerCLILoginSuite struct { ds *DockerSuite } -func (s *DockerCLILoginSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLILoginSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLILoginSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_logout_test.go b/integration-cli/docker_cli_logout_test.go index 6f667006f5..f080d8c43e 100644 --- a/integration-cli/docker_cli_logout_test.go +++ b/integration-cli/docker_cli_logout_test.go @@ -9,11 +9,13 @@ import ( "strings" "testing" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" ) func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) workingDir, err := os.Getwd() assert.NilError(c, err) diff --git a/integration-cli/docker_cli_logs_test.go b/integration-cli/docker_cli_logs_test.go index a963686aec..60a6341745 100644 --- a/integration-cli/docker_cli_logs_test.go +++ b/integration-cli/docker_cli_logs_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "io" "os/exec" @@ -11,6 +12,9 @@ import ( "github.com/containerd/containerd/log" "github.com/docker/docker/integration-cli/cli" + "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" + testdaemon "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) @@ -19,8 +23,8 @@ type DockerCLILogsSuite struct { ds *DockerSuite } -func (s *DockerCLILogsSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLILogsSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLILogsSuite) OnTimeout(c *testing.T) { @@ -282,24 +286,39 @@ func ConsumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, s } func (s *DockerCLILogsSuite) TestLogsFollowGoroutinesWithStdout(c *testing.T) { - out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done") - id := strings.TrimSpace(out) - assert.NilError(c, waitRun(id)) + testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) + c.Parallel() - nroutines, err := getGoroutineNumber() + ctx := testutil.GetContext(c) + d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvVars("OTEL_SDK_DISABLED=1")) + defer func() { + d.Stop(c) + d.Cleanup(c) + }() + d.StartWithBusybox(ctx, c, "--iptables=false") + + out, err := d.Cmd("run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done") assert.NilError(c, err) - cmd := exec.Command(dockerBinary, "logs", "-f", id) + + id := strings.TrimSpace(out) + assert.NilError(c, d.WaitRun(id)) + + client := d.NewClientT(c) + nroutines := waitForStableGourtineCount(ctx, c, client) + + cmd := d.Command("logs", "-f", id) r, w := io.Pipe() defer r.Close() defer w.Close() cmd.Stdout = w - assert.NilError(c, cmd.Start()) - defer cmd.Process.Kill() + res := icmd.StartCmd(cmd) + assert.NilError(c, res.Error) + defer res.Cmd.Process.Kill() finished := make(chan error) go func() { - finished <- cmd.Wait() + finished <- res.Cmd.Wait() }() // Make sure pipe is written to @@ -314,35 +333,52 @@ func (s *DockerCLILogsSuite) TestLogsFollowGoroutinesWithStdout(c *testing.T) { // Check read from pipe succeeded assert.NilError(c, <-chErr) - assert.NilError(c, cmd.Process.Kill()) + assert.NilError(c, res.Cmd.Process.Kill()) <-finished // NGoroutines is not updated right away, so we need to wait before failing - assert.NilError(c, waitForGoroutines(nroutines)) + waitForGoroutines(ctx, c, client, nroutines) } func (s *DockerCLILogsSuite) TestLogsFollowGoroutinesNoOutput(c *testing.T) { - out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 2; done") - id := strings.TrimSpace(out) - assert.NilError(c, waitRun(id)) + testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) + c.Parallel() - nroutines, err := getGoroutineNumber() + d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvVars("OTEL_SDK_DISABLED=1")) + defer func() { + d.Stop(c) + d.Cleanup(c) + }() + + ctx := testutil.GetContext(c) + + d.StartWithBusybox(ctx, c, "--iptables=false") + + out, err := d.Cmd("run", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 2; done") assert.NilError(c, err) - cmd := exec.Command(dockerBinary, "logs", "-f", id) - assert.NilError(c, cmd.Start()) + id := strings.TrimSpace(out) + assert.NilError(c, d.WaitRun(id)) + + client := d.NewClientT(c) + nroutines := waitForStableGourtineCount(ctx, c, client) + assert.NilError(c, err) + + cmd := d.Command("logs", "-f", id) + res := icmd.StartCmd(cmd) + assert.NilError(c, res.Error) finished := make(chan error) go func() { - finished <- cmd.Wait() + finished <- res.Cmd.Wait() }() time.Sleep(200 * time.Millisecond) - assert.NilError(c, cmd.Process.Kill()) + assert.NilError(c, res.Cmd.Process.Kill()) <-finished // NGoroutines is not updated right away, so we need to wait before failing - assert.NilError(c, waitForGoroutines(nroutines)) + waitForGoroutines(ctx, c, client, nroutines) } func (s *DockerCLILogsSuite) TestLogsCLIContainerNotFound(c *testing.T) { diff --git a/integration-cli/docker_cli_netmode_test.go b/integration-cli/docker_cli_netmode_test.go index 48807bb0e0..035a58be3b 100644 --- a/integration-cli/docker_cli_netmode_test.go +++ b/integration-cli/docker_cli_netmode_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "strings" "testing" @@ -18,8 +19,8 @@ type DockerCLINetmodeSuite struct { ds *DockerSuite } -func (s *DockerCLINetmodeSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLINetmodeSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLINetmodeSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_network_test.go b/integration-cli/docker_cli_network_test.go index ebe19d0af7..4670f71a17 100644 --- a/integration-cli/docker_cli_network_test.go +++ b/integration-cli/docker_cli_network_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "net/http/httptest" "testing" @@ -11,8 +12,8 @@ type DockerCLINetworkSuite struct { ds *DockerSuite } -func (s *DockerCLINetworkSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLINetworkSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLINetworkSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_network_unix_test.go b/integration-cli/docker_cli_network_unix_test.go index ffd33755aa..da78bc2692 100644 --- a/integration-cli/docker_cli_network_unix_test.go +++ b/integration-cli/docker_cli_network_unix_test.go @@ -3,6 +3,7 @@ package main import ( + "context" "encoding/json" "fmt" "net" @@ -25,6 +26,7 @@ import ( "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" + "github.com/docker/docker/testutil" testdaemon "github.com/docker/docker/testutil/daemon" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" @@ -39,18 +41,18 @@ const ( var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest -func (s *DockerNetworkSuite) SetUpTest(c *testing.T) { +func (s *DockerNetworkSuite) SetUpTest(ctx context.Context, c *testing.T) { s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) } -func (s *DockerNetworkSuite) TearDownTest(c *testing.T) { +func (s *DockerNetworkSuite) TearDownTest(ctx context.Context, c *testing.T) { if s.d != nil { s.d.Stop(c) - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } } -func (s *DockerNetworkSuite) SetUpSuite(c *testing.T) { +func (s *DockerNetworkSuite) SetUpSuite(ctx context.Context, c *testing.T) { mux := http.NewServeMux() s.server = httptest.NewServer(mux) assert.Assert(c, s.server != nil, "Failed to start an HTTP Server") @@ -210,7 +212,7 @@ func setupRemoteNetworkDrivers(c *testing.T, mux *http.ServeMux, url, netDrv, ip assert.NilError(c, err) } -func (s *DockerNetworkSuite) TearDownSuite(c *testing.T) { +func (s *DockerNetworkSuite) TearDownSuite(ctx context.Context, c *testing.T) { if s.server == nil { return } @@ -306,7 +308,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *testing.T) { } func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *testing.T) { - testRequires(c, OnlyDefaultNetworks) + testRequires(c, func() bool { return OnlyDefaultNetworks(testutil.GetContext(c)) }) + testNet := "testnet1" testLabel := "foo" testValue := "bar" @@ -786,6 +789,8 @@ func (s *DockerNetworkSuite) TestDockerPluginV2NetworkDriver(c *testing.T) { } func (s *DockerDaemonSuite) TestDockerNetworkNoDiscoveryDefaultBridgeNetwork(c *testing.T) { + ctx := testutil.GetContext(c) + // On default bridge network built-in service discovery should not happen hostsFile := "/etc/hosts" bridgeName := "external-bridge" @@ -793,7 +798,7 @@ func (s *DockerDaemonSuite) TestDockerNetworkNoDiscoveryDefaultBridgeNetwork(c * createInterface(c, "bridge", bridgeName, bridgeIP) defer deleteInterface(c, bridgeName) - s.d.StartWithBusybox(c, "--bridge", bridgeName) + s.d.StartWithBusybox(ctx, c, "--bridge", bridgeName) defer s.d.Restart(c) // run two containers and store first container's etc/hosts content @@ -944,6 +949,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *testing.T) { func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *testing.T) { testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon) + + ctx := testutil.GetContext(c) dnd := "dnd" did := "did" @@ -951,7 +958,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *testing server := httptest.NewServer(mux) setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did) - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) _, err := s.d.Cmd("network", "create", "-d", dnd, "--subnet", "1.1.1.0/24", "net1") assert.NilError(c, err) @@ -1051,10 +1058,11 @@ func verifyContainerIsConnectedToNetworks(c *testing.T, d *daemon.Daemon, cName func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon) + ctx := testutil.GetContext(c) cName := "bb" nwList := []string{"nw1", "nw2", "nw3"} - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) connectContainerToNetworks(c, s.d, cName, nwList) verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList) @@ -1070,10 +1078,11 @@ func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRest func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon) + ctx := testutil.GetContext(c) cName := "cc" nwList := []string{"nw1", "nw2", "nw3"} - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) connectContainerToNetworks(c, s.d, cName, nwList) verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList) @@ -1097,7 +1106,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *testing.T) { func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *testing.T) { testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon) - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) // Run a few containers on host network for i := 0; i < 10; i++ { @@ -1620,7 +1630,8 @@ func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *t } func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *testing.T) { - s.d.StartWithBusybox(t, "--live-restore") + ctx := testutil.GetContext(t) + s.d.StartWithBusybox(ctx, t, "--live-restore") defer s.d.Stop(t) oldCon := "old" diff --git a/integration-cli/docker_cli_plugins_logdriver_test.go b/integration-cli/docker_cli_plugins_logdriver_test.go index 072668758f..ea821f32d2 100644 --- a/integration-cli/docker_cli_plugins_logdriver_test.go +++ b/integration-cli/docker_cli_plugins_logdriver_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/docker/docker/client" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" ) @@ -13,8 +14,8 @@ type DockerCLIPluginLogDriverSuite struct { ds *DockerSuite } -func (s *DockerCLIPluginLogDriverSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPluginLogDriverSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPluginLogDriverSuite) OnTimeout(c *testing.T) { @@ -51,7 +52,7 @@ func (s *DockerCLIPluginLogDriverSuite) TestPluginLogDriverInfoList(c *testing.T assert.NilError(c, err) defer apiClient.Close() - info, err := apiClient.Info(context.Background()) + info, err := apiClient.Info(testutil.GetContext(c)) assert.NilError(c, err) drivers := strings.Join(info.Plugins.Log, " ") diff --git a/integration-cli/docker_cli_plugins_test.go b/integration-cli/docker_cli_plugins_test.go index 48ad7fcf00..d7b6b6817a 100644 --- a/integration-cli/docker_cli_plugins_test.go +++ b/integration-cli/docker_cli_plugins_test.go @@ -15,6 +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/testutil" "github.com/docker/docker/testutil/fixtures/plugin" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -34,8 +35,8 @@ type DockerCLIPluginsSuite struct { ds *DockerSuite } -func (s *DockerCLIPluginsSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPluginsSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPluginsSuite) OnTimeout(c *testing.T) { @@ -162,7 +163,7 @@ func (ps *DockerPluginSuite) TestPluginSet(c *testing.T) { client := testEnv.APIClient() name := "test" - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(testutil.GetContext(c), 60*time.Second) defer cancel() initialValue := "0" @@ -207,7 +208,7 @@ func (ps *DockerPluginSuite) TestPluginSet(c *testing.T) { func (ps *DockerPluginSuite) TestPluginInstallArgs(c *testing.T) { pName := path.Join(ps.registryHost(), "plugin", "testplugininstallwithargs") - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(testutil.GetContext(c), 60*time.Second) defer cancel() plugin.CreateInRegistry(ctx, pName, nil, func(cfg *plugin.Config) { @@ -345,7 +346,7 @@ func (ps *DockerPluginSuite) TestPluginIDPrefix(c *testing.T) { name := "test" client := testEnv.APIClient() - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(testutil.GetContext(c), 60*time.Second) initialValue := "0" err := plugin.Create(ctx, client, name, func(cfg *plugin.Config) { cfg.Env = []types.PluginEnv{{Name: "DEBUG", Value: &initialValue, Settable: []string{"value"}}} @@ -406,7 +407,7 @@ func (ps *DockerPluginSuite) TestPluginListDefaultFormat(c *testing.T) { name := "test:latest" client := testEnv.APIClient() - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(testutil.GetContext(c), 60*time.Second) defer cancel() err = plugin.Create(ctx, client, name, func(cfg *plugin.Config) { cfg.Description = "test plugin" diff --git a/integration-cli/docker_cli_port_test.go b/integration-cli/docker_cli_port_test.go index 7c7eccabcf..e388e8f2fb 100644 --- a/integration-cli/docker_cli_port_test.go +++ b/integration-cli/docker_cli_port_test.go @@ -9,15 +9,17 @@ import ( "strings" "testing" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" + is "gotest.tools/v3/assert/cmp" ) type DockerCLIPortSuite struct { ds *DockerSuite } -func (s *DockerCLIPortSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPortSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPortSuite) OnTimeout(c *testing.T) { @@ -26,21 +28,19 @@ func (s *DockerCLIPortSuite) OnTimeout(c *testing.T) { func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { testRequires(c, DaemonIsLinux) + ctx := testutil.GetContext(c) + // one port out, _ := dockerCmd(c, "run", "-d", "-p", "9876:80", "busybox", "top") firstID := strings.TrimSpace(out) out, _ = dockerCmd(c, "port", firstID, "80") - err := assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876"}) - // Port list is not correct - assert.NilError(c, err) + assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876"}) out, _ = dockerCmd(c, "port", firstID) - err = assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876", "80/tcp -> [::]:9876"}) - // Port list is not correct - assert.NilError(c, err) + assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876", "80/tcp -> [::]:9876"}) dockerCmd(c, "rm", "-f", firstID) @@ -54,13 +54,11 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { out, _ = dockerCmd(c, "port", ID, "80") - err = assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876"}) - // Port list is not correct - assert.NilError(c, err) + assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876"}) out, _ = dockerCmd(c, "port", ID) - err = assertPortList(c, out, []string{ + assertPortList(c, out, []string{ "80/tcp -> 0.0.0.0:9876", "80/tcp -> [::]:9876", "81/tcp -> 0.0.0.0:9877", @@ -68,8 +66,6 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { "82/tcp -> 0.0.0.0:9878", "82/tcp -> [::]:9878", }) - // Port list is not correct - assert.NilError(c, err) dockerCmd(c, "rm", "-f", ID) @@ -84,13 +80,11 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { out, _ = dockerCmd(c, "port", ID, "80") - err = assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876", "0.0.0.0:9999", "[::]:9999"}) - // Port list is not correct - assert.NilError(c, err) + assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876", "0.0.0.0:9999", "[::]:9999"}) out, _ = dockerCmd(c, "port", ID) - err = assertPortList(c, out, []string{ + assertPortList(c, out, []string{ "80/tcp -> 0.0.0.0:9876", "80/tcp -> 0.0.0.0:9999", "80/tcp -> [::]:9876", @@ -100,8 +94,6 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { "82/tcp -> 0.0.0.0:9878", "82/tcp -> [::]:9878", }) - // Port list is not correct - assert.NilError(c, err) dockerCmd(c, "rm", "-f", ID) testRange := func() { @@ -113,16 +105,14 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { out, _ = dockerCmd(c, "port", IDs[i]) - err = assertPortList(c, out, []string{ + assertPortList(c, out, []string{ fmt.Sprintf("80/tcp -> 0.0.0.0:%d", 9090+i), fmt.Sprintf("80/tcp -> [::]:%d", 9090+i), }) - // Port list is not correct - assert.NilError(c, err) } // test port range exhaustion - out, _, err = dockerCmdWithError("run", "-d", "-p", "9090-9092:80", "busybox", "top") + out, _, err := dockerCmdWithError("run", "-d", "-p", "9090-9092:80", "busybox", "top") // Exhausted port range did not return an error assert.Assert(c, err != nil, "out: %s", out) @@ -136,7 +126,7 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { // test invalid port ranges for _, invalidRange := range []string{"9090-9089:80", "9090-:80", "-9090:80"} { - out, _, err = dockerCmdWithError("run", "-d", "-p", invalidRange, "busybox", "top") + out, _, err := dockerCmdWithError("run", "-d", "-p", invalidRange, "busybox", "top") // Port range should have returned an error assert.Assert(c, err != nil, "out: %s", out) } @@ -147,7 +137,7 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { out, _ = dockerCmd(c, "port", ID) - err = assertPortList(c, out, []string{ + assertPortList(c, out, []string{ "80/tcp -> 0.0.0.0:9800", "80/tcp -> [::]:9800", "81/tcp -> 0.0.0.0:9801", @@ -157,8 +147,6 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { "83/tcp -> 0.0.0.0:9803", "83/tcp -> [::]:9803", }) - // Port list is not correct - assert.NilError(c, err) dockerCmd(c, "rm", "-f", ID) // test mixing protocols in same port range @@ -168,18 +156,15 @@ func (s *DockerCLIPortSuite) TestPortList(c *testing.T) { out, _ = dockerCmd(c, "port", ID) // Running this test multiple times causes the TCP port to increment. - err = assertPortRange(ID, []int{8000, 8080}, []int{8000, 8080}) - // Port list is not correct - assert.NilError(c, err) + assertPortRange(ctx, ID, []int{8000, 8080}, []int{8000, 8080}) dockerCmd(c, "rm", "-f", ID) } -func assertPortList(c *testing.T, out string, expected []string) error { +func assertPortList(c *testing.T, out string, expected []string) { c.Helper() lines := strings.Split(strings.Trim(out, "\n "), "\n") - if len(lines) != len(expected) { - return fmt.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected)) - } + assert.Assert(c, is.Len(lines, len(expected)), "exepcted: %s", strings.Join(expected, ", ")) + sort.Strings(lines) sort.Strings(expected) @@ -196,17 +181,13 @@ func assertPortList(c *testing.T, out string, expected []string) error { if lines[i] == expected[i] { continue } - if lines[i] != oldFormat(expected[i]) { - return fmt.Errorf("|" + lines[i] + "!=" + expected[i] + "|") - } + assert.Equal(c, lines[i], oldFormat(expected[i])) } - - return nil } -func assertPortRange(id string, expectedTCP, expectedUDP []int) error { +func assertPortRange(ctx context.Context, id string, expectedTCP, expectedUDP []int) error { client := testEnv.APIClient() - inspect, err := client.ContainerInspect(context.TODO(), id) + inspect, err := client.ContainerInspect(ctx, id) if err != nil { return err } @@ -331,17 +312,15 @@ func (s *DockerCLIPortSuite) TestPortHostBinding(c *testing.T) { out, _ = dockerCmd(c, "port", firstID, "80") - err := assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876"}) - // Port list is not correct - assert.NilError(c, err) + assertPortList(c, out, []string{"0.0.0.0:9876", "[::]:9876"}) dockerCmd(c, "run", "--net=host", "busybox", "nc", "localhost", "9876") dockerCmd(c, "rm", "-f", firstID) - out, _, err = dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "9876") + out, _, err := dockerCmdWithError("run", "--net=host", "busybox", "nc", "localhost", "9876") // Port is still bound after the Container is removed - assert.Assert(c, err != nil, "out: %s", out) + assert.Assert(c, err != nil, out) } func (s *DockerCLIPortSuite) TestPortExposeHostBinding(c *testing.T) { diff --git a/integration-cli/docker_cli_proxy_test.go b/integration-cli/docker_cli_proxy_test.go index e138e5e39c..551dfcb973 100644 --- a/integration-cli/docker_cli_proxy_test.go +++ b/integration-cli/docker_cli_proxy_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "net" "strings" "testing" @@ -13,8 +14,8 @@ type DockerCLIProxySuite struct { ds *DockerSuite } -func (s *DockerCLIProxySuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIProxySuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIProxySuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_prune_unix_test.go b/integration-cli/docker_cli_prune_unix_test.go index 6e2162091f..a7241038e5 100644 --- a/integration-cli/docker_cli_prune_unix_test.go +++ b/integration-cli/docker_cli_prune_unix_test.go @@ -3,6 +3,7 @@ package main import ( + "context" "os" "path/filepath" "strconv" @@ -14,13 +15,14 @@ import ( "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" ) -func (s *DockerCLIPruneSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPruneSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPruneSuite) OnTimeout(c *testing.T) { @@ -49,7 +51,8 @@ func pruneNetworkAndVerify(c *testing.T, d *daemon.Daemon, kept, pruned []string } func (s *DockerSwarmSuite) TestPruneNetwork(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) _, err := d.Cmd("network", "create", "n1") // used by container (testprune) assert.NilError(c, err) _, err = d.Cmd("network", "create", "n2") @@ -72,7 +75,7 @@ func (s *DockerSwarmSuite) TestPruneNetwork(c *testing.T) { "busybox", "top") assert.NilError(c, err) assert.Assert(c, strings.TrimSpace(out) != "") - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(replicas+1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(replicas+1)), poll.WithTimeout(defaultReconciliationTimeout)) // prune and verify pruneNetworkAndVerify(c, d, []string{"n1", "n3"}, []string{"n2", "n4"}) @@ -82,13 +85,14 @@ func (s *DockerSwarmSuite) TestPruneNetwork(c *testing.T) { assert.NilError(c, err) _, err = d.Cmd("service", "rm", serviceName) assert.NilError(c, err) - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) pruneNetworkAndVerify(c, d, []string{}, []string{"n1", "n3"}) } func (s *DockerDaemonSuite) TestPruneImageDangling(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) result := cli.BuildCmd(c, "test", cli.Daemon(s.d), build.WithDockerfile(`FROM busybox @@ -258,7 +262,8 @@ func (s *DockerCLIPruneSuite) TestPruneNetworkLabel(c *testing.T) { } func (s *DockerDaemonSuite) TestPruneImageLabel(c *testing.T) { - s.d.StartWithBusybox(c) + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c) result := cli.BuildCmd(c, "test1", cli.Daemon(s.d), build.WithDockerfile(`FROM busybox diff --git a/integration-cli/docker_cli_ps_test.go b/integration-cli/docker_cli_ps_test.go index b5ae77286f..3b7bef0b6e 100644 --- a/integration-cli/docker_cli_ps_test.go +++ b/integration-cli/docker_cli_ps_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "sort" "strconv" @@ -22,8 +23,8 @@ type DockerCLIPsSuite struct { ds *DockerSuite } -func (s *DockerCLIPsSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPsSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPsSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_pull_test.go b/integration-cli/docker_cli_pull_test.go index f06640d3a3..27e83424de 100644 --- a/integration-cli/docker_cli_pull_test.go +++ b/integration-cli/docker_cli_pull_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "regexp" "strings" @@ -17,8 +18,8 @@ type DockerCLIPullSuite struct { ds *DockerSuite } -func (s *DockerCLIPullSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPullSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPullSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_push_test.go b/integration-cli/docker_cli_push_test.go index bea9ecdcd1..29065e5a70 100644 --- a/integration-cli/docker_cli_push_test.go +++ b/integration-cli/docker_cli_push_test.go @@ -2,6 +2,7 @@ package main import ( "archive/tar" + "context" "fmt" "net/http" "net/http/httptest" @@ -21,8 +22,8 @@ type DockerCLIPushSuite struct { ds *DockerSuite } -func (s *DockerCLIPushSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIPushSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIPushSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_registry_user_agent_test.go b/integration-cli/docker_cli_registry_user_agent_test.go index 13e2c8058e..0ddc2f7e19 100644 --- a/integration-cli/docker_cli_registry_user_agent_test.go +++ b/integration-cli/docker_cli_registry_user_agent_test.go @@ -7,6 +7,7 @@ import ( "regexp" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/registry" "gotest.tools/v3/assert" ) @@ -71,6 +72,7 @@ func registerUserAgentHandler(reg *registry.Mock, result *string) { // a registry, the registry should see a User-Agent string of the form // [docker engine UA] UpstreamClientSTREAM-CLIENT([client UA]) func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *testing.T) { + ctx := testutil.GetContext(c) var ua string reg, err := registry.NewMock(c) @@ -80,7 +82,7 @@ func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *testing.T) { registerUserAgentHandler(reg, &ua) repoName := fmt.Sprintf("%s/busybox", reg.URL()) - s.d.StartWithBusybox(c, "--insecure-registry", reg.URL()) + s.d.StartWithBusybox(ctx, c, "--insecure-registry", reg.URL()) tmp, err := os.MkdirTemp("", "integration-cli-") assert.NilError(c, err) diff --git a/integration-cli/docker_cli_restart_test.go b/integration-cli/docker_cli_restart_test.go index 2bd49ed1c3..3732a4756a 100644 --- a/integration-cli/docker_cli_restart_test.go +++ b/integration-cli/docker_cli_restart_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "os" "strconv" "strings" @@ -18,8 +19,8 @@ type DockerCLIRestartSuite struct { ds *DockerSuite } -func (s *DockerCLIRestartSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIRestartSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIRestartSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_rmi_test.go b/integration-cli/docker_cli_rmi_test.go index 57d23ce70c..7125cc89d9 100644 --- a/integration-cli/docker_cli_rmi_test.go +++ b/integration-cli/docker_cli_rmi_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "strings" "testing" @@ -17,8 +18,8 @@ type DockerCLIRmiSuite struct { ds *DockerSuite } -func (s *DockerCLIRmiSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIRmiSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIRmiSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index 0c4a9f93da..0487a60a7c 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -25,10 +25,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/integration-cli/daemon" "github.com/docker/docker/libnetwork/resolvconf" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" "github.com/docker/docker/testutil" + testdaemon "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "github.com/docker/go-connections/nat" "github.com/moby/sys/mountinfo" @@ -42,8 +44,8 @@ type DockerCLIRunSuite struct { ds *DockerSuite } -func (s *DockerCLIRunSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIRunSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIRunSuite) OnTimeout(c *testing.T) { @@ -3795,7 +3797,7 @@ func (s *DockerCLIRunSuite) TestRunNamedVolumesFromNotRemoved(c *testing.T) { assert.NilError(c, err) defer apiClient.Close() - container, err := apiClient.ContainerInspect(context.Background(), strings.TrimSpace(cid)) + container, err := apiClient.ContainerInspect(testutil.GetContext(c), strings.TrimSpace(cid)) assert.NilError(c, err) var vname string for _, v := range container.Mounts { @@ -3816,19 +3818,40 @@ func (s *DockerCLIRunSuite) TestRunNamedVolumesFromNotRemoved(c *testing.T) { } func (s *DockerCLIRunSuite) TestRunAttachFailedNoLeak(c *testing.T) { - nroutines, err := getGoroutineNumber() + testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) + ctx := testutil.GetContext(c) + d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvVars("OTEL_SDK_DISABLED=1")) + defer func() { + if c.Failed() { + d.Daemon.DumpStackAndQuit() + } else { + d.Stop(c) + } + d.Cleanup(c) + }() + d.StartWithBusybox(ctx, c) + + // Run a dummy container to ensure all goroutines are up and running before we get a count + _, err := d.Cmd("run", "--rm", "busybox", "true") assert.NilError(c, err) - runSleepingContainer(c, "--name=test", "-p", "8000:8000") + client := d.NewClientT(c) + + nroutines := waitForStableGourtineCount(ctx, c, client) + + out, err := d.Cmd(append([]string{"run", "-d", "--name=test", "-p", "8000:8000", "busybox"}, sleepCommandForDaemonPlatform()...)...) + assert.NilError(c, err, out) // Wait until container is fully up and running - assert.Assert(c, waitRun("test") == nil) + assert.NilError(c, d.WaitRun("test")) + + out, err = d.Cmd("run", "--name=fail", "-p", "8000:8000", "busybox", "true") - out, _, err := dockerCmdWithError("run", "--name=fail", "-p", "8000:8000", "busybox", "true") // We will need the following `inspect` to diagnose the issue if test fails (#21247) - out1, err1 := dockerCmd(c, "inspect", "--format", "{{json .State}}", "test") - out2, err2 := dockerCmd(c, "inspect", "--format", "{{json .State}}", "fail") + out1, err1 := d.Cmd("inspect", "--format", "{{json .State}}", "test") + out2, err2 := d.Cmd("inspect", "--format", "{{json .State}}", "fail") assert.Assert(c, err != nil, "Command should have failed but succeeded with: %s\nContainer 'test' [%+v]: %s\nContainer 'fail' [%+v]: %s", out, err1, out1, err2, out2) + // check for windows error as well // TODO Windows Post TP5. Fix the error message string outLowerCase := strings.ToLower(out) @@ -3837,10 +3860,12 @@ func (s *DockerCLIRunSuite) TestRunAttachFailedNoLeak(c *testing.T) { strings.Contains(outLowerCase, "the specified port already exists") || strings.Contains(outLowerCase, "hns failed with error : failed to create endpoint") || strings.Contains(outLowerCase, "hns failed with error : the object already exists"), fmt.Sprintf("Output: %s", out)) - dockerCmd(c, "rm", "-f", "test") + + out, err = d.Cmd("rm", "-f", "test") + assert.NilError(c, err, out) // NGoroutines is not updated right away, so we need to wait before failing - assert.Assert(c, waitForGoroutines(nroutines) == nil) + waitForGoroutines(ctx, c, client, nroutines) } // Test for one character directory name case (#20122) @@ -3993,35 +4018,44 @@ exec "$@"`, } func (s *DockerDaemonSuite) TestRunWithUlimitAndDaemonDefault(c *testing.T) { - s.d.StartWithBusybox(c, "--debug", "--default-ulimit=nofile=65535") + ctx := testutil.GetContext(c) + d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvVars("OTEL_SDK_DISABLED=1")) + defer func() { + d.Stop(c) + d.Cleanup(c) + }() + d.StartWithBusybox(ctx, c, "--debug", "--default-ulimit=nofile=65535") name := "test-A" - _, err := s.d.Cmd("run", "--name", name, "-d", "busybox", "top") + _, err := d.Cmd("run", "--name", name, "-d", "busybox", "top") assert.NilError(c, err) - assert.NilError(c, s.d.WaitRun(name)) + assert.NilError(c, d.WaitRun(name)) - out, err := s.d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name) + out, err := d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name) assert.NilError(c, err) assert.Assert(c, strings.Contains(out, "[nofile=65535:65535]")) name = "test-B" - _, err = s.d.Cmd("run", "--name", name, "--ulimit=nofile=42", "-d", "busybox", "top") + _, err = d.Cmd("run", "--name", name, "--ulimit=nofile=42", "-d", "busybox", "top") assert.NilError(c, err) - assert.NilError(c, s.d.WaitRun(name)) + assert.NilError(c, d.WaitRun(name)) - out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name) + out, err = d.Cmd("inspect", "--format", "{{.HostConfig.Ulimits}}", name) assert.NilError(c, err) assert.Assert(c, strings.Contains(out, "[nofile=42:42]")) } func (s *DockerCLIRunSuite) TestRunStoppedLoggingDriverNoLeak(c *testing.T) { - nroutines, err := getGoroutineNumber() + client := testEnv.APIClient() + ctx := testutil.GetContext(c) + nroutines, err := getGoroutineNumber(ctx, client) assert.NilError(c, err) out, _, err := dockerCmdWithError("run", "--name=fail", "--log-driver=splunk", "busybox", "true") assert.ErrorContains(c, err, "") assert.Assert(c, strings.Contains(out, "failed to initialize logging driver"), "error should be about logging driver, got output %s", out) + // NGoroutines is not updated right away, so we need to wait before failing - assert.Assert(c, waitForGoroutines(nroutines) == nil) + waitForGoroutines(ctx, c, client, nroutines) } // Handles error conditions for --credentialspec. Validating E2E success cases diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index 161bef1148..d2049bb4fc 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -4,7 +4,6 @@ package main import ( "bufio" - "context" "encoding/json" "fmt" "os" @@ -24,6 +23,7 @@ import ( "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/sysinfo" + "github.com/docker/docker/testutil" "github.com/moby/sys/mount" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" @@ -993,7 +993,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompProfileDenyUnshareUserns(c *testing.T) // with a the default seccomp profile exits with operation not permitted. func (s *DockerCLIRunSuite) TestRunSeccompProfileDenyCloneUserns(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, seccompEnabled) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) icmd.RunCommand(dockerBinary, "run", "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{ ExitCode: 1, @@ -1005,7 +1005,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompProfileDenyCloneUserns(c *testing.T) { // 'docker run --security-opt seccomp=unconfined syscall-test' allows creating a userns. func (s *DockerCLIRunSuite) TestRunSeccompUnconfinedCloneUserns(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, seccompEnabled, UserNamespaceInKernel, NotUserNamespace, unprivilegedUsernsClone) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // make sure running w privileged is ok icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined", @@ -1018,7 +1018,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompUnconfinedCloneUserns(c *testing.T) { // allows creating a userns. func (s *DockerCLIRunSuite) TestRunSeccompAllowPrivCloneUserns(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, seccompEnabled, UserNamespaceInKernel, NotUserNamespace) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // make sure running w privileged is ok icmd.RunCommand(dockerBinary, "run", "--privileged", "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{ @@ -1030,7 +1030,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompAllowPrivCloneUserns(c *testing.T) { // with the default seccomp profile. func (s *DockerCLIRunSuite) TestRunSeccompProfileAllow32Bit(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, seccompEnabled, IsAmd64) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) icmd.RunCommand(dockerBinary, "run", "syscall-test", "exit32-test").Assert(c, icmd.Success) } @@ -1045,7 +1045,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompAllowSetrlimit(c *testing.T) { func (s *DockerCLIRunSuite) TestRunSeccompDefaultProfileAcct(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, seccompEnabled, NotUserNamespace) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) out, _, err := dockerCmdWithError("run", "syscall-test", "acct-test") if err == nil || !strings.Contains(out, "Operation not permitted") { @@ -1075,7 +1075,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompDefaultProfileAcct(c *testing.T) { func (s *DockerCLIRunSuite) TestRunSeccompDefaultProfileNS(c *testing.T) { testRequires(c, testEnv.IsLocalDaemon, seccompEnabled, NotUserNamespace) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) out, _, err := dockerCmdWithError("run", "syscall-test", "ns-test", "echo", "hello0") if err == nil || !strings.Contains(out, "Operation not permitted") { @@ -1112,7 +1112,7 @@ func (s *DockerCLIRunSuite) TestRunSeccompDefaultProfileNS(c *testing.T) { // effective uid transitions on executing setuid binaries. func (s *DockerCLIRunSuite) TestRunNoNewPrivSetuid(c *testing.T) { testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon) - ensureNNPTest(c) + ensureNNPTest(testutil.GetContext(c), c) // test that running a setuid binary results in no effective uid transition icmd.RunCommand(dockerBinary, "run", "--security-opt", "no-new-privileges=true", "--user", "1000", @@ -1125,7 +1125,7 @@ func (s *DockerCLIRunSuite) TestRunNoNewPrivSetuid(c *testing.T) { // effective uid transitions on executing setuid binaries. func (s *DockerCLIRunSuite) TestLegacyRunNoNewPrivSetuid(c *testing.T) { testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon) - ensureNNPTest(c) + ensureNNPTest(testutil.GetContext(c), c) // test that running a setuid binary results in no effective uid transition icmd.RunCommand(dockerBinary, "run", "--security-opt", "no-new-privileges", "--user", "1000", @@ -1136,7 +1136,7 @@ func (s *DockerCLIRunSuite) TestLegacyRunNoNewPrivSetuid(c *testing.T) { func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesChown(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_CHOWN dockerCmd(c, "run", "busybox", "chown", "100", "/tmp") @@ -1154,7 +1154,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesChown(c *testing.T) { func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesDacOverride(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_DAC_OVERRIDE dockerCmd(c, "run", "busybox", "sh", "-c", "echo test > /etc/passwd") @@ -1167,7 +1167,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesDacOverride(c *testin func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesFowner(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_FOWNER dockerCmd(c, "run", "busybox", "chmod", "777", "/etc/passwd") @@ -1183,7 +1183,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesFowner(c *testing.T) func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesSetuid(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_SETUID dockerCmd(c, "run", "syscall-test", "setuid-test") @@ -1201,7 +1201,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesSetuid(c *testing.T) func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesSetgid(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_SETGID dockerCmd(c, "run", "syscall-test", "setgid-test") @@ -1229,7 +1229,7 @@ func sysctlExists(s string) bool { func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesNetBindService(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_NET_BIND_SERVICE dockerCmd(c, "run", "syscall-test", "socket-test") @@ -1258,7 +1258,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesNetBindService(c *tes func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesNetRaw(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_NET_RAW dockerCmd(c, "run", "syscall-test", "raw-test") @@ -1276,7 +1276,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesNetRaw(c *testing.T) func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesChroot(c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_SYS_CHROOT dockerCmd(c, "run", "busybox", "chroot", "/", "/bin/true") @@ -1294,7 +1294,7 @@ func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesChroot(c *testing.T) func (s *DockerCLIRunSuite) TestUserNoEffectiveCapabilitiesMknod(c *testing.T) { testRequires(c, DaemonIsLinux, NotUserNamespace, testEnv.IsLocalDaemon) - ensureSyscallTest(c) + ensureSyscallTest(testutil.GetContext(c), c) // test that a root user has default capability CAP_MKNOD dockerCmd(c, "run", "busybox", "mknod", "/tmp/node", "b", "1", "2") @@ -1428,8 +1428,9 @@ func (s *DockerCLIRunSuite) TestRunUserDeviceAllowed(c *testing.T) { func (s *DockerDaemonSuite) TestRunSeccompJSONNewFormat(c *testing.T) { testRequires(c, seccompEnabled) + ctx := testutil.GetContext(c) - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) jsonData := `{ "defaultAction": "SCMP_ACT_ALLOW", @@ -1453,8 +1454,9 @@ func (s *DockerDaemonSuite) TestRunSeccompJSONNewFormat(c *testing.T) { func (s *DockerDaemonSuite) TestRunSeccompJSONNoNameAndNames(c *testing.T) { testRequires(c, seccompEnabled) + ctx := testutil.GetContext(c) - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) jsonData := `{ "defaultAction": "SCMP_ACT_ALLOW", @@ -1479,8 +1481,9 @@ func (s *DockerDaemonSuite) TestRunSeccompJSONNoNameAndNames(c *testing.T) { func (s *DockerDaemonSuite) TestRunSeccompJSONNoArchAndArchMap(c *testing.T) { testRequires(c, seccompEnabled) + ctx := testutil.GetContext(c) - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) jsonData := `{ "archMap": [ @@ -1516,8 +1519,9 @@ func (s *DockerDaemonSuite) TestRunSeccompJSONNoArchAndArchMap(c *testing.T) { func (s *DockerDaemonSuite) TestRunWithDaemonDefaultSeccompProfile(c *testing.T) { testRequires(c, seccompEnabled) + ctx := testutil.GetContext(c) - s.d.StartWithBusybox(c) + s.d.StartWithBusybox(ctx, c) // 1) verify I can run containers with the Docker default shipped profile which allows chmod _, err := s.d.Cmd("run", "busybox", "chmod", "777", ".") @@ -1560,7 +1564,7 @@ func (s *DockerCLIRunSuite) TestRunWithNanoCPUs(c *testing.T) { clt, err := client.NewClientWithOpts(client.FromEnv) assert.NilError(c, err) - inspect, err := clt.ContainerInspect(context.Background(), "test") + inspect, err := clt.ContainerInspect(testutil.GetContext(c), "test") assert.NilError(c, err) assert.Equal(c, inspect.HostConfig.NanoCPUs, int64(500000000)) diff --git a/integration-cli/docker_cli_save_load_test.go b/integration-cli/docker_cli_save_load_test.go index a46fd16011..143f4435dd 100644 --- a/integration-cli/docker_cli_save_load_test.go +++ b/integration-cli/docker_cli_save_load_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "os" "os/exec" @@ -17,8 +18,8 @@ type DockerCLISaveLoadSuite struct { ds *DockerSuite } -func (s *DockerCLISaveLoadSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLISaveLoadSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLISaveLoadSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_save_load_unix_test.go b/integration-cli/docker_cli_save_load_unix_test.go index 0c9c4e3fad..ee61f24529 100644 --- a/integration-cli/docker_cli_save_load_unix_test.go +++ b/integration-cli/docker_cli_save_load_unix_test.go @@ -13,6 +13,7 @@ import ( "github.com/creack/pty" "github.com/docker/docker/integration-cli/cli/build" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) @@ -90,7 +91,7 @@ func (s *DockerCLISaveLoadSuite) TestSaveAndLoadWithProgressBar(c *testing.T) { func (s *DockerCLISaveLoadSuite) TestLoadNoStdinFail(c *testing.T) { pty, tty, err := pty.Open() assert.NilError(c, err) - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + ctx, cancel := context.WithTimeout(testutil.GetContext(c), 5*time.Second) defer cancel() cmd := exec.CommandContext(ctx, dockerBinary, "load") cmd.Stdin = tty diff --git a/integration-cli/docker_cli_search_test.go b/integration-cli/docker_cli_search_test.go index 3c60ca9df9..af89c7b869 100644 --- a/integration-cli/docker_cli_search_test.go +++ b/integration-cli/docker_cli_search_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "strings" "testing" @@ -12,8 +13,8 @@ type DockerCLISearchSuite struct { ds *DockerSuite } -func (s *DockerCLISearchSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLISearchSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLISearchSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_service_create_test.go b/integration-cli/docker_cli_service_create_test.go index a56fedc0d8..23036e2226 100644 --- a/integration-cli/docker_cli_service_create_test.go +++ b/integration-cli/docker_cli_service_create_test.go @@ -13,26 +13,28 @@ import ( "github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/integration-cli/checker" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" ) func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--mount", "type=volume,source=foo,target=/foo,volume-nocopy", "busybox", "top") assert.NilError(c, err, out) id := strings.TrimSpace(out) var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, id) + tasks = d.GetServiceTasks(ctx, c, id) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -66,7 +68,8 @@ func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceCreateWithSecretSimple(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) serviceName := "test-service-secret" testName := "test_secret" @@ -100,7 +103,8 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretSimple(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTargetPaths(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) testPaths := map[string]string{ "app": "/etc/secret", @@ -139,14 +143,14 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTargetPaths(c *testi var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, serviceName) + tasks = d.GetServiceTasks(ctx, c, serviceName) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -166,7 +170,8 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTargetPaths(c *testi } func (s *DockerSwarmSuite) TestServiceCreateWithSecretReferencedTwice(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) id := d.CreateSecret(c, swarm.SecretSpec{ Annotations: swarm.Annotations{ @@ -189,14 +194,14 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretReferencedTwice(c *testing var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, serviceName) + tasks = d.GetServiceTasks(ctx, c, serviceName) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -214,7 +219,8 @@ func (s *DockerSwarmSuite) TestServiceCreateWithSecretReferencedTwice(c *testing } func (s *DockerSwarmSuite) TestServiceCreateWithConfigSimple(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) serviceName := "test-service-config" testName := "test_config" @@ -248,7 +254,8 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigSimple(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceCreateWithConfigSourceTargetPaths(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) testPaths := map[string]string{ "app": "/etc/config", @@ -286,14 +293,14 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigSourceTargetPaths(c *testi var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, serviceName) + tasks = d.GetServiceTasks(ctx, c, serviceName) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -313,7 +320,8 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigSourceTargetPaths(c *testi } func (s *DockerSwarmSuite) TestServiceCreateWithConfigReferencedTwice(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) id := d.CreateConfig(c, swarm.ConfigSpec{ Annotations: swarm.Annotations{ @@ -336,14 +344,14 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigReferencedTwice(c *testing var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, serviceName) + tasks = d.GetServiceTasks(ctx, c, serviceName) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -361,21 +369,22 @@ func (s *DockerSwarmSuite) TestServiceCreateWithConfigReferencedTwice(c *testing } func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, 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; exec tail -f /dev/null") assert.NilError(c, err, out) id := strings.TrimSpace(out) var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, id) + tasks = d.GetServiceTasks(ctx, c, id) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -414,7 +423,8 @@ func (s *DockerSwarmSuite) TestServiceCreateMountTmpfs(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceCreateWithNetworkAlias(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "--scope=swarm", "test_swarm_br") assert.NilError(c, err, out) @@ -424,14 +434,14 @@ func (s *DockerSwarmSuite) TestServiceCreateWithNetworkAlias(c *testing.T) { var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, id) + tasks = d.GetServiceTasks(ctx, c, id) return len(tasks) > 0, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) task := tasks[0] poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { if task.NodeID == "" || task.Status.ContainerStatus == nil { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) } return task.NodeID != "" && task.Status.ContainerStatus != nil, "" }, checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) diff --git a/integration-cli/docker_cli_service_health_test.go b/integration-cli/docker_cli_service_health_test.go index c5330a2a07..dfb6ed9397 100644 --- a/integration-cli/docker_cli_service_health_test.go +++ b/integration-cli/docker_cli_service_health_test.go @@ -12,6 +12,7 @@ import ( "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/cli/build" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" @@ -22,7 +23,8 @@ import ( func (s *DockerSwarmSuite) TestServiceHealthRun(c *testing.T) { testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // build image with health-check imageName := "testhealth" @@ -41,7 +43,7 @@ func (s *DockerSwarmSuite) TestServiceHealthRun(c *testing.T) { var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, id) + tasks = d.GetServiceTasks(ctx, c, id) return tasks, "" }, checker.HasLen(1)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -49,7 +51,7 @@ func (s *DockerSwarmSuite) TestServiceHealthRun(c *testing.T) { // wait for task to start poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) return task.Status.State, "" }, checker.Equals(swarm.TaskStateRunning)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -71,7 +73,7 @@ func (s *DockerSwarmSuite) TestServiceHealthRun(c *testing.T) { // Task should be terminated poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) return task.Status.State, "" }, checker.Equals(swarm.TaskStateFailed)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -85,7 +87,8 @@ func (s *DockerSwarmSuite) TestServiceHealthRun(c *testing.T) { func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) { testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // service started from this image won't pass health check imageName := "testhealth" @@ -103,7 +106,7 @@ func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) { var tasks []swarm.Task poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - tasks = d.GetServiceTasks(c, id) + tasks = d.GetServiceTasks(ctx, c, id) return tasks, "" }, checker.HasLen(1)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -111,7 +114,7 @@ func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) { // wait for task to start poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) return task.Status.State, "" }, checker.Equals(swarm.TaskStateStarting)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -125,7 +128,7 @@ func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) { }, checker.GreaterThan(0)), poll.WithTimeout(defaultReconciliationTimeout)) // task should be blocked at starting status - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) assert.Equal(c, task.Status.State, swarm.TaskStateStarting) // make it healthy @@ -133,7 +136,7 @@ func (s *DockerSwarmSuite) TestServiceHealthStart(c *testing.T) { // Task should be at running status poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { - task = d.GetTask(c, task.ID) + task = d.GetTask(ctx, c, task.ID) return task.Status.State, "" }, checker.Equals(swarm.TaskStateRunning)), poll.WithTimeout(defaultReconciliationTimeout)) } diff --git a/integration-cli/docker_cli_service_logs_test.go b/integration-cli/docker_cli_service_logs_test.go index 7e3b52b0c7..150f5075be 100644 --- a/integration-cli/docker_cli_service_logs_test.go +++ b/integration-cli/docker_cli_service_logs_test.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" "gotest.tools/v3/poll" @@ -24,7 +25,8 @@ type logMessage struct { } func (s *DockerSwarmSuite) TestServiceLogs(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // we have multiple services here for detecting the goroutine issue #28915 services := map[string]string{ @@ -41,7 +43,7 @@ func (s *DockerSwarmSuite) TestServiceLogs(c *testing.T) { // make sure task has been deployed. poll.WaitOn(c, pollCheck(c, - d.CheckRunningTaskImages, checker.DeepEquals(map[string]int{"busybox:latest": len(services)})), poll.WithTimeout(defaultReconciliationTimeout)) + d.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{"busybox:latest": len(services)})), poll.WithTimeout(defaultReconciliationTimeout)) for name, message := range services { out, err := d.Cmd("service", "logs", name) @@ -69,7 +71,8 @@ func countLogLines(d *daemon.Daemon, name string) func(*testing.T) (interface{}, } func (s *DockerSwarmSuite) TestServiceLogsCompleteness(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsCompleteness" @@ -79,7 +82,7 @@ func (s *DockerSwarmSuite) TestServiceLogsCompleteness(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // and make sure we have all the log lines poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(6)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -96,7 +99,8 @@ func (s *DockerSwarmSuite) TestServiceLogsCompleteness(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsTail(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsTail" @@ -106,7 +110,7 @@ func (s *DockerSwarmSuite) TestServiceLogsTail(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(6)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("service", "logs", "--tail=2", name) @@ -120,15 +124,16 @@ func (s *DockerSwarmSuite) TestServiceLogsTail(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsSince(c *testing.T) { + ctx := testutil.GetContext(c) // See DockerSuite.TestLogsSince, which is where this comes from - d := s.AddDaemon(c, true, true) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsSince" 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 -f /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)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // wait a sec for the logs to come in poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(3)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -155,7 +160,8 @@ func (s *DockerSwarmSuite) TestServiceLogsSince(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsFollow" @@ -164,7 +170,7 @@ func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) args := []string{"service", "logs", "-f", name} cmd := exec.Command(dockerBinary, d.PrependHostArg(args)...) @@ -207,7 +213,8 @@ func (s *DockerSwarmSuite) TestServiceLogsFollow(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsTaskLogs(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServicelogsTaskLogs" replicas := 2 @@ -233,7 +240,7 @@ func (s *DockerSwarmSuite) TestServiceLogsTaskLogs(c *testing.T) { result.Assert(c, icmd.Expected{Out: id}) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(replicas)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(replicas)), poll.WithTimeout(defaultReconciliationTimeout)) poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(6*replicas)), poll.WithTimeout(defaultReconciliationTimeout)) // get the task ids @@ -260,7 +267,8 @@ func (s *DockerSwarmSuite) TestServiceLogsTaskLogs(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsTTY(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsTTY" @@ -286,7 +294,7 @@ func (s *DockerSwarmSuite) TestServiceLogsTTY(c *testing.T) { result.Assert(c, icmd.Expected{Out: id}) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // and make sure we have all the log lines poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -298,7 +306,8 @@ func (s *DockerSwarmSuite) TestServiceLogsTTY(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsNoHangDeletedContainer" @@ -320,7 +329,7 @@ func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *testing.T) { assert.Assert(c, id != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // and make sure we have all the log lines poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout)) @@ -345,7 +354,8 @@ func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *testing.T) { } func (s *DockerSwarmSuite) TestServiceLogsDetails(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "TestServiceLogsDetails" @@ -371,7 +381,7 @@ func (s *DockerSwarmSuite) TestServiceLogsDetails(c *testing.T) { assert.Assert(c, id != "") // make sure task has been deployed - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // and make sure we have all the log lines poll.WaitOn(c, pollCheck(c, countLogLines(d, name), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) diff --git a/integration-cli/docker_cli_service_scale_test.go b/integration-cli/docker_cli_service_scale_test.go index 4f7e114839..716615f9f9 100644 --- a/integration-cli/docker_cli_service_scale_test.go +++ b/integration-cli/docker_cli_service_scale_test.go @@ -7,11 +7,13 @@ import ( "strings" "testing" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" ) func (s *DockerSwarmSuite) TestServiceScale(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) service1Name := "TestService1" service1Args := append([]string{"service", "create", "--detach", "--no-resolve-image", "--name", service1Name, "busybox"}, sleepCommandForDaemonPlatform()...) diff --git a/integration-cli/docker_cli_sni_test.go b/integration-cli/docker_cli_sni_test.go index 23dc0969c9..e72b83d961 100644 --- a/integration-cli/docker_cli_sni_test.go +++ b/integration-cli/docker_cli_sni_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "io" "log" @@ -18,8 +19,8 @@ type DockerCLISNISuite struct { ds *DockerSuite } -func (s *DockerCLISNISuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLISNISuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLISNISuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_start_test.go b/integration-cli/docker_cli_start_test.go index eb91b69574..229aebd468 100644 --- a/integration-cli/docker_cli_start_test.go +++ b/integration-cli/docker_cli_start_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "strings" "testing" @@ -15,8 +16,8 @@ type DockerCLIStartSuite struct { ds *DockerSuite } -func (s *DockerCLIStartSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIStartSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIStartSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_stats_test.go b/integration-cli/docker_cli_stats_test.go index c29f10cab4..070e149905 100644 --- a/integration-cli/docker_cli_stats_test.go +++ b/integration-cli/docker_cli_stats_test.go @@ -2,6 +2,7 @@ package main import ( "bufio" + "context" "os/exec" "regexp" "strings" @@ -17,8 +18,8 @@ type DockerCLIStatsSuite struct { ds *DockerSuite } -func (s *DockerCLIStatsSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIStatsSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIStatsSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_swarm_test.go b/integration-cli/docker_cli_swarm_test.go index 53291aa177..856ef76c03 100644 --- a/integration-cli/docker_cli_swarm_test.go +++ b/integration-cli/docker_cli_swarm_test.go @@ -27,6 +27,7 @@ import ( "github.com/docker/docker/libnetwork/ipamapi" remoteipam "github.com/docker/docker/libnetwork/ipams/remote/api" "github.com/docker/docker/pkg/plugins" + "github.com/docker/docker/testutil" "github.com/moby/swarmkit/v2/ca/keyutils" "github.com/vishvananda/netlink" "gotest.tools/v3/assert" @@ -36,7 +37,8 @@ import ( ) func (s *DockerSwarmSuite) TestSwarmUpdate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) getSpec := func() swarm.Spec { sw := d.GetSwarm(c) @@ -84,7 +86,8 @@ func (s *DockerSwarmSuite) TestSwarmUpdate(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmInit(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) getSpec := func() swarm.Spec { sw := d.GetSwarm(c) @@ -118,7 +121,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *testing.T) { assert.Equal(c, spec.CAConfig.ExternalCAs[0].CACert, "") assert.Equal(c, spec.CAConfig.ExternalCAs[1].CACert, string(expected)) - assert.Assert(c, d.SwarmLeave(c, true) == nil) + assert.Assert(c, d.SwarmLeave(ctx, c, true) == nil) cli.Docker(cli.Args("swarm", "init"), cli.Daemon(d)).Assert(c, icmd.Success) spec = getSpec() @@ -128,10 +131,11 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *testing.T) { func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *testing.T) { testRequires(c, IPv6) - d1 := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, false, false) cli.Docker(cli.Args("swarm", "init", "--listen-add", "::1"), cli.Daemon(d1)).Assert(c, icmd.Success) - d2 := s.AddDaemon(c, false, false) + d2 := s.AddDaemon(ctx, c, false, false) cli.Docker(cli.Args("swarm", "join", "::1"), cli.Daemon(d2)).Assert(c, icmd.Success) out := cli.Docker(cli.Args("info"), cli.Daemon(d2)).Assert(c, icmd.Success).Combined() @@ -139,16 +143,18 @@ func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedAdvertiseAddr(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) out, err := d.Cmd("swarm", "init", "--advertise-addr", "0.0.0.0") assert.ErrorContains(c, err, "") assert.Assert(c, strings.Contains(out, "advertise address must be a non-zero IP address")) } func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *testing.T) { + ctx := testutil.GetContext(c) // init swarm mode and stop a daemon - d := s.AddDaemon(c, true, true) - info := d.SwarmInfo(c) + d := s.AddDaemon(ctx, c, true, true) + info := d.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) d.Stop(c) @@ -163,7 +169,8 @@ func (s *DockerSwarmSuite) TestSwarmIncompatibleDaemon(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) hostname, err := d.Cmd("node", "inspect", "--format", "{{.Description.Hostname}}", "self") assert.Assert(c, err == nil, hostname) @@ -171,9 +178,9 @@ func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *testing.T) { assert.NilError(c, err, out) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) - containers := d.ActiveContainers(c) + containers := d.ActiveContainers(testutil.GetContext(c), c) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.Hostname}}", containers[0]) assert.NilError(c, err, out) assert.Equal(c, strings.Split(out, "\n")[0], "test-1-"+strings.Split(hostname, "\n")[0], "hostname with templating invalid") @@ -181,7 +188,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *testing.T) { // Test case for #24270 func (s *DockerSwarmSuite) TestSwarmServiceListFilter(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name1 := "redis-cluster-md5" name2 := "redis-cluster" @@ -220,7 +228,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceListFilter(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmNodeListFilter(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("node", "inspect", "--format", "{{ .Description.Hostname }}", "self") assert.NilError(c, err, out) @@ -238,7 +247,8 @@ func (s *DockerSwarmSuite) TestSwarmNodeListFilter(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "redis-cluster-md5" out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--replicas=3", "busybox", "top") @@ -246,7 +256,7 @@ func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(3)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(3)), poll.WithTimeout(defaultReconciliationTimeout)) filter := "name=redis-cluster" @@ -264,7 +274,8 @@ func (s *DockerSwarmSuite) TestSwarmNodeTaskListFilter(c *testing.T) { // Test case for #25375 func (s *DockerSwarmSuite) TestSwarmPublishAdd(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "top" // this first command does not have to be retried because service creates @@ -290,7 +301,8 @@ func (s *DockerSwarmSuite) TestSwarmPublishAdd(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "top" out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--user", "root:root", "--group", "wheel", "--group", "audio", "--group", "staff", "--group", "777", "busybox", "top") @@ -298,7 +310,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("ps", "-q") assert.NilError(c, err, out) @@ -312,7 +324,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceWithGroup(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmContainerAutoStart(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", "foo") assert.NilError(c, err, out) @@ -334,7 +347,8 @@ func (s *DockerSwarmSuite) TestSwarmContainerAutoStart(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmContainerEndpointOptions(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", "foo") assert.NilError(c, err, out) @@ -359,7 +373,8 @@ func (s *DockerSwarmSuite) TestSwarmContainerEndpointOptions(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmContainerAttachByNetworkId(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", "testnet") assert.NilError(c, err, out) @@ -387,7 +402,8 @@ func (s *DockerSwarmSuite) TestSwarmContainerAttachByNetworkId(c *testing.T) { } func (s *DockerSwarmSuite) TestOverlayAttachable(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", "ovnet") assert.NilError(c, err, out) @@ -409,7 +425,8 @@ func (s *DockerSwarmSuite) TestOverlayAttachable(c *testing.T) { } func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create an attachable swarm network nwName := "attovl" @@ -421,7 +438,7 @@ func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *testing.T) { assert.NilError(c, err, out) // Leave the swarm - assert.Assert(c, d.SwarmLeave(c, true) == nil) + assert.Assert(c, d.SwarmLeave(ctx, c, true) == nil) // Check the container is disconnected out, err = d.Cmd("inspect", "c1", "--format", "{{.NetworkSettings.Networks."+nwName+"}}") @@ -435,7 +452,8 @@ func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *testing.T) { } func (s *DockerSwarmSuite) TestOverlayAttachableReleaseResourcesOnFailure(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create attachable network out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", "--subnet", "10.10.9.0/24", "ovnet") @@ -459,7 +477,8 @@ func (s *DockerSwarmSuite) TestOverlayAttachableReleaseResourcesOnFailure(c *tes } func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Ingress network can be removed removeNetwork := func(name string) *icmd.Result { @@ -510,7 +529,8 @@ func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmCreateServiceWithNoIngressNetwork(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Remove ingress network result := cli.Docker( @@ -529,7 +549,8 @@ func (s *DockerSwarmSuite) TestSwarmCreateServiceWithNoIngressNetwork(c *testing // Test case for #24108, also the case from: // https://github.com/docker/docker/pull/24620#issuecomment-233715656 func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "redis-cluster-md5" out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", name, "--replicas=3", "busybox", "top") @@ -582,7 +603,8 @@ func (s *DockerSwarmSuite) TestSwarmTaskListFilter(c *testing.T) { } func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create a bare container out, err := d.Cmd("run", "-d", "--name=bare-container", "busybox", "top") @@ -595,7 +617,7 @@ func (s *DockerSwarmSuite) TestPsListContainersFilterIsTask(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckServiceRunningTasks(name), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckServiceRunningTasks(ctx, name), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // Filter non-tasks out, err = d.Cmd("ps", "-a", "-q", "--filter=is-task=false") @@ -785,6 +807,7 @@ func setupRemoteGlobalNetworkPlugin(c *testing.T, mux *http.ServeMux, url, netDr } func (s *DockerSwarmSuite) TestSwarmNetworkPlugin(c *testing.T) { + ctx := testutil.GetContext(c) mux := http.NewServeMux() s.server = httptest.NewServer(mux) assert.Assert(c, s.server != nil) // check that HTTP server has started @@ -795,7 +818,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPlugin(c *testing.T) { assert.NilError(c, err) }() - d := s.AddDaemon(c, true, true) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "-d", globalNetworkPlugin, "foo") assert.ErrorContains(c, err, "", out) @@ -804,7 +827,8 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPlugin(c *testing.T) { // Test case for #24712 func (s *DockerSwarmSuite) TestSwarmServiceEnvFile(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) path := filepath.Join(d.Folder, "env.txt") err := os.WriteFile(path, []byte("VAR1=A\nVAR2=A\n"), 0o644) @@ -822,7 +846,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceEnvFile(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "top" @@ -834,7 +859,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) { assert.NilError(c, err, out) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // We need to get the container id. out, err = d.Cmd("ps", "-q", "--no-trunc") @@ -848,7 +873,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) { out, err = d.Cmd("service", "rm", name) assert.NilError(c, err, out) // Make sure container has been destroyed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) // With --tty expectedOutput = "TTY" @@ -856,7 +881,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) { assert.NilError(c, err, out) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // We need to get the container id. out, err = d.Cmd("ps", "-q", "--no-trunc") @@ -869,7 +894,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create a service name := "top" @@ -877,7 +903,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *testing.T) { assert.NilError(c, err, out) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.TTY }}", name) assert.NilError(c, err, out) @@ -892,7 +918,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTYUpdate(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmServiceNetworkUpdate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) result := icmd.RunCmd(d.Command("network", "create", "-d", "overlay", "foo")) result.Assert(c, icmd.Success) @@ -912,23 +939,24 @@ func (s *DockerSwarmSuite) TestSwarmServiceNetworkUpdate(c *testing.T) { result.Assert(c, icmd.Success) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEquals(map[string]int{fooNetwork: 1, barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks(ctx), checker.DeepEquals(map[string]int{fooNetwork: 1, barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout)) // Remove a network result = icmd.RunCmd(d.Command("service", "update", "--detach", "--network-rm", "foo", name)) result.Assert(c, icmd.Success) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEquals(map[string]int{barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks(ctx), checker.DeepEquals(map[string]int{barNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout)) // Add a network result = icmd.RunCmd(d.Command("service", "update", "--detach", "--network-add", "baz", name)) result.Assert(c, icmd.Success) - poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks, checker.DeepEquals(map[string]int{barNetwork: 1, bazNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckRunningTaskNetworks(ctx), checker.DeepEquals(map[string]int{barNetwork: 1, bazNetwork: 1})), poll.WithTimeout(defaultReconciliationTimeout)) } func (s *DockerSwarmSuite) TestDNSConfig(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create a service name := "top" @@ -936,7 +964,7 @@ func (s *DockerSwarmSuite) TestDNSConfig(c *testing.T) { assert.NilError(c, err, out) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // We need to get the container id. out, err = d.Cmd("ps", "-a", "-q", "--no-trunc") @@ -955,7 +983,8 @@ func (s *DockerSwarmSuite) TestDNSConfig(c *testing.T) { } func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create a service name := "top" @@ -963,7 +992,7 @@ func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *testing.T) { assert.NilError(c, err, out) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("service", "update", "--detach", "--dns-add=1.2.3.4", "--dns-search-add=example.com", "--dns-option-add=timeout:3", name) assert.NilError(c, err, out) @@ -974,7 +1003,8 @@ func (s *DockerSwarmSuite) TestDNSConfigUpdate(c *testing.T) { } func getNodeStatus(c *testing.T, d *daemon.Daemon) swarm.LocalNodeState { - info := d.SwarmInfo(c) + ctx := testutil.GetContext(c) + info := d.SwarmInfo(ctx, c) return info.LocalNodeState } @@ -994,24 +1024,25 @@ func checkKeyIsEncrypted(d *daemon.Daemon) func(*testing.T) (interface{}, string } } -func checkSwarmLockedToUnlocked(c *testing.T, d *daemon.Daemon) { +func checkSwarmLockedToUnlocked(ctx context.Context, c *testing.T, d *daemon.Daemon) { // Wait for the PEM file to become unencrypted poll.WaitOn(c, pollCheck(c, checkKeyIsEncrypted(d), checker.Equals(false)), poll.WithTimeout(defaultReconciliationTimeout)) d.RestartNode(c) - poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second)) + poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState(ctx), checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second)) } -func checkSwarmUnlockedToLocked(c *testing.T, d *daemon.Daemon) { +func checkSwarmUnlockedToLocked(ctx context.Context, c *testing.T, d *daemon.Daemon) { // Wait for the PEM file to become encrypted poll.WaitOn(c, pollCheck(c, checkKeyIsEncrypted(d), checker.Equals(true)), poll.WithTimeout(defaultReconciliationTimeout)) d.RestartNode(c) - poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateLocked)), poll.WithTimeout(time.Second)) + poll.WaitOn(c, pollCheck(c, d.CheckLocalNodeState(ctx), checker.Equals(swarm.LocalNodeStateLocked)), poll.WithTimeout(time.Second)) } func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) // unlocking a normal engine should return an error - it does not even ask for the key cmd := d.Command("swarm", "unlock") @@ -1037,7 +1068,8 @@ func (s *DockerSwarmSuite) TestUnlockEngineAndUnlockedSwarm(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmInitLocked(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) outs, err := d.Cmd("swarm", "init", "--autolock") assert.Assert(c, err == nil, outs) @@ -1070,7 +1102,7 @@ func (s *DockerSwarmSuite) TestSwarmInitLocked(c *testing.T) { outs, err = d.Cmd("swarm", "update", "--autolock=false") assert.Assert(c, err == nil, outs) - checkSwarmLockedToUnlocked(c, d) + checkSwarmLockedToUnlocked(ctx, c, d) outs, err = d.Cmd("node", "ls") assert.Assert(c, err == nil, outs) @@ -1078,7 +1110,8 @@ func (s *DockerSwarmSuite) TestSwarmInitLocked(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) outs, err := d.Cmd("swarm", "init", "--autolock") assert.Assert(c, err == nil, outs) @@ -1086,7 +1119,7 @@ func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *testing.T) { // It starts off locked d.RestartNode(c) - info := d.SwarmInfo(c) + info := d.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateLocked) outs, _ = d.Cmd("node", "ls") @@ -1098,20 +1131,21 @@ func (s *DockerSwarmSuite) TestSwarmLeaveLocked(c *testing.T) { outs, err = d.Cmd("swarm", "leave", "--force") assert.Assert(c, err == nil, outs) - info = d.SwarmInfo(c) + info = d.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateInactive) outs, err = d.Cmd("swarm", "init") assert.Assert(c, err == nil, outs) - info = d.SwarmInfo(c) + info = d.SwarmInfo(ctx, c) assert.Equal(c, info.LocalNodeState, swarm.LocalNodeStateActive) } func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) // they start off unlocked d2.RestartNode(c) @@ -1127,7 +1161,7 @@ func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *testing.T) { // The ones that got the cluster update should be set to locked for _, d := range []*daemon.Daemon{d1, d3} { - checkSwarmUnlockedToLocked(c, d) + checkSwarmUnlockedToLocked(ctx, c, d) cmd := d.Command("swarm", "unlock") cmd.Stdin = bytes.NewBufferString(unlockKey) @@ -1140,7 +1174,7 @@ func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *testing.T) { assert.Equal(c, getNodeStatus(c, d2), swarm.LocalNodeStateActive) // d2 is now set to lock - checkSwarmUnlockedToLocked(c, d2) + checkSwarmUnlockedToLocked(ctx, c, d2) // leave it locked, and set the cluster to no longer autolock outs, err = d1.Cmd("swarm", "update", "--autolock=false") @@ -1148,7 +1182,7 @@ func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *testing.T) { // the ones that got the update are now set to unlocked for _, d := range []*daemon.Daemon{d1, d3} { - checkSwarmLockedToUnlocked(c, d) + checkSwarmLockedToUnlocked(ctx, c, d) } // d2 still locked @@ -1161,16 +1195,17 @@ func (s *DockerSwarmSuite) TestSwarmLockUnlockCluster(c *testing.T) { assert.Equal(c, getNodeStatus(c, d2), swarm.LocalNodeStateActive) // once it's caught up, d2 is set to not be locked - checkSwarmLockedToUnlocked(c, d2) + checkSwarmLockedToUnlocked(ctx, c, d2) // managers who join now are never set to locked in the first place - d4 := s.AddDaemon(c, true, true) + d4 := s.AddDaemon(ctx, c, true, true) d4.RestartNode(c) assert.Equal(c, getNodeStatus(c, d4), swarm.LocalNodeStateActive) } func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) { - d1 := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) // enable autolock outs, err := d1.Cmd("swarm", "update", "--autolock") @@ -1178,20 +1213,20 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) { unlockKey := getUnlockKey(d1, c, outs) // joined workers start off unlocked - d2 := s.AddDaemon(c, true, false) + d2 := s.AddDaemon(ctx, c, true, false) d2.RestartNode(c) - poll.WaitOn(c, pollCheck(c, d2.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second)) + poll.WaitOn(c, pollCheck(c, d2.CheckLocalNodeState(ctx), checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second)) // promote worker outs, err = d1.Cmd("node", "promote", d2.NodeID()) assert.NilError(c, err) assert.Assert(c, strings.Contains(outs, "promoted to a manager in the swarm"), outs) // join new manager node - d3 := s.AddDaemon(c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) // both new nodes are locked for _, d := range []*daemon.Daemon{d2, d3} { - checkSwarmUnlockedToLocked(c, d) + checkSwarmUnlockedToLocked(ctx, c, d) cmd := d.Command("swarm", "unlock") cmd.Stdin = bytes.NewBufferString(unlockKey) @@ -1208,7 +1243,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) { // to be replaced, then the node still has the manager TLS key which is still locked // (because we never want a manager TLS key to be on disk unencrypted if the cluster // is set to autolock) - poll.WaitOn(c, pollCheck(c, d3.CheckControlAvailable, checker.False()), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d3.CheckControlAvailable(ctx), checker.False()), poll.WithTimeout(defaultReconciliationTimeout)) poll.WaitOn(c, pollCheck(c, func(c *testing.T) (interface{}, string) { certBytes, err := os.ReadFile(filepath.Join(d3.Folder, "root", "swarm", "certificates", "swarm-node.crt")) if err != nil { @@ -1223,11 +1258,12 @@ func (s *DockerSwarmSuite) TestSwarmJoinPromoteLocked(c *testing.T) { // by now, it should *never* be locked on restart d3.RestartNode(c) - poll.WaitOn(c, pollCheck(c, d3.CheckLocalNodeState, checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second)) + poll.WaitOn(c, pollCheck(c, d3.CheckLocalNodeState(ctx), checker.Equals(swarm.LocalNodeStateActive)), poll.WithTimeout(time.Second)) } func (s *DockerSwarmSuite) TestSwarmRotateUnlockKey(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) outs, err := d.Cmd("swarm", "update", "--autolock") assert.Assert(c, err == nil, "out: %v", outs) @@ -1311,10 +1347,11 @@ func (s *DockerSwarmSuite) TestSwarmClusterRotateUnlockKey(c *testing.T) { if runtime.GOARCH == "ppc64le" { c.Skip("Disabled on ppc64le") } + ctx := testutil.GetContext(c) - d1 := s.AddDaemon(c, true, true) // leader - don't restart this one, we don't want leader election delays - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, true) + d1 := s.AddDaemon(ctx, c, true, true) // leader - don't restart this one, we don't want leader election delays + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) outs, err := d1.Cmd("swarm", "update", "--autolock") assert.Assert(c, err == nil, outs) @@ -1396,7 +1433,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterRotateUnlockKey(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmAlternateLockUnlock(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) for i := 0; i < 2; i++ { // set to lock @@ -1405,7 +1443,7 @@ func (s *DockerSwarmSuite) TestSwarmAlternateLockUnlock(c *testing.T) { assert.Assert(c, strings.Contains(outs, "docker swarm unlock"), outs) unlockKey := getUnlockKey(d, c, outs) - checkSwarmUnlockedToLocked(c, d) + checkSwarmUnlockedToLocked(ctx, c, d) cmd := d.Command("swarm", "unlock") cmd.Stdin = bytes.NewBufferString(unlockKey) @@ -1416,12 +1454,13 @@ func (s *DockerSwarmSuite) TestSwarmAlternateLockUnlock(c *testing.T) { outs, err = d.Cmd("swarm", "update", "--autolock=false") assert.Assert(c, err == nil, "out: %v", outs) - checkSwarmLockedToUnlocked(c, d) + checkSwarmLockedToUnlocked(ctx, c, d) } } func (s *DockerSwarmSuite) TestExtraHosts(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // Create a service name := "top" @@ -1429,7 +1468,7 @@ func (s *DockerSwarmSuite) TestExtraHosts(c *testing.T) { assert.NilError(c, err, out) // Make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // We need to get the container id. out, err = d.Cmd("ps", "-a", "-q", "--no-trunc") @@ -1444,9 +1483,10 @@ func (s *DockerSwarmSuite) TestExtraHosts(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmManagerAddress(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) - d3 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) + d3 := s.AddDaemon(ctx, c, true, false) // Manager Addresses will always show Node 1's address expectedOutput := fmt.Sprintf("127.0.0.1:%d", d1.SwarmPort) @@ -1465,7 +1505,8 @@ func (s *DockerSwarmSuite) TestSwarmManagerAddress(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "create", "-d", "overlay", "--ipam-opt", "foo=bar", "foo") assert.NilError(c, err, out) @@ -1480,7 +1521,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *testing.T) { assert.NilError(c, err, out) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("network", "inspect", "--format", "{{.IPAM.Options}}", "foo") assert.NilError(c, err, out) @@ -1491,7 +1532,8 @@ func (s *DockerSwarmSuite) TestSwarmNetworkIPAMOptions(c *testing.T) { // Test case for issue #27866, which did not allow NW name that is the prefix of a swarm NW ID. // e.g. if the ingress ID starts with "n1", it was impossible to create a NW named "n1". func (s *DockerSwarmSuite) TestSwarmNetworkCreateIssue27866(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("network", "inspect", "-f", "{{.Id}}", "ingress") assert.NilError(c, err, "out: %v", out) ingressID := strings.TrimSpace(out) @@ -1514,7 +1556,8 @@ func (s *DockerSwarmSuite) TestSwarmNetworkCreateIssue27866(c *testing.T) { // Note that it is to ok have multiple networks with the same name if the operations are done // in parallel. (#18864) func (s *DockerSwarmSuite) TestSwarmNetworkCreateDup(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) drivers := []string{"bridge", "overlay"} for i, driver1 := range drivers { for _, driver2 := range drivers { @@ -1533,14 +1576,15 @@ func (s *DockerSwarmSuite) TestSwarmNetworkCreateDup(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmPublishDuplicatePorts(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("service", "create", "--no-resolve-image", "--detach=true", "--publish", "5005:80", "--publish", "5006:80", "--publish", "80", "--publish", "80", "busybox", "top") assert.NilError(c, err, out) id := strings.TrimSpace(out) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) // Total len = 4, with 2 dynamic ports and 2 non-dynamic ports // Dynamic ports are likely to be 30000 and 30001 but doesn't matter @@ -1552,7 +1596,8 @@ func (s *DockerSwarmSuite) TestSwarmPublishDuplicatePorts(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmJoinWithDrain(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("node", "ls") assert.NilError(c, err) @@ -1563,7 +1608,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinWithDrain(c *testing.T) { token := strings.TrimSpace(out) - d1 := s.AddDaemon(c, false, false) + d1 := s.AddDaemon(ctx, c, false, false) out, err = d1.Cmd("swarm", "join", "--availability=drain", "--token", token, d.SwarmListenAddr()) assert.NilError(c, err) @@ -1578,7 +1623,8 @@ func (s *DockerSwarmSuite) TestSwarmJoinWithDrain(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmInitWithDrain(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) out, err := d.Cmd("swarm", "init", "--availability", "drain") assert.NilError(c, err, "out: %v", out) @@ -1590,27 +1636,29 @@ func (s *DockerSwarmSuite) TestSwarmInitWithDrain(c *testing.T) { func (s *DockerSwarmSuite) TestSwarmReadonlyRootfs(c *testing.T) { testRequires(c, DaemonIsLinux, UserNamespaceROMount) + ctx := testutil.GetContext(c) - d := s.AddDaemon(c, true, true) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top", "--read-only", "busybox", "top") assert.NilError(c, err, out) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.ReadOnly }}", "top") assert.NilError(c, err, out) assert.Equal(c, strings.TrimSpace(out), "true") - containers := d.ActiveContainers(c) + containers := d.ActiveContainers(testutil.GetContext(c), c) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.HostConfig.ReadonlyRootfs}}", containers[0]) assert.NilError(c, err, out) assert.Equal(c, strings.TrimSpace(out), "true") } func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) name := "foo" options := types.NetworkCreate{ @@ -1621,7 +1669,7 @@ func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *testing.T) { cli := d.NewClientT(c) defer cli.Close() - n1, err := cli.NetworkCreate(context.Background(), name, options) + n1, err := cli.NetworkCreate(testutil.GetContext(c), name, options) assert.NilError(c, err) // Full ID always works @@ -1634,7 +1682,7 @@ func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *testing.T) { assert.NilError(c, err, out) assert.Equal(c, strings.TrimSpace(out), n1.ID) - n2, err := cli.NetworkCreate(context.Background(), name, options) + n2, err := cli.NetworkCreate(testutil.GetContext(c), name, options) assert.NilError(c, err) // Full ID always works out, err = d.Cmd("network", "inspect", "--format", "{{.ID}}", n1.ID) @@ -1655,7 +1703,7 @@ func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *testing.T) { // Duplicates with name but with different driver options.Driver = "overlay" - n2, err = cli.NetworkCreate(context.Background(), name, options) + n2, err = cli.NetworkCreate(testutil.GetContext(c), name, options) assert.NilError(c, err) // Full ID always works @@ -1674,21 +1722,22 @@ func (s *DockerSwarmSuite) TestNetworkInspectWithDuplicateNames(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmStopSignal(c *testing.T) { + ctx := testutil.GetContext(c) testRequires(c, DaemonIsLinux, UserNamespaceROMount) - d := s.AddDaemon(c, true, true) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top", "--stop-signal=SIGHUP", "busybox", "top") assert.NilError(c, err, out) // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("service", "inspect", "--format", "{{ .Spec.TaskTemplate.ContainerSpec.StopSignal }}", "top") assert.NilError(c, err, out) assert.Equal(c, strings.TrimSpace(out), "SIGHUP") - containers := d.ActiveContainers(c) + containers := d.ActiveContainers(testutil.GetContext(c), c) out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.StopSignal}}", containers[0]) assert.NilError(c, err, out) assert.Equal(c, strings.TrimSpace(out), "SIGHUP") @@ -1702,7 +1751,8 @@ func (s *DockerSwarmSuite) TestSwarmStopSignal(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", "top1", "busybox", "top") assert.NilError(c, err, out) @@ -1713,7 +1763,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *testing.T) { assert.Assert(c, strings.TrimSpace(out) != "") // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("service", "ls") assert.NilError(c, err, out) @@ -1732,7 +1782,8 @@ func (s *DockerSwarmSuite) TestSwarmServiceLsFilterMode(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedDataPathAddr(c *testing.T) { - d := s.AddDaemon(c, false, false) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, false, false) out, err := d.Cmd("swarm", "init", "--data-path-addr", "0.0.0.0") assert.ErrorContains(c, err, "") @@ -1743,7 +1794,8 @@ func (s *DockerSwarmSuite) TestSwarmInitUnspecifiedDataPathAddr(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("swarm", "join-token", "-q", "worker") assert.NilError(c, err) @@ -1752,7 +1804,7 @@ func (s *DockerSwarmSuite) TestSwarmJoinLeave(c *testing.T) { token := strings.TrimSpace(out) // Verify that back to back join/leave does not cause panics - d1 := s.AddDaemon(c, false, false) + d1 := s.AddDaemon(ctx, c, false, false) for i := 0; i < 10; i++ { out, err = d1.Cmd("swarm", "join", "--token", token, d.SwarmListenAddr()) assert.NilError(c, err) @@ -1793,9 +1845,10 @@ func waitForEvent(c *testing.T, d *daemon.Daemon, since string, filter string, e } func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, false) // create a network out, err := d1.Cmd("network", "create", "--attachable", "-d", "overlay", "foo") @@ -1813,7 +1866,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsSource(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // create a service out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "test", "--detach=false", "busybox", "top") @@ -1833,7 +1887,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsScope(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // create a service out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "test", "--detach=false", "busybox", "top") @@ -1855,7 +1910,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsType(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsService(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // create a service out, err := d.Cmd("service", "create", "--no-resolve-image", "--name", "test", "--detach=false", "busybox", "top") @@ -1892,9 +1948,10 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsService(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *testing.T) { - d1 := s.AddDaemon(c, true, true) - s.AddDaemon(c, true, true) - d3 := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + s.AddDaemon(ctx, c, true, true) + d3 := s.AddDaemon(ctx, c, true, true) d3ID := d3.NodeID() waitForEvent(c, d1, "0", "-f scope=swarm", "node create "+d3ID, defaultRetryCount) @@ -1921,7 +1978,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNode(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) // create a network out, err := d.Cmd("network", "create", "--attachable", "-d", "overlay", "foo") @@ -1940,7 +1998,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsNetwork(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) testName := "test_secret" id := d.CreateSecret(c, swarm.SecretSpec{ @@ -1960,7 +2019,8 @@ func (s *DockerSwarmSuite) TestSwarmClusterEventsSecret(c *testing.T) { } func (s *DockerSwarmSuite) TestSwarmClusterEventsConfig(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) testName := "test_config" id := d.CreateConfig(c, swarm.ConfigSpec{ diff --git a/integration-cli/docker_cli_swarm_unix_test.go b/integration-cli/docker_cli_swarm_unix_test.go index 1ce31e5eba..c971be1470 100644 --- a/integration-cli/docker_cli_swarm_unix_test.go +++ b/integration-cli/docker_cli_swarm_unix_test.go @@ -10,18 +10,20 @@ import ( "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/integration-cli/checker" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" ) func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *testing.T) { - d := s.AddDaemon(c, true, true) + ctx := testutil.GetContext(c) + d := s.AddDaemon(ctx, c, true, true) out, err := d.Cmd("service", "create", "--detach", "--no-resolve-image", "--mount", "type=volume,source=my-volume,destination=/foo,volume-driver=customvolumedriver", "--name", "top", "busybox", "top") assert.NilError(c, err, out) // Make sure task stays pending before plugin is available - poll.WaitOn(c, pollCheck(c, d.CheckServiceTasksInStateWithError("top", swarm.TaskStatePending, "missing plugin on 1 node"), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckServiceTasksInStateWithError(ctx, "top", swarm.TaskStatePending, "missing plugin on 1 node"), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) plugin := newVolumePlugin(c, "customvolumedriver") defer plugin.Close() @@ -35,7 +37,7 @@ func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *testing.T) { // this long delay. // make sure task has been deployed. - poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount, checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d.CheckActiveContainerCount(ctx), checker.Equals(1)), poll.WithTimeout(defaultReconciliationTimeout)) out, err = d.Cmd("ps", "-q") assert.NilError(c, err) @@ -58,8 +60,9 @@ func (s *DockerSwarmSuite) TestSwarmVolumePlugin(c *testing.T) { // Test network plugin filter in swarm func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) { testRequires(c, IsAmd64) - d1 := s.AddDaemon(c, true, true) - d2 := s.AddDaemon(c, true, false) + ctx := testutil.GetContext(c) + d1 := s.AddDaemon(ctx, c, true, true) + d2 := s.AddDaemon(ctx, c, true, false) // install plugin on d1 and d2 pluginName := "aragunathan/global-net-plugin:latest" @@ -81,7 +84,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) { assert.NilError(c, err) // wait for tasks ready - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx)), checker.Equals(2)), poll.WithTimeout(defaultReconciliationTimeout)) // remove service _, err = d1.Cmd("service", "rm", serviceName) @@ -89,7 +92,7 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) { // wait to ensure all containers have exited before removing the plugin. Else there's a // possibility of container exits erroring out due to plugins being unavailable. - poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount(ctx), d2.CheckActiveContainerCount(ctx)), checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) // disable plugin on worker _, err = d2.Cmd("plugin", "disable", "-f", pluginName) @@ -102,5 +105,5 @@ func (s *DockerSwarmSuite) TestSwarmNetworkPluginV2(c *testing.T) { _, err = d1.Cmd("service", "create", "--detach", "--no-resolve-image", "--name", serviceName, "--mode=global", "--network", networkName, image, "top") assert.NilError(c, err) - poll.WaitOn(c, pollCheck(c, d1.CheckRunningTaskImages, checker.DeepEquals(map[string]int{image: 1})), poll.WithTimeout(defaultReconciliationTimeout)) + poll.WaitOn(c, pollCheck(c, d1.CheckRunningTaskImages(ctx), checker.DeepEquals(map[string]int{image: 1})), poll.WithTimeout(defaultReconciliationTimeout)) } diff --git a/integration-cli/docker_cli_top_test.go b/integration-cli/docker_cli_top_test.go index c3ee2f2dab..b57d8c4b2a 100644 --- a/integration-cli/docker_cli_top_test.go +++ b/integration-cli/docker_cli_top_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "strings" "testing" @@ -12,8 +13,8 @@ type DockerCLITopSuite struct { ds *DockerSuite } -func (s *DockerCLITopSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLITopSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLITopSuite) OnTimeout(c *testing.T) { diff --git a/integration-cli/docker_cli_update_unix_test.go b/integration-cli/docker_cli_update_unix_test.go index ccde53182a..6925b95afe 100644 --- a/integration-cli/docker_cli_update_unix_test.go +++ b/integration-cli/docker_cli_update_unix_test.go @@ -14,12 +14,13 @@ import ( "github.com/creack/pty" "github.com/docker/docker/api/types" "github.com/docker/docker/client" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" ) -func (s *DockerCLIUpdateSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIUpdateSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIUpdateSuite) OnTimeout(c *testing.T) { @@ -180,7 +181,7 @@ func (s *DockerCLIUpdateSuite) TestUpdateStats(c *testing.T) { assert.NilError(c, waitRun(name)) getMemLimit := func(id string) uint64 { - resp, body, err := request.Get(fmt.Sprintf("/containers/%s/stats?stream=false", id)) + resp, body, err := request.Get(testutil.GetContext(c), fmt.Sprintf("/containers/%s/stats?stream=false", id)) assert.NilError(c, err) assert.Equal(c, resp.Header.Get("Content-Type"), "application/json") @@ -255,7 +256,7 @@ func (s *DockerCLIUpdateSuite) TestUpdateWithNanoCPUs(c *testing.T) { clt, err := client.NewClientWithOpts(client.FromEnv) assert.NilError(c, err) - inspect, err := clt.ContainerInspect(context.Background(), "top") + inspect, err := clt.ContainerInspect(testutil.GetContext(c), "top") assert.NilError(c, err) assert.Equal(c, inspect.HostConfig.NanoCPUs, int64(500000000)) @@ -269,7 +270,7 @@ func (s *DockerCLIUpdateSuite) TestUpdateWithNanoCPUs(c *testing.T) { assert.Assert(c, strings.Contains(out, "Conflicting options: CPU Quota cannot be updated as NanoCPUs has already been set")) dockerCmd(c, "update", "--cpus", "0.8", "top") - inspect, err = clt.ContainerInspect(context.Background(), "top") + inspect, err = clt.ContainerInspect(testutil.GetContext(c), "top") assert.NilError(c, err) assert.Equal(c, inspect.HostConfig.NanoCPUs, int64(800000000)) diff --git a/integration-cli/docker_cli_userns_test.go b/integration-cli/docker_cli_userns_test.go index b30387459c..054eac9726 100644 --- a/integration-cli/docker_cli_userns_test.go +++ b/integration-cli/docker_cli_userns_test.go @@ -14,6 +14,7 @@ import ( "testing" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" ) @@ -23,7 +24,8 @@ import ( func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *testing.T) { testRequires(c, UserNamespaceInKernel) - s.d.StartWithBusybox(c, "--userns-remap", "default") + ctx := testutil.GetContext(c) + s.d.StartWithBusybox(ctx, c, "--userns-remap", "default") tmpDir, err := os.MkdirTemp("", "userns") assert.NilError(c, err) diff --git a/integration-cli/docker_cli_volume_test.go b/integration-cli/docker_cli_volume_test.go index f1980b329e..5faa425176 100644 --- a/integration-cli/docker_cli_volume_test.go +++ b/integration-cli/docker_cli_volume_test.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/api/types/network" "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/cli/build" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" ) @@ -22,8 +23,8 @@ type DockerCLIVolumeSuite struct { ds *DockerSuite } -func (s *DockerCLIVolumeSuite) TearDownTest(c *testing.T) { - s.ds.TearDownTest(c) +func (s *DockerCLIVolumeSuite) TearDownTest(ctx context.Context, c *testing.T) { + s.ds.TearDownTest(ctx, c) } func (s *DockerCLIVolumeSuite) OnTimeout(c *testing.T) { @@ -589,7 +590,7 @@ func (s *DockerCLIVolumeSuite) TestDuplicateMountpointsForVolumesFromAndMounts(c }, }, } - _, err = apiClient.ContainerCreate(context.Background(), &config, &hostConfig, &network.NetworkingConfig{}, nil, "app") + _, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "app") assert.NilError(c, err) diff --git a/integration-cli/docker_deprecated_api_v124_test.go b/integration-cli/docker_deprecated_api_v124_test.go index a6e4315e55..db13662a5d 100644 --- a/integration-cli/docker_deprecated_api_v124_test.go +++ b/integration-cli/docker_deprecated_api_v124_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -24,7 +25,7 @@ func (s *DockerAPISuite) TestDeprecatedContainerAPIStartHostConfig(c *testing.T) config := map[string]interface{}{ "Binds": []string{"/aa:/bb"}, } - res, body, err := request.Post("/containers/"+name+"/start", request.JSONBody(config)) + res, body, err := request.Post(testutil.GetContext(c), "/containers/"+name+"/start", request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusBadRequest) if versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), "1.32") { @@ -50,7 +51,7 @@ func (s *DockerAPISuite) TestDeprecatedContainerAPIStartVolumeBinds(c *testing.T "Volumes": map[string]struct{}{path: {}}, } - res, _, err := request.Post(formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config)) + res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusCreated) @@ -58,7 +59,7 @@ func (s *DockerAPISuite) TestDeprecatedContainerAPIStartVolumeBinds(c *testing.T config = map[string]interface{}{ "Binds": []string{bindPath + ":" + path}, } - res, _, err = request.Post(formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config)) + res, _, err = request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) @@ -77,7 +78,7 @@ func (s *DockerAPISuite) TestDeprecatedContainerAPIStartDupVolumeBinds(c *testin "Volumes": map[string]struct{}{"/tmp": {}}, } - res, _, err := request.Post(formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config)) + res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusCreated) @@ -87,7 +88,7 @@ func (s *DockerAPISuite) TestDeprecatedContainerAPIStartDupVolumeBinds(c *testin config = map[string]interface{}{ "Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"}, } - res, body, err := request.Post(formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config)) + res, body, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config)) assert.NilError(c, err) buf, err := request.ReadBody(body) @@ -115,14 +116,14 @@ func (s *DockerAPISuite) TestDeprecatedContainerAPIStartVolumesFrom(c *testing.T "Volumes": map[string]struct{}{volPath: {}}, } - res, _, err := request.Post(formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config)) + res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusCreated) config = map[string]interface{}{ "VolumesFrom": []string{volName}, } - res, _, err = request.Post(formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config)) + res, _, err = request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) @@ -145,7 +146,7 @@ func (s *DockerAPISuite) TestDeprecatedPostContainerBindNormalVolume(c *testing. dockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox") bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}} - res, _, err := request.Post(formatV123StartAPIURL("/containers/two/start"), request.JSONBody(bindSpec)) + res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/two/start"), request.JSONBody(bindSpec)) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) @@ -166,7 +167,7 @@ func (s *DockerAPISuite) TestDeprecatedStartWithTooLowMemoryLimit(c *testing.T) "Memory": 524287 }` - res, body, err := request.Post(formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON) + res, body, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON) assert.NilError(c, err) b, err := request.ReadBody(body) assert.NilError(c, err) @@ -189,7 +190,7 @@ func (s *DockerAPISuite) TestDeprecatedPostContainersStartWithoutLinksInHostConf hc := inspectFieldJSON(c, name, "HostConfig") config := `{"HostConfig":` + hc + `}` - res, b, err := request.Post(formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON) + res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) b.Close() @@ -207,7 +208,7 @@ func (s *DockerAPISuite) TestDeprecatedPostContainersStartWithLinksInHostConfig( hc := inspectFieldJSON(c, name, "HostConfig") config := `{"HostConfig":` + hc + `}` - res, b, err := request.Post(formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON) + res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) b.Close() @@ -227,7 +228,7 @@ func (s *DockerAPISuite) TestDeprecatedPostContainersStartWithLinksInHostConfigI hc := inspectFieldJSON(c, name, "HostConfig") config := `{"HostConfig":` + hc + `}` - res, b, err := request.Post(formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON) + res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) b.Close() @@ -241,7 +242,7 @@ func (s *DockerAPISuite) TestDeprecatedStartWithNilDNS(c *testing.T) { config := `{"HostConfig": {"Dns": null}}` - res, b, err := request.Post(formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON) + res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON) assert.NilError(c, err) assert.Equal(c, res.StatusCode, http.StatusNoContent) b.Close() diff --git a/integration-cli/docker_deprecated_api_v124_unix_test.go b/integration-cli/docker_deprecated_api_v124_unix_test.go index 7012b6b073..dc182c35bc 100644 --- a/integration-cli/docker_deprecated_api_v124_unix_test.go +++ b/integration-cli/docker_deprecated_api_v124_unix_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" ) @@ -22,7 +23,7 @@ func (s *DockerNetworkSuite) TestDeprecatedDockerNetworkStartAPIWithHostconfig(c "NetworkMode": netName, }, } - _, _, err := request.Post(formatV123StartAPIURL("/containers/"+conName+"/start"), request.JSONBody(config)) + _, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+conName+"/start"), request.JSONBody(config)) assert.NilError(c, err) assert.NilError(c, waitRun(conName)) networks := inspectField(c, conName, "NetworkSettings.Networks") diff --git a/integration-cli/docker_hub_pull_suite_test.go b/integration-cli/docker_hub_pull_suite_test.go index dbc6e94785..dc043d85a7 100644 --- a/integration-cli/docker_hub_pull_suite_test.go +++ b/integration-cli/docker_hub_pull_suite_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "os/exec" "strings" "testing" @@ -30,31 +31,31 @@ func newDockerHubPullSuite() *DockerHubPullSuite { } // SetUpSuite starts the suite daemon. -func (s *DockerHubPullSuite) SetUpSuite(c *testing.T) { +func (s *DockerHubPullSuite) SetUpSuite(ctx context.Context, c *testing.T) { testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) s.d.Start(c) } // TearDownSuite stops the suite daemon. -func (s *DockerHubPullSuite) TearDownSuite(c *testing.T) { +func (s *DockerHubPullSuite) TearDownSuite(ctx context.Context, c *testing.T) { if s.d != nil { s.d.Stop(c) } } // SetUpTest declares that all tests of this suite require network. -func (s *DockerHubPullSuite) SetUpTest(c *testing.T) { +func (s *DockerHubPullSuite) SetUpTest(ctx context.Context, c *testing.T) { testRequires(c, Network) } // TearDownTest removes all images from the suite daemon. -func (s *DockerHubPullSuite) TearDownTest(c *testing.T) { +func (s *DockerHubPullSuite) TearDownTest(ctx context.Context, c *testing.T) { out := s.Cmd(c, "images", "-aq") images := strings.Split(out, "\n") images = append([]string{"rmi", "-f"}, images...) s.d.Cmd(images...) - s.ds.TearDownTest(c) + s.ds.TearDownTest(ctx, c) } // Cmd executes a command against the suite daemon and returns the combined diff --git a/integration-cli/docker_utils_test.go b/integration-cli/docker_utils_test.go index faf2da53a4..834880a1f4 100644 --- a/integration-cli/docker_utils_test.go +++ b/integration-cli/docker_utils_test.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/cli" "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/assert/cmp" "gotest.tools/v3/icmd" @@ -249,7 +250,7 @@ func daemonTime(c *testing.T) time.Time { assert.NilError(c, err) defer apiClient.Close() - info, err := apiClient.Info(context.Background()) + info, err := apiClient.Info(testutil.GetContext(c)) assert.NilError(c, err) dt, err := time.Parse(time.RFC3339Nano, info.SystemTime) @@ -327,7 +328,7 @@ func getInspectBody(c *testing.T, version, id string) []byte { apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion(version)) assert.NilError(c, err) defer apiClient.Close() - _, body, err := apiClient.ContainerInspectWithRaw(context.Background(), id, false) + _, body, err := apiClient.ContainerInspectWithRaw(testutil.GetContext(c), id, false) assert.NilError(c, err) return body } @@ -356,45 +357,71 @@ func minimalBaseImage() string { return testEnv.PlatformDefaults.BaseImage } -func getGoroutineNumber() (int, error) { - apiClient, err := client.NewClientWithOpts(client.FromEnv) - if err != nil { - return 0, err - } - defer apiClient.Close() - - info, err := apiClient.Info(context.Background()) +func getGoroutineNumber(ctx context.Context, apiClient client.APIClient) (int, error) { + info, err := apiClient.Info(ctx) if err != nil { return 0, err } return info.NGoroutines, nil } -func waitForGoroutines(expected int) error { - t := time.After(30 * time.Second) - for { - select { - case <-t: - n, err := getGoroutineNumber() - if err != nil { - return err - } - if n > expected { - return fmt.Errorf("leaked goroutines: expected less than or equal to %d, got: %d", expected, n) - } - default: - n, err := getGoroutineNumber() - if err != nil { - return err - } - if n <= expected { - return nil - } - time.Sleep(200 * time.Millisecond) +func waitForStableGourtineCount(ctx context.Context, t poll.TestingT, apiClient client.APIClient) int { + var out int + poll.WaitOn(t, stableGoroutineCount(ctx, apiClient, &out), poll.WithTimeout(30*time.Second)) + return out +} + +func stableGoroutineCount(ctx context.Context, apiClient client.APIClient, count *int) poll.Check { + var ( + numStable int + nRoutines int + ) + + return func(t poll.LogT) poll.Result { + n, err := getGoroutineNumber(ctx, apiClient) + if err != nil { + return poll.Error(err) } + + last := nRoutines + + if nRoutines == n { + numStable++ + } else { + numStable = 0 + nRoutines = n + } + + if numStable > 3 { + *count = n + return poll.Success() + } + return poll.Continue("goroutine count is not stable: last %d, current %d, stable iters: %d", last, n, numStable) } } +func checkGoroutineCount(ctx context.Context, apiClient client.APIClient, expected int) poll.Check { + first := true + return func(t poll.LogT) poll.Result { + n, err := getGoroutineNumber(ctx, apiClient) + if err != nil { + return poll.Error(err) + } + if n > expected { + if first { + t.Log("Waiting for goroutines to stabilize") + first = false + } + return poll.Continue("exepcted %d goroutines, got %d", expected, n) + } + return poll.Success() + } +} + +func waitForGoroutines(ctx context.Context, t poll.TestingT, apiClient client.APIClient, expected int) { + poll.WaitOn(t, checkGoroutineCount(ctx, apiClient, expected), poll.WithDelay(500*time.Millisecond), poll.WithTimeout(30*time.Second)) +} + // getErrorMessage returns the error message from an error API response func getErrorMessage(c *testing.T, body []byte) string { c.Helper() diff --git a/integration-cli/environment/environment.go b/integration-cli/environment/environment.go index 5f28fb6907..f4f8219058 100644 --- a/integration-cli/environment/environment.go +++ b/integration-cli/environment/environment.go @@ -1,6 +1,7 @@ package environment // import "github.com/docker/docker/integration-cli/environment" import ( + "context" "os" "os/exec" @@ -29,8 +30,8 @@ func (e *Execution) DockerBinary() string { } // New returns details about the testing environment -func New() (*Execution, error) { - env, err := environment.New() +func New(ctx context.Context) (*Execution, error) { + env, err := environment.New(ctx) if err != nil { return nil, err } diff --git a/integration-cli/fixtures_linux_daemon_test.go b/integration-cli/fixtures_linux_daemon_test.go index 5de08cdf15..384169462e 100644 --- a/integration-cli/fixtures_linux_daemon_test.go +++ b/integration-cli/fixtures_linux_daemon_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "os" "os/exec" @@ -13,7 +14,7 @@ import ( "gotest.tools/v3/assert" ) -func ensureSyscallTest(c *testing.T) { +func ensureSyscallTest(ctx context.Context, c *testing.T) { defer testEnv.ProtectImage(c, "syscall-test:latest") // If the image already exists, there's nothing left to do. @@ -24,7 +25,7 @@ func ensureSyscallTest(c *testing.T) { // if no match, must build in docker, which is significantly slower // (slower mostly because of the vfs graphdriver) if testEnv.DaemonInfo.OSType != runtime.GOOS { - ensureSyscallTestBuild(c) + ensureSyscallTestBuild(ctx, c) return } @@ -63,8 +64,8 @@ func ensureSyscallTest(c *testing.T) { dockerCmd(c, buildArgs...) } -func ensureSyscallTestBuild(c *testing.T) { - err := load.FrozenImagesLinux(testEnv.APIClient(), "debian:bullseye-slim") +func ensureSyscallTestBuild(ctx context.Context, c *testing.T) { + err := load.FrozenImagesLinux(ctx, testEnv.APIClient(), "debian:bullseye-slim") assert.NilError(c, err) var buildArgs []string @@ -76,7 +77,7 @@ func ensureSyscallTestBuild(c *testing.T) { dockerCmd(c, buildArgs...) } -func ensureNNPTest(c *testing.T) { +func ensureNNPTest(ctx context.Context, c *testing.T) { defer testEnv.ProtectImage(c, "nnp-test:latest") // If the image already exists, there's nothing left to do. @@ -87,7 +88,7 @@ func ensureNNPTest(c *testing.T) { // if no match, must build in docker, which is significantly slower // (slower mostly because of the vfs graphdriver) if testEnv.DaemonInfo.OSType != runtime.GOOS { - ensureNNPTestBuild(c) + ensureNNPTestBuild(ctx, c) return } @@ -118,8 +119,8 @@ func ensureNNPTest(c *testing.T) { dockerCmd(c, buildArgs...) } -func ensureNNPTestBuild(c *testing.T) { - err := load.FrozenImagesLinux(testEnv.APIClient(), "debian:bullseye-slim") +func ensureNNPTestBuild(ctx context.Context, c *testing.T) { + err := load.FrozenImagesLinux(ctx, testEnv.APIClient(), "debian:bullseye-slim") assert.NilError(c, err) var buildArgs []string diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go index c681eecb49..9786fd9fac 100644 --- a/integration-cli/requirements_test.go +++ b/integration-cli/requirements_test.go @@ -33,12 +33,12 @@ func MinimumAPIVersion(version string) func() bool { } } -func OnlyDefaultNetworks() bool { +func OnlyDefaultNetworks(ctx context.Context) bool { apiClient, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return false } - networks, err := apiClient.NetworkList(context.TODO(), types.NetworkListOptions{}) + networks, err := apiClient.NetworkList(ctx, types.NetworkListOptions{}) if err != nil || len(networks) > 0 { return false } diff --git a/integration-cli/requirements_unix_test.go b/integration-cli/requirements_unix_test.go index 7fd81e963e..3e3dc0cdf2 100644 --- a/integration-cli/requirements_unix_test.go +++ b/integration-cli/requirements_unix_test.go @@ -11,8 +11,11 @@ import ( "github.com/docker/docker/pkg/sysinfo" ) -// SysInfo stores information about which features a kernel supports. -var SysInfo *sysinfo.SysInfo +var sysInfo *sysinfo.SysInfo + +func setupLocalInfo() { + sysInfo = sysinfo.New() +} func cpuCfsPeriod() bool { return testEnv.DaemonInfo.CPUCfsPeriod @@ -31,7 +34,7 @@ func oomControl() bool { } func pidsLimit() bool { - return SysInfo.PidsLimit + return sysInfo.PidsLimit } func memoryLimitSupport() bool { @@ -39,7 +42,7 @@ func memoryLimitSupport() bool { } func memoryReservationSupport() bool { - return SysInfo.MemoryReservation + return sysInfo.MemoryReservation } func swapMemorySupport() bool { @@ -47,11 +50,11 @@ func swapMemorySupport() bool { } func memorySwappinessSupport() bool { - return testEnv.IsLocalDaemon() && SysInfo.MemorySwappiness + return testEnv.IsLocalDaemon() && sysInfo.MemorySwappiness } func blkioWeight() bool { - return testEnv.IsLocalDaemon() && SysInfo.BlkioWeight + return testEnv.IsLocalDaemon() && sysInfo.BlkioWeight } func cgroupCpuset() bool { @@ -59,11 +62,11 @@ func cgroupCpuset() bool { } func seccompEnabled() bool { - return SysInfo.Seccomp + return sysInfo.Seccomp } func bridgeNfIptables() bool { - return !SysInfo.BridgeNFCallIPTablesDisabled + return !sysInfo.BridgeNFCallIPTablesDisabled } func unprivilegedUsernsClone() bool { @@ -79,9 +82,3 @@ func overlayFSSupported() bool { } return bytes.Contains(out, []byte("overlay\n")) } - -func init() { - if testEnv.IsLocalDaemon() { - SysInfo = sysinfo.New() - } -} diff --git a/integration-cli/requirements_windows_test.go b/integration-cli/requirements_windows_test.go new file mode 100644 index 0000000000..d5b883dda9 --- /dev/null +++ b/integration-cli/requirements_windows_test.go @@ -0,0 +1,4 @@ +package main + +func setupLocalInfo() { +} diff --git a/integration/build/build_cgroupns_linux_test.go b/integration/build/build_cgroupns_linux_test.go index 20e982d85f..93a3cd07e5 100644 --- a/integration/build/build_cgroupns_linux_test.go +++ b/integration/build/build_cgroupns_linux_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/requirement" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" @@ -38,16 +39,15 @@ func getCgroupFromBuildOutput(buildOutput io.Reader) (string, error) { // Runs a docker build against a daemon with the given cgroup namespace default value. // Returns the container cgroup and daemon cgroup. -func testBuildWithCgroupNs(t *testing.T, daemonNsMode string) (string, string) { +func testBuildWithCgroupNs(ctx context.Context, t *testing.T, daemonNsMode string) (string, string) { d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode)) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) dockerfile := ` FROM busybox RUN readlink /proc/self/ns/cgroup ` - ctx := context.Background() source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) defer source.Close() @@ -74,9 +74,11 @@ func TestCgroupNamespacesBuild(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to private cgroup namespaces, containers launched // should be in their own private cgroup namespace by default - containerCgroup, daemonCgroup := testBuildWithCgroupNs(t, "private") + containerCgroup, daemonCgroup := testBuildWithCgroupNs(ctx, t, "private") assert.Assert(t, daemonCgroup != containerCgroup) } @@ -85,8 +87,10 @@ func TestCgroupNamespacesBuildDaemonHostMode(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to host cgroup namespaces, containers // launched should not be inside their own cgroup namespaces - containerCgroup, daemonCgroup := testBuildWithCgroupNs(t, "host") + containerCgroup, daemonCgroup := testBuildWithCgroupNs(ctx, t, "host") assert.Assert(t, daemonCgroup == containerCgroup) } diff --git a/integration/build/build_session_test.go b/integration/build/build_session_test.go index 30a6ca9747..e1468c82b0 100644 --- a/integration/build/build_session_test.go +++ b/integration/build/build_session_test.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" dclient "github.com/docker/docker/client" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/fakecontext" "github.com/docker/docker/testutil/request" "github.com/moby/buildkit/session" @@ -26,6 +27,8 @@ func TestBuildWithSession(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "experimental in older versions") + ctx := testutil.StartSpan(baseContext, t) + client := testEnv.APIClient() dockerfile := ` @@ -39,7 +42,7 @@ func TestBuildWithSession(t *testing.T) { ) defer fctx.Close() - out := testBuildWithSession(t, client, client.DaemonHost(), fctx.Dir, dockerfile) + out := testBuildWithSession(ctx, t, client, client.DaemonHost(), fctx.Dir, dockerfile) assert.Check(t, is.Contains(out, "some content")) fctx.Add("second", "contentcontent") @@ -49,25 +52,25 @@ func TestBuildWithSession(t *testing.T) { RUN cat /second ` - out = testBuildWithSession(t, client, client.DaemonHost(), fctx.Dir, dockerfile) + out = testBuildWithSession(ctx, t, client, client.DaemonHost(), fctx.Dir, dockerfile) assert.Check(t, is.Equal(strings.Count(out, "Using cache"), 2)) assert.Check(t, is.Contains(out, "contentcontent")) - du, err := client.DiskUsage(context.TODO(), types.DiskUsageOptions{}) + du, err := client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.Check(t, err) assert.Check(t, du.BuilderSize > 10) - out = testBuildWithSession(t, client, client.DaemonHost(), fctx.Dir, dockerfile) + out = testBuildWithSession(ctx, t, client, client.DaemonHost(), fctx.Dir, dockerfile) assert.Check(t, is.Equal(strings.Count(out, "Using cache"), 4)) - du2, err := client.DiskUsage(context.TODO(), types.DiskUsageOptions{}) + du2, err := client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.Check(t, err) assert.Check(t, is.Equal(du.BuilderSize, du2.BuilderSize)) // rebuild with regular tar, confirm cache still applies fctx.Add("Dockerfile", dockerfile) // FIXME(vdemeester) use sock here - res, body, err := request.Do( + res, body, err := request.Do(ctx, "/build", request.Host(client.DaemonHost()), request.Method(http.MethodPost), @@ -81,17 +84,16 @@ func TestBuildWithSession(t *testing.T) { assert.Check(t, is.Contains(string(outBytes), "Successfully built")) assert.Check(t, is.Equal(strings.Count(string(outBytes), "Using cache"), 4)) - _, err = client.BuildCachePrune(context.TODO(), types.BuildCachePruneOptions{All: true}) + _, err = client.BuildCachePrune(ctx, types.BuildCachePruneOptions{All: true}) assert.Check(t, err) - du, err = client.DiskUsage(context.TODO(), types.DiskUsageOptions{}) + du, err = client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.Check(t, err) assert.Check(t, is.Equal(du.BuilderSize, int64(0))) } //nolint:unused // false positive: linter detects this as "unused" -func testBuildWithSession(t *testing.T, client dclient.APIClient, daemonHost string, dir, dockerfile string) (outStr string) { - ctx := context.Background() +func testBuildWithSession(ctx context.Context, t *testing.T, client dclient.APIClient, daemonHost string, dir, dockerfile string) (outStr string) { sess, err := session.NewSession(ctx, "foo1", "foo") assert.Check(t, err) @@ -110,7 +112,7 @@ func testBuildWithSession(t *testing.T, client dclient.APIClient, daemonHost str g.Go(func() error { // FIXME use sock here - res, body, err := request.Do( + res, body, err := request.Do(ctx, "/build?remote=client-session&session="+sess.ID(), request.Host(daemonHost), request.Method(http.MethodPost), diff --git a/integration/build/build_squash_test.go b/integration/build/build_squash_test.go index 2e8e45604b..70fd878e10 100644 --- a/integration/build/build_squash_test.go +++ b/integration/build/build_squash_test.go @@ -2,7 +2,6 @@ package build import ( "bytes" - "context" "io" "strings" "testing" @@ -11,6 +10,7 @@ import ( dclient "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" @@ -21,12 +21,14 @@ import ( func TestBuildSquashParent(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") + ctx := testutil.StartSpan(baseContext, t) + var client dclient.APIClient if !testEnv.DaemonInfo.ExperimentalBuild { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") d := daemon.New(t, daemon.WithExperimental()) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) client = d.NewClientT(t) } else { @@ -43,7 +45,6 @@ func TestBuildSquashParent(t *testing.T) { ` // build and get the ID that we can use later for history comparison - ctx := context.Background() source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) defer source.Close() diff --git a/integration/build/build_test.go b/integration/build/build_test.go index 8a7d0a5e15..b009bdefff 100644 --- a/integration/build/build_test.go +++ b/integration/build/build_test.go @@ -3,7 +3,6 @@ package build // import "github.com/docker/docker/integration/build" import ( "archive/tar" "bytes" - "context" "encoding/json" "io" "os" @@ -15,6 +14,7 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -22,7 +22,7 @@ import ( ) func TestBuildWithRemoveAndForceRemove(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) cases := []struct { name string @@ -88,11 +88,11 @@ func TestBuildWithRemoveAndForceRemove(t *testing.T) { } client := testEnv.APIClient() - ctx := context.Background() for _, c := range cases { c := c t.Run(c.name, func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) dockerfile := []byte(c.dockerfile) buff := bytes.NewBuffer(nil) @@ -143,7 +143,7 @@ func buildContainerIdsFilter(buildOutput io.Reader) (filters.Args, error) { // GUID path (\\?\Volume{dae8d3ac-b9a1-11e9-88eb-e8554b2ba1db}\newdir\hello}), // which currently isn't supported by Golang. func TestBuildMultiStageCopy(t *testing.T) { - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) dockerfile, err := os.ReadFile("testdata/Dockerfile." + t.Name()) assert.NilError(t, err) @@ -201,7 +201,7 @@ func TestBuildMultiStageParentConfig(t *testing.T) { FROM stage0 WORKDIR sub2 ` - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) defer source.Close() @@ -249,7 +249,7 @@ func TestBuildLabelWithTargets(t *testing.T) { LABEL label-b=inline-b ` - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) defer source.Close() @@ -314,7 +314,7 @@ func TestBuildWithEmptyLayers(t *testing.T) { COPY 2/ /target/ COPY 3/ /target/ ` - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile), fakecontext.WithFile("1/a", "asdf"), @@ -340,7 +340,8 @@ func TestBuildWithEmptyLayers(t *testing.T) { // #35652 func TestBuildMultiStageOnBuild(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.33"), "broken in earlier versions") - defer setupTest(t)() + ctx := setupTest(t) + // test both metadata and layer based commands as they may be implemented differently dockerfile := `FROM busybox AS stage1 ONBUILD RUN echo 'foo' >somefile @@ -353,7 +354,6 @@ RUN cat somefile FROM stage1 RUN cat somefile` - ctx := context.Background() source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) defer source.Close() @@ -378,7 +378,7 @@ RUN cat somefile` assert.NilError(t, err) assert.Assert(t, is.Equal(3, len(imageIDs))) - image, _, err := apiclient.ImageInspectWithRaw(context.Background(), imageIDs[2]) + image, _, err := apiclient.ImageInspectWithRaw(ctx, imageIDs[2]) assert.NilError(t, err) assert.Check(t, is.Contains(image.Config.Env, "bar=baz")) } @@ -388,8 +388,7 @@ func TestBuildUncleanTarFilenames(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.37"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") - ctx := context.TODO() - defer setupTest(t)() + ctx := setupTest(t) dockerfile := `FROM scratch COPY foo / @@ -447,8 +446,7 @@ COPY bar /` // #35641 func TestBuildMultiStageLayerLeak(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.37"), "broken in earlier versions") - ctx := context.TODO() - defer setupTest(t)() + ctx := setupTest(t) // all commands need to match until COPY dockerfile := `FROM busybox @@ -487,8 +485,7 @@ RUN [ ! -f foo ] // #37581 // #40444 (Windows Containers only) func TestBuildWithHugeFile(t *testing.T) { - ctx := context.TODO() - defer setupTest(t)() + ctx := setupTest(t) dockerfile := `FROM busybox ` @@ -527,8 +524,7 @@ RUN for g in $(seq 0 8); do dd if=/dev/urandom of=rnd bs=1K count=1 seek=$((1024 func TestBuildWCOWSandboxSize(t *testing.T) { t.Skip("FLAKY_TEST that needs to be fixed; see https://github.com/moby/moby/issues/42743") skip.If(t, testEnv.DaemonInfo.OSType != "windows", "only Windows has sandbox size control") - ctx := context.TODO() - defer setupTest(t)() + ctx := setupTest(t) dockerfile := `FROM busybox AS intermediate WORKDIR C:\\stuff @@ -576,8 +572,7 @@ COPY --from=intermediate C:\\stuff C:\\stuff func TestBuildWithEmptyDockerfile(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "broken in earlier versions") - ctx := context.TODO() - t.Cleanup(setupTest(t)) + ctx := setupTest(t) tests := []struct { name string @@ -634,7 +629,7 @@ func TestBuildPreserveOwnership(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "broken in earlier versions") - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) dockerfile, err := os.ReadFile("testdata/Dockerfile." + t.Name()) assert.NilError(t, err) @@ -646,6 +641,8 @@ func TestBuildPreserveOwnership(t *testing.T) { for _, target := range []string{"copy_from", "copy_from_chowned"} { t.Run(target, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) + resp, err := apiclient.ImageBuild( ctx, source.AsTarReader(t), @@ -671,8 +668,7 @@ func TestBuildPreserveOwnership(t *testing.T) { func TestBuildPlatformInvalid(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "experimental in older versions") - ctx := context.Background() - defer setupTest(t)() + ctx := setupTest(t) dockerfile := `FROM busybox ` diff --git a/integration/build/build_userns_linux_test.go b/integration/build/build_userns_linux_test.go index dbb70f5961..d465546aa8 100644 --- a/integration/build/build_userns_linux_test.go +++ b/integration/build/build_userns_linux_test.go @@ -3,7 +3,6 @@ package build // import "github.com/docker/docker/integration/build" import ( "bufio" "bytes" - "context" "io" "os" "strings" @@ -13,6 +12,7 @@ import ( "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "github.com/docker/docker/testutil/fixtures/load" @@ -30,6 +30,8 @@ func TestBuildUserNamespaceValidateCapabilitiesAreV2(t *testing.T) { skip.If(t, !testEnv.IsUserNamespaceInKernel()) skip.If(t, testEnv.IsRootless()) + ctx := testutil.StartSpan(baseContext, t) + const imageTag = "capabilities:1.0" tmp, err := os.MkdirTemp("", "integration-") @@ -38,11 +40,10 @@ func TestBuildUserNamespaceValidateCapabilitiesAreV2(t *testing.T) { dUserRemap := daemon.New(t) dUserRemap.Start(t, "--userns-remap", "default") - ctx := context.Background() clientUserRemap := dUserRemap.NewClientT(t) defer clientUserRemap.Close() - err = load.FrozenImagesLinux(clientUserRemap, "debian:bullseye-slim") + err = load.FrozenImagesLinux(ctx, clientUserRemap, "debian:bullseye-slim") assert.NilError(t, err) dUserRemapRunning := true diff --git a/integration/build/main_test.go b/integration/build/main_test.go index 735f2a49a6..231113eae4 100644 --- a/integration/build/main_test.go +++ b/integration/build/main_test.go @@ -1,33 +1,56 @@ package build // import "github.com/docker/docker/integration/build" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + + ctx, span := otel.Tracer("").Start(context.Background(), "integration/build/TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + span.End() + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { testEnv.Clean(ctx, t) }) + return ctx } diff --git a/integration/capabilities/capabilities_linux_test.go b/integration/capabilities/capabilities_linux_test.go index 836d7af8cc..876ef1af05 100644 --- a/integration/capabilities/capabilities_linux_test.go +++ b/integration/capabilities/capabilities_linux_test.go @@ -2,7 +2,6 @@ package capabilities import ( "bytes" - "context" "io" "strings" "testing" @@ -11,6 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" @@ -18,7 +18,7 @@ import ( ) func TestNoNewPrivileges(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) withFileCapability := ` FROM debian:bullseye-slim @@ -35,7 +35,6 @@ func TestNoNewPrivileges(t *testing.T) { client := testEnv.APIClient() // Build image - ctx := context.TODO() resp, err := client.ImageBuild(ctx, source.AsTarReader(t), types.ImageBuildOptions{ @@ -72,6 +71,8 @@ func TestNoNewPrivileges(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.doc, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) + // Run the container with the image opts := append(tc.opts, container.WithImage(imageTag), diff --git a/integration/capabilities/main_linux_test.go b/integration/capabilities/main_linux_test.go index 0f074dd156..9054572228 100644 --- a/integration/capabilities/main_linux_test.go +++ b/integration/capabilities/main_linux_test.go @@ -1,33 +1,56 @@ package capabilities import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + + ctx, span := otel.Tracer("").Start(context.Background(), "integration/capabilities/TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + span.End() + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { testEnv.Clean(ctx, t) }) + return ctx } diff --git a/integration/config/config_test.go b/integration/config/config_test.go index a19917998f..6d83698e9e 100644 --- a/integration/config/config_test.go +++ b/integration/config/config_test.go @@ -15,6 +15,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration/internal/swarm" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/poll" @@ -24,14 +25,13 @@ import ( func TestConfigInspect(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() - testName := t.Name() configID := createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), nil) @@ -48,12 +48,12 @@ func TestConfigInspect(t *testing.T) { func TestConfigList(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() // This test case is ported from the original TestConfigsEmptyList configs, err := c.ConfigList(ctx, types.ConfigListOptions{}) @@ -76,39 +76,46 @@ func TestConfigList(t *testing.T) { assert.Check(t, is.DeepEqual(configNamesFromList(entries), testNames)) testCases := []struct { + desc string filters filters.Args expected []string }{ - // test filter by name `config ls --filter name=xxx` { + desc: "test filter by name", filters: filters.NewArgs(filters.Arg("name", testName0)), expected: []string{testName0}, }, - // test filter by id `config ls --filter id=xxx` { + desc: "test filter by id", filters: filters.NewArgs(filters.Arg("id", config1ID)), expected: []string{testName1}, }, - // test filter by label `config ls --filter label=xxx` { + desc: "test filter by label key only", filters: filters.NewArgs(filters.Arg("label", "type")), expected: testNames, }, { + desc: "test filter by label key=value " + testName0, filters: filters.NewArgs(filters.Arg("label", "type=test")), expected: []string{testName0}, }, { + desc: "test filter by label key=value " + testName1, filters: filters.NewArgs(filters.Arg("label", "type=production")), expected: []string{testName1}, }, } for _, tc := range testCases { - entries, err = c.ConfigList(ctx, types.ConfigListOptions{ - Filters: tc.filters, + tc := tc + t.Run(tc.desc, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) + entries, err = c.ConfigList(ctx, types.ConfigListOptions{ + Filters: tc.filters, + }) + assert.NilError(t, err) + assert.Check(t, is.DeepEqual(configNamesFromList(entries), tc.expected)) }) - assert.NilError(t, err) - assert.Check(t, is.DeepEqual(configNamesFromList(entries), tc.expected)) } } @@ -128,12 +135,11 @@ func createConfig(ctx context.Context, t *testing.T, client client.APIClient, na func TestConfigsCreateAndDelete(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() testName := "test_config-" + t.Name() configID := createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), nil) @@ -166,12 +172,12 @@ func TestConfigsCreateAndDelete(t *testing.T) { func TestConfigsUpdate(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() testName := "test_config-" + t.Name() configID := createConfig(ctx, t, c, testName, []byte("TESTINGDATA"), nil) @@ -217,11 +223,12 @@ func TestConfigsUpdate(t *testing.T) { func TestTemplatedConfig(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - d := swarm.NewSwarm(t, testEnv) + ctx := testutil.StartSpan(baseContext, t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() referencedSecretName := "referencedsecret-" + t.Name() referencedSecretSpec := swarmtypes.SecretSpec{ @@ -261,7 +268,7 @@ func TestTemplatedConfig(t *testing.T) { assert.Check(t, err) serviceName := "svc_" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithConfig( &swarmtypes.ConfigReference{ File: &swarmtypes.ConfigReferenceFileTarget{ @@ -301,12 +308,12 @@ func TestTemplatedConfig(t *testing.T) { swarm.ServiceWithName(serviceName), ) - poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, 1), swarm.ServicePoll, poll.WithTimeout(1*time.Minute)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, 1), swarm.ServicePoll, poll.WithTimeout(1*time.Minute)) - tasks := swarm.GetRunningTasks(t, c, serviceID) + tasks := swarm.GetRunningTasks(ctx, t, c, serviceID) assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) - attach := swarm.ExecTask(t, d, tasks[0], types.ExecConfig{ + attach := swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ Cmd: []string{"/bin/cat", "/templated_config"}, AttachStdout: true, AttachStderr: true, @@ -317,7 +324,7 @@ func TestTemplatedConfig(t *testing.T) { "this is a config\n" assertAttachedStream(t, attach, expect) - attach = swarm.ExecTask(t, d, tasks[0], types.ExecConfig{ + attach = swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ Cmd: []string{"mount"}, AttachStdout: true, AttachStderr: true, @@ -329,14 +336,13 @@ func TestTemplatedConfig(t *testing.T) { func TestConfigCreateResolve(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() - configName := "test_config_" + t.Name() configID := createConfig(ctx, t, c, configName, []byte("foo"), nil) diff --git a/integration/config/main_test.go b/integration/config/main_test.go index dc5c8e834d..4c62ec61f0 100644 --- a/integration/config/main_test.go +++ b/integration/config/main_test.go @@ -1,33 +1,55 @@ package config // import "github.com/docker/docker/integration/config" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/config/TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + span.End() + shutdown(ctx) os.Exit(m.Run()) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { testEnv.Clean(ctx, t) }) + return ctx } diff --git a/integration/container/attach_test.go b/integration/container/attach_test.go index f0eabd4e9d..c2c2c4b888 100644 --- a/integration/container/attach_test.go +++ b/integration/container/attach_test.go @@ -1,19 +1,19 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) func TestAttach(t *testing.T) { - t.Cleanup(setupTest(t)) - apiClient := testEnv.APIClient() + ctx := setupTest(t) + client := testEnv.APIClient() tests := []struct { doc string @@ -34,7 +34,9 @@ func TestAttach(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() - resp, err := apiClient.ContainerCreate(context.Background(), + + ctx := testutil.StartSpan(ctx, t) + resp, err := client.ContainerCreate(ctx, &container.Config{ Image: "busybox", Cmd: []string{"echo", "hello"}, @@ -46,7 +48,7 @@ func TestAttach(t *testing.T) { "", ) assert.NilError(t, err) - attach, err := apiClient.ContainerAttach(context.Background(), resp.ID, types.ContainerAttachOptions{ + attach, err := client.ContainerAttach(ctx, resp.ID, types.ContainerAttachOptions{ Stdout: true, Stderr: true, }) diff --git a/integration/container/cdi_test.go b/integration/container/cdi_test.go index 52a356d287..2a803488e8 100644 --- a/integration/container/cdi_test.go +++ b/integration/container/cdi_test.go @@ -2,7 +2,6 @@ package container // import "github.com/docker/docker/integration/container" import ( "bytes" - "context" "encoding/json" "io" "os" @@ -14,6 +13,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -24,15 +24,16 @@ func TestCreateWithCDIDevices(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux", "CDI devices are only supported on Linux") skip.If(t, testEnv.IsRemoteDaemon, "cannot run cdi tests with a remote daemon") + ctx := testutil.StartSpan(baseContext, t) + cwd, err := os.Getwd() assert.NilError(t, err) d := daemon.New(t, daemon.WithExperimental()) - d.StartWithBusybox(t, "--cdi-spec-dir="+filepath.Join(cwd, "testdata", "cdi")) + d.StartWithBusybox(ctx, t, "--cdi-spec-dir="+filepath.Join(cwd, "testdata", "cdi")) defer d.Stop(t) apiClient := d.NewClientT(t) - ctx := context.Background() id := container.Run(ctx, t, apiClient, container.WithCmd("/bin/sh", "-c", "env"), container.WithCDIDevices("vendor1.com/device=foo"), diff --git a/integration/container/checkpoint_test.go b/integration/container/checkpoint_test.go index 8419a7b765..03d2872b43 100644 --- a/integration/container/checkpoint_test.go +++ b/integration/container/checkpoint_test.go @@ -21,9 +21,8 @@ import ( ) //nolint:unused // false positive: linter detects this as "unused" -func containerExec(t *testing.T, client client.APIClient, cID string, cmd []string) { +func containerExec(ctx context.Context, t *testing.T, client client.APIClient, cID string, cmd []string) { t.Logf("Exec: %s", cmd) - ctx := context.Background() r, err := container.Exec(ctx, client, cID, cmd) assert.NilError(t, err) t.Log(r.Combined()) @@ -35,13 +34,12 @@ func TestCheckpoint(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, !testEnv.DaemonInfo.ExperimentalBuild) - defer setupTest(t)() + ctx := setupTest(t) stdoutStderr, err := exec.Command("criu", "check").CombinedOutput() t.Logf("%s", stdoutStderr) assert.NilError(t, err) - ctx := context.Background() apiClient := request.NewAPIClient(t) t.Log("Start a container") @@ -101,7 +99,7 @@ func TestCheckpoint(t *testing.T) { assert.Equal(t, checkpoints[0].Name, "test") // Create a test file on a tmpfs mount. - containerExec(t, apiClient, cID, []string{"touch", "/tmp/test-file"}) + containerExec(ctx, t, apiClient, cID, []string{"touch", "/tmp/test-file"}) // Do a second checkpoint t.Log("Do a checkpoint and stop the container") @@ -144,7 +142,7 @@ func TestCheckpoint(t *testing.T) { assert.Check(t, is.Equal(true, inspect.State.Running)) // Check that the test file has been restored. - containerExec(t, apiClient, cID, []string{"test", "-f", "/tmp/test-file"}) + containerExec(ctx, t, apiClient, cID, []string{"test", "-f", "/tmp/test-file"}) for _, id := range []string{"test", "test2"} { err = apiClient.CheckpointDelete(ctx, cID, checkpoint.DeleteOptions{ diff --git a/integration/container/container_test.go b/integration/container/container_test.go index e822667615..aa62cb89e7 100644 --- a/integration/container/container_test.go +++ b/integration/container/container_test.go @@ -5,6 +5,7 @@ import ( "runtime" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -13,7 +14,7 @@ import ( // TestContainerInvalidJSON tests that POST endpoints that expect a body return // the correct error when sending invalid JSON requests. func TestContainerInvalidJSON(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) // POST endpoints that accept / expect a JSON body; endpoints := []string{ @@ -39,7 +40,8 @@ func TestContainerInvalidJSON(t *testing.T) { t.Parallel() t.Run("invalid content type", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{}"), request.ContentType("text/plain")) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{}"), request.ContentType("text/plain")) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -49,7 +51,8 @@ func TestContainerInvalidJSON(t *testing.T) { }) t.Run("invalid JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{invalid json"), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -59,7 +62,8 @@ func TestContainerInvalidJSON(t *testing.T) { }) t.Run("extra content after JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString(`{} trailing content`), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString(`{} trailing content`), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -69,10 +73,11 @@ func TestContainerInvalidJSON(t *testing.T) { }) t.Run("empty body", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) // empty body should not produce an 500 internal server error, or // any 5XX error (this is assuming the request does not produce // an internal server error for another reason, but it shouldn't) - res, _, err := request.Post(ep, request.RawString(``), request.JSON) + res, _, err := request.Post(ctx, ep, request.RawString(``), request.JSON) assert.NilError(t, err) assert.Check(t, res.StatusCode < http.StatusInternalServerError) }) diff --git a/integration/container/copy_test.go b/integration/container/copy_test.go index c9b8878517..02143bc53d 100644 --- a/integration/container/copy_test.go +++ b/integration/container/copy_test.go @@ -3,7 +3,6 @@ package container // import "github.com/docker/docker/integration/container" import ( "archive/tar" "bytes" - "context" "encoding/json" "io" "os" @@ -22,9 +21,8 @@ import ( ) func TestCopyFromContainerPathDoesNotExist(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() cid := container.Create(ctx, t, apiClient) @@ -34,9 +32,8 @@ func TestCopyFromContainerPathDoesNotExist(t *testing.T) { } func TestCopyFromContainerPathIsNotDir(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() cid := container.Create(ctx, t, apiClient) @@ -51,9 +48,8 @@ func TestCopyFromContainerPathIsNotDir(t *testing.T) { } func TestCopyToContainerPathDoesNotExist(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() cid := container.Create(ctx, t, apiClient) @@ -63,9 +59,8 @@ func TestCopyToContainerPathDoesNotExist(t *testing.T) { } func TestCopyEmptyFile(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() cid := container.Create(ctx, t, apiClient) @@ -120,9 +115,8 @@ func makeEmptyArchive(t *testing.T) (string, io.ReadCloser) { } func TestCopyToContainerPathIsNotDir(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() cid := container.Create(ctx, t, apiClient) @@ -136,9 +130,8 @@ func TestCopyToContainerPathIsNotDir(t *testing.T) { func TestCopyFromContainer(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() dir, err := os.MkdirTemp("", t.Name()) diff --git a/integration/container/create_test.go b/integration/container/create_test.go index f01f7e1f43..912a50824f 100644 --- a/integration/container/create_test.go +++ b/integration/container/create_test.go @@ -16,6 +16,7 @@ import ( "github.com/docker/docker/errdefs" ctr "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/oci" + "github.com/docker/docker/testutil" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -24,8 +25,8 @@ import ( ) func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) { - t.Cleanup(setupTest(t)) - apiClient := testEnv.APIClient() + ctx := setupTest(t) + client := testEnv.APIClient() testCases := []struct { doc string @@ -53,7 +54,8 @@ func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() - _, err := apiClient.ContainerCreate(context.Background(), + ctx := testutil.StartSpan(ctx, t) + _, err := client.ContainerCreate(ctx, &container.Config{Image: tc.image}, &container.HostConfig{}, &network.NetworkingConfig{}, @@ -71,10 +73,10 @@ func TestCreateFailsWhenIdentifierDoesNotExist(t *testing.T) { // "non exists" (404). func TestCreateLinkToNonExistingContainer(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "legacy links are not supported on windows") - defer setupTest(t)() - apiClient := testEnv.APIClient() + ctx := setupTest(t) + c := testEnv.APIClient() - _, err := apiClient.ContainerCreate(context.Background(), + _, err := c.ContainerCreate(ctx, &container.Config{ Image: "busybox", }, @@ -90,8 +92,8 @@ func TestCreateLinkToNonExistingContainer(t *testing.T) { } func TestCreateWithInvalidEnv(t *testing.T) { - t.Cleanup(setupTest(t)) - apiClient := testEnv.APIClient() + ctx := setupTest(t) + client := testEnv.APIClient() testCases := []struct { env string @@ -115,7 +117,8 @@ func TestCreateWithInvalidEnv(t *testing.T) { tc := tc t.Run(strconv.Itoa(index), func(t *testing.T) { t.Parallel() - _, err := apiClient.ContainerCreate(context.Background(), + ctx := testutil.StartSpan(ctx, t) + _, err := client.ContainerCreate(ctx, &container.Config{ Image: "busybox", Env: []string{tc.env}, @@ -134,9 +137,9 @@ func TestCreateWithInvalidEnv(t *testing.T) { // Test case for #30166 (target was not validated) func TestCreateTmpfsMountsTarget(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") + ctx := setupTest(t) - defer setupTest(t)() - apiClient := testEnv.APIClient() + client := testEnv.APIClient() testCases := []struct { target string @@ -161,7 +164,7 @@ func TestCreateTmpfsMountsTarget(t *testing.T) { } for _, tc := range testCases { - _, err := apiClient.ContainerCreate(context.Background(), + _, err := client.ContainerCreate(ctx, &container.Config{ Image: "busybox", }, @@ -180,9 +183,8 @@ func TestCreateTmpfsMountsTarget(t *testing.T) { func TestCreateWithCustomMaskedPaths(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() testCases := []struct { maskedPaths []string @@ -224,6 +226,8 @@ func TestCreateWithCustomMaskedPaths(t *testing.T) { assert.DeepEqual(t, expected, mps) } + // TODO: This should be using subtests + for i, tc := range testCases { name := fmt.Sprintf("create-masked-paths-%d", i) config := container.Config{ @@ -236,7 +240,7 @@ func TestCreateWithCustomMaskedPaths(t *testing.T) { } // Create the container. - c, err := apiClient.ContainerCreate(context.Background(), + c, err := apiClient.ContainerCreate(ctx, &config, &hc, &network.NetworkingConfig{}, @@ -260,9 +264,8 @@ func TestCreateWithCustomMaskedPaths(t *testing.T) { func TestCreateWithCustomReadonlyPaths(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() testCases := []struct { readonlyPaths []string @@ -315,7 +318,7 @@ func TestCreateWithCustomReadonlyPaths(t *testing.T) { } // Create the container. - c, err := apiClient.ContainerCreate(context.Background(), + c, err := apiClient.ContainerCreate(ctx, &config, &hc, &network.NetworkingConfig{}, @@ -337,9 +340,8 @@ func TestCreateWithCustomReadonlyPaths(t *testing.T) { } func TestCreateWithInvalidHealthcheckParams(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() testCases := []struct { doc string @@ -391,6 +393,7 @@ func TestCreateWithInvalidHealthcheckParams(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) cfg := container.Config{ Image: "busybox", Healthcheck: &container.HealthConfig{ @@ -420,9 +423,8 @@ func TestCreateWithInvalidHealthcheckParams(t *testing.T) { // https://github.com/moby/moby/issues/40446 func TestCreateTmpfsOverrideAnonymousVolume(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "windows does not support tmpfs") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() id := ctr.Create(ctx, t, apiClient, ctr.WithVolume("/foo"), @@ -466,15 +468,15 @@ func TestCreateTmpfsOverrideAnonymousVolume(t *testing.T) { // Test that if the referenced image platform does not match the requested platform on container create that we get an // error. func TestCreateDifferentPlatform(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() img, _, err := apiClient.ImageInspectWithRaw(ctx, "busybox:latest") assert.NilError(t, err) assert.Assert(t, img.Architecture != "") t.Run("different os", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) p := ocispec.Platform{ OS: img.Os + "DifferentOS", Architecture: img.Architecture, @@ -484,6 +486,7 @@ func TestCreateDifferentPlatform(t *testing.T) { assert.Check(t, is.ErrorType(err, errdefs.IsNotFound)) }) t.Run("different cpu arch", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) p := ocispec.Platform{ OS: img.Os, Architecture: img.Architecture + "DifferentArch", @@ -495,11 +498,11 @@ func TestCreateDifferentPlatform(t *testing.T) { } func TestCreateVolumesFromNonExistingContainer(t *testing.T) { - defer setupTest(t)() - apiClient := testEnv.APIClient() + ctx := setupTest(t) + cli := testEnv.APIClient() - _, err := apiClient.ContainerCreate( - context.Background(), + _, err := cli.ContainerCreate( + ctx, &container.Config{Image: "busybox"}, &container.HostConfig{VolumesFrom: []string{"nosuchcontainer"}}, nil, @@ -512,14 +515,14 @@ func TestCreateVolumesFromNonExistingContainer(t *testing.T) { // Test that we can create a container from an image that is for a different platform even if a platform was not specified // This is for the regression detailed here: https://github.com/moby/moby/issues/41552 func TestCreatePlatformSpecificImageNoPlatform(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) skip.If(t, testEnv.DaemonInfo.Architecture == "arm", "test only makes sense to run on non-arm systems") skip.If(t, testEnv.DaemonInfo.OSType != "linux", "test image is only available on linux") - apiClient := testEnv.APIClient() + cli := testEnv.APIClient() - _, err := apiClient.ContainerCreate( - context.Background(), + _, err := cli.ContainerCreate( + ctx, &container.Config{Image: "arm32v7/hello-world"}, &container.HostConfig{}, nil, @@ -532,9 +535,8 @@ func TestCreatePlatformSpecificImageNoPlatform(t *testing.T) { func TestCreateInvalidHostConfig(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - t.Cleanup(setupTest(t)) + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() testCases := []struct { doc string @@ -572,6 +574,7 @@ func TestCreateInvalidHostConfig(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) cfg := container.Config{ Image: "busybox", } diff --git a/integration/container/daemon_linux_test.go b/integration/container/daemon_linux_test.go index 07d79bd05d..ef22f0706f 100644 --- a/integration/container/daemon_linux_test.go +++ b/integration/container/daemon_linux_test.go @@ -13,6 +13,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" realcontainer "github.com/docker/docker/container" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "golang.org/x/sys/unix" "gotest.tools/v3/assert" @@ -37,14 +38,14 @@ func TestContainerStartOnDaemonRestart(t *testing.T) { skip.If(t, testEnv.IsRootless) t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t, "--iptables=false") + d.StartWithBusybox(ctx, t, "--iptables=false") defer d.Stop(t) c := d.NewClientT(t) - ctx := context.Background() - cID := container.Create(ctx, t, c) defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) @@ -91,12 +92,13 @@ func TestDaemonRestartIpcMode(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t, "--iptables=false", "--default-ipc-mode=private") + d.StartWithBusybox(ctx, t, "--iptables=false", "--default-ipc-mode=private") defer d.Stop(t) c := d.NewClientT(t) - ctx := context.Background() // check the container is created with private ipc mode as per daemon default cID := container.Run(ctx, t, c, @@ -137,12 +139,13 @@ func TestDaemonHostGatewayIP(t *testing.T) { skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + // Verify the IP in /etc/hosts is same as host-gateway-ip d := daemon.New(t) // Verify the IP in /etc/hosts is same as the default bridge's IP - d.StartWithBusybox(t, "--iptables=false") + d.StartWithBusybox(ctx, t, "--iptables=false") c := d.NewClientT(t) - ctx := context.Background() cID := container.Run(ctx, t, c, container.WithExtraHost("host.docker.internal:host-gateway"), ) @@ -157,7 +160,7 @@ func TestDaemonHostGatewayIP(t *testing.T) { d.Stop(t) // Verify the IP in /etc/hosts is same as host-gateway-ip - d.StartWithBusybox(t, "--iptables=false", "--host-gateway-ip=6.7.8.9") + d.StartWithBusybox(ctx, t, "--iptables=false", "--host-gateway-ip=6.7.8.9") cID = container.Run(ctx, t, c, container.WithExtraHost("host.docker.internal:host-gateway"), ) @@ -187,13 +190,14 @@ func TestRestartDaemonWithRestartingContainer(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) defer d.Cleanup(t) - d.StartWithBusybox(t, "--iptables=false") + d.StartWithBusybox(ctx, t, "--iptables=false") defer d.Stop(t) - ctx := context.Background() apiClient := d.NewClientT(t) // Just create the container, no need to start it to be started. @@ -232,13 +236,14 @@ func TestHardRestartWhenContainerIsRunning(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) defer d.Cleanup(t) - d.StartWithBusybox(t, "--iptables=false") + d.StartWithBusybox(ctx, t, "--iptables=false") defer d.Stop(t) - ctx := context.Background() apiClient := d.NewClientT(t) // Just create the containers, no need to start them. @@ -259,6 +264,7 @@ func TestHardRestartWhenContainerIsRunning(t *testing.T) { d.Start(t, "--iptables=false") t.Run("RestartPolicy=none", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() inspect, err := apiClient.ContainerInspect(ctx, noPolicy) @@ -272,6 +278,7 @@ func TestHardRestartWhenContainerIsRunning(t *testing.T) { }) t.Run("RestartPolicy=on-failure", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() inspect, err := apiClient.ContainerInspect(ctx, onFailure) diff --git a/integration/container/daemon_test.go b/integration/container/daemon_test.go index 343170f2f0..4aeb2e3fd8 100644 --- a/integration/container/daemon_test.go +++ b/integration/container/daemon_test.go @@ -1,11 +1,11 @@ package container import ( - "context" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -21,14 +21,15 @@ func TestContainerKillOnDaemonStart(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) defer d.Cleanup(t) - d.StartWithBusybox(t, "--iptables=false") + d.StartWithBusybox(ctx, t, "--iptables=false") defer d.Stop(t) apiClient := d.NewClientT(t) - ctx := context.Background() // The intention of this container is to ignore stop signals. // Sadly this means the test will take longer, but at least this test can be parallelized. diff --git a/integration/container/devices_windows_test.go b/integration/container/devices_windows_test.go index fb83dfe932..4fe1e8793c 100644 --- a/integration/container/devices_windows_test.go +++ b/integration/container/devices_windows_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "strings" "testing" "time" @@ -9,6 +8,7 @@ import ( "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" "gotest.tools/v3/skip" @@ -18,9 +18,8 @@ import ( // via HostConfig.Devices through to the implementation in hcsshim. func TestWindowsDevices(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "windows") - t.Cleanup(setupTest(t)) + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() testData := []struct { doc string @@ -90,6 +89,7 @@ func TestWindowsDevices(t *testing.T) { d := d t.Run(d.doc, func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) deviceOptions := []func(*container.TestContainerConfig){container.WithIsolation(d.isolation)} for _, deviceName := range d.devices { deviceOptions = append(deviceOptions, container.WithWindowsDevice(deviceName)) diff --git a/integration/container/diff_test.go b/integration/container/diff_test.go index ed54f2acaf..e01a90e5c3 100644 --- a/integration/container/diff_test.go +++ b/integration/container/diff_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "time" @@ -14,9 +13,8 @@ import ( func TestDiff(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithCmd("sh", "-c", `mkdir /foo; echo xyzzy > /foo/bar`)) diff --git a/integration/container/exec_linux_test.go b/integration/container/exec_linux_test.go index f61fc47879..06f5856f18 100644 --- a/integration/container/exec_linux_test.go +++ b/integration/container/exec_linux_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "strings" "testing" @@ -16,9 +15,8 @@ func TestExecConsoleSize(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.42"), "skip test from new feature") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithImage("busybox")) diff --git a/integration/container/exec_test.go b/integration/container/exec_test.go index 81a36fbb51..8fd663eb2a 100644 --- a/integration/container/exec_test.go +++ b/integration/container/exec_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "io" "testing" "time" @@ -19,9 +18,8 @@ import ( func TestExecWithCloseStdin(t *testing.T) { skip.If(t, testEnv.RuntimeIsWindowsContainerd(), "FIXME. Hang on Windows + containerd combination") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "broken in earlier versions") - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() // run top with detached mode @@ -86,8 +84,7 @@ func TestExecWithCloseStdin(t *testing.T) { func TestExec(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.35"), "broken in earlier versions") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithWorkingDir("/root")) @@ -129,8 +126,7 @@ func TestExec(t *testing.T) { func TestExecUser(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME. Probably needs to wait for container to be in running state.") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithUser("1:1")) diff --git a/integration/container/export_test.go b/integration/container/export_test.go index 8a4bd86e25..41609d00a9 100644 --- a/integration/container/export_test.go +++ b/integration/container/export_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "encoding/json" "strings" "testing" @@ -11,6 +10,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -22,9 +22,8 @@ import ( func TestExportContainerAndImportImage(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithCmd("true")) poll.WaitOn(t, container.IsStopped(ctx, apiClient, cID), poll.WithDelay(100*time.Millisecond)) @@ -61,13 +60,14 @@ func TestExportContainerAfterDaemonRestart(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRemoteDaemon) + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) c := d.NewClientT(t) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) - ctx := context.Background() ctrID := container.Create(ctx, t, c) d.Restart(t) diff --git a/integration/container/health_test.go b/integration/container/health_test.go index 5d3c0a9ded..9444bfa9ba 100644 --- a/integration/container/health_test.go +++ b/integration/container/health_test.go @@ -19,8 +19,7 @@ import ( // working-dir. func TestHealthCheckWorkdir(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithWorkingDir("/foo"), func(c *container.TestContainerConfig) { @@ -38,9 +37,8 @@ func TestHealthCheckWorkdir(t *testing.T) { // Do not stop healthchecks just because we sent a signal to the container func TestHealthKillContainer(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "Windows only supports SIGKILL and SIGTERM? See https://github.com/moby/moby/issues/39574") - defer setupTest(t)() + ctx := setupTest(t) - ctx := context.Background() apiClient := testEnv.APIClient() id := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { @@ -96,8 +94,7 @@ while true; do sleep 1; done // TestHealthCheckProcessKilled verifies that health-checks exec get killed on time-out. func TestHealthCheckProcessKilled(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { @@ -113,8 +110,7 @@ func TestHealthCheckProcessKilled(t *testing.T) { func TestHealthStartInterval(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "The shell commands used in the test healthcheck do not work on Windows") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() // Note: Windows is much slower than linux so this use longer intervals/timeouts diff --git a/integration/container/inspect_test.go b/integration/container/inspect_test.go index 31e41e30c0..4df2d17aa4 100644 --- a/integration/container/inspect_test.go +++ b/integration/container/inspect_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "encoding/json" "strings" "testing" @@ -19,9 +18,8 @@ import ( func TestInspectCpusetInConfigPre120(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows" || !testEnv.DaemonInfo.CPUSet) - defer setupTest(t)() + ctx := setupTest(t) apiClient := request.NewAPIClient(t, client.WithVersion("1.19")) - ctx := context.Background() name := strings.ToLower(t.Name()) // Create container with up to-date-API @@ -49,9 +47,8 @@ func TestInspectCpusetInConfigPre120(t *testing.T) { } func TestInspectAnnotations(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := request.NewAPIClient(t) - ctx := context.Background() annotations := map[string]string{ "hello": "world", diff --git a/integration/container/ipcmode_linux_test.go b/integration/container/ipcmode_linux_test.go index edf5c4f51e..99224a6364 100644 --- a/integration/container/ipcmode_linux_test.go +++ b/integration/container/ipcmode_linux_test.go @@ -2,7 +2,6 @@ package container // import "github.com/docker/docker/integration/container" import ( "bufio" - "context" "os" "regexp" "strings" @@ -13,6 +12,7 @@ import ( "github.com/docker/docker/api/types/versions" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" @@ -53,7 +53,7 @@ func testIpcCheckDevExists(mm string) (bool, error) { // testIpcNonePrivateShareable is a helper function to test "none", // "private" and "shareable" modes. func testIpcNonePrivateShareable(t *testing.T, mode string, mustBeMounted bool, mustBeShared bool) { - defer setupTest(t)() + ctx := setupTest(t) cfg := containertypes.Config{ Image: "busybox", @@ -63,7 +63,6 @@ func testIpcNonePrivateShareable(t *testing.T, mode string, mustBeMounted bool, IpcMode: containertypes.IpcMode(mode), } apiClient := testEnv.APIClient() - ctx := context.Background() resp, err := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "") assert.NilError(t, err) @@ -124,7 +123,7 @@ func TestIpcModeShareable(t *testing.T) { func testIpcContainer(t *testing.T, donorMode string, mustWork bool) { t.Helper() - defer setupTest(t)() + ctx := setupTest(t) cfg := containertypes.Config{ Image: "busybox", @@ -133,7 +132,6 @@ func testIpcContainer(t *testing.T, donorMode string, mustWork bool) { hostCfg := containertypes.HostConfig{ IpcMode: containertypes.IpcMode(donorMode), } - ctx := context.Background() apiClient := testEnv.APIClient() // create and start the "donor" container @@ -199,7 +197,8 @@ func TestAPIIpcModeHost(t *testing.T) { hostCfg := containertypes.HostConfig{ IpcMode: containertypes.IPCModeHost, } - ctx := context.Background() + + ctx := testutil.StartSpan(baseContext, t) apiClient := testEnv.APIClient() resp, err := apiClient.ContainerCreate(ctx, &cfg, &hostCfg, nil, nil, "") @@ -225,10 +224,10 @@ func TestAPIIpcModeHost(t *testing.T) { // testDaemonIpcPrivateShareable is a helper function to test "private" and "shareable" daemon default ipc modes. func testDaemonIpcPrivateShareable(t *testing.T, mustBeShared bool, arg ...string) { - defer setupTest(t)() + ctx := setupTest(t) d := daemon.New(t) - d.StartWithBusybox(t, arg...) + d.StartWithBusybox(ctx, t, arg...) defer d.Stop(t) c := d.NewClientT(t) @@ -237,7 +236,6 @@ func testDaemonIpcPrivateShareable(t *testing.T, mustBeShared bool, arg ...strin Image: "busybox", Cmd: []string{"top"}, } - ctx := context.Background() resp, err := c.ContainerCreate(ctx, &cfg, &containertypes.HostConfig{}, nil, nil, "") assert.NilError(t, err) @@ -308,7 +306,7 @@ func TestIpcModeOlderClient(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) // pre-check: default ipc mode in daemon is private cID := container.Create(ctx, t, apiClient, container.WithAutoRemove) diff --git a/integration/container/kill_test.go b/integration/container/kill_test.go index 55e441210d..5951b74d0b 100644 --- a/integration/container/kill_test.go +++ b/integration/container/kill_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "runtime" "testing" "time" @@ -9,6 +8,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/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -17,9 +17,8 @@ import ( ) func TestKillContainerInvalidSignal(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() id := container.Run(ctx, t, apiClient) err := apiClient.ContainerKill(ctx, id, "0") @@ -34,7 +33,7 @@ func TestKillContainerInvalidSignal(t *testing.T) { } func TestKillContainer(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() testCases := []struct { @@ -72,7 +71,7 @@ func TestKillContainer(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == tc.skipOs, "Windows does not support SIGWINCH") - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) id := container.Run(ctx, t, apiClient) err := apiClient.ContainerKill(ctx, id, tc.signal) assert.NilError(t, err) @@ -83,7 +82,7 @@ func TestKillContainer(t *testing.T) { } func TestKillWithStopSignalAndRestartPolicies(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() testCases := []struct { @@ -111,7 +110,7 @@ func TestKillWithStopSignalAndRestartPolicies(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.doc, func(t *testing.T) { - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) id := container.Run(ctx, t, apiClient, container.WithRestartPolicy(containertypes.RestartPolicyAlways), func(c *container.TestContainerConfig) { @@ -126,8 +125,7 @@ func TestKillWithStopSignalAndRestartPolicies(t *testing.T) { } func TestKillStoppedContainer(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() id := container.Create(ctx, t, apiClient) err := apiClient.ContainerKill(ctx, id, "SIGKILL") @@ -137,8 +135,7 @@ func TestKillStoppedContainer(t *testing.T) { func TestKillStoppedContainerAPIPre120(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "Windows only supports 1.25 or later") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := request.NewAPIClient(t, client.WithVersion("1.19")) id := container.Create(ctx, t, apiClient) err := apiClient.ContainerKill(ctx, id, "SIGKILL") @@ -149,8 +146,7 @@ func TestKillDifferentUserContainer(t *testing.T) { // TODO Windows: Windows does not yet support -u (Feb 2016). skip.If(t, testEnv.DaemonInfo.OSType == "windows", "User containers (container.Config.User) are not yet supported on %q platform", testEnv.DaemonInfo.OSType) - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := request.NewAPIClient(t, client.WithVersion("1.19")) id := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { @@ -169,8 +165,7 @@ func TestInspectOomKilledTrue(t *testing.T) { skip.If(t, !testEnv.DaemonInfo.MemoryLimit || !testEnv.DaemonInfo.SwapLimit) skip.If(t, testEnv.DaemonInfo.CgroupVersion == "2", "FIXME: flaky on cgroup v2 (https://github.com/moby/moby/issues/41929)") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient, container.WithCmd("sh", "-c", "x=a; while true; do x=$x$x$x$x; done"), func(c *container.TestContainerConfig) { @@ -187,8 +182,7 @@ func TestInspectOomKilledTrue(t *testing.T) { func TestInspectOomKilledFalse(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows" || !testEnv.DaemonInfo.MemoryLimit || !testEnv.DaemonInfo.SwapLimit) - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient, container.WithCmd("sh", "-c", "echo hello world")) diff --git a/integration/container/links_linux_test.go b/integration/container/links_linux_test.go index 51e9fca6da..92d4cc1514 100644 --- a/integration/container/links_linux_test.go +++ b/integration/container/links_linux_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "os" "testing" @@ -20,9 +19,9 @@ func TestLinksEtcHostsContentMatch(t *testing.T) { hosts, err := os.ReadFile("/etc/hosts") skip.If(t, os.IsNotExist(err)) - defer setupTest(t)() + ctx := setupTest(t) + apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithNetworkMode("host")) res, err := container.Exec(ctx, apiClient, cID, []string{"cat", "/etc/hosts"}) @@ -36,9 +35,8 @@ func TestLinksEtcHostsContentMatch(t *testing.T) { func TestLinksContainerNames(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() containerA := "first_" + t.Name() containerB := "second_" + t.Name() diff --git a/integration/container/logs_test.go b/integration/container/logs_test.go index d18737fcd9..7bf95c1567 100644 --- a/integration/container/logs_test.go +++ b/integration/container/logs_test.go @@ -2,7 +2,6 @@ package container // import "github.com/docker/docker/integration/container" import ( "bytes" - "context" "io" "strings" "testing" @@ -25,9 +24,8 @@ import ( func TestLogsFollowTailEmpty(t *testing.T) { // FIXME(vdemeester) fails on a e2e run on linux... skip.If(t, testEnv.IsRemoteDaemon) - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() id := container.Run(ctx, t, apiClient, container.WithCmd("sleep", "100000")) @@ -52,9 +50,8 @@ func TestLogs(t *testing.T) { } func testLogs(t *testing.T, logDriver string) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() testCases := []struct { desc string diff --git a/integration/container/main_test.go b/integration/container/main_test.go index bb7b2eb02f..a8d364e8a3 100644 --- a/integration/container/main_test.go +++ b/integration/container/main_test.go @@ -1,33 +1,56 @@ package container // import "github.com/docker/docker/integration/container" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { var err error - testEnv, err = environment.New() + shutdown := testutil.ConfigureTracing() + + ctx, span := otel.Tracer("").Start(context.Background(), "integration/container/TestMain") + baseContext = ctx + + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, "environment.New failed") + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + span.End() + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { testEnv.Clean(ctx, t) }) + return ctx } diff --git a/integration/container/mounts_linux_test.go b/integration/container/mounts_linux_test.go index 2ee54d5899..13bf138c2a 100644 --- a/integration/container/mounts_linux_test.go +++ b/integration/container/mounts_linux_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "fmt" "os" "path/filepath" @@ -17,6 +16,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/parsers/kernel" + "github.com/docker/docker/testutil" "github.com/moby/sys/mount" "github.com/moby/sys/mountinfo" "gotest.tools/v3/assert" @@ -30,9 +30,7 @@ func TestContainerNetworkMountsNoChown(t *testing.T) { // chown only applies to Linux bind mounted volumes; must be same host to verify skip.If(t, testEnv.IsRemoteDaemon) - defer setupTest(t)() - - ctx := context.Background() + ctx := setupTest(t) tmpDir := fs.NewDir(t, "network-file-mounts", fs.WithMode(0o755), fs.WithFile("nwfile", "network file bind mount", fs.WithMode(0o644))) defer tmpDir.Remove() @@ -91,9 +89,8 @@ func TestContainerNetworkMountsNoChown(t *testing.T) { func TestMountDaemonRoot(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) - t.Cleanup(setupTest(t)) + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() info, err := apiClient.Info(ctx) if err != nil { t.Fatal(err) @@ -140,6 +137,8 @@ func TestMountDaemonRoot(t *testing.T) { test := test t.Parallel() + ctx := testutil.StartSpan(ctx, t) + propagationSpec := fmt.Sprintf(":%s", test.propagation) if test.propagation == "" { propagationSpec = "" @@ -175,6 +174,8 @@ func TestMountDaemonRoot(t *testing.T) { hc := hc t.Parallel() + ctx := testutil.StartSpan(ctx, t) + c, err := apiClient.ContainerCreate(ctx, &containertypes.Config{ Image: "busybox", Cmd: []string{"true"}, @@ -219,7 +220,7 @@ func TestContainerBindMountNonRecursive(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "BindOptions.NonRecursive requires API v1.40") skip.If(t, testEnv.IsRootless, "cannot be tested because RootlessKit executes the daemon in private mount namespace (https://github.com/rootless-containers/rootlesskit/issues/97)") - defer setupTest(t)() + ctx := setupTest(t) tmpDir1 := fs.NewDir(t, "tmpdir1", fs.WithMode(0o755), fs.WithDir("mnt", fs.WithMode(0o755))) @@ -257,7 +258,6 @@ func TestContainerBindMountNonRecursive(t *testing.T) { } nonRecursiveVerifier := []string{"test", "!", "-f", "/foo/mnt/file"} - ctx := context.Background() apiClient := testEnv.APIClient() containers := []string{ container.Run(ctx, t, apiClient, container.WithMount(implicit), container.WithCmd(recursiveVerifier...)), @@ -277,7 +277,7 @@ func TestContainerVolumesMountedAsShared(t *testing.T) { skip.If(t, testEnv.IsUserNamespace) skip.If(t, testEnv.IsRootless, "cannot be tested because RootlessKit executes the daemon in private mount namespace (https://github.com/rootless-containers/rootlesskit/issues/97)") - defer setupTest(t)() + ctx := setupTest(t) // Prepare a source directory to bind mount tmpDir1 := fs.NewDir(t, "volume-source", fs.WithMode(0o755), @@ -310,7 +310,6 @@ func TestContainerVolumesMountedAsShared(t *testing.T) { bindMountCmd := []string{"mount", "--bind", "/volume-dest/mnt1", "/volume-dest/mnt1"} - ctx := context.Background() apiClient := testEnv.APIClient() containerID := container.Run(ctx, t, apiClient, container.WithPrivileged(true), container.WithMount(sharedMount), container.WithCmd(bindMountCmd...)) poll.WaitOn(t, container.IsSuccessful(ctx, apiClient, containerID), poll.WithDelay(100*time.Millisecond)) @@ -330,6 +329,8 @@ func TestContainerVolumesMountedAsSlave(t *testing.T) { skip.If(t, testEnv.IsUserNamespace) skip.If(t, testEnv.IsRootless, "cannot be tested because RootlessKit executes the daemon in private mount namespace (https://github.com/rootless-containers/rootlesskit/issues/97)") + ctx := testutil.StartSpan(baseContext, t) + // Prepare a source directory to bind mount tmpDir1 := fs.NewDir(t, "volume-source", fs.WithMode(0o755), fs.WithDir("mnt1", fs.WithMode(0o755))) @@ -367,7 +368,6 @@ func TestContainerVolumesMountedAsSlave(t *testing.T) { topCmd := []string{"top"} - ctx := context.Background() apiClient := testEnv.APIClient() containerID := container.Run(ctx, t, apiClient, container.WithTty(true), container.WithMount(slaveMount), container.WithCmd(topCmd...)) @@ -396,7 +396,7 @@ func TestContainerVolumesMountedAsSlave(t *testing.T) { // Regression test for #38995 and #43390. func TestContainerCopyLeaksMounts(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) bindMount := mounttypes.Mount{ Type: mounttypes.TypeBind, @@ -407,7 +407,6 @@ func TestContainerCopyLeaksMounts(t *testing.T) { }, } - ctx := context.Background() apiClient := testEnv.APIClient() cid := container.Run(ctx, t, apiClient, container.WithMount(bindMount), container.WithCmd("sleep", "120s")) @@ -433,7 +432,7 @@ func TestContainerBindMountRecursivelyReadOnly(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.44"), "requires API v1.44") - defer setupTest(t)() + ctx := setupTest(t) // 0o777 for allowing rootless containers to write to this directory tmpDir1 := fs.NewDir(t, "tmpdir1", fs.WithMode(0o777), @@ -488,7 +487,6 @@ func TestContainerBindMountRecursivelyReadOnly(t *testing.T) { Propagation: mounttypes.PropagationRPrivate, } - ctx := context.Background() apiClient := testEnv.APIClient() containers := []string{ diff --git a/integration/container/nat_test.go b/integration/container/nat_test.go index 9fa47b9e16..6836c6aa70 100644 --- a/integration/container/nat_test.go +++ b/integration/container/nat_test.go @@ -23,10 +23,10 @@ func TestNetworkNat(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") skip.If(t, testEnv.IsRemoteDaemon) - defer setupTest(t)() + ctx := setupTest(t) msg := "it works" - startServerContainer(t, msg, 8080) + startServerContainer(ctx, t, msg, 8080) endpoint := getExternalAddress(t) conn, err := net.Dial("tcp", net.JoinHostPort(endpoint.String(), "8080")) @@ -41,10 +41,10 @@ func TestNetworkNat(t *testing.T) { func TestNetworkLocalhostTCPNat(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) - defer setupTest(t)() + ctx := setupTest(t) msg := "hi yall" - startServerContainer(t, msg, 8081) + startServerContainer(ctx, t, msg, 8081) conn, err := net.Dial("tcp", "localhost:8081") assert.NilError(t, err) @@ -60,15 +60,14 @@ func TestNetworkLoopbackNat(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") skip.If(t, testEnv.IsRemoteDaemon) - defer setupTest(t)() + ctx := setupTest(t) msg := "it works" - serverContainerID := startServerContainer(t, msg, 8080) + serverContainerID := startServerContainer(ctx, t, msg, 8080) endpoint := getExternalAddress(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithCmd("sh", "-c", fmt.Sprintf("stty raw && nc -w 1 %s 8080", endpoint.String())), @@ -91,10 +90,9 @@ func TestNetworkLoopbackNat(t *testing.T) { assert.Check(t, is.Equal(msg, strings.TrimSpace(b.String()))) } -func startServerContainer(t *testing.T, msg string, port int) string { +func startServerContainer(ctx context.Context, t *testing.T, msg string, port int) string { t.Helper() apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithName("server-"+t.Name()), diff --git a/integration/container/overlayfs_linux_test.go b/integration/container/overlayfs_linux_test.go index 4736e6afc2..1b160b5fdd 100644 --- a/integration/container/overlayfs_linux_test.go +++ b/integration/container/overlayfs_linux_test.go @@ -1,7 +1,6 @@ package container import ( - "context" "io" "strings" "testing" @@ -19,9 +18,8 @@ func TestNoOverlayfsWarningsAboutUndefinedBehaviors(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon(), "local daemon is needed for kernel log access") skip.If(t, testEnv.IsRootless(), "root is needed for reading kernel log") - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, client, container.WithCmd("sh", "-c", `while true; do echo $RANDOM >>/file; sleep 0.1; done`)) diff --git a/integration/container/pause_test.go b/integration/container/pause_test.go index e46d5f4b66..61119c4fe3 100644 --- a/integration/container/pause_test.go +++ b/integration/container/pause_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "io" "testing" "time" @@ -24,9 +23,8 @@ func TestPause(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows" && testEnv.DaemonInfo.Isolation == "process") skip.If(t, testEnv.DaemonInfo.CgroupDriver == "none") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient) poll.WaitOn(t, container.IsInState(ctx, apiClient, cID, "running"), poll.WithDelay(100*time.Millisecond)) @@ -56,9 +54,8 @@ func TestPause(t *testing.T) { func TestPauseFailsOnWindowsServerContainers(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "windows" || testEnv.DaemonInfo.Isolation != "process") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient) poll.WaitOn(t, container.IsInState(ctx, apiClient, cID, "running"), poll.WithDelay(100*time.Millisecond)) @@ -71,9 +68,8 @@ func TestPauseStopPausedContainer(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.31"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.CgroupDriver == "none") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient) poll.WaitOn(t, container.IsInState(ctx, apiClient, cID, "running"), poll.WithDelay(100*time.Millisecond)) diff --git a/integration/container/pidmode_linux_test.go b/integration/container/pidmode_linux_test.go index aeb209a44b..f0713a2c07 100644 --- a/integration/container/pidmode_linux_test.go +++ b/integration/container/pidmode_linux_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "os" "testing" "time" @@ -22,9 +21,8 @@ func TestPIDModeHost(t *testing.T) { hostPid, err := os.Readlink("/proc/1/ns/pid") assert.NilError(t, err) - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithPIDMode("host")) poll.WaitOn(t, container.IsInState(ctx, apiClient, cID, "running"), poll.WithDelay(100*time.Millisecond)) diff --git a/integration/container/ps_test.go b/integration/container/ps_test.go index 4fcc14f84f..048e541a2b 100644 --- a/integration/container/ps_test.go +++ b/integration/container/ps_test.go @@ -1,20 +1,19 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) func TestPsFilter(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() prev := container.Create(ctx, t, apiClient) top := container.Create(ctx, t, apiClient) @@ -29,6 +28,7 @@ func TestPsFilter(t *testing.T) { } t.Run("since", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) results, err := apiClient.ContainerList(ctx, types.ContainerListOptions{ All: true, Filters: filters.NewArgs(filters.Arg("since", top)), @@ -38,6 +38,7 @@ func TestPsFilter(t *testing.T) { }) t.Run("before", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) results, err := apiClient.ContainerList(ctx, types.ContainerListOptions{ All: true, Filters: filters.NewArgs(filters.Arg("before", top)), diff --git a/integration/container/remove_test.go b/integration/container/remove_test.go index 1c2e06d99f..e6bcf90c4d 100644 --- a/integration/container/remove_test.go +++ b/integration/container/remove_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "os" "testing" "time" @@ -29,8 +28,7 @@ func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) { func TestRemoveContainerWithRemovedVolume(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() prefix, slash := getPrefixAndSlashFromDaemonPlatform() @@ -56,8 +54,7 @@ func TestRemoveContainerWithRemovedVolume(t *testing.T) { // Test case for #2099/#2125 func TestRemoveContainerWithVolume(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() prefix, slash := getPrefixAndSlashFromDaemonPlatform() @@ -83,8 +80,7 @@ func TestRemoveContainerWithVolume(t *testing.T) { } func TestRemoveContainerRunning(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient) @@ -95,8 +91,7 @@ func TestRemoveContainerRunning(t *testing.T) { } func TestRemoveContainerForceRemoveRunning(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() cID := container.Run(ctx, t, apiClient) @@ -108,8 +103,7 @@ func TestRemoveContainerForceRemoveRunning(t *testing.T) { } func TestRemoveInvalidContainer(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() err := apiClient.ContainerRemove(ctx, "unknown", types.ContainerRemoveOptions{}) diff --git a/integration/container/rename_test.go b/integration/container/rename_test.go index c0a91f9b87..5383699d2e 100644 --- a/integration/container/rename_test.go +++ b/integration/container/rename_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "time" @@ -24,8 +23,7 @@ import ( func TestRenameLinkedContainer(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.32"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() aName := "a0" + t.Name() @@ -49,8 +47,7 @@ func TestRenameLinkedContainer(t *testing.T) { } func TestRenameStoppedContainer(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() oldName := "first_name" + t.Name() @@ -71,8 +68,7 @@ func TestRenameStoppedContainer(t *testing.T) { } func TestRenameRunningContainerAndReuse(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() oldName := "first_name" + t.Name() @@ -99,8 +95,7 @@ func TestRenameRunningContainerAndReuse(t *testing.T) { } func TestRenameInvalidName(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() oldName := "first_name" + t.Name() @@ -123,8 +118,7 @@ func TestRenameInvalidName(t *testing.T) { // This test is to make sure once the container has been renamed, // the service discovery for the (re)named container works. func TestRenameAnonymousContainer(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() networkName := "network1" + t.Name() @@ -169,8 +163,7 @@ func TestRenameAnonymousContainer(t *testing.T) { // TODO: should be a unit test func TestRenameContainerWithSameName(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() oldName := "old" + t.Name() @@ -192,8 +185,7 @@ func TestRenameContainerWithLinkedContainer(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) apiClient := testEnv.APIClient() db1Name := "db1" + t.Name() diff --git a/integration/container/resize_test.go b/integration/container/resize_test.go index b4ddd972ba..3de202d997 100644 --- a/integration/container/resize_test.go +++ b/integration/container/resize_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "net/http" "testing" "time" @@ -17,9 +16,8 @@ import ( ) func TestResize(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithTty(true)) @@ -34,24 +32,22 @@ func TestResize(t *testing.T) { func TestResizeWithInvalidSize(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.32"), "broken in earlier versions") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient) poll.WaitOn(t, container.IsInState(ctx, apiClient, cID, "running"), poll.WithDelay(100*time.Millisecond)) endpoint := "/containers/" + cID + "/resize?h=foo&w=bar" - res, _, err := req.Post(endpoint) + res, _, err := req.Post(ctx, endpoint) assert.NilError(t, err) assert.Check(t, is.DeepEqual(http.StatusBadRequest, res.StatusCode)) } func TestResizeWhenContainerNotStarted(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithCmd("echo")) diff --git a/integration/container/restart_test.go b/integration/container/restart_test.go index 55e10e5548..c3324c3f2e 100644 --- a/integration/container/restart_test.go +++ b/integration/container/restart_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" testContainer "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/poll" @@ -20,6 +21,9 @@ func TestDaemonRestartKillContainers(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run") skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRootless, "rootless mode doesn't support live-restore") + + ctx := testutil.StartSpan(baseContext, t) + type testCase struct { desc string config *container.Config @@ -83,6 +87,8 @@ func TestDaemonRestartKillContainers(t *testing.T) { t.Run(fmt.Sprintf("live-restore=%v/%s/%s", liveRestoreEnabled, tc.desc, fnName), func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) + d := daemon.New(t) apiClient := d.NewClientT(t) @@ -91,9 +97,8 @@ func TestDaemonRestartKillContainers(t *testing.T) { args = append(args, "--live-restore") } - d.StartWithBusybox(t, args...) + d.StartWithBusybox(ctx, t, args...) defer d.Stop(t) - ctx := context.Background() resp, err := apiClient.ContainerCreate(ctx, tc.config, tc.hostConfig, nil, nil, "") assert.NilError(t, err) @@ -157,9 +162,8 @@ func pollForNewHealthCheck(ctx context.Context, client *client.Client, startTime // Container started with --rm should be able to be restarted. // It should be removed only if killed or stopped func TestContainerWithAutoRemoveCanBeRestarted(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() noWaitTimeout := 0 @@ -182,6 +186,7 @@ func TestContainerWithAutoRemoveCanBeRestarted(t *testing.T) { } { tc := tc t.Run(tc.desc, func(t *testing.T) { + testutil.StartSpan(ctx, t) cID := testContainer.Run(ctx, t, apiClient, testContainer.WithName("autoremove-restart-and-"+tc.desc), testContainer.WithAutoRemove, diff --git a/integration/container/run_cgroupns_linux_test.go b/integration/container/run_cgroupns_linux_test.go index 534b1aa4db..e6a8dcfc26 100644 --- a/integration/container/run_cgroupns_linux_test.go +++ b/integration/container/run_cgroupns_linux_test.go @@ -8,6 +8,7 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/integration/internal/requirement" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/poll" @@ -15,12 +16,11 @@ import ( ) // Bring up a daemon with the specified default cgroup namespace mode, and then create a container with the container options -func testRunWithCgroupNs(t *testing.T, daemonNsMode string, containerOpts ...func(*container.TestContainerConfig)) (string, string) { +func testRunWithCgroupNs(ctx context.Context, t *testing.T, daemonNsMode string, containerOpts ...func(*container.TestContainerConfig)) (string, string) { d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode)) apiClient := d.NewClientT(t) - ctx := context.Background() - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) cID := container.Run(ctx, t, apiClient, containerOpts...) @@ -33,12 +33,11 @@ func testRunWithCgroupNs(t *testing.T, daemonNsMode string, containerOpts ...fun // Bring up a daemon with the specified default cgroup namespace mode. Create a container with the container options, // expecting an error with the specified string -func testCreateFailureWithCgroupNs(t *testing.T, daemonNsMode string, errStr string, containerOpts ...func(*container.TestContainerConfig)) { +func testCreateFailureWithCgroupNs(ctx context.Context, t *testing.T, daemonNsMode string, errStr string, containerOpts ...func(*container.TestContainerConfig)) { d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode(daemonNsMode)) apiClient := d.NewClientT(t) - ctx := context.Background() - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) _, err := container.CreateFromConfig(ctx, apiClient, container.NewTestConfig(containerOpts...)) assert.ErrorContains(t, err, errStr) @@ -49,9 +48,11 @@ func TestCgroupNamespacesRun(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to private cgroup namespaces, containers launched // should be in their own private cgroup namespace by default - containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private") + containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private") assert.Assert(t, daemonCgroup != containerCgroup) } @@ -61,9 +62,11 @@ func TestCgroupNamespacesRunPrivileged(t *testing.T) { skip.If(t, !requirement.CgroupNamespacesEnabled()) skip.If(t, testEnv.DaemonInfo.CgroupVersion == "2", "on cgroup v2, privileged containers use private cgroupns") + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to private cgroup namespaces, privileged containers // launched should not be inside their own cgroup namespaces - containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithPrivileged(true)) + containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithPrivileged(true)) assert.Assert(t, daemonCgroup == containerCgroup) } @@ -72,9 +75,11 @@ func TestCgroupNamespacesRunDaemonHostMode(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to host cgroup namespaces, containers // launched should not be inside their own cgroup namespaces - containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "host") + containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "host") assert.Assert(t, daemonCgroup == containerCgroup) } @@ -83,9 +88,11 @@ func TestCgroupNamespacesRunHostMode(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to private cgroup namespaces, containers launched // with a cgroup ns mode of "host" should not be inside their own cgroup namespaces - containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithCgroupnsMode("host")) + containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithCgroupnsMode("host")) assert.Assert(t, daemonCgroup == containerCgroup) } @@ -94,9 +101,11 @@ func TestCgroupNamespacesRunPrivateMode(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // When the daemon defaults to private cgroup namespaces, containers launched // with a cgroup ns mode of "private" should be inside their own cgroup namespaces - containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithCgroupnsMode("private")) + containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithCgroupnsMode("private")) assert.Assert(t, daemonCgroup != containerCgroup) } @@ -105,7 +114,9 @@ func TestCgroupNamespacesRunPrivilegedAndPrivate(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) - containerCgroup, daemonCgroup := testRunWithCgroupNs(t, "private", container.WithPrivileged(true), container.WithCgroupnsMode("private")) + ctx := testutil.StartSpan(baseContext, t) + + containerCgroup, daemonCgroup := testRunWithCgroupNs(ctx, t, "private", container.WithPrivileged(true), container.WithCgroupnsMode("private")) assert.Assert(t, daemonCgroup != containerCgroup) } @@ -114,9 +125,11 @@ func TestCgroupNamespacesRunInvalidMode(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + // An invalid cgroup namespace mode should return an error on container creation errStr := "invalid cgroup namespace mode: invalid" - testCreateFailureWithCgroupNs(t, "private", errStr, container.WithCgroupnsMode("invalid")) + testCreateFailureWithCgroupNs(ctx, t, "private", errStr, container.WithCgroupnsMode("invalid")) } // Clients before 1.40 expect containers to be created in the host cgroup namespace, @@ -126,11 +139,12 @@ func TestCgroupNamespacesRunOlderClient(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon()) skip.If(t, !requirement.CgroupNamespacesEnabled()) + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t, daemon.WithDefaultCgroupNamespaceMode("private")) apiClient := d.NewClientT(t, client.WithVersion("1.39")) - ctx := context.Background() - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) cID := container.Run(ctx, t, apiClient) diff --git a/integration/container/run_linux_test.go b/integration/container/run_linux_test.go index 6d51f6df66..cd34077aa2 100644 --- a/integration/container/run_linux_test.go +++ b/integration/container/run_linux_test.go @@ -2,7 +2,6 @@ package container // import "github.com/docker/docker/integration/container" import ( "bytes" - "context" "io" "os" "os/exec" @@ -17,6 +16,7 @@ import ( "github.com/docker/docker/integration/internal/container" net "github.com/docker/docker/integration/internal/network" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "golang.org/x/sys/unix" "gotest.tools/v3/assert" @@ -37,9 +37,8 @@ func TestNISDomainname(t *testing.T) { // "write sysctl key kernel.domainname: open /proc/sys/kernel/domainname: permission denied\"": unknown. skip.If(t, testEnv.IsRootless, "rootless mode doesn't support setting Domainname (TODO: https://github.com/moby/moby/issues/40632)") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() const ( hostname = "foobar" @@ -78,9 +77,8 @@ func TestNISDomainname(t *testing.T) { func TestHostnameDnsResolution(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() const ( hostname = "foobar" @@ -88,7 +86,7 @@ func TestHostnameDnsResolution(t *testing.T) { // using user defined network as we want to use internal DNS netName := "foobar-net" - net.CreateNoError(context.Background(), t, apiClient, netName, net.WithDriver("bridge")) + net.CreateNoError(ctx, t, apiClient, netName, net.WithDriver("bridge")) cID := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { c.Config.Hostname = hostname @@ -113,9 +111,8 @@ func TestUnprivilegedPortsAndPing(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, testEnv.IsRootless, "rootless mode doesn't support setting net.ipv4.ping_group_range and net.ipv4.ip_unprivileged_port_start") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { c.Config.User = "1000:1000" @@ -144,9 +141,8 @@ func TestPrivilegedHostDevices(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() const ( devTest = "/dev/test" @@ -193,9 +189,8 @@ func TestRunConsoleSize(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.42"), "skip test from new feature") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithTty(true), @@ -221,6 +216,8 @@ func TestRunWithAlternativeContainerdShim(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType != "linux") + ctx := testutil.StartSpan(baseContext, t) + realShimPath, err := exec.LookPath("containerd-shim-runc-v2") assert.Assert(t, err) realShimPath, err = filepath.Abs(realShimPath) @@ -246,11 +243,10 @@ func TestRunWithAlternativeContainerdShim(t *testing.T) { daemon.WithEnvVars("PATH="+shimDir+":"+os.Getenv("PATH")), daemon.WithContainerdSocket(""), // A new containerd instance needs to be started which inherits the PATH env var defined above. ) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) apiClient := d.NewClientT(t) - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithImage("busybox"), diff --git a/integration/container/stats_test.go b/integration/container/stats_test.go index 502cd3b2bc..5d78c23dae 100644 --- a/integration/container/stats_test.go +++ b/integration/container/stats_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "encoding/json" "io" "reflect" @@ -20,9 +19,8 @@ func TestStats(t *testing.T) { skip.If(t, testEnv.DaemonInfo.CgroupDriver == "none") skip.If(t, !testEnv.DaemonInfo.MemoryLimit) - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() info, err := apiClient.Info(ctx) assert.NilError(t, err) diff --git a/integration/container/stop_linux_test.go b/integration/container/stop_linux_test.go index 8b9965cd09..bb65d370c9 100644 --- a/integration/container/stop_linux_test.go +++ b/integration/container/stop_linux_test.go @@ -15,6 +15,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/poll" @@ -24,9 +25,9 @@ import ( // a timeout works as documented, i.e. in case of negative timeout // waiting is not limited (issue #35311). func TestStopContainerWithTimeout(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) + apiClient := testEnv.APIClient() - ctx := context.Background() testCmd := container.WithCmd("sh", "-c", "sleep 2 && exit 42") testData := []struct { @@ -58,6 +59,7 @@ func TestStopContainerWithTimeout(t *testing.T) { d := d t.Run(strconv.Itoa(d.timeout), func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) id := container.Run(ctx, t, apiClient, testCmd) err := apiClient.ContainerStop(ctx, id, containertypes.StopOptions{Timeout: &d.timeout}) @@ -78,17 +80,17 @@ func TestStopContainerWithTimeout(t *testing.T) { // See issue https://github.com/moby/moby/issues/45731 func TestStopContainerWithTimeoutCancel(t *testing.T) { t.Parallel() - defer setupTest(t)() + + ctx := setupTest(t) apiClient := testEnv.APIClient() t.Cleanup(func() { _ = apiClient.Close() }) - ctx := context.Background() id := container.Run(ctx, t, apiClient, container.WithCmd("sh", "-c", "trap 'echo received TERM' TERM; while true; do usleep 10; done"), ) poll.WaitOn(t, container.IsInState(ctx, apiClient, id, "running")) - ctxCancel, cancel := context.WithCancel(context.Background()) + ctxCancel, cancel := context.WithCancel(ctx) t.Cleanup(cancel) const stopTimeout = 3 diff --git a/integration/container/stop_test.go b/integration/container/stop_test.go index ab46c3281e..be53138aaa 100644 --- a/integration/container/stop_test.go +++ b/integration/container/stop_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "time" @@ -15,9 +14,8 @@ import ( const StopContainerWindowsPollTimeout = 75 * time.Second func TestStopContainerWithRestartPolicyAlways(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() names := []string{"verifyRestart1-" + t.Name(), "verifyRestart2-" + t.Name()} for _, name := range names { diff --git a/integration/container/stop_windows_test.go b/integration/container/stop_windows_test.go index c9b1d9167c..2d7dc33dad 100644 --- a/integration/container/stop_windows_test.go +++ b/integration/container/stop_windows_test.go @@ -1,13 +1,13 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "strconv" "testing" "time" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" "gotest.tools/v3/skip" @@ -18,9 +18,9 @@ import ( // waiting is not limited (issue #35311). func TestStopContainerWithTimeout(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - t.Cleanup(setupTest(t)) + ctx := setupTest(t) + apiClient := testEnv.APIClient() - ctx := context.Background() testCmd := container.WithCmd("sh", "-c", "sleep 2 && exit 42") testData := []struct { @@ -52,6 +52,7 @@ func TestStopContainerWithTimeout(t *testing.T) { d := d t.Run(strconv.Itoa(d.timeout), func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) id := container.Run(ctx, t, apiClient, testCmd) err := apiClient.ContainerStop(ctx, id, containertypes.StopOptions{Timeout: &d.timeout}) diff --git a/integration/container/update_linux_test.go b/integration/container/update_linux_test.go index 4c3b30c751..3ecc806ef5 100644 --- a/integration/container/update_linux_test.go +++ b/integration/container/update_linux_test.go @@ -10,6 +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/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -23,9 +24,8 @@ func TestUpdateMemory(t *testing.T) { skip.If(t, !testEnv.DaemonInfo.MemoryLimit) skip.If(t, !testEnv.DaemonInfo.SwapLimit) - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) { c.HostConfig.Resources = containertypes.Resources{ @@ -85,9 +85,8 @@ func TestUpdateMemory(t *testing.T) { func TestUpdateCPUQuota(t *testing.T) { skip.If(t, testEnv.DaemonInfo.CgroupDriver == "none") - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient) @@ -155,10 +154,9 @@ func TestUpdatePidsLimit(t *testing.T) { skip.If(t, testEnv.DaemonInfo.CgroupDriver == "none") skip.If(t, !testEnv.DaemonInfo.PidsLimit) - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() oldAPIClient := request.NewAPIClient(t, client.WithVersion("1.24")) - ctx := context.Background() intPtr := func(i int64) *int64 { return &i @@ -186,6 +184,7 @@ func TestUpdatePidsLimit(t *testing.T) { } t.Run(test.desc, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) // Using "network=host" to speed up creation (13.96s vs 6.54s) cID := container.Run(ctx, t, apiClient, container.WithPidsLimit(test.initial), container.WithNetworkMode("host")) diff --git a/integration/container/update_test.go b/integration/container/update_test.go index 8f83b89e42..672def670b 100644 --- a/integration/container/update_test.go +++ b/integration/container/update_test.go @@ -1,7 +1,6 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "time" @@ -13,9 +12,8 @@ import ( ) func TestUpdateRestartPolicy(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithCmd("sh", "-c", "sleep 1 && false"), func(c *container.TestContainerConfig) { c.HostConfig.RestartPolicy = containertypes.RestartPolicy{ @@ -46,9 +44,8 @@ func TestUpdateRestartPolicy(t *testing.T) { } func TestUpdateRestartWithAutoRemove(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) apiClient := testEnv.APIClient() - ctx := context.Background() cID := container.Run(ctx, t, apiClient, container.WithAutoRemove) diff --git a/integration/container/wait_test.go b/integration/container/wait_test.go index 47b5640575..28a45c94ca 100644 --- a/integration/container/wait_test.go +++ b/integration/container/wait_test.go @@ -1,13 +1,13 @@ package container // import "github.com/docker/docker/integration/container" import ( - "context" "testing" "time" "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -16,7 +16,8 @@ import ( ) func TestWaitNonBlocked(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) + cli := request.NewAPIClient(t) testCases := []struct { @@ -40,7 +41,8 @@ func TestWaitNonBlocked(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() - ctx := context.Background() + + ctx := testutil.StartSpan(ctx, t) containerID := container.Run(ctx, t, cli, container.WithCmd("sh", "-c", tc.cmd)) poll.WaitOn(t, container.IsInState(ctx, cli, containerID, "exited"), poll.WithTimeout(30*time.Second), poll.WithDelay(100*time.Millisecond)) @@ -59,7 +61,7 @@ func TestWaitBlocked(t *testing.T) { // Windows busybox does not support trap in this way, not sleep with sub-second // granularity. It will always exit 0x40010004. skip.If(t, testEnv.DaemonInfo.OSType != "linux") - t.Cleanup(setupTest(t)) + ctx := setupTest(t) cli := request.NewAPIClient(t) testCases := []struct { @@ -82,7 +84,7 @@ func TestWaitBlocked(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) containerID := container.Run(ctx, t, cli, container.WithCmd("sh", "-c", tc.cmd)) poll.WaitOn(t, container.IsInState(ctx, cli, containerID, "running"), poll.WithTimeout(30*time.Second), poll.WithDelay(100*time.Millisecond)) @@ -104,7 +106,7 @@ func TestWaitBlocked(t *testing.T) { } func TestWaitConditions(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) cli := request.NewAPIClient(t) testCases := []struct { @@ -134,7 +136,7 @@ func TestWaitConditions(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) opts := append([]func(*container.TestContainerConfig){ container.WithCmd("sh", "-c", "read -r; exit 99"), func(tcc *container.TestContainerConfig) { @@ -179,7 +181,7 @@ func TestWaitConditions(t *testing.T) { } func TestWaitRestartedContainer(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) cli := request.NewAPIClient(t) testCases := []struct { @@ -206,7 +208,7 @@ func TestWaitRestartedContainer(t *testing.T) { tc := tc t.Run(tc.doc, func(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) containerID := container.Run(ctx, t, cli, container.WithCmd("sh", "-c", "trap 'exit 5' SIGTERM; while true; do sleep 0.1; done"), ) diff --git a/integration/daemon/daemon_test.go b/integration/daemon/daemon_test.go index 21632572a7..394d75c87c 100644 --- a/integration/daemon/daemon_test.go +++ b/integration/daemon/daemon_test.go @@ -2,7 +2,6 @@ package daemon // import "github.com/docker/docker/integration/daemon" import ( "bytes" - "context" "fmt" "io" "net/http" @@ -23,6 +22,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -34,6 +34,8 @@ import ( func TestConfigDaemonID(t *testing.T) { skip.If(t, runtime.GOOS == "windows") + _ = testutil.StartSpan(baseContext, t) + d := daemon.New(t) defer d.Stop(t) @@ -59,6 +61,7 @@ func TestConfigDaemonID(t *testing.T) { func TestDaemonConfigValidation(t *testing.T) { skip.If(t, runtime.GOOS == "windows") + ctx := testutil.StartSpan(baseContext, t) d := daemon.New(t) dockerBinary, err := d.BinaryPath() @@ -111,6 +114,7 @@ func TestDaemonConfigValidation(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() + _ = testutil.StartSpan(ctx, t) cmd := exec.Command(dockerBinary, tc.args...) out, err := cmd.CombinedOutput() assert.Check(t, is.Contains(string(out), tc.expectedOut)) @@ -125,6 +129,7 @@ func TestDaemonConfigValidation(t *testing.T) { func TestConfigDaemonSeccompProfiles(t *testing.T) { skip.If(t, runtime.GOOS == "windows") + ctx := testutil.StartSpan(baseContext, t) d := daemon.New(t) defer d.Stop(t) @@ -154,6 +159,8 @@ func TestConfigDaemonSeccompProfiles(t *testing.T) { for _, tc := range tests { tc := tc t.Run(tc.doc, func(t *testing.T) { + _ = testutil.StartSpan(ctx, t) + d.Start(t, "--seccomp-profile="+tc.profile) info := d.Info(t) assert.Assert(t, is.Contains(info.SecurityOptions, "name=seccomp,profile="+tc.expectedProfile)) @@ -174,6 +181,7 @@ func TestConfigDaemonSeccompProfiles(t *testing.T) { func TestDaemonProxy(t *testing.T) { skip.If(t, runtime.GOOS == "windows", "cannot start multiple daemons on windows") skip.If(t, os.Getenv("DOCKER_ROOTLESS") != "", "cannot connect to localhost proxy in rootless environment") + ctx := testutil.StartSpan(baseContext, t) newProxy := func(rcvd *string, t *testing.T) *httptest.Server { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -191,7 +199,7 @@ func TestDaemonProxy(t *testing.T) { t.Run("environment variables", func(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) var received string proxyServer := newProxy(&received, t) @@ -224,7 +232,8 @@ func TestDaemonProxy(t *testing.T) { t.Run("command-line options", func(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) + var received string proxyServer := newProxy(&received, t) @@ -273,7 +282,7 @@ func TestDaemonProxy(t *testing.T) { // Configure proxy through configuration file t.Run("configuration file", func(t *testing.T) { t.Parallel() - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) var received string proxyServer := newProxy(&received, t) @@ -322,7 +331,7 @@ func TestDaemonProxy(t *testing.T) { // Conflicting options (passed both through command-line options and config file) t.Run("conflicting options", func(t *testing.T) { - ctx := context.Background() + ctx := testutil.StartSpan(ctx, t) const ( proxyRawURL = "https://" + userPass + "example.org" proxyURL = "https://xxxxx:xxxxx@example.org" @@ -347,8 +356,8 @@ func TestDaemonProxy(t *testing.T) { // Make sure values are sanitized when reloading the daemon-config t.Run("reload sanitized", func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) - ctx := context.Background() const ( proxyRawURL = "https://" + userPass + "example.org" proxyURL = "https://xxxxx:xxxxx@example.org" @@ -369,25 +378,27 @@ func TestDaemonProxy(t *testing.T) { func TestLiveRestore(t *testing.T) { skip.If(t, runtime.GOOS == "windows", "cannot start multiple daemons on windows") + _ = testutil.StartSpan(baseContext, t) t.Run("volume references", testLiveRestoreVolumeReferences) } func testLiveRestoreVolumeReferences(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(baseContext, t) d := daemon.New(t) - d.StartWithBusybox(t, "--live-restore", "--iptables=false") + d.StartWithBusybox(ctx, t, "--live-restore", "--iptables=false") defer func() { d.Stop(t) d.Cleanup(t) }() c := d.NewClientT(t) - ctx := context.Background() runTest := func(t *testing.T, policy containertypes.RestartPolicyMode) { t.Run(string(policy), func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) volName := "test-live-restore-volume-references-" + string(policy) _, err := c.VolumeCreate(ctx, volume.CreateOptions{Name: volName}) assert.NilError(t, err) @@ -423,6 +434,7 @@ func testLiveRestoreVolumeReferences(t *testing.T) { // Make sure that the local volume driver's mount ref count is restored // Addresses https://github.com/moby/moby/issues/44422 t.Run("local volume with mount options", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) v, err := c.VolumeCreate(ctx, volume.CreateOptions{ Driver: "local", Name: "test-live-restore-volume-references-local", @@ -505,6 +517,7 @@ func testLiveRestoreVolumeReferences(t *testing.T) { // (which should not be "restored") // Regression test for https://github.com/moby/moby/issues/45898 t.Run("container with bind-mounts", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) m := mount.Mount{ Type: mount.TypeBind, Source: os.TempDir(), @@ -523,6 +536,8 @@ func testLiveRestoreVolumeReferences(t *testing.T) { func TestDaemonDefaultBridgeWithFixedCidrButNoBip(t *testing.T) { skip.If(t, runtime.GOOS == "windows") + ctx := testutil.StartSpan(baseContext, t) + bridgeName := "ext-bridge1" d := daemon.New(t, daemon.WithEnvVars("DOCKER_TEST_CREATE_DEFAULT_BRIDGE="+bridgeName)) defer func() { @@ -538,7 +553,7 @@ func TestDaemonDefaultBridgeWithFixedCidrButNoBip(t *testing.T) { deleteInterface(t, bridgeName) } }() - d.StartWithBusybox(t, "--bridge", bridgeName, "--fixed-cidr", "192.168.130.0/24") + d.StartWithBusybox(ctx, t, "--bridge", bridgeName, "--fixed-cidr", "192.168.130.0/24") } func deleteInterface(t *testing.T, ifName string) { diff --git a/integration/daemon/main_test.go b/integration/daemon/main_test.go index 6fb7250a0f..48c73d1de6 100644 --- a/integration/daemon/main_test.go +++ b/integration/daemon/main_test.go @@ -1,28 +1,44 @@ package daemon // import "github.com/docker/docker/integration/daemon" import ( - "fmt" + "context" "os" "testing" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { var err error - testEnv, err = environment.New() + + ctx, span := otel.Tracer("").Start(context.Background(), "integration/daemon/TestMain") + baseContext = ctx + + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + panic(err) } testEnv.Print() - os.Exit(m.Run()) + + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + os.Exit(code) } diff --git a/integration/image/commit_test.go b/integration/image/commit_test.go index 813af90aa2..08cd1cf2f2 100644 --- a/integration/image/commit_test.go +++ b/integration/image/commit_test.go @@ -1,7 +1,6 @@ package image // import "github.com/docker/docker/integration/image" import ( - "context" "strings" "testing" @@ -16,9 +15,9 @@ import ( func TestCommitInheritsEnv(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.36"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") - defer setupTest(t)() + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() cID1 := container.Create(ctx, t, client) imgName := strings.ToLower(t.Name()) diff --git a/integration/image/import_test.go b/integration/image/import_test.go index 76c1d44dc1..d38d65c542 100644 --- a/integration/image/import_test.go +++ b/integration/image/import_test.go @@ -3,7 +3,6 @@ package image // import "github.com/docker/docker/integration/image" import ( "archive/tar" "bytes" - "context" "io" "runtime" "strconv" @@ -25,6 +24,8 @@ func TestImportExtremelyLargeImageWorks(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "TODO enable on windows") t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + // Spin up a new daemon, so that we can run this test in parallel (it's a slow test) d := daemon.New(t) d.Start(t, "--iptables=false") @@ -43,7 +44,7 @@ func TestImportExtremelyLargeImageWorks(t *testing.T) { imageRdr := io.MultiReader(&tarBuffer, io.LimitReader(testutil.DevZero, 8*1024*1024*1024)) reference := strings.ToLower(t.Name()) + ":v42" - _, err = client.ImageImport(context.Background(), + _, err = client.ImageImport(ctx, types.ImageImportSource{Source: imageRdr, SourceName: "-"}, reference, types.ImageImportOptions{}) @@ -53,9 +54,9 @@ func TestImportExtremelyLargeImageWorks(t *testing.T) { func TestImportWithCustomPlatform(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "TODO enable on windows") - defer setupTest(t)() + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() // Construct an empty tar archive. var tarBuffer bytes.Buffer @@ -127,8 +128,9 @@ func TestImportWithCustomPlatform(t *testing.T) { for i, tc := range tests { tc := tc t.Run(tc.platform, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) reference := "import-with-platform:tc-" + strconv.Itoa(i) - _, err = client.ImageImport(context.Background(), + _, err = client.ImageImport(ctx, types.ImageImportSource{Source: imageRdr, SourceName: "-"}, reference, types.ImageImportOptions{Platform: tc.platform}) diff --git a/integration/image/inspect_test.go b/integration/image/inspect_test.go index 594bcb9caa..c65154e461 100644 --- a/integration/image/inspect_test.go +++ b/integration/image/inspect_test.go @@ -1,7 +1,6 @@ package image import ( - "context" "encoding/json" "testing" @@ -14,10 +13,9 @@ import ( // Regression test for: https://github.com/moby/moby/issues/45556 func TestImageInspectEmptyTagsAndDigests(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "build-empty-images is not called on Windows") - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() danglingID := environment.GetTestDanglingImageId(testEnv) diff --git a/integration/image/list_test.go b/integration/image/list_test.go index b9eadb2e04..caabd809bf 100644 --- a/integration/image/list_test.go +++ b/integration/image/list_test.go @@ -1,7 +1,6 @@ package image // import "github.com/docker/docker/integration/image" import ( - "context" "fmt" "strings" "testing" @@ -11,6 +10,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/testutil" "github.com/google/go-cmp/cmp/cmpopts" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -20,9 +20,9 @@ import ( // Regression : #38171 func TestImagesFilterMultiReference(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "broken in earlier versions") - t.Cleanup(setupTest(t)) + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() name := strings.ToLower(t.Name()) repoTags := []string{ @@ -57,9 +57,9 @@ func TestImagesFilterMultiReference(t *testing.T) { } func TestImagesFilterBeforeSince(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() name := strings.ToLower(t.Name()) ctr := container.Create(ctx, t, client, container.WithName(name)) @@ -95,9 +95,8 @@ func TestImagesFilterBeforeSince(t *testing.T) { } func TestAPIImagesFilters(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() for _, n := range []string{"utest:tag1", "utest/docker:tag2", "utest:5000/docker:tag3"} { err := client.ImageTag(ctx, "busybox:latest", n) @@ -140,7 +139,9 @@ func TestAPIImagesFilters(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() - images, err := client.ImageList(context.Background(), types.ImageListOptions{ + + ctx := testutil.StartSpan(ctx, t) + images, err := client.ImageList(ctx, types.ImageListOptions{ Filters: filters.NewArgs(tc.filters...), }) assert.Check(t, err) diff --git a/integration/image/main_test.go b/integration/image/main_test.go index 893e2fdf5d..20a25ad268 100644 --- a/integration/image/main_test.go +++ b/integration/image/main_test.go @@ -1,33 +1,49 @@ package image // import "github.com/docker/docker/integration/image" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/daemon/TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() os.Exit(m.Run()) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { testEnv.Clean(ctx, t) }) + return ctx } diff --git a/integration/image/prune_test.go b/integration/image/prune_test.go index 48fb07ce6f..6c9ad467d2 100644 --- a/integration/image/prune_test.go +++ b/integration/image/prune_test.go @@ -1,7 +1,6 @@ package image import ( - "context" "testing" "github.com/docker/docker/api/types/filters" @@ -16,9 +15,8 @@ import ( func TestPruneDontDeleteUsedDangling(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME: hack/make/.build-empty-images doesn't run on Windows") - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() danglingID := environment.GetTestDanglingImageId(testEnv) diff --git a/integration/image/pull_test.go b/integration/image/pull_test.go index 689ceea976..08658b7d28 100644 --- a/integration/image/pull_test.go +++ b/integration/image/pull_test.go @@ -26,9 +26,9 @@ import ( func TestImagePullPlatformInvalid(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "experimental in older versions") - defer setupTest(t)() + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() _, err := client.ImagePull(ctx, "docker.io/library/hello-world:latest", types.ImagePullOptions{Platform: "foobar"}) assert.Assert(t, err != nil) @@ -117,14 +117,12 @@ func TestImagePullStoredfDigestForOtherRepo(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "We don't run a test registry on Windows") skip.If(t, testEnv.IsRootless, "Rootless has a different view of localhost (needed for test registry access)") - defer setupTest(t)() + ctx := setupTest(t) reg := registry.NewV2(t, registry.WithStdout(os.Stdout), registry.WithStderr(os.Stderr)) defer reg.Close() reg.WaitReady(t) - ctx := context.Background() - // First create an image and upload it to our local registry // Then we'll download it so that we can make sure the content is available in dockerd's manifest cache. // Then we'll try to pull the same digest but with a different repo name. diff --git a/integration/image/remove_test.go b/integration/image/remove_test.go index 59684a1752..a655e175fd 100644 --- a/integration/image/remove_test.go +++ b/integration/image/remove_test.go @@ -1,7 +1,6 @@ package image // import "github.com/docker/docker/integration/image" import ( - "context" "strings" "testing" @@ -14,8 +13,8 @@ import ( ) func TestRemoveImageOrphaning(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) + client := testEnv.APIClient() imgName := strings.ToLower(t.Name()) diff --git a/integration/image/remove_unix_test.go b/integration/image/remove_unix_test.go index 18921459f3..cee3a25a4d 100644 --- a/integration/image/remove_unix_test.go +++ b/integration/image/remove_unix_test.go @@ -3,7 +3,6 @@ package image // import "github.com/docker/docker/integration/image" import ( - "context" "io" "os" "path/filepath" @@ -18,6 +17,7 @@ import ( "github.com/docker/docker/daemon/images" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "gotest.tools/v3/assert" @@ -34,13 +34,14 @@ func TestRemoveImageGarbageCollector(t *testing.T) { skip.If(t, testEnv.NotAmd64) skip.If(t, testEnv.IsRootless, "rootless mode doesn't support overlay2 on most distros") + ctx := testutil.StartSpan(baseContext, t) + // 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")) d.Start(t) defer d.Stop(t) - ctx := context.Background() client := d.NewClientT(t) layerStore, _ := layer.NewStoreFromOptions(layer.StoreOptions{ diff --git a/integration/image/save_test.go b/integration/image/save_test.go index c74344bb7c..2e75f2078e 100644 --- a/integration/image/save_test.go +++ b/integration/image/save_test.go @@ -53,9 +53,8 @@ func tarIndexFS(t *testing.T, rdr io.Reader) fs.FS { func TestSaveCheckTimes(t *testing.T) { t.Parallel() - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() const repoName = "busybox:latest" img, _, err := client.ImageInspectWithRaw(ctx, repoName) @@ -83,8 +82,7 @@ func TestSaveCheckTimes(t *testing.T) { } func TestSaveRepoWithMultipleImages(t *testing.T) { - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) client := testEnv.APIClient() makeImage := func(from string, tag string) string { @@ -163,9 +161,7 @@ func TestSaveRepoWithMultipleImages(t *testing.T) { func TestSaveDirectoryPermissions(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "Test is looking at linux specific details") - defer setupTest(t)() - - ctx := context.Background() + ctx := setupTest(t) client := testEnv.APIClient() layerEntries := []string{"opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"} diff --git a/integration/image/tag_test.go b/integration/image/tag_test.go index 7203efe9ff..0c7a8faa40 100644 --- a/integration/image/tag_test.go +++ b/integration/image/tag_test.go @@ -1,7 +1,6 @@ package image // import "github.com/docker/docker/integration/image" import ( - "context" "fmt" "testing" @@ -11,9 +10,9 @@ import ( // tagging a named image in a new unprefixed repo should work func TestTagUnprefixedRepoByNameOrName(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() // By name err := client.ImageTag(ctx, "busybox:latest", "testfoobarbaz") @@ -27,18 +26,17 @@ func TestTagUnprefixedRepoByNameOrName(t *testing.T) { } func TestTagUsingDigestAlgorithmAsName(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() err := client.ImageTag(ctx, "busybox:latest", "sha256:sometag") assert.Check(t, is.ErrorContains(err, "refusing to create an ambiguous tag using digest algorithm as name")) } // ensure we allow the use of valid tags func TestTagValidPrefixedRepo(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) + client := testEnv.APIClient() - ctx := context.Background() validRepos := []string{"fooo/bar", "fooaa/test", "foooo:t", "HOSTNAME.DOMAIN.COM:443/foo/bar"} @@ -54,9 +52,8 @@ func TestTagValidPrefixedRepo(t *testing.T) { // tag an image with an existed tag name without -f option should work func TestTagExistedNameWithoutForce(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() err := client.ImageTag(ctx, "busybox:latest", "busybox:test") assert.NilError(t, err) @@ -65,9 +62,8 @@ func TestTagExistedNameWithoutForce(t *testing.T) { // ensure tagging using official names works // ensure all tags result in the same name func TestTagOfficialNames(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() names := []string{ "docker.io/busybox", @@ -97,9 +93,8 @@ func TestTagOfficialNames(t *testing.T) { // ensure tags can not match digests func TestTagMatchesDigest(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() digest := "busybox@sha256:abcdef76720241213f5303bda7704ec4c2ef75613173910a56fb1b6e20251507" // test setting tag fails diff --git a/integration/internal/swarm/service.go b/integration/internal/swarm/service.go index 19ebff0e9a..bf75016d66 100644 --- a/integration/internal/swarm/service.go +++ b/integration/internal/swarm/service.go @@ -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 ...daemon.Option) *daemon.Daemon { +func NewSwarm(ctx context.Context, 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") @@ -58,7 +58,7 @@ func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...daemon.Option ops = append(ops, daemon.WithExperimental()) } d := daemon.New(t, ops...) - d.StartAndSwarmInit(t) + d.StartAndSwarmInit(ctx, t) return d } @@ -66,14 +66,14 @@ func NewSwarm(t *testing.T, testEnv *environment.Execution, ops ...daemon.Option type ServiceSpecOpt func(*swarmtypes.ServiceSpec) // CreateService creates a service on the passed in swarm daemon. -func CreateService(t *testing.T, d *daemon.Daemon, opts ...ServiceSpecOpt) string { +func CreateService(ctx context.Context, t *testing.T, d *daemon.Daemon, opts ...ServiceSpecOpt) string { t.Helper() client := d.NewClientT(t) defer client.Close() spec := CreateServiceSpec(t, opts...) - resp, err := client.ServiceCreate(context.Background(), spec, types.ServiceCreateOptions{}) + resp, err := client.ServiceCreate(ctx, spec, types.ServiceCreateOptions{}) assert.NilError(t, err, "error creating service") return resp.ID } @@ -206,10 +206,10 @@ func ServiceWithPidsLimit(limit int64) ServiceSpecOpt { } // GetRunningTasks gets the list of running tasks for a service -func GetRunningTasks(t *testing.T, c client.ServiceAPIClient, serviceID string) []swarmtypes.Task { +func GetRunningTasks(ctx context.Context, t *testing.T, c client.ServiceAPIClient, serviceID string) []swarmtypes.Task { t.Helper() - tasks, err := c.TaskList(context.Background(), types.TaskListOptions{ + tasks, err := c.TaskList(ctx, types.TaskListOptions{ Filters: filters.NewArgs( filters.Arg("service", serviceID), filters.Arg("desired-state", "running"), @@ -221,12 +221,11 @@ func GetRunningTasks(t *testing.T, c client.ServiceAPIClient, serviceID string) } // ExecTask runs the passed in exec config on the given task -func ExecTask(t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse { +func ExecTask(ctx context.Context, t *testing.T, d *daemon.Daemon, task swarmtypes.Task, config types.ExecConfig) types.HijackedResponse { t.Helper() client := d.NewClientT(t) defer client.Close() - ctx := context.Background() resp, err := client.ContainerExecCreate(ctx, task.Status.ContainerStatus.ContainerID, config) assert.NilError(t, err, "error creating exec") diff --git a/integration/internal/swarm/states.go b/integration/internal/swarm/states.go index 8d202405b7..0800a75c84 100644 --- a/integration/internal/swarm/states.go +++ b/integration/internal/swarm/states.go @@ -49,11 +49,11 @@ func NoTasks(ctx context.Context, client client.ServiceAPIClient) func(log poll. } // RunningTasksCount verifies there are `instances` tasks running for `serviceID` -func RunningTasksCount(client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result { +func RunningTasksCount(ctx context.Context, client client.ServiceAPIClient, serviceID string, instances uint64) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { filter := filters.NewArgs() filter.Add("service", serviceID) - tasks, err := client.TaskList(context.Background(), types.TaskListOptions{ + tasks, err := client.TaskList(ctx, types.TaskListOptions{ Filters: filter, }) var running int @@ -87,7 +87,7 @@ func RunningTasksCount(client client.ServiceAPIClient, serviceID string, instanc // JobComplete is a poll function for determining that a ReplicatedJob is // completed additionally, while polling, it verifies that the job never // exceeds MaxConcurrent running tasks -func JobComplete(client client.CommonAPIClient, service swarmtypes.Service) func(log poll.LogT) poll.Result { +func JobComplete(ctx context.Context, client client.CommonAPIClient, service swarmtypes.Service) func(log poll.LogT) poll.Result { filter := filters.NewArgs(filters.Arg("service", service.ID)) var jobIteration swarmtypes.Version @@ -100,7 +100,7 @@ func JobComplete(client client.CommonAPIClient, service swarmtypes.Service) func previousResult := "" return func(log poll.LogT) poll.Result { - tasks, err := client.TaskList(context.Background(), types.TaskListOptions{ + tasks, err := client.TaskList(ctx, types.TaskListOptions{ Filters: filter, }) if err != nil { diff --git a/integration/network/delete_test.go b/integration/network/delete_test.go index c020d8ac22..0fcabb919b 100644 --- a/integration/network/delete_test.go +++ b/integration/network/delete_test.go @@ -44,20 +44,19 @@ func createAmbiguousNetworks(ctx context.Context, t *testing.T, client dclient.A // TestNetworkCreateDelete tests creation and deletion of a network. func TestNetworkCreateDelete(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() netName := "testnetwork_" + t.Name() network.CreateNoError(ctx, t, client, netName, network.WithCheckDuplicate(), ) - assert.Check(t, IsNetworkAvailable(client, netName)) + assert.Check(t, IsNetworkAvailable(ctx, client, netName)) // delete the network and make sure it is deleted err := client.NetworkRemove(ctx, netName) assert.NilError(t, err) - assert.Check(t, IsNetworkNotAvailable(client, netName)) + assert.Check(t, IsNetworkNotAvailable(ctx, client, netName)) } // TestDockerNetworkDeletePreferID tests that if a network with a name @@ -67,9 +66,10 @@ func TestDockerNetworkDeletePreferID(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.34"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME. Windows doesn't run DinD and uses networks shared between control daemon and daemon under test") - defer setupTest(t)() + + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() + testNet, idPrefixNet, fullIDNet := createAmbiguousNetworks(ctx, t, client) // Delete the network using a prefix of the first network's ID as name. diff --git a/integration/network/dns_test.go b/integration/network/dns_test.go index c4a50fe9a2..ac3b13b493 100644 --- a/integration/network/dns_test.go +++ b/integration/network/dns_test.go @@ -1,13 +1,13 @@ package network // import "github.com/docker/docker/integration/network" import ( - "context" "testing" "time" "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/integration/internal/network" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/poll" "gotest.tools/v3/skip" @@ -17,13 +17,13 @@ func TestDaemonDNSFallback(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run") skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, testEnv.IsUserNamespace) + ctx := testutil.StartSpan(baseContext, t) d := daemon.New(t) - d.StartWithBusybox(t, "-b", "none", "--dns", "127.127.127.1", "--dns", "8.8.8.8") + d.StartWithBusybox(ctx, t, "-b", "none", "--dns", "127.127.127.1", "--dns", "8.8.8.8") defer d.Stop(t) c := d.NewClientT(t) - ctx := context.Background() network.CreateNoError(ctx, t, c, "test") defer c.NetworkRemove(ctx, "test") diff --git a/integration/network/helpers.go b/integration/network/helpers.go index fe45bb4289..f297c15aa0 100644 --- a/integration/network/helpers.go +++ b/integration/network/helpers.go @@ -9,42 +9,43 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/client" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert/cmp" "gotest.tools/v3/icmd" ) // CreateMasterDummy creates a dummy network interface -func CreateMasterDummy(t *testing.T, master string) { +func CreateMasterDummy(ctx context.Context, t *testing.T, master string) { // ip link add type dummy - icmd.RunCommand("ip", "link", "add", master, "type", "dummy").Assert(t, icmd.Success) - icmd.RunCommand("ip", "link", "set", master, "up").Assert(t, icmd.Success) + testutil.RunCommand(ctx, "ip", "link", "add", master, "type", "dummy").Assert(t, icmd.Success) + testutil.RunCommand(ctx, "ip", "link", "set", master, "up").Assert(t, icmd.Success) } // CreateVlanInterface creates a vlan network interface -func CreateVlanInterface(t *testing.T, master, slave, id string) { +func CreateVlanInterface(ctx context.Context, t *testing.T, master, slave, id string) { // ip link add link name . type vlan id - icmd.RunCommand("ip", "link", "add", "link", master, "name", slave, "type", "vlan", "id", id).Assert(t, icmd.Success) + testutil.RunCommand(ctx, "ip", "link", "add", "link", master, "name", slave, "type", "vlan", "id", id).Assert(t, icmd.Success) // ip link set up - icmd.RunCommand("ip", "link", "set", slave, "up").Assert(t, icmd.Success) + testutil.RunCommand(ctx, "ip", "link", "set", slave, "up").Assert(t, icmd.Success) } // DeleteInterface deletes a network interface -func DeleteInterface(t *testing.T, ifName string) { - icmd.RunCommand("ip", "link", "delete", ifName).Assert(t, icmd.Success) - icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(t, icmd.Success) - icmd.RunCommand("iptables", "--flush").Assert(t, icmd.Success) +func DeleteInterface(ctx context.Context, t *testing.T, ifName string) { + testutil.RunCommand(ctx, "ip", "link", "delete", ifName).Assert(t, icmd.Success) + testutil.RunCommand(ctx, "iptables", "-t", "nat", "--flush").Assert(t, icmd.Success) + testutil.RunCommand(ctx, "iptables", "--flush").Assert(t, icmd.Success) } // LinkExists verifies that a link exists -func LinkExists(t *testing.T, master string) { +func LinkExists(ctx context.Context, t *testing.T, master string) { // verify the specified link exists, ip link show - icmd.RunCommand("ip", "link", "show", master).Assert(t, icmd.Success) + testutil.RunCommand(ctx, "ip", "link", "show", master).Assert(t, icmd.Success) } // IsNetworkAvailable provides a comparison to check if a docker network is available -func IsNetworkAvailable(c client.NetworkAPIClient, name string) cmp.Comparison { +func IsNetworkAvailable(ctx context.Context, c client.NetworkAPIClient, name string) cmp.Comparison { return func() cmp.Result { - networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) + networks, err := c.NetworkList(ctx, types.NetworkListOptions{}) if err != nil { return cmp.ResultFromError(err) } @@ -58,9 +59,9 @@ func IsNetworkAvailable(c client.NetworkAPIClient, name string) cmp.Comparison { } // IsNetworkNotAvailable provides a comparison to check if a docker network is not available -func IsNetworkNotAvailable(c client.NetworkAPIClient, name string) cmp.Comparison { +func IsNetworkNotAvailable(ctx context.Context, c client.NetworkAPIClient, name string) cmp.Comparison { return func() cmp.Result { - networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) + networks, err := c.NetworkList(ctx, types.NetworkListOptions{}) if err != nil { return cmp.ResultFromError(err) } diff --git a/integration/network/helpers_windows.go b/integration/network/helpers_windows.go index 35121fb200..76182ab099 100644 --- a/integration/network/helpers_windows.go +++ b/integration/network/helpers_windows.go @@ -10,9 +10,9 @@ import ( ) // IsNetworkAvailable provides a comparison to check if a docker network is available -func IsNetworkAvailable(c client.NetworkAPIClient, name string) cmp.Comparison { +func IsNetworkAvailable(ctx context.Context, c client.NetworkAPIClient, name string) cmp.Comparison { return func() cmp.Result { - networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) + networks, err := c.NetworkList(ctx, types.NetworkListOptions{}) if err != nil { return cmp.ResultFromError(err) } @@ -26,9 +26,9 @@ func IsNetworkAvailable(c client.NetworkAPIClient, name string) cmp.Comparison { } // IsNetworkNotAvailable provides a comparison to check if a docker network is not available -func IsNetworkNotAvailable(c client.NetworkAPIClient, name string) cmp.Comparison { +func IsNetworkNotAvailable(ctx context.Context, c client.NetworkAPIClient, name string) cmp.Comparison { return func() cmp.Result { - networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) + networks, err := c.NetworkList(ctx, types.NetworkListOptions{}) if err != nil { return cmp.ResultFromError(err) } diff --git a/integration/network/inspect_test.go b/integration/network/inspect_test.go index a5db4265d8..136eec508f 100644 --- a/integration/network/inspect_test.go +++ b/integration/network/inspect_test.go @@ -1,12 +1,12 @@ package network // import "github.com/docker/docker/integration/network" import ( - "context" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/network" "github.com/docker/docker/integration/internal/swarm" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" "gotest.tools/v3/poll" "gotest.tools/v3/skip" @@ -15,14 +15,15 @@ import ( func TestInspectNetwork(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() networkName := "Overlay" + t.Name() - overlayID := network.CreateNoError(context.Background(), t, c, networkName, + overlayID := network.CreateNoError(ctx, t, c, networkName, network.WithDriver("overlay"), network.WithCheckDuplicate(), ) @@ -30,13 +31,13 @@ func TestInspectNetwork(t *testing.T) { var instances uint64 = 2 serviceName := "TestService" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(serviceName), swarm.ServiceWithNetwork(networkName), ) - poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll) tests := []struct { name string @@ -73,10 +74,10 @@ func TestInspectNetwork(t *testing.T) { }, }, } - ctx := context.Background() for _, tc := range tests { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) nw, err := c.NetworkInspect(ctx, tc.network, tc.opts) assert.NilError(t, err) diff --git a/integration/network/ipvlan/ipvlan_test.go b/integration/network/ipvlan/ipvlan_test.go index fea2900a18..130b60d953 100644 --- a/integration/network/ipvlan/ipvlan_test.go +++ b/integration/network/ipvlan/ipvlan_test.go @@ -14,6 +14,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/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/skip" @@ -24,36 +25,40 @@ func TestDockerNetworkIpvlanPersistance(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, !ipvlanKernelSupport(t), "Kernel doesn't support ipvlan") + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) // master dummy interface 'di' notation represent 'docker ipvlan' master := "di-dummy0" - n.CreateMasterDummy(t, master) - defer n.DeleteInterface(t, master) + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) c := d.NewClientT(t) // create a network specifying the desired sub-interface name netName := "di-persist" - net.CreateNoError(context.Background(), t, c, netName, + net.CreateNoError(ctx, t, c, netName, net.WithIPvlan("di-dummy0.70", ""), ) - assert.Check(t, n.IsNetworkAvailable(c, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, c, netName)) // Restart docker daemon to test the config has persisted to disk d.Restart(t) - assert.Check(t, n.IsNetworkAvailable(c, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, c, netName)) } func TestDockerNetworkIpvlan(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, !ipvlanKernelSupport(t), "Kernel doesn't support ipvlan") + ctx := testutil.StartSpan(baseContext, t) + for _, tc := range []struct { name string - test func(dclient.APIClient) func(*testing.T) + test func(context.Context, dclient.APIClient) func(*testing.T) }{ { name: "Subinterface", @@ -84,55 +89,58 @@ func TestDockerNetworkIpvlan(t *testing.T) { test: testIpvlanAddressing, }, } { - d := daemon.New(t) - d.StartWithBusybox(t) - c := d.NewClientT(t) - t.Run(tc.name, tc.test(c)) + t.Run(tc.name, func(t *testing.T) { + testutil.StartSpan(ctx, t) + d := daemon.New(t) + t.Cleanup(func() { d.Stop(t) }) + d.StartWithBusybox(ctx, t) + c := d.NewClientT(t) + tc.test(ctx, c) + }) - d.Stop(t) // FIXME(vdemeester) clean network } } -func testIpvlanSubinterface(client dclient.APIClient) func(*testing.T) { +func testIpvlanSubinterface(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { master := "di-dummy0" - n.CreateMasterDummy(t, master) - defer n.DeleteInterface(t, master) + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) netName := "di-subinterface" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("di-dummy0.60", ""), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) // delete the network while preserving the parent link - err := client.NetworkRemove(context.Background(), netName) + err := client.NetworkRemove(ctx, netName) assert.NilError(t, err) - assert.Check(t, n.IsNetworkNotAvailable(client, netName)) + assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) // verify the network delete did not delete the predefined link - n.LinkExists(t, "di-dummy0") + n.LinkExists(ctx, t, "di-dummy0") } } -func testIpvlanOverlapParent(client dclient.APIClient) func(*testing.T) { +func testIpvlanOverlapParent(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { // verify the same parent interface cannot be used if already in use by an existing network master := "di-dummy0" parent := master + ".30" - n.CreateMasterDummy(t, master) - defer n.DeleteInterface(t, master) - n.CreateVlanInterface(t, master, parent, "30") + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) + n.CreateVlanInterface(ctx, t, master, parent, "30") netName := "di-subinterface" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan(parent, ""), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - _, err := net.Create(context.Background(), client, netName, + _, err := net.Create(ctx, client, netName, net.WithIPvlan(parent, ""), ) // verify that the overlap returns an error @@ -140,16 +148,15 @@ func testIpvlanOverlapParent(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanL2NilParent(client dclient.APIClient) func(*testing.T) { +func testIpvlanL2NilParent(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { // ipvlan l2 mode - dummy parent interface is provisioned dynamically netName := "di-nil-parent" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", ""), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) @@ -158,16 +165,15 @@ func testIpvlanL2NilParent(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanL2InternalMode(client dclient.APIClient) func(*testing.T) { +func testIpvlanL2InternalMode(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { netName := "di-internal" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", ""), net.WithInternal(), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) @@ -179,17 +185,16 @@ func testIpvlanL2InternalMode(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanL3NilParent(client dclient.APIClient) func(*testing.T) { +func testIpvlanL3NilParent(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { netName := "di-nil-parent-l3" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", "l3"), net.WithIPAM("172.28.230.0/24", ""), net.WithIPAM("172.28.220.0/24", ""), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName), container.WithIPv4(netName, "172.28.220.10"), @@ -204,18 +209,17 @@ func testIpvlanL3NilParent(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanL3InternalMode(client dclient.APIClient) func(*testing.T) { +func testIpvlanL3InternalMode(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { netName := "di-internal-l3" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", "l3"), net.WithInternal(), net.WithIPAM("172.28.230.0/24", ""), net.WithIPAM("172.28.220.0/24", ""), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName), container.WithIPv4(netName, "172.28.220.10"), @@ -233,10 +237,10 @@ func testIpvlanL3InternalMode(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanL2MultiSubnet(client dclient.APIClient) func(*testing.T) { +func testIpvlanL2MultiSubnet(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { netName := "dualstackl2" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", ""), net.WithIPv6(), net.WithIPAM("172.28.200.0/24", ""), @@ -244,10 +248,9 @@ func testIpvlanL2MultiSubnet(client dclient.APIClient) func(*testing.T) { net.WithIPAM("2001:db8:abc8::/64", ""), net.WithIPAM("2001:db8:abc6::/64", "2001:db8:abc6::254"), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName), container.WithIPv4(netName, "172.28.200.20"), @@ -300,10 +303,10 @@ func testIpvlanL2MultiSubnet(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanL3MultiSubnet(client dclient.APIClient) func(*testing.T) { +func testIpvlanL3MultiSubnet(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { netName := "dualstackl3" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithIPvlan("", "l3"), net.WithIPv6(), net.WithIPAM("172.28.10.0/24", ""), @@ -311,10 +314,9 @@ func testIpvlanL3MultiSubnet(client dclient.APIClient) func(*testing.T) { net.WithIPAM("2001:db8:abc9::/64", ""), net.WithIPAM("2001:db8:abc7::/64", "2001:db8:abc7::254"), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName), container.WithIPv4(netName, "172.28.10.20"), @@ -367,20 +369,19 @@ func testIpvlanL3MultiSubnet(client dclient.APIClient) func(*testing.T) { } } -func testIpvlanAddressing(client dclient.APIClient) func(*testing.T) { +func testIpvlanAddressing(ctx context.Context, client dclient.APIClient) func(*testing.T) { return func(t *testing.T) { // Verify ipvlan l2 mode sets the proper default gateway routes via netlink // for either an explicitly set route by the user or inferred via default IPAM netNameL2 := "dualstackl2" - net.CreateNoError(context.Background(), t, client, netNameL2, + net.CreateNoError(ctx, t, client, netNameL2, net.WithIPvlan("", "l2"), net.WithIPv6(), net.WithIPAM("172.28.140.0/24", "172.28.140.254"), net.WithIPAM("2001:db8:abcb::/64", ""), ) - assert.Check(t, n.IsNetworkAvailable(client, netNameL2)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL2)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netNameL2), ) @@ -395,13 +396,13 @@ func testIpvlanAddressing(client dclient.APIClient) func(*testing.T) { // Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops netNameL3 := "dualstackl3" - net.CreateNoError(context.Background(), t, client, netNameL3, + net.CreateNoError(ctx, t, client, netNameL3, net.WithIPvlan("", "l3"), net.WithIPv6(), net.WithIPAM("172.28.160.0/24", "172.28.160.254"), net.WithIPAM("2001:db8:abcd::/64", "2001:db8:abcd::254"), ) - assert.Check(t, n.IsNetworkAvailable(client, netNameL3)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL3)) id2 := container.Run(ctx, t, client, container.WithNetworkMode(netNameL3), diff --git a/integration/network/ipvlan/main_test.go b/integration/network/ipvlan/main_test.go index d4c7619e0f..8255ac1730 100644 --- a/integration/network/ipvlan/main_test.go +++ b/integration/network/ipvlan/main_test.go @@ -3,28 +3,48 @@ package ipvlan // import "github.com/docker/docker/integration/network/ipvlan" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/network/ipvlan/TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() returned non-zero exit code") + } + span.End() + shutdown(ctx) + os.Exit(code) } diff --git a/integration/network/macvlan/macvlan_test.go b/integration/network/macvlan/macvlan_test.go index 140411290a..c41373c5ca 100644 --- a/integration/network/macvlan/macvlan_test.go +++ b/integration/network/macvlan/macvlan_test.go @@ -11,6 +11,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/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/skip" @@ -21,32 +22,36 @@ func TestDockerNetworkMacvlanPersistance(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) defer d.Stop(t) master := "dm-dummy0" - n.CreateMasterDummy(t, master) - defer n.DeleteInterface(t, master) + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) c := d.NewClientT(t) netName := "dm-persist" - net.CreateNoError(context.Background(), t, c, netName, + net.CreateNoError(ctx, t, c, netName, net.WithMacvlan("dm-dummy0.60"), ) - assert.Check(t, n.IsNetworkAvailable(c, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, c, netName)) d.Restart(t) - assert.Check(t, n.IsNetworkAvailable(c, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, c, netName)) } func TestDockerNetworkMacvlan(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + for _, tc := range []struct { name string - test func(client.APIClient) func(*testing.T) + test func(context.Context, client.APIClient) func(*testing.T) }{ { name: "Subinterface", @@ -68,81 +73,85 @@ func TestDockerNetworkMacvlan(t *testing.T) { test: testMacvlanAddressing, }, } { - d := daemon.New(t) - d.StartWithBusybox(t) - c := d.NewClientT(t) + tc := tc + t.Run(tc.name, func(t *testing.T) { + testutil.StartSpan(ctx, t) - t.Run(tc.name, tc.test(c)) + d := daemon.New(t) + t.Cleanup(func() { d.Stop(t) }) + d.StartWithBusybox(ctx, t) + c := d.NewClientT(t) + + tc.test(ctx, c) + }) - d.Stop(t) // FIXME(vdemeester) clean network } } -func testMacvlanOverlapParent(client client.APIClient) func(*testing.T) { +func testMacvlanOverlapParent(ctx context.Context, client client.APIClient) func(*testing.T) { return func(t *testing.T) { // verify the same parent interface cannot be used if already in use by an existing network master := "dm-dummy0" - n.CreateMasterDummy(t, master) - defer n.DeleteInterface(t, master) + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) netName := "dm-subinterface" parentName := "dm-dummy0.40" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithMacvlan(parentName), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - _, err := net.Create(context.Background(), client, "dm-parent-net-overlap", + _, err := net.Create(ctx, client, "dm-parent-net-overlap", net.WithMacvlan(parentName), ) assert.Check(t, err != nil) // delete the network while preserving the parent link - err = client.NetworkRemove(context.Background(), netName) + err = client.NetworkRemove(ctx, netName) assert.NilError(t, err) - assert.Check(t, n.IsNetworkNotAvailable(client, netName)) + assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) // verify the network delete did not delete the predefined link - n.LinkExists(t, master) + n.LinkExists(ctx, t, master) } } -func testMacvlanSubinterface(client client.APIClient) func(*testing.T) { +func testMacvlanSubinterface(ctx context.Context, client client.APIClient) func(*testing.T) { return func(t *testing.T) { // verify the same parent interface cannot be used if already in use by an existing network master := "dm-dummy0" parentName := "dm-dummy0.20" - n.CreateMasterDummy(t, master) - defer n.DeleteInterface(t, master) - n.CreateVlanInterface(t, master, parentName, "20") + n.CreateMasterDummy(ctx, t, master) + defer n.DeleteInterface(ctx, t, master) + n.CreateVlanInterface(ctx, t, master, parentName, "20") netName := "dm-subinterface" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithMacvlan(parentName), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) // delete the network while preserving the parent link - err := client.NetworkRemove(context.Background(), netName) + err := client.NetworkRemove(ctx, netName) assert.NilError(t, err) - assert.Check(t, n.IsNetworkNotAvailable(client, netName)) + assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName)) // verify the network delete did not delete the predefined link - n.LinkExists(t, parentName) + n.LinkExists(ctx, t, parentName) } } -func testMacvlanNilParent(client client.APIClient) func(*testing.T) { +func testMacvlanNilParent(ctx context.Context, client client.APIClient) func(*testing.T) { return func(t *testing.T) { // macvlan bridge mode - dummy parent interface is provisioned dynamically netName := "dm-nil-parent" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithMacvlan(""), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) @@ -151,17 +160,16 @@ func testMacvlanNilParent(client client.APIClient) func(*testing.T) { } } -func testMacvlanInternalMode(client client.APIClient) func(*testing.T) { +func testMacvlanInternalMode(ctx context.Context, client client.APIClient) func(*testing.T) { return func(t *testing.T) { // macvlan bridge mode - dummy parent interface is provisioned dynamically netName := "dm-internal" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithMacvlan(""), net.WithInternal(), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName)) @@ -173,10 +181,10 @@ func testMacvlanInternalMode(client client.APIClient) func(*testing.T) { } } -func testMacvlanMultiSubnet(client client.APIClient) func(*testing.T) { +func testMacvlanMultiSubnet(ctx context.Context, client client.APIClient) func(*testing.T) { return func(t *testing.T) { netName := "dualstackbridge" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithMacvlan(""), net.WithIPv6(), net.WithIPAM("172.28.100.0/24", ""), @@ -185,10 +193,9 @@ func testMacvlanMultiSubnet(client client.APIClient) func(*testing.T) { net.WithIPAM("2001:db8:abc4::/64", "2001:db8:abc4::254"), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) // start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64 - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode("dualstackbridge"), container.WithIPv4("dualstackbridge", "172.28.100.20"), @@ -241,20 +248,19 @@ func testMacvlanMultiSubnet(client client.APIClient) func(*testing.T) { } } -func testMacvlanAddressing(client client.APIClient) func(*testing.T) { +func testMacvlanAddressing(ctx context.Context, client client.APIClient) func(*testing.T) { return func(t *testing.T) { // Ensure the default gateways, next-hops and default dev devices are properly set netName := "dualstackbridge" - net.CreateNoError(context.Background(), t, client, netName, + net.CreateNoError(ctx, t, client, netName, net.WithMacvlan(""), net.WithIPv6(), net.WithOption("macvlan_mode", "bridge"), net.WithIPAM("172.28.130.0/24", ""), net.WithIPAM("2001:db8:abca::/64", "2001:db8:abca::254"), ) - assert.Check(t, n.IsNetworkAvailable(client, netName)) + assert.Check(t, n.IsNetworkAvailable(ctx, client, netName)) - ctx := context.Background() id1 := container.Run(ctx, t, client, container.WithNetworkMode("dualstackbridge"), ) diff --git a/integration/network/macvlan/main_test.go b/integration/network/macvlan/main_test.go index d9f90b8ebe..f26f89e1c8 100644 --- a/integration/network/macvlan/main_test.go +++ b/integration/network/macvlan/main_test.go @@ -3,28 +3,52 @@ package macvlan // import "github.com/docker/docker/integration/network/macvlan" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + + ctx, span := otel.Tracer("").Start(context.Background(), "integration/network/macvlan/TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() returned non-zero exit code") + } + span.SetAttributes(attribute.Int("exit", code)) + span.End() + shutdown(ctx) os.Exit(m.Run()) } diff --git a/integration/network/main_test.go b/integration/network/main_test.go index 80354dcf0e..730b8aac67 100644 --- a/integration/network/main_test.go +++ b/integration/network/main_test.go @@ -1,33 +1,56 @@ package network // import "github.com/docker/docker/integration/network" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/network.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() returned non-zero exit code") + } + span.End() + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { testEnv.Clean(ctx, t) }) + return ctx } diff --git a/integration/network/network_test.go b/integration/network/network_test.go index 010102e9e0..50ff58132e 100644 --- a/integration/network/network_test.go +++ b/integration/network/network_test.go @@ -2,7 +2,6 @@ package network // import "github.com/docker/docker/integration/network" import ( "bytes" - "context" "encoding/json" "fmt" "net/http" @@ -14,6 +13,7 @@ import ( ntypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/integration/internal/network" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" @@ -28,12 +28,13 @@ func TestRunContainerWithBridgeNone(t *testing.T) { skip.If(t, testEnv.IsUserNamespace) skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t, "-b", "none") + d.StartWithBusybox(ctx, t, "-b", "none") defer d.Stop(t) c := d.NewClientT(t) - ctx := context.Background() id1 := container.Run(ctx, t, c) defer c.ContainerRemove(ctx, id1, types.ContainerRemoveOptions{Force: true}) @@ -67,7 +68,7 @@ func TestRunContainerWithBridgeNone(t *testing.T) { // TestNetworkInvalidJSON tests that POST endpoints that expect a body return // the correct error when sending invalid JSON requests. func TestNetworkInvalidJSON(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) // POST endpoints that accept / expect a JSON body; endpoints := []string{ @@ -80,9 +81,11 @@ func TestNetworkInvalidJSON(t *testing.T) { ep := ep t.Run(ep[1:], func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) t.Run("invalid content type", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{}"), request.ContentType("text/plain")) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{}"), request.ContentType("text/plain")) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -92,7 +95,8 @@ func TestNetworkInvalidJSON(t *testing.T) { }) t.Run("invalid JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{invalid json"), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -102,7 +106,8 @@ func TestNetworkInvalidJSON(t *testing.T) { }) t.Run("extra content after JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString(`{} trailing content`), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString(`{} trailing content`), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -112,10 +117,11 @@ func TestNetworkInvalidJSON(t *testing.T) { }) t.Run("empty body", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) // empty body should not produce an 500 internal server error, or // any 5XX error (this is assuming the request does not produce // an internal server error for another reason, but it shouldn't) - res, _, err := request.Post(ep, request.RawString(``), request.JSON) + res, _, err := request.Post(ctx, ep, request.RawString(``), request.JSON) assert.NilError(t, err) assert.Check(t, res.StatusCode < http.StatusInternalServerError) }) @@ -126,7 +132,7 @@ func TestNetworkInvalidJSON(t *testing.T) { // TestNetworkList verifies that /networks returns a list of networks either // with, or without a trailing slash (/networks/). Regression test for https://github.com/moby/moby/issues/24595 func TestNetworkList(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) endpoints := []string{ "/networks", @@ -136,9 +142,10 @@ func TestNetworkList(t *testing.T) { for _, ep := range endpoints { ep := ep t.Run(ep, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) t.Parallel() - res, body, err := request.Get(ep, request.JSON) + res, body, err := request.Get(ctx, ep, request.JSON) assert.NilError(t, err) assert.Equal(t, res.StatusCode, http.StatusOK) @@ -156,12 +163,13 @@ func TestHostIPv4BridgeLabel(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) d.Start(t) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() ipv4SNATAddr := "172.0.0.172" // Create a bridge network with --opt com.docker.network.host_ipv4=172.0.0.172 @@ -175,13 +183,14 @@ func TestHostIPv4BridgeLabel(t *testing.T) { assert.NilError(t, err) assert.Assert(t, len(out.IPAM.Config) > 0) // Make sure the SNAT rule exists - icmd.RunCommand("iptables", "-t", "nat", "-C", "POSTROUTING", "-s", out.IPAM.Config[0].Subnet, "!", "-o", bridgeName, "-j", "SNAT", "--to-source", ipv4SNATAddr).Assert(t, icmd.Success) + testutil.RunCommand(ctx, "iptables", "-t", "nat", "-C", "POSTROUTING", "-s", out.IPAM.Config[0].Subnet, "!", "-o", bridgeName, "-j", "SNAT", "--to-source", ipv4SNATAddr).Assert(t, icmd.Success) } func TestDefaultNetworkOpts(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) tests := []struct { name string @@ -210,12 +219,12 @@ func TestDefaultNetworkOpts(t *testing.T) { for _, tc := range tests { tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) d := daemon.New(t) - d.StartWithBusybox(t, tc.args...) + d.StartWithBusybox(ctx, t, tc.args...) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() if tc.configFrom { // Create a new network config diff --git a/integration/network/service_test.go b/integration/network/service_test.go index 9803b718d6..5231ecf16e 100644 --- a/integration/network/service_test.go +++ b/integration/network/service_test.go @@ -11,6 +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/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/icmd" @@ -19,11 +20,11 @@ import ( ) // delInterface removes given network interface -func delInterface(t *testing.T, ifName string) { +func delInterface(ctx context.Context, t *testing.T, ifName string) { t.Helper() - icmd.RunCommand("ip", "link", "delete", ifName).Assert(t, icmd.Success) - icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(t, icmd.Success) - icmd.RunCommand("iptables", "--flush").Assert(t, icmd.Success) + testutil.RunCommand(ctx, "ip", "link", "delete", ifName).Assert(t, icmd.Success) + testutil.RunCommand(ctx, "iptables", "-t", "nat", "--flush").Assert(t, icmd.Success) + testutil.RunCommand(ctx, "iptables", "--flush").Assert(t, icmd.Success) } func TestDaemonRestartWithLiveRestore(t *testing.T) { @@ -31,6 +32,8 @@ func TestDaemonRestartWithLiveRestore(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature") skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) defer d.Stop(t) d.Start(t) @@ -39,7 +42,7 @@ func TestDaemonRestartWithLiveRestore(t *testing.T) { defer c.Close() // Verify bridge network's subnet - out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{}) + out, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{}) assert.NilError(t, err) subnet := out.IPAM.Config[0].Subnet @@ -49,7 +52,7 @@ func TestDaemonRestartWithLiveRestore(t *testing.T) { "--default-address-pool", "base=175.33.0.0/16,size=24", ) - out1, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{}) + out1, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{}) assert.NilError(t, err) // Make sure docker0 doesn't get override with new IP in live restore case assert.Equal(t, out1.IPAM.Config[0].Subnet, subnet) @@ -61,8 +64,10 @@ func TestDaemonDefaultNetworkPools(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature") skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + defaultNetworkBridge := "docker0" - delInterface(t, defaultNetworkBridge) + delInterface(ctx, t, defaultNetworkBridge) d := daemon.New(t) defer d.Stop(t) d.Start(t, @@ -74,28 +79,28 @@ func TestDaemonDefaultNetworkPools(t *testing.T) { defer c.Close() // Verify bridge network's subnet - out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{}) + out, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{}) assert.NilError(t, err) assert.Equal(t, out.IPAM.Config[0].Subnet, "175.30.0.0/16") // Create a bridge network and verify its subnet is the second default pool name := "elango" + t.Name() - network.CreateNoError(context.Background(), t, c, name, + network.CreateNoError(ctx, t, c, name, network.WithDriver("bridge"), ) - out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out, err = c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.0.0/24") // Create a bridge network and verify its subnet is the third default pool name = "saanvi" + t.Name() - network.CreateNoError(context.Background(), t, c, name, + network.CreateNoError(ctx, t, c, name, network.WithDriver("bridge"), ) - out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out, err = c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) assert.Equal(t, out.IPAM.Config[0].Subnet, "175.33.1.0/24") - delInterface(t, defaultNetworkBridge) + delInterface(ctx, t, defaultNetworkBridge) } func TestDaemonRestartWithExistingNetwork(t *testing.T) { @@ -103,6 +108,8 @@ func TestDaemonRestartWithExistingNetwork(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature") skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + ctx := testutil.StartSpan(baseContext, t) + defaultNetworkBridge := "docker0" d := daemon.New(t) d.Start(t) @@ -112,12 +119,12 @@ func TestDaemonRestartWithExistingNetwork(t *testing.T) { // Create a bridge network name := "elango" + t.Name() - network.CreateNoError(context.Background(), t, c, name, + network.CreateNoError(ctx, t, c, name, network.WithDriver("bridge"), ) // Verify bridge network's subnet - out, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) networkip := out.IPAM.Config[0].Subnet @@ -126,10 +133,10 @@ func TestDaemonRestartWithExistingNetwork(t *testing.T) { "--default-address-pool", "base=175.30.0.0/16,size=16", "--default-address-pool", "base=175.33.0.0/16,size=24") - out1, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out1, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) assert.Equal(t, out1.IPAM.Config[0].Subnet, networkip) - delInterface(t, defaultNetworkBridge) + delInterface(ctx, t, defaultNetworkBridge) } func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) { @@ -137,6 +144,9 @@ func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature") skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + + ctx := testutil.StartSpan(baseContext, t) + defaultNetworkBridge := "docker0" d := daemon.New(t) d.Start(t) @@ -146,21 +156,21 @@ func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) { // Create a bridge network name := "elango" + t.Name() - network.CreateNoError(context.Background(), t, c, name, + network.CreateNoError(ctx, t, c, name, network.WithDriver("bridge"), ) // Verify bridge network's subnet - out, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) networkip := out.IPAM.Config[0].Subnet // Create a bridge network name = "sthira" + t.Name() - network.CreateNoError(context.Background(), t, c, name, + network.CreateNoError(ctx, t, c, name, network.WithDriver("bridge"), ) - out, err = c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out, err = c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) networkip2 := out.IPAM.Config[0].Subnet @@ -172,15 +182,15 @@ func TestDaemonRestartWithExistingNetworkWithDefaultPoolRange(t *testing.T) { // Create a bridge network name = "saanvi" + t.Name() - network.CreateNoError(context.Background(), t, c, name, + network.CreateNoError(ctx, t, c, name, network.WithDriver("bridge"), ) - out1, err := c.NetworkInspect(context.Background(), name, types.NetworkInspectOptions{}) + out1, err := c.NetworkInspect(ctx, name, types.NetworkInspectOptions{}) assert.NilError(t, err) assert.Check(t, out1.IPAM.Config[0].Subnet != networkip) assert.Check(t, out1.IPAM.Config[0].Subnet != networkip2) - delInterface(t, defaultNetworkBridge) + delInterface(ctx, t, defaultNetworkBridge) } func TestDaemonWithBipAndDefaultNetworkPool(t *testing.T) { @@ -188,6 +198,9 @@ func TestDaemonWithBipAndDefaultNetworkPool(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.38"), "skip test from new feature") skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") + + ctx := testutil.StartSpan(baseContext, t) + defaultNetworkBridge := "docker0" d := daemon.New(t) defer d.Stop(t) @@ -201,18 +214,19 @@ func TestDaemonWithBipAndDefaultNetworkPool(t *testing.T) { defer c.Close() // Verify bridge network's subnet - out, err := c.NetworkInspect(context.Background(), "bridge", types.NetworkInspectOptions{}) + out, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{}) assert.NilError(t, err) // Make sure BIP IP doesn't get override with new default address pool . assert.Equal(t, out.IPAM.Config[0].Subnet, "172.60.0.0/16") - delInterface(t, defaultNetworkBridge) + delInterface(ctx, t, defaultNetworkBridge) } func TestServiceWithPredefinedNetwork(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() @@ -221,18 +235,18 @@ func TestServiceWithPredefinedNetwork(t *testing.T) { var instances uint64 = 1 serviceName := "TestService" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(serviceName), swarm.ServiceWithNetwork(hostName), ) - poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll) - _, _, err := c.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) + _, _, err := c.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) - err = c.ServiceRemove(context.Background(), serviceID) + err = c.ServiceRemove(ctx, serviceID) assert.NilError(t, err) } @@ -243,17 +257,18 @@ func TestServiceRemoveKeepsIngressNetwork(t *testing.T) { skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode") skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - poll.WaitOn(t, swarmIngressReady(c), swarm.NetworkPoll) + poll.WaitOn(t, swarmIngressReady(ctx, c), swarm.NetworkPoll) var instances uint64 = 1 - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(t.Name()+"-service"), swarm.ServiceWithEndpoint(&swarmtypes.EndpointSpec{ @@ -267,9 +282,8 @@ func TestServiceRemoveKeepsIngressNetwork(t *testing.T) { }), ) - poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll) - ctx := context.Background() _, _, err := c.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) @@ -293,9 +307,9 @@ func TestServiceRemoveKeepsIngressNetwork(t *testing.T) { } //nolint:unused // for some reason, the "unused" linter marks this function as "unused" -func swarmIngressReady(client client.NetworkAPIClient) func(log poll.LogT) poll.Result { +func swarmIngressReady(ctx context.Context, client client.NetworkAPIClient) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { - netInfo, err := client.NetworkInspect(context.Background(), ingressNet, types.NetworkInspectOptions{ + netInfo, err := client.NetworkInspect(ctx, ingressNet, types.NetworkInspectOptions{ Verbose: true, Scope: "swarm", }) @@ -333,24 +347,24 @@ func TestServiceWithDataPathPortInit(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "DataPathPort was added in API v1.40") skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode") - defer setupTest(t)() + ctx := setupTest(t) + var datapathPort uint32 = 7777 - d := swarm.NewSwarm(t, testEnv, daemon.WithSwarmDataPathPort(datapathPort)) + d := swarm.NewSwarm(ctx, t, testEnv, daemon.WithSwarmDataPathPort(datapathPort)) c := d.NewClientT(t) - ctx := context.Background() // Create a overlay network name := "saanvisthira" + t.Name() - overlayID := network.CreateNoError(context.Background(), t, c, name, + overlayID := network.CreateNoError(ctx, t, c, name, network.WithDriver("overlay")) var instances uint64 = 1 - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(name), swarm.ServiceWithNetwork(name), ) - poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, instances), swarm.ServicePoll) info := d.Info(t) assert.Equal(t, info.Swarm.Cluster.DataPathPort, datapathPort) @@ -361,13 +375,13 @@ func TestServiceWithDataPathPortInit(t *testing.T) { err = c.NetworkRemove(ctx, overlayID) assert.NilError(t, err) c.Close() - err = d.SwarmLeave(t, true) + err = d.SwarmLeave(ctx, t, true) assert.NilError(t, err) d.Stop(t) // Clean up , set it back to original one to make sure other tests don't fail // call without datapath port option. - d = swarm.NewSwarm(t, testEnv) + d = swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) nc := d.NewClientT(t) defer nc.Close() @@ -376,13 +390,13 @@ func TestServiceWithDataPathPortInit(t *testing.T) { overlayID = network.CreateNoError(ctx, t, nc, name, network.WithDriver("overlay")) - serviceID = swarm.CreateService(t, d, + serviceID = swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(name), swarm.ServiceWithNetwork(name), ) - poll.WaitOn(t, swarm.RunningTasksCount(nc, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, nc, serviceID, instances), swarm.ServicePoll) info = d.Info(t) var defaultDataPathPort uint32 = 4789 @@ -393,21 +407,21 @@ func TestServiceWithDataPathPortInit(t *testing.T) { poll.WaitOn(t, swarm.NoTasks(ctx, nc), swarm.ServicePoll) err = nc.NetworkRemove(ctx, overlayID) assert.NilError(t, err) - err = d.SwarmLeave(t, true) + err = d.SwarmLeave(ctx, t, true) assert.NilError(t, err) } func TestServiceWithDefaultAddressPoolInit(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRootless, "rootless mode doesn't support Swarm-mode") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv, + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv, daemon.WithSwarmDefaultAddrPool([]string{"20.20.0.0/16"}), daemon.WithSwarmDefaultAddrPoolSubnetSize(24)) defer d.Stop(t) cli := d.NewClientT(t) defer cli.Close() - ctx := context.Background() // Create a overlay network name := "sthira" + t.Name() @@ -418,13 +432,13 @@ func TestServiceWithDefaultAddressPoolInit(t *testing.T) { var instances uint64 = 1 serviceName := "TestService" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(serviceName), swarm.ServiceWithNetwork(name), ) - poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, cli, serviceID, instances), swarm.ServicePoll) _, _, err := cli.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) @@ -451,6 +465,6 @@ func TestServiceWithDefaultAddressPoolInit(t *testing.T) { assert.NilError(t, err) err = cli.NetworkRemove(ctx, overlayID) assert.NilError(t, err) - err = d.SwarmLeave(t, true) + err = d.SwarmLeave(ctx, t, true) assert.NilError(t, err) } diff --git a/integration/plugin/authz/authz_plugin_test.go b/integration/plugin/authz/authz_plugin_test.go index 1eebedc24f..658e57e97c 100644 --- a/integration/plugin/authz/authz_plugin_test.go +++ b/integration/plugin/authz/authz_plugin_test.go @@ -51,9 +51,10 @@ type authorizationController struct { resUser string } -func setupTestV1(t *testing.T) func() { +func setupTestV1(t *testing.T) context.Context { + ctx := setupTest(t) + ctrl = &authorizationController{} - teardown := setupTest(t) err := os.MkdirAll("/etc/docker/plugins", 0o755) assert.NilError(t, err) @@ -62,13 +63,12 @@ func setupTestV1(t *testing.T) func() { err = os.WriteFile(fileName, []byte(server.URL), 0o644) assert.NilError(t, err) - return func() { + t.Cleanup(func() { err := os.RemoveAll("/etc/docker/plugins") assert.NilError(t, err) - - teardown() ctrl = nil - } + }) + return ctx } // check for always allowed endpoints to not inhibit test framework functions @@ -82,13 +82,13 @@ func isAllowed(reqURI string) bool { } func TestAuthZPluginAllowRequest(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) + ctrl.reqRes.Allow = true ctrl.resRes.Allow = true - d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin) + d.StartWithBusybox(ctx, t, "--authorization-plugin="+testAuthZPlugin) c := d.NewClientT(t) - ctx := context.Background() // Ensure command successful cID := container.Run(ctx, t, c) @@ -103,7 +103,7 @@ func TestAuthZPluginAllowRequest(t *testing.T) { } func TestAuthZPluginTLS(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) const ( testDaemonHTTPSAddr = "tcp://localhost:4271" cacertPath = "../../testdata/https/ca.pem" @@ -127,7 +127,7 @@ func TestAuthZPluginTLS(t *testing.T) { c, err := newTLSAPIClient(testDaemonHTTPSAddr, cacertPath, clientCertPath, clientKeyPath) assert.NilError(t, err) - _, err = c.ServerVersion(context.Background()) + _, err = c.ServerVersion(ctx) assert.NilError(t, err) assert.Equal(t, "client", ctrl.reqUser) @@ -146,7 +146,8 @@ func newTLSAPIClient(host, cacertPath, certPath, keyPath string) (client.APIClie } func TestAuthZPluginDenyRequest(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) + d.Start(t, "--authorization-plugin="+testAuthZPlugin) ctrl.reqRes.Allow = false ctrl.reqRes.Msg = unauthorizedMessage @@ -154,7 +155,7 @@ func TestAuthZPluginDenyRequest(t *testing.T) { c := d.NewClientT(t) // Ensure command is blocked - _, err := c.ServerVersion(context.Background()) + _, err := c.ServerVersion(ctx) assert.Assert(t, err != nil) assert.Equal(t, 1, ctrl.versionReqCount) assert.Equal(t, 0, ctrl.versionResCount) @@ -166,7 +167,8 @@ func TestAuthZPluginDenyRequest(t *testing.T) { // TestAuthZPluginAPIDenyResponse validates that when authorization // plugin deny the request, the status code is forbidden func TestAuthZPluginAPIDenyResponse(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) + d.Start(t, "--authorization-plugin="+testAuthZPlugin) ctrl.reqRes.Allow = false ctrl.resRes.Msg = unauthorizedMessage @@ -179,6 +181,7 @@ func TestAuthZPluginAPIDenyResponse(t *testing.T) { c := httputil.NewClientConn(conn, nil) req, err := http.NewRequest(http.MethodGet, "/version", nil) assert.NilError(t, err) + req = req.WithContext(ctx) resp, err := c.Do(req) assert.NilError(t, err) @@ -186,7 +189,8 @@ func TestAuthZPluginAPIDenyResponse(t *testing.T) { } func TestAuthZPluginDenyResponse(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) + d.Start(t, "--authorization-plugin="+testAuthZPlugin) ctrl.reqRes.Allow = true ctrl.resRes.Allow = false @@ -195,7 +199,7 @@ func TestAuthZPluginDenyResponse(t *testing.T) { c := d.NewClientT(t) // Ensure command is blocked - _, err := c.ServerVersion(context.Background()) + _, err := c.ServerVersion(ctx) assert.Assert(t, err != nil) assert.Equal(t, 1, ctrl.versionReqCount) assert.Equal(t, 1, ctrl.versionResCount) @@ -210,16 +214,15 @@ func TestAuthZPluginAllowEventStream(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTestV1(t)() + ctx := setupTestV1(t) ctrl.reqRes.Allow = true ctrl.resRes.Allow = true - d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin) + d.StartWithBusybox(ctx, t, "--authorization-plugin="+testAuthZPlugin) c := d.NewClientT(t) - ctx := context.Background() - startTime := strconv.FormatInt(systemTime(t, c, testEnv).Unix(), 10) - events, errs, cancel := systemEventsSince(c, startTime) + startTime := strconv.FormatInt(systemTime(ctx, t, c, testEnv).Unix(), 10) + events, errs, cancel := systemEventsSince(ctx, c, startTime) defer cancel() // Create a container and wait for the creation events @@ -257,12 +260,11 @@ func TestAuthZPluginAllowEventStream(t *testing.T) { assertURIRecorded(t, ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", cID)) } -func systemTime(t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time { +func systemTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time { if testEnv.IsLocalDaemon() { return time.Now() } - ctx := context.Background() info, err := client.Info(ctx) assert.NilError(t, err) @@ -271,18 +273,18 @@ func systemTime(t *testing.T, client client.APIClient, testEnv *environment.Exec return dt } -func systemEventsSince(client client.APIClient, since string) (<-chan eventtypes.Message, <-chan error, func()) { +func systemEventsSince(ctx context.Context, client client.APIClient, since string) (<-chan eventtypes.Message, <-chan error, func()) { eventOptions := types.EventsOptions{ Since: since, } - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(ctx) events, errs := client.Events(ctx, eventOptions) return events, errs, cancel } func TestAuthZPluginErrorResponse(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) d.Start(t, "--authorization-plugin="+testAuthZPlugin) ctrl.reqRes.Allow = true ctrl.resRes.Err = errorMessage @@ -290,26 +292,26 @@ func TestAuthZPluginErrorResponse(t *testing.T) { c := d.NewClientT(t) // Ensure command is blocked - _, err := c.ServerVersion(context.Background()) + _, err := c.ServerVersion(ctx) assert.Assert(t, err != nil) assert.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiResponse, errorMessage), err.Error()) } func TestAuthZPluginErrorRequest(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) d.Start(t, "--authorization-plugin="+testAuthZPlugin) ctrl.reqRes.Err = errorMessage c := d.NewClientT(t) // Ensure command is blocked - _, err := c.ServerVersion(context.Background()) + _, err := c.ServerVersion(ctx) assert.Assert(t, err != nil) assert.Equal(t, fmt.Sprintf("Error response from daemon: plugin %s failed with error: %s: %s", testAuthZPlugin, authorization.AuthZApiRequest, errorMessage), err.Error()) } func TestAuthZPluginEnsureNoDuplicatePluginRegistration(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) d.Start(t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin) ctrl.reqRes.Allow = true @@ -317,7 +319,7 @@ func TestAuthZPluginEnsureNoDuplicatePluginRegistration(t *testing.T) { c := d.NewClientT(t) - _, err := c.ServerVersion(context.Background()) + _, err := c.ServerVersion(ctx) assert.NilError(t, err) // assert plugin is only called once.. @@ -326,13 +328,13 @@ func TestAuthZPluginEnsureNoDuplicatePluginRegistration(t *testing.T) { } func TestAuthZPluginEnsureLoadImportWorking(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) + ctrl.reqRes.Allow = true ctrl.resRes.Allow = true - d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin) + d.StartWithBusybox(ctx, t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin) c := d.NewClientT(t) - ctx := context.Background() tmp, err := os.MkdirTemp("", "test-authz-load-import") assert.NilError(t, err) @@ -340,16 +342,16 @@ func TestAuthZPluginEnsureLoadImportWorking(t *testing.T) { savedImagePath := filepath.Join(tmp, "save.tar") - err = imageSave(c, savedImagePath, "busybox") + err = imageSave(ctx, c, savedImagePath, "busybox") assert.NilError(t, err) - err = imageLoad(c, savedImagePath) + err = imageLoad(ctx, c, savedImagePath) assert.NilError(t, err) exportedImagePath := filepath.Join(tmp, "export.tar") cID := container.Run(ctx, t, c) - responseReader, err := c.ContainerExport(context.Background(), cID) + responseReader, err := c.ContainerExport(ctx, cID) assert.NilError(t, err) defer responseReader.Close() file, err := os.Create(exportedImagePath) @@ -358,15 +360,15 @@ func TestAuthZPluginEnsureLoadImportWorking(t *testing.T) { _, err = io.Copy(file, responseReader) assert.NilError(t, err) - err = imageImport(c, exportedImagePath) + err = imageImport(ctx, c, exportedImagePath) assert.NilError(t, err) } func TestAuthzPluginEnsureContainerCopyToFrom(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) ctrl.reqRes.Allow = true ctrl.resRes.Allow = true - d.StartWithBusybox(t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin) + d.StartWithBusybox(ctx, t, "--authorization-plugin="+testAuthZPlugin, "--authorization-plugin="+testAuthZPlugin) dir, err := os.MkdirTemp("", t.Name()) assert.NilError(t, err) @@ -385,7 +387,6 @@ func TestAuthzPluginEnsureContainerCopyToFrom(t *testing.T) { } c := d.NewClientT(t) - ctx := context.Background() cID := container.Run(ctx, t, c) defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) @@ -411,8 +412,7 @@ func TestAuthzPluginEnsureContainerCopyToFrom(t *testing.T) { assert.NilError(t, err) } -func imageSave(client client.APIClient, path, image string) error { - ctx := context.Background() +func imageSave(ctx context.Context, client client.APIClient, path, image string) error { responseReader, err := client.ImageSave(ctx, []string{image}) if err != nil { return err @@ -427,14 +427,13 @@ func imageSave(client client.APIClient, path, image string) error { return err } -func imageLoad(client client.APIClient, path string) error { +func imageLoad(ctx context.Context, client client.APIClient, path string) error { file, err := os.Open(path) if err != nil { return err } defer file.Close() quiet := true - ctx := context.Background() response, err := client.ImageLoad(ctx, file, quiet) if err != nil { return err @@ -443,7 +442,7 @@ func imageLoad(client client.APIClient, path string) error { return nil } -func imageImport(client client.APIClient, path string) error { +func imageImport(ctx context.Context, client client.APIClient, path string) error { file, err := os.Open(path) if err != nil { return err @@ -455,7 +454,6 @@ func imageImport(client client.APIClient, path string) error { Source: file, SourceName: "-", } - ctx := context.Background() responseReader, err := client.ImageImport(ctx, source, ref, options) if err != nil { return err @@ -465,10 +463,11 @@ func imageImport(client client.APIClient, path string) error { } func TestAuthZPluginHeader(t *testing.T) { - defer setupTestV1(t)() + ctx := setupTestV1(t) + ctrl.reqRes.Allow = true ctrl.resRes.Allow = true - d.StartWithBusybox(t, "--debug", "--authorization-plugin="+testAuthZPlugin) + d.StartWithBusybox(ctx, t, "--debug", "--authorization-plugin="+testAuthZPlugin) daemonURL, err := url.Parse(d.Sock()) assert.NilError(t, err) @@ -478,6 +477,7 @@ func TestAuthZPluginHeader(t *testing.T) { client := httputil.NewClientConn(conn, nil) req, err := http.NewRequest(http.MethodGet, "/version", nil) assert.NilError(t, err) + req = req.WithContext(ctx) resp, err := client.Do(req) assert.NilError(t, err) assert.Equal(t, "application/json", resp.Header["Content-Type"][0]) diff --git a/integration/plugin/authz/authz_plugin_v2_test.go b/integration/plugin/authz/authz_plugin_v2_test.go index 9ba5c2b1f1..5c1a9c1233 100644 --- a/integration/plugin/authz/authz_plugin_v2_test.go +++ b/integration/plugin/authz/authz_plugin_v2_test.go @@ -27,31 +27,28 @@ var ( nonexistentAuthzPluginName = "riyaz/nonexistent-authz-plugin" ) -func setupTestV2(t *testing.T) func() { +func setupTestV2(t *testing.T) context.Context { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, !requirement.HasHubConnectivity(t)) - teardown := setupTest(t) - + ctx := setupTest(t) d.Start(t) - - return teardown + return ctx } func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) { skip.If(t, testEnv.NotAmd64) - defer setupTestV2(t)() + ctx := setupTestV2(t) c := d.NewClientT(t) - ctx := context.Background() // Install authz plugin - err := pluginInstallGrantAllPermissions(c, authzPluginNameWithTag) + err := pluginInstallGrantAllPermissions(ctx, c, authzPluginNameWithTag) assert.NilError(t, err) // start the daemon with the plugin and load busybox, --net=none build fails otherwise // because it needs to pull busybox d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag) - d.LoadBusybox(t) + d.LoadBusybox(ctx, t) // Ensure docker run command and accompanying docker ps are successful cID := container.Run(ctx, t, c) @@ -62,73 +59,73 @@ func TestAuthZPluginV2AllowNonVolumeRequest(t *testing.T) { func TestAuthZPluginV2Disable(t *testing.T) { skip.If(t, testEnv.NotAmd64) - defer setupTestV2(t)() + ctx := setupTestV2(t) c := d.NewClientT(t) // Install authz plugin - err := pluginInstallGrantAllPermissions(c, authzPluginNameWithTag) + err := pluginInstallGrantAllPermissions(ctx, c, authzPluginNameWithTag) assert.NilError(t, err) d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag) - d.LoadBusybox(t) + d.LoadBusybox(ctx, t) - _, err = c.VolumeCreate(context.Background(), volume.CreateOptions{Driver: "local"}) + _, err = c.VolumeCreate(ctx, volume.CreateOptions{Driver: "local"}) assert.Assert(t, err != nil) assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag))) // disable the plugin - err = c.PluginDisable(context.Background(), authzPluginNameWithTag, types.PluginDisableOptions{}) + err = c.PluginDisable(ctx, authzPluginNameWithTag, types.PluginDisableOptions{}) assert.NilError(t, err) // now test to see if the docker api works. - _, err = c.VolumeCreate(context.Background(), volume.CreateOptions{Driver: "local"}) + _, err = c.VolumeCreate(ctx, volume.CreateOptions{Driver: "local"}) assert.NilError(t, err) } func TestAuthZPluginV2RejectVolumeRequests(t *testing.T) { skip.If(t, testEnv.NotAmd64) - defer setupTestV2(t)() + ctx := setupTestV2(t) c := d.NewClientT(t) // Install authz plugin - err := pluginInstallGrantAllPermissions(c, authzPluginNameWithTag) + err := pluginInstallGrantAllPermissions(ctx, c, authzPluginNameWithTag) assert.NilError(t, err) // restart the daemon with the plugin d.Restart(t, "--authorization-plugin="+authzPluginNameWithTag) - _, err = c.VolumeCreate(context.Background(), volume.CreateOptions{Driver: "local"}) + _, err = c.VolumeCreate(ctx, volume.CreateOptions{Driver: "local"}) assert.Assert(t, err != nil) assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag))) - _, err = c.VolumeList(context.Background(), volume.ListOptions{}) + _, err = c.VolumeList(ctx, volume.ListOptions{}) assert.Assert(t, err != nil) assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag))) // The plugin will block the command before it can determine the volume does not exist - err = c.VolumeRemove(context.Background(), "test", false) + err = c.VolumeRemove(ctx, "test", false) assert.Assert(t, err != nil) assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag))) - _, err = c.VolumeInspect(context.Background(), "test") + _, err = c.VolumeInspect(ctx, "test") assert.Assert(t, err != nil) assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag))) - _, err = c.VolumesPrune(context.Background(), filters.Args{}) + _, err = c.VolumesPrune(ctx, filters.Args{}) assert.Assert(t, err != nil) assert.Assert(t, strings.Contains(err.Error(), fmt.Sprintf("Error response from daemon: plugin %s failed with error:", authzPluginNameWithTag))) } func TestAuthZPluginV2BadManifestFailsDaemonStart(t *testing.T) { skip.If(t, testEnv.NotAmd64) - defer setupTestV2(t)() + ctx := setupTestV2(t) c := d.NewClientT(t) // Install authz plugin with bad manifest - err := pluginInstallGrantAllPermissions(c, authzPluginBadManifestName) + err := pluginInstallGrantAllPermissions(ctx, c, authzPluginBadManifestName) assert.NilError(t, err) // start the daemon with the plugin, it will error @@ -140,7 +137,7 @@ func TestAuthZPluginV2BadManifestFailsDaemonStart(t *testing.T) { } func TestAuthZPluginV2NonexistentFailsDaemonStart(t *testing.T) { - defer setupTestV2(t)() + _ = setupTestV2(t) // start the daemon with a non-existent authz plugin, it will error err := d.RestartWithError("--authorization-plugin=" + nonexistentAuthzPluginName) @@ -150,8 +147,7 @@ func TestAuthZPluginV2NonexistentFailsDaemonStart(t *testing.T) { d.Start(t) } -func pluginInstallGrantAllPermissions(client client.APIClient, name string) error { - ctx := context.Background() +func pluginInstallGrantAllPermissions(ctx context.Context, client client.APIClient, name string) error { options := types.PluginInstallOptions{ RemoteRef: name, AcceptAllPermissions: true, diff --git a/integration/plugin/authz/main_test.go b/integration/plugin/authz/main_test.go index 9d693aa948..128b7d39bf 100644 --- a/integration/plugin/authz/main_test.go +++ b/integration/plugin/authz/main_test.go @@ -3,6 +3,7 @@ package authz // import "github.com/docker/docker/integration/plugin/authz" import ( + "context" "encoding/json" "fmt" "io" @@ -14,28 +15,43 @@ import ( "github.com/docker/docker/pkg/authorization" "github.com/docker/docker/pkg/plugins" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" "gotest.tools/v3/skip" ) var ( - testEnv *environment.Execution - d *daemon.Daemon - server *httptest.Server + testEnv *environment.Execution + d *daemon.Daemon + server *httptest.Server + baseContext context.Context ) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + + ctx, span := otel.Tracer("").Start(context.Background(), "integration/plugin/authz.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() @@ -43,28 +59,37 @@ func TestMain(m *testing.M) { exitCode := m.Run() teardownSuite() + if exitCode != 0 { + span.SetAttributes(attribute.Int("exit", exitCode)) + span.SetStatus(codes.Error, "m.Run() exited with non-zero exit code") + } + shutdown(ctx) + os.Exit(exitCode) } -func setupTest(t *testing.T) func() { +func setupTest(t *testing.T) context.Context { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRootless, "rootless mode has different view of localhost") - environment.ProtectAll(t, testEnv) + + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) d = daemon.New(t, daemon.WithExperimental()) - return func() { + t.Cleanup(func() { if d != nil { d.Stop(t) } - testEnv.Clean(t) - } + testEnv.Clean(ctx, t) + }) + return ctx } func setupSuite() { mux := http.NewServeMux() - server = httptest.NewServer(mux) + server = httptest.NewServer(otelhttp.NewHandler(mux, "")) mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { b, err := json.Marshal(plugins.Manifest{Implements: []string{authorization.AuthZApiImplements}}) diff --git a/integration/plugin/common/main_test.go b/integration/plugin/common/main_test.go index 5bcbac2a83..b2af3e69f4 100644 --- a/integration/plugin/common/main_test.go +++ b/integration/plugin/common/main_test.go @@ -1,27 +1,50 @@ package common // import "github.com/docker/docker/integration/plugin/common" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/plugin/common.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() + ec := m.Run() + if ec != 0 { + span.SetStatus(codes.Error, "m.Run() returned non-zero exit code") + } + span.SetAttributes(attribute.Int("exit", ec)) + shutdown(ctx) os.Exit(m.Run()) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { + testEnv.Clean(ctx, t) + }) + return ctx } diff --git a/integration/plugin/common/plugin_test.go b/integration/plugin/common/plugin_test.go index 5258d1487d..afb8e3cc3b 100644 --- a/integration/plugin/common/plugin_test.go +++ b/integration/plugin/common/plugin_test.go @@ -1,7 +1,6 @@ package common // import "github.com/docker/docker/integration/plugin/common" import ( - "context" "encoding/base64" "encoding/json" "fmt" @@ -20,6 +19,7 @@ import ( registrytypes "github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/system" "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fixtures/plugin" "github.com/docker/docker/testutil/registry" @@ -33,7 +33,7 @@ import ( // TestPluginInvalidJSON tests that POST endpoints that expect a body return // the correct error when sending invalid JSON requests. func TestPluginInvalidJSON(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) // POST endpoints that accept / expect a JSON body; endpoints := []string{ @@ -47,8 +47,11 @@ func TestPluginInvalidJSON(t *testing.T) { t.Run(ep[1:], func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) + t.Run("invalid content type", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("[]"), request.ContentType("text/plain")) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("[]"), request.ContentType("text/plain")) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -58,7 +61,8 @@ func TestPluginInvalidJSON(t *testing.T) { }) t.Run("invalid JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{invalid json"), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -68,7 +72,8 @@ func TestPluginInvalidJSON(t *testing.T) { }) t.Run("extra content after JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString(`[] trailing content`), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString(`[] trailing content`), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -78,10 +83,11 @@ func TestPluginInvalidJSON(t *testing.T) { }) t.Run("empty body", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) // empty body should not produce an 500 internal server error, or // any 5XX error (this is assuming the request does not produce // an internal server error for another reason, but it shouldn't) - res, _, err := request.Post(ep, request.RawString(``), request.JSON) + res, _, err := request.Post(ctx, ep, request.RawString(``), request.JSON) assert.NilError(t, err) assert.Check(t, res.StatusCode < http.StatusInternalServerError) }) @@ -94,11 +100,11 @@ func TestPluginInstall(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRootless, "rootless mode has different view of localhost") - ctx := context.Background() + ctx := testutil.StartSpan(baseContext, t) client := testEnv.APIClient() t.Run("no auth", func(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) reg := registry.NewV2(t) defer reg.Close() @@ -119,7 +125,7 @@ func TestPluginInstall(t *testing.T) { }) t.Run("with htpasswd", func(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) reg := registry.NewV2(t, registry.Htpasswd) defer reg.Close() @@ -149,6 +155,8 @@ func TestPluginInstall(t *testing.T) { t.Run("with insecure", func(t *testing.T) { skip.If(t, !testEnv.IsLocalDaemon()) + ctx := testutil.StartSpan(ctx, t) + addrs, err := net.InterfaceAddrs() assert.NilError(t, err) @@ -202,6 +210,8 @@ func TestPluginsWithRuntimes(t *testing.T) { skip.If(t, testEnv.IsRootless, "Test not supported on rootless due to buggy daemon setup in rootless mode due to daemon restart") skip.If(t, testEnv.DaemonInfo.OSType == "windows") + ctx := testutil.StartSpan(baseContext, t) + dir, err := os.MkdirTemp("", t.Name()) assert.NilError(t, err) defer os.RemoveAll(dir) @@ -212,7 +222,6 @@ func TestPluginsWithRuntimes(t *testing.T) { d.Start(t) defer d.Stop(t) - ctx := context.Background() client := d.NewClientT(t) assert.NilError(t, plugin.Create(ctx, client, "test:latest")) @@ -248,12 +257,14 @@ func TestPluginsWithRuntimes(t *testing.T) { os.WriteFile(configPath, cfg, 0o644) t.Run("No Args", func(t *testing.T) { + _ = testutil.StartSpan(ctx, t) d.Restart(t, "--default-runtime=myrt", "--config-file="+configPath) _, err = os.Stat(filepath.Join(dir, "success")) assert.NilError(t, err) }) t.Run("With Args", func(t *testing.T) { + _ = testutil.StartSpan(ctx, t) d.Restart(t, "--default-runtime=myrtArgs", "--config-file="+configPath) _, err = os.Stat(filepath.Join(dir, "success_someArg")) assert.NilError(t, err) @@ -265,7 +276,7 @@ func TestPluginBackCompatMediaTypes(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.IsRootless, "Rootless has a different view of localhost (needed for test registry access)") - defer setupTest(t)() + ctx := setupTest(t) reg := registry.NewV2(t) defer reg.Close() @@ -275,7 +286,6 @@ func TestPluginBackCompatMediaTypes(t *testing.T) { client := testEnv.APIClient() - ctx := context.Background() assert.NilError(t, plugin.Create(ctx, client, repo)) rdr, err := client.PluginPush(ctx, repo, "") diff --git a/integration/plugin/graphdriver/external_test.go b/integration/plugin/graphdriver/external_test.go index 3781ac1be2..5d56555510 100644 --- a/integration/plugin/graphdriver/external_test.go +++ b/integration/plugin/graphdriver/external_test.go @@ -21,6 +21,7 @@ import ( "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/plugins" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -51,6 +52,8 @@ func TestExternalGraphDriver(t *testing.T) { skip.If(t, !requirement.HasHubConnectivity(t)) skip.If(t, testEnv.IsRootless, "rootless mode doesn't support external graph driver") + ctx := testutil.StartSpan(baseContext, t) + // Setup plugin(s) ec := make(map[string]*graphEventsCounter) sserver := setupPluginViaSpecFile(t, ec) @@ -61,7 +64,7 @@ func TestExternalGraphDriver(t *testing.T) { for _, tc := range []struct { name string - test func(client.APIClient, *daemon.Daemon) func(*testing.T) + test func(context.Context, client.APIClient, *daemon.Daemon) func(*testing.T) }{ { name: "json", @@ -76,7 +79,10 @@ func TestExternalGraphDriver(t *testing.T) { test: testGraphDriverPull, }, } { - t.Run(tc.name, tc.test(c, d)) + t.Run(tc.name, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) + tc.test(ctx, c, d) + }) } sserver.Close() @@ -353,13 +359,11 @@ func setupPlugin(t *testing.T, ec map[string]*graphEventsCounter, ext string, mu assert.NilError(t, err) } -func testExternalGraphDriver(ext string, ec map[string]*graphEventsCounter) func(client.APIClient, *daemon.Daemon) func(*testing.T) { - return func(c client.APIClient, d *daemon.Daemon) func(*testing.T) { +func testExternalGraphDriver(ext string, ec map[string]*graphEventsCounter) func(context.Context, client.APIClient, *daemon.Daemon) func(*testing.T) { + return func(ctx context.Context, c client.APIClient, d *daemon.Daemon) func(*testing.T) { return func(t *testing.T) { driverName := fmt.Sprintf("%s-external-graph-driver", ext) - d.StartWithBusybox(t, "-s", driverName) - - ctx := context.Background() + d.StartWithBusybox(ctx, t, "-s", driverName) testGraphDriver(ctx, t, c, driverName, func(t *testing.T) { d.Restart(t, "-s", driverName) @@ -389,11 +393,10 @@ func testExternalGraphDriver(ext string, ec map[string]*graphEventsCounter) func } } -func testGraphDriverPull(c client.APIClient, d *daemon.Daemon) func(*testing.T) { +func testGraphDriverPull(ctx context.Context, c client.APIClient, d *daemon.Daemon) func(*testing.T) { return func(t *testing.T) { d.Start(t) defer d.Stop(t) - ctx := context.Background() r, err := c.ImagePull(ctx, "busybox:latest@sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209", types.ImagePullOptions{}) assert.NilError(t, err) @@ -412,13 +415,14 @@ func TestGraphdriverPluginV2(t *testing.T) { skip.If(t, testEnv.NotAmd64) skip.If(t, !requirement.Overlay2Supported(testEnv.DaemonInfo.KernelVersion)) + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t, daemon.WithExperimental()) d.Start(t) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() // install the plugin plugin := "cpuguy83/docker-overlay2-graphdriver-plugin" @@ -434,7 +438,7 @@ func TestGraphdriverPluginV2(t *testing.T) { // restart the daemon with the plugin set as the storage driver d.Stop(t) - d.StartWithBusybox(t, "-s", plugin) + d.StartWithBusybox(ctx, t, "-s", plugin) testGraphDriver(ctx, t, client, plugin, nil) } diff --git a/integration/plugin/graphdriver/main_test.go b/integration/plugin/graphdriver/main_test.go index c708766f16..2d794ebb4e 100644 --- a/integration/plugin/graphdriver/main_test.go +++ b/integration/plugin/graphdriver/main_test.go @@ -1,27 +1,46 @@ package graphdriver // import "github.com/docker/docker/integration/plugin/graphdriver" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/plugin/graphdriver.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } diff --git a/integration/plugin/logging/helpers_test.go b/integration/plugin/logging/helpers_test.go index 7a9f146c9d..8920e93a6a 100644 --- a/integration/plugin/logging/helpers_test.go +++ b/integration/plugin/logging/helpers_test.go @@ -6,12 +6,12 @@ import ( "os/exec" "path/filepath" "testing" - "time" "github.com/docker/docker/api/types" "github.com/docker/docker/testutil/fixtures/plugin" "github.com/moby/locker" "github.com/pkg/errors" + "gotest.tools/v3/assert" ) var pluginBuildLock = locker.New() @@ -45,19 +45,16 @@ func withSockPath(name string) func(*plugin.Config) { } } -func createPlugin(t *testing.T, client plugin.CreateClient, alias, bin string, opts ...plugin.CreateOpt) { +func createPlugin(ctx context.Context, t *testing.T, client plugin.CreateClient, alias, bin string, opts ...plugin.CreateOpt) { + t.Helper() + pluginBin := ensurePlugin(t, bin) opts = append(opts, withSockPath("plugin.sock")) opts = append(opts, plugin.WithBinary(pluginBin)) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) err := plugin.Create(ctx, client, alias, opts...) - cancel() - - if err != nil { - t.Fatal(err) - } + assert.NilError(t, err) } func asLogDriver(cfg *plugin.Config) { diff --git a/integration/plugin/logging/logging_linux_test.go b/integration/plugin/logging/logging_linux_test.go index 2af0237f7c..c0b2995db4 100644 --- a/integration/plugin/logging/logging_linux_test.go +++ b/integration/plugin/logging/logging_linux_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/skip" @@ -19,21 +20,25 @@ func TestContinueAfterPluginCrash(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "test requires daemon on the same host") t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t, "--iptables=false", "--init") + d.StartWithBusybox(ctx, t, "--iptables=false", "--init") defer d.Stop(t) client := d.NewClientT(t) - createPlugin(t, client, "test", "close_on_start", asLogDriver) + createPlugin(ctx, t, client, "test", "close_on_start", asLogDriver) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - assert.Assert(t, client.PluginEnable(ctx, "test", types.PluginEnableOptions{Timeout: 30})) + ctxT, cancel := context.WithTimeout(ctx, 60*time.Second) + defer cancel() + assert.Assert(t, client.PluginEnable(ctxT, "test", types.PluginEnableOptions{Timeout: 30})) cancel() - defer client.PluginRemove(context.Background(), "test", types.PluginRemoveOptions{Force: true}) + defer client.PluginRemove(ctx, "test", types.PluginRemoveOptions{Force: true}) - ctx, cancel = context.WithTimeout(context.Background(), 60*time.Second) + ctxT, cancel = context.WithTimeout(ctx, 60*time.Second) + defer cancel() - id := container.Run(ctx, t, client, + id := container.Run(ctxT, t, client, container.WithAutoRemove, container.WithLogDriver("test"), container.WithCmd( @@ -41,10 +46,10 @@ func TestContinueAfterPluginCrash(t *testing.T) { ), ) cancel() - defer client.ContainerRemove(context.Background(), id, types.ContainerRemoveOptions{Force: true}) + defer client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{Force: true}) // Attach to the container to make sure it's written a few times to stdout - attach, err := client.ContainerAttach(context.Background(), id, types.ContainerAttachOptions{Stream: true, Stdout: true}) + attach, err := client.ContainerAttach(ctx, id, types.ContainerAttachOptions{Stream: true, Stdout: true}) assert.NilError(t, err) chErr := make(chan error, 1) diff --git a/integration/plugin/logging/main_test.go b/integration/plugin/logging/main_test.go index e22ce8c0ae..abcb2544b1 100644 --- a/integration/plugin/logging/main_test.go +++ b/integration/plugin/logging/main_test.go @@ -1,27 +1,48 @@ package logging // import "github.com/docker/docker/integration/plugin/logging" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/plugin/logging.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } + testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + span.End() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } diff --git a/integration/plugin/logging/read_test.go b/integration/plugin/logging/read_test.go index 2964e90295..a80c4634de 100644 --- a/integration/plugin/logging/read_test.go +++ b/integration/plugin/logging/read_test.go @@ -2,7 +2,6 @@ package logging import ( "bytes" - "context" "runtime" "strings" "testing" @@ -11,6 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" ) @@ -21,15 +21,16 @@ func TestReadPluginNoRead(t *testing.T) { t.Skip("no unix domain sockets on Windows") } t.Parallel() + + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) - d.StartWithBusybox(t, "--iptables=false") + d.StartWithBusybox(ctx, t, "--iptables=false") defer d.Stop(t) client, err := d.NewClient() assert.Assert(t, err) - createPlugin(t, client, "test", "discard", asLogDriver) - - ctx := context.Background() + createPlugin(ctx, t, client, "test", "discard", asLogDriver) err = client.PluginEnable(ctx, "test", types.PluginEnableOptions{Timeout: 30}) assert.Check(t, err) @@ -48,6 +49,7 @@ func TestReadPluginNoRead(t *testing.T) { "explicitly enabled caching": {[]string{"--log-opt=cache-disabled=false"}, true}, } { t.Run(desc, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) d.Start(t, append([]string{"--iptables=false"}, test.dOpts...)...) defer d.Stop(t) c, err := client.ContainerCreate(ctx, diff --git a/integration/plugin/logging/validation_test.go b/integration/plugin/logging/validation_test.go index 1559d55b37..930d9fa907 100644 --- a/integration/plugin/logging/validation_test.go +++ b/integration/plugin/logging/validation_test.go @@ -3,10 +3,10 @@ package logging import ( - "context" "testing" "github.com/docker/docker/api/types" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/skip" @@ -20,14 +20,15 @@ func TestDaemonStartWithLogOpt(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) d.Start(t, "--iptables=false") defer d.Stop(t) c := d.NewClientT(t) - ctx := context.Background() - createPlugin(t, c, "test", "dummy", asLogDriver) + createPlugin(ctx, t, c, "test", "dummy", asLogDriver) err := c.PluginEnable(ctx, "test", types.PluginEnableOptions{Timeout: 30}) assert.Check(t, err) defer c.PluginRemove(ctx, "test", types.PluginRemoveOptions{Force: true}) diff --git a/integration/plugin/volumes/helpers_test.go b/integration/plugin/volumes/helpers_test.go index 96cefead92..667034ba8f 100644 --- a/integration/plugin/volumes/helpers_test.go +++ b/integration/plugin/volumes/helpers_test.go @@ -50,13 +50,13 @@ func withSockPath(name string) func(*plugin.Config) { } } -func createPlugin(t *testing.T, client plugin.CreateClient, alias, bin string, opts ...plugin.CreateOpt) { +func createPlugin(ctx context.Context, t *testing.T, client plugin.CreateClient, alias, bin string, opts ...plugin.CreateOpt) { pluginBin := ensurePlugin(t, bin) opts = append(opts, withSockPath("plugin.sock")) opts = append(opts, plugin.WithBinary(pluginBin)) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + ctx, cancel := context.WithTimeout(ctx, 60*time.Second) err := plugin.Create(ctx, client, alias, opts...) cancel() diff --git a/integration/plugin/volumes/main_test.go b/integration/plugin/volumes/main_test.go index 87698dbac9..02fdc01bb4 100644 --- a/integration/plugin/volumes/main_test.go +++ b/integration/plugin/volumes/main_test.go @@ -1,27 +1,46 @@ package volumes // import "github.com/docker/docker/integration/plugin/volumes" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/plugin/volume.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } diff --git a/integration/plugin/volumes/mounts_test.go b/integration/plugin/volumes/mounts_test.go index c80c4cd79c..5d5cf2f713 100644 --- a/integration/plugin/volumes/mounts_test.go +++ b/integration/plugin/volumes/mounts_test.go @@ -1,11 +1,11 @@ package volumes import ( - "context" "os" "testing" "github.com/docker/docker/api/types" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fixtures/plugin" "gotest.tools/v3/assert" @@ -20,18 +20,19 @@ func TestPluginWithDevMounts(t *testing.T) { skip.If(t, testEnv.IsRootless) t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) d.Start(t, "--iptables=false") defer d.Stop(t) c := d.NewClientT(t) - ctx := context.Background() testDir, err := os.MkdirTemp("", "test-dir") assert.NilError(t, err) defer os.RemoveAll(testDir) - createPlugin(t, c, "test", "dummy", asVolumeDriver, func(c *plugin.Config) { + createPlugin(ctx, t, c, "test", "dummy", asVolumeDriver, func(c *plugin.Config) { root := "/" dev := "/dev" mounts := []types.PluginMount{ diff --git a/integration/secret/main_test.go b/integration/secret/main_test.go index a0cc4d889c..4e784cfe80 100644 --- a/integration/secret/main_test.go +++ b/integration/secret/main_test.go @@ -1,33 +1,55 @@ package secret // import "github.com/docker/docker/integration/secret" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/secret.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { + testEnv.Clean(ctx, t) + }) + return ctx } diff --git a/integration/secret/secret_test.go b/integration/secret/secret_test.go index ab11538d6d..ffb0718196 100644 --- a/integration/secret/secret_test.go +++ b/integration/secret/secret_test.go @@ -15,6 +15,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration/internal/swarm" "github.com/docker/docker/pkg/stdcopy" + "github.com/docker/docker/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/poll" @@ -24,14 +25,12 @@ import ( func TestSecretInspect(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() - testName := t.Name() secretID := createSecret(ctx, t, c, testName, []byte("TESTINGDATA"), nil) @@ -48,12 +47,11 @@ func TestSecretInspect(t *testing.T) { func TestSecretList(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() configs, err := c.SecretList(ctx, types.SecretListOptions{}) assert.NilError(t, err) @@ -128,12 +126,11 @@ func createSecret(ctx context.Context, t *testing.T, client client.APIClient, na func TestSecretsCreateAndDelete(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() testName := "test_secret_" + t.Name() secretID := createSecret(ctx, t, c, testName, []byte("TESTINGDATA"), nil) @@ -176,12 +173,11 @@ func TestSecretsCreateAndDelete(t *testing.T) { func TestSecretsUpdate(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() testName := "test_secret_" + t.Name() secretID := createSecret(ctx, t, c, testName, []byte("TESTINGDATA"), nil) @@ -227,11 +223,13 @@ func TestSecretsUpdate(t *testing.T) { func TestTemplatedSecret(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - d := swarm.NewSwarm(t, testEnv) + + ctx := testutil.StartSpan(baseContext, t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() referencedSecretName := "referencedsecret_" + t.Name() referencedSecretSpec := swarmtypes.SecretSpec{ @@ -270,7 +268,7 @@ func TestTemplatedSecret(t *testing.T) { assert.Check(t, err) serviceName := "svc_" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithSecret( &swarmtypes.SecretReference{ File: &swarmtypes.SecretReferenceFileTarget{ @@ -310,12 +308,12 @@ func TestTemplatedSecret(t *testing.T) { swarm.ServiceWithName(serviceName), ) - poll.WaitOn(t, swarm.RunningTasksCount(c, serviceID, 1), swarm.ServicePoll, poll.WithTimeout(1*time.Minute)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, c, serviceID, 1), swarm.ServicePoll, poll.WithTimeout(1*time.Minute)) - tasks := swarm.GetRunningTasks(t, c, serviceID) + tasks := swarm.GetRunningTasks(ctx, t, c, serviceID) assert.Assert(t, len(tasks) > 0, "no running tasks found for service %s", serviceID) - attach := swarm.ExecTask(t, d, tasks[0], types.ExecConfig{ + attach := swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ Cmd: []string{"/bin/cat", "/run/secrets/templated_secret"}, AttachStdout: true, AttachStderr: true, @@ -326,7 +324,7 @@ func TestTemplatedSecret(t *testing.T) { "this is a config\n" assertAttachedStream(t, attach, expect) - attach = swarm.ExecTask(t, d, tasks[0], types.ExecConfig{ + attach = swarm.ExecTask(ctx, t, d, tasks[0], types.ExecConfig{ Cmd: []string{"mount"}, AttachStdout: true, AttachStderr: true, @@ -338,14 +336,12 @@ func TestTemplatedSecret(t *testing.T) { func TestSecretCreateResolve(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() - testName := "test_secret_" + t.Name() secretID := createSecret(ctx, t, c, testName, []byte("foo"), nil) diff --git a/integration/service/create_test.go b/integration/service/create_test.go index 5db29229ce..4d70361e3b 100644 --- a/integration/service/create_test.go +++ b/integration/service/create_test.go @@ -16,6 +16,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/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -24,19 +25,20 @@ import ( ) func TestServiceCreateInit(t *testing.T) { - defer setupTest(t)() - t.Run("daemonInitDisabled", testServiceCreateInit(false)) - t.Run("daemonInitEnabled", testServiceCreateInit(true)) + ctx := setupTest(t) + t.Run("daemonInitDisabled", testServiceCreateInit(ctx, false)) + t.Run("daemonInitEnabled", testServiceCreateInit(ctx, true)) } -func testServiceCreateInit(daemonEnabled bool) func(t *testing.T) { +func testServiceCreateInit(ctx context.Context, daemonEnabled bool) func(t *testing.T) { return func(t *testing.T) { + _ = testutil.StartSpan(ctx, t) ops := []daemon.Option{} if daemonEnabled { ops = append(ops, daemon.WithInit()) } - d := swarm.NewSwarm(t, testEnv, ops...) + d := swarm.NewSwarm(ctx, t, testEnv, ops...) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() @@ -44,45 +46,45 @@ func testServiceCreateInit(daemonEnabled bool) func(t *testing.T) { booleanTrue := true booleanFalse := false - serviceID := swarm.CreateService(t, d) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, 1), swarm.ServicePoll) - i := inspectServiceContainer(t, client, serviceID) + serviceID := swarm.CreateService(ctx, t, d) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, 1), swarm.ServicePoll) + i := inspectServiceContainer(ctx, t, client, serviceID) // HostConfig.Init == nil means that it delegates to daemon configuration assert.Check(t, i.HostConfig.Init == nil) - serviceID = swarm.CreateService(t, d, swarm.ServiceWithInit(&booleanTrue)) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, 1), swarm.ServicePoll) - i = inspectServiceContainer(t, client, serviceID) + serviceID = swarm.CreateService(ctx, t, d, swarm.ServiceWithInit(&booleanTrue)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, 1), swarm.ServicePoll) + i = inspectServiceContainer(ctx, t, client, serviceID) assert.Check(t, is.Equal(true, *i.HostConfig.Init)) - serviceID = swarm.CreateService(t, d, swarm.ServiceWithInit(&booleanFalse)) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, 1), swarm.ServicePoll) - i = inspectServiceContainer(t, client, serviceID) + serviceID = swarm.CreateService(ctx, t, d, swarm.ServiceWithInit(&booleanFalse)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, 1), swarm.ServicePoll) + i = inspectServiceContainer(ctx, t, client, serviceID) assert.Check(t, is.Equal(false, *i.HostConfig.Init)) } } -func inspectServiceContainer(t *testing.T, client client.APIClient, serviceID string) types.ContainerJSON { +func inspectServiceContainer(ctx context.Context, t *testing.T, client client.APIClient, serviceID string) types.ContainerJSON { t.Helper() - containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{ + containers, err := client.ContainerList(ctx, types.ContainerListOptions{ Filters: filters.NewArgs(filters.Arg("label", "com.docker.swarm.service.id="+serviceID)), }) assert.NilError(t, err) assert.Check(t, is.Len(containers, 1)) - i, err := client.ContainerInspect(context.Background(), containers[0].ID) + i, err := client.ContainerInspect(ctx, containers[0].ID) assert.NilError(t, err) return i } func TestCreateServiceMultipleTimes(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() overlayName := "overlay1_" + t.Name() overlayID := network.CreateNoError(ctx, t, client, overlayName, @@ -99,21 +101,21 @@ func TestCreateServiceMultipleTimes(t *testing.T) { swarm.ServiceWithNetwork(overlayName), } - serviceID := swarm.CreateService(t, d, serviceSpec...) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, instances), swarm.ServicePoll) + serviceID := swarm.CreateService(ctx, t, d, serviceSpec...) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, instances), swarm.ServicePoll) - _, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) + _, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) - err = client.ServiceRemove(context.Background(), serviceID) + err = client.ServiceRemove(ctx, serviceID) assert.NilError(t, err) poll.WaitOn(t, swarm.NoTasksForService(ctx, client, serviceID), swarm.ServicePoll) - serviceID2 := swarm.CreateService(t, d, serviceSpec...) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID2, instances), swarm.ServicePoll) + serviceID2 := swarm.CreateService(ctx, t, d, serviceSpec...) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID2, instances), swarm.ServicePoll) - err = client.ServiceRemove(context.Background(), serviceID2) + err = client.ServiceRemove(ctx, serviceID2) assert.NilError(t, err) // we can't just wait on no tasks for the service, counter-intuitively. @@ -123,7 +125,7 @@ func TestCreateServiceMultipleTimes(t *testing.T) { poll.WaitOn(t, swarm.NoTasksForService(ctx, client, serviceID2), swarm.ServicePoll) for retry := 0; retry < 5; retry++ { - err = client.NetworkRemove(context.Background(), overlayID) + err = client.NetworkRemove(ctx, overlayID) // TODO(dperny): using strings.Contains for error checking is awful, // but so is the fact that swarm functions don't return errdefs errors. // I don't have time at this moment to fix the latter, so I guess I'll @@ -145,24 +147,24 @@ func TestCreateServiceMultipleTimes(t *testing.T) { } assert.NilError(t, err) - poll.WaitOn(t, network.IsRemoved(context.Background(), client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) + poll.WaitOn(t, network.IsRemoved(ctx, client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) } func TestCreateServiceConflict(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) c := d.NewClientT(t) defer c.Close() - ctx := context.Background() serviceName := "TestService_" + t.Name() serviceSpec := []swarm.ServiceSpecOpt{ swarm.ServiceWithName(serviceName), } - swarm.CreateService(t, d, serviceSpec...) + swarm.CreateService(ctx, t, d, serviceSpec...) spec := swarm.CreateServiceSpec(t, serviceSpec...) _, err := c.ServiceCreate(ctx, spec, types.ServiceCreateOptions{}) @@ -171,8 +173,9 @@ func TestCreateServiceConflict(t *testing.T) { } func TestCreateServiceMaxReplicas(t *testing.T) { - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() @@ -183,21 +186,20 @@ func TestCreateServiceMaxReplicas(t *testing.T) { swarm.ServiceWithMaxReplicas(maxReplicas), } - serviceID := swarm.CreateService(t, d, serviceSpec...) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, maxReplicas), swarm.ServicePoll) + serviceID := swarm.CreateService(ctx, t, d, serviceSpec...) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, maxReplicas), swarm.ServicePoll) - _, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) + _, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) } func TestCreateWithDuplicateNetworkNames(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() name := "foo_" + t.Name() n1 := network.CreateNoError(ctx, t, client, name, network.WithDriver("bridge")) @@ -210,13 +212,13 @@ func TestCreateWithDuplicateNetworkNames(t *testing.T) { var instances uint64 = 1 serviceName := "top_" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(serviceName), swarm.ServiceWithNetwork(name), ) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, instances), swarm.ServicePoll) resp, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) @@ -228,30 +230,30 @@ func TestCreateWithDuplicateNetworkNames(t *testing.T) { poll.WaitOn(t, swarm.NoTasksForService(ctx, client, serviceID), swarm.ServicePoll) // Remove networks - err = client.NetworkRemove(context.Background(), n3) + err = client.NetworkRemove(ctx, n3) assert.NilError(t, err) - err = client.NetworkRemove(context.Background(), n2) + err = client.NetworkRemove(ctx, n2) assert.NilError(t, err) - err = client.NetworkRemove(context.Background(), n1) + err = client.NetworkRemove(ctx, n1) assert.NilError(t, err) // Make sure networks have been destroyed. - poll.WaitOn(t, network.IsRemoved(context.Background(), client, n3), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) - poll.WaitOn(t, network.IsRemoved(context.Background(), client, n2), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) - poll.WaitOn(t, network.IsRemoved(context.Background(), client, n1), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) + poll.WaitOn(t, network.IsRemoved(ctx, client, n3), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) + poll.WaitOn(t, network.IsRemoved(ctx, client, n2), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) + poll.WaitOn(t, network.IsRemoved(ctx, client, n1), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) } func TestCreateServiceSecretFileMode(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() secretName := "TestSecret_" + t.Name() secretResp, err := client.SecretCreate(ctx, swarmtypes.SecretSpec{ Annotations: swarmtypes.Annotations{ @@ -263,7 +265,7 @@ func TestCreateServiceSecretFileMode(t *testing.T) { var instances uint64 = 1 serviceName := "TestService_" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(serviceName), swarm.ServiceWithCommand([]string{"/bin/sh", "-c", "ls -l /etc/secret && sleep inf"}), @@ -279,7 +281,7 @@ func TestCreateServiceSecretFileMode(t *testing.T) { }), ) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, instances), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, instances), swarm.ServicePoll) body, err := client.ServiceLogs(ctx, serviceID, types.ContainerLogsOptions{ Tail: "1", @@ -302,13 +304,13 @@ func TestCreateServiceSecretFileMode(t *testing.T) { func TestCreateServiceConfigFileMode(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() configName := "TestConfig_" + t.Name() configResp, err := client.ConfigCreate(ctx, swarmtypes.ConfigSpec{ Annotations: swarmtypes.Annotations{ @@ -320,7 +322,7 @@ func TestCreateServiceConfigFileMode(t *testing.T) { var instances uint64 = 1 serviceName := "TestService_" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithName(serviceName), swarm.ServiceWithCommand([]string{"/bin/sh", "-c", "ls -l /etc/config && sleep inf"}), swarm.ServiceWithReplicas(instances), @@ -336,7 +338,7 @@ func TestCreateServiceConfigFileMode(t *testing.T) { }), ) - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, instances)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, instances)) body, err := client.ServiceLogs(ctx, serviceID, types.ContainerLogsOptions{ Tail: "1", @@ -385,14 +387,13 @@ func TestCreateServiceSysctls(t *testing.T) { "setting service sysctls is unsupported before api v1.40", ) - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() - // run thie block twice, so that no matter what the default value of // net.ipv4.ip_nonlocal_bind is, we can verify that setting the sysctl // options works @@ -402,12 +403,12 @@ func TestCreateServiceSysctls(t *testing.T) { // Create the service with the sysctl options var instances uint64 = 1 - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithSysctls(expectedSysctls), ) // wait for the service to converge to 1 running task as expected - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, instances)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, instances)) // we're going to check 3 things: // @@ -466,26 +467,25 @@ func TestCreateServiceCapabilities(t *testing.T) { "setting service capabilities is unsupported before api v1.41", ) - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() - // store the map we're going to be using everywhere. capAdd := []string{"CAP_SYS_CHROOT"} capDrop := []string{"CAP_NET_RAW"} // Create the service with the capabilities options var instances uint64 = 1 - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithCapabilities(capAdd, capDrop), ) // wait for the service to converge to 1 running task as expected - poll.WaitOn(t, swarm.RunningTasksCount(client, serviceID, instances)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, serviceID, instances)) // we're going to check 3 things: // diff --git a/integration/service/inspect_test.go b/integration/service/inspect_test.go index 90c5b13b5c..74865b15f4 100644 --- a/integration/service/inspect_test.go +++ b/integration/service/inspect_test.go @@ -1,7 +1,6 @@ package service // import "github.com/docker/docker/integration/service" import ( - "context" "testing" "time" @@ -19,8 +18,8 @@ import ( func TestInspect(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() @@ -29,14 +28,13 @@ func TestInspect(t *testing.T) { var instances uint64 = 2 serviceSpec := fullSwarmServiceSpec("test-service-inspect"+t.Name(), instances) - ctx := context.Background() resp, err := client.ServiceCreate(ctx, serviceSpec, types.ServiceCreateOptions{ QueryRegistry: false, }) assert.NilError(t, err) id := resp.ID - poll.WaitOn(t, swarm.RunningTasksCount(client, id, instances)) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, id, instances)) service, _, err := client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{}) assert.NilError(t, err) diff --git a/integration/service/jobs_test.go b/integration/service/jobs_test.go index 6379b7cad0..b6305bc0b7 100644 --- a/integration/service/jobs_test.go +++ b/integration/service/jobs_test.go @@ -1,7 +1,6 @@ package service import ( - "context" "testing" "github.com/docker/docker/api/types" @@ -21,9 +20,9 @@ func TestCreateJob(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t) + ctx := setupTest(t) - d := swarm.NewSwarm(t, testEnv) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) @@ -33,9 +32,9 @@ func TestCreateJob(t *testing.T) { {ReplicatedJob: &swarmtypes.ReplicatedJob{}}, {GlobalJob: &swarmtypes.GlobalJob{}}, } { - id := swarm.CreateService(t, d, swarm.ServiceWithMode(mode)) + id := swarm.CreateService(ctx, t, d, swarm.ServiceWithMode(mode)) - poll.WaitOn(t, swarm.RunningTasksCount(client, id, 1), swarm.ServicePoll) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, client, id, 1), swarm.ServicePoll) } } @@ -45,6 +44,8 @@ func TestReplicatedJob(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows") + ctx := setupTest(t) + // we need variables, because the replicas field takes a pointer maxConcurrent := uint64(2) // there is overhead, especially in the test environment, associated with @@ -56,15 +57,13 @@ func TestReplicatedJob(t *testing.T) { // after 15 seconds. this means 7 completions ought not be too many. total := uint64(7) - defer setupTest(t) - - d := swarm.NewSwarm(t, testEnv) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - id := swarm.CreateService(t, d, + id := swarm.CreateService(ctx, t, d, swarm.ServiceWithMode(swarmtypes.ServiceMode{ ReplicatedJob: &swarmtypes.ReplicatedJob{ MaxConcurrent: &maxConcurrent, @@ -76,11 +75,11 @@ func TestReplicatedJob(t *testing.T) { ) service, _, err := client.ServiceInspectWithRaw( - context.Background(), id, types.ServiceInspectOptions{}, + ctx, id, types.ServiceInspectOptions{}, ) assert.NilError(t, err) - poll.WaitOn(t, swarm.JobComplete(client, service), swarm.ServicePoll) + poll.WaitOn(t, swarm.JobComplete(ctx, client, service), swarm.ServicePoll) } // TestUpdateJob tests that a job can be updated, and that it runs with the @@ -89,19 +88,16 @@ func TestUpdateReplicatedJob(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() + ctx := setupTest(t) - d := swarm.NewSwarm(t, testEnv) + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - // avoid writing "context.Background()" over and over again - ctx := context.Background() - // Create the job service - id := swarm.CreateService(t, d, + id := swarm.CreateService(ctx, t, d, swarm.ServiceWithMode(swarmtypes.ServiceMode{ ReplicatedJob: &swarmtypes.ReplicatedJob{ // use the default, empty values. @@ -117,7 +113,7 @@ func TestUpdateReplicatedJob(t *testing.T) { assert.NilError(t, err) // wait for the job to completed - poll.WaitOn(t, swarm.JobComplete(client, service), swarm.ServicePoll) + poll.WaitOn(t, swarm.JobComplete(ctx, client, service), swarm.ServicePoll) // update the job. spec := service.Spec @@ -139,5 +135,5 @@ func TestUpdateReplicatedJob(t *testing.T) { ) // now wait for the service to complete a second time. - poll.WaitOn(t, swarm.JobComplete(client, service2), swarm.ServicePoll) + poll.WaitOn(t, swarm.JobComplete(ctx, client, service2), swarm.ServicePoll) } diff --git a/integration/service/list_test.go b/integration/service/list_test.go index 4f2653aaf2..fe3caf72dd 100644 --- a/integration/service/list_test.go +++ b/integration/service/list_test.go @@ -1,7 +1,6 @@ package service // import "github.com/docker/docker/integration/service" import ( - "context" "fmt" "testing" @@ -32,14 +31,14 @@ func TestServiceListWithStatuses(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") // statuses were added in API version 1.41 skip.If(t, versions.LessThan(testEnv.DaemonInfo.ServerVersion, "1.41")) - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() - serviceCount := 3 // create some services. for i := 0; i < serviceCount; i++ { @@ -57,7 +56,7 @@ func TestServiceListWithStatuses(t *testing.T) { // serviceContainerCount function does not do. instead, we'll use a // bespoke closure right here. poll.WaitOn(t, func(log poll.LogT) poll.Result { - tasks, err := client.TaskList(context.Background(), types.TaskListOptions{ + tasks, err := client.TaskList(ctx, types.TaskListOptions{ Filters: filters.NewArgs(filters.Arg("service", id)), }) diff --git a/integration/service/main_test.go b/integration/service/main_test.go index 939c5ac897..563df8f14b 100644 --- a/integration/service/main_test.go +++ b/integration/service/main_test.go @@ -1,33 +1,55 @@ package service // import "github.com/docker/docker/integration/service" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/service.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { + testEnv.Clean(ctx, t) + }) + return ctx } diff --git a/integration/service/network_test.go b/integration/service/network_test.go index e0c2103f60..c3e407967c 100644 --- a/integration/service/network_test.go +++ b/integration/service/network_test.go @@ -1,7 +1,6 @@ package service // import "github.com/docker/docker/integration/service" import ( - "context" "testing" "github.com/docker/docker/api/types" @@ -16,12 +15,12 @@ import ( func TestDockerNetworkConnectAlias(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() name := t.Name() + "test-alias" net.CreateNoError(ctx, t, client, name, @@ -78,12 +77,12 @@ func TestDockerNetworkConnectAlias(t *testing.T) { func TestDockerNetworkReConnect(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.Background() name := t.Name() + "dummyNet" net.CreateNoError(ctx, t, client, name, diff --git a/integration/service/plugin_test.go b/integration/service/plugin_test.go index 696cd1d5d5..47f2ef7c00 100644 --- a/integration/service/plugin_test.go +++ b/integration/service/plugin_test.go @@ -1,7 +1,6 @@ package service import ( - "context" "io" "path" "strings" @@ -24,7 +23,7 @@ func TestServicePlugin(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") skip.If(t, testEnv.DaemonInfo.OSType == "windows") skip.If(t, testEnv.NotAmd64) - defer setupTest(t)() + ctx := setupTest(t) reg := registry.NewV2(t) defer reg.Close() @@ -34,48 +33,48 @@ func TestServicePlugin(t *testing.T) { repo2 := path.Join(registry.DefaultURL, "swarm", name+":v2") d := daemon.New(t) - d.StartWithBusybox(t) + d.StartWithBusybox(ctx, t) apiclient := d.NewClientT(t) - err := plugin.Create(context.Background(), apiclient, repo) + err := plugin.Create(ctx, apiclient, repo) assert.NilError(t, err) - r, err := apiclient.PluginPush(context.Background(), repo, "") + r, err := apiclient.PluginPush(ctx, repo, "") assert.NilError(t, err) _, err = io.Copy(io.Discard, r) assert.NilError(t, err) - err = apiclient.PluginRemove(context.Background(), repo, types.PluginRemoveOptions{}) + err = apiclient.PluginRemove(ctx, repo, types.PluginRemoveOptions{}) assert.NilError(t, err) - err = plugin.Create(context.Background(), apiclient, repo2) + err = plugin.Create(ctx, apiclient, repo2) assert.NilError(t, err) - r, err = apiclient.PluginPush(context.Background(), repo2, "") + r, err = apiclient.PluginPush(ctx, repo2, "") assert.NilError(t, err) _, err = io.Copy(io.Discard, r) assert.NilError(t, err) - err = apiclient.PluginRemove(context.Background(), repo2, types.PluginRemoveOptions{}) + err = apiclient.PluginRemove(ctx, repo2, types.PluginRemoveOptions{}) assert.NilError(t, err) d.Stop(t) - d1 := swarm.NewSwarm(t, testEnv, daemon.WithExperimental()) + d1 := swarm.NewSwarm(ctx, t, testEnv, daemon.WithExperimental()) defer d1.Stop(t) d2 := daemon.New(t, daemon.WithExperimental(), daemon.WithSwarmPort(daemon.DefaultSwarmPort+1)) - d2.StartAndSwarmJoin(t, d1, true) + d2.StartAndSwarmJoin(ctx, t, d1, true) defer d2.Stop(t) d3 := daemon.New(t, daemon.WithExperimental(), daemon.WithSwarmPort(daemon.DefaultSwarmPort+2)) - d3.StartAndSwarmJoin(t, d1, false) + d3.StartAndSwarmJoin(ctx, t, d1, false) defer d3.Stop(t) - id := d1.CreateService(t, makePlugin(repo, name, nil)) + id := d1.CreateService(ctx, t, makePlugin(repo, name, nil)) poll.WaitOn(t, d1.PluginIsRunning(t, name), swarm.ServicePoll) poll.WaitOn(t, d2.PluginIsRunning(t, name), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsRunning(t, name), swarm.ServicePoll) // test that environment variables are passed from plugin service to plugin instance - service := d1.GetService(t, id) - tasks := d1.GetServiceTasks(t, service.Spec.Annotations.Name, filters.Arg("runtime", "plugin")) + service := d1.GetService(ctx, t, id) + tasks := d1.GetServiceTasks(ctx, t, service.Spec.Annotations.Name, filters.Arg("runtime", "plugin")) if len(tasks) == 0 { t.Log("No tasks found for plugin service") t.Fail() } - plugin, _, err := d1.NewClientT(t).PluginInspectWithRaw(context.Background(), name) + plugin, _, err := d1.NewClientT(t).PluginInspectWithRaw(ctx, name) assert.NilError(t, err, "Error inspecting service plugin") found := false for _, env := range plugin.Settings.Env { @@ -87,7 +86,7 @@ func TestServicePlugin(t *testing.T) { } assert.Equal(t, true, found, "Environment variable %q not found in plugin", "foo") - d1.UpdateService(t, service, makePlugin(repo2, name, nil)) + d1.UpdateService(ctx, t, service, makePlugin(repo2, name, nil)) poll.WaitOn(t, d1.PluginReferenceIs(t, name, repo2), swarm.ServicePoll) poll.WaitOn(t, d2.PluginReferenceIs(t, name, repo2), swarm.ServicePoll) poll.WaitOn(t, d3.PluginReferenceIs(t, name, repo2), swarm.ServicePoll) @@ -95,29 +94,29 @@ func TestServicePlugin(t *testing.T) { poll.WaitOn(t, d2.PluginIsRunning(t, name), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsRunning(t, name), swarm.ServicePoll) - d1.RemoveService(t, id) + d1.RemoveService(ctx, t, id) poll.WaitOn(t, d1.PluginIsNotPresent(t, name), swarm.ServicePoll) poll.WaitOn(t, d2.PluginIsNotPresent(t, name), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsNotPresent(t, name), swarm.ServicePoll) // constrain to managers only - id = d1.CreateService(t, makePlugin(repo, name, []string{"node.role==manager"})) + id = d1.CreateService(ctx, t, makePlugin(repo, name, []string{"node.role==manager"})) poll.WaitOn(t, d1.PluginIsRunning(t, name), swarm.ServicePoll) poll.WaitOn(t, d2.PluginIsRunning(t, name), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsNotPresent(t, name), swarm.ServicePoll) - d1.RemoveService(t, id) + d1.RemoveService(ctx, t, id) poll.WaitOn(t, d1.PluginIsNotPresent(t, name), swarm.ServicePoll) poll.WaitOn(t, d2.PluginIsNotPresent(t, name), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsNotPresent(t, name), swarm.ServicePoll) // with no name - id = d1.CreateService(t, makePlugin(repo, "", nil)) + id = d1.CreateService(ctx, t, makePlugin(repo, "", nil)) poll.WaitOn(t, d1.PluginIsRunning(t, repo), swarm.ServicePoll) poll.WaitOn(t, d2.PluginIsRunning(t, repo), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsRunning(t, repo), swarm.ServicePoll) - d1.RemoveService(t, id) + d1.RemoveService(ctx, t, id) poll.WaitOn(t, d1.PluginIsNotPresent(t, repo), swarm.ServicePoll) poll.WaitOn(t, d2.PluginIsNotPresent(t, repo), swarm.ServicePoll) poll.WaitOn(t, d3.PluginIsNotPresent(t, repo), swarm.ServicePoll) diff --git a/integration/service/update_test.go b/integration/service/update_test.go index 77690f28a4..d4f72f13fb 100644 --- a/integration/service/update_test.go +++ b/integration/service/update_test.go @@ -11,6 +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/testutil" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" "gotest.tools/v3/poll" @@ -19,69 +20,69 @@ import ( func TestServiceUpdateLabel(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) cli := d.NewClientT(t) defer cli.Close() - ctx := context.Background() serviceName := "TestService_" + t.Name() - serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) - service := getService(t, cli, serviceID) + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithName(serviceName)) + service := getService(ctx, t, cli, serviceID) assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{})) // add label to empty set service.Spec.Labels["foo"] = "bar" _, err := cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceSpecIsUpdated(ctx, cli, serviceID, service.Version.Index), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) // add label to non-empty set service.Spec.Labels["foo2"] = "bar" _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceSpecIsUpdated(ctx, cli, serviceID, service.Version.Index), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar", "foo2": "bar"})) delete(service.Spec.Labels, "foo2") _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceSpecIsUpdated(ctx, cli, serviceID, service.Version.Index), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) delete(service.Spec.Labels, "foo") _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceSpecIsUpdated(ctx, cli, serviceID, service.Version.Index), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{})) // now make sure we can add again service.Spec.Labels["foo"] = "bar" _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceSpecIsUpdated(cli, serviceID, service.Version.Index), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceSpecIsUpdated(ctx, cli, serviceID, service.Version.Index), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.DeepEqual(service.Spec.Labels, map[string]string{"foo": "bar"})) - err = cli.ServiceRemove(context.Background(), serviceID) + err = cli.ServiceRemove(ctx, serviceID) assert.NilError(t, err) } func TestServiceUpdateSecrets(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) cli := d.NewClientT(t) defer cli.Close() - ctx := context.Background() secretName := "TestSecret_" + t.Name() secretTarget := "targetName" resp, err := cli.SecretCreate(ctx, swarmtypes.SecretSpec{ @@ -94,8 +95,8 @@ func TestServiceUpdateSecrets(t *testing.T) { assert.Check(t, resp.ID != "") serviceName := "TestService_" + t.Name() - serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) - service := getService(t, cli, serviceID) + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithName(serviceName)) + service := getService(ctx, t, cli, serviceID) // add secret service.Spec.TaskTemplate.ContainerSpec.Secrets = append(service.Spec.TaskTemplate.ContainerSpec.Secrets, @@ -112,9 +113,9 @@ func TestServiceUpdateSecrets(t *testing.T) { ) _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) + poll.WaitOn(t, serviceIsUpdated(ctx, cli, serviceID), swarm.ServicePoll) - service = getService(t, cli, serviceID) + service = getService(ctx, t, cli, serviceID) secrets := service.Spec.TaskTemplate.ContainerSpec.Secrets assert.Assert(t, is.Equal(1, len(secrets))) @@ -127,23 +128,23 @@ func TestServiceUpdateSecrets(t *testing.T) { service.Spec.TaskTemplate.ContainerSpec.Secrets = []*swarmtypes.SecretReference{} _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceIsUpdated(ctx, cli, serviceID), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Secrets))) - err = cli.ServiceRemove(context.Background(), serviceID) + err = cli.ServiceRemove(ctx, serviceID) assert.NilError(t, err) } func TestServiceUpdateConfigs(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) cli := d.NewClientT(t) defer cli.Close() - ctx := context.Background() configName := "TestConfig_" + t.Name() configTarget := "targetName" resp, err := cli.ConfigCreate(ctx, swarmtypes.ConfigSpec{ @@ -156,8 +157,8 @@ func TestServiceUpdateConfigs(t *testing.T) { assert.Check(t, resp.ID != "") serviceName := "TestService_" + t.Name() - serviceID := swarm.CreateService(t, d, swarm.ServiceWithName(serviceName)) - service := getService(t, cli, serviceID) + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithName(serviceName)) + service := getService(ctx, t, cli, serviceID) // add config service.Spec.TaskTemplate.ContainerSpec.Configs = append(service.Spec.TaskTemplate.ContainerSpec.Configs, @@ -174,9 +175,9 @@ func TestServiceUpdateConfigs(t *testing.T) { ) _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) + poll.WaitOn(t, serviceIsUpdated(ctx, cli, serviceID), swarm.ServicePoll) - service = getService(t, cli, serviceID) + service = getService(ctx, t, cli, serviceID) configs := service.Spec.TaskTemplate.ContainerSpec.Configs assert.Assert(t, is.Equal(1, len(configs))) @@ -189,24 +190,23 @@ func TestServiceUpdateConfigs(t *testing.T) { service.Spec.TaskTemplate.ContainerSpec.Configs = []*swarmtypes.ConfigReference{} _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, serviceIsUpdated(ctx, cli, serviceID), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) assert.Check(t, is.Equal(0, len(service.Spec.TaskTemplate.ContainerSpec.Configs))) - err = cli.ServiceRemove(context.Background(), serviceID) + err = cli.ServiceRemove(ctx, serviceID) assert.NilError(t, err) } func TestServiceUpdateNetwork(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType != "linux") - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) cli := d.NewClientT(t) defer cli.Close() - ctx := context.Background() - // Create a overlay network testNet := "testNet" + t.Name() overlayID := network.CreateNoError(ctx, t, cli, testNet, @@ -215,13 +215,13 @@ func TestServiceUpdateNetwork(t *testing.T) { var instances uint64 = 1 // Create service with the overlay network serviceName := "TestServiceUpdateNetworkRM_" + t.Name() - serviceID := swarm.CreateService(t, d, + serviceID := swarm.CreateService(ctx, t, d, swarm.ServiceWithReplicas(instances), swarm.ServiceWithName(serviceName), swarm.ServiceWithNetwork(testNet)) - poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, instances), swarm.ServicePoll) - service := getService(t, cli, serviceID) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, cli, serviceID, instances), swarm.ServicePoll) + service := getService(ctx, t, cli, serviceID) netInfo, err := cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{ Verbose: true, Scope: "swarm", @@ -233,7 +233,7 @@ func TestServiceUpdateNetwork(t *testing.T) { service.Spec.TaskTemplate.Networks = []swarmtypes.NetworkAttachmentConfig{} _, err = cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) + poll.WaitOn(t, serviceIsUpdated(ctx, cli, serviceID), swarm.ServicePoll) netInfo, err = cli.NetworkInspect(ctx, testNet, types.NetworkInspectOptions{ Verbose: true, @@ -279,22 +279,24 @@ func TestServiceUpdatePidsLimit(t *testing.T) { }, } - defer setupTest(t)() - d := swarm.NewSwarm(t, testEnv) + ctx := setupTest(t) + + d := swarm.NewSwarm(ctx, t, testEnv) defer d.Stop(t) cli := d.NewClientT(t) defer func() { _ = cli.Close() }() - ctx := context.Background() var ( serviceID string service swarmtypes.Service ) for i, tc := range tests { + tc := tc t.Run(tc.name, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) if i == 0 { - serviceID = swarm.CreateService(t, d, swarm.ServiceWithPidsLimit(tc.pidsLimit)) + serviceID = swarm.CreateService(ctx, t, d, swarm.ServiceWithPidsLimit(tc.pidsLimit)) } else { - service = getService(t, cli, serviceID) + service = getService(ctx, t, cli, serviceID) if service.Spec.TaskTemplate.Resources == nil { service.Spec.TaskTemplate.Resources = &swarmtypes.ResourceRequirements{} } @@ -304,11 +306,11 @@ func TestServiceUpdatePidsLimit(t *testing.T) { service.Spec.TaskTemplate.Resources.Limits.Pids = tc.pidsLimit _, err := cli.ServiceUpdate(ctx, serviceID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) - poll.WaitOn(t, serviceIsUpdated(cli, serviceID), swarm.ServicePoll) + poll.WaitOn(t, serviceIsUpdated(ctx, cli, serviceID), swarm.ServicePoll) } - poll.WaitOn(t, swarm.RunningTasksCount(cli, serviceID, 1), swarm.ServicePoll) - service = getService(t, cli, serviceID) + poll.WaitOn(t, swarm.RunningTasksCount(ctx, cli, serviceID, 1), swarm.ServicePoll) + service = getService(ctx, t, cli, serviceID) container := getServiceTaskContainer(ctx, t, cli, serviceID) assert.Equal(t, service.Spec.TaskTemplate.Resources.Limits.Pids, tc.expected) if tc.expected == 0 { @@ -343,16 +345,16 @@ func getServiceTaskContainer(ctx context.Context, t *testing.T, cli client.APICl return ctr } -func getService(t *testing.T, cli client.ServiceAPIClient, serviceID string) swarmtypes.Service { +func getService(ctx context.Context, t *testing.T, cli client.ServiceAPIClient, serviceID string) swarmtypes.Service { t.Helper() - service, _, err := cli.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) + service, _, err := cli.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) assert.NilError(t, err) return service } -func serviceIsUpdated(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result { +func serviceIsUpdated(ctx context.Context, client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { - service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) + service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) switch { case err != nil: return poll.Error(err) @@ -367,9 +369,9 @@ func serviceIsUpdated(client client.ServiceAPIClient, serviceID string) func(log } } -func serviceSpecIsUpdated(client client.ServiceAPIClient, serviceID string, serviceOldVersion uint64) func(log poll.LogT) poll.Result { +func serviceSpecIsUpdated(ctx context.Context, client client.ServiceAPIClient, serviceID string, serviceOldVersion uint64) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { - service, _, err := client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) + service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) switch { case err != nil: return poll.Error(err) diff --git a/integration/session/main_test.go b/integration/session/main_test.go index 766bd512b3..131b359d1f 100644 --- a/integration/session/main_test.go +++ b/integration/session/main_test.go @@ -1,33 +1,55 @@ package session // import "github.com/docker/docker/integration/session" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/session.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { + testEnv.Clean(ctx, t) + }) + return ctx } diff --git a/integration/session/session_test.go b/integration/session/session_test.go index 566469a8c7..fc9c988f30 100644 --- a/integration/session/session_test.go +++ b/integration/session/session_test.go @@ -15,10 +15,10 @@ func TestSessionCreate(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "experimental in older versions") - defer setupTest(t)() + ctx := setupTest(t) daemonHost := req.DaemonHost() - res, body, err := req.Post("/session", + res, body, err := req.Post(ctx, "/session", req.Host(daemonHost), req.With(func(r *http.Request) error { r.Header.Set("X-Docker-Expose-Session-Uuid", "testsessioncreate") // so we don't block default name if something else is using it @@ -36,17 +36,17 @@ func TestSessionCreateWithBadUpgrade(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.39"), "experimental in older versions") - defer setupTest(t)() + ctx := setupTest(t) daemonHost := req.DaemonHost() - res, body, err := req.Post("/session", req.Host(daemonHost)) + res, body, err := req.Post(ctx, "/session", req.Host(daemonHost)) assert.NilError(t, err) assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusBadRequest)) buf, err := req.ReadBody(body) assert.NilError(t, err) assert.Check(t, is.Contains(string(buf), "no upgrade")) - res, body, err = req.Post("/session", + res, body, err = req.Post(ctx, "/session", req.Host(daemonHost), req.With(func(r *http.Request) error { r.Header.Set("Upgrade", "foo") diff --git a/integration/system/cgroupdriver_systemd_test.go b/integration/system/cgroupdriver_systemd_test.go index 4544edffc9..c011e9f1d6 100644 --- a/integration/system/cgroupdriver_systemd_test.go +++ b/integration/system/cgroupdriver_systemd_test.go @@ -1,12 +1,12 @@ package system import ( - "context" "os" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" @@ -32,15 +32,16 @@ func TestCgroupDriverSystemdMemoryLimit(t *testing.T) { skip.If(t, !hasSystemd()) t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) c := d.NewClientT(t) - d.StartWithBusybox(t, "--exec-opt", "native.cgroupdriver=systemd", "--iptables=false") + d.StartWithBusybox(ctx, t, "--exec-opt", "native.cgroupdriver=systemd", "--iptables=false") defer d.Stop(t) const mem = int64(64 * 1024 * 1024) // 64 MB - ctx := context.Background() ctrID := container.Create(ctx, t, c, func(ctr *container.TestContainerConfig) { ctr.HostConfig.Resources.Memory = mem }) diff --git a/integration/system/disk_usage_test.go b/integration/system/disk_usage_test.go index 3d6bd3187d..8a4f9a460b 100644 --- a/integration/system/disk_usage_test.go +++ b/integration/system/disk_usage_test.go @@ -1,12 +1,12 @@ package system // import "github.com/docker/docker/integration/system" import ( - "context" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/volume" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/skip" @@ -17,14 +17,14 @@ func TestDiskUsage(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) defer d.Cleanup(t) d.Start(t, "--iptables=false") defer d.Stop(t) client := d.NewClientT(t) - ctx := context.Background() - var stepDU types.DiskUsage for _, step := range []struct { doc string @@ -47,7 +47,7 @@ func TestDiskUsage(t *testing.T) { { doc: "after LoadBusybox", next: func(t *testing.T, _ types.DiskUsage) types.DiskUsage { - d.LoadBusybox(t) + d.LoadBusybox(ctx, t) du, err := client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.NilError(t, err) @@ -116,6 +116,7 @@ func TestDiskUsage(t *testing.T) { }, } { t.Run(step.doc, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) stepDU = step.next(t, stepDU) for _, tc := range []struct { @@ -263,6 +264,7 @@ func TestDiskUsage(t *testing.T) { } { tc := tc t.Run(tc.doc, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) // TODO: Run in parallel once https://github.com/moby/moby/pull/42560 is merged. du, err := client.DiskUsage(ctx, tc.options) diff --git a/integration/system/event_test.go b/integration/system/event_test.go index 2e7d81e4d5..8e2237c145 100644 --- a/integration/system/event_test.go +++ b/integration/system/event_test.go @@ -30,8 +30,7 @@ import ( func TestEventsExecDie(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.36"), "broken in earlier versions") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME. Suspect may need to wait until container is running before exec") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) client := testEnv.APIClient() cID := container.Run(ctx, t, client) @@ -78,8 +77,7 @@ func TestEventsExecDie(t *testing.T) { // This test verifies that backward compatibility maintains. func TestEventsBackwardsCompatible(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "Windows doesn't support back-compat messages") - defer setupTest(t)() - ctx := context.Background() + ctx := setupTest(t) client := testEnv.APIClient() since := request.DaemonTime(ctx, t, client, testEnv) @@ -90,7 +88,7 @@ func TestEventsBackwardsCompatible(t *testing.T) { // In case there is no events, the API should have responded immediately (not blocking), // The test here makes sure the response time is less than 3 sec. expectedTime := time.Now().Add(3 * time.Second) - emptyResp, emptyBody, err := req.Get("/events") + emptyResp, emptyBody, err := req.Get(ctx, "/events") assert.NilError(t, err) defer emptyBody.Close() assert.Check(t, is.DeepEqual(http.StatusOK, emptyResp.StatusCode)) @@ -99,7 +97,7 @@ func TestEventsBackwardsCompatible(t *testing.T) { // We also test to make sure the `events.Message` is compatible with `JSONMessage` q := url.Values{} q.Set("since", ts) - _, body, err := req.Get("/events?" + q.Encode()) + _, body, err := req.Get(ctx, "/events?"+q.Encode()) assert.NilError(t, err) defer body.Close() @@ -130,8 +128,8 @@ func TestEventsBackwardsCompatible(t *testing.T) { func TestEventsVolumeCreate(t *testing.T) { skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME: Windows doesn't trigger the events? Could be a race") - defer setupTest(t)() - ctx, cancel := context.WithCancel(context.Background()) + ctx := setupTest(t) + ctx, cancel := context.WithCancel(ctx) defer cancel() client := testEnv.APIClient() diff --git a/integration/system/info_linux_test.go b/integration/system/info_linux_test.go index 6d31bab289..6c4430337f 100644 --- a/integration/system/info_linux_test.go +++ b/integration/system/info_linux_test.go @@ -3,20 +3,20 @@ package system // import "github.com/docker/docker/integration/system" import ( - "context" "net/http" "testing" + "github.com/docker/docker/testutil" req "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) func TestInfoBinaryCommits(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - info, err := client.Info(context.Background()) + info, err := client.Info(ctx) assert.NilError(t, err) assert.Check(t, "N/A" != info.ContainerdCommit.ID) @@ -30,9 +30,10 @@ func TestInfoBinaryCommits(t *testing.T) { } func TestInfoAPIVersioned(t *testing.T) { + ctx := testutil.StartSpan(baseContext, t) // Windows only supports 1.25 or later - res, body, err := req.Get("/v1.20/info") + res, body, err := req.Get(ctx, "/v1.20/info") assert.NilError(t, err) assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusOK)) diff --git a/integration/system/info_test.go b/integration/system/info_test.go index d9992c00f7..a4a9a2485b 100644 --- a/integration/system/info_test.go +++ b/integration/system/info_test.go @@ -1,12 +1,12 @@ package system // import "github.com/docker/docker/integration/system" import ( - "context" "fmt" "sort" "testing" "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -14,10 +14,10 @@ import ( ) func TestInfoAPI(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - info, err := client.Info(context.Background()) + info, err := client.Info(ctx) assert.NilError(t, err) // always shown fields @@ -49,13 +49,16 @@ func TestInfoAPI(t *testing.T) { func TestInfoAPIWarnings(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME") + + ctx := testutil.StartSpan(baseContext, t) + d := daemon.New(t) c := d.NewClientT(t) d.Start(t, "-H=0.0.0.0:23756", "-H="+d.Sock()) defer d.Stop(t) - info, err := c.Info(context.Background()) + info, err := c.Info(ctx) assert.NilError(t, err) stringsToCheck := []string{ @@ -73,6 +76,8 @@ func TestInfoDebug(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "FIXME: test starts daemon with -H unix://.....") + _ = testutil.StartSpan(baseContext, t) + d := daemon.New(t) d.Start(t, "--debug") defer d.Stop(t) diff --git a/integration/system/login_test.go b/integration/system/login_test.go index a47e593416..1eb5f9ee8c 100644 --- a/integration/system/login_test.go +++ b/integration/system/login_test.go @@ -1,7 +1,6 @@ package system // import "github.com/docker/docker/integration/system" import ( - "context" "fmt" "testing" @@ -17,14 +16,14 @@ import ( func TestLoginFailsWithBadCredentials(t *testing.T) { skip.If(t, !requirement.HasHubConnectivity(t)) - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() config := registry.AuthConfig{ Username: "no-user", Password: "no-password", } - _, err := client.RegistryLogin(context.Background(), config) + _, err := client.RegistryLogin(ctx, config) assert.Assert(t, err != nil) assert.Check(t, is.ErrorContains(err, "unauthorized: incorrect username or password")) assert.Check(t, is.ErrorContains(err, fmt.Sprintf("https://%s/v2/", registrypkg.DefaultRegistryHost))) diff --git a/integration/system/main_test.go b/integration/system/main_test.go index 6dd4761cd5..1a2dbffbdc 100644 --- a/integration/system/main_test.go +++ b/integration/system/main_test.go @@ -1,33 +1,55 @@ package system // import "github.com/docker/docker/integration/system" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/system.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { + testEnv.Clean(ctx, t) + }) + return ctx } diff --git a/integration/system/ping_test.go b/integration/system/ping_test.go index 9636eaf1b6..1738087132 100644 --- a/integration/system/ping_test.go +++ b/integration/system/ping_test.go @@ -1,7 +1,6 @@ package system // import "github.com/docker/docker/integration/system" import ( - "context" "net/http" "os" "path/filepath" @@ -12,6 +11,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/request" "gotest.tools/v3/assert" @@ -20,9 +20,9 @@ import ( func TestPingCacheHeaders(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "skip test from new feature") - defer setupTest(t)() + ctx := setupTest(t) - res, _, err := request.Get("/_ping") + res, _, err := request.Get(ctx, "/_ping") assert.NilError(t, err) assert.Equal(t, res.StatusCode, http.StatusOK) @@ -31,9 +31,9 @@ func TestPingCacheHeaders(t *testing.T) { } func TestPingGet(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) - res, body, err := request.Get("/_ping") + res, body, err := request.Get(ctx, "/_ping") assert.NilError(t, err) b, err := request.ReadBody(body) @@ -45,9 +45,9 @@ func TestPingGet(t *testing.T) { func TestPingHead(t *testing.T) { skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.40"), "skip test from new feature") - defer setupTest(t)() + ctx := setupTest(t) - res, body, err := request.Head("/_ping") + res, body, err := request.Head(ctx, "/_ping") assert.NilError(t, err) b, err := request.ReadBody(body) @@ -61,15 +61,15 @@ func TestPingSwarmHeader(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows") - defer setupTest(t)() + ctx := setupTest(t) d := daemon.New(t) d.Start(t) defer d.Stop(t) client := d.NewClientT(t) defer client.Close() - ctx := context.TODO() t.Run("before swarm init", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) p, err := client.Ping(ctx) assert.NilError(t, err) assert.Equal(t, p.SwarmStatus.NodeState, swarm.LocalNodeStateInactive) @@ -80,6 +80,7 @@ func TestPingSwarmHeader(t *testing.T) { assert.NilError(t, err) t.Run("after swarm init", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) p, err := client.Ping(ctx) assert.NilError(t, err) assert.Equal(t, p.SwarmStatus.NodeState, swarm.LocalNodeStateActive) @@ -90,6 +91,7 @@ func TestPingSwarmHeader(t *testing.T) { assert.NilError(t, err) t.Run("after swarm leave", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) p, err := client.Ping(ctx) assert.NilError(t, err) assert.Equal(t, p.SwarmStatus.NodeState, swarm.LocalNodeStateInactive) @@ -101,13 +103,13 @@ func TestPingBuilderHeader(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon) skip.If(t, testEnv.DaemonInfo.OSType == "windows", "cannot spin up additional daemons on windows") - defer setupTest(t)() + ctx := setupTest(t) d := daemon.New(t) client := d.NewClientT(t) defer client.Close() - ctx := context.TODO() t.Run("default config", func(t *testing.T) { + testutil.StartSpan(ctx, t) d.Start(t) defer d.Stop(t) @@ -122,6 +124,7 @@ func TestPingBuilderHeader(t *testing.T) { }) t.Run("buildkit disabled", func(t *testing.T) { + testutil.StartSpan(ctx, t) cfg := filepath.Join(d.RootDir(), "daemon.json") err := os.WriteFile(cfg, []byte(`{"features": { "buildkit": false }}`), 0o644) assert.NilError(t, err) diff --git a/integration/system/version_test.go b/integration/system/version_test.go index e78b201da8..7390041f69 100644 --- a/integration/system/version_test.go +++ b/integration/system/version_test.go @@ -1,7 +1,6 @@ package system // import "github.com/docker/docker/integration/system" import ( - "context" "testing" "gotest.tools/v3/assert" @@ -9,10 +8,10 @@ import ( ) func TestVersion(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - version, err := client.ServerVersion(context.Background()) + version, err := client.ServerVersion(ctx) assert.NilError(t, err) assert.Check(t, version.APIVersion != "") diff --git a/integration/volume/main_test.go b/integration/volume/main_test.go index e3e9935207..5f404912e8 100644 --- a/integration/volume/main_test.go +++ b/integration/volume/main_test.go @@ -1,33 +1,55 @@ package volume // import "github.com/docker/docker/integration/volume" import ( - "fmt" + "context" "os" "testing" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/environment" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/codes" ) -var testEnv *environment.Execution +var ( + testEnv *environment.Execution + baseContext context.Context +) func TestMain(m *testing.M) { + shutdown := testutil.ConfigureTracing() + ctx, span := otel.Tracer("").Start(context.Background(), "integration/volume.TestMain") + baseContext = ctx + var err error - testEnv, err = environment.New() + testEnv, err = environment.New(ctx) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - err = environment.EnsureFrozenImagesLinux(testEnv) + err = environment.EnsureFrozenImagesLinux(ctx, testEnv) if err != nil { - fmt.Println(err) - os.Exit(1) + span.SetStatus(codes.Error, err.Error()) + span.End() + shutdown(ctx) + panic(err) } - testEnv.Print() - os.Exit(m.Run()) + code := m.Run() + if code != 0 { + span.SetStatus(codes.Error, "m.Run() exited with non-zero code") + } + shutdown(ctx) + os.Exit(code) } -func setupTest(t *testing.T) func() { - environment.ProtectAll(t, testEnv) - return func() { testEnv.Clean(t) } +func setupTest(t *testing.T) context.Context { + ctx := testutil.StartSpan(baseContext, t) + environment.ProtectAll(ctx, t, testEnv) + t.Cleanup(func() { + testEnv.Clean(ctx, t) + }) + return ctx } diff --git a/integration/volume/volume_test.go b/integration/volume/volume_test.go index c5836d0121..6de70e3f26 100644 --- a/integration/volume/volume_test.go +++ b/integration/volume/volume_test.go @@ -1,7 +1,6 @@ package volume import ( - "context" "net/http" "os" "path/filepath" @@ -16,6 +15,7 @@ import ( "github.com/docker/docker/errdefs" "github.com/docker/docker/integration/internal/build" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/testutil" "github.com/docker/docker/testutil/daemon" "github.com/docker/docker/testutil/fakecontext" "github.com/docker/docker/testutil/request" @@ -26,9 +26,8 @@ import ( ) func TestVolumesCreateAndList(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() name := t.Name() // Windows file system is case insensitive @@ -67,9 +66,8 @@ func TestVolumesCreateAndList(t *testing.T) { } func TestVolumesRemove(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() prefix, slash := getPrefixAndSlashFromDaemonPlatform() @@ -114,16 +112,15 @@ func TestVolumesRemoveSwarmEnabled(t *testing.T) { skip.If(t, testEnv.IsRemoteDaemon, "cannot run daemon when remote daemon") skip.If(t, testEnv.DaemonInfo.OSType == "windows", "TODO enable on windows") t.Parallel() - defer setupTest(t)() + ctx := setupTest(t) // Spin up a new daemon, so that we can run this test in parallel (it's a slow test) d := daemon.New(t) - d.StartAndSwarmInit(t) + d.StartAndSwarmInit(ctx, t) defer d.Stop(t) client := d.NewClientT(t) - ctx := context.Background() prefix, slash := getPrefixAndSlashFromDaemonPlatform() id := container.Create(ctx, t, client, container.WithVolume(prefix+slash+"foo")) @@ -159,9 +156,8 @@ func TestVolumesRemoveSwarmEnabled(t *testing.T) { } func TestVolumesInspect(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() now := time.Now() vol, err := client.VolumeCreate(ctx, volume.CreateOptions{}) @@ -196,7 +192,7 @@ func TestVolumesInspect(t *testing.T) { // TestVolumesInvalidJSON tests that POST endpoints that expect a body return // the correct error when sending invalid JSON requests. func TestVolumesInvalidJSON(t *testing.T) { - t.Cleanup(setupTest(t)) + ctx := setupTest(t) // POST endpoints that accept / expect a JSON body; endpoints := []string{"/volumes/create"} @@ -205,9 +201,11 @@ func TestVolumesInvalidJSON(t *testing.T) { ep := ep t.Run(ep[1:], func(t *testing.T) { t.Parallel() + ctx := testutil.StartSpan(ctx, t) t.Run("invalid content type", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{}"), request.ContentType("text/plain")) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{}"), request.ContentType("text/plain")) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -217,7 +215,8 @@ func TestVolumesInvalidJSON(t *testing.T) { }) t.Run("invalid JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString("{invalid json"), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString("{invalid json"), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -227,7 +226,8 @@ func TestVolumesInvalidJSON(t *testing.T) { }) t.Run("extra content after JSON", func(t *testing.T) { - res, body, err := request.Post(ep, request.RawString(`{} trailing content`), request.JSON) + ctx := testutil.StartSpan(ctx, t) + res, body, err := request.Post(ctx, ep, request.RawString(`{} trailing content`), request.JSON) assert.NilError(t, err) assert.Check(t, is.Equal(res.StatusCode, http.StatusBadRequest)) @@ -237,10 +237,11 @@ func TestVolumesInvalidJSON(t *testing.T) { }) t.Run("empty body", func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) // empty body should not produce an 500 internal server error, or // any 5XX error (this is assuming the request does not produce // an internal server error for another reason, but it shouldn't) - res, _, err := request.Post(ep, request.RawString(``), request.JSON) + res, _, err := request.Post(ctx, ep, request.RawString(``), request.JSON) assert.NilError(t, err) assert.Check(t, res.StatusCode < http.StatusInternalServerError) }) @@ -256,10 +257,9 @@ func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) { } func TestVolumePruneAnonymous(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() - ctx := context.Background() // Create an anonymous volume v, err := client.VolumeCreate(ctx, volume.CreateOptions{}) @@ -307,7 +307,7 @@ func TestVolumePruneAnonymous(t *testing.T) { } func TestVolumePruneAnonFromImage(t *testing.T) { - defer setupTest(t)() + ctx := setupTest(t) client := testEnv.APIClient() volDest := "/foo" @@ -318,7 +318,6 @@ func TestVolumePruneAnonFromImage(t *testing.T) { dockerfile := `FROM busybox VOLUME ` + volDest - ctx := context.Background() img := build.Do(ctx, t, client, fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile))) id := container.Create(ctx, t, client, container.WithImage(img)) diff --git a/internal/test/suite/interfaces.go b/internal/test/suite/interfaces.go index 263de86ab8..2bbaa17f1e 100644 --- a/internal/test/suite/interfaces.go +++ b/internal/test/suite/interfaces.go @@ -1,29 +1,32 @@ package suite -import "testing" +import ( + "context" + "testing" +) // SetupAllSuite has a SetupSuite method, which will run before the // tests in the suite are run. type SetupAllSuite interface { - SetUpSuite(t *testing.T) + SetUpSuite(context.Context, *testing.T) } // SetupTestSuite has a SetupTest method, which will run before each // test in the suite. type SetupTestSuite interface { - SetUpTest(t *testing.T) + SetUpTest(context.Context, *testing.T) } // TearDownAllSuite has a TearDownSuite method, which will run after // all the tests in the suite have been run. type TearDownAllSuite interface { - TearDownSuite(t *testing.T) + TearDownSuite(context.Context, *testing.T) } // TearDownTestSuite has a TearDownTest method, which will run after // each test in the suite. type TearDownTestSuite interface { - TearDownTest(t *testing.T) + TearDownTest(context.Context, *testing.T) } // TimeoutTestSuite has a OnTimeout method, which will run after diff --git a/internal/test/suite/suite.go b/internal/test/suite/suite.go index edb6e40c1c..318aae6a70 100644 --- a/internal/test/suite/suite.go +++ b/internal/test/suite/suite.go @@ -3,11 +3,14 @@ package suite import ( + "context" "flag" "reflect" "runtime/debug" "strings" "testing" + + "github.com/docker/docker/testutil" ) // TimeoutFlag is the flag to set a per-test timeout when running tests. Defaults to `-timeout`. @@ -16,15 +19,18 @@ var TimeoutFlag = flag.Duration("timeout", 0, "DO NOT USE") var typTestingT = reflect.TypeOf(new(testing.T)) // Run takes a testing suite and runs all of the tests attached to it. -func Run(t *testing.T, suite interface{}) { +func Run(ctx context.Context, t *testing.T, suite interface{}) { defer failOnPanic(t) + ctx = testutil.StartSpan(ctx, t) + suiteCtx := ctx + suiteSetupDone := false defer func() { if suiteSetupDone { - if tearDownAllSuite, ok := suite.(TearDownAllSuite); ok { - tearDownAllSuite.TearDownSuite(t) + if tearDownAllSuite, ok := getTeardownAllSuite(suite); ok { + tearDownAllSuite.TearDownSuite(suiteCtx, t) } } }() @@ -36,21 +42,27 @@ func Run(t *testing.T, suite interface{}) { continue } t.Run(method.Name, func(t *testing.T) { + ctx := testutil.StartSpan(ctx, t) + testutil.SetContext(t, ctx) + t.Cleanup(func() { + testutil.CleanupContext(t) + }) + defer failOnPanic(t) if !suiteSetupDone { - if setupAllSuite, ok := suite.(SetupAllSuite); ok { - setupAllSuite.SetUpSuite(t) + if setupAllSuite, ok := getSetupAllSuite(suite); ok { + setupAllSuite.SetUpSuite(suiteCtx, t) } suiteSetupDone = true } - if setupTestSuite, ok := suite.(SetupTestSuite); ok { - setupTestSuite.SetUpTest(t) + if setupTestSuite, ok := getSetupTestSuite(suite); ok { + setupTestSuite.SetUpTest(ctx, t) } defer func() { - if tearDownTestSuite, ok := suite.(TearDownTestSuite); ok { - tearDownTestSuite.TearDownTest(t) + if tearDownTestSuite, ok := getTearDownTestSuite(suite); ok { + tearDownTestSuite.TearDownTest(ctx, t) } }() @@ -59,6 +71,66 @@ func Run(t *testing.T, suite interface{}) { } } +func getSetupAllSuite(suite interface{}) (SetupAllSuite, bool) { + setupAllSuite, ok := suite.(SetupAllSuite) + if ok { + return setupAllSuite, ok + } + + t := reflect.TypeOf(suite) + for i := 0; i < t.NumMethod(); i++ { + if t.Method(i).Name == "SetUpSuite" { + panic("Wrong SetUpSuite signature") + } + } + return nil, false +} + +func getSetupTestSuite(suite interface{}) (SetupTestSuite, bool) { + setupAllTest, ok := suite.(SetupTestSuite) + if ok { + return setupAllTest, ok + } + + t := reflect.TypeOf(suite) + for i := 0; i < t.NumMethod(); i++ { + if t.Method(i).Name == "SetUpTest" { + panic("Wrong SetUpTest signature") + } + } + return nil, false +} + +func getTearDownTestSuite(suite interface{}) (TearDownTestSuite, bool) { + tearDownTest, ok := suite.(TearDownTestSuite) + if ok { + return tearDownTest, ok + } + + t := reflect.TypeOf(suite) + for i := 0; i < t.NumMethod(); i++ { + if t.Method(i).Name == "TearDownTest" { + panic("Wrong TearDownTest signature") + } + } + return nil, false +} + +func getTeardownAllSuite(suite interface{}) (TearDownAllSuite, bool) { + tearDownAll, ok := suite.(TearDownAllSuite) + if ok { + return tearDownAll, ok + } + + t := reflect.TypeOf(suite) + for i := 0; i < t.NumMethod(); i++ { + if t.Method(i).Name == "TearDownSuite" { + panic("Wrong TearDownSuite signature") + } + } + return nil, false +} + func failOnPanic(t *testing.T) { r := recover() if r != nil { diff --git a/testutil/daemon/container.go b/testutil/daemon/container.go index 8e88e7b202..42dafe7f5c 100644 --- a/testutil/daemon/container.go +++ b/testutil/daemon/container.go @@ -9,7 +9,7 @@ import ( ) // ActiveContainers returns the list of ids of the currently running containers -func (d *Daemon) ActiveContainers(t testing.TB) []string { +func (d *Daemon) ActiveContainers(ctx context.Context, t testing.TB) []string { t.Helper() cli := d.NewClientT(t) defer cli.Close() diff --git a/testutil/daemon/daemon.go b/testutil/daemon/daemon.go index dedda286d8..65b9cba62e 100644 --- a/testutil/daemon/daemon.go +++ b/testutil/daemon/daemon.go @@ -496,6 +496,7 @@ func (d *Daemon) StartWithLogFile(out *os.File, providedArgs ...string) error { cmd := exec.Command(dockerdBinary, d.args...) cmd.Env = append(os.Environ(), "DOCKER_SERVICE_PREFER_OFFLINE_IMAGE=1") cmd.Env = append(cmd.Env, d.extraEnv...) + cmd.Env = append(cmd.Env, "OTEL_SERVICE_NAME=dockerd-"+d.id) cmd.Stdout = out cmd.Stderr = out d.logFile = out @@ -581,10 +582,10 @@ 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 testing.TB, arg ...string) { +func (d *Daemon) StartWithBusybox(ctx context.Context, t testing.TB, arg ...string) { t.Helper() d.Start(t, arg...) - d.LoadBusybox(t) + d.LoadBusybox(ctx, t) } // Kill will send a SIGKILL to the daemon @@ -764,7 +765,7 @@ func (d *Daemon) ReloadConfig() error { errCh := make(chan error, 1) started := make(chan struct{}) go func() { - _, body, err := request.Get("/events", request.Host(d.Sock())) + _, body, err := request.Get(context.TODO(), "/events", request.Host(d.Sock())) close(started) if err != nil { errCh <- err @@ -805,13 +806,12 @@ func (d *Daemon) ReloadConfig() error { } // LoadBusybox image into the daemon -func (d *Daemon) LoadBusybox(t testing.TB) { +func (d *Daemon) LoadBusybox(ctx context.Context, t testing.TB) { t.Helper() clientHost, err := client.NewClientWithOpts(client.FromEnv) assert.NilError(t, err, "[%s] failed to create client", d.id) defer clientHost.Close() - ctx := context.Background() reader, err := clientHost.ImageSave(ctx, []string{"busybox:latest"}) assert.NilError(t, err, "[%s] failed to download busybox", d.id) defer reader.Close() diff --git a/testutil/daemon/node.go b/testutil/daemon/node.go index 89d0817b00..ce3141439c 100644 --- a/testutil/daemon/node.go +++ b/testutil/daemon/node.go @@ -15,12 +15,12 @@ import ( type NodeConstructor func(*swarm.Node) // GetNode returns a swarm node identified by the specified id -func (d *Daemon) GetNode(t testing.TB, id string, errCheck ...func(error) bool) *swarm.Node { +func (d *Daemon) GetNode(ctx context.Context, t testing.TB, id string, errCheck ...func(error) bool) *swarm.Node { t.Helper() cli := d.NewClientT(t) defer cli.Close() - node, _, err := cli.NodeInspectWithRaw(context.Background(), id) + node, _, err := cli.NodeInspectWithRaw(ctx, id) if err != nil { for _, f := range errCheck { if f(err) { @@ -34,7 +34,7 @@ func (d *Daemon) GetNode(t testing.TB, id string, errCheck ...func(error) bool) } // RemoveNode removes the specified node -func (d *Daemon) RemoveNode(t testing.TB, id string, force bool) { +func (d *Daemon) RemoveNode(ctx context.Context, t testing.TB, id string, force bool) { t.Helper() cli := d.NewClientT(t) defer cli.Close() @@ -42,23 +42,23 @@ func (d *Daemon) RemoveNode(t testing.TB, id string, force bool) { options := types.NodeRemoveOptions{ Force: force, } - err := cli.NodeRemove(context.Background(), id, options) + err := cli.NodeRemove(ctx, id, options) assert.NilError(t, err) } // UpdateNode updates a swarm node with the specified node constructor -func (d *Daemon) UpdateNode(t testing.TB, id string, f ...NodeConstructor) { +func (d *Daemon) UpdateNode(ctx context.Context, t testing.TB, id string, f ...NodeConstructor) { t.Helper() cli := d.NewClientT(t) defer cli.Close() for i := 0; ; i++ { - node := d.GetNode(t, id) + node := d.GetNode(ctx, t, id) for _, fn := range f { fn(node) } - err := cli.NodeUpdate(context.Background(), node.ID, node.Version, node.Spec) + err := cli.NodeUpdate(ctx, node.ID, node.Version, node.Spec) if i < 10 && err != nil && strings.Contains(err.Error(), "update out of sequence") { time.Sleep(100 * time.Millisecond) continue @@ -69,12 +69,12 @@ func (d *Daemon) UpdateNode(t testing.TB, id string, f ...NodeConstructor) { } // ListNodes returns the list of the current swarm nodes -func (d *Daemon) ListNodes(t testing.TB) []swarm.Node { +func (d *Daemon) ListNodes(ctx context.Context, t testing.TB) []swarm.Node { t.Helper() cli := d.NewClientT(t) defer cli.Close() - nodes, err := cli.NodeList(context.Background(), types.NodeListOptions{}) + nodes, err := cli.NodeList(ctx, types.NodeListOptions{}) assert.NilError(t, err) return nodes diff --git a/testutil/daemon/service.go b/testutil/daemon/service.go index 9ec1c66aa5..83501c8edf 100644 --- a/testutil/daemon/service.go +++ b/testutil/daemon/service.go @@ -14,7 +14,7 @@ import ( // ServiceConstructor defines a swarm service constructor function type ServiceConstructor func(*swarm.Service) -func (d *Daemon) createServiceWithOptions(t testing.TB, opts types.ServiceCreateOptions, f ...ServiceConstructor) string { +func (d *Daemon) createServiceWithOptions(ctx context.Context, t testing.TB, opts types.ServiceCreateOptions, f ...ServiceConstructor) string { t.Helper() var service swarm.Service for _, fn := range f { @@ -24,7 +24,7 @@ func (d *Daemon) createServiceWithOptions(t testing.TB, opts types.ServiceCreate cli := d.NewClientT(t) defer cli.Close() - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() res, err := cli.ServiceCreate(ctx, service.Spec, opts) @@ -33,24 +33,24 @@ func (d *Daemon) createServiceWithOptions(t testing.TB, opts types.ServiceCreate } // CreateService creates a swarm service given the specified service constructor -func (d *Daemon) CreateService(t testing.TB, f ...ServiceConstructor) string { +func (d *Daemon) CreateService(ctx context.Context, t testing.TB, f ...ServiceConstructor) string { t.Helper() - return d.createServiceWithOptions(t, types.ServiceCreateOptions{}, f...) + return d.createServiceWithOptions(ctx, t, types.ServiceCreateOptions{}, f...) } // GetService returns the swarm service corresponding to the specified id -func (d *Daemon) GetService(t testing.TB, id string) *swarm.Service { +func (d *Daemon) GetService(ctx context.Context, t testing.TB, id string) *swarm.Service { t.Helper() cli := d.NewClientT(t) defer cli.Close() - service, _, err := cli.ServiceInspectWithRaw(context.Background(), id, types.ServiceInspectOptions{}) + service, _, err := cli.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{}) assert.NilError(t, err) return &service } // GetServiceTasks returns the swarm tasks for the specified service -func (d *Daemon) GetServiceTasks(t testing.TB, service string, additionalFilters ...filters.KeyValuePair) []swarm.Task { +func (d *Daemon) GetServiceTasks(ctx context.Context, t testing.TB, service string, additionalFilters ...filters.KeyValuePair) []swarm.Task { t.Helper() cli := d.NewClientT(t) defer cli.Close() @@ -67,13 +67,13 @@ func (d *Daemon) GetServiceTasks(t testing.TB, service string, additionalFilters Filters: filterArgs, } - tasks, err := cli.TaskList(context.Background(), options) + tasks, err := cli.TaskList(ctx, options) assert.NilError(t, err) return tasks } // UpdateService updates a swarm service with the specified service constructor -func (d *Daemon) UpdateService(t testing.TB, service *swarm.Service, f ...ServiceConstructor) { +func (d *Daemon) UpdateService(ctx context.Context, t testing.TB, service *swarm.Service, f ...ServiceConstructor) { t.Helper() cli := d.NewClientT(t) defer cli.Close() @@ -82,38 +82,38 @@ func (d *Daemon) UpdateService(t testing.TB, service *swarm.Service, f ...Servic fn(service) } - _, err := cli.ServiceUpdate(context.Background(), service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) + _, err := cli.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) assert.NilError(t, err) } // RemoveService removes the specified service -func (d *Daemon) RemoveService(t testing.TB, id string) { +func (d *Daemon) RemoveService(ctx context.Context, t testing.TB, id string) { t.Helper() cli := d.NewClientT(t) defer cli.Close() - err := cli.ServiceRemove(context.Background(), id) + err := cli.ServiceRemove(ctx, id) assert.NilError(t, err) } // ListServices returns the list of the current swarm services -func (d *Daemon) ListServices(t testing.TB) []swarm.Service { +func (d *Daemon) ListServices(ctx context.Context, t testing.TB) []swarm.Service { t.Helper() cli := d.NewClientT(t) defer cli.Close() - services, err := cli.ServiceList(context.Background(), types.ServiceListOptions{}) + services, err := cli.ServiceList(ctx, types.ServiceListOptions{}) assert.NilError(t, err) return services } // GetTask returns the swarm task identified by the specified id -func (d *Daemon) GetTask(t testing.TB, id string) swarm.Task { +func (d *Daemon) GetTask(ctx context.Context, t testing.TB, id string) swarm.Task { t.Helper() cli := d.NewClientT(t) defer cli.Close() - task, _, err := cli.TaskInspectWithRaw(context.Background(), id) + task, _, err := cli.TaskInspectWithRaw(ctx, id) assert.NilError(t, err) return task } diff --git a/testutil/daemon/swarm.go b/testutil/daemon/swarm.go index bbdc27c84a..71ca715171 100644 --- a/testutil/daemon/swarm.go +++ b/testutil/daemon/swarm.go @@ -25,9 +25,9 @@ func (d *Daemon) StartNode(t testing.TB) { } // StartNodeWithBusybox starts daemon to be used as a swarm node, and loads the busybox image -func (d *Daemon) StartNodeWithBusybox(t testing.TB) { +func (d *Daemon) StartNodeWithBusybox(ctx context.Context, t testing.TB) { t.Helper() - d.StartWithBusybox(t, startArgs...) + d.StartWithBusybox(ctx, t, startArgs...) } // RestartNode restarts a daemon to be used as a swarm node @@ -39,15 +39,15 @@ func (d *Daemon) RestartNode(t testing.TB) { } // StartAndSwarmInit starts the daemon (with busybox) and init the swarm -func (d *Daemon) StartAndSwarmInit(t testing.TB) { - d.StartNodeWithBusybox(t) - d.SwarmInit(t, swarm.InitRequest{}) +func (d *Daemon) StartAndSwarmInit(ctx context.Context, t testing.TB) { + d.StartNodeWithBusybox(ctx, t) + d.SwarmInit(ctx, t, swarm.InitRequest{}) } // StartAndSwarmJoin starts the daemon (with busybox) and join the specified swarm as worker or manager -func (d *Daemon) StartAndSwarmJoin(t testing.TB, leader *Daemon, manager bool) { +func (d *Daemon) StartAndSwarmJoin(ctx context.Context, t testing.TB, leader *Daemon, manager bool) { t.Helper() - d.StartNodeWithBusybox(t) + d.StartNodeWithBusybox(ctx, t) tokens := leader.JoinTokens(t) token := tokens.Worker @@ -55,7 +55,7 @@ func (d *Daemon) StartAndSwarmJoin(t testing.TB, leader *Daemon, manager bool) { token = tokens.Manager } t.Logf("[%s] joining swarm manager [%s]@%s, swarm listen addr %s", d.id, leader.id, leader.SwarmListenAddr(), d.SwarmListenAddr()) - d.SwarmJoin(t, swarm.JoinRequest{ + d.SwarmJoin(ctx, t, swarm.JoinRequest{ RemoteAddrs: []string{leader.SwarmListenAddr()}, JoinToken: token, }) @@ -75,7 +75,7 @@ func (d *Daemon) NodeID() string { } // SwarmInit initializes a new swarm cluster. -func (d *Daemon) SwarmInit(t testing.TB, req swarm.InitRequest) { +func (d *Daemon) SwarmInit(ctx context.Context, t testing.TB, req swarm.InitRequest) { t.Helper() if req.ListenAddr == "" { req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort) @@ -89,20 +89,20 @@ func (d *Daemon) SwarmInit(t testing.TB, req swarm.InitRequest) { } cli := d.NewClientT(t) defer cli.Close() - _, err := cli.SwarmInit(context.Background(), req) + _, err := cli.SwarmInit(ctx, req) assert.NilError(t, err, "initializing swarm") d.CachedInfo = d.Info(t) } // SwarmJoin joins a daemon to an existing cluster. -func (d *Daemon) SwarmJoin(t testing.TB, req swarm.JoinRequest) { +func (d *Daemon) SwarmJoin(ctx context.Context, t testing.TB, req swarm.JoinRequest) { t.Helper() if req.ListenAddr == "" { req.ListenAddr = fmt.Sprintf("%s:%d", d.swarmListenAddr, d.SwarmPort) } cli := d.NewClientT(t) defer cli.Close() - err := cli.SwarmJoin(context.Background(), req) + err := cli.SwarmJoin(ctx, req) assert.NilError(t, err, "[%s] joining swarm", d.id) d.CachedInfo = d.Info(t) } @@ -112,17 +112,17 @@ func (d *Daemon) SwarmJoin(t testing.TB, req swarm.JoinRequest) { // The passed in testing.TB is only used to validate that the client was successfully created // Some tests rely on error checking the result of the actual unlock, so allow // the error to be returned. -func (d *Daemon) SwarmLeave(t testing.TB, force bool) error { +func (d *Daemon) SwarmLeave(ctx context.Context, t testing.TB, force bool) error { cli := d.NewClientT(t) defer cli.Close() - return cli.SwarmLeave(context.Background(), force) + return cli.SwarmLeave(ctx, force) } // SwarmInfo returns the swarm information of the daemon -func (d *Daemon) SwarmInfo(t testing.TB) swarm.Info { +func (d *Daemon) SwarmInfo(ctx context.Context, t testing.TB) swarm.Info { t.Helper() cli := d.NewClientT(t) - info, err := cli.Info(context.Background()) + info, err := cli.Info(ctx) assert.NilError(t, err, "get swarm info") return info.Swarm } diff --git a/testutil/environment/clean.go b/testutil/environment/clean.go index 10d7607d19..8e591ba05e 100644 --- a/testutil/environment/clean.go +++ b/testutil/environment/clean.go @@ -11,32 +11,36 @@ import ( "github.com/docker/docker/api/types/volume" "github.com/docker/docker/client" "github.com/docker/docker/errdefs" + "go.opentelemetry.io/otel" "gotest.tools/v3/assert" ) // Clean the environment, preserving protected objects (images, containers, ...) // 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 testing.TB) { +func (e *Execution) Clean(ctx context.Context, t testing.TB) { t.Helper() + + ctx, span := otel.Tracer("").Start(ctx, "CleanupEnvironment") + defer span.End() + apiClient := e.APIClient() platform := e.DaemonInfo.OSType if (platform != "windows") || (platform == "windows" && e.DaemonInfo.Isolation == "hyperv") { - unpauseAllContainers(t, apiClient) + unpauseAllContainers(ctx, t, apiClient) } - deleteAllContainers(t, apiClient, e.protectedElements.containers) - deleteAllImages(t, apiClient, e.protectedElements.images) - deleteAllVolumes(t, apiClient, e.protectedElements.volumes) - deleteAllNetworks(t, apiClient, platform, e.protectedElements.networks) + deleteAllContainers(ctx, t, apiClient, e.protectedElements.containers) + deleteAllImages(ctx, t, apiClient, e.protectedElements.images) + deleteAllVolumes(ctx, t, apiClient, e.protectedElements.volumes) + deleteAllNetworks(ctx, t, apiClient, platform, e.protectedElements.networks) if platform == "linux" { - deleteAllPlugins(t, apiClient, e.protectedElements.plugins) + deleteAllPlugins(ctx, t, apiClient, e.protectedElements.plugins) } } -func unpauseAllContainers(t testing.TB, client client.ContainerAPIClient) { +func unpauseAllContainers(ctx context.Context, t testing.TB, client client.ContainerAPIClient) { t.Helper() - ctx := context.Background() containers := getPausedContainers(ctx, t, client) if len(containers) > 0 { for _, container := range containers { @@ -58,9 +62,8 @@ func getPausedContainers(ctx context.Context, t testing.TB, client client.Contai var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`) -func deleteAllContainers(t testing.TB, apiclient client.ContainerAPIClient, protectedContainers map[string]struct{}) { +func deleteAllContainers(ctx context.Context, t testing.TB, apiclient client.ContainerAPIClient, protectedContainers map[string]struct{}) { t.Helper() - ctx := context.Background() containers := getAllContainers(ctx, t, apiclient) if len(containers) == 0 { return @@ -90,12 +93,11 @@ func getAllContainers(ctx context.Context, t testing.TB, client client.Container return containers } -func deleteAllImages(t testing.TB, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) { +func deleteAllImages(ctx context.Context, t testing.TB, apiclient client.ImageAPIClient, protectedImages map[string]struct{}) { t.Helper() - images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{}) + images, err := apiclient.ImageList(ctx, types.ImageListOptions{}) assert.Check(t, err, "failed to list images") - ctx := context.Background() for _, image := range images { tags := tagsFromImageSummary(image) if _, ok := protectedImages[image.ID]; ok { @@ -124,16 +126,16 @@ func removeImage(ctx context.Context, t testing.TB, apiclient client.ImageAPICli assert.Check(t, err, "failed to remove image %s", ref) } -func deleteAllVolumes(t testing.TB, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) { +func deleteAllVolumes(ctx context.Context, t testing.TB, c client.VolumeAPIClient, protectedVolumes map[string]struct{}) { t.Helper() - volumes, err := c.VolumeList(context.Background(), volume.ListOptions{}) + volumes, err := c.VolumeList(ctx, volume.ListOptions{}) assert.Check(t, err, "failed to list volumes") for _, v := range volumes.Volumes { if _, ok := protectedVolumes[v.Name]; ok { continue } - err := c.VolumeRemove(context.Background(), v.Name, true) + err := c.VolumeRemove(ctx, v.Name, true) // Docker EE may list volumes that no longer exist. if isErrNotFoundSwarmClassic(err) { continue @@ -142,9 +144,9 @@ func deleteAllVolumes(t testing.TB, c client.VolumeAPIClient, protectedVolumes m } } -func deleteAllNetworks(t testing.TB, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) { +func deleteAllNetworks(ctx context.Context, t testing.TB, c client.NetworkAPIClient, daemonPlatform string, protectedNetworks map[string]struct{}) { t.Helper() - networks, err := c.NetworkList(context.Background(), types.NetworkListOptions{}) + networks, err := c.NetworkList(ctx, types.NetworkListOptions{}) assert.Check(t, err, "failed to list networks") for _, n := range networks { @@ -158,14 +160,14 @@ func deleteAllNetworks(t testing.TB, c client.NetworkAPIClient, daemonPlatform s // nat is a pre-defined network on Windows and cannot be removed continue } - err := c.NetworkRemove(context.Background(), n.ID) + err := c.NetworkRemove(ctx, n.ID) assert.Check(t, err, "failed to remove network %s", n.ID) } } -func deleteAllPlugins(t testing.TB, c client.PluginAPIClient, protectedPlugins map[string]struct{}) { +func deleteAllPlugins(ctx context.Context, t testing.TB, c client.PluginAPIClient, protectedPlugins map[string]struct{}) { t.Helper() - plugins, err := c.PluginList(context.Background(), filters.Args{}) + plugins, err := c.PluginList(ctx, filters.Args{}) // Docker EE does not allow cluster-wide plugin management. if errdefs.IsNotImplemented(err) { return @@ -176,7 +178,7 @@ func deleteAllPlugins(t testing.TB, c client.PluginAPIClient, protectedPlugins m if _, ok := protectedPlugins[p.Name]; ok { continue } - err := c.PluginRemove(context.Background(), p.Name, types.PluginRemoveOptions{Force: true}) + err := c.PluginRemove(ctx, p.Name, types.PluginRemoveOptions{Force: true}) assert.Check(t, err, "failed to remove plugin %s", p.ID) } } diff --git a/testutil/environment/environment.go b/testutil/environment/environment.go index ff4c5a028b..b5b52f678f 100644 --- a/testutil/environment/environment.go +++ b/testutil/environment/environment.go @@ -36,17 +36,17 @@ type PlatformDefaults struct { // New creates a new Execution struct // This is configured using the env client (see client.FromEnv) -func New() (*Execution, error) { +func New(ctx context.Context) (*Execution, error) { c, err := client.NewClientWithOpts(client.FromEnv) if err != nil { return nil, errors.Wrapf(err, "failed to create client") } - return FromClient(c) + return FromClient(ctx, c) } // FromClient creates a new Execution environment from the passed in client -func FromClient(c *client.Client) (*Execution, error) { - info, err := c.Info(context.Background()) +func FromClient(ctx context.Context, c *client.Client) (*Execution, error) { + info, err := c.Info(ctx) if err != nil { return nil, errors.Wrapf(err, "failed to get info from daemon") } @@ -212,9 +212,9 @@ func (e *Execution) HasExistingImage(t testing.TB, reference string) bool { // EnsureFrozenImagesLinux loads frozen test images into the daemon // if they aren't already loaded -func EnsureFrozenImagesLinux(testEnv *Execution) error { +func EnsureFrozenImagesLinux(ctx context.Context, testEnv *Execution) error { if testEnv.DaemonInfo.OSType == "linux" { - err := load.FrozenImagesLinux(testEnv.APIClient(), frozenImages...) + err := load.FrozenImagesLinux(ctx, testEnv.APIClient(), frozenImages...) if err != nil { return errors.Wrap(err, "error loading frozen images") } diff --git a/testutil/environment/protect.go b/testutil/environment/protect.go index f63a9ada04..4ea745ceec 100644 --- a/testutil/environment/protect.go +++ b/testutil/environment/protect.go @@ -8,6 +8,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/volume" "github.com/docker/docker/errdefs" + "go.opentelemetry.io/otel" "gotest.tools/v3/assert" ) @@ -34,14 +35,17 @@ func newProtectedElements() protectedElements { // ProtectAll protects the existing environment (containers, images, networks, // volumes, and, on Linux, plugins) from being cleaned up at the end of test // runs -func ProtectAll(t testing.TB, testEnv *Execution) { +func ProtectAll(ctx context.Context, t testing.TB, testEnv *Execution) { t.Helper() - ProtectContainers(t, testEnv) - ProtectImages(t, testEnv) - ProtectNetworks(t, testEnv) - ProtectVolumes(t, testEnv) + ctx, span := otel.Tracer("").Start(ctx, "ProtectAll") + defer span.End() + + ProtectContainers(ctx, t, testEnv) + ProtectImages(ctx, t, testEnv) + ProtectNetworks(ctx, t, testEnv) + ProtectVolumes(ctx, t, testEnv) if testEnv.DaemonInfo.OSType == "linux" { - ProtectPlugins(t, testEnv) + ProtectPlugins(ctx, t, testEnv) } } @@ -56,16 +60,16 @@ func (e *Execution) ProtectContainer(t testing.TB, containers ...string) { // ProtectContainers protects existing containers from being cleaned up at the // end of test runs -func ProtectContainers(t testing.TB, testEnv *Execution) { +func ProtectContainers(ctx context.Context, t testing.TB, testEnv *Execution) { t.Helper() - containers := getExistingContainers(t, testEnv) + containers := getExistingContainers(ctx, t, testEnv) testEnv.ProtectContainer(t, containers...) } -func getExistingContainers(t testing.TB, testEnv *Execution) []string { +func getExistingContainers(ctx context.Context, t testing.TB, testEnv *Execution) []string { t.Helper() client := testEnv.APIClient() - containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{ + containerList, err := client.ContainerList(ctx, types.ContainerListOptions{ All: true, }) assert.NilError(t, err, "failed to list containers") @@ -87,9 +91,9 @@ func (e *Execution) ProtectImage(t testing.TB, images ...string) { // ProtectImages protects existing images and on linux frozen images from being // cleaned up at the end of test runs -func ProtectImages(t testing.TB, testEnv *Execution) { +func ProtectImages(ctx context.Context, t testing.TB, testEnv *Execution) { t.Helper() - images := getExistingImages(t, testEnv) + images := getExistingImages(ctx, t, testEnv) if testEnv.DaemonInfo.OSType == "linux" { images = append(images, frozenImages...) @@ -98,10 +102,10 @@ func ProtectImages(t testing.TB, testEnv *Execution) { testEnv.ProtectImage(t, DanglingImageIdGraphDriver, DanglingImageIdSnapshotter) } -func getExistingImages(t testing.TB, testEnv *Execution) []string { +func getExistingImages(ctx context.Context, t testing.TB, testEnv *Execution) []string { t.Helper() client := testEnv.APIClient() - imageList, err := client.ImageList(context.Background(), types.ImageListOptions{ + imageList, err := client.ImageList(ctx, types.ImageListOptions{ All: true, Filters: filters.NewArgs(filters.Arg("dangling", "false")), }) @@ -143,16 +147,16 @@ func (e *Execution) ProtectNetwork(t testing.TB, networks ...string) { // ProtectNetworks protects existing networks from being cleaned up at the end // of test runs -func ProtectNetworks(t testing.TB, testEnv *Execution) { +func ProtectNetworks(ctx context.Context, t testing.TB, testEnv *Execution) { t.Helper() - networks := getExistingNetworks(t, testEnv) + networks := getExistingNetworks(ctx, t, testEnv) testEnv.ProtectNetwork(t, networks...) } -func getExistingNetworks(t testing.TB, testEnv *Execution) []string { +func getExistingNetworks(ctx context.Context, t testing.TB, testEnv *Execution) []string { t.Helper() client := testEnv.APIClient() - networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{}) + networkList, err := client.NetworkList(ctx, types.NetworkListOptions{}) assert.NilError(t, err, "failed to list networks") var networks []string @@ -172,16 +176,16 @@ func (e *Execution) ProtectPlugin(t testing.TB, plugins ...string) { // ProtectPlugins protects existing plugins from being cleaned up at the end of // test runs -func ProtectPlugins(t testing.TB, testEnv *Execution) { +func ProtectPlugins(ctx context.Context, t testing.TB, testEnv *Execution) { t.Helper() - plugins := getExistingPlugins(t, testEnv) + plugins := getExistingPlugins(ctx, t, testEnv) testEnv.ProtectPlugin(t, plugins...) } -func getExistingPlugins(t testing.TB, testEnv *Execution) []string { +func getExistingPlugins(ctx context.Context, t testing.TB, testEnv *Execution) []string { t.Helper() client := testEnv.APIClient() - pluginList, err := client.PluginList(context.Background(), filters.Args{}) + pluginList, err := client.PluginList(ctx, filters.Args{}) // Docker EE does not allow cluster-wide plugin management. if errdefs.IsNotImplemented(err) { return []string{} @@ -205,16 +209,16 @@ func (e *Execution) ProtectVolume(t testing.TB, volumes ...string) { // ProtectVolumes protects existing volumes from being cleaned up at the end of // test runs -func ProtectVolumes(t testing.TB, testEnv *Execution) { +func ProtectVolumes(ctx context.Context, t testing.TB, testEnv *Execution) { t.Helper() - volumes := getExistingVolumes(t, testEnv) + volumes := getExistingVolumes(ctx, t, testEnv) testEnv.ProtectVolume(t, volumes...) } -func getExistingVolumes(t testing.TB, testEnv *Execution) []string { +func getExistingVolumes(ctx context.Context, t testing.TB, testEnv *Execution) []string { t.Helper() client := testEnv.APIClient() - volumeList, err := client.VolumeList(context.Background(), volume.ListOptions{}) + volumeList, err := client.VolumeList(ctx, volume.ListOptions{}) assert.NilError(t, err, "failed to list volumes") var volumes []string diff --git a/testutil/fixtures/load/frozen.go b/testutil/fixtures/load/frozen.go index aba4345e66..85cddf7527 100644 --- a/testutil/fixtures/load/frozen.go +++ b/testutil/fixtures/load/frozen.go @@ -15,6 +15,10 @@ import ( "github.com/docker/docker/pkg/jsonmessage" "github.com/moby/term" "github.com/pkg/errors" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" ) const frozenImgDir = "/docker-frozen-images" @@ -24,10 +28,13 @@ const frozenImgDir = "/docker-frozen-images" // TODO: This loads whatever is in the frozen image dir, regardless of what // images were passed in. If the images need to be downloaded, then it will respect // the passed in images -func FrozenImagesLinux(client client.APIClient, images ...string) error { +func FrozenImagesLinux(ctx context.Context, client client.APIClient, images ...string) error { + ctx, span := otel.Tracer("").Start(ctx, "LoadFrozenImages") + defer span.End() + var loadImages []struct{ srcName, destName string } for _, img := range images { - if !imageExists(client, img) { + if !imageExists(ctx, client, img) { srcName := img // hello-world:latest gets re-tagged as hello-world:frozen // there are some tests that use hello-world:latest specifically so it pulls @@ -47,7 +54,6 @@ func FrozenImagesLinux(client client.APIClient, images ...string) error { return nil } - ctx := context.Background() fi, err := os.Stat(frozenImgDir) if err != nil || !fi.IsDir() { srcImages := make([]string, 0, len(loadImages)) @@ -76,12 +82,20 @@ func FrozenImagesLinux(client client.APIClient, images ...string) error { return nil } -func imageExists(client client.APIClient, name string) bool { - _, _, err := client.ImageInspectWithRaw(context.Background(), name) +func imageExists(ctx context.Context, client client.APIClient, name string) bool { + ctx, span := otel.Tracer("").Start(ctx, "check image exists: "+name) + defer span.End() + _, _, err := client.ImageInspectWithRaw(ctx, name) + if err != nil { + span.RecordError(err) + } return err == nil } func loadFrozenImages(ctx context.Context, client client.APIClient) error { + ctx, span := otel.Tracer("").Start(ctx, "load frozen images") + defer span.End() + tar, err := exec.LookPath("tar") if err != nil { return errors.Wrap(err, "could not find tar binary") @@ -116,7 +130,7 @@ func pullImages(ctx context.Context, client client.APIClient, images []string) e dockerfile = "Dockerfile" } dockerfilePath := filepath.Join(filepath.Dir(filepath.Clean(cwd)), dockerfile) - pullRefs, err := readFrozenImageList(dockerfilePath, images) + pullRefs, err := readFrozenImageList(ctx, dockerfilePath, images) if err != nil { return errors.Wrap(err, "error reading frozen image list") } @@ -138,7 +152,16 @@ func pullImages(ctx context.Context, client client.APIClient, images []string) e return <-chErr } -func pullTagAndRemove(ctx context.Context, client client.APIClient, ref string, tag string) error { +func pullTagAndRemove(ctx context.Context, client client.APIClient, ref string, tag string) (retErr error) { + ctx, span := otel.Tracer("").Start(ctx, "pull image: "+ref+" with tag: "+tag) + defer func() { + if retErr != nil { + // An error here is a real error for the span, so set the span status + span.SetStatus(codes.Error, retErr.Error()) + } + span.End() + }() + resp, err := client.ImagePull(ctx, ref, types.ImagePullOptions{}) if err != nil { return errors.Wrapf(err, "failed to pull %s", ref) @@ -156,7 +179,7 @@ func pullTagAndRemove(ctx context.Context, client client.APIClient, ref string, return errors.Wrapf(err, "failed to remove %s", ref) } -func readFrozenImageList(dockerfilePath string, images []string) (map[string]string, error) { +func readFrozenImageList(ctx context.Context, dockerfilePath string, images []string) (map[string]string, error) { f, err := os.Open(dockerfilePath) if err != nil { return nil, errors.Wrap(err, "error reading dockerfile") @@ -164,6 +187,8 @@ func readFrozenImageList(dockerfilePath string, images []string) (map[string]str defer f.Close() ls := make(map[string]string) + span := trace.SpanFromContext(ctx) + scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.Fields(scanner.Text()) @@ -186,6 +211,9 @@ func readFrozenImageList(dockerfilePath string, images []string) (map[string]str for _, i := range images { if split[0] == i { ls[i] = img + if span.IsRecording() { + span.AddEvent("found frozen image", trace.WithAttributes(attribute.String("image", i))) + } break } } diff --git a/testutil/helpers.go b/testutil/helpers.go index e522b5a9a4..f00aba8a29 100644 --- a/testutil/helpers.go +++ b/testutil/helpers.go @@ -1,7 +1,23 @@ package testutil // import "github.com/docker/docker/testutil" import ( + "context" "io" + "os" + "strings" + "sync" + "testing" + + "github.com/containerd/containerd/log" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.7.0" + "gotest.tools/v3/icmd" ) // DevZero acts like /dev/zero but in an OS-independent fashion. @@ -15,3 +31,129 @@ func (d devZero) Read(p []byte) (n int, err error) { } return len(p), nil } + +var ( + tracingOnce sync.Once +) + +// configureTracing sets up an OTLP tracing exporter for use in tests. +func ConfigureTracing() func(context.Context) { + if os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") == "" { + // No OTLP endpoint configured, so don't bother setting up tracing. + // Since we are not using a batch exporter we don't want tracing to block up tests. + return func(context.Context) {} + } + var tp *trace.TracerProvider + tracingOnce.Do(func() { + ctx := context.Background() + exp := otlptracehttp.NewUnstarted() + sp := trace.NewBatchSpanProcessor(exp) + props := propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}) + otel.SetTextMapPropagator(props) + + tp = trace.NewTracerProvider( + trace.WithSpanProcessor(sp), + trace.WithSampler(trace.AlwaysSample()), + trace.WithResource(resource.NewSchemaless( + attribute.KeyValue{Key: semconv.ServiceNameKey, Value: attribute.StringValue("integration-test-client")}, + )), + ) + otel.SetTracerProvider(tp) + + if err := exp.Start(ctx); err != nil { + log.G(ctx).WithError(err).Warn("Failed to start tracing exporter") + } + }) + + // if ConfigureTracing was called multiple times we'd have a nil `tp` here + // Get the already configured tracer provider + if tp == nil { + tp = otel.GetTracerProvider().(*trace.TracerProvider) + } + return func(ctx context.Context) { + if err := tp.Shutdown(ctx); err != nil { + log.G(ctx).WithError(err).Warn("Failed to shutdown tracer") + } + } +} + +// TestingT is an interface wrapper around *testing.T and *testing.B. +type TestingT interface { + Name() string + Cleanup(func()) + Log(...any) + Failed() bool +} + +// StartSpan starts a span for the given test. +func StartSpan(ctx context.Context, t TestingT) context.Context { + ConfigureTracing() + ctx, span := otel.Tracer("").Start(ctx, t.Name()) + t.Cleanup(func() { + if t.Failed() { + span.SetStatus(codes.Error, "test failed") + } + span.End() + }) + return ctx +} + +func RunCommand(ctx context.Context, cmd string, args ...string) *icmd.Result { + _, span := otel.Tracer("").Start(ctx, "RunCommand "+cmd+" "+strings.Join(args, " ")) + res := icmd.RunCommand(cmd, args...) + if res.Error != nil { + span.SetStatus(codes.Error, res.Error.Error()) + } + span.SetAttributes(attribute.String("cmd", cmd), attribute.String("args", strings.Join(args, " "))) + span.SetAttributes(attribute.Int("exit", res.ExitCode)) + span.SetAttributes(attribute.String("stdout", res.Stdout()), attribute.String("stderr", res.Stderr())) + span.End() + return res +} + +type testContextStore struct { + mu sync.Mutex + idx map[TestingT]context.Context +} + +var testContexts = &testContextStore{idx: make(map[TestingT]context.Context)} + +func (s *testContextStore) Get(t TestingT) context.Context { + s.mu.Lock() + defer s.mu.Unlock() + + ctx, ok := s.idx[t] + if ok { + return ctx + } + ctx = context.Background() + s.idx[t] = ctx + return ctx +} + +func (s *testContextStore) Set(ctx context.Context, t TestingT) { + s.mu.Lock() + if _, ok := s.idx[t]; ok { + panic("test context already set") + } + s.idx[t] = ctx + s.mu.Unlock() +} + +func (s *testContextStore) Delete(t *testing.T) { + s.mu.Lock() + defer s.mu.Unlock() + delete(s.idx, t) +} + +func GetContext(t TestingT) context.Context { + return testContexts.Get(t) +} + +func SetContext(t TestingT, ctx context.Context) { + testContexts.Set(ctx, t) +} + +func CleanupContext(t *testing.T) { + testContexts.Delete(t) +} diff --git a/testutil/request/request.go b/testutil/request/request.go index c23ac65e1a..0fdfb7af6b 100644 --- a/testutil/request/request.go +++ b/testutil/request/request.go @@ -19,6 +19,7 @@ import ( "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" "github.com/pkg/errors" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "gotest.tools/v3/assert" ) @@ -55,27 +56,27 @@ func DaemonUnixTime(ctx context.Context, t testing.TB, client client.APIClient, } // Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers -func Post(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, append(modifiers, Method(http.MethodPost))...) +func Post(ctx context.Context, endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { + return Do(ctx, endpoint, append(modifiers, Method(http.MethodPost))...) } // Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers -func Delete(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, append(modifiers, Method(http.MethodDelete))...) +func Delete(ctx context.Context, endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { + return Do(ctx, endpoint, append(modifiers, Method(http.MethodDelete))...) } // Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers -func Get(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, modifiers...) +func Get(ctx context.Context, endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { + return Do(ctx, endpoint, modifiers...) } // Head creates and execute a HEAD request on the specified host and endpoint, with the specified request modifiers -func Head(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { - return Do(endpoint, append(modifiers, Method(http.MethodHead))...) +func Head(ctx context.Context, endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { + return Do(ctx, endpoint, append(modifiers, Method(http.MethodHead))...) } // Do creates and execute a request on the specified endpoint, with the specified request modifiers -func Do(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { +func Do(ctx context.Context, endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) { opts := &Options{ host: DaemonHost(), } @@ -86,10 +87,13 @@ func Do(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCl if err != nil { return nil, nil, err } + req = req.WithContext(ctx) + httpClient, err := newHTTPClient(opts.host) if err != nil { return nil, nil, err } + resp, err := httpClient.Do(req) var body io.ReadCloser if resp != nil { @@ -158,7 +162,7 @@ func newHTTPClient(host string) (*http.Client, error) { } transport.DisableKeepAlives = true err = sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host) - return &http.Client{Transport: transport}, err + return &http.Client{Transport: otelhttp.NewTransport(transport)}, err } func getTLSConfig() (*tls.Config, error) { diff --git a/vendor.mod b/vendor.mod index d124ce1464..711d79bc42 100644 --- a/vendor.mod +++ b/vendor.mod @@ -96,7 +96,7 @@ require ( go.opentelemetry.io/otel v1.4.1 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 go.opentelemetry.io/otel/sdk v1.4.1 go.opentelemetry.io/otel/trace v1.4.1 golang.org/x/mod v0.10.0