Merge "Fix for Image members not generating notifications"

This commit is contained in:
Jenkins 2016-01-26 19:33:48 +00:00 committed by Gerrit Code Review
commit cbfd426042
14 changed files with 334 additions and 100 deletions

View File

@ -112,13 +112,24 @@ class ImageRepoProxy(glance.domain.proxy.Repo):
return [proxy_image(self.context, i) for i in images]
class ImageMemberRepoProxy(glance.domain.proxy.Repo):
class ImageMemberRepoProxy(glance.domain.proxy.MemberRepo):
def __init__(self, member_repo, image, context):
self.member_repo = member_repo
self.image = image
self.context = context
super(ImageMemberRepoProxy, self).__init__(member_repo)
proxy_kwargs = {'context': self.context}
super(ImageMemberRepoProxy, self).__init__(
image,
member_repo,
member_proxy_class=ImageMemberProxy,
member_proxy_kwargs=proxy_kwargs)
self._check_image_visibility()
def _check_image_visibility(self):
if self.image.visibility == 'public':
message = _("Public images do not have members.")
raise exception.Forbidden(message)
def get(self, member_id):
if (self.context.is_admin or
@ -189,11 +200,16 @@ class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
return super(ImageFactoryProxy, self).new_image(owner=owner, **kwargs)
class ImageMemberFactoryProxy(object):
class ImageMemberFactoryProxy(glance.domain.proxy.ImageMembershipFactory):
def __init__(self, image_member_factory, context):
self.image_member_factory = image_member_factory
self.context = context
kwargs = {'context': self.context}
super(ImageMemberFactoryProxy, self).__init__(
image_member_factory,
proxy_class=ImageMemberProxy,
proxy_kwargs=kwargs)
def new_image_member(self, image, member_id):
owner = image.owner
@ -315,10 +331,6 @@ class ImmutableImageProxy(object):
message = _("You are not permitted to delete this image.")
raise exception.Forbidden(message)
def get_member_repo(self):
member_repo = self.base.get_member_repo()
return ImageMemberRepoProxy(member_repo, self, self.context)
def get_data(self, *args, **kwargs):
return self.base.get_data(*args, **kwargs)
@ -401,13 +413,13 @@ class ImageProxy(glance.domain.proxy.Image):
self.context = context
super(ImageProxy, self).__init__(image)
def get_member_repo(self, **kwargs):
if self.image.visibility == 'public':
message = _("Public images do not have members.")
raise exception.Forbidden(message)
else:
member_repo = self.image.get_member_repo(**kwargs)
return ImageMemberRepoProxy(member_repo, self, self.context)
class ImageMemberProxy(glance.domain.proxy.ImageMember):
def __init__(self, image_member, context):
self.image_member = image_member
self.context = context
super(ImageMemberProxy, self).__init__(image_member)
class TaskProxy(glance.domain.proxy.Task):

View File

@ -191,9 +191,14 @@ class ImageProxy(glance.domain.proxy.Image):
self.policy.enforce(self.context, 'upload_image', self.target)
return self.image.set_data(*args, **kwargs)
def get_member_repo(self, **kwargs):
member_repo = self.image.get_member_repo(**kwargs)
return ImageMemberRepoProxy(member_repo, self.context, self.policy)
class ImageMemberProxy(glance.domain.proxy.ImageMember):
def __init__(self, image_member, context, policy):
super(ImageMemberProxy, self).__init__(image_member)
self.image_member = image_member
self.context = context
self.policy = policy
class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
@ -218,15 +223,16 @@ class ImageMemberFactoryProxy(glance.domain.proxy.ImageMembershipFactory):
def __init__(self, member_factory, context, policy):
super(ImageMemberFactoryProxy, self).__init__(
member_factory,
image_proxy_class=ImageProxy,
image_proxy_kwargs={'context': context, 'policy': policy})
proxy_class=ImageMemberProxy,
proxy_kwargs={'context': context, 'policy': policy})
class ImageMemberRepoProxy(glance.domain.proxy.Repo):
def __init__(self, member_repo, context, policy):
def __init__(self, member_repo, image, context, policy):
self.member_repo = member_repo
self.target = ImageTarget(self.member_repo.image)
self.image = image
self.target = ImageTarget(image)
self.context = context
self.policy = policy

View File

