diff --git a/data/database.py b/data/database.py index 0f46ff9f6..9c5f48efd 100644 --- a/data/database.py +++ b/data/database.py @@ -172,6 +172,15 @@ class EmailConfirmation(BaseModel): created = DateTimeField(default=datetime.now) +class ImageStorage(BaseModel): + uuid = CharField(default=uuid_generator) + checksum = CharField(null=True) + created = DateTimeField(null=True) + comment = TextField(null=True) + command = TextField(null=True) + image_size = BigIntegerField(null=True) + + class Image(BaseModel): # This class is intentionally denormalized. Even though images are supposed # to be globally unique we can't treat them as such for permissions and @@ -198,18 +207,6 @@ class Image(BaseModel): ) -class ImageStorage(BaseModel): - storage_uuid = CharField(default=uuid_generator) - checksum = CharField(null=True) - created = DateTimeField(null=True) - comment = TextField(null=True) - command = TextField(null=True) - image_size = BigIntegerField(null=True) - - # '/' separated list of ancestory ids, e.g. /1/2/6/7/10/ - ancestors = CharField(index=True, default='/', max_length=64535) - - class RepositoryTag(BaseModel): name = CharField() image = ForeignKeyField(Image) @@ -262,4 +259,4 @@ all_models = [User, Repository, Image, AccessToken, Role, RepositoryPermission, Visibility, RepositoryTag, EmailConfirmation, FederatedLogin, LoginService, QueueItem, RepositoryBuild, Team, TeamMember, TeamRole, Webhook, - LogEntryKind, LogEntry, PermissionPrototype] + LogEntryKind, LogEntry, PermissionPrototype, ImageStorage] diff --git a/data/model.py b/data/model.py index 524245db9..3d9c1e128 100644 --- a/data/model.py +++ b/data/model.py @@ -537,26 +537,30 @@ def get_user_teams_within_org(username, organization): def get_visible_repository_count(username=None, include_public=True, - sort=False, namespace=None): - return get_visible_repository_internal(username=username, - include_public=include_public, - sort=sort, namespace=namespace, - get_count=True) + namespace=None): + query = _visible_repository_query(username=username, + include_public=include_public, + namespace=namespace) + return query.count() + def get_visible_repositories(username=None, include_public=True, page=None, limit=None, sort=False, namespace=None): - return get_visible_repository_internal(username=username, - include_public=include_public, - page=page, limit=limit, sort=sort, - namespace=namespace, get_count=False) + query = _visible_repository_query(username=username, + include_public=include_public, page=page, + limit=limit, namespace=namespace) + + if sort: + query = query.order_by(Repository.description.desc()) + + if limit: + query = query.limit(limit) + + return query -def get_visible_repository_internal(username=None, include_public=True, - limit=None, page=None, sort=False, - namespace=None, get_count=False): - if not username and not include_public: - return [] - +def _visible_repository_query(username=None, include_public=True, limit=None, + page=None, namespace=None): query = (Repository .select() # Note: We need to leave this blank for the get_count case. Otherwise, MySQL/RDS complains. .distinct() @@ -564,8 +568,19 @@ def get_visible_repository_internal(username=None, include_public=True, .switch(Repository) .join(RepositoryPermission, JOIN_LEFT_OUTER)) + query = _filter_to_repos_for_user(query, username, namespace, include_public) + + if page: + query = query.paginate(page, limit) + elif limit: + query = query.limit(limit) + + return query + + +def _filter_to_repos_for_user(query, username=None, namespace=None, + include_public=True): where_clause = None - admin_query = None if username: UserThroughTeam = User.alias() Org = User.alias() @@ -574,6 +589,7 @@ def get_visible_repository_internal(username=None, include_public=True, AdminUser = User.alias() query = (query + .switch(RepositoryPermission) .join(User, JOIN_LEFT_OUTER) .switch(RepositoryPermission) .join(Team, JOIN_LEFT_OUTER) @@ -606,19 +622,7 @@ def get_visible_repository_internal(username=None, include_public=True, else: where_clause = new_clause - if sort: - query = query.order_by(Repository.description.desc()) - - if page: - query = query.paginate(page, limit) - elif limit: - query = query.limit(limit) - - where = query.where(where_clause) - if get_count: - return where.count() - else: - return where + return query.where(where_clause) def get_matching_repositories(repo_term, username=None): @@ -779,14 +783,13 @@ def get_repo_image(namespace_name, repository_name, image_id): .join(ImageStorage, JOIN_LEFT_OUTER) .where(Repository.name == repository_name, Repository.namespace == namespace_name, - Image.docker_image_id == image_id) - .limit(1)) - result = list(query) - if not result: + Image.docker_image_id == image_id)) + + try: + return query.get() + except Image.DoesNotExist: return None - return result[0] - def repository_is_public(namespace_name, repository_name): joined = Repository.select().join(Visibility) @@ -868,10 +871,31 @@ def create_repository(namespace, name, creating_user, visibility='private'): return repo -def create_image(docker_image_id, repository): - new_image = Image.create(docker_image_id=docker_image_id, - repository=repository) - return new_image +def create_or_link_image(docker_image_id, repository, username, create=True): + with db.transaction(): + query = (ImageStorage + .select() + .distinct() + .join(Image) + .join(Repository) + .join(Visibility) + .switch(Repository) + .join(RepositoryPermission, JOIN_LEFT_OUTER)) + + query = (_filter_to_repos_for_user(query, username) + .where(Image.docker_image_id == docker_image_id)) + + try: + storage = query.get() + msg = 'Linking image to existing storage with docker id: %s and uuid: %s' + logger.debug(msg, docker_image_id, storage.uuid) + except ImageStorage.DoesNotExist: + logger.debug('Creating new storage for docker id: %s', docker_image_id) + storage = ImageStorage.create() + + new_image = Image.create(docker_image_id=docker_image_id, + repository=repository, storage=storage) + return new_image def set_image_checksum(docker_image_id, repository, checksum): @@ -884,46 +908,67 @@ def set_image_checksum(docker_image_id, repository, checksum): def set_image_size(docker_image_id, namespace_name, repository_name, image_size): - joined = Image.select().join(Repository) - image_list = list(joined.where(Repository.name == repository_name, - Repository.namespace == namespace_name, - Image.docker_image_id == docker_image_id)) + try: + image = (Image + .select(Image, ImageStorage) + .join(Repository) + .switch(Image) + .join(ImageStorage, JOIN_LEFT_OUTER) + .where(Repository.name == repository_name, + Repository.namespace == namespace_name, + Image.docker_image_id == docker_image_id) + .get()) - if not image_list: + except Image.DoesNotExist: raise DataModelException('No image with specified id and repository') - fetched = image_list[0] - fetched.image_size = image_size - fetched.save() - return fetched + if image.storage: + image.storage.image_size = image_size + image.storage.save() + else: + image.image_size = image_size + image.save() + + return image def set_image_metadata(docker_image_id, namespace_name, repository_name, created_date_str, comment, command, parent=None): - joined = Image.select().join(Repository) - image_list = list(joined.where(Repository.name == repository_name, - Repository.namespace == namespace_name, - Image.docker_image_id == docker_image_id)) + with db.transaction(): + query = (Image + .select(Image, ImageStorage) + .join(Repository) + .switch(Image) + .join(ImageStorage) + .where(Repository.name == repository_name, + Repository.namespace == namespace_name, + Image.docker_image_id == docker_image_id)) - if not image_list: - raise DataModelException('No image with specified id and repository') + try: + fetched = query.get() + except Image.DoesNotExist: + raise DataModelException('No image with specified id and repository') - fetched = image_list[0] - fetched.created = dateutil.parser.parse(created_date_str) - fetched.comment = comment - fetched.command = command + fetched.storage.created = dateutil.parser.parse(created_date_str) + fetched.storage.comment = comment + fetched.storage.command = command - if parent: - fetched.ancestors = '%s%s/' % (parent.ancestors, parent.id) + if parent: + fetched.ancestors = '%s%s/' % (parent.ancestors, parent.id) - fetched.save() - return fetched + fetched.save() + fetched.storage.save() + return fetched def get_repository_images(namespace_name, repository_name): - joined = Image.select().join(Repository) - return joined.where(Repository.name == repository_name, - Repository.namespace == namespace_name) + return (Image + .select(Image, ImageStorage) + .join(Repository) + .switch(Image) + .join(ImageStorage, JOIN_LEFT_OUTER) + .where(Repository.name == repository_name, + Repository.namespace == namespace_name)) def list_repository_tags(namespace_name, repository_name): @@ -933,111 +978,97 @@ def list_repository_tags(namespace_name, repository_name): return with_image.where(Repository.name == repository_name, Repository.namespace == namespace_name) -def delete_tag_and_images(namespace_name, repository_name, tag_name): - all_images = get_repository_images(namespace_name, repository_name) - all_tags = list_repository_tags(namespace_name, repository_name) - - # Find the tag's information. - found_tag = None - for tag in all_tags: - if tag.name == tag_name: - found_tag = tag - break - - if not found_tag: - return - - # Build the set of database IDs corresponding to the tag's ancestor images, - # as well as the tag's image itself. - tag_image_ids = set(found_tag.image.ancestors.split('/')) - tag_image_ids.add(str(found_tag.image.id)) - - # Filter out any images that belong to any other tags. - for tag in all_tags: - if tag.name != tag_name: - # Remove all ancestors of the tag. - tag_image_ids = tag_image_ids - set(tag.image.ancestors.split('/')) - - # Remove the current image ID. - tag_image_ids.discard(str(tag.image.id)) - - # Find all the images that belong to the tag. - tag_images = [image for image in all_images - if str(image.id) in tag_image_ids] - - # Delete the tag found. - found_tag.delete_instance() - - # Delete the images found. - for image in tag_images: - image.delete_instance() - - repository_path = store.image_path(namespace_name, repository_name, - image.docker_image_id) - logger.debug('Recursively deleting image path: %s' % repository_path) - store.remove(repository_path) - def garbage_collect_repository(namespace_name, repository_name): - # Get a list of all images used by tags in the repository - tag_query = (RepositoryTag - .select(RepositoryTag, Image) - .join(Image) - .switch(RepositoryTag) - .join(Repository) - .where(Repository.name == repository_name, - Repository.namespace == namespace_name)) + with db.transaction(): + # Get a list of all images used by tags in the repository + tag_query = (RepositoryTag + .select(RepositoryTag, Image, ImageStorage) + .join(Image) + .join(ImageStorage, JOIN_LEFT_OUTER) + .switch(RepositoryTag) + .join(Repository) + .where(Repository.name == repository_name, + Repository.namespace == namespace_name)) - referenced_anscestors = set() - for tag in tag_query: - # The anscestor list is in the format '/1/2/3/', extract just the ids - anscestor_id_strings = tag.image.ancestors.split('/')[1:-1] - ancestor_list = [int(img_id_str) for img_id_str in anscestor_id_strings] - referenced_anscestors = referenced_anscestors.union(set(ancestor_list)) - referenced_anscestors.add(tag.image.id) + referenced_anscestors = set() + for tag in tag_query: + # The anscestor list is in the format '/1/2/3/', extract just the ids + anscestor_id_strings = tag.image.ancestors.split('/')[1:-1] + ancestor_list = [int(img_id_str) for img_id_str in anscestor_id_strings] + referenced_anscestors = referenced_anscestors.union(set(ancestor_list)) + referenced_anscestors.add(tag.image.id) - all_repo_images = get_repository_images(namespace_name, repository_name) - all_images = {int(img.id):img for img in all_repo_images} - to_remove = set(all_images.keys()).difference(referenced_anscestors) + all_repo_images = get_repository_images(namespace_name, repository_name) + all_images = {int(img.id): img for img in all_repo_images} + to_remove = set(all_images.keys()).difference(referenced_anscestors) - logger.info('Cleaning up unreferenced images: %s', to_remove) + logger.info('Cleaning up unreferenced images: %s', to_remove) - for image_id_to_remove in to_remove: - image_to_remove = all_images[image_id_to_remove] - image_path = store.image_path(namespace_name, repository_name, - image_to_remove.docker_image_id) - image_to_remove.delete_instance() - logger.debug('Deleting image storage: %s' % image_path) - store.remove(image_path) + uuids_to_check_for_gc = set() + for image_id_to_remove in to_remove: + image_to_remove = all_images[image_id_to_remove] + image_to_remove.delete_instance() + + if not image_to_remove.storage: + image_path = store.image_path(namespace_name, repository_name, + image_to_remove.docker_image_id, None) + logger.debug('Deleting image storage: %s', image_path) + else: + uuids_to_check_for_gc.add(image_to_remove.storage.uuid) + + storage_to_remove = (ImageStorage + .select() + .join(Image, JOIN_LEFT_OUTER) + .group_by(ImageStorage) + .where(ImageStorage.uuid << list(uuids_to_check_for_gc)) + .having(fn.Count(Image.id) == 0)) + + for storage in storage_to_remove: + logger.debug('Garbage collecting image storage: %s', storage.uuid) + storage.delete_instance() + image_path = store.image_path(namespace_name, repository_name, + image_to_remove.docker_image_id, + storage.uuid) + store.remove(image_path) return len(to_remove) def get_tag_image(namespace_name, repository_name, tag_name): - joined = Image.select().join(RepositoryTag).join(Repository) - fetched = list(joined.where(Repository.name == repository_name, - Repository.namespace == namespace_name, - RepositoryTag.name == tag_name)) + query = (Image + .select(Image, ImageStorage) + .join(RepositoryTag) + .join(Repository) + .switch(Image) + .join(ImageStorage, JOIN_LEFT_OUTER) + .where(Repository.name == repository_name, + Repository.namespace == namespace_name, + RepositoryTag.name == tag_name)) - if not fetched: + try: + return query.get() + except Image.DoesNotExist: raise DataModelException('Unable to find image for tag.') - return fetched[0] - def get_image_by_id(namespace_name, repository_name, docker_image_id): - joined = Image.select().join(Repository) - fetched = list(joined.where(Repository.name == repository_name, - Repository.namespace == namespace_name, - Image.docker_image_id == docker_image_id)) + query = (Image + .select(Image, ImageStorage) + .join(Repository) + .switch(Image) + .join(ImageStorage, JOIN_LEFT_OUTER) + .where(Repository.name == repository_name, + Repository.namespace == namespace_name, + Image.docker_image_id == docker_image_id)) - if not fetched: + try: + return query.get() + except Image.DoesNotExist: raise DataModelException('Unable to find image \'%s\' for repo \'%s/%s\'' % (docker_image_id, namespace_name, repository_name)) - return fetched[0] - def get_parent_images(image_obj): """ Returns a list of parent Image objects in chronilogical order. """ @@ -1047,8 +1078,11 @@ def get_parent_images(image_obj): if parent_db_ids == ['']: return [] - or_clauses = [(Image.id == db_id) for db_id in parent_db_ids] - parent_images = Image.select().where(reduce(operator.or_, or_clauses)) + parent_images = (Image + .select(Image, ImageStorage) + .join(ImageStorage, JOIN_LEFT_OUTER) + .where(Image.id << parent_db_ids)) + id_to_image = {unicode(image.id): image for image in parent_images} return [id_to_image[parent_id] for parent_id in parent_db_ids] @@ -1206,15 +1240,17 @@ def set_team_repo_permission(team_name, namespace_name, repository_name, def purge_repository(namespace_name, repository_name): + # Delete all tags to allow gc to reclaim storage + delete_all_repository_tags(namespace_name, repository_name) + + # Gc to remove the images and storage + garbage_collect_repository(namespace_name, repository_name) + + # Delete the rest of the repository metadata fetched = Repository.get(Repository.name == repository_name, Repository.namespace == namespace_name) fetched.delete_instance(recursive=True) - repository_path = store.repository_namespace_path(namespace_name, - repository_name) - logger.debug('Recursively deleting path: %s' % repository_path) - store.remove(repository_path) - def get_private_repo_count(username): joined = Repository.select().join(Visibility) diff --git a/endpoints/api.py b/endpoints/api.py index 4372c9774..1e694e1b0 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -1012,7 +1012,6 @@ def list_repos(): if include_count: repo_count = model.get_visible_repository_count(username, include_public=include_public, - sort=sort, namespace=namespace_filter) repo_query = model.get_visible_repositories(username, limit=limit, page=page, @@ -1089,14 +1088,16 @@ def delete_repository(namespace, repository): def image_view(image): + extended_props = image.storage or image + command = extended_props.command return { 'id': image.docker_image_id, - 'created': image.created, - 'comment': image.comment, - 'command': json.loads(image.command) if image.command else None, + 'created': extended_props.created, + 'comment': extended_props.comment, + 'command': json.loads(command) if command else None, 'ancestors': image.ancestors, 'dbid': image.id, - 'size': image.image_size, + 'size': extended_props.image_size, } @@ -1399,7 +1400,14 @@ def get_image(namespace, repository, image_id): def get_image_changes(namespace, repository, image_id): permission = ReadRepositoryPermission(namespace, repository) if permission.can() or model.repository_is_public(namespace, repository): - diffs_path = store.image_file_diffs_path(namespace, repository, image_id) + image = model.get_repo_image(namespace, repository, image_id) + + if not image: + abort(404) + + uuid = image.storage and image.storage.uuid + diffs_path = store.image_file_diffs_path(namespace, repository, image_id, + uuid) try: response_json = store.get_content(diffs_path) @@ -1416,7 +1424,8 @@ def get_image_changes(namespace, repository, image_id): def delete_full_tag(namespace, repository, tag): permission = AdministerRepositoryPermission(namespace, repository) if permission.can(): - model.delete_tag_and_images(namespace, repository, tag) + model.delete_tag(namespace, repository, tag) + model.garbage_collect_repository(namespace, repository) username = current_user.db_user().username log_action('delete_tag', namespace, diff --git a/endpoints/index.py b/endpoints/index.py index 5106873cb..4af671849 100644 --- a/endpoints/index.py +++ b/endpoints/index.py @@ -33,6 +33,11 @@ def generate_headers(role='read'): session['namespace'] = namespace session['repository'] = repository + if get_authenticated_user(): + session['username'] = get_authenticated_user().username + else: + session.pop('username', None) + # We run our index and registry on the same hosts for now registry_server = urlparse.urlparse(request.url).netloc response.headers['X-Docker-Endpoints'] = registry_server @@ -179,8 +184,9 @@ def create_repository(namespace, repository): if existing.docker_image_id in new_repo_images: added_images.pop(existing.docker_image_id) + username = get_authenticated_user() and get_authenticated_user().username for image_description in added_images.values(): - model.create_image(image_description['id'], repo) + model.create_or_link_image(image_description['id'], repo, username) response = make_response('Created', 201) diff --git a/endpoints/registry.py b/endpoints/registry.py index 1446238ca..9727d5ccb 100644 --- a/endpoints/registry.py +++ b/endpoints/registry.py @@ -44,8 +44,12 @@ def require_completion(f): """This make sure that the image push correctly finished.""" @wraps(f) def wrapper(namespace, repository, *args, **kwargs): - if store.exists(store.image_mark_path(namespace, repository, - kwargs['image_id'])): + image_id = kwargs['image_id'] + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + + if store.exists(store.image_mark_path(namespace, repository, image_id, + uuid)): abort(400, 'Image %(image_id)s is being uploaded, retry later', issue='upload-in-progress', image_id=kwargs['image_id']) @@ -85,14 +89,18 @@ def set_cache_headers(f): def get_image_layer(namespace, repository, image_id, headers): permission = ReadRepositoryPermission(namespace, repository) if permission.can() or model.repository_is_public(namespace, repository): - path = store.image_layer_path(namespace, repository, image_id) + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + + path = store.image_layer_path(namespace, repository, image_id, uuid) direct_download_url = store.get_direct_download_url(path) if direct_download_url: return redirect(direct_download_url) try: return Response(store.stream_read(path), headers=headers) except IOError: - abort(404, 'Image %(image_id)s not found', issue='unknown-image', image_id=image_id) + abort(404, 'Image %(image_id)s not found', issue='unknown-image', + image_id=image_id) abort(403) @@ -105,14 +113,17 @@ def put_image_layer(namespace, repository, image_id): if not permission.can(): abort(403) + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid try: json_data = store.get_content(store.image_json_path(namespace, repository, - image_id)) + image_id, uuid)) except IOError: - abort(404, 'Image %(image_id)s not found', issue='unknown-image', image_id=image_id) + abort(404, 'Image %(image_id)s not found', issue='unknown-image', + image_id=image_id) - layer_path = store.image_layer_path(namespace, repository, image_id) - mark_path = store.image_mark_path(namespace, repository, image_id) + layer_path = store.image_layer_path(namespace, repository, image_id, uuid) + mark_path = store.image_mark_path(namespace, repository, image_id, uuid) if store.exists(layer_path) and not store.exists(mark_path): abort(409, 'Image already exists', issue='image-exists', image_id=image_id) @@ -149,7 +160,7 @@ def put_image_layer(namespace, repository, image_id): try: checksum = store.get_content(store.image_checksum_path(namespace, repository, - image_id)) + image_id, uuid)) except IOError: # We don't have a checksum stored yet, that's fine skipping the check. # Not removing the mark though, image is not downloadable yet. @@ -193,15 +204,18 @@ def put_image_checksum(namespace, repository, image_id): abort(400, 'Checksum not found in Cookie for image %(imaage_id)s', issue='missing-checksum-cookie', image_id=image_id) - if not store.exists(store.image_json_path(namespace, repository, image_id)): + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + if not store.exists(store.image_json_path(namespace, repository, image_id, + uuid)): abort(404, 'Image not found: %(image_id)s', issue='unknown-image', image_id=image_id) - mark_path = store.image_mark_path(namespace, repository, image_id) + mark_path = store.image_mark_path(namespace, repository, image_id, uuid) if not store.exists(mark_path): abort(409, 'Cannot set checksum for image %(image_id)s', issue='image-write-error', image_id=image_id) - err = store_checksum(namespace, repository, image_id, checksum) + err = store_checksum(namespace, repository, image_id, uuid, checksum) if err: abort(400, err) @@ -238,20 +252,24 @@ def get_image_json(namespace, repository, image_id, headers): repository): abort(403) + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + try: data = store.get_content(store.image_json_path(namespace, repository, - image_id)) + image_id, uuid)) except IOError: flask_abort(404) try: size = store.get_size(store.image_layer_path(namespace, repository, - image_id)) + image_id, uuid)) headers['X-Docker-Size'] = str(size) except OSError: pass - checksum_path = store.image_checksum_path(namespace, repository, image_id) + checksum_path = store.image_checksum_path(namespace, repository, image_id, + uuid) if store.exists(checksum_path): headers['X-Docker-Checksum'] = store.get_content(checksum_path) @@ -271,39 +289,45 @@ def get_image_ancestry(namespace, repository, image_id, headers): repository): abort(403) + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + try: data = store.get_content(store.image_ancestry_path(namespace, repository, - image_id)) + image_id, uuid)) except IOError: - abort(404, 'Image %(image_id)s not found', issue='unknown-image', image_id=image_id) + abort(404, 'Image %(image_id)s not found', issue='unknown-image', + image_id=image_id) response = make_response(json.dumps(json.loads(data)), 200) response.headers.extend(headers) return response -def generate_ancestry(namespace, repository, image_id, parent_id=None): +def generate_ancestry(namespace, repository, image_id, uuid, parent_id=None, + parent_uuid=None): if not parent_id: store.put_content(store.image_ancestry_path(namespace, repository, - image_id), + image_id, uuid), json.dumps([image_id])) return data = store.get_content(store.image_ancestry_path(namespace, repository, - parent_id)) + parent_id, parent_uuid)) data = json.loads(data) data.insert(0, image_id) store.put_content(store.image_ancestry_path(namespace, repository, - image_id), + image_id, uuid), json.dumps(data)) -def store_checksum(namespace, repository, image_id, checksum): +def store_checksum(namespace, repository, image_id, uuid, checksum): checksum_parts = checksum.split(':') if len(checksum_parts) != 2: return 'Invalid checksum format' # We store the checksum - checksum_path = store.image_checksum_path(namespace, repository, image_id) + checksum_path = store.image_checksum_path(namespace, repository, image_id, + uuid) store.put_content(checksum_path, checksum) @@ -327,58 +351,69 @@ def put_image_json(namespace, repository, image_id): abort(400, 'Missing key `id` in JSON for image: %(image_id)s', issue='invalid-request', image_id=image_id) + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + # Read the checksum checksum = request.headers.get('X-Docker-Checksum') if checksum: # Storing the checksum is optional at this stage - err = store_checksum(namespace, repository, image_id, checksum) + err = store_checksum(namespace, repository, image_id, uuid, checksum) if err: abort(400, err, issue='write-error') else: # We cleanup any old checksum in case it's a retry after a fail - store.remove(store.image_checksum_path(namespace, repository, image_id)) + store.remove(store.image_checksum_path(namespace, repository, image_id, + uuid)) if image_id != data['id']: abort(400, 'JSON data contains invalid id for image: %(image_id)s', issue='invalid-request', image_id=image_id) parent_id = data.get('parent') + + parent_image = None + if parent_id: + parent_image = model.get_repo_image(namespace, repository, parent_id) + parent_uuid = (parent_image and parent_image.storage and + parent_image.storage.uuid) + if (parent_id and not - store.exists(store.image_json_path(namespace, repository, parent_id))): + store.exists(store.image_json_path(namespace, repository, parent_id, + parent_uuid))): abort(400, 'Image %(image_id)s depends on non existing parent image %(parent_id)s', issue='invalid-request', image_id=image_id, parent_id=parent_id) - json_path = store.image_json_path(namespace, repository, image_id) - mark_path = store.image_mark_path(namespace, repository, image_id) + json_path = store.image_json_path(namespace, repository, image_id, uuid) + mark_path = store.image_mark_path(namespace, repository, image_id, uuid) if store.exists(json_path) and not store.exists(mark_path): abort(409, 'Image already exists', issue='image-exists', image_id=image_id) # If we reach that point, it means that this is a new image or a retry # on a failed push # save the metadata - if parent_id: - parent_obj = model.get_image_by_id(namespace, repository, parent_id) - else: - parent_obj = None - command_list = data.get('container_config', {}).get('Cmd', None) command = json.dumps(command_list) if command_list else None model.set_image_metadata(image_id, namespace, repository, data.get('created'), data.get('comment'), command, - parent_obj) + parent_image) store.put_content(mark_path, 'true') store.put_content(json_path, request.data) - generate_ancestry(namespace, repository, image_id, parent_id) + generate_ancestry(namespace, repository, image_id, uuid, parent_id, + parent_uuid) return make_response('true', 200) def process_image_changes(namespace, repository, image_id): logger.debug('Generating diffs for image: %s' % image_id) + repo_image = model.get_repo_image(namespace, repository, image_id) + uuid = repo_image and repo_image.storage and repo_image.storage.uuid + image_diffs_path = store.image_file_diffs_path(namespace, repository, - image_id) + image_id, uuid) image_trie_path = store.image_file_trie_path(namespace, repository, - image_id) + image_id, uuid) if store.exists(image_diffs_path): logger.debug('Diffs already exist for image: %s' % image_id) @@ -400,7 +435,7 @@ def process_image_changes(namespace, repository, image_id): parent_trie.frombytes(parent_trie_bytes) # Read in the file entries from the layer tar file - layer_path = store.image_layer_path(namespace, repository, image_id) + layer_path = store.image_layer_path(namespace, repository, image_id, uuid) with store.stream_read_file(layer_path) as layer_tar_stream: removed_files = set() layer_files = changes.files_and_dirs_from_tar(layer_tar_stream, diff --git a/initdb.py b/initdb.py index cb29d5246..03cabb999 100644 --- a/initdb.py +++ b/initdb.py @@ -43,7 +43,7 @@ def __gen_image_id(repo, image_num): global_image_num = [0] -def __create_subtree(repo, structure, parent): +def __create_subtree(repo, structure, creator_username, parent): num_nodes, subtrees, last_node_tags = structure # create the nodes @@ -54,7 +54,7 @@ def __create_subtree(repo, structure, parent): logger.debug('new docker id: %s' % docker_image_id) checksum = __gen_checksum(docker_image_id) - new_image = model.create_image(docker_image_id, repo) + new_image = model.create_or_link_image(docker_image_id, repo, None) model.set_image_checksum(docker_image_id, repo, checksum) creation_time = REFERENCE_DATE + timedelta(days=image_num) @@ -69,7 +69,8 @@ def __create_subtree(repo, structure, parent): # Populate the diff file diff_path = store.image_file_diffs_path(repo.namespace, repo.name, - docker_image_id) + docker_image_id, + new_image.storage.uuid) source_diff = SAMPLE_DIFFS[image_num % len(SAMPLE_DIFFS)] with open(source_diff, 'r') as source_file: @@ -86,7 +87,7 @@ def __create_subtree(repo, structure, parent): new_image.docker_image_id) for subtree in subtrees: - __create_subtree(repo, subtree, new_image) + __create_subtree(repo, subtree, creator_username, new_image) def __generate_repository(user, name, description, is_public, permissions, @@ -106,9 +107,9 @@ def __generate_repository(user, name, description, is_public, permissions, if isinstance(structure, list): for s in structure: - __create_subtree(repo, s, None) + __create_subtree(repo, s, user.username, None) else: - __create_subtree(repo, structure, None) + __create_subtree(repo, structure, user.username, None) return repo diff --git a/storage/basestorage.py b/storage/basestorage.py index 474e53894..a89e3cb72 100644 --- a/storage/basestorage.py +++ b/storage/basestorage.py @@ -56,9 +56,6 @@ class Storage(object): base_path = self.image_path(namespace, repository, image_id, storage_uuid) return '{0}/ancestry'.format(base_path) - def repository_namespace_path(self, namespace, repository): - return '{0}/{1}/{2}/'.format(self.images, namespace, repository) - def image_file_trie_path(self, namespace, repository, image_id, storage_uuid): base_path = self.image_path(namespace, repository, image_id, storage_uuid) diff --git a/test/data/registry/images/devtable/complex/c3d710edbd3be254a2bfe7e27a7f47fdc3d710edbd3be254a2bfe7e27a7f47fd/diffs.json b/test/data/registry/sharedimages/01ca8e73-1961-40d9-bf1f-96cb90564c0b/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/c3d710edbd3be254a2bfe7e27a7f47fdc3d710edbd3be254a2bfe7e27a7f47fd/diffs.json rename to test/data/registry/sharedimages/01ca8e73-1961-40d9-bf1f-96cb90564c0b/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/14c839f5acd4b9ed0929c60f6ad8b6ec14c839f5acd4b9ed0929c60f6ad8b6ec/diffs.json b/test/data/registry/sharedimages/0e778f76-42fb-4d77-a538-03f3a323fcd2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/14c839f5acd4b9ed0929c60f6ad8b6ec14c839f5acd4b9ed0929c60f6ad8b6ec/diffs.json rename to test/data/registry/sharedimages/0e778f76-42fb-4d77-a538-03f3a323fcd2/diffs.json diff --git a/test/data/registry/images/devtable/complex/24aadc03801e2ca87ba34337b7df1df324aadc03801e2ca87ba34337b7df1df3/diffs.json b/test/data/registry/sharedimages/0f16ed5a-59d3-4b59-953d-c441dc6d77d2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/24aadc03801e2ca87ba34337b7df1df324aadc03801e2ca87ba34337b7df1df3/diffs.json rename to test/data/registry/sharedimages/0f16ed5a-59d3-4b59-953d-c441dc6d77d2/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/25f3f74ae1cdb37cd5e7fbf4b29f42d825f3f74ae1cdb37cd5e7fbf4b29f42d8/diffs.json b/test/data/registry/sharedimages/10d8eae0-28f6-45ce-b103-53cc2f59b674/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/25f3f74ae1cdb37cd5e7fbf4b29f42d825f3f74ae1cdb37cd5e7fbf4b29f42d8/diffs.json rename to test/data/registry/sharedimages/10d8eae0-28f6-45ce-b103-53cc2f59b674/diffs.json diff --git a/test/data/registry/images/devtable/complex/d3acf10ce5ad8b208ba38e626ced2946d3acf10ce5ad8b208ba38e626ced2946/diffs.json b/test/data/registry/sharedimages/1508e485-e94f-4154-87c1-53a147ff2c21/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/d3acf10ce5ad8b208ba38e626ced2946d3acf10ce5ad8b208ba38e626ced2946/diffs.json rename to test/data/registry/sharedimages/1508e485-e94f-4154-87c1-53a147ff2c21/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/0ccb6d859cbdf08f5c71132707e144fc0ccb6d859cbdf08f5c71132707e144fc/diffs.json b/test/data/registry/sharedimages/16b2c776-20b0-426d-81c8-53abe0026706/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/0ccb6d859cbdf08f5c71132707e144fc0ccb6d859cbdf08f5c71132707e144fc/diffs.json rename to test/data/registry/sharedimages/16b2c776-20b0-426d-81c8-53abe0026706/diffs.json diff --git a/test/data/registry/images/buynlarge/orgrepo/5159d2eda87bc26f91e9b7bd0ce73f695159d2eda87bc26f91e9b7bd0ce73f69/diffs.json b/test/data/registry/sharedimages/17197704-0e3f-4829-99f2-e246787661a8/diffs.json similarity index 100% rename from test/data/registry/images/buynlarge/orgrepo/5159d2eda87bc26f91e9b7bd0ce73f695159d2eda87bc26f91e9b7bd0ce73f69/diffs.json rename to test/data/registry/sharedimages/17197704-0e3f-4829-99f2-e246787661a8/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/2561f1d3a276103635c2cde5a7dc77592561f1d3a276103635c2cde5a7dc7759/diffs.json b/test/data/registry/sharedimages/2929a979-08c3-44bf-8471-c2bda1ee55ac/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/2561f1d3a276103635c2cde5a7dc77592561f1d3a276103635c2cde5a7dc7759/diffs.json rename to test/data/registry/sharedimages/2929a979-08c3-44bf-8471-c2bda1ee55ac/diffs.json diff --git a/test/data/registry/images/devtable/complex/a4efbdc85fca8ab9db85bf6cbd54b154a4efbdc85fca8ab9db85bf6cbd54b154/diffs.json b/test/data/registry/sharedimages/2b11f03d-719c-4a5f-a8fb-f5573ecda5ca/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/a4efbdc85fca8ab9db85bf6cbd54b154a4efbdc85fca8ab9db85bf6cbd54b154/diffs.json rename to test/data/registry/sharedimages/2b11f03d-719c-4a5f-a8fb-f5573ecda5ca/diffs.json diff --git a/test/data/registry/images/devtable/complex/5762f8352fb68b3baf43cee20946da815762f8352fb68b3baf43cee20946da81/diffs.json b/test/data/registry/sharedimages/2ddcc4ed-0a3f-400b-861c-b16f61e3d54e/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/5762f8352fb68b3baf43cee20946da815762f8352fb68b3baf43cee20946da81/diffs.json rename to test/data/registry/sharedimages/2ddcc4ed-0a3f-400b-861c-b16f61e3d54e/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/22d54e9c626a2aa258e5185dc315d5a022d54e9c626a2aa258e5185dc315d5a0/diffs.json b/test/data/registry/sharedimages/305f4299-676e-4a2e-953a-cd299bb1a4c0/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/22d54e9c626a2aa258e5185dc315d5a022d54e9c626a2aa258e5185dc315d5a0/diffs.json rename to test/data/registry/sharedimages/305f4299-676e-4a2e-953a-cd299bb1a4c0/diffs.json diff --git a/test/data/registry/images/devtable/complex/bfbba189913c9454c3e26b62b91bb906bfbba189913c9454c3e26b62b91bb906/diffs.json b/test/data/registry/sharedimages/3408fccf-3d90-4e05-9d6e-5cbbd459330a/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/bfbba189913c9454c3e26b62b91bb906bfbba189913c9454c3e26b62b91bb906/diffs.json rename to test/data/registry/sharedimages/3408fccf-3d90-4e05-9d6e-5cbbd459330a/diffs.json diff --git a/test/data/registry/images/buynlarge/orgrepo/0abe0a670562d152243c92280507c7e00abe0a670562d152243c92280507c7e0/diffs.json b/test/data/registry/sharedimages/353bd7fe-246a-43b5-a978-7da35c23f6ad/diffs.json similarity index 100% rename from test/data/registry/images/buynlarge/orgrepo/0abe0a670562d152243c92280507c7e00abe0a670562d152243c92280507c7e0/diffs.json rename to test/data/registry/sharedimages/353bd7fe-246a-43b5-a978-7da35c23f6ad/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/1f9c4e12e13735668f2f2b5ebed92a271f9c4e12e13735668f2f2b5ebed92a27/diffs.json b/test/data/registry/sharedimages/358d33f4-63ff-4767-95a8-3d524d685bce/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/1f9c4e12e13735668f2f2b5ebed92a271f9c4e12e13735668f2f2b5ebed92a27/diffs.json rename to test/data/registry/sharedimages/358d33f4-63ff-4767-95a8-3d524d685bce/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/425c8ea110720bca7fd14e57a59921d8425c8ea110720bca7fd14e57a59921d8/diffs.json b/test/data/registry/sharedimages/3825fa0f-5918-4da4-b56c-921f8e88d3f0/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/425c8ea110720bca7fd14e57a59921d8425c8ea110720bca7fd14e57a59921d8/diffs.json rename to test/data/registry/sharedimages/3825fa0f-5918-4da4-b56c-921f8e88d3f0/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/215cde86f7910181c2b480eddacc55f6215cde86f7910181c2b480eddacc55f6/diffs.json b/test/data/registry/sharedimages/3dc8dc91-b7c6-41d8-a74f-ab7d6d949ec0/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/215cde86f7910181c2b480eddacc55f6215cde86f7910181c2b480eddacc55f6/diffs.json rename to test/data/registry/sharedimages/3dc8dc91-b7c6-41d8-a74f-ab7d6d949ec0/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/e072d8d21d7dd0b73004258dbabc038de072d8d21d7dd0b73004258dbabc038d/diffs.json b/test/data/registry/sharedimages/3ea3578c-f04b-4804-8bbf-821c3f1d6d18/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/e072d8d21d7dd0b73004258dbabc038de072d8d21d7dd0b73004258dbabc038d/diffs.json rename to test/data/registry/sharedimages/3ea3578c-f04b-4804-8bbf-821c3f1d6d18/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/43839fc1f7d7167236871fac6b0bc26043839fc1f7d7167236871fac6b0bc260/diffs.json b/test/data/registry/sharedimages/4d2e5054-bfc3-4b4f-8135-4f03b5e69b53/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/43839fc1f7d7167236871fac6b0bc26043839fc1f7d7167236871fac6b0bc260/diffs.json rename to test/data/registry/sharedimages/4d2e5054-bfc3-4b4f-8135-4f03b5e69b53/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/b4edeedb5eb9a0322f224452b69bd545b4edeedb5eb9a0322f224452b69bd545/diffs.json b/test/data/registry/sharedimages/4de57937-8f5f-44ff-80b8-387eb4ffb469/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/b4edeedb5eb9a0322f224452b69bd545b4edeedb5eb9a0322f224452b69bd545/diffs.json rename to test/data/registry/sharedimages/4de57937-8f5f-44ff-80b8-387eb4ffb469/diffs.json diff --git a/test/data/registry/images/buynlarge/orgrepo/a99fd6afd29cd0ed2d6eb03f4ef8c3aca99fd6afd29cd0ed2d6eb03f4ef8c3ac/diffs.json b/test/data/registry/sharedimages/4f16ecc7-c2bc-427c-9894-28cb50ff04e1/diffs.json similarity index 100% rename from test/data/registry/images/buynlarge/orgrepo/a99fd6afd29cd0ed2d6eb03f4ef8c3aca99fd6afd29cd0ed2d6eb03f4ef8c3ac/diffs.json rename to test/data/registry/sharedimages/4f16ecc7-c2bc-427c-9894-28cb50ff04e1/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/1dcf485dfbdf2ee735d39f74d4ec91321dcf485dfbdf2ee735d39f74d4ec9132/diffs.json b/test/data/registry/sharedimages/5012c7dd-524a-4125-affc-c2b424a7f011/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/1dcf485dfbdf2ee735d39f74d4ec91321dcf485dfbdf2ee735d39f74d4ec9132/diffs.json rename to test/data/registry/sharedimages/5012c7dd-524a-4125-affc-c2b424a7f011/diffs.json diff --git a/test/data/registry/images/devtable/complex/333b7df80772c6336de9b3fc595649e6333b7df80772c6336de9b3fc595649e6/diffs.json b/test/data/registry/sharedimages/5072be66-6816-4f5e-a597-bd981d864768/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/333b7df80772c6336de9b3fc595649e6333b7df80772c6336de9b3fc595649e6/diffs.json rename to test/data/registry/sharedimages/5072be66-6816-4f5e-a597-bd981d864768/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/5feb1289afba113e86027d8e1221ebd15feb1289afba113e86027d8e1221ebd1/diffs.json b/test/data/registry/sharedimages/50780ff3-75cc-4ad3-a762-5336892b1bd8/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/5feb1289afba113e86027d8e1221ebd15feb1289afba113e86027d8e1221ebd1/diffs.json rename to test/data/registry/sharedimages/50780ff3-75cc-4ad3-a762-5336892b1bd8/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/850c91f203b9eb1b83b3d2097f9a0c29850c91f203b9eb1b83b3d2097f9a0c29/diffs.json b/test/data/registry/sharedimages/51817c4b-997b-4afe-925a-99f84876e0b1/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/850c91f203b9eb1b83b3d2097f9a0c29850c91f203b9eb1b83b3d2097f9a0c29/diffs.json rename to test/data/registry/sharedimages/51817c4b-997b-4afe-925a-99f84876e0b1/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/47f6628f60a012e10865362cfaf3625a47f6628f60a012e10865362cfaf3625a/diffs.json b/test/data/registry/sharedimages/52e82877-fd84-4202-bacb-88df0e7d0da6/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/47f6628f60a012e10865362cfaf3625a47f6628f60a012e10865362cfaf3625a/diffs.json rename to test/data/registry/sharedimages/52e82877-fd84-4202-bacb-88df0e7d0da6/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/a742734a834f9049c373316825e6ab8ea742734a834f9049c373316825e6ab8e/diffs.json b/test/data/registry/sharedimages/532ac01a-d62d-4b8f-8e73-a6bee7a24455/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/a742734a834f9049c373316825e6ab8ea742734a834f9049c373316825e6ab8e/diffs.json rename to test/data/registry/sharedimages/532ac01a-d62d-4b8f-8e73-a6bee7a24455/diffs.json diff --git a/test/data/registry/images/devtable/shared/fb820a41a1b0f94cf779305c2e23d4d1fb820a41a1b0f94cf779305c2e23d4d1/diffs.json b/test/data/registry/sharedimages/53796278-cce8-4e4d-9ba3-c911f9f1fd81/diffs.json similarity index 100% rename from test/data/registry/images/devtable/shared/fb820a41a1b0f94cf779305c2e23d4d1fb820a41a1b0f94cf779305c2e23d4d1/diffs.json rename to test/data/registry/sharedimages/53796278-cce8-4e4d-9ba3-c911f9f1fd81/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/6474104fec6385f173ee7cc4346ba1716474104fec6385f173ee7cc4346ba171/diffs.json b/test/data/registry/sharedimages/5707dbfe-09e1-450b-89e5-284a96d640d1/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/6474104fec6385f173ee7cc4346ba1716474104fec6385f173ee7cc4346ba171/diffs.json rename to test/data/registry/sharedimages/5707dbfe-09e1-450b-89e5-284a96d640d1/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/5c0b2f2fede746349355d608b07904735c0b2f2fede746349355d608b0790473/diffs.json b/test/data/registry/sharedimages/57a9a644-ff7c-4578-9f1e-d39e17e86e50/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/5c0b2f2fede746349355d608b07904735c0b2f2fede746349355d608b0790473/diffs.json rename to test/data/registry/sharedimages/57a9a644-ff7c-4578-9f1e-d39e17e86e50/diffs.json diff --git a/test/data/registry/images/devtable/superwide/0e621287d1eb7c094af178a9c54ef5f10e621287d1eb7c094af178a9c54ef5f1/diffs.json b/test/data/registry/sharedimages/588a6ca4-9403-4f28-a1c2-9807c70cad7e/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/0e621287d1eb7c094af178a9c54ef5f10e621287d1eb7c094af178a9c54ef5f1/diffs.json rename to test/data/registry/sharedimages/588a6ca4-9403-4f28-a1c2-9807c70cad7e/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/b2a795ca9198e911c359f2b90e75973db2a795ca9198e911c359f2b90e75973d/diffs.json b/test/data/registry/sharedimages/59bd87db-6c0d-4fe0-b6c3-c4b5fa966c64/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/b2a795ca9198e911c359f2b90e75973db2a795ca9198e911c359f2b90e75973d/diffs.json rename to test/data/registry/sharedimages/59bd87db-6c0d-4fe0-b6c3-c4b5fa966c64/diffs.json diff --git a/test/data/registry/images/buynlarge/orgrepo/ec0dd7fc4e4c5cf34b2a24dc03ed74b9ec0dd7fc4e4c5cf34b2a24dc03ed74b9/diffs.json b/test/data/registry/sharedimages/5a380fa9-72b6-4ca4-bf12-e3ba606f439d/diffs.json similarity index 100% rename from test/data/registry/images/buynlarge/orgrepo/ec0dd7fc4e4c5cf34b2a24dc03ed74b9ec0dd7fc4e4c5cf34b2a24dc03ed74b9/diffs.json rename to test/data/registry/sharedimages/5a380fa9-72b6-4ca4-bf12-e3ba606f439d/diffs.json diff --git a/test/data/registry/images/devtable/complex/85f3f40271af0a032ec07aec57eedf9185f3f40271af0a032ec07aec57eedf91/diffs.json b/test/data/registry/sharedimages/5b07deb6-4319-437c-867f-19de0a2a789e/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/85f3f40271af0a032ec07aec57eedf9185f3f40271af0a032ec07aec57eedf91/diffs.json rename to test/data/registry/sharedimages/5b07deb6-4319-437c-867f-19de0a2a789e/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/c9a19e9e3661af8be048a7e0fbd75ecec9a19e9e3661af8be048a7e0fbd75ece/diffs.json b/test/data/registry/sharedimages/5bb9536c-0452-46f6-9e07-b940e6438e8f/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/c9a19e9e3661af8be048a7e0fbd75ecec9a19e9e3661af8be048a7e0fbd75ece/diffs.json rename to test/data/registry/sharedimages/5bb9536c-0452-46f6-9e07-b940e6438e8f/diffs.json diff --git a/test/data/registry/images/devtable/complex/22d1aaa0bc26d6ce091069aaf97ab11d22d1aaa0bc26d6ce091069aaf97ab11d/diffs.json b/test/data/registry/sharedimages/5d130ed2-57da-464b-bd7f-6dcbbb9d21d6/diffs.json similarity index 100% rename from test/data/registry/images/devtable/complex/22d1aaa0bc26d6ce091069aaf97ab11d22d1aaa0bc26d6ce091069aaf97ab11d/diffs.json rename to test/data/registry/sharedimages/5d130ed2-57da-464b-bd7f-6dcbbb9d21d6/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/7ebb2eae1ecf7a46ef6d7401c16c6fcd7ebb2eae1ecf7a46ef6d7401c16c6fcd/diffs.json b/test/data/registry/sharedimages/5f813e36-f439-44ee-aa2f-d5171f37e9e8/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/7ebb2eae1ecf7a46ef6d7401c16c6fcd7ebb2eae1ecf7a46ef6d7401c16c6fcd/diffs.json rename to test/data/registry/sharedimages/5f813e36-f439-44ee-aa2f-d5171f37e9e8/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/aa954e497de27864883678892fe00389aa954e497de27864883678892fe00389/diffs.json b/test/data/registry/sharedimages/6165db2e-a725-4f09-83f6-ac391620c631/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/aa954e497de27864883678892fe00389aa954e497de27864883678892fe00389/diffs.json rename to test/data/registry/sharedimages/6165db2e-a725-4f09-83f6-ac391620c631/diffs.json diff --git a/test/data/registry/images/devtable/superwide/5b4f83a3bb31df974c281eaeba38d2cf5b4f83a3bb31df974c281eaeba38d2cf/diffs.json b/test/data/registry/sharedimages/6306add6-1dc3-4cdc-a11d-0ff8a57521f9/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/5b4f83a3bb31df974c281eaeba38d2cf5b4f83a3bb31df974c281eaeba38d2cf/diffs.json rename to test/data/registry/sharedimages/6306add6-1dc3-4cdc-a11d-0ff8a57521f9/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/6f07844f49df64d3f98b33c7cebc11cf6f07844f49df64d3f98b33c7cebc11cf/diffs.json b/test/data/registry/sharedimages/66dc45e9-1687-4cb6-a850-ac8c847ae547/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/6f07844f49df64d3f98b33c7cebc11cf6f07844f49df64d3f98b33c7cebc11cf/diffs.json rename to test/data/registry/sharedimages/66dc45e9-1687-4cb6-a850-ac8c847ae547/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/f52f7ded0612cff3e638da941ac53441f52f7ded0612cff3e638da941ac53441/diffs.json b/test/data/registry/sharedimages/6af86670-4135-4d3f-b96b-c80c1e3c195f/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/f52f7ded0612cff3e638da941ac53441f52f7ded0612cff3e638da941ac53441/diffs.json rename to test/data/registry/sharedimages/6af86670-4135-4d3f-b96b-c80c1e3c195f/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/c913951ea0cd4c6206f10aef139818f6c913951ea0cd4c6206f10aef139818f6/diffs.json b/test/data/registry/sharedimages/6b1c1f88-7c8b-4b01-8078-d8a11c836cd2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/c913951ea0cd4c6206f10aef139818f6c913951ea0cd4c6206f10aef139818f6/diffs.json rename to test/data/registry/sharedimages/6b1c1f88-7c8b-4b01-8078-d8a11c836cd2/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/d935480ec258b7e5f5ff21013ee402a6d935480ec258b7e5f5ff21013ee402a6/diffs.json b/test/data/registry/sharedimages/6cd9e738-2282-4c7b-acaf-ecc1075e200d/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/d935480ec258b7e5f5ff21013ee402a6d935480ec258b7e5f5ff21013ee402a6/diffs.json rename to test/data/registry/sharedimages/6cd9e738-2282-4c7b-acaf-ecc1075e200d/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/69df2430f958b4532bca77f61438c39669df2430f958b4532bca77f61438c396/diffs.json b/test/data/registry/sharedimages/6d0ee75b-2116-45c5-acb2-a068fa5c3eaa/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/69df2430f958b4532bca77f61438c39669df2430f958b4532bca77f61438c396/diffs.json rename to test/data/registry/sharedimages/6d0ee75b-2116-45c5-acb2-a068fa5c3eaa/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/7f89233fc020acaf004fb7e4d293ae6f7f89233fc020acaf004fb7e4d293ae6f/diffs.json b/test/data/registry/sharedimages/6e0bbb9f-3d2e-460c-8560-18fdecfc02a2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/7f89233fc020acaf004fb7e4d293ae6f7f89233fc020acaf004fb7e4d293ae6f/diffs.json rename to test/data/registry/sharedimages/6e0bbb9f-3d2e-460c-8560-18fdecfc02a2/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/ee43c0adbd6004f2fa0c91af80229849ee43c0adbd6004f2fa0c91af80229849/diffs.json b/test/data/registry/sharedimages/759c8017-ae45-4cdb-8bb1-798870dc0bfa/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/ee43c0adbd6004f2fa0c91af80229849ee43c0adbd6004f2fa0c91af80229849/diffs.json rename to test/data/registry/sharedimages/759c8017-ae45-4cdb-8bb1-798870dc0bfa/diffs.json diff --git a/test/data/registry/images/devtable/superwide/77e619ad5684dac98971aae11fb4925677e619ad5684dac98971aae11fb49256/diffs.json b/test/data/registry/sharedimages/79321db4-d86a-45df-8898-f66cc43861f5/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/77e619ad5684dac98971aae11fb4925677e619ad5684dac98971aae11fb49256/diffs.json rename to test/data/registry/sharedimages/79321db4-d86a-45df-8898-f66cc43861f5/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/8324a62cde97d7a0ebfc011068186a058324a62cde97d7a0ebfc011068186a05/diffs.json b/test/data/registry/sharedimages/82b69c6b-8897-4386-be22-0d53c42ed783/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/8324a62cde97d7a0ebfc011068186a058324a62cde97d7a0ebfc011068186a05/diffs.json rename to test/data/registry/sharedimages/82b69c6b-8897-4386-be22-0d53c42ed783/diffs.json diff --git a/test/data/registry/images/devtable/simple/44c28f16388dcfba12cbde037563982c44c28f16388dcfba12cbde037563982c/diffs.json b/test/data/registry/sharedimages/83d0f1b8-5c58-4019-8bce-af257ebd0f06/diffs.json similarity index 100% rename from test/data/registry/images/devtable/simple/44c28f16388dcfba12cbde037563982c44c28f16388dcfba12cbde037563982c/diffs.json rename to test/data/registry/sharedimages/83d0f1b8-5c58-4019-8bce-af257ebd0f06/diffs.json diff --git a/test/data/registry/images/devtable/superwide/35ccc88fa79c0d01e159fe82ed98851c35ccc88fa79c0d01e159fe82ed98851c/diffs.json b/test/data/registry/sharedimages/86006d61-0aa7-467d-9de9-66a35a25cb33/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/35ccc88fa79c0d01e159fe82ed98851c35ccc88fa79c0d01e159fe82ed98851c/diffs.json rename to test/data/registry/sharedimages/86006d61-0aa7-467d-9de9-66a35a25cb33/diffs.json diff --git a/test/data/registry/images/devtable/shared/4bc9d873a9b4ee89dcaaf55a55a84b974bc9d873a9b4ee89dcaaf55a55a84b97/diffs.json b/test/data/registry/sharedimages/882fbbfd-623c-421b-83d3-ac0f03cab013/diffs.json similarity index 100% rename from test/data/registry/images/devtable/shared/4bc9d873a9b4ee89dcaaf55a55a84b974bc9d873a9b4ee89dcaaf55a55a84b97/diffs.json rename to test/data/registry/sharedimages/882fbbfd-623c-421b-83d3-ac0f03cab013/diffs.json diff --git a/test/data/registry/images/devtable/simple/d4842afed193ee9830dcc5a1e57f4fa0d4842afed193ee9830dcc5a1e57f4fa0/diffs.json b/test/data/registry/sharedimages/8aa4612e-29d4-4dd6-8983-a3cb4eb6c13d/diffs.json similarity index 100% rename from test/data/registry/images/devtable/simple/d4842afed193ee9830dcc5a1e57f4fa0d4842afed193ee9830dcc5a1e57f4fa0/diffs.json rename to test/data/registry/sharedimages/8aa4612e-29d4-4dd6-8983-a3cb4eb6c13d/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/ff382595eafa11320e23fcb372f2f547ff382595eafa11320e23fcb372f2f547/diffs.json b/test/data/registry/sharedimages/8adf6c52-50c3-4651-be96-02c966fa9949/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/ff382595eafa11320e23fcb372f2f547ff382595eafa11320e23fcb372f2f547/diffs.json rename to test/data/registry/sharedimages/8adf6c52-50c3-4651-be96-02c966fa9949/diffs.json diff --git a/test/data/registry/images/devtable/superwide/4be4bd16a1fa277540b8943a58ace5e54be4bd16a1fa277540b8943a58ace5e5/diffs.json b/test/data/registry/sharedimages/8be50fe6-01c7-406a-8fca-d5e208ec1270/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/4be4bd16a1fa277540b8943a58ace5e54be4bd16a1fa277540b8943a58ace5e5/diffs.json rename to test/data/registry/sharedimages/8be50fe6-01c7-406a-8fca-d5e208ec1270/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/85b43d0201f25007b18909d6d495f92d85b43d0201f25007b18909d6d495f92d/diffs.json b/test/data/registry/sharedimages/910a594e-ae04-4238-9926-607206d1ff8f/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/85b43d0201f25007b18909d6d495f92d85b43d0201f25007b18909d6d495f92d/diffs.json rename to test/data/registry/sharedimages/910a594e-ae04-4238-9926-607206d1ff8f/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/c1d29009854393d48c3c9a64891e2ba6c1d29009854393d48c3c9a64891e2ba6/diffs.json b/test/data/registry/sharedimages/914dd053-4214-4745-ab7f-5c78cef726a9/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/c1d29009854393d48c3c9a64891e2ba6c1d29009854393d48c3c9a64891e2ba6/diffs.json rename to test/data/registry/sharedimages/914dd053-4214-4745-ab7f-5c78cef726a9/diffs.json diff --git a/test/data/registry/images/devtable/shared/fc53cea92e5567da559fa149253a44ecfc53cea92e5567da559fa149253a44ec/diffs.json b/test/data/registry/sharedimages/938ad98e-32df-4526-ba6f-08abda5926eb/diffs.json similarity index 100% rename from test/data/registry/images/devtable/shared/fc53cea92e5567da559fa149253a44ecfc53cea92e5567da559fa149253a44ec/diffs.json rename to test/data/registry/sharedimages/938ad98e-32df-4526-ba6f-08abda5926eb/diffs.json diff --git a/test/data/registry/images/devtable/shared/bf3883d81e05555919f2ca9d7ca2983ebf3883d81e05555919f2ca9d7ca2983e/diffs.json b/test/data/registry/sharedimages/94b9ff3f-dd72-41ad-8c2e-25109787bf5d/diffs.json similarity index 100% rename from test/data/registry/images/devtable/shared/bf3883d81e05555919f2ca9d7ca2983ebf3883d81e05555919f2ca9d7ca2983e/diffs.json rename to test/data/registry/sharedimages/94b9ff3f-dd72-41ad-8c2e-25109787bf5d/diffs.json diff --git a/test/data/registry/images/devtable/superwide/c81e86f17e713dde15d87635c06ab9c5c81e86f17e713dde15d87635c06ab9c5/diffs.json b/test/data/registry/sharedimages/9653fd09-98c3-46d4-9c73-99c09e7f90ae/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/c81e86f17e713dde15d87635c06ab9c5c81e86f17e713dde15d87635c06ab9c5/diffs.json rename to test/data/registry/sharedimages/9653fd09-98c3-46d4-9c73-99c09e7f90ae/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/e35146409ec17c0e94dbc56a120919a4e35146409ec17c0e94dbc56a120919a4/diffs.json b/test/data/registry/sharedimages/9b368a3a-d147-47a0-9613-e68a90aec8c4/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/e35146409ec17c0e94dbc56a120919a4e35146409ec17c0e94dbc56a120919a4/diffs.json rename to test/data/registry/sharedimages/9b368a3a-d147-47a0-9613-e68a90aec8c4/diffs.json diff --git a/test/data/registry/images/devtable/shared/74e2e6b2c6688900b1a8e31a772d217774e2e6b2c6688900b1a8e31a772d2177/diffs.json b/test/data/registry/sharedimages/9de2902d-4b9e-47c6-b81e-47b434416424/diffs.json similarity index 100% rename from test/data/registry/images/devtable/shared/74e2e6b2c6688900b1a8e31a772d217774e2e6b2c6688900b1a8e31a772d2177/diffs.json rename to test/data/registry/sharedimages/9de2902d-4b9e-47c6-b81e-47b434416424/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/efb34827b6c92107c252da9d451b6222efb34827b6c92107c252da9d451b6222/diffs.json b/test/data/registry/sharedimages/9e8669cf-3a64-4f77-a5d2-3c4014a33675/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/efb34827b6c92107c252da9d451b6222efb34827b6c92107c252da9d451b6222/diffs.json rename to test/data/registry/sharedimages/9e8669cf-3a64-4f77-a5d2-3c4014a33675/diffs.json diff --git a/test/data/registry/images/devtable/superwide/6bd9f4dbacd08334ff661c9e1f1f0f3d6bd9f4dbacd08334ff661c9e1f1f0f3d/diffs.json b/test/data/registry/sharedimages/a1f24165-9406-47d9-bb93-20da061092ae/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/6bd9f4dbacd08334ff661c9e1f1f0f3d6bd9f4dbacd08334ff661c9e1f1f0f3d/diffs.json rename to test/data/registry/sharedimages/a1f24165-9406-47d9-bb93-20da061092ae/diffs.json diff --git a/test/data/registry/images/devtable/superwide/929d49280a9aab5e6aa2fe9420cc918a929d49280a9aab5e6aa2fe9420cc918a/diffs.json b/test/data/registry/sharedimages/a223d22e-4899-4bd7-9867-a053df90ef4a/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/929d49280a9aab5e6aa2fe9420cc918a929d49280a9aab5e6aa2fe9420cc918a/diffs.json rename to test/data/registry/sharedimages/a223d22e-4899-4bd7-9867-a053df90ef4a/diffs.json diff --git a/test/data/registry/images/devtable/simple/d2accec6b09963021245853aadfd9af8d2accec6b09963021245853aadfd9af8/diffs.json b/test/data/registry/sharedimages/a5219e77-44ed-4085-8bee-e733873a3e6f/diffs.json similarity index 100% rename from test/data/registry/images/devtable/simple/d2accec6b09963021245853aadfd9af8d2accec6b09963021245853aadfd9af8/diffs.json rename to test/data/registry/sharedimages/a5219e77-44ed-4085-8bee-e733873a3e6f/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/8de22bdae0bcfee17a4b54c46ccca70a8de22bdae0bcfee17a4b54c46ccca70a/diffs.json b/test/data/registry/sharedimages/a7a88216-743f-40cb-beb4-295a4dacd939/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/8de22bdae0bcfee17a4b54c46ccca70a8de22bdae0bcfee17a4b54c46ccca70a/diffs.json rename to test/data/registry/sharedimages/a7a88216-743f-40cb-beb4-295a4dacd939/diffs.json diff --git a/test/data/registry/images/devtable/simple/7c66286da6034cfd15f4711f598a08c97c66286da6034cfd15f4711f598a08c9/diffs.json b/test/data/registry/sharedimages/aa54a871-c433-416c-ac2d-8b2a82649ec7/diffs.json similarity index 100% rename from test/data/registry/images/devtable/simple/7c66286da6034cfd15f4711f598a08c97c66286da6034cfd15f4711f598a08c9/diffs.json rename to test/data/registry/sharedimages/aa54a871-c433-416c-ac2d-8b2a82649ec7/diffs.json diff --git a/test/data/registry/images/devtable/superwide/939b37fb87a747ce351c8a1ae79b58a8939b37fb87a747ce351c8a1ae79b58a8/diffs.json b/test/data/registry/sharedimages/abd60c43-3c8a-428b-87d6-a522eac6c03e/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/939b37fb87a747ce351c8a1ae79b58a8939b37fb87a747ce351c8a1ae79b58a8/diffs.json rename to test/data/registry/sharedimages/abd60c43-3c8a-428b-87d6-a522eac6c03e/diffs.json diff --git a/test/data/registry/images/devtable/superwide/26762d44bb25cfe5d869f41110b96dce26762d44bb25cfe5d869f41110b96dce/diffs.json b/test/data/registry/sharedimages/abea3421-01a5-4979-8499-c78073d01778/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/26762d44bb25cfe5d869f41110b96dce26762d44bb25cfe5d869f41110b96dce/diffs.json rename to test/data/registry/sharedimages/abea3421-01a5-4979-8499-c78073d01778/diffs.json diff --git a/test/data/registry/images/devtable/superwide/3159d2462348da94bece4d80b4facfd93159d2462348da94bece4d80b4facfd9/diffs.json b/test/data/registry/sharedimages/add92c8e-ab96-4c73-b228-463c0b3fe34a/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/3159d2462348da94bece4d80b4facfd93159d2462348da94bece4d80b4facfd9/diffs.json rename to test/data/registry/sharedimages/add92c8e-ab96-4c73-b228-463c0b3fe34a/diffs.json diff --git a/test/data/registry/images/devtable/superwide/5b1517bc8165d91beda306692aa867c25b1517bc8165d91beda306692aa867c2/diffs.json b/test/data/registry/sharedimages/af3de1c0-3350-4ddb-97d0-e77f599410c0/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/5b1517bc8165d91beda306692aa867c25b1517bc8165d91beda306692aa867c2/diffs.json rename to test/data/registry/sharedimages/af3de1c0-3350-4ddb-97d0-e77f599410c0/diffs.json diff --git a/test/data/registry/images/devtable/superwide/f3decc05500979bea50ef970da1353a7f3decc05500979bea50ef970da1353a7/diffs.json b/test/data/registry/sharedimages/b0de04d3-9aa1-433b-8148-60704ce9701c/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/f3decc05500979bea50ef970da1353a7f3decc05500979bea50ef970da1353a7/diffs.json rename to test/data/registry/sharedimages/b0de04d3-9aa1-433b-8148-60704ce9701c/diffs.json diff --git a/test/data/registry/images/devtable/superwide/4a0d5192dae3ab310018f57bb76f7b2d4a0d5192dae3ab310018f57bb76f7b2d/diffs.json b/test/data/registry/sharedimages/b1e03886-e56c-41b2-8247-bc65330f119b/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/4a0d5192dae3ab310018f57bb76f7b2d4a0d5192dae3ab310018f57bb76f7b2d/diffs.json rename to test/data/registry/sharedimages/b1e03886-e56c-41b2-8247-bc65330f119b/diffs.json diff --git a/test/data/registry/images/devtable/gargantuan/fd2e6b4b1fea3d1a500a0c5745066bdffd2e6b4b1fea3d1a500a0c5745066bdf/diffs.json b/test/data/registry/sharedimages/b5605f56-727a-4a44-923d-abb1407e86e4/diffs.json similarity index 100% rename from test/data/registry/images/devtable/gargantuan/fd2e6b4b1fea3d1a500a0c5745066bdffd2e6b4b1fea3d1a500a0c5745066bdf/diffs.json rename to test/data/registry/sharedimages/b5605f56-727a-4a44-923d-abb1407e86e4/diffs.json diff --git a/test/data/registry/images/public/publicrepo/068bc434cfbb875d706ae4a1fab1ab1c068bc434cfbb875d706ae4a1fab1ab1c/diffs.json b/test/data/registry/sharedimages/b705d6fd-0f02-480b-9e4c-92073527bda1/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/068bc434cfbb875d706ae4a1fab1ab1c068bc434cfbb875d706ae4a1fab1ab1c/diffs.json rename to test/data/registry/sharedimages/b705d6fd-0f02-480b-9e4c-92073527bda1/diffs.json diff --git a/test/data/registry/images/devtable/superwide/7a6dcdee524b1ef0a66f5f8e3be5ae1b7a6dcdee524b1ef0a66f5f8e3be5ae1b/diffs.json b/test/data/registry/sharedimages/b7742b21-e1e2-4c4d-8e13-2c2acbd4ec50/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/7a6dcdee524b1ef0a66f5f8e3be5ae1b7a6dcdee524b1ef0a66f5f8e3be5ae1b/diffs.json rename to test/data/registry/sharedimages/b7742b21-e1e2-4c4d-8e13-2c2acbd4ec50/diffs.json diff --git a/test/data/registry/images/devtable/superwide/8dbd7ccc692d6113282b0939f1798f6e8dbd7ccc692d6113282b0939f1798f6e/diffs.json b/test/data/registry/sharedimages/bc11c1a6-4588-479b-a336-3cf2e8b596a0/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/8dbd7ccc692d6113282b0939f1798f6e8dbd7ccc692d6113282b0939f1798f6e/diffs.json rename to test/data/registry/sharedimages/bc11c1a6-4588-479b-a336-3cf2e8b596a0/diffs.json diff --git a/test/data/registry/images/devtable/superwide/8eb89d1a9f0980fb348d81e7c9136a768eb89d1a9f0980fb348d81e7c9136a76/diffs.json b/test/data/registry/sharedimages/bd2e01c6-b55e-48ce-abab-f86889be6351/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/8eb89d1a9f0980fb348d81e7c9136a768eb89d1a9f0980fb348d81e7c9136a76/diffs.json rename to test/data/registry/sharedimages/bd2e01c6-b55e-48ce-abab-f86889be6351/diffs.json diff --git a/test/data/registry/images/devtable/superwide/ea92aa1746527ca3463d22163eba9c32ea92aa1746527ca3463d22163eba9c32/diffs.json b/test/data/registry/sharedimages/bdca58b9-9123-46f2-a7af-b61d38cb31d2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/ea92aa1746527ca3463d22163eba9c32ea92aa1746527ca3463d22163eba9c32/diffs.json rename to test/data/registry/sharedimages/bdca58b9-9123-46f2-a7af-b61d38cb31d2/diffs.json diff --git a/test/data/registry/images/devtable/superwide/0eaf8aa3a4640429b0a35f66ecb237d00eaf8aa3a4640429b0a35f66ecb237d0/diffs.json b/test/data/registry/sharedimages/bf25cd6c-68b5-4145-bcd8-bc61b05be937/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/0eaf8aa3a4640429b0a35f66ecb237d00eaf8aa3a4640429b0a35f66ecb237d0/diffs.json rename to test/data/registry/sharedimages/bf25cd6c-68b5-4145-bcd8-bc61b05be937/diffs.json diff --git a/test/data/registry/images/devtable/superwide/56f91a5d89d065364bde6c5035aaa55156f91a5d89d065364bde6c5035aaa551/diffs.json b/test/data/registry/sharedimages/c1c83733-324f-43a6-93fa-1f58637a1ba2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/56f91a5d89d065364bde6c5035aaa55156f91a5d89d065364bde6c5035aaa551/diffs.json rename to test/data/registry/sharedimages/c1c83733-324f-43a6-93fa-1f58637a1ba2/diffs.json diff --git a/test/data/registry/images/devtable/superwide/01cc26e3eb8add33920614712d22382c01cc26e3eb8add33920614712d22382c/diffs.json b/test/data/registry/sharedimages/c29eadb1-d366-4559-b759-d44ffc0994e8/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/01cc26e3eb8add33920614712d22382c01cc26e3eb8add33920614712d22382c/diffs.json rename to test/data/registry/sharedimages/c29eadb1-d366-4559-b759-d44ffc0994e8/diffs.json diff --git a/test/data/registry/images/devtable/superwide/1c3e1a10479d118426aaa1afc2ed38261c3e1a10479d118426aaa1afc2ed3826/diffs.json b/test/data/registry/sharedimages/c2cdbbca-4c1d-4596-ad9e-8ca5999643ec/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/1c3e1a10479d118426aaa1afc2ed38261c3e1a10479d118426aaa1afc2ed3826/diffs.json rename to test/data/registry/sharedimages/c2cdbbca-4c1d-4596-ad9e-8ca5999643ec/diffs.json diff --git a/test/data/registry/images/devtable/superwide/b1663c5aba499d7b189b8b18da1e85c5b1663c5aba499d7b189b8b18da1e85c5/diffs.json b/test/data/registry/sharedimages/c2d78244-02c7-4560-b5d3-45d16973dbc9/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/b1663c5aba499d7b189b8b18da1e85c5b1663c5aba499d7b189b8b18da1e85c5/diffs.json rename to test/data/registry/sharedimages/c2d78244-02c7-4560-b5d3-45d16973dbc9/diffs.json diff --git a/test/data/registry/images/devtable/superwide/a764e2127e9987b40dda2cff5b68fa03a764e2127e9987b40dda2cff5b68fa03/diffs.json b/test/data/registry/sharedimages/c67ca40c-1b3c-448b-82d4-52e7bd8a4da6/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/a764e2127e9987b40dda2cff5b68fa03a764e2127e9987b40dda2cff5b68fa03/diffs.json rename to test/data/registry/sharedimages/c67ca40c-1b3c-448b-82d4-52e7bd8a4da6/diffs.json diff --git a/test/data/registry/images/devtable/superwide/dc14642adcdd132b30870e665f13730fdc14642adcdd132b30870e665f13730f/diffs.json b/test/data/registry/sharedimages/ca1cf59d-68a1-4c49-87c5-73a6989b1d9d/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/dc14642adcdd132b30870e665f13730fdc14642adcdd132b30870e665f13730f/diffs.json rename to test/data/registry/sharedimages/ca1cf59d-68a1-4c49-87c5-73a6989b1d9d/diffs.json diff --git a/test/data/registry/images/devtable/superwide/34820e32c0e1bb98bf92ab69793900e834820e32c0e1bb98bf92ab69793900e8/diffs.json b/test/data/registry/sharedimages/cc78948e-cf4f-4a97-aac2-0db33affd25b/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/34820e32c0e1bb98bf92ab69793900e834820e32c0e1bb98bf92ab69793900e8/diffs.json rename to test/data/registry/sharedimages/cc78948e-cf4f-4a97-aac2-0db33affd25b/diffs.json diff --git a/test/data/registry/images/devtable/superwide/a0d5c5f27c1c4c23a1ffebd179d3d856a0d5c5f27c1c4c23a1ffebd179d3d856/diffs.json b/test/data/registry/sharedimages/cf834035-2db5-41fe-aacb-30ad533e9bf9/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/a0d5c5f27c1c4c23a1ffebd179d3d856a0d5c5f27c1c4c23a1ffebd179d3d856/diffs.json rename to test/data/registry/sharedimages/cf834035-2db5-41fe-aacb-30ad533e9bf9/diffs.json diff --git a/test/data/registry/images/devtable/superwide/a686b51a7fd71d9a92e59ad05ab0b76da686b51a7fd71d9a92e59ad05ab0b76d/diffs.json b/test/data/registry/sharedimages/cfa60ed4-9ec9-4268-b283-1dbfb0f647a2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/a686b51a7fd71d9a92e59ad05ab0b76da686b51a7fd71d9a92e59ad05ab0b76d/diffs.json rename to test/data/registry/sharedimages/cfa60ed4-9ec9-4268-b283-1dbfb0f647a2/diffs.json diff --git a/test/data/registry/images/devtable/superwide/f967ecd286d83fa6f3e8f1908a65c6f6f967ecd286d83fa6f3e8f1908a65c6f6/diffs.json b/test/data/registry/sharedimages/d3ddce06-cdb7-4acc-9afd-ea90b84fc195/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/f967ecd286d83fa6f3e8f1908a65c6f6f967ecd286d83fa6f3e8f1908a65c6f6/diffs.json rename to test/data/registry/sharedimages/d3ddce06-cdb7-4acc-9afd-ea90b84fc195/diffs.json diff --git a/test/data/registry/images/devtable/superwide/cd292bc08dbf282f6667978704fe4fcecd292bc08dbf282f6667978704fe4fce/diffs.json b/test/data/registry/sharedimages/d4d29c5c-410c-4986-9dd9-6b45d513b5ef/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/cd292bc08dbf282f6667978704fe4fcecd292bc08dbf282f6667978704fe4fce/diffs.json rename to test/data/registry/sharedimages/d4d29c5c-410c-4986-9dd9-6b45d513b5ef/diffs.json diff --git a/test/data/registry/images/devtable/superwide/ec21bac47e305066e0f2735c827cccecec21bac47e305066e0f2735c827cccec/diffs.json b/test/data/registry/sharedimages/d52fe920-9bd2-43f6-a1d5-7b1de9b4593b/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/ec21bac47e305066e0f2735c827cccecec21bac47e305066e0f2735c827cccec/diffs.json rename to test/data/registry/sharedimages/d52fe920-9bd2-43f6-a1d5-7b1de9b4593b/diffs.json diff --git a/test/data/registry/images/devtable/superwide/aed48948f4b08def8953aa0ac4095773aed48948f4b08def8953aa0ac4095773/diffs.json b/test/data/registry/sharedimages/d7f6f01c-38d0-4ef0-bde9-c969c8067a46/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/aed48948f4b08def8953aa0ac4095773aed48948f4b08def8953aa0ac4095773/diffs.json rename to test/data/registry/sharedimages/d7f6f01c-38d0-4ef0-bde9-c969c8067a46/diffs.json diff --git a/test/data/registry/images/public/publicrepo/5f14df20df37b306cb8ecb423fa539c75f14df20df37b306cb8ecb423fa539c7/diffs.json b/test/data/registry/sharedimages/d8c8f451-4cce-4cca-aa67-0d3ed29cb9ad/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/5f14df20df37b306cb8ecb423fa539c75f14df20df37b306cb8ecb423fa539c7/diffs.json rename to test/data/registry/sharedimages/d8c8f451-4cce-4cca-aa67-0d3ed29cb9ad/diffs.json diff --git a/test/data/registry/images/public/publicrepo/030581d6f421978b637479b73f862b63030581d6f421978b637479b73f862b63/diffs.json b/test/data/registry/sharedimages/d95447f8-507c-453e-a7f8-3089253b53e8/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/030581d6f421978b637479b73f862b63030581d6f421978b637479b73f862b63/diffs.json rename to test/data/registry/sharedimages/d95447f8-507c-453e-a7f8-3089253b53e8/diffs.json diff --git a/test/data/registry/images/devtable/superwide/b88a057dcc693e5a2e212e267c5f2d04b88a057dcc693e5a2e212e267c5f2d04/diffs.json b/test/data/registry/sharedimages/da37b866-4262-4c68-8a42-6661880151f6/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/b88a057dcc693e5a2e212e267c5f2d04b88a057dcc693e5a2e212e267c5f2d04/diffs.json rename to test/data/registry/sharedimages/da37b866-4262-4c68-8a42-6661880151f6/diffs.json diff --git a/test/data/registry/images/devtable/superwide/b74e9112918638ac9b6118ef55b0224cb74e9112918638ac9b6118ef55b0224c/diffs.json b/test/data/registry/sharedimages/ddb9734b-b587-4cdb-a774-da43aa2b76b8/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/b74e9112918638ac9b6118ef55b0224cb74e9112918638ac9b6118ef55b0224c/diffs.json rename to test/data/registry/sharedimages/ddb9734b-b587-4cdb-a774-da43aa2b76b8/diffs.json diff --git a/test/data/registry/images/devtable/superwide/d8213f593aeaefe7e14562114965dee1d8213f593aeaefe7e14562114965dee1/diffs.json b/test/data/registry/sharedimages/deb73515-8ba5-4a9f-b37b-a18c6bb21a64/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/d8213f593aeaefe7e14562114965dee1d8213f593aeaefe7e14562114965dee1/diffs.json rename to test/data/registry/sharedimages/deb73515-8ba5-4a9f-b37b-a18c6bb21a64/diffs.json diff --git a/test/data/registry/images/devtable/superwide/f4c4e168362552e3bef64f5e06857991f4c4e168362552e3bef64f5e06857991/diffs.json b/test/data/registry/sharedimages/deed11ba-d788-4d7c-ba77-8a1f3596c3e8/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/f4c4e168362552e3bef64f5e06857991f4c4e168362552e3bef64f5e06857991/diffs.json rename to test/data/registry/sharedimages/deed11ba-d788-4d7c-ba77-8a1f3596c3e8/diffs.json diff --git a/test/data/registry/images/devtable/superwide/fa95798c5aeae672bf8a68be4d954190fa95798c5aeae672bf8a68be4d954190/diffs.json b/test/data/registry/sharedimages/e370876e-20fd-431c-b69e-2f187f2ddf09/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/fa95798c5aeae672bf8a68be4d954190fa95798c5aeae672bf8a68be4d954190/diffs.json rename to test/data/registry/sharedimages/e370876e-20fd-431c-b69e-2f187f2ddf09/diffs.json diff --git a/test/data/registry/images/devtable/superwide/f577c8ff27c0689c5cc58297dffdfb61f577c8ff27c0689c5cc58297dffdfb61/diffs.json b/test/data/registry/sharedimages/e7a16cf3-7b8d-464b-84e8-30d39e9e3268/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/f577c8ff27c0689c5cc58297dffdfb61f577c8ff27c0689c5cc58297dffdfb61/diffs.json rename to test/data/registry/sharedimages/e7a16cf3-7b8d-464b-84e8-30d39e9e3268/diffs.json diff --git a/test/data/registry/images/devtable/superwide/fcb18e158c1aa950a3ccf30cb668b07dfcb18e158c1aa950a3ccf30cb668b07d/diffs.json b/test/data/registry/sharedimages/ebe546ff-65ec-44ce-87f5-f6e07108dd22/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/fcb18e158c1aa950a3ccf30cb668b07dfcb18e158c1aa950a3ccf30cb668b07d/diffs.json rename to test/data/registry/sharedimages/ebe546ff-65ec-44ce-87f5-f6e07108dd22/diffs.json diff --git a/test/data/registry/images/devtable/superwide/fd40aaf01b09ed108501cd2df887fc07fd40aaf01b09ed108501cd2df887fc07/diffs.json b/test/data/registry/sharedimages/ec100ead-dca9-443f-b588-fbc1b4cc4112/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/fd40aaf01b09ed108501cd2df887fc07fd40aaf01b09ed108501cd2df887fc07/diffs.json rename to test/data/registry/sharedimages/ec100ead-dca9-443f-b588-fbc1b4cc4112/diffs.json diff --git a/test/data/registry/images/public/publicrepo/9646530d3f1f3b1a384947dbd5a3a0319646530d3f1f3b1a384947dbd5a3a031/diffs.json b/test/data/registry/sharedimages/f0472195-49c2-408e-95c4-34625faaec23/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/9646530d3f1f3b1a384947dbd5a3a0319646530d3f1f3b1a384947dbd5a3a031/diffs.json rename to test/data/registry/sharedimages/f0472195-49c2-408e-95c4-34625faaec23/diffs.json diff --git a/test/data/registry/images/devtable/superwide/d6a19d555f83b99392bdd9f44735d425d6a19d555f83b99392bdd9f44735d425/diffs.json b/test/data/registry/sharedimages/f058fa2a-cba2-4308-9fb6-0c94ea8366f2/diffs.json similarity index 100% rename from test/data/registry/images/devtable/superwide/d6a19d555f83b99392bdd9f44735d425d6a19d555f83b99392bdd9f44735d425/diffs.json rename to test/data/registry/sharedimages/f058fa2a-cba2-4308-9fb6-0c94ea8366f2/diffs.json diff --git a/test/data/registry/images/public/publicrepo/7eb06578cc1b5a8d0cafa075a2f634937eb06578cc1b5a8d0cafa075a2f63493/diffs.json b/test/data/registry/sharedimages/f5801fc1-e889-4c2a-a194-a2b565a4d340/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/7eb06578cc1b5a8d0cafa075a2f634937eb06578cc1b5a8d0cafa075a2f63493/diffs.json rename to test/data/registry/sharedimages/f5801fc1-e889-4c2a-a194-a2b565a4d340/diffs.json diff --git a/test/data/registry/images/public/publicrepo/1b4bc84b74c71ac837ff19eae76e76c01b4bc84b74c71ac837ff19eae76e76c0/diffs.json b/test/data/registry/sharedimages/f6834ba6-4cb9-457b-a7aa-5b93c5b30010/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/1b4bc84b74c71ac837ff19eae76e76c01b4bc84b74c71ac837ff19eae76e76c0/diffs.json rename to test/data/registry/sharedimages/f6834ba6-4cb9-457b-a7aa-5b93c5b30010/diffs.json diff --git a/test/data/registry/images/public/publicrepo/c11210080ed68235719a6f2ff39467ffc11210080ed68235719a6f2ff39467ff/diffs.json b/test/data/registry/sharedimages/f8337809-d8a1-47be-a14a-c705dfceaf60/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/c11210080ed68235719a6f2ff39467ffc11210080ed68235719a6f2ff39467ff/diffs.json rename to test/data/registry/sharedimages/f8337809-d8a1-47be-a14a-c705dfceaf60/diffs.json diff --git a/test/data/registry/images/public/publicrepo/c02f0fa3b78e16755fc38e0529571587c02f0fa3b78e16755fc38e0529571587/diffs.json b/test/data/registry/sharedimages/fa7a8a7c-d895-490f-b278-f789cc9cb78d/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/c02f0fa3b78e16755fc38e0529571587c02f0fa3b78e16755fc38e0529571587/diffs.json rename to test/data/registry/sharedimages/fa7a8a7c-d895-490f-b278-f789cc9cb78d/diffs.json diff --git a/test/data/registry/images/public/publicrepo/7025cb49ee8cd5da3054e4b69210fdbe7025cb49ee8cd5da3054e4b69210fdbe/diffs.json b/test/data/registry/sharedimages/fad2bf28-105b-4a86-b8f5-ee5e3149cc01/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/7025cb49ee8cd5da3054e4b69210fdbe7025cb49ee8cd5da3054e4b69210fdbe/diffs.json rename to test/data/registry/sharedimages/fad2bf28-105b-4a86-b8f5-ee5e3149cc01/diffs.json diff --git a/test/data/registry/images/public/publicrepo/cd3e411f13126e8aaf1ccd8d7e9fd28bcd3e411f13126e8aaf1ccd8d7e9fd28b/diffs.json b/test/data/registry/sharedimages/fca6dabc-e0a0-486a-91c7-fe55ca2f4611/diffs.json similarity index 100% rename from test/data/registry/images/public/publicrepo/cd3e411f13126e8aaf1ccd8d7e9fd28bcd3e411f13126e8aaf1ccd8d7e9fd28b/diffs.json rename to test/data/registry/sharedimages/fca6dabc-e0a0-486a-91c7-fe55ca2f4611/diffs.json diff --git a/test/data/test.db b/test/data/test.db index 775f2c82d..f7d65a32a 100644 Binary files a/test/data/test.db and b/test/data/test.db differ diff --git a/tools/backfill_commands.py b/tools/backfill_commands.py deleted file mode 100644 index d781cdfeb..000000000 --- a/tools/backfill_commands.py +++ /dev/null @@ -1,20 +0,0 @@ -from data.database import Image -from app import app -import json - - -store = app.config['STORAGE'] - - -for image in Image.select(): - if image.command == None: - image_json_path = store.image_json_path(image.repository.namespace, - image.repository.name, - image.docker_image_id) - if store.exists(image_json_path): - data = json.loads(store.get_content(image_json_path)) - command_list = data.get('container_config', {}).get('Cmd', None) - command = json.dumps(command_list) if command_list else None - print 'Setting command to: %s' % command - image.command = command - image.save() \ No newline at end of file diff --git a/tools/backfillsizes.py b/tools/backfillsizes.py deleted file mode 100644 index 2f60cd374..000000000 --- a/tools/backfillsizes.py +++ /dev/null @@ -1,17 +0,0 @@ -from data.database import Image -from app import app - - -store = app.config['STORAGE'] - - -for image in Image.select(): - if image.image_size == None: - image_path = store.image_layer_path(image.repository.namespace, - image.repository.name, - image.docker_image_id) - if store.exists(image_path): - size = store.get_size(image_path) - print 'Setting image %s size to: %s' % (image.docker_image_id, size) - image.image_size = size - image.save() \ No newline at end of file