Change V1 to use the manifest builder and new registry data model

This commit is contained in:
Joseph Schorr 2018-09-24 18:57:27 -04:00
parent 65d5be23c7
commit 4520f9e842
12 changed files with 291 additions and 689 deletions

View file

@ -1,3 +1,4 @@
import logging
import json
import uuid
@ -9,11 +10,11 @@ from data import model
from data.database import db_transaction
from data.registry_model import registry_model
logger = logging.getLogger(__name__)
ManifestLayer = namedtuple('ManifestLayer', ['layer_id', 'v1_metadata', 'db_id'])
ManifestLayer = namedtuple('ManifestLayer', ['layer_id', 'v1_metadata_string', 'db_id'])
_BuilderState = namedtuple('_BuilderState', ['builder_id', 'images', 'tags', 'checksums'])
_SESSION_KEY = '__manifestbuilder'
@ -61,7 +62,8 @@ class _ManifestBuilder(object):
return [registry_model.get_repo_tag(self._repository_ref, tag_name, include_legacy_image=True)
for tag_name in self._builder_state.tags.keys()]
def start_layer(self, layer_id, v1_metadata, location_name, calling_user, temp_tag_expiration):
def start_layer(self, layer_id, v1_metadata_string, location_name, calling_user,
temp_tag_expiration):
""" Starts a new layer with the given ID to be placed into a manifest. Returns the layer
started or None if an error occurred.
"""
@ -73,6 +75,15 @@ class _ManifestBuilder(object):
namespace_name = repository.namespace_user.username
repo_name = repository.name
try:
v1_metadata = json.loads(v1_metadata_string)
except ValueError:
logger.exception('Exception when trying to parse V1 metadata JSON for layer %s', layer_id)
return None
except TypeError:
logger.exception('Exception when trying to parse V1 metadata JSON for layer %s', layer_id)
return None
# Sanity check that the ID matches the v1 metadata.
if layer_id != v1_metadata['id']:
return None
@ -91,7 +102,7 @@ class _ManifestBuilder(object):
if existing_image is not None:
self._builder_state.images[layer_id] = existing_image.id
self._save_to_session()
return ManifestLayer(layer_id, v1_metadata, existing_image.id)
return ManifestLayer(layer_id, v1_metadata_string, existing_image.id)
with db_transaction():
# Otherwise, create a new legacy image and point a temporary tag at it.
@ -117,7 +128,7 @@ class _ManifestBuilder(object):
self._builder_state.images[layer_id] = created.id
self._save_to_session()
return ManifestLayer(layer_id, v1_metadata, created.id)
return ManifestLayer(layer_id, v1_metadata_string, created.id)
def lookup_layer(self, layer_id):
""" Returns a layer with the given ID under this builder. If none exists, returns None. """
@ -128,7 +139,7 @@ class _ManifestBuilder(object):
if image is None:
return None
return ManifestLayer(layer_id, json.loads(image.v1_json_metadata), image.id)
return ManifestLayer(layer_id, image.v1_json_metadata, image.id)
def assign_layer_blob(self, layer, blob, computed_checksums):
""" Assigns a blob to a layer. """
@ -151,7 +162,18 @@ class _ManifestBuilder(object):
def validate_layer_checksum(self, layer, checksum):
""" Returns whether the checksum for a layer matches that specified.
"""
return checksum in self._builder_state.checksums.get(layer.layer_id)
return checksum in self.get_layer_checksums(layer)
def get_layer_checksums(self, layer):
""" Returns the registered defined for the layer, if any. """
return self._builder_state.checksums.get(layer.layer_id) or []
def save_precomputed_checksum(self, layer, checksum):
""" Saves a precomputed checksum for a layer. """
checksums = self._builder_state.checksums.get(layer.layer_id) or []
checksums.append(checksum)
self._builder_state.checksums[layer.layer_id] = checksums
self._save_to_session()
def commit_tag_and_manifest(self, tag_name, layer):
""" Commits a new tag + manifest for that tag to the repository with the given name,
@ -171,7 +193,7 @@ class _ManifestBuilder(object):
def done(self):
""" Marks the manifest builder as complete and disposes of any state. This call is optional
and it is expected manifest builders will eventually time out if unusued for an
and it is expected manifest builders will eventually time out if unused for an
extended period of time.
"""
session.pop(_SESSION_KEY, None)