@ -47,6 +47,18 @@ class ImageMembersController(object):
self.gateway = glance.gateway.Gateway(self.db_api, self.store_api,
self.notifier, self.policy)
def _get_member_repo(self, req, image):
try:
# For public images, a forbidden exception with message
# "Public images do not have members" is thrown.
return self.gateway.get_member_repo(image, req.context)
except exception.Forbidden as e:
msg = (_("Error fetching members of image %(image_id)s: "
"%(inner_msg)s") % {"image_id": image.image_id,
"inner_msg": e.msg})
LOG.warning(msg)
raise webob.exc.HTTPForbidden(explanation=msg)
def _lookup_image(self, req, image_id):
image_repo = self.gateway.get_repo(req.context)
try:
@ -60,21 +72,8 @@ class ImageMembersController(object):
LOG.warning(msg)
raise webob.exc.HTTPForbidden(explanation=msg)
@staticmethod
def _get_member_repo(image):
try:
# For public images, a forbidden exception with message
# "Public images do not have members" is thrown.
return image.get_member_repo()
except exception.Forbidden as e:
msg = (_("Error fetching members of image %(image_id)s: "
"%(inner_msg)s") % {"image_id": image.image_id,
"inner_msg": e.msg})
LOG.warning(msg)
raise webob.exc.HTTPForbidden(explanation=msg)
def _lookup_member(self, image, member_id):
member_repo = self._get_member_repo(image)
def _lookup_member(self, req, image, member_id):
member_repo = self._get_member_repo(req, image)
try:
return member_repo.get(member_id)
except (exception.NotFound):
@ -106,7 +105,7 @@ class ImageMembersController(object):
"""
image = self._lookup_image(req, image_id)
member_repo = self._get_member_repo(image)
member_repo = self._get_member_repo(req, image)
image_member_factory = self.gateway.get_image_member_factory(
req.context)
try:
@ -148,8 +147,8 @@ class ImageMembersController(object):
"""
image = self._lookup_image(req, image_id)
member_repo = self._get_member_repo(image)
member = self._lookup_member(image, member_id)
member_repo = self._get_member_repo(req, image)
member = self._lookup_member(req, image, member_id)
try:
member.status = status
member_repo.save(member)
@ -182,7 +181,7 @@ class ImageMembersController(object):
]}
"""
image = self._lookup_image(req, image_id)
member_repo = self._get_member_repo(image)
member_repo = self._get_member_repo(req, image)
members = []
try:
for member in member_repo.list():
@ -209,7 +208,7 @@ class ImageMembersController(object):
"""
try:
image = self._lookup_image(req, image_id)
return self._lookup_member(image, member_id)
return self._lookup_member(req, image, member_id)
except webob.exc.HTTPForbidden as e:
# Convert Forbidden to NotFound to prevent information
# leakage.
@ -221,8 +220,8 @@ class ImageMembersController(object):
Removes a membership from the image.
"""
image = self._lookup_image(req, image_id)
member_repo = self._get_member_repo(image)
member = self._lookup_member(image, member_id)
member_repo = self._get_member_repo(req, image)
member = self._lookup_member(req, image, member_id)
try:
member_repo.remove(member)
return webob.Response(body='', status=204)

View File

@ -303,11 +303,6 @@ class ImageProxy(glance.domain.proxy.Image):
self.image = image
super(ImageProxy, self).__init__(image)
def get_member_repo(self):
member_repo = ImageMemberRepo(self.context, self.db_api,
self.image)
return member_repo
class ImageMemberRepo(object):

View File

@ -105,6 +105,37 @@ class Repo(object):
return self.helper.proxy(result)
class MemberRepo(object):
def __init__(self, image, base,
member_proxy_class=None, member_proxy_kwargs=None):
self.image = image
self.base = base
self.member_proxy_helper = Helper(member_proxy_class,
member_proxy_kwargs)
def get(self, member_id):
member = self.base.get(member_id)
return self.member_proxy_helper.proxy(member)
def add(self, member):
self.base.add(self.member_proxy_helper.unproxy(member))
def list(self, *args, **kwargs):
members = self.base.list(*args, **kwargs)
return [self.member_proxy_helper.proxy(member) for member
in members]
def remove(self, member):
base_item = self.member_proxy_helper.unproxy(member)
result = self.base.remove(base_item)
return self.member_proxy_helper.proxy(result)
def save(self, member, from_state=None):
base_item = self.member_proxy_helper.unproxy(member)
result = self.base.save(base_item, from_state=from_state)
return self.member_proxy_helper.proxy(result)
class ImageFactory(object):
def __init__(self, base, proxy_class=None, proxy_kwargs=None):
self.helper = Helper(proxy_class, proxy_kwargs)
@ -115,16 +146,14 @@ class ImageFactory(object):
class ImageMembershipFactory(object):
def __init__(self, base, image_proxy_class=None, image_proxy_kwargs=None,
member_proxy_class=None, member_proxy_kwargs=None):
def __init__(self, base, proxy_class=None, proxy_kwargs=None):
self.helper = Helper(proxy_class, proxy_kwargs)
self.base = base
self.image_helper = Helper(image_proxy_class, image_proxy_kwargs)
self.member_helper = Helper(member_proxy_class, member_proxy_kwargs)
def new_image_member(self, image, member_id):
base_image = self.image_helper.unproxy(image)
member = self.base.new_image_member(base_image, member_id)
return self.member_helper.proxy(member)
def new_image_member(self, image, member, **kwargs):
return self.helper.proxy(self.base.new_image_member(image,
member,
**kwargs))
class Image(object):
@ -168,8 +197,17 @@ class Image(object):
def get_data(self, *args, **kwargs):
return self.base.get_data(*args, **kwargs)
def get_member_repo(self):
return self.helper.proxy(self.base.get_member_repo())
class ImageMember(object):
def __init__(self, base):
self.base = base
id = _proxy('base', 'id')
image_id = _proxy('base', 'image_id')
member_id = _proxy('base', 'member_id')
status = _proxy('base', 'status')
created_at = _proxy('base', 'created_at')
updated_at = _proxy('base', 'updated_at')
class Task(object):

View File

@ -89,6 +89,20 @@ class Gateway(object):
return authorized_image_repo
def get_member_repo(self, image, context):
image_member_repo = glance.db.ImageMemberRepo(
context, self.db_api, image)
store_image_repo = glance.location.ImageMemberRepoProxy(
image_member_repo, image, context, self.store_api)
policy_member_repo = policy.ImageMemberRepoProxy(
store_image_repo, image, context, self.policy)
notifier_member_repo = glance.notifier.ImageMemberRepoProxy(
policy_member_repo, image, context, self.notifier)
authorized_member_repo = authorization.ImageMemberRepoProxy(
notifier_member_repo, image, context)
return authorized_member_repo
def get_task_factory(self, context):
task_factory = glance.domain.TaskFactory()
policy_task_factory = policy.TaskFactoryProxy(

View File

@ -45,11 +45,16 @@ class ImageRepoProxy(glance.domain.proxy.Repo):
item_proxy_class=ImageProxy,
item_proxy_kwargs=proxy_kwargs)
self.db_api = glance.db.get_api()
def _set_acls(self, image):
public = image.visibility == 'public'
member_ids = []
if image.locations and not public:
member_repo = image.get_member_repo()
member_repo = _get_member_repo_for_store(image,
self.context,
self.db_api,
self.store_api)
member_ids = [m.member_id for m in member_repo.list()]
for location in image.locations:
self.store_api.set_acls(location['url'], public=public,
@ -67,6 +72,15 @@ class ImageRepoProxy(glance.domain.proxy.Repo):
return result
def _get_member_repo_for_store(image, context, db_api, store_api):
image_member_repo = glance.db.ImageMemberRepo(
context, db_api, image)
store_image_repo = glance.location.ImageMemberRepoProxy(
image_member_repo, image, context, store_api)
return store_image_repo
def _check_location_uri(context, store_api, store_utils, uri):
"""Check if an image location is valid.

