Refactor leaky abstractions

Prior to this change, it was common for a domain layer that was wrapping
Image objects returned by methods to neglect to unwrap the objects on
the way in to other methods.

This change fixes that by making proxy base classes less leaky and
inheriting from them in the various domain layers.

Change-Id: I22866cdd800c4c95b43c92762ead3775cffeaa80
This commit is contained in:
Mark J. Washenberger 2013-02-28 14:48:42 -08:00
parent 3597718978
commit ffcf343198
12 changed files with 545 additions and 204 deletions

View File

@ -14,7 +14,7 @@
# under the License.
from glance.common import exception
import glance.domain
import glance.domain.proxy
def is_image_mutable(context, image):
@ -53,15 +53,18 @@ def proxy_member(context, member):
return ImmutableMemberProxy(member)
class ImageRepoProxy(glance.domain.ImageRepoProxy):
class ImageRepoProxy(glance.domain.proxy.Repo):
def __init__(self, image_repo, context):
self.context = context
self.image_repo = image_repo
super(ImageRepoProxy, self).__init__(image_repo)
proxy_kwargs = {'context': self.context}
super(ImageRepoProxy, self).__init__(image_repo,
item_proxy_class=ImageProxy,
item_proxy_kwargs=proxy_kwargs)
def get(self, *args, **kwargs):
image = self.image_repo.get(*args, **kwargs)
def get(self, image_id):
image = self.image_repo.get(image_id)
return proxy_image(self.context, image)
def list(self, *args, **kwargs):
@ -69,7 +72,7 @@ class ImageRepoProxy(glance.domain.ImageRepoProxy):
return [proxy_image(self.context, i) for i in images]
class ImageMembershipRepoProxy(glance.domain.ImageMembershipRepoProxy):
class ImageMembershipRepoProxy(glance.domain.proxy.Repo):
def __init__(self, member_repo, context):
self.context = context
@ -125,11 +128,15 @@ class ImageMembershipRepoProxy(glance.domain.ImageMembershipRepoProxy):
raise exception.Forbidden(message % image_member.member_id)
class ImageFactoryProxy(object):
class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
def __init__(self, image_factory, context):
self.image_factory = image_factory
self.context = context
kwargs = {'context': self.context}
super(ImageFactoryProxy, self).__init__(image_factory,
proxy_class=ImageProxy,
proxy_kwargs=kwargs)
def new_image(self, **kwargs):
owner = kwargs.pop('owner', self.context.owner)
@ -140,7 +147,7 @@ class ImageFactoryProxy(object):
"owned by '%s'.")
raise exception.Forbidden(message % owner)
return self.image_factory.new_image(owner=owner, **kwargs)
return super(ImageFactoryProxy, self).new_image(owner=owner, **kwargs)
class ImageMemberFactoryProxy(object):
@ -286,7 +293,7 @@ class ImmutableMemberProxy(object):
updated_at = _immutable_attr('base', 'updated_at')
class ImageProxy(glance.domain.ImageProxy):
class ImageProxy(glance.domain.proxy.Image):
def __init__(self, image, context):
self.image = image

View File

