diff --git a/glance/db/__init__.py b/glance/db/__init__.py index 210923a24d..5702c283cf 100644 --- a/glance/db/__init__.py +++ b/glance/db/__init__.py @@ -66,13 +66,14 @@ class ImageRepo(object): def get(self, image_id): try: - db_api_image = dict(self.db_api.image_get(self.context, image_id)) + db_api_image = dict(self.db_api.image_get(self.context, + image_id, + return_tag=True)) assert not db_api_image['deleted'] except (exception.NotFound, exception.Forbidden, AssertionError): msg = _("No image found with ID %s") % image_id raise exception.NotFound(msg) - tags = self.db_api.image_tag_get_all(self.context, image_id) - image = self._format_image_from_db(db_api_image, tags) + image = self._format_image_from_db(db_api_image, db_api_image['tags']) return ImageProxy(image, self.context, self.db_api) def list(self, marker=None, limit=None, sort_key=None, diff --git a/glance/db/registry/api.py b/glance/db/registry/api.py index 8ec10c023d..223a8620fb 100644 --- a/glance/db/registry/api.py +++ b/glance/db/registry/api.py @@ -83,9 +83,10 @@ def image_destroy(client, image_id): @_get_client -def image_get(client, image_id, force_show_deleted=False): +def image_get(client, image_id, force_show_deleted=False, return_tag=False): return client.image_get(image_id=image_id, - force_show_deleted=force_show_deleted) + force_show_deleted=force_show_deleted, + return_tag=return_tag) def is_image_visible(context, image, status=None): diff --git a/glance/db/simple/api.py b/glance/db/simple/api.py index 7013f9b2e3..14829f2939 100644 --- a/glance/db/simple/api.py +++ b/glance/db/simple/api.py @@ -380,7 +380,8 @@ def _sort_images(images, sort_key, sort_dir): return images -def _image_get(context, image_id, force_show_deleted=False, status=None): +def _image_get(context, image_id, force_show_deleted=False, status=None, + return_tag=False): try: image = DATA['images'][image_id] except KeyError: @@ -396,12 +397,18 @@ def _image_get(context, image_id, force_show_deleted=False, status=None): LOG.warn(_LW('Unable to get unowned image')) raise exception.Forbidden("Image not visible to you") + if return_tag: + image['tags'] = image_tag_get_all(context, image_id) + return image @log_call -def image_get(context, image_id, session=None, force_show_deleted=False): - image = _image_get(context, image_id, force_show_deleted) +def image_get(context, image_id, session=None, force_show_deleted=False, + return_tag=False): + image = _image_get(context, image_id, force_show_deleted, + return_tag=return_tag) + return _normalize_locations(context, copy.deepcopy(image), force_show_deleted=force_show_deleted) diff --git a/glance/db/sqlalchemy/api.py b/glance/db/sqlalchemy/api.py index cf20ca01d5..c5f2a0f938 100644 --- a/glance/db/sqlalchemy/api.py +++ b/glance/db/sqlalchemy/api.py @@ -196,11 +196,17 @@ def _normalize_tags(image): return image -def image_get(context, image_id, session=None, force_show_deleted=False): +def image_get(context, image_id, session=None, force_show_deleted=False, + return_tag=False): image = _image_get(context, image_id, session=session, - force_show_deleted=force_show_deleted) + force_show_deleted=force_show_deleted, + return_tag=return_tag) image = _normalize_locations(context, image.to_dict(), force_show_deleted=force_show_deleted) + + if return_tag: + image = _normalize_tags(image) + return image @@ -218,7 +224,8 @@ def _check_image_id(image_id): raise exception.NotFound() -def _image_get(context, image_id, session=None, force_show_deleted=False): +def _image_get(context, image_id, session=None, force_show_deleted=False, + return_tag=False): """Get an image or raise if it does not exist.""" _check_image_id(image_id) session = session or get_session() @@ -233,6 +240,9 @@ def _image_get(context, image_id, session=None, force_show_deleted=False): if not force_show_deleted and not context.can_see_deleted: query = query.filter_by(deleted=False) + if return_tag: + query = query.options(sa_orm.joinedload(models.Image.tags)) + image = query.one() except sa_orm.exc.NoResultFound: diff --git a/glance/tests/functional/db/base.py b/glance/tests/functional/db/base.py index 36d454d004..bfb6536d0f 100644 --- a/glance/tests/functional/db/base.py +++ b/glance/tests/functional/db/base.py @@ -382,6 +382,28 @@ class DriverTests(object): force_show_deleted=True) self.assertEqual(self.fixtures[0]['id'], image['id']) + def test_image_get_with_tag_returning(self): + expected_tags = {UUID1: ['foo'], UUID2: ['bar'], UUID3: ['baz']} + + self.db_api.image_tag_create(self.context, UUID1, + expected_tags[UUID1][0]) + self.db_api.image_tag_create(self.context, UUID2, + expected_tags[UUID2][0]) + self.db_api.image_tag_create(self.context, UUID3, + expected_tags[UUID3][0]) + + image = self.db_api.image_get(self.context, UUID1, return_tag=True) + self.assertEqual(self.fixtures[0]['id'], image['id']) + self.assertEqual(expected_tags[image['id']], image['tags']) + + self.db_api.image_tag_delete(self.context, UUID1, + expected_tags[UUID1][0]) + expected_tags[UUID1] = [] + + image = self.db_api.image_get(self.context, UUID1, return_tag=True) + self.assertEqual(self.fixtures[0]['id'], image['id']) + self.assertEqual(expected_tags[image['id']], image['tags']) + def test_image_get_not_owned(self): TENANT1 = str(uuid.uuid4()) TENANT2 = str(uuid.uuid4())