From e8dc9027819a9256f2237c54c13c66105edfc01e Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Fri, 14 Jul 2023 18:02:38 +0000 Subject: [PATCH] Wire up tests to support otel tracing Integration tests will now configure clients to propagate traces as well as create spans for all tests. Some extra changes were needed (or desired for trace propagation) in the test helpers to pass through tracing spans via context. Signed-off-by: Brian Goff --- Makefile | 5 +- hack/make/.integration-test-helpers | 2 + integration-cli/benchmark_test.go | 5 +- integration-cli/check_test.go | 372 +++++++++++------- integration-cli/daemon/daemon.go | 17 +- integration-cli/daemon/daemon_swarm.go | 142 ++++--- integration-cli/docker_api_attach_test.go | 12 +- integration-cli/docker_api_build_test.go | 95 +++-- .../docker_api_build_windows_test.go | 3 +- integration-cli/docker_api_containers_test.go | 175 ++++---- .../docker_api_containers_windows_test.go | 4 +- .../docker_api_exec_resize_test.go | 7 +- integration-cli/docker_api_exec_test.go | 55 +-- integration-cli/docker_api_images_test.go | 24 +- integration-cli/docker_api_inspect_test.go | 4 +- integration-cli/docker_api_logs_test.go | 16 +- integration-cli/docker_api_network_test.go | 15 +- integration-cli/docker_api_stats_test.go | 18 +- integration-cli/docker_api_swarm_node_test.go | 82 ++-- .../docker_api_swarm_service_test.go | 271 +++++++------ integration-cli/docker_api_swarm_test.go | 348 ++++++++-------- integration-cli/docker_api_test.go | 20 +- integration-cli/docker_cli_attach_test.go | 5 +- integration-cli/docker_cli_build_test.go | 5 +- integration-cli/docker_cli_commit_test.go | 5 +- integration-cli/docker_cli_cp_test.go | 5 +- integration-cli/docker_cli_create_test.go | 5 +- integration-cli/docker_cli_daemon_test.go | 143 +++---- integration-cli/docker_cli_events_test.go | 7 +- integration-cli/docker_cli_exec_test.go | 12 +- .../docker_cli_external_volume_driver_test.go | 39 +- integration-cli/docker_cli_health_test.go | 5 +- integration-cli/docker_cli_history_test.go | 5 +- integration-cli/docker_cli_images_test.go | 5 +- integration-cli/docker_cli_import_test.go | 5 +- integration-cli/docker_cli_info_test.go | 5 +- integration-cli/docker_cli_info_unix_test.go | 4 +- integration-cli/docker_cli_inspect_test.go | 5 +- integration-cli/docker_cli_links_test.go | 5 +- integration-cli/docker_cli_login_test.go | 5 +- integration-cli/docker_cli_logout_test.go | 4 +- integration-cli/docker_cli_logs_test.go | 78 +++- integration-cli/docker_cli_netmode_test.go | 5 +- integration-cli/docker_cli_network_test.go | 5 +- .../docker_cli_network_unix_test.go | 35 +- .../docker_cli_plugins_logdriver_test.go | 7 +- integration-cli/docker_cli_plugins_test.go | 13 +- integration-cli/docker_cli_port_test.go | 73 ++-- integration-cli/docker_cli_proxy_test.go | 5 +- integration-cli/docker_cli_prune_unix_test.go | 19 +- integration-cli/docker_cli_ps_test.go | 5 +- integration-cli/docker_cli_pull_test.go | 5 +- integration-cli/docker_cli_push_test.go | 5 +- .../docker_cli_registry_user_agent_test.go | 4 +- integration-cli/docker_cli_restart_test.go | 5 +- integration-cli/docker_cli_rmi_test.go | 5 +- integration-cli/docker_cli_run_test.go | 74 +++- integration-cli/docker_cli_run_unix_test.go | 50 +-- integration-cli/docker_cli_save_load_test.go | 5 +- .../docker_cli_save_load_unix_test.go | 3 +- integration-cli/docker_cli_search_test.go | 5 +- .../docker_cli_service_create_test.go | 56 +-- .../docker_cli_service_health_test.go | 21 +- .../docker_cli_service_logs_test.go | 46 ++- .../docker_cli_service_scale_test.go | 4 +- integration-cli/docker_cli_sni_test.go | 5 +- integration-cli/docker_cli_start_test.go | 5 +- integration-cli/docker_cli_stats_test.go | 5 +- integration-cli/docker_cli_swarm_test.go | 302 ++++++++------ integration-cli/docker_cli_swarm_unix_test.go | 19 +- integration-cli/docker_cli_top_test.go | 5 +- .../docker_cli_update_unix_test.go | 11 +- integration-cli/docker_cli_userns_test.go | 4 +- integration-cli/docker_cli_volume_test.go | 7 +- .../docker_deprecated_api_v124_test.go | 27 +- .../docker_deprecated_api_v124_unix_test.go | 3 +- integration-cli/docker_hub_pull_suite_test.go | 11 +- integration-cli/docker_utils_test.go | 89 +++-- integration-cli/environment/environment.go | 5 +- integration-cli/fixtures_linux_daemon_test.go | 17 +- integration-cli/requirements_test.go | 4 +- integration-cli/requirements_unix_test.go | 25 +- integration-cli/requirements_windows_test.go | 4 + .../build/build_cgroupns_linux_test.go | 14 +- integration/build/build_session_test.go | 24 +- integration/build/build_squash_test.go | 7 +- integration/build/build_test.go | 42 +- integration/build/build_userns_linux_test.go | 7 +- integration/build/main_test.go | 47 ++- .../capabilities/capabilities_linux_test.go | 7 +- integration/capabilities/main_linux_test.go | 47 ++- integration/config/config_test.go | 68 ++-- integration/config/main_test.go | 44 ++- integration/container/attach_test.go | 12 +- integration/container/cdi_test.go | 7 +- integration/container/checkpoint_test.go | 10 +- integration/container/container_test.go | 15 +- integration/container/copy_test.go | 19 +- integration/container/create_test.go | 71 ++-- integration/container/daemon_linux_test.go | 31 +- integration/container/daemon_test.go | 7 +- integration/container/devices_windows_test.go | 6 +- integration/container/diff_test.go | 4 +- integration/container/exec_linux_test.go | 4 +- integration/container/exec_test.go | 10 +- integration/container/export_test.go | 10 +- integration/container/health_test.go | 12 +- integration/container/inspect_test.go | 7 +- integration/container/ipcmode_linux_test.go | 18 +- integration/container/kill_test.go | 28 +- integration/container/links_linux_test.go | 8 +- integration/container/logs_test.go | 7 +- integration/container/main_test.go | 47 ++- integration/container/mounts_linux_test.go | 28 +- integration/container/nat_test.go | 16 +- integration/container/overlayfs_linux_test.go | 4 +- integration/container/pause_test.go | 10 +- integration/container/pidmode_linux_test.go | 4 +- integration/container/ps_test.go | 7 +- integration/container/remove_test.go | 16 +- integration/container/rename_test.go | 22 +- integration/container/resize_test.go | 12 +- integration/container/restart_test.go | 13 +- .../container/run_cgroupns_linux_test.go | 44 ++- integration/container/run_linux_test.go | 24 +- integration/container/stats_test.go | 4 +- integration/container/stop_linux_test.go | 12 +- integration/container/stop_test.go | 4 +- integration/container/stop_windows_test.go | 7 +- integration/container/update_linux_test.go | 11 +- integration/container/update_test.go | 7 +- integration/container/wait_test.go | 20 +- integration/daemon/daemon_test.go | 33 +- integration/daemon/main_test.go | 34 +- integration/image/commit_test.go | 5 +- integration/image/import_test.go | 12 +- integration/image/inspect_test.go | 4 +- integration/image/list_test.go | 17 +- integration/image/main_test.go | 38 +- integration/image/prune_test.go | 4 +- integration/image/pull_test.go | 8 +- integration/image/remove_test.go | 5 +- integration/image/remove_unix_test.go | 5 +- integration/image/save_test.go | 10 +- integration/image/tag_test.go | 21 +- integration/internal/swarm/service.go | 15 +- integration/internal/swarm/states.go | 8 +- integration/network/delete_test.go | 12 +- integration/network/dns_test.go | 6 +- integration/network/helpers.go | 33 +- integration/network/helpers_windows.go | 8 +- integration/network/inspect_test.go | 15 +- integration/network/ipvlan/ipvlan_test.go | 115 +++--- integration/network/ipvlan/main_test.go | 38 +- integration/network/macvlan/macvlan_test.go | 98 ++--- integration/network/macvlan/main_test.go | 40 +- integration/network/main_test.go | 47 ++- integration/network/network_test.go | 37 +- integration/network/service_test.go | 128 +++--- integration/plugin/authz/authz_plugin_test.go | 98 ++--- .../plugin/authz/authz_plugin_v2_test.go | 50 ++- integration/plugin/authz/main_test.go | 55 ++- integration/plugin/common/main_test.go | 39 +- integration/plugin/common/plugin_test.go | 34 +- .../plugin/graphdriver/external_test.go | 26 +- integration/plugin/graphdriver/main_test.go | 37 +- integration/plugin/logging/helpers_test.go | 13 +- .../plugin/logging/logging_linux_test.go | 23 +- integration/plugin/logging/main_test.go | 39 +- integration/plugin/logging/read_test.go | 12 +- integration/plugin/logging/validation_test.go | 7 +- integration/plugin/volumes/helpers_test.go | 4 +- integration/plugin/volumes/main_test.go | 37 +- integration/plugin/volumes/mounts_test.go | 7 +- integration/secret/main_test.go | 48 ++- integration/secret/secret_test.go | 44 +-- integration/service/create_test.go | 142 +++---- integration/service/inspect_test.go | 8 +- integration/service/jobs_test.go | 34 +- integration/service/list_test.go | 11 +- integration/service/main_test.go | 48 ++- integration/service/network_test.go | 13 +- integration/service/plugin_test.go | 43 +- integration/service/update_test.go | 118 +++--- integration/session/main_test.go | 48 ++- integration/session/session_test.go | 10 +- .../system/cgroupdriver_systemd_test.go | 7 +- integration/system/disk_usage_test.go | 10 +- integration/system/event_test.go | 14 +- integration/system/info_linux_test.go | 9 +- integration/system/info_test.go | 13 +- integration/system/login_test.go | 5 +- integration/system/main_test.go | 48 ++- integration/system/ping_test.go | 25 +- integration/system/version_test.go | 5 +- integration/volume/main_test.go | 48 ++- integration/volume/volume_test.go | 37 +- internal/test/suite/interfaces.go | 13 +- internal/test/suite/suite.go | 90 ++++- testutil/daemon/container.go | 2 +- testutil/daemon/daemon.go | 10 +- testutil/daemon/node.go | 18 +- testutil/daemon/service.go | 32 +- testutil/daemon/swarm.go | 32 +- testutil/environment/clean.go | 48 +-- testutil/environment/environment.go | 12 +- testutil/environment/protect.go | 56 +-- testutil/fixtures/load/frozen.go | 44 ++- testutil/helpers.go | 142 +++++++ testutil/request/request.go | 24 +- vendor.mod | 2 +- 211 files changed, 3830 insertions(+), 2712 deletions(-) create mode 100644 integration-cli/requirements_windows_test.go 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