From e2be765e7b2b5232d3219ecb594ea0faf234f9f4 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sun, 10 Mar 2024 00:25:32 +0100 Subject: [PATCH 1/8] tests: refactor worker handling in sandbox Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- tests/bake.go | 8 ++++---- tests/build.go | 36 ++++++++++++++++++------------------ tests/create.go | 8 ++++---- tests/imagetools.go | 16 ++++++++-------- tests/inspect.go | 10 +++++----- tests/integration.go | 24 ++++++++++++++++++++++-- tests/ls.go | 2 +- tests/rm.go | 8 ++++---- 8 files changed, 66 insertions(+), 46 deletions(-) diff --git a/tests/bake.go b/tests/bake.go index 4cadd559ee0b..520662f76d29 100644 --- a/tests/bake.go +++ b/tests/bake.go @@ -641,8 +641,8 @@ target "default" { } func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } registry, err := sb.NewRegistry() @@ -722,8 +722,8 @@ target "default" { } func testBakeLoadPush(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } registry, err := sb.NewRegistry() diff --git a/tests/build.go b/tests/build.go index 5bf14fd11526..7d20bacd85c2 100644 --- a/tests/build.go +++ b/tests/build.go @@ -125,7 +125,7 @@ func testBuildRegistryExportAttestations(t *testing.T, sb integration.Sandbox) { target := registry + "/buildx/registry:latest" out, err := buildCmd(sb, withArgs(fmt.Sprintf("--output=type=image,name=%s,push=true", target), "--provenance=true", dir)) - if sb.Name() == "docker" { + if isMobyWorker(sb) { require.Error(t, err) require.Contains(t, out, "Attestation is not supported") return @@ -200,7 +200,7 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) { func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) { if !isDockerWorker(sb) { - t.Skip("skipping test for non-docker workers") + t.Skip("only testing with docker workers") } // pull image @@ -290,7 +290,7 @@ RUN exit 1`) func testBuildProgress(t *testing.T, sb integration.Sandbox) { dir := createTestProject(t) - driver, _, _ := strings.Cut(sb.Name(), "+") + sbDriver, _ := driverName(sb.Name()) name := sb.Address() // progress=tty @@ -301,7 +301,7 @@ func testBuildProgress(t *testing.T, sb integration.Sandbox) { io.Copy(buf, f) ttyOutput := buf.String() require.Contains(t, ttyOutput, "[+] Building") - require.Contains(t, ttyOutput, fmt.Sprintf("%s:%s", driver, name)) + require.Contains(t, ttyOutput, fmt.Sprintf("%s:%s", sbDriver, name)) require.Contains(t, ttyOutput, "=> [internal] load build definition from Dockerfile") require.Contains(t, ttyOutput, "=> [base 1/3] FROM docker.io/library/busybox:latest") @@ -309,13 +309,13 @@ func testBuildProgress(t *testing.T, sb integration.Sandbox) { cmd = buildxCmd(sb, withArgs("build", "--progress=plain", "--output=type=cacheonly", dir)) plainOutput, err := cmd.CombinedOutput() require.NoError(t, err) - require.Contains(t, string(plainOutput), fmt.Sprintf(`#0 building with "%s" instance using %s driver`, name, driver)) + require.Contains(t, string(plainOutput), fmt.Sprintf(`#0 building with "%s" instance using %s driver`, name, sbDriver)) require.Contains(t, string(plainOutput), "[internal] load build definition from Dockerfile") require.Contains(t, string(plainOutput), "[base 1/3] FROM docker.io/library/busybox:latest") } func testBuildAnnotations(t *testing.T, sb integration.Sandbox) { - if sb.Name() == "docker" { + if isMobyWorker(sb) { t.Skip("annotations not supported on docker worker") } @@ -374,8 +374,8 @@ func testBuildLabelNoKey(t *testing.T, sb integration.Sandbox) { } func testBuildCacheExportNotSupported(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isMobyWorker(sb) { + t.Skip("only testing with docker worker") } dir := createTestProject(t) @@ -386,8 +386,8 @@ func testBuildCacheExportNotSupported(t *testing.T, sb integration.Sandbox) { } func testBuildOCIExportNotSupported(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isMobyWorker(sb) { + t.Skip("only testing with docker worker") } dir := createTestProject(t) @@ -398,8 +398,8 @@ func testBuildOCIExportNotSupported(t *testing.T, sb integration.Sandbox) { } func testBuildMultiPlatformNotSupported(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isMobyWorker(sb) { + t.Skip("only testing with docker worker") } dir := createTestProject(t) @@ -426,8 +426,8 @@ RUN ping -c 1 buildx.host-gateway-ip.local } func testBuildNetworkModeBridge(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } var builderName string @@ -546,8 +546,8 @@ func testBuildRef(t *testing.T, sb integration.Sandbox) { } func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } registry, err := sb.NewRegistry() @@ -614,8 +614,8 @@ func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) { } func testBuildLoadPush(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker" { - t.Skip("skipping test for non-docker workers") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } registry, err := sb.NewRegistry() diff --git a/tests/create.go b/tests/create.go index 1a2757fcad5f..195691fbbc21 100644 --- a/tests/create.go +++ b/tests/create.go @@ -26,8 +26,8 @@ var createTests = []func(t *testing.T, sb integration.Sandbox){ } func testCreateMemoryLimit(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("only testing for docker-container driver") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } var builderName string @@ -45,8 +45,8 @@ func testCreateMemoryLimit(t *testing.T, sb integration.Sandbox) { } func testCreateRestartAlways(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("only testing for docker-container driver") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } var builderName string diff --git a/tests/imagetools.go b/tests/imagetools.go index 59d06944fe9a..b6d21b49663f 100644 --- a/tests/imagetools.go +++ b/tests/imagetools.go @@ -22,8 +22,8 @@ var imagetoolsTests = []func(t *testing.T, sb integration.Sandbox){ } func testImagetoolsCopyManifest(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("imagetools tests are not driver specific and only run on docker-container") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker, imagetools only runs on docker-container") } dir := createDockerfile(t) @@ -81,8 +81,8 @@ func testImagetoolsCopyManifest(t *testing.T, sb integration.Sandbox) { } func testImagetoolsCopyIndex(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("imagetools tests are not driver specific and only run on docker-container") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker, imagetools only runs on docker-container") } dir := createDockerfile(t) @@ -130,8 +130,8 @@ func testImagetoolsCopyIndex(t *testing.T, sb integration.Sandbox) { } func testImagetoolsInspectAndFilter(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("imagetools tests are not driver specific and only run on docker-container") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker, imagetools only runs on docker-container") } dir := createDockerfile(t) @@ -181,8 +181,8 @@ func testImagetoolsInspectAndFilter(t *testing.T, sb integration.Sandbox) { } func testImagetoolsAnnotation(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("imagetools tests are not driver specific and only run on docker-container") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker, imagetools only runs on docker-container") } dir := createDockerfile(t) diff --git a/tests/inspect.go b/tests/inspect.go index 755ac16563ea..8dea100fa07d 100644 --- a/tests/inspect.go +++ b/tests/inspect.go @@ -41,7 +41,7 @@ func testInspect(t *testing.T, sb integration.Sandbox) { } require.Equal(t, sb.Address(), name) - sbDriver, _, _ := strings.Cut(sb.Name(), "+") + sbDriver, _ := driverName(sb.Name()) require.Equal(t, sbDriver, driver) if isDockerWorker(sb) { require.NotEmpty(t, hostGatewayIP, "host-gateway-ip worker label should be set with docker driver") @@ -51,8 +51,8 @@ func testInspect(t *testing.T, sb integration.Sandbox) { } func testInspectBuildkitdFlags(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("only testing for docker-container driver") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } var builderName string @@ -81,8 +81,8 @@ func testInspectBuildkitdFlags(t *testing.T, sb integration.Sandbox) { } func testInspectNetworkHostEntitlement(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("only testing for docker-container driver") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } var builderName string diff --git a/tests/integration.go b/tests/integration.go index 335b757c3d9b..38cdafbd9bfb 100644 --- a/tests/integration.go +++ b/tests/integration.go @@ -71,7 +71,27 @@ func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd { return cmd } +func isMobyWorker(sb integration.Sandbox) bool { + name, hasFeature := driverName(sb.Name()) + return name == "docker" && !hasFeature +} + func isDockerWorker(sb integration.Sandbox) bool { - sbDriver, _, _ := strings.Cut(sb.Name(), "+") - return sbDriver == "docker" + name, _ := driverName(sb.Name()) + return name == "docker" +} + +func isDockerContainerWorker(sb integration.Sandbox) bool { + name, _ := driverName(sb.Name()) + return name == "docker-container" +} + +func driverName(sbName string) (string, bool) { + name := sbName + var hasFeature bool + if b, _, ok := strings.Cut(name, "+"); ok { + name = b + hasFeature = true + } + return name, hasFeature } diff --git a/tests/ls.go b/tests/ls.go index 53246d9826ab..1e147fe0c1e6 100644 --- a/tests/ls.go +++ b/tests/ls.go @@ -34,7 +34,7 @@ func testLs(t *testing.T, sb integration.Sandbox) { }, } - sbDriver, _, _ := strings.Cut(sb.Name(), "+") + sbDriver, _ := driverName(sb.Name()) for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { diff --git a/tests/rm.go b/tests/rm.go index 40cf8c942697..5f7d45569cbe 100644 --- a/tests/rm.go +++ b/tests/rm.go @@ -21,8 +21,8 @@ var rmTests = []func(t *testing.T, sb integration.Sandbox){ } func testRm(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("only testing for docker-container driver") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } out, err := rmCmd(sb, withArgs("default")) @@ -40,8 +40,8 @@ func testRm(t *testing.T, sb integration.Sandbox) { } func testRmMulti(t *testing.T, sb integration.Sandbox) { - if sb.Name() != "docker-container" { - t.Skip("only testing for docker-container driver") + if !isDockerContainerWorker(sb) { + t.Skip("only testing with docker-container worker") } var builderNames []string From f7226a52358c66463707e8ccf4ebb15474cf82b2 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sat, 9 Mar 2024 19:10:58 +0100 Subject: [PATCH 2/8] tests: matrix with buildkit versions Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/build.yml | 39 ++++++++++--------------------------- docker-bake.hcl | 4 ++++ hack/test | 3 ++- tests/integration.go | 9 +++++++++ tests/integration_test.go | 2 +- 5 files changed, 26 insertions(+), 31 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ba30181cff0..f89c2b08d0a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,35 +30,8 @@ env: GOTESTSUM_VERSION: "v1.9.0" # same as one in Dockerfile jobs: - prepare-test-integration: - runs-on: ubuntu-22.04 - steps: - - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - version: ${{ env.BUILDX_VERSION }} - driver-opts: image=${{ env.BUILDKIT_IMAGE }} - buildkitd-flags: --debug - - - name: Build - uses: docker/bake-action@v4 - with: - targets: integration-test-base - set: | - *.cache-from=type=gha,scope=${{ env.TEST_CACHE_SCOPE }} - *.cache-to=type=gha,scope=${{ env.TEST_CACHE_SCOPE }} - test-integration: runs-on: ubuntu-22.04 - needs: - - prepare-test-integration env: TESTFLAGS_DOCKER: "-v --parallel=1 --timeout=30m" TEST_IMAGE_BUILD: "0" @@ -66,6 +39,12 @@ jobs: strategy: fail-fast: false matrix: + buildkit: + - master + - latest + - buildx-stable-1 + - v0.11.6 + - v0.10.6 worker: - docker - docker\+containerd # same as docker, but with containerd snapshotter @@ -77,7 +56,10 @@ jobs: - name: Prepare run: | - echo "TESTREPORTS_NAME=${{ github.job }}-$(echo "${{ matrix.pkg }}-${{ matrix.worker }}" | tr -dc '[:alnum:]-\n\r' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + echo "TESTREPORTS_NAME=${{ github.job }}-$(echo "${{ matrix.pkg }}-${{ matrix.buildkit }}-${{ matrix.worker }}" | tr -dc '[:alnum:]-\n\r' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + if [ -n "${{ matrix.buildkit }}" ]; then + echo "TEST_BUILDKIT_TAG=${{ matrix.buildkit }}" >> $GITHUB_ENV + fi - name: Checkout uses: actions/checkout@v4 @@ -99,7 +81,6 @@ jobs: with: targets: integration-test set: | - *.cache-from=type=gha,scope=${{ env.TEST_CACHE_SCOPE }} *.output=type=docker,name=${{ env.TEST_IMAGE_ID }} - name: Test diff --git a/docker-bake.hcl b/docker-bake.hcl index 435d8df70ab4..084fdd6450c3 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -180,6 +180,9 @@ variable "HTTPS_PROXY" { variable "NO_PROXY" { default = "" } +variable "TEST_BUILDKIT_TAG" { + default = null +} target "integration-test-base" { inherits = ["_common"] @@ -187,6 +190,7 @@ target "integration-test-base" { HTTP_PROXY = HTTP_PROXY HTTPS_PROXY = HTTPS_PROXY NO_PROXY = NO_PROXY + BUILDKIT_VERSION = TEST_BUILDKIT_TAG } target = "integration-test-base" output = ["type=cacheonly"] diff --git a/hack/test b/hack/test index b1cea0832f51..1f8cdddb026d 100755 --- a/hack/test +++ b/hack/test @@ -10,6 +10,7 @@ set -eu -o pipefail : "${TEST_REPORT_SUFFIX=}" : "${TEST_KEEP_CACHE=}" : "${TEST_DOCKERD=}" +: "${TEST_BUILDKIT_TAG=}" : "${TEST_BUILDKIT_IMAGE=}" if [ "$TEST_IMAGE_BUILD" = "1" ]; then @@ -30,5 +31,5 @@ if [ "$TEST_KEEP_CACHE" != "1" ]; then trap 'docker rm -v $cacheVolume' EXIT fi -cid=$(docker create --rm -v /tmp $testReportsVol --volumes-from=$cacheVolume -e GITHUB_REF -e TEST_DOCKERD -e TEST_BUILDKIT_IMAGE -e SKIP_INTEGRATION_TESTS -e GOTESTSUM_FORMAT ${BUILDKIT_INTEGRATION_SNAPSHOTTER:+"-eBUILDKIT_INTEGRATION_SNAPSHOTTER"} -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry --privileged $TEST_IMAGE_ID gotestsum $gotestsumArgs --packages="${TESTPKGS:-./...}" -- $gotestArgs ${TESTFLAGS:--v}) +cid=$(docker create --rm -v /tmp $testReportsVol --volumes-from=$cacheVolume -e GITHUB_REF -e TEST_DOCKERD -e TEST_BUILDKIT_IMAGE -e TEST_BUILDKIT_TAG -e SKIP_INTEGRATION_TESTS -e GOTESTSUM_FORMAT ${BUILDKIT_INTEGRATION_SNAPSHOTTER:+"-eBUILDKIT_INTEGRATION_SNAPSHOTTER"} -e BUILDKIT_REGISTRY_MIRROR_DIR=/root/.cache/registry --privileged $TEST_IMAGE_ID gotestsum $gotestsumArgs --packages="${TESTPKGS:-./...}" -- $gotestArgs ${TESTFLAGS:--v}) docker start -a -i $cid diff --git a/tests/integration.go b/tests/integration.go index 38cdafbd9bfb..b05fa3d0b691 100644 --- a/tests/integration.go +++ b/tests/integration.go @@ -11,6 +11,8 @@ import ( "github.com/stretchr/testify/require" ) +const defaultBuildKitTag = "buildx-stable-1" + func tmpdir(t *testing.T, appliers ...fstest.Applier) string { t.Helper() tmpdir := t.TempDir() @@ -95,3 +97,10 @@ func driverName(sbName string) (string, bool) { } return name, hasFeature } + +func buildkitTag() string { + if v := os.Getenv("TEST_BUILDKIT_TAG"); v != "" { + return v + } + return defaultBuildKitTag +} diff --git a/tests/integration_test.go b/tests/integration_test.go index 49c5d06dd055..ed763a1b1cf4 100644 --- a/tests/integration_test.go +++ b/tests/integration_test.go @@ -35,7 +35,7 @@ func TestIntegration(t *testing.T) { func testIntegration(t *testing.T, funcs ...func(t *testing.T, sb integration.Sandbox)) { mirroredImages := integration.OfficialImages("busybox:latest", "alpine:latest") - buildkitImage := "docker.io/moby/buildkit:buildx-stable-1" + buildkitImage := "docker.io/moby/buildkit:" + buildkitTag() if bkworkers.IsTestDockerd() { if img, ok := os.LookupEnv("TEST_BUILDKIT_IMAGE"); ok { ref, err := reference.ParseNormalizedNamed(img) From b509d45c0a65d685577cdc0c42229622273fcfda Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sun, 10 Mar 2024 01:09:06 +0100 Subject: [PATCH 3/8] dockerfile: add undock for integration tests Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dockerfile b/Dockerfile index f48105ee987c..cf77777b3632 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,7 @@ ARG DOCKER_VERSION=25.0.2 ARG GOTESTSUM_VERSION=v1.9.0 ARG REGISTRY_VERSION=2.8.0 ARG BUILDKIT_VERSION=v0.12.5 +ARG UNDOCK_VERSION=0.7.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS golatest @@ -15,6 +16,7 @@ FROM moby/moby-bin:$DOCKER_VERSION AS docker-engine FROM dockereng/cli-bin:$DOCKER_VERSION AS docker-cli FROM registry:$REGISTRY_VERSION AS registry FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit +FROM crazymax/undock:$UNDOCK_VERSION AS undock FROM golatest AS gobase COPY --from=xx / / @@ -92,6 +94,7 @@ COPY --link --from=docker-engine / /usr/bin/ COPY --link --from=docker-cli / /usr/bin/ COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/ COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/ +COPY --link --from=undock /usr/local/bin/undock /usr/bin/ COPY --link --from=binaries /buildx /usr/bin/ FROM integration-test-base AS integration-test From 2e43c5da4156a3c4fcc4cea2335a936af4a66904 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sun, 10 Mar 2024 00:29:40 +0100 Subject: [PATCH 4/8] tests: skip according to buildkit version constraint Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- hack/test | 2 +- tests/bake.go | 41 +------------------- tests/build.go | 53 +++++++------------------ tests/dialstdio.go | 1 + tests/integration.go | 81 +++++++++++++++++++++++++++++++++++++++ tests/integration_test.go | 2 +- 6 files changed, 99 insertions(+), 81 deletions(-) diff --git a/hack/test b/hack/test index 1f8cdddb026d..6ab303c4e11b 100755 --- a/hack/test +++ b/hack/test @@ -25,7 +25,7 @@ gotestArgs="-mod=vendor -coverprofile=/testreports/coverage-report$TEST_REPORT_S cacheVolume="buildx-test-cache" if ! docker container inspect "$cacheVolume" >/dev/null 2>/dev/null; then - docker create -v /root/.cache -v /root/.cache/registry -v /go/pkg/mod --name "$cacheVolume" alpine + docker create -v /root/.cache -v /root/.cache/registry -v /root/.cache/undock -v /go/pkg/mod --name "$cacheVolume" alpine fi if [ "$TEST_KEEP_CACHE" != "1" ]; then trap 'docker rm -v $cacheVolume' EXIT diff --git a/tests/bake.go b/tests/bake.go index 520662f76d29..33b85c81a46a 100644 --- a/tests/bake.go +++ b/tests/bake.go @@ -5,7 +5,6 @@ import ( "fmt" "os" "path/filepath" - "strings" "testing" "github.com/containerd/continuity/fs/fstest" @@ -644,6 +643,7 @@ func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) { if !isDockerContainerWorker(sb) { t.Skip("only testing with docker-container worker") } + skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "multi exporters") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { @@ -654,30 +654,12 @@ func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) { targetReg := registry + "/buildx/registry:latest" targetStore := "buildx:local-" + identity.NewID() - var builderName string t.Cleanup(func() { - if builderName == "" { - return - } - cmd := dockerCmd(sb, withArgs("image", "rm", targetStore)) cmd.Stderr = os.Stderr require.NoError(t, cmd.Run()) - - out, err := rmCmd(sb, withArgs(builderName)) - require.NoError(t, err, out) }) - // TODO: use stable buildkit image when v0.13.0 released - out, err := createCmd(sb, withArgs( - "--driver", "docker-container", - "--buildkitd-flags=--allow-insecure-entitlement=network.host", - "--driver-opt", "network=host", - "--driver-opt", "image=moby/buildkit:v0.13.0-rc3", - )) - require.NoError(t, err, out) - builderName = strings.TrimSpace(out) - dockerfile := []byte(` FROM scratch COPY foo /foo @@ -699,7 +681,6 @@ target "default" { "--set", fmt.Sprintf("*.output=type=oci,dest=%s/result", dir), } cmd := buildxCmd(sb, withDir(dir), withArgs("bake"), withArgs(outputs...)) - cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName) outb, err := cmd.CombinedOutput() require.NoError(t, err, string(outb)) @@ -725,6 +706,7 @@ func testBakeLoadPush(t *testing.T, sb integration.Sandbox) { if !isDockerContainerWorker(sb) { t.Skip("only testing with docker-container worker") } + skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "multi exporters") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { @@ -734,30 +716,12 @@ func testBakeLoadPush(t *testing.T, sb integration.Sandbox) { target := registry + "/buildx/registry:" + identity.NewID() - var builderName string t.Cleanup(func() { - if builderName == "" { - return - } - cmd := dockerCmd(sb, withArgs("image", "rm", target)) cmd.Stderr = os.Stderr require.NoError(t, cmd.Run()) - - out, err := rmCmd(sb, withArgs(builderName)) - require.NoError(t, err, out) }) - // TODO: use stable buildkit image when v0.13.0 released - out, err := createCmd(sb, withArgs( - "--driver", "docker-container", - "--buildkitd-flags=--allow-insecure-entitlement=network.host", - "--driver-opt", "network=host", - "--driver-opt", "image=moby/buildkit:v0.13.0-rc3", - )) - require.NoError(t, err, out) - builderName = strings.TrimSpace(out) - dockerfile := []byte(` FROM scratch COPY foo /foo @@ -774,7 +738,6 @@ target "default" { ) cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--push", "--load", fmt.Sprintf("--set=*.tags=%s", target))) - cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName) outb, err := cmd.CombinedOutput() require.NoError(t, err, string(outb)) diff --git a/tests/build.go b/tests/build.go index 7d20bacd85c2..500cade1d8e7 100644 --- a/tests/build.go +++ b/tests/build.go @@ -129,6 +129,10 @@ func testBuildRegistryExportAttestations(t *testing.T, sb integration.Sandbox) { require.Error(t, err) require.Contains(t, out, "Attestation is not supported") return + } else if !isMobyContainerdSnapWorker(sb) && !matchesBuildKitVersion(t, sb, ">= 0.11.0-0") { + require.Error(t, err) + require.Contains(t, out, "Attestations are not supported by the current BuildKit daemon") + return } require.NoError(t, err, string(out)) @@ -247,6 +251,7 @@ RUN busybox | head -1 | grep v1.36.1 } func testBuildDetailsLink(t *testing.T, sb integration.Sandbox) { + skipNoCompatBuildKit(t, sb, ">= 0.11.0-0", "build details link") buildDetailsPattern := regexp.MustCompile(`(?m)^View build details: docker-desktop://dashboard/build/[^/]+/[^/]+/[^/]+\n$`) // build simple dockerfile @@ -318,6 +323,7 @@ func testBuildAnnotations(t *testing.T, sb integration.Sandbox) { if isMobyWorker(sb) { t.Skip("annotations not supported on docker worker") } + skipNoCompatBuildKit(t, sb, ">= 0.11.0-0", "annotations") dir := createTestProject(t) @@ -429,6 +435,7 @@ func testBuildNetworkModeBridge(t *testing.T, sb integration.Sandbox) { if !isDockerContainerWorker(sb) { t.Skip("only testing with docker-container worker") } + skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "network bridge") var builderName string t.Cleanup(func() { @@ -439,8 +446,10 @@ func testBuildNetworkModeBridge(t *testing.T, sb integration.Sandbox) { require.NoError(t, err, out) }) - // TODO: use stable buildkit image when v0.13.0 released - out, err := createCmd(sb, withArgs("--driver", "docker-container", "--buildkitd-flags=--oci-worker-net=bridge --allow-insecure-entitlement=network.host", "--driver-opt", "image=moby/buildkit:v0.13.0-rc3")) + out, err := createCmd(sb, withArgs( + "--driver", "docker-container", + "--buildkitd-flags=--oci-worker-net=bridge --allow-insecure-entitlement=network.host", + )) require.NoError(t, err, out) builderName = strings.TrimSpace(out) @@ -549,6 +558,7 @@ func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) { if !isDockerContainerWorker(sb) { t.Skip("only testing with docker-container worker") } + skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "multi exporters") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { @@ -559,30 +569,12 @@ func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) { targetReg := registry + "/buildx/registry:latest" targetStore := "buildx:local-" + identity.NewID() - var builderName string t.Cleanup(func() { - if builderName == "" { - return - } - cmd := dockerCmd(sb, withArgs("image", "rm", targetStore)) cmd.Stderr = os.Stderr require.NoError(t, cmd.Run()) - - out, err := rmCmd(sb, withArgs(builderName)) - require.NoError(t, err, out) }) - // TODO: use stable buildkit image when v0.13.0 released - out, err := createCmd(sb, withArgs( - "--driver", "docker-container", - "--buildkitd-flags=--allow-insecure-entitlement=network.host", - "--driver-opt", "network=host", - "--driver-opt", "image=moby/buildkit:v0.13.0-rc3", - )) - require.NoError(t, err, out) - builderName = strings.TrimSpace(out) - dir := createTestProject(t) outputs := []string{ @@ -591,7 +583,6 @@ func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) { "--output", fmt.Sprintf("type=oci,dest=%s/result", dir), } cmd := buildxCmd(sb, withArgs("build"), withArgs(outputs...), withArgs(dir)) - cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName) outb, err := cmd.CombinedOutput() require.NoError(t, err, string(outb)) @@ -617,6 +608,7 @@ func testBuildLoadPush(t *testing.T, sb integration.Sandbox) { if !isDockerContainerWorker(sb) { t.Skip("only testing with docker-container worker") } + skipNoCompatBuildKit(t, sb, ">= 0.13.0-0", "multi exporters") registry, err := sb.NewRegistry() if errors.Is(err, integration.ErrRequirements) { @@ -626,30 +618,12 @@ func testBuildLoadPush(t *testing.T, sb integration.Sandbox) { target := registry + "/buildx/registry:" + identity.NewID() - var builderName string t.Cleanup(func() { - if builderName == "" { - return - } - cmd := dockerCmd(sb, withArgs("image", "rm", target)) cmd.Stderr = os.Stderr require.NoError(t, cmd.Run()) - - out, err := rmCmd(sb, withArgs(builderName)) - require.NoError(t, err, out) }) - // TODO: use stable buildkit image when v0.13.0 released - out, err := createCmd(sb, withArgs( - "--driver", "docker-container", - "--buildkitd-flags=--allow-insecure-entitlement=network.host", - "--driver-opt", "network=host", - "--driver-opt", "image=moby/buildkit:v0.13.0-rc3", - )) - require.NoError(t, err, out) - builderName = strings.TrimSpace(out) - dir := createTestProject(t) cmd := buildxCmd(sb, withArgs( @@ -657,7 +631,6 @@ func testBuildLoadPush(t *testing.T, sb integration.Sandbox) { fmt.Sprintf("-t=%s", target), dir, )) - cmd.Env = append(cmd.Env, "BUILDX_BUILDER="+builderName) outb, err := cmd.CombinedOutput() require.NoError(t, err, string(outb)) diff --git a/tests/dialstdio.go b/tests/dialstdio.go index afb441cb749f..4a034a5f8ba2 100644 --- a/tests/dialstdio.go +++ b/tests/dialstdio.go @@ -61,6 +61,7 @@ func testDialStdio(t *testing.T, sb integration.Sandbox) { } }() + skipNoCompatBuildKit(t, sb, ">= 0.11.0-0", "unknown method Info for service moby.buildkit.v1.Control") _, err = c.Info(sb.Context()) require.NoError(t, err) diff --git a/tests/integration.go b/tests/integration.go index b05fa3d0b691..b14e73bf14c5 100644 --- a/tests/integration.go +++ b/tests/integration.go @@ -3,9 +3,12 @@ package tests import ( "os" "os/exec" + "path/filepath" "strings" + "sync" "testing" + "github.com/Masterminds/semver/v3" "github.com/containerd/continuity/fs/fstest" "github.com/moby/buildkit/util/testutil/integration" "github.com/stretchr/testify/require" @@ -13,6 +16,8 @@ import ( const defaultBuildKitTag = "buildx-stable-1" +var buildkitImage string + func tmpdir(t *testing.T, appliers ...fstest.Applier) string { t.Helper() tmpdir := t.TempDir() @@ -78,6 +83,11 @@ func isMobyWorker(sb integration.Sandbox) bool { return name == "docker" && !hasFeature } +func isMobyContainerdSnapWorker(sb integration.Sandbox) bool { + name, hasFeature := driverName(sb.Name()) + return name == "docker" && hasFeature +} + func isDockerWorker(sb integration.Sandbox) bool { name, _ := driverName(sb.Name()) return name == "docker" @@ -104,3 +114,74 @@ func buildkitTag() string { } return defaultBuildKitTag } + +var ( + bkvers map[string]string + bkversMu sync.Mutex +) + +func buildkitVersion(t *testing.T, sb integration.Sandbox) string { + bkversMu.Lock() + defer bkversMu.Unlock() + + if bkvers == nil { + bkvers = make(map[string]string) + } + + ver, ok := bkvers[sb.Name()] + if !ok { + out, err := inspectCmd(sb, withArgs(sb.Address())) + require.NoError(t, err, out) + for _, line := range strings.Split(out, "\n") { + if v, ok := strings.CutPrefix(line, "BuildKit version:"); ok { + ver = strings.TrimSpace(v) + bkvers[sb.Name()] = ver + } + } + if ver == "" { + t.Logf("BuildKit version not found in inspect output, extract it from the image.\n%s", out) + undockBin, err := exec.LookPath("undock") + require.NoError(t, err, "undock not found") + + destDir := t.TempDir() + t.Cleanup(func() { + os.RemoveAll(destDir) + }) + + cmd := exec.Command(undockBin, "--cachedir", "/root/.cache/undock", "--include", "/usr/bin/buildkitd", "--rm-dist", buildkitImage, destDir) + require.NoErrorf(t, cmd.Run(), "failed to extract buildkitd binary from %q", buildkitImage) + + cmd = exec.Command(filepath.Join(destDir, "usr", "bin", "buildkitd"), "--version") + out, err := cmd.CombinedOutput() + require.NoErrorf(t, err, "failed to get BuildKit version from %q: %s", buildkitImage, string(out)) + + v := strings.Fields(strings.TrimSpace(string(out))) + if len(v) != 4 { + require.Fail(t, "unexpected version format: "+strings.TrimSpace(string(out))) + } + ver = v[2] + bkvers[sb.Name()] = ver + } + } + + return ver +} + +func matchesBuildKitVersion(t *testing.T, sb integration.Sandbox, constraint string) bool { + c, err := semver.NewConstraint(constraint) + if err != nil { + return false + } + v, err := semver.NewVersion(buildkitVersion(t, sb)) + if err != nil { + // if the version is not a valid semver, we assume it matches (master) + return true + } + return c.Check(v) +} + +func skipNoCompatBuildKit(t *testing.T, sb integration.Sandbox, constraint string, msg string) { + if !matchesBuildKitVersion(t, sb, constraint) { + t.Skipf("buildkit version %s does not match %s constraint (%s)", buildkitVersion(t, sb), constraint, msg) + } +} diff --git a/tests/integration_test.go b/tests/integration_test.go index ed763a1b1cf4..a9d49ea76fb5 100644 --- a/tests/integration_test.go +++ b/tests/integration_test.go @@ -35,7 +35,7 @@ func TestIntegration(t *testing.T) { func testIntegration(t *testing.T, funcs ...func(t *testing.T, sb integration.Sandbox)) { mirroredImages := integration.OfficialImages("busybox:latest", "alpine:latest") - buildkitImage := "docker.io/moby/buildkit:" + buildkitTag() + buildkitImage = "docker.io/moby/buildkit:" + buildkitTag() if bkworkers.IsTestDockerd() { if img, ok := os.LookupEnv("TEST_BUILDKIT_IMAGE"); ok { ref, err := reference.ParseNormalizedNamed(img) From 4fd16b06a53b1859604f83d242f6cad7bb037285 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sun, 10 Mar 2024 01:45:28 +0100 Subject: [PATCH 5/8] dockerfile: update buildkit to 0.13.0 Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/build.yml | 3 ++- Dockerfile | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f89c2b08d0a1..b1f18a5066fb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,8 +43,9 @@ jobs: - master - latest - buildx-stable-1 + - v0.13.0 + - v0.12.5 - v0.11.6 - - v0.10.6 worker: - docker - docker\+containerd # same as docker, but with containerd snapshotter diff --git a/Dockerfile b/Dockerfile index cf77777b3632..3cdb1e21bf64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ ARG XX_VERSION=1.4.0 ARG DOCKER_VERSION=25.0.2 ARG GOTESTSUM_VERSION=v1.9.0 ARG REGISTRY_VERSION=2.8.0 -ARG BUILDKIT_VERSION=v0.12.5 +ARG BUILDKIT_VERSION=v0.13.0 ARG UNDOCK_VERSION=0.7.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx From d3a96d87cb691ee7075080dc3c00f70ded1c7f56 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sun, 10 Mar 2024 01:51:53 +0100 Subject: [PATCH 6/8] ci: run docker worker in dedicated matrix Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b1f18a5066fb..1b04b334741b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,12 +47,15 @@ jobs: - v0.12.5 - v0.11.6 worker: - - docker - - docker\+containerd # same as docker, but with containerd snapshotter - docker-container - remote pkg: - ./tests + include: + - worker: docker + pkg: ./tests + - worker: docker\+containerd # same as docker, but with containerd snapshotter + pkg: ./tests steps: - name: Prepare From 0c72c95e29f268197ead205d4c026011b2d580e4 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sun, 10 Mar 2024 01:53:40 +0100 Subject: [PATCH 7/8] ci: remove buildkit-edge job Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/build.yml | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1b04b334741b..81c430516a62 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -340,27 +340,3 @@ jobs: with: draft: true files: ${{ env.DESTDIR }}/* - - buildkit-edge: - runs-on: ubuntu-22.04 - continue-on-error: true - steps: - - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - version: ${{ env.BUILDX_VERSION }} - driver-opts: image=moby/buildkit:master - buildkitd-flags: --debug - - - # Just run a bake target to check eveything runs fine - name: Build - uses: docker/bake-action@v4 - with: - targets: binaries From 489d348b151f4fd50bb60cc38e0fb7541360960b Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:59:41 +0100 Subject: [PATCH 8/8] tests: run remote worker on tcp and container endpoints Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/workflows/build.yml | 19 ++++++-- Dockerfile | 4 -- docker-bake.hcl | 4 -- tests/workers/docker.go | 3 +- tests/workers/remote.go | 94 +++++++++++++++++++++++++++++-------- 5 files changed, 92 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81c430516a62..f08824dfebdc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,13 +48,14 @@ jobs: - v0.11.6 worker: - docker-container - - remote + - remote+docker-container + - remote+tcp pkg: - ./tests include: - worker: docker pkg: ./tests - - worker: docker\+containerd # same as docker, but with containerd snapshotter + - worker: docker+containerd # same as docker, but with containerd snapshotter pkg: ./tests steps: - @@ -64,6 +65,18 @@ jobs: if [ -n "${{ matrix.buildkit }}" ]; then echo "TEST_BUILDKIT_TAG=${{ matrix.buildkit }}" >> $GITHUB_ENV fi + testFlags="--run=//worker=$(echo "${{ matrix.worker }}" | sed 's/\+/\\+/g')$" + case "${{ matrix.worker }}" in + docker | docker+containerd | docker@* | docker+containerd@* | remote*) + echo "TESTFLAGS=${{ env.TESTFLAGS_DOCKER }} $testFlags" >> $GITHUB_ENV + ;; + *) + echo "TESTFLAGS=${{ env.TESTFLAGS }} $testFlags" >> $GITHUB_ENV + ;; + esac + if [[ "${{ matrix.worker }}" == "docker"* ]]; then + echo "TEST_DOCKERD=1" >> $GITHUB_ENV + fi - name: Checkout uses: actions/checkout@v4 @@ -92,8 +105,6 @@ jobs: ./hack/test env: TEST_REPORT_SUFFIX: "-${{ env.TESTREPORTS_NAME }}" - TEST_DOCKERD: "${{ startsWith(matrix.worker, 'docker') && '1' || '0' }}" - TESTFLAGS: "${{ (matrix.worker == 'docker' || matrix.worker == 'docker\\+containerd') && env.TESTFLAGS_DOCKER || env.TESTFLAGS }} --run=//worker=${{ matrix.worker }}$" TESTPKGS: "${{ matrix.pkg }}" - name: Send to Codecov diff --git a/Dockerfile b/Dockerfile index 3cdb1e21bf64..d6c13962f9f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,6 @@ ARG XX_VERSION=1.4.0 ARG DOCKER_VERSION=25.0.2 ARG GOTESTSUM_VERSION=v1.9.0 ARG REGISTRY_VERSION=2.8.0 -ARG BUILDKIT_VERSION=v0.13.0 ARG UNDOCK_VERSION=0.7.0 FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx @@ -15,7 +14,6 @@ FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS golatest FROM moby/moby-bin:$DOCKER_VERSION AS docker-engine FROM dockereng/cli-bin:$DOCKER_VERSION AS docker-cli FROM registry:$REGISTRY_VERSION AS registry -FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit FROM crazymax/undock:$UNDOCK_VERSION AS undock FROM golatest AS gobase @@ -92,8 +90,6 @@ COPY --link --from=gotestsum /out/gotestsum /usr/bin/ COPY --link --from=registry /bin/registry /usr/bin/ COPY --link --from=docker-engine / /usr/bin/ COPY --link --from=docker-cli / /usr/bin/ -COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/ -COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/ COPY --link --from=undock /usr/local/bin/undock /usr/bin/ COPY --link --from=binaries /buildx /usr/bin/ diff --git a/docker-bake.hcl b/docker-bake.hcl index 084fdd6450c3..435d8df70ab4 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -180,9 +180,6 @@ variable "HTTPS_PROXY" { variable "NO_PROXY" { default = "" } -variable "TEST_BUILDKIT_TAG" { - default = null -} target "integration-test-base" { inherits = ["_common"] @@ -190,7 +187,6 @@ target "integration-test-base" { HTTP_PROXY = HTTP_PROXY HTTPS_PROXY = HTTPS_PROXY NO_PROXY = NO_PROXY - BUILDKIT_VERSION = TEST_BUILDKIT_TAG } target = "integration-test-base" output = ["type=cacheonly"] diff --git a/tests/workers/docker.go b/tests/workers/docker.go index cd6d6084b8af..37c3a4d8c017 100644 --- a/tests/workers/docker.go +++ b/tests/workers/docker.go @@ -24,7 +24,8 @@ func InitDockerWorker() { type dockerWorker struct { id string containerdSnapshotter bool - unsupported []string + + unsupported []string } func (c dockerWorker) Name() string { diff --git a/tests/workers/remote.go b/tests/workers/remote.go index 4ded704f4f3f..8247cc950de5 100644 --- a/tests/workers/remote.go +++ b/tests/workers/remote.go @@ -2,24 +2,41 @@ package workers import ( "context" + "fmt" + "net" "os" "os/exec" + "sync" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/util/testutil/integration" - bkworkers "github.com/moby/buildkit/util/testutil/workers" "github.com/pkg/errors" ) +var protos = []string{ + "docker-container", + "tcp", +} + func InitRemoteWorker() { - integration.Register(&remoteWorker{ - id: "remote", - }) + for _, p := range protos { + integration.Register(&remoteWorker{ + id: "remote+" + p, + proto: p, + }) + } } type remoteWorker struct { - id string + id string + proto string + unsupported []string + + docker integration.Backend + dockerClose func() error + dockerErr error + dockerOnce sync.Once } func (w remoteWorker) Name() string { @@ -35,32 +52,71 @@ func (w remoteWorker) NetNSDetached() bool { } func (w remoteWorker) New(ctx context.Context, cfg *integration.BackendConfig) (b integration.Backend, cl func() error, err error) { - oci := bkworkers.OCI{ID: w.id} - bk, bkclose, err := oci.New(ctx, cfg) - if err != nil { - return bk, cl, err + w.dockerOnce.Do(func() { + w.docker, w.dockerClose, w.dockerErr = dockerWorker{id: w.id}.New(ctx, cfg) + }) + if w.dockerErr != nil { + return w.docker, w.dockerClose, w.dockerErr } + bkCtnName := "buildkit-integration-" + identity.NewID() name := "integration-remote-" + identity.NewID() + envs := append( + os.Environ(), + "BUILDX_CONFIG=/tmp/buildx-"+name, + "DOCKER_CONTEXT="+w.docker.DockerAddress(), + ) + + // random host port for buildkit container + l, _ := net.Listen("tcp", ":0") //nolint:gosec + _ = l.Close() + bkPort := l.Addr().(*net.TCPAddr).Port + + // create buildkit container + bkCtnCmd := exec.Command("docker", "run", + "-d", "--rm", + "--privileged", + "-p", fmt.Sprintf("%d:1234", bkPort), + "--name="+bkCtnName, + "moby/buildkit:buildx-stable-1", + "--addr=tcp://0.0.0.0:1234", + ) + bkCtnCmd.Env = envs + if out, err := bkCtnCmd.CombinedOutput(); err != nil { + return nil, nil, errors.Wrapf(err, "failed to create buildkit container %s: %s", bkCtnName, string(out)) + } + + // create builder + var endpoint string + switch w.proto { + case "docker-container": + endpoint = fmt.Sprintf("docker-container://%s", bkCtnName) + case "tcp": + endpoint = fmt.Sprintf("tcp://localhost:%d", bkPort) + default: + return nil, nil, errors.Errorf("unsupported protocol %s", w.proto) + } cmd := exec.Command("buildx", "create", "--bootstrap", "--name="+name, "--driver=remote", - bk.Address(), + endpoint, ) - cmd.Env = append(os.Environ(), "BUILDX_CONFIG=/tmp/buildx-"+name) - if err := cmd.Run(); err != nil { - return nil, nil, errors.Wrapf(err, "failed to create buildx instance %s", name) + cmd.Env = envs + if out, err := cmd.CombinedOutput(); err != nil { + return nil, nil, errors.Wrapf(err, "failed to create buildx instance %s: %s", name, string(out)) } cl = func() error { - var err error - if err1 := bkclose(); err == nil { - err = err1 + cmd := exec.Command("docker", "container", "rm", "-f", name) + cmd.Env = envs + if err1 := cmd.Run(); err1 != nil { + err = errors.Wrapf(err1, "failed to remove buildkit container %s", bkCtnName) } - cmd := exec.Command("buildx", "rm", "-f", name) - if err1 := cmd.Run(); err == nil { - err = err1 + cmd = exec.Command("buildx", "rm", "-f", name) + cmd.Env = envs + if err1 := cmd.Run(); err1 != nil { + err = errors.Wrapf(err1, "failed to remove buildx instance %s", name) } return err }