Skip to content

Commit b065656

Browse files
authored
feat: set user, workdir, entrypoint when pushing image (#246)
1 parent 48c8fa3 commit b065656

File tree

2 files changed

+53
-70
lines changed

2 files changed

+53
-70
lines changed

envbuilder.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,11 @@ func Run(ctx context.Context, options Options) error {
420420
return xerrors.Errorf("add exe path to ignore list: %w", err)
421421
}
422422
// Copy the envbuilder binary into the build context.
423-
buildParams.DockerfileContent += fmt.Sprintf("\nCOPY %s %s", exePath, exePath)
423+
buildParams.DockerfileContent += fmt.Sprintf(`
424+
COPY --chmod=0755 %s %s
425+
USER root
426+
WORKDIR /
427+
ENTRYPOINT [%q]`, exePath, exePath, exePath)
424428
dst := filepath.Join(buildParams.BuildContext, exePath)
425429
if err := copyFile(exePath, dst); err != nil {
426430
return xerrors.Errorf("copy running binary to build context: %w", err)

integration/integration_test.go

+48-69
Original file line numberDiff line numberDiff line change
@@ -1138,16 +1138,63 @@ func TestPushImage(t *testing.T) {
11381138
require.NoError(t, err)
11391139

11401140
// Then: the image should be pushed
1141-
_, err = remote.Image(ref)
1141+
img, err := remote.Image(ref)
11421142
require.NoError(t, err, "expected image to be present after build + push")
11431143

1144+
// Then: the image should have its directives replaced with those required
1145+
// to run envbuilder automatically
1146+
configFile, err := img.ConfigFile()
1147+
require.NoError(t, err, "expected image to return a config file")
1148+
1149+
assert.Equal(t, "root", configFile.Config.User, "user must be root")
1150+
assert.Equal(t, "/", configFile.Config.WorkingDir, "workdir must be /")
1151+
if assert.Len(t, configFile.Config.Entrypoint, 1) {
1152+
assert.Equal(t, "/.envbuilder/bin/envbuilder", configFile.Config.Entrypoint[0], "incorrect entrypoint")
1153+
}
1154+
11441155
// Then: re-running envbuilder with GET_CACHED_IMAGE should succeed
11451156
_, err = runEnvbuilder(t, options{env: []string{
11461157
envbuilderEnv("GIT_URL", srv.URL),
11471158
envbuilderEnv("CACHE_REPO", testRepo),
11481159
envbuilderEnv("GET_CACHED_IMAGE", "1"),
11491160
}})
11501161
require.NoError(t, err)
1162+
1163+
// When: we pull the image we just built
1164+
ctx, cancel := context.WithCancel(context.Background())
1165+
t.Cleanup(cancel)
1166+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
1167+
require.NoError(t, err)
1168+
defer cli.Close()
1169+
rc, err := cli.ImagePull(ctx, ref.String(), image.PullOptions{})
1170+
require.NoError(t, err)
1171+
t.Cleanup(func() { _ = rc.Close() })
1172+
_, err = io.ReadAll(rc)
1173+
require.NoError(t, err)
1174+
1175+
// When: we run the image we just built
1176+
ctr, err := cli.ContainerCreate(ctx, &container.Config{
1177+
Image: ref.String(),
1178+
Entrypoint: []string{"sleep", "infinity"},
1179+
Labels: map[string]string{
1180+
testContainerLabel: "true",
1181+
},
1182+
}, nil, nil, nil, "")
1183+
require.NoError(t, err)
1184+
t.Cleanup(func() {
1185+
_ = cli.ContainerRemove(ctx, ctr.ID, container.RemoveOptions{
1186+
RemoveVolumes: true,
1187+
Force: true,
1188+
})
1189+
})
1190+
err = cli.ContainerStart(ctx, ctr.ID, container.StartOptions{})
1191+
require.NoError(t, err)
1192+
1193+
// Then: the envbuilder binary exists in the image!
1194+
out := execContainer(t, ctr.ID, "/.envbuilder/bin/envbuilder --help")
1195+
require.Regexp(t, `(?s)^USAGE:\s+envbuilder`, strings.TrimSpace(out))
1196+
out = execContainer(t, ctr.ID, "cat /root/date.txt")
1197+
require.NotEmpty(t, strings.TrimSpace(out))
11511198
})
11521199

11531200
t.Run("CacheAndPushAuth", func(t *testing.T) {
@@ -1397,74 +1444,6 @@ COPY --from=a /root/date.txt /date.txt`, testImageAlpine, testImageAlpine),
13971444
})
13981445
}
13991446

1400-
func TestEmbedBinaryImage(t *testing.T) {
1401-
t.Parallel()
1402-
1403-
srv := createGitServer(t, gitServerOptions{
1404-
files: map[string]string{
1405-
".devcontainer/Dockerfile": fmt.Sprintf("FROM %s\nRUN date --utc > /root/date.txt", testImageAlpine),
1406-
".devcontainer/devcontainer.json": `{
1407-
"name": "Test",
1408-
"build": {
1409-
"dockerfile": "Dockerfile"
1410-
},
1411-
}`,
1412-
},
1413-
})
1414-
1415-
testReg := setupInMemoryRegistry(t, setupInMemoryRegistryOpts{})
1416-
testRepo := testReg + "/test-embed-binary-image"
1417-
ref, err := name.ParseReference(testRepo + ":latest")
1418-
require.NoError(t, err)
1419-
1420-
_, err = runEnvbuilder(t, options{env: []string{
1421-
envbuilderEnv("GIT_URL", srv.URL),
1422-
envbuilderEnv("CACHE_REPO", testRepo),
1423-
envbuilderEnv("PUSH_IMAGE", "1"),
1424-
}})
1425-
require.NoError(t, err)
1426-
1427-
_, err = remote.Image(ref)
1428-
require.NoError(t, err, "expected image to be present after build + push")
1429-
1430-
ctx := context.Background()
1431-
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
1432-
require.NoError(t, err)
1433-
t.Cleanup(func() {
1434-
cli.Close()
1435-
})
1436-
1437-
// Pull the image we just built
1438-
rc, err := cli.ImagePull(ctx, ref.String(), image.PullOptions{})
1439-
require.NoError(t, err)
1440-
t.Cleanup(func() { _ = rc.Close() })
1441-
_, err = io.ReadAll(rc)
1442-
require.NoError(t, err)
1443-
1444-
// Run it
1445-
ctr, err := cli.ContainerCreate(ctx, &container.Config{
1446-
Image: ref.String(),
1447-
Cmd: []string{"sleep", "infinity"},
1448-
Labels: map[string]string{
1449-
testContainerLabel: "true",
1450-
},
1451-
}, nil, nil, nil, "")
1452-
require.NoError(t, err)
1453-
t.Cleanup(func() {
1454-
_ = cli.ContainerRemove(ctx, ctr.ID, container.RemoveOptions{
1455-
RemoveVolumes: true,
1456-
Force: true,
1457-
})
1458-
})
1459-
err = cli.ContainerStart(ctx, ctr.ID, container.StartOptions{})
1460-
require.NoError(t, err)
1461-
1462-
out := execContainer(t, ctr.ID, "[[ -f \"/.envbuilder/bin/envbuilder\" ]] && echo \"exists\"")
1463-
require.Equal(t, "exists", strings.TrimSpace(out))
1464-
out = execContainer(t, ctr.ID, "cat /root/date.txt")
1465-
require.NotEmpty(t, strings.TrimSpace(out))
1466-
}
1467-
14681447
func TestChownHomedir(t *testing.T) {
14691448
t.Parallel()
14701449

0 commit comments

Comments
 (0)