@@ -18,6 +18,7 @@ import (
18
18
"os/exec"
19
19
"path/filepath"
20
20
"regexp"
21
+ "slices"
21
22
"strings"
22
23
"testing"
23
24
"time"
@@ -39,6 +40,7 @@ import (
39
40
"github.com/docker/docker/api/types/volume"
40
41
"github.com/docker/docker/client"
41
42
"github.com/docker/docker/pkg/stdcopy"
43
+ "github.com/google/go-cmp/cmp"
42
44
"github.com/google/go-containerregistry/pkg/authn"
43
45
"github.com/google/go-containerregistry/pkg/name"
44
46
"github.com/google/go-containerregistry/pkg/registry"
@@ -1312,6 +1314,126 @@ RUN date --utc > /root/date.txt`, testImageAlpine),
1312
1314
require .NotEmpty (t , strings .TrimSpace (out ))
1313
1315
})
1314
1316
1317
+ t .Run ("CompareBuiltAndCachedImageEnvironment" , func (t * testing.T ) {
1318
+ t .Parallel ()
1319
+
1320
+ ctx , cancel := context .WithCancel (context .Background ())
1321
+ t .Cleanup (cancel )
1322
+
1323
+ wantOverrides := []string {
1324
+ "FROM_CONTAINER_ENV=containerEnv" ,
1325
+ "FROM_REMOTE_ENV=remoteEnv" ,
1326
+ "CONTAINER_OVERRIDE_C=containerEnv" ,
1327
+ "CONTAINER_OVERRIDE_CR=remoteEnv" ,
1328
+ "CONTAINER_OVERRIDE_R=remoteEnv" ,
1329
+ }
1330
+
1331
+ srv := gittest .CreateGitServer (t , gittest.Options {
1332
+ Files : map [string ]string {
1333
+ ".devcontainer/Dockerfile" : fmt .Sprintf (`
1334
+ FROM %s
1335
+ ENV FROM_CONTAINER=container
1336
+ ENV CONTAINER_OVERRIDE_C=container
1337
+ ENV CONTAINER_OVERRIDE_CR=container
1338
+ ENV CONTAINER_OVERRIDE_R=container
1339
+ ` , testImageAlpine ),
1340
+ ".devcontainer/devcontainer.json" : `
1341
+ {
1342
+ "dockerFile": "Dockerfile",
1343
+ "containerEnv": {
1344
+ "CONTAINER_OVERRIDE_C": "containerEnv",
1345
+ "CONTAINER_OVERRIDE_CR": "containerEnv",
1346
+ "FROM_CONTAINER_ENV": "containerEnv",
1347
+ },
1348
+ "remoteEnv": {
1349
+ "CONTAINER_OVERRIDE_CR": "remoteEnv",
1350
+ "CONTAINER_OVERRIDE_R": "remoteEnv",
1351
+ "FROM_REMOTE_ENV": "remoteEnv",
1352
+ },
1353
+ "onCreateCommand": "echo onCreateCommand",
1354
+ "postCreateCommand": "echo postCreateCommand",
1355
+ }
1356
+ ` ,
1357
+ },
1358
+ })
1359
+
1360
+ // Given: an empty registry
1361
+ testReg := setupInMemoryRegistry (t , setupInMemoryRegistryOpts {})
1362
+ testRepo := testReg + "/test"
1363
+ ref , err := name .ParseReference (testRepo + ":latest" )
1364
+ require .NoError (t , err )
1365
+ _ , err = remote .Image (ref )
1366
+ require .ErrorContains (t , err , "NAME_UNKNOWN" , "expected image to not be present before build + push" )
1367
+
1368
+ opts := []string {
1369
+ envbuilderEnv ("GIT_URL" , srv .URL ),
1370
+ envbuilderEnv ("CACHE_REPO" , testRepo ),
1371
+ envbuilderEnv ("INIT_SCRIPT" , "echo '[start]' && whoami && env && echo '[end]'" ),
1372
+ envbuilderEnv ("INIT_COMMAND" , "/bin/ash" ),
1373
+ }
1374
+
1375
+ // When: we run envbuilder with PUSH_IMAGE set
1376
+ ctrID , err := runEnvbuilder (t , runOpts {env : append (opts , envbuilderEnv ("PUSH_IMAGE" , "1" ))})
1377
+ require .NoError (t , err , "envbuilder push image failed" )
1378
+
1379
+ cli , err := client .NewClientWithOpts (client .FromEnv , client .WithAPIVersionNegotiation ())
1380
+ require .NoError (t , err )
1381
+ defer cli .Close ()
1382
+
1383
+ var started bool
1384
+ var wantEnv , gotEnv []string
1385
+ logs , _ := streamContainerLogs (t , cli , ctrID )
1386
+ for {
1387
+ log := <- logs
1388
+ if log == "[start]" {
1389
+ started = true
1390
+ continue
1391
+ }
1392
+ if log == "[end]" {
1393
+ break
1394
+ }
1395
+ if started {
1396
+ wantEnv = append (wantEnv , log )
1397
+ }
1398
+ }
1399
+ started = false
1400
+
1401
+ // Then: re-running envbuilder with GET_CACHED_IMAGE should succeed
1402
+ cachedRef := getCachedImage (ctx , t , cli , opts ... )
1403
+
1404
+ // When: we run the image we just built
1405
+ ctrID , err = runEnvbuilder (t , runOpts {
1406
+ image : cachedRef .String (),
1407
+ env : opts ,
1408
+ })
1409
+ require .NoError (t , err , "envbuilder run cached image failed" )
1410
+
1411
+ logs , _ = streamContainerLogs (t , cli , ctrID )
1412
+ for {
1413
+ log := <- logs
1414
+ if log == "[start]" {
1415
+ started = true
1416
+ continue
1417
+ }
1418
+ if log == "[end]" {
1419
+ break
1420
+ }
1421
+ if started {
1422
+ gotEnv = append (gotEnv , log )
1423
+ }
1424
+ }
1425
+
1426
+ slices .Sort (wantEnv )
1427
+ slices .Sort (gotEnv )
1428
+ if diff := cmp .Diff (wantEnv , gotEnv ); diff != "" {
1429
+ t .Fatalf ("unexpected output (-want +got):\n %s" , diff )
1430
+ }
1431
+
1432
+ for _ , want := range wantOverrides {
1433
+ assert .Contains (t , gotEnv , want , "expected env var %q to be present" , want )
1434
+ }
1435
+ })
1436
+
1315
1437
t .Run ("CacheAndPushWithNoChangeLayers" , func (t * testing.T ) {
1316
1438
t .Parallel ()
1317
1439
@@ -2003,7 +2125,7 @@ func startContainerFromRef(ctx context.Context, t *testing.T, cli *client.Client
2003
2125
rc , err := cli .ImagePull (ctx , ref .String (), image.PullOptions {})
2004
2126
require .NoError (t , err )
2005
2127
t .Cleanup (func () { _ = rc .Close () })
2006
- _ , err = io .ReadAll ( rc )
2128
+ _ , err = io .Copy ( io . Discard , rc )
2007
2129
require .NoError (t , err )
2008
2130
2009
2131
// Start the container.
@@ -2033,6 +2155,7 @@ func startContainerFromRef(ctx context.Context, t *testing.T, cli *client.Client
2033
2155
}
2034
2156
2035
2157
type runOpts struct {
2158
+ image string
2036
2159
binds []string
2037
2160
env []string
2038
2161
volumes map [string ]string
@@ -2063,8 +2186,18 @@ func runEnvbuilder(t *testing.T, opts runOpts) (string, error) {
2063
2186
_ = cli .VolumeRemove (ctx , volName , true )
2064
2187
})
2065
2188
}
2189
+ img := "envbuilder:latest"
2190
+ if opts .image != "" {
2191
+ // Pull the image first so we can start it afterwards.
2192
+ rc , err := cli .ImagePull (ctx , opts .image , image.PullOptions {})
2193
+ require .NoError (t , err , "failed to pull image" )
2194
+ t .Cleanup (func () { _ = rc .Close () })
2195
+ _ , err = io .Copy (io .Discard , rc )
2196
+ require .NoError (t , err , "failed to read image pull response" )
2197
+ img = opts .image
2198
+ }
2066
2199
ctr , err := cli .ContainerCreate (ctx , & container.Config {
2067
- Image : "envbuilder:latest" ,
2200
+ Image : img ,
2068
2201
Env : opts .env ,
2069
2202
Labels : map [string ]string {
2070
2203
testContainerLabel : "true" ,
0 commit comments