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

fix: Accept schema 2 images as OCI index children (PROJQUAY-4826) #1959

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions image/oci/index.py
Expand Up @@ -47,6 +47,8 @@
DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE,
DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE,
)
from image.docker.schema2.manifest import DockerSchema2Manifest
from image.docker.schema2.list import DockerSchema2ManifestList
from image.oci import OCI_IMAGE_INDEX_CONTENT_TYPE, OCI_IMAGE_MANIFEST_CONTENT_TYPE
from image.oci.descriptor import get_descriptor_schema
from image.oci.manifest import OCIManifest
Expand Down Expand Up @@ -262,6 +264,8 @@ def manifests(self, content_retriever):
"""
manifests = self._parsed[INDEX_MANIFESTS_KEY]
supported_types = {}
supported_types[DOCKER_SCHEMA2_MANIFEST_CONTENT_TYPE] = DockerSchema2Manifest
supported_types[DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE] = DockerSchema2ManifestList
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a lot of assumptions in the code when dealing with parent tags of manifest lists. This might break some of those assumptions. e.g. When expiring a tag past the time machine, we expire the parent tag. In this scenario it's actually the parent tag of the parent tag that would need to be expired. Garbage collection also just checks the parent tag. We would probably want some additional testing around this to what exactly happens when you push nested manifest lists.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added this line because there is already one for OCI index:

supported_types[OCI_IMAGE_INDEX_CONTENT_TYPE] = OCIIndex

supported_types[OCI_IMAGE_MANIFEST_CONTENT_TYPE] = OCIManifest
supported_types[OCI_IMAGE_INDEX_CONTENT_TYPE] = OCIIndex
return [
Expand Down
31 changes: 22 additions & 9 deletions test/registry/registry_tests.py
Expand Up @@ -2271,14 +2271,24 @@ def test_push_pull_manifest_list_back_compat(
)


@pytest.mark.parametrize("schema_version", [1, 2, "oci"])
@pytest.mark.parametrize(
"schema_version, first_manifest_schema_version, second_manifest_schema_version",
[
(1, 1, 2),
(2, 2, 2),
("oci", "oci", "oci"),
("oci", 2, 2),
],
)
def test_push_pull_manifest_list(
v22_protocol,
basic_images,
different_images,
liveserver_session,
app_reloader,
schema_version,
first_manifest_schema_version,
second_manifest_schema_version,
data_model,
):
"""Test: Push a new tag with a manifest list containing two manifests, one (possibly) legacy
Expand All @@ -2294,15 +2304,18 @@ def test_push_pull_manifest_list(
"devtable", "newrepo", "latest", basic_images, blobs, options
)

if schema_version == "oci":
first_manifest = v22_protocol.build_oci(basic_images, blobs, options)
second_manifest = v22_protocol.build_oci(different_images, blobs, options)
else:
first_manifest = signed.unsigned()
if schema_version == 2:
first_manifest = v22_protocol.build_schema2(basic_images, blobs, options)
def _build_manifest(layers, schema_version):
if schema_version == "oci":
return v22_protocol.build_oci(layers, blobs, options)
elif schema_version == 2:
return v22_protocol.build_schema2(layers, blobs, options)
elif schema_version == 1:
return signed.unsigned()
else:
raise ValueError("invalid schema version")

second_manifest = v22_protocol.build_schema2(different_images, blobs, options)
first_manifest = _build_manifest(basic_images, first_manifest_schema_version)
second_manifest = _build_manifest(different_images, second_manifest_schema_version)

# Create and push the manifest list.
builder = OCIIndexBuilder() if schema_version == "oci" else DockerSchema2ManifestListBuilder()
Expand Down