diff --git a/cmd/buildctl/build_test.go b/cmd/buildctl/build_test.go index d85ceb688a01..1eb577185ac0 100644 --- a/cmd/buildctl/build_test.go +++ b/cmd/buildctl/build_test.go @@ -120,64 +120,114 @@ func testBuildMetadataFile(t *testing.T, sb integration.Sandbox) { rdr, err := marshal(sb.Context(), st.Root()) require.NoError(t, err) - tmpDir := t.TempDir() - imageName := "example.com/moby/metadata:test" - metadataFile := filepath.Join(tmpDir, "metadata.json") - buildCmd := []string{ - "build", "--progress=plain", - "--output type=image,name=" + imageName + ",push=false", - "--metadata-file", metadataFile, + cases := []struct { + name string + buildCmd []string + // TODO: Add descriptors counts + }{ + { + name: "single architecture", + buildCmd: []string{ + "build", "--progress=plain", + "--output type=image,name=" + imageName + ",push=false", + }, + }, + { + name: "multiple architecture", + buildCmd: []string{ + "build", "--progress=plain", + "--output type=image,name=" + imageName + ",push=false", + "--opt", "platform=linux/amd64,linux/arm64", + }, + }, + { + name: "single architecture attestation", + buildCmd: []string{ + "build", "--progress=plain", + "--output type=image,name=" + imageName + ",push=false", + "--opt", "attest:provenance=mode=max", + }, + }, + { + name: "multi architecture attestations", + buildCmd: []string{ + "build", "--progress=plain", + "--output type=image,name=" + imageName + ",push=false", + "--opt", "platform=linux/amd64,linux/arm64", + "--opt", "attest:provenance=mode=max", + }, + }, } - cmd := sb.Cmd(strings.Join(buildCmd, " ")) - cmd.Stdin = rdr - err = cmd.Run() - require.NoError(t, err) - - require.FileExists(t, metadataFile) - metadataBytes, err := os.ReadFile(metadataFile) - require.NoError(t, err) - - var metadata map[string]json.RawMessage - err = json.Unmarshal(metadataBytes, &metadata) - require.NoError(t, err) - - require.Contains(t, metadata, "image.name") - require.Equal(t, imageName, metadata["image.name"]) - - require.Contains(t, metadata, exptypes.ExporterImageDigestKey) - digest := metadata[exptypes.ExporterImageDigestKey] - require.NotEmpty(t, digest) - - require.Contains(t, metadata, exptypes.ExporterImageDescriptorKey) - var desc *ocispecs.Descriptor - err = json.Unmarshal(metadata[exptypes.ExporterImageDescriptorKey], &desc) - require.NoError(t, err) - require.NotEmpty(t, desc.MediaType) - require.NotEmpty(t, desc.Digest.String()) - - require.Contains(t, metadata, exptypes.ExporterImageDescriptorsKey) - var descList []*ocispecs.Descriptor - require.NoError(t, err) - err = json.Unmarshal(metadata[exptypes.ExporterImageDescriptorsKey], &descList) - require.NoError(t, err) - - cdAddress := sb.ContainerdAddress() - if cdAddress == "" { - t.Log("no containerd worker, skipping digest verification") - } else { - client, err := containerd.New(cdAddress, containerd.WithTimeout(60*time.Second)) - require.NoError(t, err) - defer client.Close() - - ctx := namespaces.WithNamespace(context.Background(), "buildkit") - - img, err := client.GetImage(ctx, imageName) - require.NoError(t, err) - - require.Equal(t, img.Metadata().Target.Digest.String(), digest) + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + tmpDir := t.TempDir() + metadataFile := filepath.Join(tmpDir, "metadata.json") + + buildCmd := append( + tt.buildCmd, + "--metadata-file", metadataFile, + ) + cmd := sb.Cmd(strings.Join(buildCmd, " ")) + cmd.Stdin = rdr + err = cmd.Run() + require.NoError(t, err) + + require.FileExists(t, metadataFile) + metadataBytes, err := os.ReadFile(metadataFile) + require.NoError(t, err) + + var metadata map[string]json.RawMessage + err = json.Unmarshal(metadataBytes, &metadata) + require.NoError(t, err) + + require.Contains(t, metadata, "image.name") + var name string + err = json.Unmarshal(metadata["image.name"], &name) + require.NoError(t, err) + require.Equal(t, imageName, string(name)) + + var digest string + require.Contains(t, metadata, exptypes.ExporterImageDigestKey) + err = json.Unmarshal(metadata[exptypes.ExporterImageDigestKey], &digest) + require.NoError(t, err) + require.NotEmpty(t, digest) + + require.Contains(t, metadata, exptypes.ExporterImageDescriptorKey) + var desc *ocispecs.Descriptor + err = json.Unmarshal(metadata[exptypes.ExporterImageDescriptorKey], &desc) + require.NoError(t, err) + require.NotEmpty(t, desc.MediaType) + require.NotEmpty(t, desc.Digest.String()) + + require.Contains(t, metadata, exptypes.ExporterImageDescriptorsKey) + var descList []*ocispecs.Descriptor + require.NoError(t, err) + err = json.Unmarshal(metadata[exptypes.ExporterImageDescriptorsKey], &descList) + require.NoError(t, err) + for _, desc := range descList { + require.NotEmpty(t, desc.MediaType) + require.NotEmpty(t, desc.Digest.String()) + } + + cdAddress := sb.ContainerdAddress() + if cdAddress == "" { + t.Log("no containerd worker, skipping digest verification") + } else { + client, err := containerd.New(cdAddress, containerd.WithTimeout(60*time.Second)) + require.NoError(t, err) + defer client.Close() + + ctx := namespaces.WithNamespace(context.Background(), "buildkit") + + img, err := client.GetImage(ctx, imageName) + require.NoError(t, err) + + require.Equal(t, img.Metadata().Target.Digest.String(), digest) + } + }) } }