diff --git a/src/controller/artifact/abstractor.go b/src/controller/artifact/abstractor.go index 233008157d54..2c2bd50b9b38 100644 --- a/src/controller/artifact/abstractor.go +++ b/src/controller/artifact/abstractor.go @@ -131,6 +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-rc4/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 == "application/vnd.oci.empty.v1+json" && manifest.ArtifactType != "" { + artifact.MediaType = manifest.ArtifactType + } // set size artifact.Size = int64(len(content)) + manifest.Config.Size diff --git a/src/controller/artifact/abstractor_test.go b/src/controller/artifact/abstractor_test.go index 47b340f04a88..42d2c34fca09 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.go b/src/controller/artifact/processor/default.go index e8fea66f2b5d..cfe7fffb3f7a 100644 --- a/src/controller/artifact/processor/default.go +++ b/src/controller/artifact/processor/default.go @@ -101,7 +101,21 @@ func (d *defaultProcessor) AbstractMetadata(ctx context.Context, artifact *artif if err := json.Unmarshal(manifest, mani); err != nil { return err } - // get config layer + // parse annotation + annotationParser := annotation.NewParser() + err := annotationParser.Parse(ctx, artifact, manifest) + if err != nil { + log.Errorf("the annotation parser parse annotation for artifact error: %v", err) + } + + // if manifest.Config.Mediatype not comply with stanard config json regex (unknown type), + // regex will filter either none-json format config or empty config layer, and skip abstract artifact.ExtraAttrs + // "application/vnd.example+type", "application/vnd.oci.empty.v1+json" + if d.GetArtifactType(ctx, artifact) == ArtifactTypeUnknown { + return nil + } + + // else get config layer _, blob, err := d.regCli.PullBlob(artifact.RepositoryName, mani.Config.Digest.String()) if err != nil { return err @@ -109,19 +123,11 @@ func (d *defaultProcessor) AbstractMetadata(ctx context.Context, artifact *artif defer blob.Close() // parse metadata from config layer metadata := map[string]interface{}{} - // Some artifact may not have empty config layer. - if mani.Config.Size != 0 { - if err := json.NewDecoder(blob).Decode(&metadata); err != nil { - return err - } + if err := json.NewDecoder(blob).Decode(&metadata); err != nil { + return err } // Populate all metadata into the ExtraAttrs first. artifact.ExtraAttrs = metadata - annotationParser := annotation.NewParser() - err = annotationParser.Parse(ctx, artifact, manifest) - if err != nil { - log.Errorf("the annotation parser parse annotation for artifact error: %v", err) - } return nil } diff --git a/src/go.mod b/src/go.mod index 57367e4b24d6..046761bbfd99 100644 --- a/src/go.mod +++ b/src/go.mod @@ -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-rc5 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 github.com/robfig/cron/v3 v3.0.0 diff --git a/src/go.sum b/src/go.sum index 15f011b5dc60..8b36830172fe 100644 --- a/src/go.sum +++ b/src/go.sum @@ -614,8 +614,8 @@ github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= 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-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= 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= diff --git a/src/server/middleware/subject/subject.go b/src/server/middleware/subject/subject.go index b285891e70a1..b7a2daa45228 100644 --- a/src/server/middleware/subject/subject.go +++ b/src/server/middleware/subject/subject.go @@ -146,7 +146,9 @@ func Middleware() func(http.Handler) http.Handler { return err } } - w.Header().Set("OCI-Subject", subjectArt.Digest) + // when subject artifact is pushed before accessory artifact, current subject artifact do not exist. + // so we use reference manifest subject digest instead of subjectArt.Digest + w.Header().Set("OCI-Subject", mf.Subject.Digest.String()) } return nil diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go index 6f9e6fd3abff..581cf7cdfadf 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go @@ -59,13 +59,4 @@ const ( // AnnotationBaseImageName is the annotation key for the image reference of the image's base image. AnnotationBaseImageName = "org.opencontainers.image.base.name" - - // AnnotationArtifactCreated is the annotation key for the date and time on which the artifact was built, conforming to RFC 3339. - AnnotationArtifactCreated = "org.opencontainers.artifact.created" - - // AnnotationArtifactDescription is the annotation key for the human readable description for the artifact. - AnnotationArtifactDescription = "org.opencontainers.artifact.description" - - // AnnotationReferrersFiltersApplied is the annotation key for the comma separated list of filters applied by the registry in the referrers listing. - AnnotationReferrersFiltersApplied = "org.opencontainers.referrers.filtersApplied" ) diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/artifact.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/artifact.go deleted file mode 100644 index 03d76ce437ae..000000000000 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/artifact.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2022 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -// Artifact describes an artifact manifest. -// This structure provides `application/vnd.oci.artifact.manifest.v1+json` mediatype when marshalled to JSON. -type Artifact struct { - // MediaType is the media type of the object this schema refers to. - MediaType string `json:"mediaType"` - - // ArtifactType is the IANA media type of the artifact this schema refers to. - ArtifactType string `json:"artifactType"` - - // Blobs is a collection of blobs referenced by this manifest. - Blobs []Descriptor `json:"blobs,omitempty"` - - // Subject (reference) is an optional link from the artifact to another manifest forming an association between the artifact and the other manifest. - Subject *Descriptor `json:"subject,omitempty"` - - // Annotations contains arbitrary metadata for the artifact manifest. - Annotations map[string]string `json:"annotations,omitempty"` -} diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go index e6aa113f074e..36b0aeb8f1fc 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/config.go @@ -49,13 +49,15 @@ type ImageConfig struct { // StopSignal contains the system call signal that will be sent to the container to exit. StopSignal string `json:"StopSignal,omitempty"` - // ArgsEscaped `[Deprecated]` - This field is present only for legacy - // compatibility with Docker and should not be used by new image builders. - // It is used by Docker for Windows images to indicate that the `Entrypoint` - // or `Cmd` or both, contains only a single element array, that is a - // pre-escaped, and combined into a single string `CommandLine`. If `true` - // the value in `Entrypoint` or `Cmd` should be used as-is to avoid double - // escaping. + // ArgsEscaped + // + // Deprecated: This field is present only for legacy compatibility with + // Docker and should not be used by new image builders. It is used by Docker + // for Windows images to indicate that the `Entrypoint` or `Cmd` or both, + // contains only a single element array, that is a pre-escaped, and combined + // into a single string `CommandLine`. If `true` the value in `Entrypoint` or + // `Cmd` should be used as-is to avoid double escaping. + // https://github.com/opencontainers/image-spec/pull/892 ArgsEscaped bool `json:"ArgsEscaped,omitempty"` } @@ -95,22 +97,8 @@ type Image struct { // Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image. Author string `json:"author,omitempty"` - // Architecture is the CPU architecture which the binaries in this image are built to run on. - Architecture string `json:"architecture"` - - // Variant is the variant of the specified CPU architecture which image binaries are intended to run on. - Variant string `json:"variant,omitempty"` - - // OS is the name of the operating system which the image is built to run on. - OS string `json:"os"` - - // OSVersion is an optional field specifying the operating system - // version, for example on Windows `10.0.14393.1066`. - OSVersion string `json:"os.version,omitempty"` - - // OSFeatures is an optional field specifying an array of strings, - // each listing a required OS feature (for example on Windows `win32k`). - OSFeatures []string `json:"os.features,omitempty"` + // Platform describes the platform which the image in the manifest runs on. + Platform // Config defines the execution parameters which should be used as a base when running a container using the image. Config ImageConfig `json:"config,omitempty"` diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go index 9654aa5af68a..1881b11814b0 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go @@ -21,7 +21,7 @@ import digest "github.com/opencontainers/go-digest" // when marshalled to JSON. type Descriptor struct { // MediaType is the media type of the object this schema refers to. - MediaType string `json:"mediaType,omitempty"` + MediaType string `json:"mediaType"` // Digest is the digest of the targeted content. Digest digest.Digest `json:"digest"` @@ -52,7 +52,7 @@ type Descriptor struct { // Platform describes the platform which the image in the manifest runs on. type Platform struct { // Architecture field specifies the CPU architecture, for example - // `amd64` or `ppc64`. + // `amd64` or `ppc64le`. Architecture string `json:"architecture"` // OS specifies the operating system, for example `linux` or `windows`. @@ -70,3 +70,11 @@ type Platform struct { // example `v7` to specify ARMv7 when architecture is `arm`. Variant string `json:"variant,omitempty"` } + +// DescriptorEmptyJSON is the descriptor of a blob with content of `{}`. +var DescriptorEmptyJSON = Descriptor{ + MediaType: MediaTypeEmptyJSON, + Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`, + Size: 2, + Data: []byte(`{}`), +} diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go index ed4a56e59e85..e2bed9d4e469 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go @@ -24,9 +24,15 @@ type Index struct { // MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json` MediaType string `json:"mediaType,omitempty"` + // ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact. + ArtifactType string `json:"artifactType,omitempty"` + // Manifests references platform specific manifests. Manifests []Descriptor `json:"manifests"` + // Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest. + Subject *Descriptor `json:"subject,omitempty"` + // Annotations contains arbitrary metadata for the image index. Annotations map[string]string `json:"annotations,omitempty"` } diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go index fc79e9e0d140..c5503cb3053b 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/layout.go @@ -15,10 +15,14 @@ package v1 const ( - // ImageLayoutFile is the file name of oci image layout file + // ImageLayoutFile is the file name containing ImageLayout in an OCI Image Layout ImageLayoutFile = "oci-layout" // ImageLayoutVersion is the version of ImageLayout ImageLayoutVersion = "1.0.0" + // ImageIndexFile is the file name of the entry point for references and descriptors in an OCI Image Layout + ImageIndexFile = "index.json" + // ImageBlobsDir is the directory name containing content addressable blobs in an OCI Image Layout + ImageBlobsDir = "blobs" ) // ImageLayout is the structure in the "oci-layout" file, found in the root diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go index 730a09359b1c..26fec52a6bcf 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go @@ -23,6 +23,9 @@ type Manifest struct { // MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json` MediaType string `json:"mediaType,omitempty"` + // ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact. + ArtifactType string `json:"artifactType,omitempty"` + // Config references a configuration object for a container, by digest. // The referenced configuration object is a JSON blob that the runtime uses to set up the container. Config Descriptor `json:"config"` diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go index 935b481e3ed5..892ba3de9de7 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go @@ -40,21 +40,36 @@ const ( // MediaTypeImageLayerNonDistributable is the media type for layers referenced by // the manifest but with distribution restrictions. + // + // Deprecated: Non-distributable layers are deprecated, and not recommended + // for future use. Implementations SHOULD NOT produce new non-distributable + // layers. + // https://github.com/opencontainers/image-spec/pull/965 MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar" // MediaTypeImageLayerNonDistributableGzip is the media type for // gzipped layers referenced by the manifest but with distribution // restrictions. + // + // Deprecated: Non-distributable layers are deprecated, and not recommended + // for future use. Implementations SHOULD NOT produce new non-distributable + // layers. + // https://github.com/opencontainers/image-spec/pull/965 MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip" // MediaTypeImageLayerNonDistributableZstd is the media type for zstd // compressed layers referenced by the manifest but with distribution // restrictions. + // + // Deprecated: Non-distributable layers are deprecated, and not recommended + // for future use. Implementations SHOULD NOT produce new non-distributable + // layers. + // https://github.com/opencontainers/image-spec/pull/965 MediaTypeImageLayerNonDistributableZstd = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd" // MediaTypeImageConfig specifies the media type for the image configuration. MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json" - // MediaTypeArtifactManifest specifies the media type for a content descriptor. - MediaTypeArtifactManifest = "application/vnd.oci.artifact.manifest.v1+json" + // MediaTypeEmptyJSON specifies the media type for an unused blob containing the value `{}` + MediaTypeEmptyJSON = "application/vnd.oci.empty.v1+json" ) diff --git a/src/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/src/vendor/github.com/opencontainers/image-spec/specs-go/version.go index 1afd590fe0b5..11e09b584677 100644 --- a/src/vendor/github.com/opencontainers/image-spec/specs-go/version.go +++ b/src/vendor/github.com/opencontainers/image-spec/specs-go/version.go @@ -25,7 +25,7 @@ const ( VersionPatch = 0 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "-dev" + VersionDev = "-rc.5" ) // Version is the specification version that the package types support. diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index fc9dca4e78c2..83d3dc75e2dc 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -477,8 +477,8 @@ github.com/olekukonko/tablewriter # github.com/opencontainers/go-digest v1.0.0 ## explicit; go 1.13 github.com/opencontainers/go-digest -# github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b -## explicit; go 1.17 +# github.com/opencontainers/image-spec v1.1.0-rc5 +## explicit; go 1.18 github.com/opencontainers/image-spec/specs-go github.com/opencontainers/image-spec/specs-go/v1 # github.com/opentracing/opentracing-go v1.2.0