View File

@ -133,6 +133,21 @@ def format_image_notification(image):
}
def format_image_member_notification(image_member):
"""Given a glance.domain.ImageMember object, return a dictionary of relevant
notification information.
"""
return {
'image_id': image_member.image_id,
'member_id': image_member.member_id,
'status': image_member.status,
'created_at': timeutils.isotime(image_member.created_at),
'updated_at': timeutils.isotime(image_member.updated_at),
'deleted': False,
'deleted_at': None,
}
def format_task_notification(task):
# NOTE(nikhil): input is not passed to the notifier payload as it may
# contain sensitive info.
@ -436,6 +451,11 @@ class ImageProxy(NotificationProxy, domain_proxy.Image):
self.send_notification('image.activate', self.repo)
class ImageMemberProxy(NotificationProxy, domain_proxy.ImageMember):
def get_super_class(self):
return domain_proxy.ImageMember
class ImageFactoryProxy(NotificationFactoryProxy, domain_proxy.ImageFactory):
def get_super_class(self):
return domain_proxy.ImageFactory
@ -469,6 +489,43 @@ class ImageRepoProxy(NotificationRepoProxy, domain_proxy.Repo):
})
class ImageMemberRepoProxy(NotificationBase, domain_proxy.MemberRepo):
def __init__(self, repo, image, context, notifier):
self.repo = repo
self.image = image
self.context = context
self.notifier = notifier
proxy_kwargs = {'context': self.context, 'notifier': self.notifier}
proxy_class = self.get_proxy_class()
super_class = self.get_super_class()
super_class.__init__(self, image, repo, proxy_class, proxy_kwargs)
def get_super_class(self):
return domain_proxy.MemberRepo
def get_proxy_class(self):
return ImageMemberProxy
def get_payload(self, obj):
return format_image_member_notification(obj)
def save(self, member, from_state=None):
super(ImageMemberRepoProxy, self).save(member, from_state=from_state)
self.send_notification('image.member.update', member)
def add(self, member):
super(ImageMemberRepoProxy, self).add(member)
self.send_notification('image.member.create', member)
def remove(self, member):
super(ImageMemberRepoProxy, self).remove(member)
self.send_notification('image.member.delete', member, extra_payload={
'deleted': True, 'deleted_at': timeutils.isotime()
})
class TaskProxy(NotificationProxy, domain_proxy.Task):
def get_super_class(self):
return domain_proxy.Task

