Reuse class Manager from common code
Class `Managers` from `glanceclient.common.base` module is similar to class `apiclient:ManagerWithFind` from common code. In this patch: - class glanceclient.common.base:Managers replaced by apiclient:ManagerWithFind - module glanceclient.common.base marked as 'deprecated' Related to bp common-client-library-2 Change-Id: I41da4a9188e97ca2c07b6234fc2ac0a877553d3f
This commit is contained in:
@@ -15,71 +15,21 @@
|
||||
|
||||
"""
|
||||
Base utilities to build API operation managers and objects on top of.
|
||||
|
||||
DEPRECATED post v.0.12.0. Use 'glanceclient.openstack.common.apiclient.base'
|
||||
instead of this module."
|
||||
"""
|
||||
|
||||
import copy
|
||||
import warnings
|
||||
|
||||
from glanceclient.openstack.common.apiclient import base
|
||||
|
||||
# Python 2.4 compat
|
||||
try:
|
||||
all
|
||||
except NameError:
|
||||
def all(iterable):
|
||||
return True not in (not x for x in iterable)
|
||||
|
||||
warnings.warn("The 'glanceclient.common.base' module is deprecated post "
|
||||
"v.0.12.0. Use 'glanceclient.openstack.common.apiclient.base' "
|
||||
"instead of this one.", DeprecationWarning)
|
||||
|
||||
|
||||
def getid(obj):
|
||||
"""
|
||||
Abstracts the common pattern of allowing both an object or an object's ID
|
||||
(UUID) as a parameter when dealing with relationships.
|
||||
"""
|
||||
try:
|
||||
return obj.id
|
||||
except AttributeError:
|
||||
return obj
|
||||
|
||||
|
||||
class Manager(object):
|
||||
"""
|
||||
Managers interact with a particular type of API (servers, flavors, images,
|
||||
etc.) and provide CRUD operations for them.
|
||||
"""
|
||||
resource_class = None
|
||||
|
||||
def __init__(self, api):
|
||||
self.api = api
|
||||
|
||||
def _list(self, url, response_key, obj_class=None, body=None):
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
|
||||
if obj_class is None:
|
||||
obj_class = self.resource_class
|
||||
|
||||
data = body[response_key]
|
||||
return ([obj_class(self, res, loaded=True) for res in data if res],
|
||||
resp)
|
||||
|
||||
def _delete(self, url):
|
||||
resp = self.api.raw_request('DELETE', url)
|
||||
return resp[0]
|
||||
|
||||
def _update(self, url, body, response_key=None):
|
||||
resp, body = self.api.json_request('PUT', url, body=body)
|
||||
# PUT requests may not return a body
|
||||
if body:
|
||||
return self.resource_class(self, body[response_key])
|
||||
|
||||
|
||||
class Resource(base.Resource):
|
||||
"""
|
||||
A resource represents a particular instance of an object (tenant, user,
|
||||
etc). This is pretty much just a bag for attributes.
|
||||
"""
|
||||
|
||||
def to_dict(self):
|
||||
# Note(akurilin): There is a patch in Oslo, that adds to_dict() method
|
||||
# to common Resource - I1db6c12a1f798de7f7fafd0c34fb0ef523610153.
|
||||
# When Oslo code comes, we will be in able to remove this method
|
||||
# and class at all.
|
||||
return copy.deepcopy(self._info)
|
||||
getid = base.getid
|
||||
Manager = base.ManagerWithFind
|
||||
Resource = base.Resource
|
||||
|
@@ -327,6 +327,36 @@ class HTTPClient(object):
|
||||
|
||||
return self._http_request(url, method, **kwargs)
|
||||
|
||||
def client_request(self, method, url, **kwargs):
|
||||
# NOTE(akurilin): this method provides compatibility with methods which
|
||||
# expects requests.Response object(for example - methods of
|
||||
# class Managers from common code).
|
||||
if 'json' in kwargs and 'body' not in kwargs:
|
||||
kwargs['body'] = kwargs.pop('json')
|
||||
resp, body = self.json_request(method, url, **kwargs)
|
||||
resp.json = lambda: body
|
||||
resp.content = bool(body)
|
||||
resp.status_code = resp.status
|
||||
return resp
|
||||
|
||||
def head(self, url, **kwargs):
|
||||
return self.client_request("HEAD", url, **kwargs)
|
||||
|
||||
def get(self, url, **kwargs):
|
||||
return self.client_request("GET", url, **kwargs)
|
||||
|
||||
def post(self, url, **kwargs):
|
||||
return self.client_request("POST", url, **kwargs)
|
||||
|
||||
def put(self, url, **kwargs):
|
||||
return self.client_request("PUT", url, **kwargs)
|
||||
|
||||
def delete(self, url, **kwargs):
|
||||
return self.raw_request("DELETE", url, **kwargs)
|
||||
|
||||
def patch(self, url, **kwargs):
|
||||
return self.client_request("PATCH", url, **kwargs)
|
||||
|
||||
|
||||
class OpenSSLConnectionDelegator(object):
|
||||
"""
|
||||
|
@@ -13,7 +13,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from glanceclient.common import base
|
||||
from glanceclient.openstack.common.apiclient import base
|
||||
|
||||
|
||||
class ImageMember(base.Resource):
|
||||
@@ -28,13 +28,13 @@ class ImageMember(base.Resource):
|
||||
self.manager.delete(self)
|
||||
|
||||
|
||||
class ImageMemberManager(base.Manager):
|
||||
class ImageMemberManager(base.ManagerWithFind):
|
||||
resource_class = ImageMember
|
||||
|
||||
def get(self, image, member_id):
|
||||
image_id = base.getid(image)
|
||||
url = '/v1/images/%s/members/%s' % (image_id, member_id)
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
resp, body = self.client.json_request('GET', url)
|
||||
member = body['member']
|
||||
member['image_id'] = image_id
|
||||
return ImageMember(self, member, loaded=True)
|
||||
@@ -60,7 +60,7 @@ class ImageMemberManager(base.Manager):
|
||||
def _list_by_image(self, image):
|
||||
image_id = base.getid(image)
|
||||
url = '/v1/images/%s/members' % image_id
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
resp, body = self.client.json_request('GET', url)
|
||||
out = []
|
||||
for member in body['members']:
|
||||
member['image_id'] = image_id
|
||||
@@ -70,7 +70,7 @@ class ImageMemberManager(base.Manager):
|
||||
def _list_by_member(self, member):
|
||||
member_id = base.getid(member)
|
||||
url = '/v1/shared-images/%s' % member_id
|
||||
resp, body = self.api.json_request('GET', url)
|
||||
resp, body = self.client.json_request('GET', url)
|
||||
out = []
|
||||
for member in body['shared_images']:
|
||||
member['member_id'] = member_id
|
||||
@@ -84,7 +84,7 @@ class ImageMemberManager(base.Manager):
|
||||
"""Creates an image."""
|
||||
url = '/v1/images/%s/members/%s' % (base.getid(image), member_id)
|
||||
body = {'member': {'can_share': can_share}}
|
||||
self._update(url, body=body)
|
||||
self._put(url, json=body)
|
||||
|
||||
def replace(self, image, members):
|
||||
memberships = []
|
||||
@@ -100,4 +100,4 @@ class ImageMemberManager(base.Manager):
|
||||
obj['can_share'] = member['can_share']
|
||||
memberships.append(obj)
|
||||
url = '/v1/images/%s/members' % base.getid(image)
|
||||
self.api.json_request('PUT', url, {}, {'memberships': memberships})
|
||||
self.client.json_request('PUT', url, {}, {'memberships': memberships})
|
||||
|
@@ -19,8 +19,8 @@ import json
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from glanceclient.common import base
|
||||
from glanceclient.common import utils
|
||||
from glanceclient.openstack.common.apiclient import base
|
||||
from glanceclient.openstack.common import strutils
|
||||
|
||||
UPDATE_PARAMS = ('name', 'disk_format', 'container_format', 'min_disk',
|
||||
@@ -56,9 +56,19 @@ class Image(base.Resource):
|
||||
return self.manager.data(self, **kwargs)
|
||||
|
||||
|
||||
class ImageManager(base.Manager):
|
||||
class ImageManager(base.ManagerWithFind):
|
||||
resource_class = Image
|
||||
|
||||
def _list(self, url, response_key, obj_class=None, body=None):
|
||||
resp = self.client.get(url)
|
||||
|
||||
if obj_class is None:
|
||||
obj_class = self.resource_class
|
||||
|
||||
data = resp.json()[response_key]
|
||||
return ([obj_class(self, res, loaded=True) for res in data if res],
|
||||
resp)
|
||||
|
||||
def _image_meta_from_headers(self, headers):
|
||||
meta = {'properties': {}}
|
||||
safe_decode = strutils.safe_decode
|
||||
@@ -112,10 +122,9 @@ class ImageManager(base.Manager):
|
||||
:param image: image object or id to look up
|
||||
:rtype: :class:`Image`
|
||||
"""
|
||||
|
||||
image_id = base.getid(image)
|
||||
resp, body = self.api.raw_request('HEAD', '/v1/images/%s'
|
||||
% parse.quote(str(image_id)))
|
||||
resp, body = self.client.raw_request(
|
||||
'HEAD', '/v1/images/%s' % parse.quote(str(image_id)))
|
||||
meta = self._image_meta_from_headers(dict(resp.getheaders()))
|
||||
return_request_id = kwargs.get('return_req_id', None)
|
||||
if return_request_id is not None:
|
||||
@@ -131,8 +140,8 @@ class ImageManager(base.Manager):
|
||||
:rtype: iterable containing image data
|
||||
"""
|
||||
image_id = base.getid(image)
|
||||
resp, body = self.api.raw_request('GET', '/v1/images/%s'
|
||||
% parse.quote(str(image_id)))
|
||||
resp, body = self.client.raw_request(
|
||||
'GET', '/v1/images/%s' % parse.quote(str(image_id)))
|
||||
checksum = resp.getheader('x-image-meta-checksum', None)
|
||||
if do_checksum and checksum is not None:
|
||||
body.set_checksum(checksum)
|
||||
@@ -244,7 +253,7 @@ class ImageManager(base.Manager):
|
||||
|
||||
def delete(self, image, **kwargs):
|
||||
"""Delete an image."""
|
||||
resp = self._delete("/v1/images/%s" % base.getid(image))
|
||||
resp = self._delete("/v1/images/%s" % base.getid(image))[0]
|
||||
return_request_id = kwargs.get('return_req_id', None)
|
||||
if return_request_id is not None:
|
||||
return_request_id.append(resp.getheader(OS_REQ_ID_HDR, None))
|
||||
@@ -275,7 +284,7 @@ class ImageManager(base.Manager):
|
||||
if copy_from is not None:
|
||||
hdrs['x-glance-api-copy-from'] = copy_from
|
||||
|
||||
resp, body_iter = self.api.raw_request(
|
||||
resp, body_iter = self.client.raw_request(
|
||||
'POST', '/v1/images', headers=hdrs, body=image_data)
|
||||
body = json.loads(''.join([c for c in body_iter]))
|
||||
return_request_id = kwargs.get('return_req_id', None)
|
||||
@@ -319,7 +328,7 @@ class ImageManager(base.Manager):
|
||||
hdrs['x-glance-api-copy-from'] = copy_from
|
||||
|
||||
url = '/v1/images/%s' % base.getid(image)
|
||||
resp, body_iter = self.api.raw_request(
|
||||
resp, body_iter = self.client.raw_request(
|
||||
'PUT', url, headers=hdrs, body=image_data)
|
||||
body = json.loads(''.join([c for c in body_iter]))
|
||||
return_request_id = kwargs.get('return_req_id', None)
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
import testtools
|
||||
|
||||
from glanceclient.common import base
|
||||
from glanceclient.openstack.common.apiclient import base
|
||||
|
||||
|
||||
class TestBase(testtools.TestCase):
|
||||
|
@@ -44,6 +44,32 @@ class FakeAPI(object):
|
||||
fixture = self._request(*args, **kwargs)
|
||||
return FakeResponse(fixture[0]), fixture[1]
|
||||
|
||||
def client_request(self, method, url, **kwargs):
|
||||
if 'json' in kwargs and 'body' not in kwargs:
|
||||
kwargs['body'] = kwargs.pop('json')
|
||||
resp, body = self.json_request(method, url, **kwargs)
|
||||
resp.json = lambda: body
|
||||
resp.content = bool(body)
|
||||
return resp
|
||||
|
||||
def head(self, url, **kwargs):
|
||||
return self.client_request("HEAD", url, **kwargs)
|
||||
|
||||
def get(self, url, **kwargs):
|
||||
return self.client_request("GET", url, **kwargs)
|
||||
|
||||
def post(self, url, **kwargs):
|
||||
return self.client_request("POST", url, **kwargs)
|
||||
|
||||
def put(self, url, **kwargs):
|
||||
return self.client_request("PUT", url, **kwargs)
|
||||
|
||||
def delete(self, url, **kwargs):
|
||||
return self.raw_request("DELETE", url, **kwargs)
|
||||
|
||||
def patch(self, url, **kwargs):
|
||||
return self.client_request("PATCH", url, **kwargs)
|
||||
|
||||
|
||||
class FakeResponse(object):
|
||||
def __init__(self, headers, body=None,
|
||||
|
@@ -837,6 +837,7 @@ class ImageTest(testtools.TestCase):
|
||||
image = self.mgr.get('1')
|
||||
image.delete()
|
||||
expect = [
|
||||
('HEAD', '/v1/images/1', {}, None),
|
||||
('HEAD', '/v1/images/1', {}, None),
|
||||
('DELETE', '/v1/images/1', {}, None),
|
||||
]
|
||||
@@ -846,6 +847,7 @@ class ImageTest(testtools.TestCase):
|
||||
image = self.mgr.get('1')
|
||||
image.update(name='image-5')
|
||||
expect = [
|
||||
('HEAD', '/v1/images/1', {}, None),
|
||||
('HEAD', '/v1/images/1', {}, None),
|
||||
('PUT', '/v1/images/1', {'x-image-meta-name': 'image-5'}, None),
|
||||
]
|
||||
@@ -855,6 +857,7 @@ class ImageTest(testtools.TestCase):
|
||||
image = self.mgr.get('1')
|
||||
data = ''.join([b for b in image.data()])
|
||||
expect = [
|
||||
('HEAD', '/v1/images/1', {}, None),
|
||||
('HEAD', '/v1/images/1', {}, None),
|
||||
('GET', '/v1/images/1', {}, None),
|
||||
]
|
||||
@@ -870,6 +873,7 @@ class ImageTest(testtools.TestCase):
|
||||
image = self.mgr.get('2')
|
||||
data = ''.join([b for b in image.data(do_checksum=False)])
|
||||
expect = [
|
||||
('HEAD', '/v1/images/2', {}, None),
|
||||
('HEAD', '/v1/images/2', {}, None),
|
||||
('GET', '/v1/images/2', {}, None),
|
||||
]
|
||||
@@ -891,6 +895,7 @@ class ImageTest(testtools.TestCase):
|
||||
image = self.mgr.get('3')
|
||||
data = ''.join([b for b in image.data(do_checksum=False)])
|
||||
expect = [
|
||||
('HEAD', '/v1/images/3', {}, None),
|
||||
('HEAD', '/v1/images/3', {}, None),
|
||||
('GET', '/v1/images/3', {}, None),
|
||||
]
|
||||
|
Reference in New Issue
Block a user