From 58036c55ffa8afc22f714d34308f99b1e1cd7b0f Mon Sep 17 00:00:00 2001 From: David Karlsson <35727626+dvdksn@users.noreply.github.com> Date: Thu, 10 Aug 2023 13:41:36 +0200 Subject: [PATCH] build: improve error messages for docker driver Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> --- build/build.go | 32 ++++++++++++++++++++++++++------ tests/build.go | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/build/build.go b/build/build.go index 619bf132f24..af2736b6c78 100644 --- a/build/build.go +++ b/build/build.go @@ -391,7 +391,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op for _, e := range opt.CacheTo { if e.Type != "inline" && !nodeDriver.Features(ctx)[driver.CacheExport] { - return nil, nil, notSupported(nodeDriver, driver.CacheExport) + return nil, nil, cacheExportNotSupported(nodeDriver) } } @@ -529,7 +529,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op // set up exporters for i, e := range opt.Exports { if e.Type == "oci" && !nodeDriver.Features(ctx)[driver.OCIExporter] { - return nil, nil, notSupported(nodeDriver, driver.OCIExporter) + return nil, nil, exporterNotSupported(nodeDriver, driver.OCIExporter) } if e.Type == "docker" { features := docker.Features(ctx, e.Attrs["context"]) @@ -555,7 +555,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op opt.Exports[i].Output = wrapWriteCloser(w) } } else if !nodeDriver.Features(ctx)[driver.DockerExporter] { - return nil, nil, notSupported(nodeDriver, driver.DockerExporter) + return nil, nil, exporterNotSupported(nodeDriver, driver.DockerExporter) } } if e.Type == "image" && nodeDriver.IsMobyDriver() { @@ -627,7 +627,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op pp[i] = platforms.Format(p) } if len(pp) > 1 && !nodeDriver.Features(ctx)[driver.MultiPlatform] { - return nil, nil, notSupported(nodeDriver, driver.MultiPlatform) + return nil, nil, multiPlatformBuildNotSupported(nodeDriver) } so.FrontendAttrs["platform"] = strings.Join(pp, ",") } @@ -1560,8 +1560,28 @@ func waitContextDeps(ctx context.Context, index int, results *waitmap.Map, so *c return nil } -func notSupported(d driver.Driver, f driver.Feature) error { - return errors.Errorf("%s feature is currently not supported for %s driver. Please switch to a different driver (eg. \"docker buildx create --use\")", f, d.Factory().Name()) +func cacheExportNotSupported(d driver.Driver) error { + return errors.Errorf(`Cache export is not supported for the %s driver. + +Switch to a different driver and try again. + +Learn more at https://docs.docker.com/go/build-cache-backends/`, d.Factory().Name()) +} + +func exporterNotSupported(d driver.Driver, f driver.Feature) error { + return errors.Errorf(`%s is not supported for the %s driver. + +Switch to a different driver and try again. + +Learn more at https://docs.docker.com/go/build-exporters/`, f, d.Factory().Name()) +} + +func multiPlatformBuildNotSupported(d driver.Driver) error { + return errors.Errorf(`Multi-platform builds is not supported for the %s driver without the containerd image store. + +Switch to a different driver, or turn on the containerd image store, and try again. + +Learn more at https://docs.docker.com/go/build-multi-platform/`, d.Factory().Name()) } func noDefaultLoad() bool { diff --git a/tests/build.go b/tests/build.go index 34ad5920e3c..1b2224555ef 100644 --- a/tests/build.go +++ b/tests/build.go @@ -40,6 +40,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testBuildMobyFromLocalImage, testBuildDetailsLink, testBuildProgress, + testBuildDockerWorkerErrors, } func testBuild(t *testing.T, sb integration.Sandbox) { @@ -313,3 +314,29 @@ func testBuildProgress(t *testing.T, sb integration.Sandbox) { 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 testBuildDockerWorkerErrors(t *testing.T, sb integration.Sandbox) { + if !isDockerWorker(sb) { + t.Skip("skipping test for non-docker workers") + } + + dir := createTestProject(t) + + // registry cache backend + cmd := buildxCmd(sb, withArgs("build", "--cache-to=type=registry", dir)) + _, err := cmd.CombinedOutput() + require.Contains(t, err.Error(), "Cache export is not supported") + require.Contains(t, err.Error(), "https://docs.docker.com/go/build-cache-backends/") + + // oci exporter + cmd = buildxCmd(sb, withArgs("build", (fmt.Sprintf("--output=type=oci,dest=%s/result", dir)), dir)) + _, err = cmd.CombinedOutput() + require.Contains(t, err.Error(), "OCI exporter feature is not supported") + require.Contains(t, err.Error(), "https://docs.docker.com/go/build-exporters/") + + // multi-platform + cmd = buildxCmd(sb, withArgs("build", "--platform=linux/amd64,linux/arm64", dir)) + _, err = cmd.CombinedOutput() + require.Contains(t, err.Error(), "Multi-platform builds is not supported") + require.Contains(t, err.Error(), "https://docs.docker.com/go/build-multi-platform/") +}