@ -23,7 +23,7 @@ import os.path
from oslo.config import cfg
from glance.common import exception
import glance.domain
import glance.domain.proxy
import glance.openstack.common.log as logging
from glance.openstack.common import policy
@ -142,70 +142,73 @@ class Enforcer(object):
return self._check(context, action, target)
class ImageRepoProxy(glance.domain.ImageRepoProxy):
class ImageRepoProxy(glance.domain.proxy.Repo):
def __init__(self, context, policy, image_repo):
self._context = context
self._policy = policy
self._image_repo = image_repo
super(ImageRepoProxy, self).__init__(image_repo)
def __init__(self, image_repo, context, policy):
self.context = context
self.policy = policy
self.image_repo = image_repo
proxy_kwargs = {'context': self.context, 'policy': self.policy}
super(ImageRepoProxy, self).__init__(image_repo,
item_proxy_class=ImageProxy,
item_proxy_kwargs=proxy_kwargs)
def get(self, *args, **kwargs):
self._policy.enforce(self._context, 'get_image', {})
image = self._image_repo.get(*args, **kwargs)
return ImageProxy(image, self._context, self._policy)
def get(self, image_id):
self.policy.enforce(self.context, 'get_image', {})
return super(ImageRepoProxy, self).get(image_id)
def list(self, *args, **kwargs):
self._policy.enforce(self._context, 'get_images', {})
images = self._image_repo.list(*args, **kwargs)
return [ImageProxy(i, self._context, self._policy)
for i in images]
self.policy.enforce(self.context, 'get_images', {})
return super(ImageRepoProxy, self).list(*args, **kwargs)
def save(self, *args, **kwargs):
self._policy.enforce(self._context, 'modify_image', {})
return self._image_repo.save(*args, **kwargs)
def save(self, image):
self.policy.enforce(self.context, 'modify_image', {})
return super(ImageRepoProxy, self).save(image)
def add(self, *args, **kwargs):
self._policy.enforce(self._context, 'add_image', {})
return self._image_repo.add(*args, **kwargs)
def add(self, image):
self.policy.enforce(self.context, 'add_image', {})
return super(ImageRepoProxy, self).add(image)
class ImageProxy(glance.domain.ImageProxy):
class ImageProxy(glance.domain.proxy.Image):
def __init__(self, image, context, policy):
self._image = image
self._context = context
self._policy = policy
self.image = image
self.context = context
self.policy = policy
super(ImageProxy, self).__init__(image)
@property
def visibility(self):
return self._image.visibility
return self.image.visibility
@visibility.setter
def visibility(self, value):
if value == 'public':
self._policy.enforce(self._context, 'publicize_image', {})
self._image.visibility = value
self.policy.enforce(self.context, 'publicize_image', {})
self.image.visibility = value
def delete(self):
self._policy.enforce(self._context, 'delete_image', {})
return self._image.delete()
self.policy.enforce(self.context, 'delete_image', {})
return self.image.delete()
def get_data(self, *args, **kwargs):
self._policy.enforce(self._context, 'download_image', {})
return self._image.get_data(*args, **kwargs)
self.policy.enforce(self.context, 'download_image', {})
return self.image.get_data(*args, **kwargs)
class ImageFactoryProxy(object):
class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
def __init__(self, image_factory, context, policy):
self.image_factory = image_factory
self.context = context
self.policy = policy
proxy_kwargs = {'context': self.context, 'policy': self.policy}
super(ImageFactoryProxy, self).__init__(image_factory,
proxy_class=ImageProxy,
proxy_kwargs=proxy_kwargs)
def new_image(self, **kwargs):
if kwargs.get('visibility') == 'public':
self.policy.enforce(self.context, 'publicize_image', {})
image = self.image_factory.new_image(**kwargs)
return image
return super(ImageFactoryProxy, self).new_image(**kwargs)

View File

