@@ -21,6 +21,8 @@ import (
2121"github.com/docker/docker/pkg/stdcopy"
2222"github.com/stretchr/testify/assert"
2323"github.com/stretchr/testify/require"
24+ "golang.org/x/exp/slices"
25+ "golang.org/x/mod/semver"
2426)
2527
2628// TestIntegration performs an integration test against an ephemeral Coder deployment.
@@ -37,6 +39,16 @@ func TestIntegration(t *testing.T) {
3739t .Skip ("Skipping integration tests during tf acceptance tests" )
3840}
3941
42+ coderImg := os .Getenv ("CODER_IMAGE" )
43+ if coderImg == "" {
44+ coderImg = "ghcr.io/coder/coder"
45+ }
46+
47+ coderVersion := os .Getenv ("CODER_VERSION" )
48+ if coderVersion == "" {
49+ coderVersion = "latest"
50+ }
51+
4052timeoutStr := os .Getenv ("TIMEOUT_MINS" )
4153if timeoutStr == "" {
4254timeoutStr = "10"
@@ -88,9 +100,17 @@ func TestIntegration(t *testing.T) {
88100} {
89101t .Run (tt .name ,func (t * testing.T ) {
90102// Given: we have an existing Coder deployment running locally
91- ctrID := setup (ctx ,t ,tt .name )
103+ ctrID := setup (ctx ,t ,tt .name , coderImg , coderVersion )
92104// Import named template
93- _ ,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 ))
105+
106+ // NOTE: Template create command was deprecated after this version
107+ // ref: https://github.com/coder/coder/pull/11390
108+ templateCreateCmd := "push"
109+ if semver .Compare (coderVersion ,"v2.7.0" )< 1 {
110+ t .Logf ("using now-deprecated templates create command for older coder version" )
111+ templateCreateCmd = "create"
112+ }
113+ _ ,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 ))
94114require .Equal (t ,0 ,rc )
95115// Create a workspace
96116_ ,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) {
105125}
106126}
107127
108- func setup (ctx context.Context ,t * testing.T ,name string )string {
128+ func setup (ctx context.Context ,t * testing.T ,name , coderImg , coderVersion string )string {
109129var (
110130// For this test to work, we pass in a custom terraformrc to use
111131// the locally built version of the provider.
@@ -118,16 +138,6 @@ func setup(ctx context.Context, t *testing.T, name string) string {
118138localURL = "http://localhost:3000"
119139)
120140
121- coderImg := os .Getenv ("CODER_IMAGE" )
122- if coderImg == "" {
123- coderImg = "ghcr.io/coder/coder"
124- }
125-
126- coderVersion := os .Getenv ("CODER_VERSION" )
127- if coderVersion == "" {
128- coderVersion = "latest"
129- }
130-
131141t .Logf ("using coder image %s:%s" ,coderImg ,coderVersion )
132142
133143// Ensure the binary is built
@@ -151,11 +161,7 @@ func setup(ctx context.Context, t *testing.T, name string) string {
151161
152162// Ensure the image is available locally.
153163refStr := coderImg + ":" + coderVersion
154- t .Logf ("ensuring image %q" ,refStr )
155- resp ,err := cli .ImagePull (ctx ,refStr , image.PullOptions {})
156- require .NoError (t ,err )
157- _ ,err = io .ReadAll (resp )
158- require .NoError (t ,err )
164+ ensureImage (ctx ,t ,cli ,refStr )
159165
160166// Stand up a temporary Coder instance
161167ctr ,err := cli .ContainerCreate (ctx ,& container.Config {
@@ -213,6 +219,25 @@ func setup(ctx context.Context, t *testing.T, name string) string {
213219return ctr .ID
214220}
215221
222+ func ensureImage (ctx context.Context ,t * testing.T ,cli * client.Client ,ref string ) {
223+ t .Helper ()
224+
225+ t .Logf ("ensuring image %q" ,ref )
226+ images ,err := cli .ImageList (ctx , image.ListOptions {})
227+ require .NoError (t ,err ,"list images" )
228+ for _ ,img := range images {
229+ if slices .Contains (img .RepoTags ,ref ) {
230+ t .Logf ("image %q found locally, not pulling" ,ref )
231+ return
232+ }
233+ }
234+ t .Logf ("image %s not found locally, attempting to pull" ,ref )
235+ resp ,err := cli .ImagePull (ctx ,ref , image.PullOptions {})
236+ require .NoError (t ,err )
237+ _ ,err = io .ReadAll (resp )
238+ require .NoError (t ,err )
239+ }
240+
216241// execContainer executes the given command in the given container and returns
217242// the output and the exit code of the command.
218243func execContainer (ctx context.Context ,t * testing.T ,containerID ,command string ) (string ,int ) {
@@ -249,7 +274,7 @@ func assertOutput(t *testing.T, expected, actual map[string]string) {
249274
250275for expectedKey ,expectedValExpr := range expected {
251276actualVal := actual [expectedKey ]
252- assert .Regexp (t ,expectedValExpr ,actualVal )
277+ assert .Regexp (t ,expectedValExpr ,actualVal , "output key %q does not have expected value" , expectedKey )
253278}
254279for actualKey := range actual {
255280_ ,ok := expected [actualKey ]