diff --git a/data/model.py b/data/model.py index d00ebbdb0..30f8f174a 100644 --- a/data/model.py +++ b/data/model.py @@ -884,12 +884,19 @@ def create_repository(namespace, name, creating_user, visibility='private'): return repo -def create_or_link_image(docker_image_id, repository, username): +def __translate_ancestry(old_ancestry, translations): + old_ids = [int(id_str) for id_str in old_ancestry.split('/')[1:-1]] + new_ids = [str(translations[old_id]) for old_id in old_ids] + return '/%s/' % '/'.join(new_ids) + + +def create_or_link_image(docker_image_id, repository, username, translations): with transaction_factory(db): - query = (ImageStorage - .select() + query = (Image + .select(Image, ImageStorage) .distinct() - .join(Image) + .join(ImageStorage) + .switch(Image) .join(Repository) .join(Visibility) .switch(Repository) @@ -898,16 +905,29 @@ def create_or_link_image(docker_image_id, repository, username): query = (_filter_to_repos_for_user(query, username) .where(Image.docker_image_id == docker_image_id)) + new_image_ancestry = '/' + origin_image_id = None try: - storage = query.get() + to_copy = 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(msg, docker_image_id, to_copy.storage.uuid) + + new_image_ancestry = __translate_ancestry(to_copy.ancestors, + translations) + + storage = to_copy.storage + origin_image_id = to_copy.id + except Image.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) + repository=repository, storage=storage, + ancestors=new_image_ancestry) + + if origin_image_id: + translations[origin_image_id] = new_image.id + return new_image diff --git a/endpoints/index.py b/endpoints/index.py index 73ced37db..10105a587 100644 --- a/endpoints/index.py +++ b/endpoints/index.py @@ -4,6 +4,7 @@ import urlparse from flask import request, make_response, jsonify, session, Blueprint from functools import wraps +from collections import OrderedDict from data import model, userevent from data.queue import webhook_queue @@ -183,15 +184,18 @@ def create_repository(namespace, repository): repo = model.create_repository(namespace, repository, get_authenticated_user()) - new_repo_images = {desc['id']: desc for desc in image_descriptions} - added_images = dict(new_repo_images) + added_images = OrderedDict([(desc['id'], desc) + for desc in image_descriptions]) + new_repo_images = dict(added_images) for existing in model.get_repository_images(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 + translations = {} for image_description in added_images.values(): - model.create_or_link_image(image_description['id'], repo, username) + model.create_or_link_image(image_description['id'], repo, username, + translations) response = make_response('Created', 201) diff --git a/initdb.py b/initdb.py index 87d7fa769..113d96a3e 100644 --- a/initdb.py +++ b/initdb.py @@ -67,7 +67,7 @@ def __create_subtree(repo, structure, creator_username, parent): logger.debug('new docker id: %s' % docker_image_id) checksum = __gen_checksum(docker_image_id) - new_image = model.create_or_link_image(docker_image_id, repo, None) + new_image = model.create_or_link_image(docker_image_id, repo, None, {}) new_image.storage.uuid = IMAGE_UUIDS[image_num % len(IMAGE_UUIDS)] new_image.storage.save() diff --git a/test/data/test.db b/test/data/test.db index 0a6b7aa20..37967b6df 100644 Binary files a/test/data/test.db and b/test/data/test.db differ diff --git a/test/test_image_sharing.py b/test/test_image_sharing.py index 6f7245feb..e9b381555 100644 --- a/test/test_image_sharing.py +++ b/test/test_image_sharing.py @@ -43,7 +43,7 @@ class TestImageSharing(unittest.TestCase): def createStorage(self, docker_image_id, repository=REPO, username=ADMIN_ACCESS_USER): repository_obj = model.get_repository(repository.split('/')[0], repository.split('/')[1]) - image = model.create_or_link_image(docker_image_id, repository_obj, username) + image = model.create_or_link_image(docker_image_id, repository_obj, username, {}) return image.storage.id def assertSameStorage(self, docker_image_id, storage_id, repository=REPO, username=ADMIN_ACCESS_USER):