View File

@ -169,8 +169,8 @@ class ImageMemberFactoryProxy(glance.domain.proxy.ImageMembershipFactory):
'store_utils': store_utils}
super(ImageMemberFactoryProxy, self).__init__(
member_factory,
image_proxy_class=ImageProxy,
image_proxy_kwargs=proxy_kwargs)
proxy_class=ImageMemberProxy,
proxy_kwargs=proxy_kwargs)
def _enforce_image_member_quota(self, image):
if CONF.image_member_quota < 0:
@ -368,3 +368,13 @@ class ImageProxy(glance.domain.proxy.Image):
def added_new_properties(self):
current_props = set(self.image.extra_properties.keys())
return bool(current_props.difference(self.orig_props))
class ImageMemberProxy(glance.domain.proxy.ImageMember):
def __init__(self, image_member, context, db_api, store_utils):
self.image_member = image_member
self.context = context
self.db_api = db_api
self.store_utils = store_utils
super(ImageMemberProxy, self).__init__(image_member)

View File

@ -220,8 +220,7 @@ class TestImageMembershipFactory(test_utils.BaseTestCase):
def test_proxy_wrapped_membership(self):
proxy_factory = proxy.ImageMembershipFactory(
self.factory, member_proxy_class=FakeProxy,
member_proxy_kwargs={'a': 1})
self.factory, proxy_class=FakeProxy, proxy_kwargs={'a': 1})
self.factory.result = 'tyrion'
membership = proxy_factory.new_image_member('jaime', 'cersei')
self.assertIsInstance(membership, FakeProxy)
@ -232,12 +231,12 @@ class TestImageMembershipFactory(test_utils.BaseTestCase):
def test_proxy_wrapped_image(self):
proxy_factory = proxy.ImageMembershipFactory(
self.factory, image_proxy_class=FakeProxy)
self.factory, proxy_class=FakeProxy)
self.factory.result = 'tyrion'
image = FakeProxy('jaime')
membership = proxy_factory.new_image_member(image, 'cersei')
self.assertEqual('tyrion', membership)
self.assertEqual('jaime', self.factory.image)
self.assertIsInstance(membership, FakeProxy)
self.assertIsInstance(self.factory.image, FakeProxy)
self.assertEqual('cersei', self.factory.member_id)
def test_proxy_both_wrapped(self):
@ -246,9 +245,8 @@ class TestImageMembershipFactory(test_utils.BaseTestCase):
proxy_factory = proxy.ImageMembershipFactory(
self.factory,
member_proxy_class=FakeProxy,
member_proxy_kwargs={'b': 2},
image_proxy_class=FakeProxy2)
proxy_class=FakeProxy,
proxy_kwargs={'b': 2})
self.factory.result = 'tyrion'
image = FakeProxy2('jaime')
@ -256,7 +254,7 @@ class TestImageMembershipFactory(test_utils.BaseTestCase):
self.assertIsInstance(membership, FakeProxy)
self.assertEqual('tyrion', membership.base)
self.assertEqual({'b': 2}, membership.kwargs)
self.assertEqual('jaime', self.factory.image)
self.assertIsInstance(self.factory.image, FakeProxy2)
self.assertEqual('cersei', self.factory.member_id)
@ -264,29 +262,6 @@ class FakeImage(object):
def __init__(self, result=None):
self.result = result
def get_member_repo(self):
return self.result
class TestImage(test_utils.BaseTestCase):
def setUp(self):
super(TestImage, self).setUp()
self.image = FakeImage()
def test_normal_member_repo(self):
proxy_image = proxy.Image(self.image)
self.image.result = 'mormont'
self.assertEqual('mormont', proxy_image.get_member_repo())
def test_proxied_member_repo(self):
proxy_image = proxy.Image(self.image,
member_repo_proxy_class=FakeProxy,
member_repo_proxy_kwargs={'a': 10})
self.image.result = 'corn'
member_repo = proxy_image.get_member_repo()
self.assertIsInstance(member_repo, FakeProxy)
self.assertEqual('corn', member_repo.base)
class TestTaskFactory(test_utils.BaseTestCase):
def setUp(self):

