From 27bf167ab3030b78c32ff78fffa153b25a914e64 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Thu, 27 Jun 2024 10:29:54 +0100 Subject: [PATCH 1/2] chore: improve integration test compatibility with older Coder versions --- go.mod | 2 + go.sum | 4 ++ integration/integration_test.go | 67 +++++++++++++++++++++++---------- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 625aae19..b5e26e56 100644 --- a/go.mod +++ b/go.mod @@ -76,6 +76,8 @@ require ( go.opentelemetry.io/otel/sdk v1.27.0 // indirect go.opentelemetry.io/otel/trace v1.27.0 // indirect golang.org/x/crypto v0.23.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/mod v0.18.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.15.0 // indirect diff --git a/go.sum b/go.sum index d07d5ff3..047612ff 100644 --- a/go.sum +++ b/go.sum @@ -252,9 +252,13 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/integration/integration_test.go b/integration/integration_test.go index cf58b99e..e23d053b 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -21,6 +21,8 @@ import ( "github.com/docker/docker/pkg/stdcopy" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" + "golang.org/x/mod/semver" ) // TestIntegration performs an integration test against an ephemeral Coder deployment. @@ -37,6 +39,16 @@ func TestIntegration(t *testing.T) { t.Skip("Skipping integration tests during tf acceptance tests") } + coderImg := os.Getenv("CODER_IMAGE") + if coderImg == "" { + coderImg = "ghcr.io/coder/coder" + } + + coderVersion := os.Getenv("CODER_VERSION") + if coderVersion == "" { + coderVersion = "latest" + } + timeoutStr := os.Getenv("TIMEOUT_MINS") if timeoutStr == "" { timeoutStr = "10" @@ -88,9 +100,17 @@ func TestIntegration(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) + ctrID := setup(ctx, t, tt.name, coderImg, coderVersion) // 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.name, tt.name, tt.name)) + + // NOTE: Template create command was deprecated after this version + // ref: https://github.com/coder/coder/pull/11390 + templateCreateCmd := "push" + if semver.Compare(coderVersion, "v2.7.0") < 1 { + t.Logf("using now-deprecated templates create command for older coder version") + templateCreateCmd = "create" + } + _, rc := execContainer(ctx, t, ctrID, fmt.Sprintf(`coder templates %s %s --directory /src/integration/%s --var output_path=/tmp/%s.json --yes`, templateCreateCmd, 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.name, tt.name)) @@ -105,7 +125,7 @@ func TestIntegration(t *testing.T) { } } -func setup(ctx context.Context, t *testing.T, name string) string { +func setup(ctx context.Context, t *testing.T, name, coderImg, coderVersion string) string { var ( // For this test to work, we pass in a custom terraformrc to use // the locally built version of the provider. @@ -118,16 +138,6 @@ func setup(ctx context.Context, t *testing.T, name string) string { localURL = "http://localhost:3000" ) - coderImg := os.Getenv("CODER_IMAGE") - if coderImg == "" { - coderImg = "ghcr.io/coder/coder" - } - - coderVersion := os.Getenv("CODER_VERSION") - if coderVersion == "" { - coderVersion = "latest" - } - t.Logf("using coder image %s:%s", coderImg, coderVersion) // Ensure the binary is built @@ -151,11 +161,7 @@ func setup(ctx context.Context, t *testing.T, name string) string { // 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) + ensureImage(ctx, t, cli, refStr) // Stand up a temporary Coder instance ctr, err := cli.ContainerCreate(ctx, &container.Config{ @@ -213,6 +219,29 @@ func setup(ctx context.Context, t *testing.T, name string) string { return ctr.ID } +func ensureImage(ctx context.Context, t *testing.T, cli *client.Client, ref string) { + t.Helper() + + t.Logf("ensuring image %q", ref) + images, err := cli.ImageList(ctx, image.ListOptions{}) + require.NoError(t, err, "list images") + var found bool + for _, img := range images { + if slices.Contains(img.RepoTags, ref) { + t.Logf("image %q found locally, not pulling", ref) + found = true + break + } + } + if !found { + t.Logf("image %s not found locally, attempting to pull", ref) + resp, err := cli.ImagePull(ctx, ref, image.PullOptions{}) + require.NoError(t, err) + _, err = io.ReadAll(resp) + require.NoError(t, err) + } +} + // execContainer executes the given command in the given container and returns // the output and the exit code of the command. func execContainer(ctx context.Context, t *testing.T, containerID, command string) (string, int) { @@ -249,7 +278,7 @@ func assertOutput(t *testing.T, expected, actual map[string]string) { for expectedKey, expectedValExpr := range expected { actualVal := actual[expectedKey] - assert.Regexp(t, expectedValExpr, actualVal) + assert.Regexp(t, expectedValExpr, actualVal, "output key %q does not have expected value", expectedKey) } for actualKey := range actual { _, ok := expected[actualKey] From a6e2e7139a27df38175b49a53be000f50924c50b Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Thu, 27 Jun 2024 10:33:30 +0100 Subject: [PATCH 2/2] ensureImage: early return instead of break --- integration/integration_test.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index e23d053b..49b36456 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -225,21 +225,17 @@ func ensureImage(ctx context.Context, t *testing.T, cli *client.Client, ref stri t.Logf("ensuring image %q", ref) images, err := cli.ImageList(ctx, image.ListOptions{}) require.NoError(t, err, "list images") - var found bool for _, img := range images { if slices.Contains(img.RepoTags, ref) { t.Logf("image %q found locally, not pulling", ref) - found = true - break + return } } - if !found { - t.Logf("image %s not found locally, attempting to pull", ref) - resp, err := cli.ImagePull(ctx, ref, image.PullOptions{}) - require.NoError(t, err) - _, err = io.ReadAll(resp) - require.NoError(t, err) - } + t.Logf("image %s not found locally, attempting to pull", ref) + resp, err := cli.ImagePull(ctx, ref, image.PullOptions{}) + require.NoError(t, err) + _, err = io.ReadAll(resp) + require.NoError(t, err) } // execContainer executes the given command in the given container and returns pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy