diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index ce91d8166c257..00741ac5133da 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -37,6 +37,41 @@ import ( "github.com/stretchr/testify/require" ) +var opts []integration.TestOpt + +type frontend interface { + Solve(context.Context, *client.Client, client.SolveOpt, chan *client.SolveStatus) (*client.SolveResponse, error) + DFCmdArgs(string, string) (string, string) + RequiresBuildctl(t *testing.T) +} + +func init() { + frontends := map[string]interface{}{} + + opts = []integration.TestOpt{ + integration.WithMirroredImages(integration.OfficialImages("busybox:latest")), + integration.WithMirroredImages(map[string]string{ + "tonistiigi/copy:v0.1.4": "docker.io/" + dockerfile2llb.DefaultCopyImage, + }), + integration.WithMatrix("frontend", frontends), + } + + if os.Getenv("FRONTEND_BUILTIN_ONLY") == "1" { + frontends["builtin"] = &builtinFrontend{} + } else if os.Getenv("FRONTEND_CLIENT_ONLY") == "1" { + frontends["client"] = &clientFrontend{} + } else if gw := os.Getenv("FRONTEND_GATEWAY_ONLY"); gw != "" { + name := "buildkit_test/" + identity.NewID() + ":latest" + opts = append(opts, integration.WithMirroredImages(map[string]string{ + name: gw, + })) + frontends["gateway"] = &gatewayFrontend{gw: name} + } else { + frontends["builtin"] = &builtinFrontend{} + frontends["client"] = &clientFrontend{} + } +} + func TestIntegration(t *testing.T) { integration.Run(t, []integration.Test{ testNoSnapshotLeak, @@ -77,16 +112,12 @@ func TestIntegration(t *testing.T) { testExportMultiPlatform, testQuotedMetaArgs, testIgnoreEntrypoint, - }, - integration.WithMirroredImages(integration.OfficialImages("busybox:latest")), - integration.WithMirroredImages(map[string]string{ - "tonistiigi/copy:v0.1.4": "docker.io/" + dockerfile2llb.DefaultCopyImage, - }), - ) + }, opts...) } func testIgnoreEntrypoint(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox @@ -104,8 +135,7 @@ RUN ["ls"] require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -116,6 +146,7 @@ RUN ["ls"] func testQuotedMetaArgs(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` ARG a1="box" @@ -142,8 +173,7 @@ COPY --from=build /out . require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -160,6 +190,7 @@ COPY --from=build /out . func testExportMultiPlatform(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -187,8 +218,7 @@ COPY arch-$TARGETARCH whoami require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -223,8 +253,7 @@ COPY arch-$TARGETARCH whoami outW, err := os.Create(out) require.NoError(t, err) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -294,6 +323,7 @@ COPY arch-$TARGETARCH whoami // tonistiigi/fsutil#46 func testContextChangeDirToFile(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -312,8 +342,7 @@ COPY foo / require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -332,8 +361,7 @@ COPY foo / require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -350,6 +378,7 @@ COPY foo / func testNoSnapshotLeak(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -367,8 +396,7 @@ COPY foo / require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -379,8 +407,7 @@ COPY foo / du, err := c.DiskUsage(context.TODO()) require.NoError(t, err) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -396,6 +423,7 @@ COPY foo / func testCopySymlinks(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -422,8 +450,7 @@ COPY sub/l* alllinks/ require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -434,6 +461,7 @@ COPY sub/l* alllinks/ func testHTTPDockerfile(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox @@ -467,8 +495,7 @@ COPY --from=0 /foo /foo require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "context": server.URL + "/df", "filename": "mydockerfile", // this is bogus, any name should work @@ -486,6 +513,7 @@ COPY --from=0 /foo /foo func testCmdShell(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) var cdAddress string if cd, ok := sb.(interface { @@ -512,8 +540,7 @@ CMD ["test"] defer c.Close() target := "docker.io/moby/cmdoverridetest:latest" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ "name": target, @@ -538,8 +565,7 @@ ENTRYPOINT my entrypoint defer os.RemoveAll(dir) target = "docker.io/moby/cmdoverridetest2:latest" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ "name": target, @@ -576,6 +602,7 @@ ENTRYPOINT my entrypoint func testPullScratch(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) var cdAddress string if cd, ok := sb.(interface { @@ -602,8 +629,7 @@ LABEL foo=bar defer c.Close() target := "docker.io/moby/testpullscratch:latest" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ "name": target, @@ -629,8 +655,7 @@ COPY foo . defer os.RemoveAll(dir) target = "docker.io/moby/testpullscratch2:latest" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ "name": target, @@ -698,6 +723,8 @@ COPY foo . func testGlobalArg(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + dockerfile := []byte(` ARG tag=nosuchtag FROM busybox:${tag} @@ -713,8 +740,7 @@ FROM busybox:${tag} require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "build-arg:tag": "latest", }, @@ -728,6 +754,9 @@ FROM busybox:${tag} func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) + dockerfile := []byte(` FROM busybox COPY foo /foo2 @@ -745,7 +774,7 @@ func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) cmd := sb.Cmd(args) @@ -755,7 +784,7 @@ func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) // relative urls - args, trace = dfCmdArgs(".", ".") + args, trace = f.DFCmdArgs(".", ".") defer os.RemoveAll(trace) cmd = sb.Cmd(args) @@ -778,7 +807,7 @@ func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) defer os.RemoveAll(dir2) - args, trace = dfCmdArgs(dir2, dir1) + args, trace = f.DFCmdArgs(dir2, dir1) defer os.RemoveAll(trace) cmd = sb.Cmd(args) @@ -794,6 +823,8 @@ func testDockerfileDirs(t *testing.T, sb integration.Sandbox) { func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) dockerfile := []byte(` FROM busybox RUN invalidcmd @@ -805,7 +836,7 @@ func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) cmd := sb.Cmd(args) @@ -819,6 +850,8 @@ func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) { func testDockerfileADDFromURL(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) modTime := time.Now().Add(-24 * time.Hour) // avoid falso positive with current time @@ -850,7 +883,7 @@ ADD %s /dest/ require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err := tmpdir() @@ -877,7 +910,7 @@ ADD %s /dest/ require.NoError(t, err) defer os.RemoveAll(dir) - args, trace = dfCmdArgs(dir, dir) + args, trace = f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err = tmpdir() @@ -900,6 +933,8 @@ ADD %s /dest/ func testDockerfileAddArchive(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) buf := bytes.NewBuffer(nil) tw := tar.NewWriter(buf) @@ -928,7 +963,7 @@ ADD t.tar / require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err := tmpdir() @@ -962,7 +997,7 @@ ADD t.tar.gz / require.NoError(t, err) defer os.RemoveAll(dir) - args, trace = dfCmdArgs(dir, dir) + args, trace = f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err = tmpdir() @@ -989,7 +1024,7 @@ COPY t.tar.gz / require.NoError(t, err) defer os.RemoveAll(dir) - args, trace = dfCmdArgs(dir, dir) + args, trace = f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err = tmpdir() @@ -1025,7 +1060,7 @@ ADD %s / require.NoError(t, err) defer os.RemoveAll(dir) - args, trace = dfCmdArgs(dir, dir) + args, trace = f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err = tmpdir() @@ -1051,7 +1086,7 @@ ADD %s /newname.tar.gz require.NoError(t, err) defer os.RemoveAll(dir) - args, trace = dfCmdArgs(dir, dir) + args, trace = f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err = tmpdir() @@ -1068,6 +1103,8 @@ ADD %s /newname.tar.gz func testSymlinkDestination(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) buf := bytes.NewBuffer(nil) tw := tar.NewWriter(buf) @@ -1096,7 +1133,7 @@ COPY foo /symlink/ require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) destDir, err := tmpdir() @@ -1122,6 +1159,8 @@ func testDockerfileScratchConfig(t *testing.T, sb integration.Sandbox) { } t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) dockerfile := []byte(` FROM scratch ENV foo=bar @@ -1133,7 +1172,7 @@ ENV foo=bar require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) target := "example.com/moby/dockerfilescratch:test" @@ -1183,6 +1222,7 @@ ENV foo=bar func testExposeExpansion(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -1202,8 +1242,7 @@ EXPOSE 5000 defer c.Close() target := "example.com/moby/dockerfileexpansion:test" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ "name": target, @@ -1259,6 +1298,7 @@ EXPOSE 5000 func testDockerignore(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -1291,8 +1331,7 @@ Dockerfile require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -1329,6 +1368,7 @@ Dockerfile func testDockerignoreInvalid(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -1349,8 +1389,7 @@ COPY . . require.NoError(t, err) defer c.Close() - _, err = c.Solve(ctx, nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(ctx, c, client.SolveOpt{ LocalDirs: map[string]string{ builder.LocalNameDockerfile: dir, builder.LocalNameContext: dir, @@ -1367,6 +1406,8 @@ COPY . . func testExportedHistory(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) + f.RequiresBuildctl(t) // using multi-stage to test that history is scoped to one stage dockerfile := []byte(` @@ -1387,7 +1428,7 @@ RUN ["ls"] require.NoError(t, err) defer os.RemoveAll(dir) - args, trace := dfCmdArgs(dir, dir) + args, trace := f.DFCmdArgs(dir, dir) defer os.RemoveAll(trace) target := "example.com/moby/dockerfilescratch:test" @@ -1445,6 +1486,7 @@ func testUser(t *testing.T, sb integration.Sandbox) { } t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox AS base @@ -1520,8 +1562,7 @@ USER nobody require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -1541,8 +1582,7 @@ USER nobody // test user in exported target := "example.com/moby/dockerfileuser:test" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ "name": target, @@ -1587,6 +1627,7 @@ USER nobody func testCopyChown(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox AS base @@ -1616,8 +1657,7 @@ COPY --from=base /out / require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -1638,6 +1678,7 @@ COPY --from=base /out / func testCopyOverrideFiles(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch AS base @@ -1668,8 +1709,7 @@ COPY files dest require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -1690,6 +1730,7 @@ COPY files dest func testCopyVarSubstitution(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch AS base @@ -1713,8 +1754,7 @@ COPY $FOO baz require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -1731,6 +1771,7 @@ COPY $FOO baz func testCopyWildcards(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch AS base @@ -1765,8 +1806,7 @@ COPY sub/dir1 subdest6 require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -1819,6 +1859,7 @@ COPY sub/dir1 subdest6 func testDockerfileFromGit(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) gitDir, err := ioutil.TempDir("", "buildkit") require.NoError(t, err) @@ -1869,8 +1910,7 @@ COPY --from=build foo bar2 require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "context": server.URL + "/.git#first", }, @@ -1892,8 +1932,7 @@ COPY --from=build foo bar2 require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "context": server.URL + "/.git", }, @@ -1913,6 +1952,7 @@ COPY --from=build foo bar2 func testDockerfileFromHTTP(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) buf := bytes.NewBuffer(nil) w := tar.NewWriter(buf) @@ -1955,8 +1995,7 @@ COPY foo bar require.NoError(t, err) defer c.Close() - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "context": server.URL + "/myurl", "filename": "mydockerfile", @@ -1973,6 +2012,7 @@ COPY foo bar func testMultiStageImplicitFrom(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -1993,8 +2033,7 @@ COPY --from=busybox /etc/passwd test require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -2028,8 +2067,7 @@ COPY --from=golang /usr/bin/go go require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -2046,6 +2084,7 @@ COPY --from=golang /usr/bin/go go func testMultiStageCaseInsensitive(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch AS STAge0 @@ -2070,8 +2109,7 @@ COPY --from=stage1 baz bax require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -2091,6 +2129,7 @@ COPY --from=stage1 baz bax func testLabels(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM scratch @@ -2111,8 +2150,7 @@ LABEL foo=bar defer os.RemoveAll(destDir) target := "example.com/moby/dockerfilelabels:test" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "label:bar": "baz", }, @@ -2166,6 +2204,7 @@ LABEL foo=bar func testCacheImportExport(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) registry, err := sb.NewRegistry() if errors.Cause(err) == integration.ErrorRequirements { @@ -2200,8 +2239,7 @@ COPY --from=base unique / target := registry + "/buildkit/testexportdf:latest" - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ Exporter: client.ExporterLocal, ExporterOutputDir: destDir, ExportCache: target, @@ -2228,8 +2266,7 @@ COPY --from=base unique / require.NoError(t, err) defer os.RemoveAll(destDir) - _, err = c.Solve(context.TODO(), nil, client.SolveOpt{ - Frontend: "dockerfile.v0", + _, err = f.Solve(context.TODO(), c, client.SolveOpt{ FrontendAttrs: map[string]string{ "cache-from": target, }, @@ -2257,6 +2294,7 @@ COPY --from=base unique / func testReproducibleIDs(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox @@ -2281,7 +2319,6 @@ RUN echo bar > bar target := "example.com/moby/dockerfileids:test" opt := client.SolveOpt{ - Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{}, Exporter: client.ExporterImage, ExporterAttrs: map[string]string{ @@ -2293,13 +2330,13 @@ RUN echo bar > bar }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) target2 := "example.com/moby/dockerfileids2:test" opt.ExporterAttrs["name"] = target2 - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) var cdAddress string @@ -2336,6 +2373,7 @@ func testImportExportReproducibleIDs(t *testing.T, sb integration.Sandbox) { } t.Parallel() + f := getFrontend(t, sb) registry, err := sb.NewRegistry() if errors.Cause(err) == integration.ErrorRequirements { @@ -2368,7 +2406,6 @@ RUN echo bar > bar target := "example.com/moby/dockerfileexpids:test" cacheTarget := registry + "/test/dockerfileexpids:cache" opt := client.SolveOpt{ - Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{}, Exporter: client.ExporterImage, ExportCache: cacheTarget, @@ -2387,7 +2424,7 @@ RUN echo bar > bar ctx := namespaces.WithNamespace(context.Background(), "buildkit") - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) img, err := ctd.ImageService().Get(ctx, target) @@ -2406,7 +2443,7 @@ RUN echo bar > bar opt.ExporterAttrs["name"] = target2 opt.FrontendAttrs["cache-from"] = cacheTarget - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) img2, err := ctd.ImageService().Get(ctx, target2) @@ -2417,6 +2454,7 @@ RUN echo bar > bar func testNoCache(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox AS s0 @@ -2442,7 +2480,6 @@ COPY --from=s1 unique2 / defer os.RemoveAll(destDir) opt := client.SolveOpt{ - Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{}, Exporter: client.ExporterLocal, ExporterOutputDir: destDir, @@ -2452,7 +2489,7 @@ COPY --from=s1 unique2 / }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) destDir2, err := ioutil.TempDir("", "buildkit") @@ -2462,7 +2499,7 @@ COPY --from=s1 unique2 / opt.FrontendAttrs["no-cache"] = "" opt.ExporterOutputDir = destDir2 - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) unique1Dir1, err := ioutil.ReadFile(filepath.Join(destDir, "unique")) @@ -2487,7 +2524,7 @@ COPY --from=s1 unique2 / opt.FrontendAttrs["no-cache"] = "s1" opt.ExporterOutputDir = destDir3 - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) unique1Dir3, err := ioutil.ReadFile(filepath.Join(destDir3, "unique")) @@ -2502,6 +2539,7 @@ COPY --from=s1 unique2 / func testPlatformArgsImplicit(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(fmt.Sprintf(` FROM scratch AS build-%s @@ -2527,7 +2565,6 @@ COPY foo2 bar2 defer os.RemoveAll(destDir) opt := client.SolveOpt{ - Frontend: "dockerfile.v0", Exporter: client.ExporterLocal, ExporterOutputDir: destDir, LocalDirs: map[string]string{ @@ -2536,7 +2573,7 @@ COPY foo2 bar2 }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) dt, err := ioutil.ReadFile(filepath.Join(destDir, "bar")) @@ -2550,6 +2587,7 @@ COPY foo2 bar2 func testPlatformArgsExplicit(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM --platform=$BUILDPLATFORM busybox AS build @@ -2575,7 +2613,6 @@ COPY --from=build out . defer os.RemoveAll(destDir) opt := client.SolveOpt{ - Frontend: "dockerfile.v0", Exporter: client.ExporterLocal, FrontendAttrs: map[string]string{ "platform": "darwin/ppc64le", @@ -2588,7 +2625,7 @@ COPY --from=build out . }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) dt, err := ioutil.ReadFile(filepath.Join(destDir, "platform")) @@ -2602,6 +2639,7 @@ COPY --from=build out . func testBuiltinArgs(t *testing.T, sb integration.Sandbox) { t.Parallel() + f := getFrontend(t, sb) dockerfile := []byte(` FROM busybox AS build @@ -2628,7 +2666,6 @@ COPY --from=build /out / defer os.RemoveAll(destDir) opt := client.SolveOpt{ - Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{ "build-arg:FOO": "foocontents", "build-arg:http_proxy": "hpvalue", @@ -2642,7 +2679,7 @@ COPY --from=build /out / }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) dt, err := ioutil.ReadFile(filepath.Join(destDir, "out")) @@ -2655,7 +2692,6 @@ COPY --from=build /out / defer os.RemoveAll(destDir) opt = client.SolveOpt{ - Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{ "build-arg:FOO": "foocontents", "build-arg:http_proxy": "hpvalue2", @@ -2668,7 +2704,7 @@ COPY --from=build /out / }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) dt, err = ioutil.ReadFile(filepath.Join(destDir, "out")) @@ -2681,7 +2717,6 @@ COPY --from=build /out / defer os.RemoveAll(destDir) opt = client.SolveOpt{ - Frontend: "dockerfile.v0", FrontendAttrs: map[string]string{ "build-arg:FOO": "foocontents2", "build-arg:http_proxy": "hpvalue2", @@ -2694,7 +2729,7 @@ COPY --from=build /out / }, } - _, err = c.Solve(context.TODO(), nil, opt, nil) + _, err = f.Solve(context.TODO(), c, opt, nil) require.NoError(t, err) dt, err = ioutil.ReadFile(filepath.Join(destDir, "out")) @@ -2713,11 +2748,6 @@ func tmpdir(appliers ...fstest.Applier) (string, error) { return tmpdir, nil } -func dfCmdArgs(ctx, dockerfile string) (string, string) { - traceFile := filepath.Join(os.TempDir(), "trace"+identity.NewID()) - return fmt.Sprintf("build --progress=plain --frontend dockerfile.v0 --local context=%s --local dockerfile=%s --trace=%s", ctx, dockerfile, traceFile), traceFile -} - func runShell(dir string, cmds ...string) error { for _, args := range cmds { cmd := exec.Command("sh", "-c", args) @@ -2747,3 +2777,67 @@ func checkAllRemoved(t *testing.T, c *client.Client, sb integration.Sandbox) { func newContainerd(cdAddress string) (*containerd.Client, error) { return containerd.New(cdAddress, containerd.WithTimeout(60*time.Second)) } + +func dfCmdArgs(ctx, dockerfile, args string) (string, string) { + traceFile := filepath.Join(os.TempDir(), "trace"+identity.NewID()) + return fmt.Sprintf("build --progress=plain %s --local context=%s --local dockerfile=%s --trace=%s", args, ctx, dockerfile, traceFile), traceFile +} + +type builtinFrontend struct{} + +var _ frontend = &builtinFrontend{} + +func (f *builtinFrontend) Solve(ctx context.Context, c *client.Client, opt client.SolveOpt, statusChan chan *client.SolveStatus) (*client.SolveResponse, error) { + opt.Frontend = "dockerfile.v0" + return c.Solve(ctx, nil, opt, statusChan) +} + +func (f *builtinFrontend) DFCmdArgs(ctx, dockerfile string) (string, string) { + return dfCmdArgs(ctx, dockerfile, "--frontend dockerfile.v0") +} + +func (f *builtinFrontend) RequiresBuildctl(t *testing.T) {} + +type clientFrontend struct{} + +var _ frontend = &clientFrontend{} + +func (f *clientFrontend) Solve(ctx context.Context, c *client.Client, opt client.SolveOpt, statusChan chan *client.SolveStatus) (*client.SolveResponse, error) { + return c.Build(ctx, opt, "", builder.Build, statusChan) +} + +func (f *clientFrontend) DFCmdArgs(ctx, dockerfile string) (string, string) { + return "", "" +} +func (f *clientFrontend) RequiresBuildctl(t *testing.T) { + t.Skip() +} + +type gatewayFrontend struct { + gw string +} + +var _ frontend = &gatewayFrontend{} + +func (f *gatewayFrontend) Solve(ctx context.Context, c *client.Client, opt client.SolveOpt, statusChan chan *client.SolveStatus) (*client.SolveResponse, error) { + opt.Frontend = "gateway.v0" + if opt.FrontendAttrs == nil { + opt.FrontendAttrs = make(map[string]string) + } + opt.FrontendAttrs["source"] = f.gw + return c.Solve(ctx, nil, opt, statusChan) +} + +func (f *gatewayFrontend) DFCmdArgs(ctx, dockerfile string) (string, string) { + return dfCmdArgs(ctx, dockerfile, "--frontend gateway.v0 --frontend-opt=source="+f.gw) +} + +func (f *gatewayFrontend) RequiresBuildctl(t *testing.T) {} + +func getFrontend(t *testing.T, sb integration.Sandbox) frontend { + v := sb.Value("frontend") + require.NotNil(t, v) + fn, ok := v.(frontend) + require.True(t, ok) + return fn +}