View File

@ -66,6 +66,23 @@ class ImageRepoStub(object):
return ['images_from_list']
class ImageMemberRepoStub(object):
def remove(self, *args, **kwargs):
return 'image_member_from_remove'
def save(self, *args, **kwargs):
return 'image_member_from_save'
def add(self, *args, **kwargs):
return 'image_member_from_add'
def get(self, *args, **kwargs):
return 'image_member_from_get'
def list(self, *args, **kwargs):
return ['image_members_from_list']
class TaskStub(glance.domain.TaskStub):
def run(self, executor):
pass
@ -394,6 +411,91 @@ class TestImageNotifications(utils.BaseTestCase):
self.assertIn('Failed', output_log['payload'])
class TestImageMemberNotifications(utils.BaseTestCase):
"""Test Image Member Notifications work"""
def setUp(self):
super(TestImageMemberNotifications, self).setUp()
self.context = glance.context.RequestContext(tenant=TENANT2,
user=USER1)
self.notifier = unit_test_utils.FakeNotifier()
self.image = ImageStub(
image_id=UUID1, name='image-1', status='active', size=1024,
created_at=DATETIME, updated_at=DATETIME, owner=TENANT1,
visibility='public', container_format='ami',
tags=['one', 'two'], disk_format='ami', min_ram=128,
min_disk=10, checksum='ca425b88f047ce8ec45ee90e813ada91',
locations=['http://127.0.0.1'])
self.image_member = glance.domain.ImageMembership(
id=1, image_id=UUID1, member_id=TENANT1, created_at=DATETIME,
updated_at=DATETIME, status='accepted')
self.image_member_repo_stub = ImageMemberRepoStub()
self.image_member_repo_proxy = glance.notifier.ImageMemberRepoProxy(
self.image_member_repo_stub, self.image,
self.context, self.notifier)
self.image_member_proxy = glance.notifier.ImageMemberProxy(
self.image_member, self.context, self.notifier)
def _assert_image_member_with_notifier(self, output_log, deleted=False):
self.assertEqual(self.image_member.member_id,
output_log['payload']['member_id'])
self.assertEqual(self.image_member.image_id,
output_log['payload']['image_id'])
self.assertEqual(self.image_member.status,
output_log['payload']['status'])
self.assertEqual(timeutils.isotime(self.image_member.created_at),
output_log['payload']['created_at'])
self.assertEqual(timeutils.isotime(self.image_member.updated_at),
output_log['payload']['updated_at'])
if deleted:
self.assertTrue(output_log['payload']['deleted'])
self.assertIsNotNone(output_log['payload']['deleted_at'])
else:
self.assertFalse(output_log['payload']['deleted'])
self.assertIsNone(output_log['payload']['deleted_at'])
def test_image_member_add_notification(self):
self.image_member_repo_proxy.add(self.image_member_proxy)
output_logs = self.notifier.get_logs()
self.assertEqual(1, len(output_logs))
output_log = output_logs[0]
self.assertEqual('INFO', output_log['notification_type'])
self.assertEqual('image.member.create', output_log['event_type'])
self._assert_image_member_with_notifier(output_log)
def test_image_member_save_notification(self):
self.image_member_repo_proxy.save(self.image_member_proxy)
output_logs = self.notifier.get_logs()
self.assertEqual(1, len(output_logs))
output_log = output_logs[0]
self.assertEqual('INFO', output_log['notification_type'])
self.assertEqual('image.member.update', output_log['event_type'])
self._assert_image_member_with_notifier(output_log)
def test_image_member_delete_notification(self):
self.image_member_repo_proxy.remove(self.image_member_proxy)
output_logs = self.notifier.get_logs()
self.assertEqual(1, len(output_logs))
output_log = output_logs[0]
self.assertEqual('INFO', output_log['notification_type'])
self.assertEqual('image.member.delete', output_log['event_type'])
self._assert_image_member_with_notifier(output_log, deleted=True)
def test_image_member_get(self):
image_member = self.image_member_repo_proxy.get(TENANT1)
self.assertIsInstance(image_member, glance.notifier.ImageMemberProxy)
self.assertEqual('image_member_from_get', image_member.repo)
def test_image_member_list(self):
image_members = self.image_member_repo_proxy.list()
self.assertIsInstance(image_members[0],
glance.notifier.ImageMemberProxy)
self.assertEqual('image_members_from_list', image_members[0].repo)
class TestTaskNotifications(utils.BaseTestCase):
"""Test Task Notifications work"""

