diff --git a/.github/workflows/test-os.yml b/.github/workflows/test-os.yml index d60a90a072e3..691e7f948751 100644 --- a/.github/workflows/test-os.yml +++ b/.github/workflows/test-os.yml @@ -174,11 +174,10 @@ jobs: uses: crazy-max/ghaction-dump-context@v2 test-freebsd-amd64: - runs-on: macos-13 + runs-on: ubuntu-22.04 needs: - build env: - VAGRANT_VAGRANTFILE: hack/Vagrantfile.freebsd13 GOOS: freebsd steps: - @@ -195,25 +194,23 @@ jobs: uses: actions/cache@v4 with: path: ~/.vagrant.d/boxes - key: ${{ runner.os }}-vagrant-${{ hashFiles('hack/Vagrantfile.freebsd13') }} + key: ${{ runner.os }}-vagrant-${{ hashFiles('hack/Vagrantfile.freebsd') }} restore-keys: | ${{ runner.os }}-vagrant- - - name: Install vagrant and VirtualBox - run: | - set -x - brew tap hashicorp/tap - brew install hashicorp/tap/hashicorp-vagrant - brew install --cask virtualbox - - - name: Check versions + name: Install vagrant run: | set -x + sudo apt-get update + sudo apt-get install -y libvirt-daemon libvirt-daemon-system vagrant vagrant-libvirt ruby-libvirt + sudo systemctl enable --now libvirtd + sudo chmod a+rw /var/run/libvirt/libvirt-sock + vagrant plugin install vagrant-libvirt vagrant --version - VBoxManage -v - name: Set up vagrant run: | + ln -sf hack/Vagrantfile.freebsd Vagrantfile vagrant up --no-tty - name: Smoke test @@ -233,7 +230,3 @@ jobs: if: always() run: | vagrant ssh -- "sudo cat /vagrant/.tmp/logs/containerd" - - - name: Dump context - if: failure() - uses: crazy-max/ghaction-dump-context@v2 diff --git a/cache/contenthash/checksum.go b/cache/contenthash/checksum.go index 7b592c794f8e..ece58b425508 100644 --- a/cache/contenthash/checksum.go +++ b/cache/contenthash/checksum.go @@ -1034,7 +1034,7 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string, follow scanPath = resolvedPath } - err = filepath.Walk(scanPath, func(itemPath string, fi os.FileInfo, err error) error { + walkFunc := func(itemPath string, fi os.FileInfo, err error) error { if scanCounterEnable { scanCounter.Add(1) } @@ -1073,7 +1073,10 @@ func (cc *cacheContext) scanPath(ctx context.Context, m *mount, p string, follow txn.Insert(k, cr) } return nil - }) + } + + err = cc.walk(scanPath, walkFunc) + if err != nil { return err } diff --git a/cache/contenthash/checksum_unix.go b/cache/contenthash/checksum_unix.go new file mode 100644 index 000000000000..444518ddd814 --- /dev/null +++ b/cache/contenthash/checksum_unix.go @@ -0,0 +1,10 @@ +//go:build !windows +// +build !windows + +package contenthash + +import "path/filepath" + +func (cc *cacheContext) walk(scanPath string, walkFunc filepath.WalkFunc) error { + return filepath.Walk(scanPath, walkFunc) +} diff --git a/cache/contenthash/checksum_windows.go b/cache/contenthash/checksum_windows.go new file mode 100644 index 000000000000..9e0c020230ed --- /dev/null +++ b/cache/contenthash/checksum_windows.go @@ -0,0 +1,16 @@ +package contenthash + +import ( + "path/filepath" + + "github.com/Microsoft/go-winio" +) + +func (cc *cacheContext) walk(scanPath string, walkFunc filepath.WalkFunc) error { + // elevating the admin privileges to walk special files/directory + // like `System Volume Information`, etc. See similar in #4994 + privileges := []string{winio.SeBackupPrivilege} + return winio.RunWithPrivileges(privileges, func() error { + return filepath.Walk(scanPath, walkFunc) + }) +} diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index b34c95b4ec73..6f27cb13067a 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -4404,13 +4404,21 @@ COPY foo bar } func testMultiStageImplicitFrom(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows( + ` FROM scratch COPY --from=busybox /etc/passwd test -`) +`, ` +FROM nanoserver AS build +USER ContainerAdministrator +RUN echo test> test + +FROM nanoserver +COPY --from=build /test /test +`, + )) dir := integration.Tmpdir( t, @@ -4439,17 +4447,26 @@ COPY --from=busybox /etc/passwd test dt, err := os.ReadFile(filepath.Join(destDir, "test")) require.NoError(t, err) - require.Contains(t, string(dt), "root") + require.Contains(t, string(dt), integration.UnixOrWindows("root", "test")) // testing masked image will load actual stage - dockerfile = []byte(` + dockerfile = []byte(integration.UnixOrWindows( + ` FROM busybox AS golang RUN mkdir -p /usr/bin && echo -n foo > /usr/bin/go FROM scratch COPY --from=golang /usr/bin/go go -`) +`, ` +FROM nanoserver AS golang +USER ContainerAdministrator +RUN echo foo> go + +FROM nanoserver +COPY --from=golang /go /go +`, + )) dir = integration.Tmpdir( t, @@ -4477,17 +4494,18 @@ COPY --from=golang /usr/bin/go go } func testMultiStageCaseInsensitive(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` -FROM scratch AS STAge0 + dockerfileStr := ` +FROM %s AS STAge0 COPY foo bar -FROM scratch AS staGE1 +FROM %s AS staGE1 COPY --from=staGE0 bar baz -FROM scratch +FROM %s COPY --from=stage1 baz bax -`) +` + baseImage := integration.UnixOrWindows("scratch", "nanoserver") + dockerfile := []byte(fmt.Sprintf(dockerfileStr, baseImage, baseImage, baseImage)) dir := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), @@ -5496,10 +5514,10 @@ COPY --from=build out . } func testBuiltinArgs(t *testing.T, sb integration.Sandbox) { - integration.SkipOnPlatform(t, "windows") f := getFrontend(t, sb) - dockerfile := []byte(` + dockerfile := []byte(integration.UnixOrWindows( + ` FROM busybox AS build ARG FOO ARG BAR @@ -5508,7 +5526,18 @@ RUN echo -n $HTTP_PROXY::$NO_PROXY::$FOO::$BAR::$BAZ > /out FROM scratch COPY --from=build /out / -`) +`, ` +FROM nanoserver AS build +USER ContainerAdministrator +ARG FOO +ARG BAR +ARG BAZ=bazcontent +RUN echo %HTTP_PROXY%::%NO_PROXY%::%FOO%::%BAR%::%BAZ%> out +FROM nanoserver +COPY --from=build out / +`, + )) + dir := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), @@ -5543,7 +5572,9 @@ COPY --from=build /out / dt, err := os.ReadFile(filepath.Join(destDir, "out")) require.NoError(t, err) - require.Equal(t, "hpvalue::npvalue::foocontents::::bazcontent", string(dt)) + // Windows can't interpret empty env variables, %BAR% handles empty values. + expectedStr := integration.UnixOrWindows(`hpvalue::npvalue::foocontents::::bazcontent`, "hpvalue::npvalue::foocontents::%BAR%::bazcontent\r\n") + require.Equal(t, expectedStr, string(dt)) // repeat with changed default args should match the old cache destDir = t.TempDir() @@ -5570,7 +5601,8 @@ COPY --from=build /out / dt, err = os.ReadFile(filepath.Join(destDir, "out")) require.NoError(t, err) - require.Equal(t, "hpvalue::npvalue::foocontents::::bazcontent", string(dt)) + expectedStr = integration.UnixOrWindows("hpvalue::npvalue::foocontents::::bazcontent", "hpvalue::npvalue::foocontents::%BAR%::bazcontent\r\n") + require.Equal(t, expectedStr, string(dt)) // changing actual value invalidates cache destDir = t.TempDir() @@ -5597,7 +5629,8 @@ COPY --from=build /out / dt, err = os.ReadFile(filepath.Join(destDir, "out")) require.NoError(t, err) - require.Equal(t, "hpvalue2::::foocontents2::::bazcontent", string(dt)) + expectedStr = integration.UnixOrWindows("hpvalue2::::foocontents2::::bazcontent", "hpvalue2::%NO_PROXY%::foocontents2::%BAR%::bazcontent\r\n") + require.Equal(t, expectedStr, string(dt)) } func testTarContext(t *testing.T, sb integration.Sandbox) { @@ -5713,15 +5746,15 @@ COPY foo bar } func testFrontendUseForwardedSolveResults(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(` -FROM scratch + dockerfileStr := ` +FROM %s COPY foo foo2 -`) +` + dockerfile := []byte(fmt.Sprintf(dockerfileStr, integration.UnixOrWindows("scratch", "nanoserver"))) dir := integration.Tmpdir( t, fstest.CreateFile("Dockerfile", dockerfile, 0600), diff --git a/hack/Vagrantfile.freebsd13 b/hack/Vagrantfile.freebsd similarity index 95% rename from hack/Vagrantfile.freebsd13 rename to hack/Vagrantfile.freebsd index 837f6a41830a..31d42f6fa5fd 100644 --- a/hack/Vagrantfile.freebsd13 +++ b/hack/Vagrantfile.freebsd @@ -2,10 +2,7 @@ # vi: set ft=ruby : Vagrant.configure("2") do |config| - config.vm.define "fbsd_13_2" do |fbsd_13_2| - fbsd_13_2.vm.box = "freebsd/FreeBSD-13.2-RELEASE" - end - + config.vm.box = "generic/freebsd14" config.vm.boot_timeout = 900 config.vm.synced_folder ".", "/vagrant", type: "rsync" config.ssh.keep_alive = true