Merge pull request #3332 from quay/joseph.schorr/QUAY-1245/retarget-schema1-manifest
Add support for retargeting a tag to all schema 1 manifests
This commit is contained in:
commit
f03abfef12
3 changed files with 56 additions and 0 deletions
|
@ -14,6 +14,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.schema1 import DOCKER_SCHEMA1_CONTENT_TYPES
|
||||
from image.docker.schema2 import DOCKER_SCHEMA2_MANIFESTLIST_CONTENT_TYPE
|
||||
|
||||
|
||||
|
@ -313,6 +314,28 @@ class OCIModel(SharedModel, RegistryDataInterface):
|
|||
return None
|
||||
|
||||
manifest_id = created.manifest.id
|
||||
else:
|
||||
# If the manifest is a schema 1 manifest and its tag name does not match that
|
||||
# specified, then we need to create a new manifest, but with that tag name.
|
||||
if manifest_or_legacy_image.media_type in DOCKER_SCHEMA1_CONTENT_TYPES:
|
||||
try:
|
||||
parsed = manifest_or_legacy_image.get_parsed_manifest()
|
||||
except ManifestException:
|
||||
logger.exception('Could not parse manifest `%s` in retarget_tag',
|
||||
manifest_or_legacy_image._db_id)
|
||||
return None
|
||||
|
||||
if parsed.tag != tag_name:
|
||||
logger.debug('Rewriting manifest `%s` for tag named `%s`',
|
||||
manifest_or_legacy_image._db_id, tag_name)
|
||||
|
||||
repository_id = repository_ref._db_id
|
||||
updated = parsed.with_tag_name(tag_name)
|
||||
created = oci.manifest.get_or_create_manifest(repository_id, updated, storage)
|
||||
if created is None:
|
||||
return None
|
||||
|
||||
manifest_id = created.manifest.id
|
||||
|
||||
tag = oci.tag.retarget_tag(tag_name, manifest_id, is_reversion=is_reversion)
|
||||
legacy_image = LegacyImage.for_image(oci.shared.get_legacy_image_for_manifest(manifest_id))
|
||||
|
|
|
@ -342,6 +342,30 @@ def test_retarget_tag_history(use_manifest, registry_model):
|
|||
assert len(new_history) == len(history) + 1
|
||||
|
||||
|
||||
def test_retarget_tag_schema1(oci_model):
|
||||
repository_ref = oci_model.lookup_repository('devtable', 'simple')
|
||||
latest_tag = oci_model.get_repo_tag(repository_ref, 'latest')
|
||||
manifest = oci_model.get_manifest_for_tag(latest_tag)
|
||||
|
||||
existing_parsed = manifest.get_parsed_manifest()
|
||||
|
||||
# Retarget a new tag to the manifest.
|
||||
updated_tag = oci_model.retarget_tag(repository_ref, 'somenewtag', manifest, storage)
|
||||
assert updated_tag
|
||||
assert updated_tag.name == 'somenewtag'
|
||||
|
||||
updated_manifest = oci_model.get_manifest_for_tag(updated_tag)
|
||||
parsed = updated_manifest.get_parsed_manifest()
|
||||
assert parsed.namespace == 'devtable'
|
||||
assert parsed.repo_name == 'simple'
|
||||
assert parsed.tag == 'somenewtag'
|
||||
|
||||
assert parsed.layers == existing_parsed.layers
|
||||
|
||||
# Ensure the tag has changed targets.
|
||||
assert oci_model.get_repo_tag(repository_ref, 'somenewtag') == updated_tag
|
||||
|
||||
|
||||
def test_change_repository_tag_expiration(registry_model):
|
||||
repository_ref = registry_model.lookup_repository('devtable', 'simple')
|
||||
tag = registry_model.get_repo_tag(repository_ref, 'latest')
|
||||
|
|
|
@ -356,6 +356,15 @@ class DockerSchema1Manifest(ManifestInterface):
|
|||
|
||||
return builder.build()
|
||||
|
||||
def with_tag_name(self, tag_name, json_web_key=None):
|
||||
""" Returns a copy of this manifest, with the tag changed to the given tag name. """
|
||||
builder = DockerSchema1ManifestBuilder(self._namespace, self._repo_name, tag_name,
|
||||
self._architecture)
|
||||
for layer in reversed(self.layers):
|
||||
builder.add_layer(str(layer.digest), layer.raw_v1_metadata)
|
||||
|
||||
return builder.build(json_web_key)
|
||||
|
||||
def _generate_layers(self):
|
||||
"""
|
||||
Returns a generator of objects that have the blobSum and v1Compatibility keys in them,
|
||||
|
|
Reference in a new issue