View File

@ -349,8 +349,10 @@ class TestMemberPolicy(test_utils.BaseTestCase):
def setUp(self):
self.policy = mock.Mock()
self.policy.enforce = mock.Mock()
self.image_stub = ImageStub(UUID1)
image = glance.api.policy.ImageProxy(self.image_stub, {}, self.policy)
self.member_repo = glance.api.policy.ImageMemberRepoProxy(
MemberRepoStub(), {}, self.policy)
MemberRepoStub(), image, {}, self.policy)
self.target = self.member_repo.target
super(TestMemberPolicy, self).setUp()

View File

@ -611,7 +611,7 @@ class TestImageMemberQuotas(test_utils.BaseTestCase):
self.image_member_factory.new_image_member(self.image,
'fake_id')
nim = self.base_image_member_factory.new_image_member
nim .assert_called_once_with(self.image.base, 'fake_id')
nim.assert_called_once_with(self.image, 'fake_id')
def test_new_image_member_unlimited_members(self):
self.config(image_member_quota=-1)
@ -619,7 +619,7 @@ class TestImageMemberQuotas(test_utils.BaseTestCase):
self.image_member_factory.new_image_member(self.image,
'fake_id')
nim = self.base_image_member_factory.new_image_member
nim.assert_called_once_with(self.image.base, 'fake_id')
nim.assert_called_once_with(self.image, 'fake_id')
def test_new_image_member_too_many_members(self):
self.config(image_member_quota=0)

View File

@ -741,6 +741,18 @@ class TestStoreImageRepo(utils.BaseTestCase):
self.image_repo = glance.location.ImageRepoProxy(self.image_repo_stub,
{}, self.store_api,
store_utils)
patcher = mock.patch("glance.location._get_member_repo_for_store",
self.get_fake_member_repo)
patcher.start()
self.addCleanup(patcher.stop)
self.fake_member_repo = FakeMemberRepo(self.image, [TENANT1, TENANT2])
self.image_member_repo = glance.location.ImageMemberRepoProxy(
self.fake_member_repo,
self.image,
{}, self.store_api)
def get_fake_member_repo(self, image, context, db_api, store_api):
return FakeMemberRepo(self.image, [TENANT1, TENANT2])
def test_add_updates_acls(self):
self.image_stub.locations = [{'url': 'foo', 'metadata': {},
@ -794,10 +806,9 @@ class TestStoreImageRepo(utils.BaseTestCase):
self.image_stub.locations = [{'url': 'glug', 'metadata': {},
'status': 'active'}]
self.image_stub.visibility = 'private'
member_repo = self.image.get_member_repo()
membership = glance.domain.ImageMembership(
UUID1, TENANT3, None, None, status='accepted')
member_repo.add(membership)
self.image_member_repo.add(membership)
self.assertIn('glug', self.store_api.acls)
acls = self.store_api.acls['glug']
self.assertFalse(acls['public'])
@ -808,10 +819,9 @@ class TestStoreImageRepo(utils.BaseTestCase):
self.image_stub.locations = [{'url': 'glug', 'metadata': {},
'status': 'active'}]
self.image_stub.visibility = 'private'
member_repo = self.image.get_member_repo()
membership = glance.domain.ImageMembership(
UUID1, TENANT1, None, None, status='accepted')
member_repo.remove(membership)
self.image_member_repo.remove(membership)
self.assertIn('glug', self.store_api.acls)
acls = self.store_api.acls['glug']
self.assertFalse(acls['public'])