diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index 3530b7a191311..ad5f751b6d6f0 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -1052,13 +1052,14 @@ COPY --from=base unique / } func testEmptyWildcard(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch COPY foo nomatch* / -`) +`, ` +FROM nanoserver +COPY foo nomatch* /`)) dir := integration.Tmpdir( t, @@ -1092,16 +1093,20 @@ COPY foo nomatch* / } func testWorkdirUser(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM busybox RUN adduser -D user USER user WORKDIR /mydir RUN [ "$(stat -c "%U %G" /mydir)" == "user user" ] -`) +`, + ` +FROM nanoserver +USER ContainerAdministrator +WORKDIR \mydir +RUN icacls \mydir | findstr Administrators >nul || exit /b 1`)) dir := integration.Tmpdir( t, @@ -1122,19 +1127,28 @@ RUN [ "$(stat -c "%U %G" /mydir)" == "user user" ] } func testOutOfOrderStage(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) + dockerfile := integration.UnixOrWindows( + ` + FROM busybox AS target + COPY --from=build %s /out + + FROM alpine AS build + COPY /Dockerfile /d2 + + FROM target + `, + ` + FROM nanoserver AS target + COPY --from=build %s /out - for _, src := range []string{"/", "/d2"} { - dockerfile := []byte(fmt.Sprintf(` -FROM busybox AS target -COPY --from=build %s /out - -FROM alpine AS build -COPY /Dockerfile /d2 + FROM nanoserver AS build + COPY /Dockerfile /d2 -FROM target -`, src)) + FROM target + `) + for _, src := range []string{"/", "/d2"} { + dockerfile := []byte(fmt.Sprintf(dockerfile, src)) dir := integration.Tmpdir( t, @@ -1189,16 +1203,22 @@ COPY --from=base Dockerfile . } func testWorkdirExists(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM busybox RUN adduser -D user RUN mkdir /mydir && chown user:user /mydir WORKDIR /mydir RUN [ "$(stat -c "%U %G" /mydir)" == "user user" ] -`) +`, ` +FROM nanoserver +USER ContainerAdministrator +RUN mkdir \mydir +RUN net user testuser Password!2345!@# /add /y +RUN icacls \mydir /grant testuser:F +WORKDIR /mydir +RUN (icacls \mydir | findstr "testuser" >nul) || exit /b 1`)) dir := integration.Tmpdir( t, @@ -2473,13 +2493,14 @@ func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) { } func testDockerfileInvalidInstruction(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) f.RequiresBuildctl(t) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch FNTRYPOINT ["/bin/sh", "-c", "echo invalidinstruction"] -`) +`, ` + FROM nanoserver + FNTRYPOINT ["cmd", "/c", "echo invalidinstruction"]`)) dir := integration.Tmpdir( t, @@ -2735,7 +2756,6 @@ ADD %s /newname.tar.gz } func testDockerfileAddArchiveWildcard(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) buf := bytes.NewBuffer(nil) @@ -2768,10 +2788,12 @@ func testDockerfileAddArchiveWildcard(t *testing.T, sb integration.Sandbox) { err = tw.Close() require.NoError(t, err) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch ADD *.tar /dest -`) +`, ` +FROM nanoserver +ADD *.tar /dest`)) dir := integration.Tmpdir( t, @@ -2888,7 +2910,6 @@ COPY foo /symlink/ } func testDockerfileScratchConfig(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") cdAddress := sb.ContainerdAddress() if cdAddress == "" { t.Skip("test requires containerd worker") @@ -2896,10 +2917,13 @@ func testDockerfileScratchConfig(t *testing.T, sb integration.Sandbox) { f := getFrontend(t, sb) f.RequiresBuildctl(t) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch ENV foo=bar -`) +`, ` +FROM nanoserver +ENV foo=bar +`)) dir := integration.Tmpdir( t, @@ -2935,14 +2959,17 @@ ENV foo=bar require.NotEqual(t, "", ociimg.OS) require.NotEqual(t, "", ociimg.Architecture) - require.NotEqual(t, "", ociimg.Config.WorkingDir) require.Equal(t, "layers", ociimg.RootFS.Type) - require.Equal(t, 0, len(ociimg.RootFS.DiffIDs)) - - require.Equal(t, 1, len(ociimg.History)) - require.Contains(t, ociimg.History[0].CreatedBy, "ENV foo=bar") - require.Equal(t, true, ociimg.History[0].EmptyLayer) + if runtime.GOOS == "windows" { + require.Equal(t, "", ociimg.Config.WorkingDir) + } else { + require.NotEqual(t, "", ociimg.Config.WorkingDir) + } + require.Equal(t, integration.UnixOrWindows(0, 1), len(ociimg.RootFS.DiffIDs)) + require.Equal(t, integration.UnixOrWindows(1, 2), len(ociimg.History)) + require.Contains(t, integration.UnixOrWindows(ociimg.History[0].CreatedBy, ociimg.History[1].CreatedBy), "ENV foo=bar") + require.Equal(t, integration.UnixOrWindows(true, false), ociimg.History[0].EmptyLayer) require.Contains(t, ociimg.Config.Env, "foo=bar") require.Condition(t, func() bool { for _, env := range ociimg.Config.Env { @@ -2955,16 +2982,19 @@ ENV foo=bar } func testExposeExpansion(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") workers.CheckFeatureCompat(t, sb, workers.FeatureImageExporter) f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch ARG PORTS="3000 4000/udp" EXPOSE $PORTS EXPOSE 5000 -`) +`, ` +FROM nanoserver +ARG PORTS="3000 4000/udp" +EXPOSE $PORTS +EXPOSE 5000`)) dir := integration.Tmpdir( t, @@ -3031,13 +3061,14 @@ EXPOSE 5000 } func testDockerignore(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch COPY . . -`) +`, ` +FROM nanoserver +COPY . .`)) dockerignore := []byte(` ba* @@ -3102,13 +3133,14 @@ Dockerfile } func testDockerignoreInvalid(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch COPY . . -`) +`, ` +FROM nanoserver +COPY . .`)) dir := integration.Tmpdir( t, @@ -3141,11 +3173,10 @@ COPY . . // moby/moby#10858 func testDockerfileLowercase(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(`FROM scratch -`) + dockerfile := []byte(integration.UnixOrWindows(`FROM scratch +`, `FROM nanoserver`)) dir := integration.Tmpdir( t, @@ -4237,14 +4268,15 @@ COPY --from=stage1 baz bax } func testLabels(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") workers.CheckFeatureCompat(t, sb, workers.FeatureImageExporter) f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch LABEL foo=bar -`) +`, ` +FROM nanoserver +LABEL foo=bar`)) dir := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), @@ -4309,14 +4341,16 @@ LABEL foo=bar // #2008 func testWildcardRenameCache(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM alpine COPY file* /files/ RUN ls /files/file1 -`) +`, ` +FROM nanoserver +COPY file* / +RUN dir file1`)) dir := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), @@ -4776,16 +4810,20 @@ COPY --from=base unique / } func testReproducibleIDs(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") workers.CheckFeatureCompat(t, sb, workers.FeatureImageExporter) f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM busybox ENV foo=bar COPY foo / RUN echo bar > bar -`) +`, ` +FROM nanoserver +USER ContainerAdministrator +ENV foo=bar +COPY foo / +RUN echo bar > bar`)) dir := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), @@ -5011,15 +5049,20 @@ COPY --from=s1 unique2 / } func testPlatformArgsImplicit(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(fmt.Sprintf(` + dockerfileTemplate := integration.UnixOrWindows(` FROM scratch AS build-%s COPY foo bar FROM build-${TARGETOS} COPY foo2 bar2 -`, runtime.GOOS)) +`, ` +FROM nanoserver AS build-%s +COPY foo bar +FROM build-${TARGETOS} +COPY foo2 bar2`) + + dockerfile := []byte(fmt.Sprintf(dockerfileTemplate, runtime.GOOS)) dir := integration.Tmpdir( t, @@ -5223,8 +5266,7 @@ func testTarContext(t *testing.T, sb integration.Sandbox) { dockerfile := []byte(` FROM scratch -COPY foo / -`) +COPY foo /`) foo := []byte("contents") @@ -5400,15 +5442,16 @@ COPY foo foo2 } func testFrontendEvaluate(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") c, err := client.New(sb.Context(), sb.Address()) require.NoError(t, err) defer c.Close() - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch COPY badfile / -`) +`, ` +FROM nanoserver +COPY badfile /`)) dir := integration.Tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) frontend := func(ctx context.Context, c gateway.Client) (*gateway.Result, error) { @@ -5418,10 +5461,11 @@ COPY badfile / }) require.ErrorContains(t, err, `"/badfile": not found`) + platformOpt := integration.UnixOrWindows("linux/amd64,linux/arm64", "windows/amd64") _, err = c.Solve(ctx, gateway.SolveRequest{ Frontend: "dockerfile.v0", FrontendOpt: map[string]string{ - "platform": "linux/amd64,linux/arm64", + "platform": platformOpt, }, Evaluate: true, }) @@ -5502,7 +5546,6 @@ COPY foo foo2 } func testFrontendSubrequests(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) if _, ok := f.(*clientFrontend); !ok { t.Skip("only test with client frontend") @@ -5512,10 +5555,12 @@ func testFrontendSubrequests(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) defer c.Close() - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows(` FROM scratch COPY Dockerfile Dockerfile -`) +`, ` +FROM nanoserver +COPY Dockerfile Dockerfile`)) dir := integration.Tmpdir( t, diff --git a/util/testutil/integration/sandbox.go b/util/testutil/integration/sandbox.go index 685458b1c339b..4049176a7c7fc 100644 --- a/util/testutil/integration/sandbox.go +++ b/util/testutil/integration/sandbox.go @@ -59,6 +59,8 @@ func (sb *sandbox) NewRegistry() (string, error) { func (sb *sandbox) Cmd(args ...string) *exec.Cmd { if len(args) == 1 { + // \\ being stripped off for Windows paths, convert to unix style + args[0] = strings.ReplaceAll(args[0], "\\", "/") if split, err := shlex.Split(args[0]); err == nil { args = split }