diff --git a/data/model/image.py b/data/model/image.py index b865c048b..8c79a12f3 100644 --- a/data/model/image.py +++ b/data/model/image.py @@ -34,26 +34,41 @@ def get_repository_image_and_deriving(docker_image_id, storage_uuid): (Image.id == image_found.id)) +def get_parent_images_with_placements(namespace_name, repository_name, image_obj): + """ Returns a list of parent Image objects starting with the most recent parent + and ending with the base layer. The images in this query will include the storage and + placements. + """ + return _get_parent_images(namespace_name, repository_name, image_obj, include_placements=True) + + def get_parent_images(namespace_name, repository_name, image_obj): """ Returns a list of parent Image objects starting with the most recent parent - and ending with the base layer. + and ending with the base layer. The images in this query will include the storage but + not the placements. """ + return _get_parent_images(namespace_name, repository_name, image_obj, include_placements=False) + + +def _get_parent_images(namespace_name, repository_name, image_obj, include_placements=False): parents = image_obj.ancestors # Ancestors are in the format ///...//, with each path section # containing the database Id of the image row. parent_db_ids = parents.strip('/').split('/') - if parent_db_ids == ['']: return [] def filter_to_parents(query): return query.where(Image.id << parent_db_ids) - parents = get_repository_images_base(namespace_name, repository_name, filter_to_parents) + if include_placements: + parents = get_repository_images_base(namespace_name, repository_name, filter_to_parents) + else: + parents = _get_repository_images_and_storages(namespace_name, repository_name, + filter_to_parents) id_to_image = {unicode(image.id): image for image in parents} - return [id_to_image[parent_id] for parent_id in reversed(parent_db_ids)] @@ -79,6 +94,19 @@ def get_repo_image_extended(namespace_name, repository_name, docker_image_id): return images[0] +def _get_repository_images_and_storages(namespace_name, repository_name, query_modifier): + query = (Image + .select(Image, ImageStorage) + .join(ImageStorage) + .switch(Image) + .join(Repository) + .join(Namespace, on=(Repository.namespace_user == Namespace.id)) + .where(Repository.name == repository_name, Namespace.username == namespace_name)) + + query = query_modifier(query) + return query + + def _get_repository_images(namespace_name, repository_name, query_modifier): query = (Image .select() diff --git a/endpoints/verbs.py b/endpoints/verbs.py index 518cb38be..fc902006c 100644 --- a/endpoints/verbs.py +++ b/endpoints/verbs.py @@ -37,7 +37,8 @@ def _open_stream(formatter, namespace, repository, tag, synthetic_image_id, imag # For performance reasons, we load the full image list here, cache it, then disconnect from # the database. with database.UseThenDisconnect(app.config): - image_list = list(model.image.get_parent_images(namespace, repository, repo_image)) + image_list = list(model.image.get_parent_images_with_placements(namespace, repository, + repo_image)) image_list.insert(0, repo_image) def get_image_json(image):