From 23c46478b79822ed9049e717e1f464ba8b2c2d2d Mon Sep 17 00:00:00 2001 From: Brandon Mitchell Date: Fri, 24 Mar 2023 16:37:36 -0400 Subject: [PATCH] Define image manifest artifactType and guidance Signed-off-by: Brandon Mitchell --- manifest.md | 93 ++++++++++++++++++++++++++++++- media-types.md | 1 + schema/image-manifest-schema.json | 4 ++ schema/manifest_test.go | 47 ++++++++++++++++ specs-go/v1/manifest.go | 3 + specs-go/v1/mediatype.go | 3 + 6 files changed, 148 insertions(+), 3 deletions(-) diff --git a/manifest.md b/manifest.md index 6f278f76c..58606e965 100644 --- a/manifest.md +++ b/manifest.md @@ -26,6 +26,12 @@ Unlike the [image index](image-index.md), which contains information about a set When used, this field MUST contain the media type `application/vnd.oci.image.manifest.v1+json`. This field usage differs from the [descriptor](descriptor.md#properties) use of `mediaType`. +- **`artifactType`** *string* + + This OPTIONAL property contains the type of an artifact when the manifest is used for an artifact. + This MUST be set when `config.mediaType` is set to the [scratch value](#example-of-a-scratch-config-or-layer-descriptor). + If defined, the value MUST comply with [RFC 6838][rfc6838], including the [naming requirements in its section 4.2][rfc6838-s4.2], and MAY be registered with [IANA][iana]. + - **`config`** *[descriptor](descriptor.md)* This REQUIRED property references a configuration object for a container, by digest. @@ -38,7 +44,8 @@ Unlike the [image index](image-index.md), which contains information about a set - [`application/vnd.oci.image.config.v1+json`](config.md) - Manifests concerned with portability SHOULD use one of the above media types. + Manifests for container images concerned with portability SHOULD use one of the above media types. + Manifests for artifacts concerned with portability SHOULD use `config.mediaType` as described in [Guidelines for Artifact Usage](#guidelines-for-artifact-usage). If the manifest uses a different media type than the above, it MUST comply with [RFC 6838][rfc6838], including the [naming requirements in its section 4.2][rfc6838-s4.2], and MAY be registered with [IANA][iana]. @@ -78,6 +85,8 @@ Unlike the [image index](image-index.md), which contains information about a set If the manifest uses a different media type than the above, it MUST comply with [RFC 6838][rfc6838], including the [naming requirements in its section 4.2][rfc6838-s4.2], and MAY be registered with [IANA][iana]. + See [Guidelines for Artifact Usage](#guidelines-for-artifact-usage) for other uses of the `layers`. + - **`subject`** *[descriptor](descriptor.md)* This OPTIONAL property specifies a [descriptor](descriptor.md) of another manifest. @@ -133,16 +142,94 @@ Unlike the [image index](image-index.md), which contains information about a set ## Example of a SCRATCH config or layer descriptor -Notice that the `mediaType` is subject to the usage or context, while the digest is specifically defined as `ScratchDigestSHA256` +Notice that the `mediaType` is subject to the usage or context, while the digest is specifically defined as `ScratchDigestSHA256`. +When the `ScratchDigestSHA256` is used, the media type SHOULD be set to `application/vnd.oci.scratch.v1+json` to differentiate the descriptor from one pointing to content. ```json,title=SCRATCH%20config&mediatype=application/vnd.oci.descriptor.v1%2Bjson { - "mediaType": "application/vnd.oci.example+json", + "mediaType": "application/vnd.oci.scratch.v1+json", "size": 2, "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" } ``` +## Guidelines for Artifact Usage + +Content other than OCI container images MAY be packaged using the image manifest. +When this is done, the `config.mediaType` value MUST be set to a value specific to the artifact type or the [scratch value](#example-of-a-scratch-config-or-layer-descriptor). +If the `config.mediaType` is set to the scratch value, the `artifactType` MUST be defined. +If the artifact does not need layers, a single layer SHOULD be included with a non-zero size. +The suggested content for an unused layer is the [SCRATCH](#example-of-a-scratch-config-or-layer-descriptor) descriptor. + +Here is an example manifest for a typical artifact: + +```json,title=Artifact%20with%20config&mediatype=application/vnd.oci.image.manifest.v1%2Bjson +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": { + "mediaType": "application/vnd.example.config.v1+json", + "digest": "sha256:5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03", + "size": 123 + }, + "layers": [ + { + "mediaType": "application/vnd.example.data.v1.tar+gzip", + "digest": "sha256:e258d248fda94c63753607f7c4494ee0fcbe92f1a76bfdac795c9d84101eb317", + "size": 1234 + } + ] +} +``` + +Here is an example manifest for a simple artifact without content in the config, using the scratch descriptor: + +```json,title=Artifact%20without%20config&mediatype=application/vnd.oci.image.manifest.v1%2Bjson +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.example+type", + "config": { + "mediaType": "application/vnd.oci.scratch.v1+json", + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a", + "size": 2 + }, + "layers": [ + { + "mediaType": "application/vnd.example+type", + "digest": "sha256:e258d248fda94c63753607f7c4494ee0fcbe92f1a76bfdac795c9d84101eb317", + "size": 1234 + } + ] +} +``` + +Here is an example manifest for an artifact with only annotations set, and the content of both blobs set to the scratch descriptor: + +```json,title=Minimal%20artifact&mediatype=application/vnd.oci.image.manifest.v1%2Bjson +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.example+type", + "config": { + "mediaType": "application/vnd.oci.scratch.v1+json", + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a", + "size": 2 + }, + "layers": [ + { + "mediaType": "application/vnd.oci.scratch.v1+json", + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a", + "size": 2 + } + ], + "annotations": { + "oci.opencontainers.image.created": "2023-01-02T03:04:05Z", + "com.example.data": "payload" + } +} +``` + [iana]: https://www.iana.org/assignments/media-types/media-types.xhtml [rfc6838]: https://tools.ietf.org/html/rfc6838 [rfc6838-s4.2]: https://tools.ietf.org/html/rfc6838#section-4.2 diff --git a/media-types.md b/media-types.md index e3d031c37..0dfe16b0a 100644 --- a/media-types.md +++ b/media-types.md @@ -10,6 +10,7 @@ The following media types identify the formats described here and their referenc - `application/vnd.oci.image.layer.v1.tar`: ["Layer", as a tar archive](layer.md) - `application/vnd.oci.image.layer.v1.tar+gzip`: ["Layer", as a tar archive](layer.md#gzip-media-types) compressed with [gzip][rfc1952] - `application/vnd.oci.image.layer.v1.tar+zstd`: ["Layer", as a tar archive](layer.md#zstd-media-types) compressed with [zstd][rfc8478] +- `application/vnd.oci.scratch.v1+json`: [Scratch blob](manifest.md#example-of-a-scratch-config-or-layer-descriptor) - `application/vnd.oci.artifact.manifest.v1+json`: [Artifact manifest](artifact.md) The following media types identify a ["Layer" with distribution restrictions](layer.md#non-distributable-layers), but are **deprecated** and not recommended for future use: diff --git a/schema/image-manifest-schema.json b/schema/image-manifest-schema.json index c16e91d6e..9bce5a150 100644 --- a/schema/image-manifest-schema.json +++ b/schema/image-manifest-schema.json @@ -15,6 +15,10 @@ "description": "the mediatype of the referenced object", "$ref": "defs-descriptor.json#/definitions/mediaType" }, + "artifactType": { + "description": "the artifact mediatype of the referenced object", + "$ref": "defs-descriptor.json#/definitions/mediaType" + }, "config": { "$ref": "content-descriptor.json" }, diff --git a/schema/manifest_test.go b/schema/manifest_test.go index 5071e2d24..7226e9ef8 100644 --- a/schema/manifest_test.go +++ b/schema/manifest_test.go @@ -289,6 +289,53 @@ func TestManifest(t *testing.T) { `, fail: true, }, + + // valid manifest for an artifact with a dedicated config + { + manifest: ` +{ + "schemaVersion": 2, + "mediaType" : "application/vnd.oci.image.manifest.v1+json", + "config": { + "mediaType": "application/vnd.example.config+json", + "size": 1470, + "digest": "sha256:c86f7763873b6c0aae22d963bab59b4f5debbed6685761b5951584f6efb0633b" + }, + "layers": [ + { + "mediaType": "application/vnd.example.data+type", + "size": 675598, + "digest": "sha256:9d3dd9504c685a304985025df4ed0283e47ac9ffa9bd0326fddf4d59513f0827" + } + ] +} +`, + fail: false, + }, + + // valid manifest for an artifact using the scratch config and artifactType + { + manifest: ` +{ + "schemaVersion": 2, + "mediaType" : "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.example+type", + "config": { + "mediaType": "application/vnd.oci.scratch.v1+json", + "size": 2, + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" + }, + "layers": [ + { + "mediaType": "application/vnd.example+type", + "size": 675598, + "digest": "sha256:9d3dd9504c685a304985025df4ed0283e47ac9ffa9bd0326fddf4d59513f0827" + } + ] +} +`, + fail: false, + }, } { r := strings.NewReader(tt.manifest) err := schema.ValidatorMediaTypeManifest.Validate(r) diff --git a/specs-go/v1/manifest.go b/specs-go/v1/manifest.go index ade02ec12..d8ed12f8a 100644 --- a/specs-go/v1/manifest.go +++ b/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/specs-go/v1/mediatype.go b/specs-go/v1/mediatype.go index bb331ad9d..3126d8107 100644 --- a/specs-go/v1/mediatype.go +++ b/specs-go/v1/mediatype.go @@ -70,6 +70,9 @@ const ( // MediaTypeImageConfig specifies the media type for the image configuration. MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json" + // MediaTypeScratch specifies the media type for an unused blob containing the value `{}` + MediaTypeScratch = "application/vnd.oci.scratch.v1+json" + // MediaTypeArtifactManifest specifies the media type for a content descriptor. MediaTypeArtifactManifest = "application/vnd.oci.artifact.manifest.v1+json" )