@ -19,9 +19,9 @@
from oslo.config import cfg
from glance.api import authorization
from glance.common import exception
import glance.domain
import glance.domain.proxy
from glance.openstack.common import importutils
sql_connection_opt = cfg.StrOpt('sql_connection',
@ -174,7 +174,7 @@ class ImageRepo(object):
image.updated_at = new_values['updated_at']
class ImageProxy(glance.domain.ImageProxy):
class ImageProxy(glance.domain.proxy.Image):
def __init__(self, image, context, db_api):
self.context = context
@ -230,7 +230,6 @@ class ImageMemberRepo(object):
return self._format_image_member_from_db(new_values)
def remove(self, image_member):
image_member_values = self._format_image_member_to_db(image_member)
try:
self.db_api.image_member_delete(self.context, image_member.id)
except (exception.NotFound, exception.Forbidden):

View File

@ -118,76 +118,6 @@ class Image(object):
raise NotImplementedError()
def _proxy(target, attr):
def get_attr(self):
return getattr(getattr(self, target), attr)
def set_attr(self, value):
return setattr(getattr(self, target), attr, value)
def del_attr(self):
return delattr(getattr(self, target), attr)
return property(get_attr, set_attr, del_attr)
class ImageRepoProxy(object):
def __init__(self, base):
self.base = base
def get(self, image_id):
return self.base.get(image_id)
def list(self, *args, **kwargs):
return self.base.list(*args, **kwargs)
def add(self, image):
return self.base.add(image)
def save(self, image):
return self.base.save(image)
def remove(self, image):
return self.base.remove(image)
class ImageProxy(object):
def __init__(self, base):
self.base = base
name = _proxy('base', 'name')
image_id = _proxy('base', 'image_id')
name = _proxy('base', 'name')
status = _proxy('base', 'status')
created_at = _proxy('base', 'created_at')
updated_at = _proxy('base', 'updated_at')
visibility = _proxy('base', 'visibility')
min_disk = _proxy('base', 'min_disk')
min_ram = _proxy('base', 'min_ram')
protected = _proxy('base', 'protected')
locations = _proxy('base', 'locations')
checksum = _proxy('base', 'checksum')
owner = _proxy('base', 'owner')
disk_format = _proxy('base', 'disk_format')
container_format = _proxy('base', 'container_format')
size = _proxy('base', 'size')
extra_properties = _proxy('base', 'extra_properties')
tags = _proxy('base', 'tags')
def delete(self):
self.base.delete()
def set_data(self, data, size=None):
self.base.set_data(data, size)
def get_data(self):
return self.base.get_data()
def get_member_repo(self):
return self.base.get_member_repo()
class ImageMembership(object):
def __init__(self, image_id, member_id, created_at, updated_at,
@ -220,24 +150,3 @@ class ImageMemberFactory(object):
return ImageMembership(image_id=image.image_id, member_id=member_id,
created_at=created_at, updated_at=updated_at,
status='pending')
class ImageMembershipRepoProxy(object):
def __init__(self, base):
self.base = base
def get(self, image_id):
return self.base.get(image_id)
def list(self, *args, **kwargs):
return self.base.list(*args, **kwargs)
def add(self, image_member):
return self.base.add(image_member)
def save(self, image_member):
return self.base.save(image_member)
def remove(self, image_member):
return self.base.remove(image_member)

132
glance/domain/proxy.py Normal file
View File

@ -0,0 +1,132 @@
# Copyright 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
def _proxy(target, attr):
def get_attr(self):
return getattr(getattr(self, target), attr)
def set_attr(self, value):
return setattr(getattr(self, target), attr, value)
def del_attr(self):
return delattr(getattr(self, target), attr)
return property(get_attr, set_attr, del_attr)
class Helper(object):
def __init__(self, proxy_class=None, proxy_kwargs=None):
self.proxy_class = proxy_class
self.proxy_kwargs = proxy_kwargs or {}
def proxy(self, obj):
if obj is None or self.proxy_class is None:
return obj
return self.proxy_class(obj, **self.proxy_kwargs)
def unproxy(self, obj):
if self.proxy_class is None:
return obj
return obj.base
class Repo(object):
def __init__(self, base, item_proxy_class=None, item_proxy_kwargs=None):
self.base = base
self.helper = Helper(item_proxy_class, item_proxy_kwargs)
def get(self, item_id):
return self.helper.proxy(self.base.get(item_id))
def list(self, *args, **kwargs):
items = self.base.list(*args, **kwargs)
return [self.helper.proxy(item) for item in items]
def add(self, item):
base_item = self.helper.unproxy(item)
result = self.base.add(base_item)
return self.helper.proxy(result)
def save(self, item):
base_item = self.helper.unproxy(item)
result = self.base.save(base_item)
return self.helper.proxy(result)
def remove(self, item):
base_item = self.helper.unproxy(item)
result = self.base.remove(base_item)
return self.helper.proxy(result)
class ImageFactory(object):
def __init__(self, base, proxy_class=None, proxy_kwargs=None):
self.helper = Helper(proxy_class, proxy_kwargs)
self.base = base
def new_image(self, **kwargs):
return self.helper.proxy(self.base.new_image(**kwargs))
class ImageMembershipFactory(object):
def __init__(self, base, image_proxy_class=None, image_proxy_kwargs=None,
member_proxy_class=None, member_proxy_kwargs=None):
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)
class Image(object):
def __init__(self, base, member_repo_proxy_class=None,
member_repo_proxy_kwargs=None):
self.base = base
self.helper = Helper(member_repo_proxy_class,
member_repo_proxy_kwargs)
name = _proxy('base', 'name')
image_id = _proxy('base', 'image_id')
name = _proxy('base', 'name')
status = _proxy('base', 'status')
created_at = _proxy('base', 'created_at')
updated_at = _proxy('base', 'updated_at')
visibility = _proxy('base', 'visibility')
min_disk = _proxy('base', 'min_disk')
min_ram = _proxy('base', 'min_ram')
protected = _proxy('base', 'protected')
locations = _proxy('base', 'locations')
checksum = _proxy('base', 'checksum')
owner = _proxy('base', 'owner')
disk_format = _proxy('base', 'disk_format')
container_format = _proxy('base', 'container_format')
size = _proxy('base', 'size')
extra_properties = _proxy('base', 'extra_properties')
tags = _proxy('base', 'tags')
def delete(self):
self.base.delete()
def set_data(self, data, size=None):
self.base.set_data(data, size)
def get_data(self):
return self.base.get_data()
def get_member_repo(self):
return self.helper.proxy(self.base.get_member_repo())

View File

@ -32,10 +32,14 @@ class Gateway(object):
def get_image_factory(self, context):
image_factory = glance.domain.ImageFactory()
store_image_factory = glance.store.ImageFactoryProxy(
image_factory, context, self.store_api)
policy_image_factory = policy.ImageFactoryProxy(
image_factory, context, self.policy)
store_image_factory, context, self.policy)
notifier_image_factory = glance.notifier.ImageFactoryProxy(
policy_image_factory, context, self.notifier)
authorized_image_factory = authorization.ImageFactoryProxy(
policy_image_factory, context)
notifier_image_factory, context)
return authorized_image_factory
def get_image_member_factory(self, context):
@ -47,9 +51,9 @@ class Gateway(object):
def get_repo(self, context):
image_repo = glance.db.ImageRepo(context, self.db_api)
store_image_repo = glance.store.ImageRepoProxy(
context, self.store_api, image_repo)
image_repo, context, self.store_api)
policy_image_repo = policy.ImageRepoProxy(
context, self.policy, store_image_repo)
store_image_repo, context, self.policy)
notifier_image_repo = glance.notifier.ImageRepoProxy(
policy_image_repo, context, self.notifier)
authorized_image_repo = authorization.ImageRepoProxy(

View File

@ -23,6 +23,7 @@ from oslo.config import cfg
from glance.common import exception
import glance.domain
import glance.domain.proxy
from glance.openstack.common import importutils
import glance.openstack.common.log as logging
from glance.openstack.common import timeutils
@ -117,39 +118,42 @@ def format_image_notification(image):
}
class ImageRepoProxy(glance.domain.ImageRepoProxy):
class ImageRepoProxy(glance.domain.proxy.Repo):
def __init__(self, image_repo, context, notifier):
self.image_repo = image_repo
self.context = context
self.notifier = notifier
super(ImageRepoProxy, self).__init__(image_repo)
proxy_kwargs = {'context': self.context, 'notifier': self.notifier}
super(ImageRepoProxy, self).__init__(image_repo,
item_proxy_class=ImageProxy,
item_proxy_kwargs=proxy_kwargs)
def save(self, image):
self.image_repo.save(image)
super(ImageRepoProxy, self).save(image)
self.notifier.info('image.update', format_image_notification(image))
def add(self, image):
self.image_repo.add(image)
super(ImageRepoProxy, self).add(image)
self.notifier.info('image.create', format_image_notification(image))
def remove(self, image):
self.image_repo.remove(image)
super(ImageRepoProxy, self).remove(image)
payload = format_image_notification(image)
payload['deleted'] = True
payload['deleted_at'] = timeutils.isotime()
self.notifier.info('image.delete', payload)
def get(self, *args, **kwargs):
image = self.image_repo.get(*args, **kwargs)
return ImageProxy(image, self.context, self.notifier)
def list(self, *args, **kwargs):
images = self.image_repo.list(*args, **kwargs)
return [ImageProxy(i, self.context, self.notifier) for i in images]
class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
def __init__(self, factory, context, notifier):
kwargs = {'context': context, 'notifier': notifier}
super(ImageFactoryProxy, self).__init__(factory,
proxy_class=ImageProxy,
proxy_kwargs=kwargs)
class ImageProxy(glance.domain.ImageProxy):
class ImageProxy(glance.domain.proxy.Image):
def __init__(self, image, context, notifier):
self.image = image

