Fix support for pulling manifest lists via Docker V1 protocol where applicable

This commit is contained in:
Joseph Schorr 2018-11-14 14:05:06 +02:00
parent 37b20010aa
commit 276d0d571d
6 changed files with 48 additions and 9 deletions

View file

@ -12,6 +12,12 @@ class RegistryDataInterface(object):
""" Returns whether the implementation of the data interface supports schema 2 format
manifests. """
@abstractmethod
def get_legacy_tags_map(self, repository_ref, storage):
""" Returns a map from tag name to its legacy image ID, for all tags with legacy images in
the repository. Note that this can be a *very* heavy operation.
"""
@abstractmethod
def find_matching_tag(self, repository_ref, tag_names):
""" Finds an alive tag in the repository matching one of the given tag names and returns it

View file

@ -13,6 +13,7 @@ from data.registry_model.datatypes import (Tag, Manifest, LegacyImage, Label, Se
from data.registry_model.shared import SharedModel
from data.registry_model.label_handlers import apply_label_to_manifest
from image.docker import ManifestException
from image.docker.schema2 import DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE
logger = logging.getLogger(__name__)
@ -28,6 +29,31 @@ class OCIModel(SharedModel, RegistryDataInterface):
manifests. """
return True
def get_legacy_tags_map(self, repository_ref, storage):
""" Returns a map from tag name to its legacy image ID, for all tags with legacy images in
the repository. Note that this can be a *very* heavy operation.
"""
tags = oci.tag.list_alive_tags(repository_ref._db_id)
legacy_images_map = oci.tag.get_legacy_images_for_tags(tags)
tags_map = {}
for tag in tags:
legacy_image = legacy_images_map.get(tag.id)
if legacy_image is not None:
tags_map[tag.name] = legacy_image.docker_image_id
else:
manifest = Manifest.for_manifest(tag.manifest, None)
if legacy_image is None and manifest.media_type == DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE:
# See if we can lookup a schema1 legacy image.
v1_compatible = self.get_schema1_parsed_manifest(manifest, '', '', '', storage)
if v1_compatible is not None:
v1_id = v1_compatible.leaf_layer_v1_image_id
if v1_id is not None:
tags_map[tag.name] = v1_id
return tags_map
def find_matching_tag(self, repository_ref, tag_names):
""" Finds an alive tag in the repository matching one of the given tag names and returns it
or None if none.

View file

@ -32,6 +32,13 @@ class PreOCIModel(SharedModel, RegistryDataInterface):
manifests. """
return False
def get_legacy_tags_map(self, repository_ref, storage):
""" Returns a map from tag name to its legacy image, for all tags with legacy images in
the repository.
"""
tags = self.list_repository_tags(repository_ref, include_legacy_images=True)
return {tag.name: tag.legacy_image.docker_image_id for tag in tags}
def find_matching_tag(self, repository_ref, tag_names):
""" Finds an alive tag in the repository matching one of the given tag names and returns it
or None if none.

View file

@ -231,6 +231,8 @@ def test_repository_tags(repo_namespace, repo_name, registry_model):
tags = registry_model.list_repository_tags(repository_ref, include_legacy_images=True)
assert len(tags)
tags_map = registry_model.get_legacy_tags_map(repository_ref, storage)
for tag in tags:
found_tag = registry_model.get_repo_tag(repository_ref, tag.name, include_legacy_image=True)
assert found_tag == tag
@ -241,6 +243,8 @@ def test_repository_tags(repo_namespace, repo_name, registry_model):
found_image = registry_model.get_legacy_image(repository_ref,
found_tag.legacy_image.docker_image_id)
assert found_image == found_tag.legacy_image
assert tag.name in tags_map
assert tags_map[tag.name] == found_image.docker_image_id
def test_repository_tag_history(registry_model):