Fix link-to-parent-with-different-blob issue and add a test

This commit is contained in:
Joseph Schorr 2016-03-14 15:24:18 -04:00
parent ba2851c952
commit 57e5141fb5
2 changed files with 165 additions and 15 deletions

View file

@ -124,7 +124,7 @@ class SignedManifest(object):
@property
def layers(self):
""" Returns a generator of objects that have the blobSum and v1Compatibility keys in them,
starting from the leaf image and working toward the base node.
starting from the base image and working toward the leaf node.
"""
for blob_sum_obj, history_obj in reversed(zip(self._parsed[_FS_LAYERS_KEY],
self._parsed[_HISTORY_KEY])):
@ -152,15 +152,9 @@ class SignedManifest(object):
@property
def payload(self):
protected = str(self._signatures[0][_PROTECTED_KEY])
parsed_protected = json.loads(jwt.utils.base64url_decode(protected))
logger.debug('parsed_protected: %s', parsed_protected)
signed_content_head = self._bytes[:parsed_protected[_FORMAT_LENGTH_KEY]]
logger.debug('signed content head: %s', signed_content_head)
signed_content_tail = jwt.utils.base64url_decode(str(parsed_protected[_FORMAT_TAIL_KEY]))
logger.debug('signed content tail: %s', signed_content_tail)
return signed_content_head + signed_content_tail
@ -189,6 +183,7 @@ class SignedManifestBuilder(object):
self._history.append({
_V1_COMPAT_KEY: v1_json_metadata,
})
return self
def build(self, json_web_key):
@ -354,7 +349,7 @@ def _updated_v1_metadata(v1_metadata_json, updated_id_map):
return json.dumps(parsed)
def _write_manifest(namespace_name, repo_name, manifest):
def _write_manifest_itself(namespace_name, repo_name, manifest):
# Ensure that the manifest is for this repository. If the manifest's namespace is empty, then
# it is for the library namespace and we need an extra check.
if (manifest.namespace == '' and features.LIBRARY_SUPPORT and
@ -396,11 +391,20 @@ def _write_manifest(namespace_name, repo_name, manifest):
has_rewritten_ids = False
updated_id_map = {}
# Synthesized image id hash. Can be used to pull a "content addressable" image id out of thin air.
digest_history = hashlib.sha256()
for mdata in layers:
digest_str = str(mdata.digest)
v1_mdata = mdata.v1_metadata
working_docker_id = v1_mdata.docker_id
# Update our digest_history hash for the new layer data.
digest_history.update(digest_str)
digest_history.update("@")
digest_history.update(mdata.v1_metadata_str.encode('utf-8'))
digest_history.update("|")
# Ensure that all blobs exist.
blob_storage = storage_map.get(digest_str)
if blob_storage is None:
@ -413,10 +417,9 @@ def _write_manifest(namespace_name, repo_name, manifest):
images_map[v1_mdata.docker_id].storage.content_checksum != digest_str) or
has_rewritten_ids):
v1_metadata_str = mdata.v1_metadata_str.encode('utf-8')
working_docker_id = hashlib.sha256(v1_metadata_str + '@' + digest_str).hexdigest()
logger.debug('Rewriting docker_id %s/%s %s -> %s', namespace_name, repo_name,
v1_mdata.docker_id, working_docker_id)
working_docker_id = digest_history.hexdigest()
logger.warning('Rewriting docker_id %s/%s %s -> %s', namespace_name, repo_name,
v1_mdata.docker_id, working_docker_id)
has_rewritten_ids = True
# Store the new docker id in the map
@ -431,9 +434,6 @@ def _write_manifest(namespace_name, repo_name, manifest):
raise ManifestInvalid(detail={'message': msg})
# Synthesize and store the v1 metadata in the db.
digest_str = str(mdata.digest)
blob_storage = storage_map[digest_str]
v1_metadata_json = mdata.v1_metadata_str
if has_rewritten_ids:
v1_metadata_json = _updated_v1_metadata(mdata.v1_metadata_str, updated_id_map)
@ -453,6 +453,11 @@ def _write_manifest(namespace_name, repo_name, manifest):
leaf_layer_id = images_map[layers[-1].v1_metadata.docker_id].docker_image_id
model.tag.store_tag_manifest(namespace_name, repo_name, tag_name, leaf_layer_id, manifest_digest,
manifest.bytes)
return (repo, tag_name, manifest_digest)
def _write_manifest(namespace_name, repo_name, manifest):
(repo, tag_name, manifest_digest) = _write_manifest_itself(namespace_name, repo_name, manifest)
# Spawn the repo_push event.
event_data = {