Update the layer rename PR to preserve the original manifest
This commit is contained in:
parent
abd2e3c234
commit
6454b5aeb7
2 changed files with 25 additions and 47 deletions
|
@ -185,13 +185,6 @@ class SignedManifestBuilder(object):
|
||||||
_V1_COMPAT_KEY: v1_json_metadata,
|
_V1_COMPAT_KEY: v1_json_metadata,
|
||||||
})
|
})
|
||||||
|
|
||||||
def add_top_layer(self, layer_digest, v1_json_metadata):
|
|
||||||
self._fs_layer_digests.insert(0, {
|
|
||||||
_BLOB_SUM_KEY: layer_digest,
|
|
||||||
})
|
|
||||||
self._history.insert(0, {
|
|
||||||
_V1_COMPAT_KEY: v1_json_metadata,
|
|
||||||
})
|
|
||||||
|
|
||||||
def build(self, json_web_key):
|
def build(self, json_web_key):
|
||||||
""" Build the payload and sign it, returning a SignedManifest object.
|
""" Build the payload and sign it, returning a SignedManifest object.
|
||||||
|
@ -395,53 +388,33 @@ def _write_manifest(namespace, repo_name, manifest):
|
||||||
# a storage with a content checksum different from the existing, then we need to rewrite
|
# a storage with a content checksum different from the existing, then we need to rewrite
|
||||||
# the Docker ID to ensure consistency.
|
# the Docker ID to ensure consistency.
|
||||||
tag_name = manifest.tag
|
tag_name = manifest.tag
|
||||||
updated_manifest_builder = SignedManifestBuilder(namespace, repo_name, tag_name)
|
has_rewritten_ids = False
|
||||||
has_updated_manifest = False
|
|
||||||
updated_id_map = {}
|
updated_id_map = {}
|
||||||
|
|
||||||
for mdata in layers:
|
for mdata in layers:
|
||||||
digest_str = str(mdata.digest)
|
digest_str = str(mdata.digest)
|
||||||
v1_mdata = mdata.v1_metadata
|
v1_mdata = mdata.v1_metadata
|
||||||
updated_id_map[v1_mdata.docker_id] = v1_mdata.docker_id
|
working_docker_id = v1_mdata.docker_id
|
||||||
|
|
||||||
# Ensure that all blobs exist.
|
# Ensure that all blobs exist.
|
||||||
blob_storage = storage_map.get(digest_str)
|
blob_storage = storage_map.get(digest_str)
|
||||||
if blob_storage is None:
|
if blob_storage is None:
|
||||||
raise BlobUnknown(detail={'digest': digest_str})
|
raise BlobUnknown(detail={'digest': digest_str})
|
||||||
|
|
||||||
if v1_mdata.docker_id in images_map:
|
# Ensure that the V1 image's storage matches the V2 blob. If not, we've found
|
||||||
# Ensure that the V1 image's storage matches the V2 blob. If not, we've found
|
# a data inconsistency and need to create a new layer ID for the V1 image, and all images
|
||||||
# a data inconsistency and need to create a new layer ID for the V1 image.
|
# that follow it in the ancestry chain.
|
||||||
v1_image = images_map[v1_mdata.docker_id]
|
if ((v1_mdata.docker_id in images_map and
|
||||||
if has_updated_manifest or v1_image.storage.content_checksum != digest_str:
|
images_map[v1_mdata.docker_id].storage.content_checksum != digest_str) or
|
||||||
new_synthetic_id = hashlib.sha256(mdata.v1_metadata_str + '@' + digest_str).hexdigest()
|
has_rewritten_ids):
|
||||||
logger.debug('Got content mismatch for layer %s under repo %s/%s. New ID: %s',
|
|
||||||
v1_mdata.docker_id, namespace, repo_name, new_synthetic_id)
|
|
||||||
|
|
||||||
updated_id_map[v1_mdata.docker_id] = new_synthetic_id
|
working_docker_id = hashlib.sha256(mdata.v1_metadata_str + '@' + digest_str).hexdigest()
|
||||||
has_updated_manifest = True
|
logger.debug('Rewriting docker_id %s/%s %s -> %s', namespace, repo_name, v1_mdata.docker_id,
|
||||||
|
working_docker_id)
|
||||||
|
has_rewritten_ids = True
|
||||||
|
|
||||||
# Update the manifest withn the new ID (if any).
|
# Store the new docker id in the map
|
||||||
v1_metadata_json = mdata.v1_metadata_str
|
updated_id_map[v1_mdata.docker_id] = working_docker_id
|
||||||
if has_updated_manifest:
|
|
||||||
v1_metadata_json = _updated_v1_metadata(mdata.v1_metadata_str, updated_id_map)
|
|
||||||
|
|
||||||
updated_manifest_builder.add_top_layer(digest_str, v1_metadata_json)
|
|
||||||
|
|
||||||
# If the manifest was changed due to an updated layer ID, then create a new manifest
|
|
||||||
# based on the updated data.
|
|
||||||
if has_updated_manifest:
|
|
||||||
manifest = updated_manifest_builder.build(docker_v2_signing_key)
|
|
||||||
layers = list(manifest.layers)
|
|
||||||
|
|
||||||
# Synthesize the V1 metadata for each layer.
|
|
||||||
for mdata in layers:
|
|
||||||
v1_mdata = mdata.v1_metadata
|
|
||||||
|
|
||||||
# If the layer with the V1 id already exists, then nothing more to do. We've ensured
|
|
||||||
# it points to the correct content SHA above.
|
|
||||||
if v1_mdata.docker_id in images_map:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Lookup the parent image for the layer, if any.
|
# Lookup the parent image for the layer, if any.
|
||||||
parent_image = None
|
parent_image = None
|
||||||
|
@ -454,9 +427,14 @@ def _write_manifest(namespace, repo_name, manifest):
|
||||||
# Synthesize and store the v1 metadata in the db.
|
# Synthesize and store the v1 metadata in the db.
|
||||||
digest_str = str(mdata.digest)
|
digest_str = str(mdata.digest)
|
||||||
blob_storage = storage_map[digest_str]
|
blob_storage = storage_map[digest_str]
|
||||||
image = model.image.synthesize_v1_image(repo, blob_storage, v1_mdata.docker_id,
|
|
||||||
|
v1_metadata_json = mdata.v1_metadata_str
|
||||||
|
if has_rewritten_ids:
|
||||||
|
v1_metadata_json = _updated_v1_metadata(mdata.v1_metadata_str, updated_id_map)
|
||||||
|
|
||||||
|
image = model.image.synthesize_v1_image(repo, blob_storage, working_docker_id,
|
||||||
v1_mdata.created, v1_mdata.comment, v1_mdata.command,
|
v1_mdata.created, v1_mdata.comment, v1_mdata.command,
|
||||||
mdata.v1_metadata_str, parent_image)
|
v1_metadata_json, parent_image)
|
||||||
|
|
||||||
images_map[v1_mdata.docker_id] = image
|
images_map[v1_mdata.docker_id] = image
|
||||||
|
|
||||||
|
@ -466,9 +444,9 @@ def _write_manifest(namespace, repo_name, manifest):
|
||||||
|
|
||||||
# Store the manifest pointing to the tag.
|
# Store the manifest pointing to the tag.
|
||||||
manifest_digest = manifest.digest
|
manifest_digest = manifest.digest
|
||||||
leaf_layer = layers[-1]
|
leaf_layer_id = images_map[layers[-1].v1_metadata.docker_id].docker_image_id
|
||||||
model.tag.store_tag_manifest(namespace, repo_name, tag_name, leaf_layer.v1_metadata.docker_id,
|
model.tag.store_tag_manifest(namespace, repo_name, tag_name, leaf_layer_id, manifest_digest,
|
||||||
manifest_digest, manifest.bytes)
|
manifest.bytes)
|
||||||
|
|
||||||
# Spawn the repo_push event.
|
# Spawn the repo_push event.
|
||||||
event_data = {
|
event_data = {
|
||||||
|
|
|
@ -678,7 +678,7 @@ class V2RegistryPullMixin(V2RegistryMixin):
|
||||||
found_v1_layers.add(v1_history['id'])
|
found_v1_layers.add(v1_history['id'])
|
||||||
|
|
||||||
for image in images:
|
for image in images:
|
||||||
self.assertEquals(not munge_shas, image['id'] in found_v1_layers)
|
self.assertIn(image['id'], found_v1_layers)
|
||||||
|
|
||||||
return blobs
|
return blobs
|
||||||
|
|
||||||
|
|
Reference in a new issue