Skip to content

Commit 8239008

Browse files
committed
add test to compare built and cached image env
1 parent 9c26443 commit 8239008

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

envbuilder.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,9 @@ func run(ctx context.Context, opts options.Options, execArgs *execArgsInfo) erro
678678
runtimeData.ContainerUser = configFile.Config.User
679679
}
680680
} else {
681-
devcontainerPath, _, err := findDevcontainerJSON(opts.WorkspaceFolder, opts)
681+
runtimeData.DevcontainerPath, _, err = findDevcontainerJSON(opts.WorkspaceFolder, opts)
682682
if err == nil {
683-
file, err := opts.Filesystem.Open(devcontainerPath)
683+
file, err := opts.Filesystem.Open(runtimeData.DevcontainerPath)
684684
if err != nil {
685685
return fmt.Errorf("open devcontainer.json: %w", err)
686686
}

integration/integration_test.go

+135-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"os/exec"
1919
"path/filepath"
2020
"regexp"
21+
"slices"
2122
"strings"
2223
"testing"
2324
"time"
@@ -39,6 +40,7 @@ import (
3940
"github.com/docker/docker/api/types/volume"
4041
"github.com/docker/docker/client"
4142
"github.com/docker/docker/pkg/stdcopy"
43+
"github.com/google/go-cmp/cmp"
4244
"github.com/google/go-containerregistry/pkg/authn"
4345
"github.com/google/go-containerregistry/pkg/name"
4446
"github.com/google/go-containerregistry/pkg/registry"
@@ -1312,6 +1314,126 @@ RUN date --utc > /root/date.txt`, testImageAlpine),
13121314
require.NotEmpty(t, strings.TrimSpace(out))
13131315
})
13141316

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+
13151437
t.Run("CacheAndPushWithNoChangeLayers", func(t *testing.T) {
13161438
t.Parallel()
13171439

@@ -2003,7 +2125,7 @@ func startContainerFromRef(ctx context.Context, t *testing.T, cli *client.Client
20032125
rc, err := cli.ImagePull(ctx, ref.String(), image.PullOptions{})
20042126
require.NoError(t, err)
20052127
t.Cleanup(func() { _ = rc.Close() })
2006-
_, err = io.ReadAll(rc)
2128+
_, err = io.Copy(io.Discard, rc)
20072129
require.NoError(t, err)
20082130

20092131
// Start the container.
@@ -2033,6 +2155,7 @@ func startContainerFromRef(ctx context.Context, t *testing.T, cli *client.Client
20332155
}
20342156

20352157
type runOpts struct {
2158+
image string
20362159
binds []string
20372160
env []string
20382161
volumes map[string]string
@@ -2063,8 +2186,18 @@ func runEnvbuilder(t *testing.T, opts runOpts) (string, error) {
20632186
_ = cli.VolumeRemove(ctx, volName, true)
20642187
})
20652188
}
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+
}
20662199
ctr, err := cli.ContainerCreate(ctx, &container.Config{
2067-
Image: "envbuilder:latest",
2200+
Image: img,
20682201
Env: opts.env,
20692202
Labels: map[string]string{
20702203
testContainerLabel: "true",

options/options.go

+4
Original file line numberDiff line numberDiff line change
@@ -573,4 +573,8 @@ func UnsetEnv() {
573573
_ = os.Unsetenv(opt.Env)
574574
_ = os.Unsetenv(strings.TrimPrefix(opt.Env, envPrefix))
575575
}
576+
577+
// Unset the Kaniko environment variable which we set it in the
578+
// Dockerfile to ensure correct behavior during building.
579+
_ = os.Unsetenv("KANIKO_DIR")
576580
}

0 commit comments

Comments
 (0)