From bf5a70023c26c0920593842d885b8554ac55ecdf 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> Co-authored-by: CrazyMax Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> --- build/build.go | 14 ++++++++------ driver/features.go | 2 +- tests/build.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/build/build.go b/build/build.go index b2705f2d23c6..1e1972798da9 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, notSupported(driver.CacheExport, nodeDriver, "https://docs.docker.com/go/build-cache-backends/") } } @@ -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, notSupported(driver.OCIExporter, nodeDriver, "https://docs.docker.com/go/build-exporters/") } 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, notSupported(driver.DockerExporter, nodeDriver, "https:/docs.docker.com/go/build-exporters/") } } 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, notSupported(driver.MultiPlatform, nodeDriver, "https://docs.docker.com/go/build-multi-platform/") } so.FrontendAttrs["platform"] = strings.Join(pp, ",") } @@ -1560,8 +1560,10 @@ 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 notSupported(f driver.Feature, d driver.Driver, docs string) error { + return errors.Errorf(`%s is not supported for the %s driver. +Switch to a different driver, or turn on the containerd image store, and try again. +Learn more at %s`, f, d.Factory().Name(), docs) } func noDefaultLoad() bool { diff --git a/driver/features.go b/driver/features.go index e48d7309427c..30ee2a482347 100644 --- a/driver/features.go +++ b/driver/features.go @@ -6,4 +6,4 @@ const OCIExporter Feature = "OCI exporter" const DockerExporter Feature = "Docker exporter" const CacheExport Feature = "Cache export" -const MultiPlatform Feature = "Multiple platforms" +const MultiPlatform Feature = "Multi-platform build" diff --git a/tests/build.go b/tests/build.go index a539651295df..0ad3cacd0b9a 100644 --- a/tests/build.go +++ b/tests/build.go @@ -44,6 +44,9 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testBuildAnnotations, testBuildBuildArgNoKey, testBuildLabelNoKey, + testBuildCacheExportNotSupported, + testBuildOCIExportNotSupported, + testBuildMultiPlatformNotSupported, } func testBuild(t *testing.T, sb integration.Sandbox) { @@ -376,3 +379,39 @@ func testBuildLabelNoKey(t *testing.T, sb integration.Sandbox) { require.Error(t, err, string(out)) require.Equal(t, strings.TrimSpace(string(out)), `ERROR: invalid key-value pair "=TEST_STRING": empty key`) } + +func testBuildCacheExportNotSupported(t *testing.T, sb integration.Sandbox) { + if sb.Name() != "docker" { + t.Skip("skipping test for non-docker workers") + } + + dir := createTestProject(t) + cmd := buildxCmd(sb, withArgs("build", "--cache-to=type=registry", dir)) + out, err := cmd.CombinedOutput() + require.Error(t, err, string(out)) + require.Contains(t, string(out), "Cache export is not supported") +} + +func testBuildOCIExportNotSupported(t *testing.T, sb integration.Sandbox) { + if sb.Name() != "docker" { + t.Skip("skipping test for non-docker workers") + } + + dir := createTestProject(t) + cmd := buildxCmd(sb, withArgs("build", fmt.Sprintf("--output=type=oci,dest=%s/result", dir), dir)) + out, err := cmd.CombinedOutput() + require.Error(t, err, string(out)) + require.Contains(t, string(out), "OCI exporter is not supported") +} + +func testBuildMultiPlatformNotSupported(t *testing.T, sb integration.Sandbox) { + if sb.Name() != "docker" { + t.Skip("skipping test for non-docker workers") + } + + dir := createTestProject(t) + cmd := buildxCmd(sb, withArgs("build", "--platform=linux/amd64,linux/arm64", dir)) + out, err := cmd.CombinedOutput() + require.Error(t, err, string(out)) + require.Contains(t, string(out), "Multi-platform build is not supported") +}