diff --git a/client/client_test.go b/client/client_test.go index 495283c34288..a95965d66d3f 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -207,6 +207,7 @@ func TestIntegration(t *testing.T) { testExportLocalNoPlatformSplit, testExportLocalNoPlatformSplitOverwrite, testValidateNullConfig, + testValidateInvalidConfig, ) } @@ -8490,6 +8491,7 @@ cat < $BUILDKIT_SCAN_DESTINATION/spdx.json EOF ` img.Config.Cmd = []string{"/bin/sh", "-c", cmd} + img.Platform = p config, err := json.Marshal(img) if err != nil { return nil, errors.Wrapf(err, "failed to marshal image config") @@ -8768,6 +8770,7 @@ cat < $BUILDKIT_SCAN_DESTINATION/spdx.json EOF ` img.Config.Cmd = []string{"/bin/sh", "-c", cmd} + img.Platform = p config, err := json.Marshal(img) if err != nil { return nil, errors.Wrapf(err, "failed to marshal image config") @@ -8820,6 +8823,7 @@ EOF var img ocispecs.Image img.Config.Cmd = []string{"/bin/sh", "-c", "cat /greeting"} + img.Platform = p config, err := json.Marshal(img) if err != nil { return nil, errors.Wrapf(err, "failed to marshal image config") diff --git a/client/validation_test.go b/client/validation_test.go index 40cde42a532f..41886443e94a 100644 --- a/client/validation_test.go +++ b/client/validation_test.go @@ -2,12 +2,14 @@ package client import ( "context" + "encoding/json" "io" "testing" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/frontend/gateway/client" "github.com/moby/buildkit/util/testutil/integration" + ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/require" ) @@ -48,3 +50,49 @@ func testValidateNullConfig(t *testing.T, sb integration.Sandbox) { require.Error(t, err) require.Contains(t, err.Error(), "invalid null image config for export") } + +func testValidateInvalidConfig(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + + ctx := sb.Context() + + c, err := New(ctx, sb.Address()) + require.NoError(t, err) + defer c.Close() + + b := func(ctx context.Context, c client.Client) (*client.Result, error) { + def, err := llb.Scratch().Marshal(ctx) + if err != nil { + return nil, err + } + + res, err := c.Solve(ctx, client.SolveRequest{ + Evaluate: true, + Definition: def.ToPB(), + }) + if err != nil { + return nil, err + } + var img ocispecs.Image + img.Platform = ocispecs.Platform{ + Architecture: "amd64", + } + dt, err := json.Marshal(img) + if err != nil { + return nil, err + } + res.AddMeta("containerimage.config", dt) + return res, nil + } + + _, err = c.Build(ctx, SolveOpt{ + Exports: []ExportEntry{ + { + Type: ExporterOCI, + Output: fixedWriteCloser(nopWriteCloser{io.Discard}), + }, + }, + }, "", b, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid image config for export: missing os") +} diff --git a/exporter/containerimage/writer.go b/exporter/containerimage/writer.go index 05b8a28477e8..c5575303810e 100644 --- a/exporter/containerimage/writer.go +++ b/exporter/containerimage/writer.go @@ -583,6 +583,13 @@ func patchImageConfig(dt []byte, descs []ocispecs.Descriptor, history []ocispecs return nil, errors.Errorf("invalid null image config for export") } + if img.OS == "" { + return nil, errors.Errorf("invalid image config for export: missing os") + } + if img.Architecture == "" { + return nil, errors.Errorf("invalid image config for export: missing architecture") + } + var rootFS ocispecs.RootFS rootFS.Type = "layers" for _, desc := range descs {