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:
parent
3597718978
commit
ffcf343198
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
|
@ -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())
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
|
@ -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'
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue