TestDockerDevcontainerCLI tests the DevcontainerCLI component with real Docker containers. This test verifies that containers can be created and recreated using the actual devcontainer CLI and Docker. It is skipped by default and can be run with: CODER_TEST_USE_DOCKER=1 go test ./agent/agentcontai
(t *testing.T)
| 540 | // |
| 541 | // The test requires Docker to be installed and running. |
| 542 | func TestDockerDevcontainerCLI(t *testing.T) { |
| 543 | t.Parallel() |
| 544 | if os.Getenv("CODER_TEST_USE_DOCKER") != "1" { |
| 545 | t.Skip("skipping Docker test; set CODER_TEST_USE_DOCKER=1 to run") |
| 546 | } |
| 547 | if _, err := exec.LookPath("devcontainer"); err != nil { |
| 548 | t.Fatal("this test requires the devcontainer CLI: npm install -g @devcontainers/cli") |
| 549 | } |
| 550 | |
| 551 | // Connect to Docker. |
| 552 | pool, err := dockertest.NewPool("") |
| 553 | require.NoError(t, err, "connect to Docker") |
| 554 | |
| 555 | t.Run("ContainerLifecycle", func(t *testing.T) { |
| 556 | t.Parallel() |
| 557 | |
| 558 | // Set up workspace directory with a devcontainer configuration. |
| 559 | workspaceFolder := t.TempDir() |
| 560 | configPath := setupDevcontainerWorkspace(t, workspaceFolder) |
| 561 | |
| 562 | // Use a long timeout because container operations are slow. |
| 563 | ctx := testutil.Context(t, testutil.WaitLong) |
| 564 | logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug) |
| 565 | |
| 566 | // Create the devcontainer CLI under test. |
| 567 | dccli := agentcontainers.NewDevcontainerCLI(logger, agentexec.DefaultExecer) |
| 568 | |
| 569 | // Create a container. |
| 570 | firstID, err := dccli.Up(ctx, workspaceFolder, configPath) |
| 571 | require.NoError(t, err, "create container") |
| 572 | require.NotEmpty(t, firstID, "container ID should not be empty") |
| 573 | defer removeDevcontainerByID(t, pool, firstID) |
| 574 | |
| 575 | // Verify container exists. |
| 576 | firstContainer, found := findDevcontainerByID(t, pool, firstID) |
| 577 | require.True(t, found, "container should exist") |
| 578 | |
| 579 | // Remember the container creation time. |
| 580 | firstCreated := firstContainer.Created |
| 581 | |
| 582 | // Recreate the container. |
| 583 | secondID, err := dccli.Up(ctx, workspaceFolder, configPath, agentcontainers.WithRemoveExistingContainer()) |
| 584 | require.NoError(t, err, "recreate container") |
| 585 | require.NotEmpty(t, secondID, "recreated container ID should not be empty") |
| 586 | defer removeDevcontainerByID(t, pool, secondID) |
| 587 | |
| 588 | // Verify the new container exists and is different. |
| 589 | secondContainer, found := findDevcontainerByID(t, pool, secondID) |
| 590 | require.True(t, found, "recreated container should exist") |
| 591 | |
| 592 | // Verify it's a different container by checking creation time. |
| 593 | secondCreated := secondContainer.Created |
| 594 | assert.NotEqual(t, firstCreated, secondCreated, "recreated container should have different creation time") |
| 595 | |
| 596 | // Verify the first container is removed by the recreation. |
| 597 | _, found = findDevcontainerByID(t, pool, firstID) |
| 598 | assert.False(t, found, "first container should be removed") |
| 599 | }) |
nothing calls this directly
no test coverage detected