oras-project / oras

OCI registry client - managing content like artifacts, images, packages
https://oras.land
Apache License 2.0
1.52k stars 181 forks source link

Adding platform annotations in artifact manifests through `--artifact-platform` #1538

Open Wwwsylvia opened 1 week ago

Wwwsylvia commented 1 week ago

Problem

In order to support multi-arch artifacts, we introduced a new --artifact-platform flag to the oras push command in the PR #1500.

The current implementation embeds the platform information into the config payload, which looks like this:

{
  "architecture": "amd64",
  "os": "linux"
}

We set the config media type to "application/vnd.oci.image.config.v1+json" for compatibility reasons, so the config descriptor looks like this:

{
  "mediaType": "application/vnd.oci.image.config.v1+json",
  "digest": "sha256:9d99a75171aea000c711b34c0e5e3f28d3d537dd99d110eafbfbc2bd8e52c2bf",
  "size": 37
}

However, we have we identified several problems with this implementation:

  1. The artifact containing such a config blob that ORAS produces is not a compliant OCI Image.
  2. It requires an extra request for the consumer to fetch the config blob in order to get the platform details.
  3. Since a config can be any blob other than JSON and can be extremely large, a list of acceptable config media types would need to be maintained by all consumers, and a size limit would need to be applied for security considerations.
  4. It would be challenging for existing OCI artifact producers to embed the platform field if they already have their config utilized.

Solution

We have opened an issue on the OCI image-spec repo to seek a proper solution for adding platform information into artifacts. While we work towards finding the best approach, we should consider implementing Approach 1 mentioned in the proposal, which offers more advantages over the current implementation.

Adding platform annotations in the manifest

As the OCI community has not yet agreed on this approach, we need to define the annotations under the ORAS namespace instead of the OCI namespace.

For instance, the architecture and OS information could be placed in land.oras.artifact.platform.architecture and land.oras.artifact.platform.os annotations, respectively. Additional details like OS version, OS features, and variant could be included in land.oras.artifact.platform.osversion, land.oras.artifact.platform.osfeatures, and land.oras.artifact.platform.variant.

For example, the manifest annotations for a linux/amd64 artifact would look like this:

{
  "land.oras.artifact.platform.architecture": "amd64",
  "land.oras.artifact.platform.os": "linux"
}

The complete manifest containing such annotations would then look like this:

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "artifactType": "application/vnd.unknown.artifact.v1",
  "config": {
    "mediaType": "application/vnd.oci.empty.v1+json",
    "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
    "size": 2,
    "data": "e30="
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.empty.v1+json",
      "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
      "size": 2
    }
  ],
  "annotations": {
    "org.opencontainers.image.created": "2024-10-22T15:41:20Z",
    "land.oras.artifact.platform.architecture": "amd64",
    "land.oras.artifact.platform.os": "linux"
  }
}

This approach is straightforward to implement for both producers and consumers, with annotations that are friendly for humans to read. It also enables end users to query or filter out specific platforms based on annotations when listing manifests. Additionally, the annotations can be applied to platform-specific Image Indexes.