From 6024f8a68aed7f0cc1f54c9674de6b688ad7b66b Mon Sep 17 00:00:00 2001 From: yminer Date: Mon, 26 Feb 2024 02:34:22 +0000 Subject: [PATCH] update support for artifactType when config mediatype is empty Signed-off-by: yminer --- src/controller/artifact/abstractor.go | 7 +++- src/controller/artifact/abstractor_test.go | 42 ++++++++++++++++++- .../artifact/processor/default_test.go | 36 ++++++++++++++++ src/go.mod | 8 ++-- src/go.sum | 4 +- 5 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/controller/artifact/abstractor.go b/src/controller/artifact/abstractor.go index 233008157..935d7804f 100644 --- a/src/controller/artifact/abstractor.go +++ b/src/controller/artifact/abstractor.go @@ -131,7 +131,12 @@ func (a *abstractor) abstractManifestV2Metadata(artifact *artifact.Artifact, con if manifest.Annotations[wasm.AnnotationVariantKey] == wasm.AnnotationVariantValue || manifest.Annotations[wasm.AnnotationHandlerKey] == wasm.AnnotationHandlerValue { artifact.MediaType = wasm.MediaType } - + // https://github.com/opencontainers/image-spec/blob/v1.1.0/specs-go/v1/mediatype.go + // if config descriptor is empty JSON{}, using manifest.ArtifactType as artifact.MediaType + // artifacts have historically been created without an artifactType field, and tooling to work with artifacts should fallback to the config.mediaType value. + if manifest.Config.MediaType == v1.MediaTypeEmptyJSON && manifest.ArtifactType != "" { + artifact.MediaType = manifest.ArtifactType + } // set size artifact.Size = int64(len(content)) + manifest.Config.Size for _, layer := range manifest.Layers { diff --git a/src/controller/artifact/abstractor_test.go b/src/controller/artifact/abstractor_test.go index 47b340f04..42d2c34fc 100644 --- a/src/controller/artifact/abstractor_test.go +++ b/src/controller/artifact/abstractor_test.go @@ -175,7 +175,27 @@ var ( "com.example.key1": "value1" } }` - + v2ManifestWithEmptyConfig = `{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.example+type", + "config": { + "mediaType": "application/vnd.oci.empty.v1+json", + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a", + "size": 2 + }, + "layers": [ + { + "mediaType": "application/vnd.example+type", + "digest": "sha256:e258d248fda94c63753607f7c4494ee0fcbe92f1a76bfdac795c9d84101eb317", + "size": 1234 + } + ], + "annotations": { + "oci.opencontainers.image.created": "2023-01-02T03:04:05Z", + "com.example.data": "payload" + } +}` index = `{ "schemaVersion": 2, "manifests": [ @@ -267,6 +287,26 @@ func (a *abstractorTestSuite) TestAbstractMetadataOfV2Manifest() { a.Equal("value1", artifact.Annotations["com.example.key1"]) } +// empty config layer +func (a *abstractorTestSuite) TestAbstractMetadataOfV2ManifestWithEmptyConfig() { + // v1.MediaTypeImageManifest + manifest, _, err := distribution.UnmarshalManifest(v1.MediaTypeImageManifest, []byte(v2ManifestWithEmptyConfig)) + a.Require().Nil(err) + a.regCli.On("PullManifest", mock.Anything, mock.Anything).Return(manifest, "", nil) + artifact := &artifact.Artifact{ + ID: 1, + } + a.processor.On("AbstractMetadata", mock.Anything, mock.Anything, mock.Anything).Return(nil) + err = a.abstractor.AbstractMetadata(nil, artifact) + a.Require().Nil(err) + a.Assert().Equal(int64(1), artifact.ID) + a.Assert().Equal(v1.MediaTypeImageManifest, artifact.ManifestMediaType) + a.Assert().Equal("application/vnd.example+type", artifact.MediaType) + a.Assert().Equal(int64(1880), artifact.Size) + a.Require().Len(artifact.Annotations, 2) + a.Equal("payload", artifact.Annotations["com.example.data"]) +} + // OCI index func (a *abstractorTestSuite) TestAbstractMetadataOfIndex() { manifest, _, err := distribution.UnmarshalManifest(v1.MediaTypeImageIndex, []byte(index)) diff --git a/src/controller/artifact/processor/default_test.go b/src/controller/artifact/processor/default_test.go index 0f6af7734..f840da37c 100644 --- a/src/controller/artifact/processor/default_test.go +++ b/src/controller/artifact/processor/default_test.go @@ -142,6 +142,29 @@ var ( } }` unknownConfig = `{NHL Peanut Butter on my NHL bagel}` + + v2ManifestWithEmptyConfig = `{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.example+type", + "config": { + "mediaType": "application/vnd.oci.empty.v1+json", + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a", + "size": 2 + }, + "layers": [ + { + "mediaType": "application/vnd.example+type", + "digest": "sha256:e258d248fda94c63753607f7c4494ee0fcbe92f1a76bfdac795c9d84101eb317", + "size": 1234 + } + ], + "annotations": { + "oci.opencontainers.image.created": "2023-01-02T03:04:05Z", + "com.example.data": "payload" + } + }` + emptyConfig = `{}` ) type defaultProcessorTestSuite struct { @@ -244,6 +267,19 @@ func (d *defaultProcessorTestSuite) TestAbstractMetadataWithUnknownConfig() { d.Len(unknownConfig, 35) } +func (d *defaultProcessorTestSuite) TestAbstractMetadataWithEmptyConfig() { + manifest, _, err := distribution.UnmarshalManifest(v1.MediaTypeImageManifest, []byte(v2ManifestWithEmptyConfig)) + d.Require().Nil(err) + manifestMediaType, content, err := manifest.Payload() + d.Require().Nil(err) + + art := &artifact.Artifact{ManifestMediaType: manifestMediaType} + err = d.processor.AbstractMetadata(context.TODO(), art, content) + d.Assert().Equal(0, len(art.ExtraAttrs)) + d.Assert().Equal(2, len(emptyConfig)) + d.Require().Nil(err) +} + func TestDefaultProcessorTestSuite(t *testing.T) { suite.Run(t, &defaultProcessorTestSuite{}) } diff --git a/src/go.mod b/src/go.mod index e8a84ace4..afff0655c 100644 --- a/src/go.mod +++ b/src/go.mod @@ -21,12 +21,12 @@ require ( github.com/go-asn1-ber/asn1-ber v1.5.5 github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-openapi/errors v0.21.0 - github.com/go-openapi/loads v0.21.2 // indirect + github.com/go-openapi/loads v0.21.2 github.com/go-openapi/runtime v0.26.2 - github.com/go-openapi/spec v0.20.11 // indirect + github.com/go-openapi/spec v0.20.11 github.com/go-openapi/strfmt v0.21.8 github.com/go-openapi/swag v0.22.7 - github.com/go-openapi/validate v0.22.3 // indirect + github.com/go-openapi/validate v0.22.3 github.com/go-redis/redis/v8 v8.11.4 github.com/gocarina/gocsv v0.0.0-20210516172204-ca9e8a8ddea8 github.com/gocraft/work v0.5.1 @@ -45,7 +45,7 @@ require ( github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b + github.com/opencontainers/image-spec v1.1.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/robfig/cron/v3 v3.0.1 diff --git a/src/go.sum b/src/go.sum index 1824a5427..7a01d92fd 100644 --- a/src/go.sum +++ b/src/go.sum @@ -496,8 +496,8 @@ github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=