Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch from scratch to empty #1068

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 37 additions & 36 deletions manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Unlike the [image index](image-index.md), which contains information about a set
- **`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).
This MUST be set when `config.mediaType` is set to the [empty value](#guidance-for-an-empty-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)*
Expand All @@ -49,16 +49,13 @@ 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].

To set an effectively NULL or SCRATCH config and maintain portability the following is considered GUIDANCE.
While an empty blob (`size` of 0) may be preferable, practice has shown that not to be ubiquitiously supported.
Instead, the blob payload can be the most minimal content that is still valid JSON object: `{}` (`size` of 2).
The blob digest of `{}` is `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`.
See the [example SCRATCH config](#example-of-a-scratch-config-or-layer-descriptor) below, and `ScratchDescriptor` of the reference code.
To set an effectively null or empty config and maintain portability see the [guidance for an empty descriptor](#guidance-for-an-empty-descriptor) below, and `DescriptorEmptyJSON` of the reference code.

- **`layers`** *array of objects*

Each item in the array MUST be a [descriptor](descriptor.md).
For portability, `layers` SHOULD have at least one entry.
See the [guidance for an empty descriptor](#guidance-for-an-empty-descriptor) below, and `DescriptorEmptyJSON` of the reference code.

When the `config.mediaType` is set to `application/vnd.oci.image.config.v1+json`, the following additional restrictions apply:

Expand All @@ -67,9 +64,6 @@ Unlike the [image index](image-index.md), which contains information about a set
- The final filesystem layout MUST match the result of [applying](layer.md#applying-changesets) the layers to an empty directory.
- The [ownership, mode, and other attributes](layer.md#file-attributes) of the initial empty directory are unspecified.

For broad portability, if a layer is required to be used, use the SCRATCH layer.
See the [example SCRATCH layer](#example-of-a-scratch-config-or-layer-descriptor) below, and `ScratchDescriptor` of the reference code.

Beyond the [descriptor requirements](descriptor.md#properties), the value has the following additional restrictions:

- **`mediaType`** *string*
Expand All @@ -89,7 +83,7 @@ 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`.
See [Guidelines for Artifact Usage](#guidelines-for-artifact-usage) for other uses of the `layers`.

- **`subject`** *[descriptor](descriptor.md)*

Expand All @@ -112,30 +106,30 @@ Unlike the [image index](image-index.md), which contains information about a set
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"
"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7",
"size": 7023
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 32654,
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"
"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0",
"size": 32654
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 16724,
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"
"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
"size": 16724
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"size": 73109,
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"
"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736",
"size": 73109
}
],
"subject": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 7682,
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270"
"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
"size": 7682
},
"annotations": {
"com.example.key1": "value1",
Expand All @@ -144,28 +138,35 @@ Unlike the [image index](image-index.md), which contains information about a set
}
```

## Example of a SCRATCH config or layer descriptor
## Guidance for an Empty Descriptor

*Implementers note*: The following is considered GUIDANCE for portability.

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.
Parts of the spec necessitate including a descriptor to a blob where some implementations of artifacts do not have associated content.
While an empty blob (`size` of 0) may be preferable, practice has shown that not to be ubiquitously supported.
The media type `application/vnd.oci.empty.v1+json` (`MediaTypeEmptyJSON`) has been specified for a descriptor that has no content for the implementation.
The blob payload is the most minimal content that is still a valid JSON object: `{}` (`size` of 2).
The blob digest of `{}` is `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`.
The data field is optional, and if included is the base64 encoding of `{}`: `e30=`.

```json,title=SCRATCH%20config&mediatype=application/vnd.oci.descriptor.v1%2Bjson
The resulting descriptor shown here is also defined in reference code as `DescriptorEmptyJSON`:

```json,title=empty%20config&mediatype=application/vnd.oci.descriptor.v1%2Bjson
{
"mediaType": "application/vnd.oci.scratch.v1+json",
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2,
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"
"data": "e30="
}
```

The content of the scratch blob is `{}` (`size` of 2).

## 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.
When this is done, the `config.mediaType` value MUST be set to a value specific to the artifact type or the [empty value](#guidance-for-an-empty-descriptor).
If the `config.mediaType` is set to the empty 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.
The suggested content for an unused `layers` array is the [empty descriptor](#guidance-for-an-empty-descriptor).

Here is an example manifest for a typical artifact:

Expand All @@ -188,15 +189,15 @@ Here is an example manifest for a typical artifact:
}
```

Here is an example manifest for a simple artifact without content in the config, using the scratch descriptor:
Here is an example manifest for a simple artifact without content in the config, using the empty 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",
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2
},
Expand All @@ -210,21 +211,21 @@ Here is an example manifest for a simple artifact without content in the config,
}
```

Here is an example manifest for an artifact with only annotations set, and the content of both blobs set to the scratch descriptor:
Here is an example manifest for an artifact with only annotations set, and the content of both blobs set to the empty 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",
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2
},
"layers": [
{
"mediaType": "application/vnd.oci.scratch.v1+json",
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2
}
Expand Down
2 changes: 1 addition & 1 deletion media-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +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.empty.v1+json`: [Empty for unused descriptors](manifest.md#guidance-for-an-empty-descriptor)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If additional "strong" language/documentation advisable here, now would be a great time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


The following media types identify a ["Layer" with distribution restrictions](layer.md#non-distributable-layers), but are **deprecated** and not recommended for future use:

Expand Down
4 changes: 2 additions & 2 deletions schema/manifest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,15 @@ func TestManifest(t *testing.T) {
fail: false,
},

// valid manifest for an artifact using the scratch config and artifactType
// valid manifest for an artifact using the empty 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",
"mediaType": "application/vnd.oci.empty.v1+json",
"size": 2,
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"
},
Expand Down
8 changes: 8 additions & 0 deletions specs-go/v1/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(`{}`),
}
8 changes: 0 additions & 8 deletions specs-go/v1/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,3 @@ type Manifest struct {
// Annotations contains arbitrary metadata for the image manifest.
Annotations map[string]string `json:"annotations,omitempty"`
}

// ScratchDescriptor is the descriptor of a blob with content of `{}`.
var ScratchDescriptor = Descriptor{
MediaType: MediaTypeScratch,
Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`,
Size: 2,
Data: []byte(`{}`),
}
4 changes: 2 additions & 2 deletions specs-go/v1/mediatype.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,6 @@ 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"
// MediaTypeEmptyJSON specifies the media type for an unused blob containing the value `{}`
MediaTypeEmptyJSON = "application/vnd.oci.empty.v1+json"
)