View File

@ -25,7 +25,7 @@ from glance.common import crypt
from glance.common import exception
from glance.common import utils
import glance.context
import glance.domain
import glance.domain.proxy
from glance.openstack.common import importutils
import glance.openstack.common.log as logging
from glance.store import location
@ -304,25 +304,24 @@ def set_acls(context, location_uri, public=False, read_tenants=[],
LOG.debug(_("Skipping store.set_acls... not implemented."))
class ImageRepoProxy(glance.domain.ImageRepoProxy):
class ImageRepoProxy(glance.domain.proxy.Repo):
def __init__(self, context, store_api, image_repo):
self.context = context
self.store_api = store_api
self.image_repo = image_repo
super(ImageRepoProxy, self).__init__(image_repo)
def get(self, *args, **kwargs):
image = self.image_repo.get(*args, **kwargs)
return ImageProxy(image, self.context, self.store_api)
def list(self, *args, **kwargs):
images = self.image_repo.list(*args, **kwargs)
return [ImageProxy(i, self.context, self.store_api)
for i in images]
def __init__(self, image_repo, context, store_api):
proxy_kwargs = {'context': context, 'store_api': store_api}
super(ImageRepoProxy, self).__init__(image_repo,
item_proxy_class=ImageProxy,
item_proxy_kwargs=proxy_kwargs)
class ImageProxy(glance.domain.ImageProxy):
class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
def __init__(self, factory, context, store_api):
proxy_kwargs = {'context': context, 'store_api': store_api}
super(ImageFactoryProxy, self).__init__(factory,
proxy_class=ImageProxy,
proxy_kwargs=proxy_kwargs)
class ImageProxy(glance.domain.proxy.Image):
def __init__(self, image, context, store_api):
self.image = image

View File

@ -0,0 +1,281 @@
# Copyright 2013 OpenStack Foundation.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from glance.domain import proxy
import glance.tests.utils as test_utils
UUID1 = 'c80a1a6c-bd1f-41c5-90ee-81afedb1d58d'
TENANT1 = '6838eb7b-6ded-434a-882c-b344c77fe8df'
class FakeProxy(object):
def __init__(self, base, *args, **kwargs):
self.base = base
self.args = args
self.kwargs = kwargs
class FakeRepo(object):
def __init__(self, result=None):
self.args = None
self.kwargs = None
self.result = result
def fake_method(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
return self.result
get = fake_method
list = fake_method
add = fake_method
save = fake_method
remove = fake_method
class TestProxyRepoPlain(test_utils.BaseTestCase):
def setUp(self):
super(TestProxyRepoPlain, self).setUp()
self.fake_repo = FakeRepo()
self.proxy_repo = proxy.Repo(self.fake_repo)
def _test_method(self, name, base_result, *args, **kwargs):
self.fake_repo.result = base_result
method = getattr(self.proxy_repo, name)
proxy_result = method(*args, **kwargs)
self.assertEqual(proxy_result, base_result)
self.assertEqual(self.fake_repo.args, args)
self.assertEqual(self.fake_repo.kwargs, kwargs)
def test_get(self):
self._test_method('get', 'snarf', 'abcd')
def test_list(self):
self._test_method('list', ['sniff', 'snarf'], 2, filter='^sn')
def test_add(self):
self._test_method('add', 'snuff', 'enough')
def test_save(self):
self._test_method('save', 'snuff', 'enough')
def test_remove(self):
self._test_method('add', None, 'flying')
class TestProxyRepoWrapping(test_utils.BaseTestCase):
def setUp(self):
super(TestProxyRepoWrapping, self).setUp()
self.fake_repo = FakeRepo()
self.proxy_repo = proxy.Repo(self.fake_repo,
item_proxy_class=FakeProxy,
item_proxy_kwargs={'a': 1})
def _test_method(self, name, base_result, *args, **kwargs):
self.fake_repo.result = base_result
method = getattr(self.proxy_repo, name)
proxy_result = method(*args, **kwargs)
self.assertTrue(isinstance(proxy_result, FakeProxy))
self.assertEquals(proxy_result.base, base_result)
self.assertEquals(len(proxy_result.args), 0)
self.assertEquals(proxy_result.kwargs, {'a': 1})
self.assertEqual(self.fake_repo.args, args)
self.assertEqual(self.fake_repo.kwargs, kwargs)
def test_get(self):
self.fake_repo.result = 'snarf'
result = self.proxy_repo.get('some-id')
self.assertTrue(isinstance(result, FakeProxy))
self.assertEqual(self.fake_repo.args, ('some-id',))
self.assertEqual(self.fake_repo.kwargs, {})
self.assertEqual(result.base, 'snarf')
self.assertEqual(result.args, tuple())
self.assertEqual(result.kwargs, {'a': 1})
def test_list(self):
self.fake_repo.result = ['scratch', 'sniff']
results = self.proxy_repo.list(2, prefix='s')
self.assertEqual(self.fake_repo.args, (2,))
self.assertEqual(self.fake_repo.kwargs, {'prefix': 's'})
self.assertEqual(len(results), 2)
for i in xrange(2):
self.assertTrue(isinstance(results[i], FakeProxy))
self.assertEqual(results[i].base, self.fake_repo.result[i])
self.assertEqual(results[i].args, tuple())
self.assertEqual(results[i].kwargs, {'a': 1})
def _test_method_with_proxied_argument(self, name, result):
self.fake_repo.result = result
item = FakeProxy('snoop')
method = getattr(self.proxy_repo, name)
proxy_result = method(item)
self.assertEqual(self.fake_repo.args, ('snoop',))
self.assertEqual(self.fake_repo.kwargs, {})
if result is None:
self.assertTrue(proxy_result is None)
else:
self.assertTrue(isinstance(proxy_result, FakeProxy))
self.assertEqual(proxy_result.base, result)
self.assertEqual(proxy_result.args, tuple())
self.assertEqual(proxy_result.kwargs, {'a': 1})
def test_add(self):
self._test_method_with_proxied_argument('add', 'dog')
def test_add_with_no_result(self):
self._test_method_with_proxied_argument('add', None)
def test_save(self):
self._test_method_with_proxied_argument('save', 'dog')
def test_save_with_no_result(self):
self._test_method_with_proxied_argument('save', None)
def test_remove(self):
self._test_method_with_proxied_argument('remove', 'dog')
def test_remove_with_no_result(self):
self._test_method_with_proxied_argument('remove', None)
class FakeImageFactory(object):
def __init__(self, result=None):
self.result = None
self.kwargs = None
def new_image(self, **kwargs):
self.kwargs = kwargs
return self.result
class TestImageFactory(test_utils.BaseTestCase):
def setUp(self):
super(TestImageFactory, self).setUp()
self.factory = FakeImageFactory()
def test_proxy_plain(self):
proxy_factory = proxy.ImageFactory(self.factory)
self.factory.result = 'eddard'
image = proxy_factory.new_image(a=1, b='two')
self.assertEqual(image, 'eddard')
self.assertEqual(self.factory.kwargs, {'a': 1, 'b': 'two'})
def test_proxy_wrapping(self):
proxy_factory = proxy.ImageFactory(self.factory,
proxy_class=FakeProxy,
proxy_kwargs={'dog': 'bark'})
self.factory.result = 'stark'
image = proxy_factory.new_image(a=1, b='two')
self.assertTrue(isinstance(image, FakeProxy))
self.assertEqual(image.base, 'stark')
self.assertEqual(self.factory.kwargs, {'a': 1, 'b': 'two'})
class FakeImageMembershipFactory(object):
def __init__(self, result=None):
self.result = None
self.image = None
self.member_id = None
def new_image_member(self, image, member_id):
self.image = image
self.member_id = member_id
return self.result
class TestImageMembershipFactory(test_utils.BaseTestCase):
def setUp(self):
super(TestImageMembershipFactory, self).setUp()
self.factory = FakeImageMembershipFactory()
def test_proxy_plain(self):
proxy_factory = proxy.ImageMembershipFactory(self.factory)
self.factory.result = 'tyrion'
membership = proxy_factory.new_image_member('jaime', 'cersei')
self.assertEqual(membership, 'tyrion')
self.assertEqual(self.factory.image, 'jaime')
self.assertEqual(self.factory.member_id, 'cersei')
def test_proxy_wrapped_membership(self):
proxy_factory = proxy.ImageMembershipFactory(
self.factory, member_proxy_class=FakeProxy,
member_proxy_kwargs={'a': 1})
self.factory.result = 'tyrion'
membership = proxy_factory.new_image_member('jaime', 'cersei')
self.assertTrue(isinstance(membership, FakeProxy))
self.assertEqual(membership.base, 'tyrion')
self.assertEqual(membership.kwargs, {'a': 1})
self.assertEqual(self.factory.image, 'jaime')
self.assertEqual(self.factory.member_id, 'cersei')
def test_proxy_wrapped_image(self):
proxy_factory = proxy.ImageMembershipFactory(
self.factory, image_proxy_class=FakeProxy)
self.factory.result = 'tyrion'
image = FakeProxy('jaime')
membership = proxy_factory.new_image_member(image, 'cersei')
self.assertEqual(membership, 'tyrion')
self.assertEqual(self.factory.image, 'jaime')
self.assertEqual(self.factory.member_id, 'cersei')
def test_proxy_both_wrapped(self):
class FakeProxy2(FakeProxy):
pass
proxy_factory = proxy.ImageMembershipFactory(
self.factory,
member_proxy_class=FakeProxy,
member_proxy_kwargs={'b': 2},
image_proxy_class=FakeProxy2)
self.factory.result = 'tyrion'
image = FakeProxy2('jaime')
membership = proxy_factory.new_image_member(image, 'cersei')
self.assertTrue(isinstance(membership, FakeProxy))
self.assertEqual(membership.base, 'tyrion')
self.assertEqual(membership.kwargs, {'b': 2})
self.assertEqual(self.factory.image, 'jaime')
self.assertEqual(self.factory.member_id, 'cersei')
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(proxy_image.get_member_repo(), 'mormont')
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.assertTrue(isinstance(member_repo, FakeProxy))
self.assertEqual(member_repo.base, 'corn')

View File

@ -461,7 +461,7 @@ class TestImageNotifications(utils.BaseTestCase):
super(TestImageNotifications, self).setUp()
def test_image_save_notification(self):
self.image_repo_proxy.save(self.image)
self.image_repo_proxy.save(self.image_proxy)
output_logs = self.notifier.get_logs()
self.assertEqual(len(output_logs), 1)
output_log = output_logs[0]
@ -472,7 +472,7 @@ class TestImageNotifications(utils.BaseTestCase):
self.fail('Notification contained location field.')
def test_image_add_notification(self):
self.image_repo_proxy.add(self.image)
self.image_repo_proxy.add(self.image_proxy)
output_logs = self.notifier.get_logs()
self.assertEqual(len(output_logs), 1)
output_log = output_logs[0]
@ -483,7 +483,7 @@ class TestImageNotifications(utils.BaseTestCase):
self.fail('Notification contained location field.')
def test_image_delete_notification(self):
self.image_repo_proxy.remove(self.image)
self.image_repo_proxy.remove(self.image_proxy)
output_logs = self.notifier.get_logs()
self.assertEqual(len(output_logs), 1)
output_log = output_logs[0]
@ -585,7 +585,7 @@ class TestImageNotifications(utils.BaseTestCase):
self.assertEqual(output_log['event_type'], 'image.upload')
self.assertTrue('Modern Major General' in output_log['payload'])
def test_image_set_data_storage_full(self):
def test_image_set_data_storage_write_denied(self):
def data_iterator():
self.notifier.log = []
yield 'abcde'

View File

@ -174,64 +174,67 @@ class TestImagePolicy(test_utils.BaseTestCase):
def test_get_image_not_allowed(self):
rules = {"get_image": False}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
self.assertRaises(exception.Forbidden, image_repo.get)
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
self.assertRaises(exception.Forbidden, image_repo.get, UUID1)
def test_get_image_allowed(self):
rules = {"get_image": True}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
output = image_repo.get()
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
output = image_repo.get(UUID1)
self.assertTrue(isinstance(output, glance.api.policy.ImageProxy))
self.assertEqual(output._image, 'image_from_get')
self.assertEqual(output.image, 'image_from_get')
def test_get_images_not_allowed(self):
rules = {"get_images": False}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
self.assertRaises(exception.Forbidden, image_repo.list)
def test_get_images_allowed(self):
rules = {"get_image": True}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
images = image_repo.list()
for i, image in enumerate(images):
self.assertTrue(isinstance(image, glance.api.policy.ImageProxy))
self.assertEqual(image._image, 'image_from_list_%d' % i)
output = image_repo.get()
self.assertEqual(image.image, 'image_from_list_%d' % i)
def test_modify_image_not_allowed(self):
rules = {"modify_image": False}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
self.assertRaises(exception.Forbidden, image_repo.save)
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
image = glance.api.policy.ImageProxy(self.image_stub, {}, self.policy)
self.assertRaises(exception.Forbidden, image_repo.save, image)
def test_modify_image_allowed(self):
rules = {"modify_image": True}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
image_repo.save()
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
image = glance.api.policy.ImageProxy(self.image_stub, {}, self.policy)
image_repo.save(image)
def test_add_image_not_allowed(self):
rules = {"add_image": False}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
self.assertRaises(exception.Forbidden, image_repo.add)
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
image = glance.api.policy.ImageProxy(self.image_stub, {}, self.policy)
self.assertRaises(exception.Forbidden, image_repo.add, image)
def test_add_image_allowed(self):
rules = {"add_image": True}
self.policy.set_rules(rules)
image_repo = glance.api.policy.ImageRepoProxy({}, self.policy,
self.image_repo_stub)
image_repo.add()
image_repo = glance.api.policy.ImageRepoProxy(self.image_repo_stub,
{}, self.policy)
image = glance.api.policy.ImageProxy(self.image_stub, {}, self.policy)
image_repo.add(image)
def test_new_image_visibility(self):
rules = {'publicize_image': False}

View File

@ -96,15 +96,15 @@ class TestStoreImage(utils.BaseTestCase):
self.assertEquals(image.status, 'active')
def test_image_repo_get(self):
image_repo = glance.store.ImageRepoProxy({}, self.store_api,
self.image_repo_stub)
image_repo = glance.store.ImageRepoProxy(self.image_repo_stub,
{}, self.store_api)
image = image_repo.get(UUID1)
self.assertTrue(isinstance(image, glance.store.ImageProxy))
self.assertEqual(image.image, 'image_from_get')
def test_image_repo_list(self):
image_repo = glance.store.ImageRepoProxy({}, self.store_api,
self.image_repo_stub)
image_repo = glance.store.ImageRepoProxy(self.image_repo_stub,
{}, self.store_api)
images = image_repo.list()
for i, image in enumerate(images):
self.assertTrue(isinstance(image, glance.store.ImageProxy))