diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a4a6bce..217c065f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,9 +33,19 @@ jobs: go mod download - name: Build + env: + CGO_ENABLED: "0" run: | go build -v . + - name: Run integration test + timeout-minutes: 10 + env: + CODER_IMAGE: "ghcr.io/coder/coder" + CODER_VERSION: "latest" + run: | + go test -v ./integration + # run acceptance tests in a matrix with Terraform core versions test: name: Matrix Test diff --git a/integration/integration_test.go b/integration/integration_test.go index f2c55ed8..1c2046be 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "io" "os" "path/filepath" "runtime" @@ -15,6 +16,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/image" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" "github.com/stretchr/testify/assert" @@ -44,17 +46,14 @@ func TestIntegration(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutMins)*time.Minute) t.Cleanup(cancel) - // Given: we have an existing Coder deployment running locally - ctrID := setup(ctx, t) - for _, tt := range []struct { // Name of the folder under `integration/` containing a test template - templateName string + name string // map of string to regex to be passed to assertOutput() expectedOutput map[string]string }{ { - templateName: "test-data-source", + name: "test-data-source", expectedOutput: map[string]string{ "provisioner.arch": runtime.GOARCH, "provisioner.id": `[a-zA-Z0-9-]+`, @@ -82,20 +81,22 @@ func TestIntegration(t *testing.T) { "workspace_owner.name": `testing`, "workspace_owner.oidc_access_token": `^$`, // TODO: test OIDC integration "workspace_owner.session_token": `.+`, - "workspace_owner.ssh_private_key": `^$`, // Depends on coder/coder#13366 - "workspace_owner.ssh_public_key": `^$`, // Depends on coder/coder#13366 + "workspace_owner.ssh_private_key": `(?s)^.+?BEGIN OPENSSH PRIVATE KEY.+?END OPENSSH PRIVATE KEY.+?$`, + "workspace_owner.ssh_public_key": `(?s)^ssh-ed25519.+$`, }, }, } { - t.Run(tt.templateName, func(t *testing.T) { + t.Run(tt.name, func(t *testing.T) { + // Given: we have an existing Coder deployment running locally + ctrID := setup(ctx, t, tt.name) // Import named template - _, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`coder templates push %s --directory /src/integration/%s --var output_path=/tmp/%s.json --yes`, tt.templateName, tt.templateName, tt.templateName)) + _, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`coder templates push %s --directory /src/integration/%s --var output_path=/tmp/%s.json --yes`, tt.name, tt.name, tt.name)) require.Equal(t, 0, rc) // Create a workspace - _, rc = execContainer(ctx, t, ctrID, fmt.Sprintf(`coder create %s -t %s --yes`, tt.templateName, tt.templateName)) + _, rc = execContainer(ctx, t, ctrID, fmt.Sprintf(`coder create %s -t %s --yes`, tt.name, tt.name)) require.Equal(t, 0, rc) // Fetch the output created by the template - out, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`cat /tmp/%s.json`, tt.templateName)) + out, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`cat /tmp/%s.json`, tt.name)) require.Equal(t, 0, rc) actual := make(map[string]string) require.NoError(t, json.NewDecoder(strings.NewReader(out)).Decode(&actual)) @@ -104,7 +105,7 @@ func TestIntegration(t *testing.T) { } } -func setup(ctx context.Context, t *testing.T) string { +func setup(ctx context.Context, t *testing.T, name string) string { var ( // For this test to work, we pass in a custom terraformrc to use // the locally built version of the provider. @@ -148,9 +149,17 @@ func setup(ctx context.Context, t *testing.T) string { require.NoError(t, err, "get abs path of parent") t.Logf("src path is %s\n", srcPath) + // Ensure the image is available locally. + refStr := coderImg + ":" + coderVersion + t.Logf("ensuring image %q", refStr) + resp, err := cli.ImagePull(ctx, refStr, image.PullOptions{}) + require.NoError(t, err) + _, err = io.ReadAll(resp) + require.NoError(t, err) + // Stand up a temporary Coder instance ctr, err := cli.ContainerCreate(ctx, &container.Config{ - Image: coderImg + ":" + coderVersion, + Image: refStr, Env: []string{ "CODER_ACCESS_URL=" + localURL, // Set explicitly to avoid creating try.coder.app URLs. "CODER_IN_MEMORY=true", // We don't necessarily care about real persistence here. @@ -163,7 +172,7 @@ func setup(ctx context.Context, t *testing.T) string { tfrcPath + ":/tmp/integration.tfrc", // Custom tfrc from above. srcPath + ":/src", // Bind-mount in the repo with the built binary and templates. }, - }, nil, nil, "") + }, nil, nil, "terraform-provider-coder-integration-"+name) require.NoError(t, err, "create test deployment") t.Logf("created container %s\n", ctr.ID)