diff --git a/hack/test b/hack/test index 74964d27..009ebded 100755 --- a/hack/test +++ b/hack/test @@ -26,7 +26,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 0de3c497..a0570c79 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" @@ -680,6 +679,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) { @@ -690,30 +690,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 @@ -735,7 +717,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)) @@ -761,6 +742,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) { @@ -770,30 +752,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 @@ -810,7 +774,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 fd4562a1..cf9c4cff 100644 --- a/tests/build.go +++ b/tests/build.go @@ -152,6 +152,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)) @@ -270,6 +274,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 @@ -346,6 +351,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) @@ -457,6 +463,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() { @@ -467,8 +474,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) @@ -577,6 +586,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) { @@ -587,30 +597,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{ @@ -619,7 +611,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)) @@ -645,6 +636,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) { @@ -654,30 +646,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( @@ -685,7 +659,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 afb441cb..4a034a5f 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 e124ebf7..0d8da93f 100644 --- a/tests/integration.go +++ b/tests/integration.go @@ -3,10 +3,13 @@ package tests import ( "os" "os/exec" + "path/filepath" "strconv" "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" @@ -14,6 +17,8 @@ import ( const defaultBuildKitTag = "buildx-stable-1" +var buildkitImage string + func tmpdir(t *testing.T, appliers ...fstest.Applier) string { t.Helper() tmpdir := t.TempDir() @@ -82,6 +87,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" @@ -116,3 +126,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 ed763a1b..a9d49ea7 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)