Add request id to returned objects
Adding two classes RequestIdProxy and GeneratorProxy derived from wrapt.ObjectProxy to wrap objects returned from the API. GeneratorProxy class is used to wrap generator objects returned by cases like images.list() etc. whereas RequestIdProxy class is used to wrap non-generator object cases like images.create() etc. In all cases the returned object will have the same behavior as the wrapped(original) object. However now the returned objects will have an extra property 'request_ids' which is a list of exactly one request id. For generator cases the request_ids property will be an empty list until the underlying generator is invoked at-least once. Co-Authored-By: Abhishek Kekane <abhishek.kekane@nttdata.com> Closes-Bug: #1525259 Blueprint: return-request-id-to-caller Change-Id: If8c0e0843270ff718a37ca2697afeb8da22aa3b1
This commit is contained in:
parent
54e6faadf2
commit
610177a779
@ -36,6 +36,7 @@ else:
|
|||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
import prettytable
|
import prettytable
|
||||||
|
import wrapt
|
||||||
|
|
||||||
from glanceclient._i18n import _
|
from glanceclient._i18n import _
|
||||||
from glanceclient import exc
|
from glanceclient import exc
|
||||||
@ -472,3 +473,76 @@ class IterableWithLength(object):
|
|||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return self.length
|
return self.length
|
||||||
|
|
||||||
|
|
||||||
|
class RequestIdProxy(wrapt.ObjectProxy):
|
||||||
|
def __init__(self, wrapped):
|
||||||
|
# `wrapped` is a tuple: (original_obj, response_obj)
|
||||||
|
super(RequestIdProxy, self).__init__(wrapped[0])
|
||||||
|
self._self_wrapped = wrapped[0]
|
||||||
|
req_id = _extract_request_id(wrapped[1])
|
||||||
|
self._self_request_ids = [req_id]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def request_ids(self):
|
||||||
|
return self._self_request_ids
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wrapped(self):
|
||||||
|
return self._self_wrapped
|
||||||
|
|
||||||
|
|
||||||
|
class GeneratorProxy(wrapt.ObjectProxy):
|
||||||
|
def __init__(self, wrapped):
|
||||||
|
super(GeneratorProxy, self).__init__(wrapped)
|
||||||
|
self._self_wrapped = wrapped
|
||||||
|
self._self_request_ids = []
|
||||||
|
|
||||||
|
def _set_request_ids(self, resp):
|
||||||
|
if self._self_request_ids == []:
|
||||||
|
req_id = _extract_request_id(resp)
|
||||||
|
self._self_request_ids = [req_id]
|
||||||
|
|
||||||
|
def _next(self):
|
||||||
|
obj, resp = next(self._self_wrapped)
|
||||||
|
self._set_request_ids(resp)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# Override generator's next method to add
|
||||||
|
# request id on each iteration
|
||||||
|
def next(self):
|
||||||
|
return self._next()
|
||||||
|
|
||||||
|
# For Python 3 compatibility
|
||||||
|
def __next__(self):
|
||||||
|
return self._next()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def request_ids(self):
|
||||||
|
return self._self_request_ids
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wrapped(self):
|
||||||
|
return self._self_wrapped
|
||||||
|
|
||||||
|
|
||||||
|
def add_req_id_to_object():
|
||||||
|
@wrapt.decorator
|
||||||
|
def inner(wrapped, instance, args, kwargs):
|
||||||
|
return RequestIdProxy(wrapped(*args, **kwargs))
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
def add_req_id_to_generator():
|
||||||
|
@wrapt.decorator
|
||||||
|
def inner(wrapped, instance, args, kwargs):
|
||||||
|
return GeneratorProxy(wrapped(*args, **kwargs))
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
def _extract_request_id(resp):
|
||||||
|
# TODO(rsjethani): Do we need more checks here?
|
||||||
|
return resp.headers.get('x-openstack-request-id')
|
||||||
|
@ -17,6 +17,7 @@ import sys
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_utils import encodeutils
|
from oslo_utils import encodeutils
|
||||||
|
from requests import Response
|
||||||
import six
|
import six
|
||||||
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
@ -25,6 +26,15 @@ import testtools
|
|||||||
from glanceclient.common import utils
|
from glanceclient.common import utils
|
||||||
|
|
||||||
|
|
||||||
|
REQUEST_ID = 'req-1234'
|
||||||
|
|
||||||
|
|
||||||
|
def create_response_obj_with_req_id(req_id):
|
||||||
|
resp = Response()
|
||||||
|
resp.headers['x-openstack-request-id'] = req_id
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
class TestUtils(testtools.TestCase):
|
class TestUtils(testtools.TestCase):
|
||||||
|
|
||||||
def test_make_size_human_readable(self):
|
def test_make_size_human_readable(self):
|
||||||
@ -178,3 +188,43 @@ class TestUtils(testtools.TestCase):
|
|||||||
(name, value) = utils.safe_header(sensitive_header, None)
|
(name, value) = utils.safe_header(sensitive_header, None)
|
||||||
self.assertEqual(sensitive_header, name)
|
self.assertEqual(sensitive_header, name)
|
||||||
self.assertIsNone(value)
|
self.assertIsNone(value)
|
||||||
|
|
||||||
|
def test_generator_proxy(self):
|
||||||
|
def _test_decorator():
|
||||||
|
i = 1
|
||||||
|
resp = create_response_obj_with_req_id(REQUEST_ID)
|
||||||
|
while True:
|
||||||
|
yield i, resp
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
gen_obj = _test_decorator()
|
||||||
|
proxy = utils.GeneratorProxy(gen_obj)
|
||||||
|
|
||||||
|
# Proxy object should succeed in behaving as the
|
||||||
|
# wrapped object
|
||||||
|
self.assertTrue(isinstance(proxy, type(gen_obj)))
|
||||||
|
|
||||||
|
# Initially request_ids should be empty
|
||||||
|
self.assertEqual([], proxy.request_ids)
|
||||||
|
|
||||||
|
# Only after we have started iterating we should
|
||||||
|
# see non-empty `request_ids` property
|
||||||
|
proxy.next()
|
||||||
|
self.assertEqual([REQUEST_ID], proxy.request_ids)
|
||||||
|
|
||||||
|
# Even after multiple iterations `request_ids` property
|
||||||
|
# should only contain one request id
|
||||||
|
proxy.next()
|
||||||
|
proxy.next()
|
||||||
|
self.assertEqual(1, len(proxy.request_ids))
|
||||||
|
|
||||||
|
def test_request_id_proxy(self):
|
||||||
|
def test_data(val):
|
||||||
|
resp = create_response_obj_with_req_id(REQUEST_ID)
|
||||||
|
return val, resp
|
||||||
|
|
||||||
|
# Object of any type except decorator can be passed to test_data
|
||||||
|
proxy = utils.RequestIdProxy(test_data(11))
|
||||||
|
# Verify that proxy object has a property `request_ids` and it is
|
||||||
|
# a list of one request id
|
||||||
|
self.assertEqual([REQUEST_ID], proxy.request_ids)
|
||||||
|
119
glanceclient/tests/unit/v2/base.py
Normal file
119
glanceclient/tests/unit/v2/base.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# Copyright 2016 NTT DATA
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
|
||||||
|
class BaseController(testtools.TestCase):
|
||||||
|
def __init__(self, api, schema_api, controller_class):
|
||||||
|
self.controller = controller_class(api, schema_api)
|
||||||
|
|
||||||
|
def _assertRequestId(self, obj):
|
||||||
|
self.assertIsNotNone(getattr(obj, 'request_ids', None))
|
||||||
|
self.assertEqual(['req-1234'], obj.request_ids)
|
||||||
|
|
||||||
|
def list(self, *args, **kwargs):
|
||||||
|
gen_obj = self.controller.list(*args, **kwargs)
|
||||||
|
# For generator cases the request_ids property will be an empty list
|
||||||
|
# until the underlying generator is invoked at-least once.
|
||||||
|
resources = list(gen_obj)
|
||||||
|
if len(resources) > 0:
|
||||||
|
self._assertRequestId(gen_obj)
|
||||||
|
else:
|
||||||
|
# If list is empty that means geneator object has raised
|
||||||
|
# StopIteration for first iteration and will not contain the
|
||||||
|
# request_id in it.
|
||||||
|
self.assertEqual([], gen_obj.request_ids)
|
||||||
|
|
||||||
|
return resources
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
resource = self.controller.get(*args, **kwargs)
|
||||||
|
|
||||||
|
self._assertRequestId(resource)
|
||||||
|
return resource
|
||||||
|
|
||||||
|
def create(self, *args, **kwargs):
|
||||||
|
resource = self.controller.create(*args, **kwargs)
|
||||||
|
self._assertRequestId(resource)
|
||||||
|
return resource
|
||||||
|
|
||||||
|
def create_multiple(self, *args, **kwargs):
|
||||||
|
tags = self.controller.create_multiple(*args, **kwargs)
|
||||||
|
actual = [tag.name for tag in tags]
|
||||||
|
self._assertRequestId(tags)
|
||||||
|
return actual
|
||||||
|
|
||||||
|
def update(self, *args, **properties):
|
||||||
|
resource = self.controller.update(*args, **properties)
|
||||||
|
self._assertRequestId(resource)
|
||||||
|
return resource
|
||||||
|
|
||||||
|
def delete(self, *args):
|
||||||
|
resp = self.controller.delete(*args)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def delete_all(self, *args):
|
||||||
|
resp = self.controller.delete_all(*args)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def deactivate(self, *args):
|
||||||
|
resp = self.controller.deactivate(*args)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def reactivate(self, *args):
|
||||||
|
resp = self.controller.reactivate(*args)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def upload(self, *args, **kwargs):
|
||||||
|
resp = self.controller.upload(*args, **kwargs)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def data(self, *args, **kwargs):
|
||||||
|
body = self.controller.data(*args, **kwargs)
|
||||||
|
self._assertRequestId(body)
|
||||||
|
return body
|
||||||
|
|
||||||
|
def delete_locations(self, *args):
|
||||||
|
resp = self.controller.delete_locations(*args)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def add_location(self, *args, **kwargs):
|
||||||
|
resp = self.controller.add_location(*args, **kwargs)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def update_location(self, *args, **kwargs):
|
||||||
|
resp = self.controller.update_location(*args, **kwargs)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
def associate(self, *args, **kwargs):
|
||||||
|
resource_types = self.controller.associate(*args, **kwargs)
|
||||||
|
self._assertRequestId(resource_types)
|
||||||
|
return resource_types
|
||||||
|
|
||||||
|
def deassociate(self, *args):
|
||||||
|
resp = self.controller.deassociate(*args)
|
||||||
|
self._assertRequestId(resp)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseResourceTypeController(BaseController):
|
||||||
|
def __init__(self, api, schema_api, controller_class):
|
||||||
|
super(BaseResourceTypeController, self).__init__(api, schema_api,
|
||||||
|
controller_class)
|
||||||
|
|
||||||
|
def get(self, *args, **kwargs):
|
||||||
|
resource_types = self.controller.get(*args)
|
||||||
|
names = [rt.name for rt in resource_types]
|
||||||
|
self._assertRequestId(resource_types)
|
||||||
|
return names
|
@ -18,6 +18,7 @@ import mock
|
|||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from glanceclient import exc
|
from glanceclient import exc
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import images
|
from glanceclient.v2 import images
|
||||||
|
|
||||||
@ -532,27 +533,25 @@ class TestController(testtools.TestCase):
|
|||||||
super(TestController, self).setUp()
|
super(TestController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = images.Controller(self.api, self.schema_api)
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
|
images.Controller)
|
||||||
|
|
||||||
def test_list_images(self):
|
def test_list_images(self):
|
||||||
# NOTE(bcwaldon):cast to list since the controller returns a generator
|
images = self.controller.list()
|
||||||
images = list(self.controller.list())
|
|
||||||
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id)
|
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id)
|
||||||
self.assertEqual('image-1', images[0].name)
|
self.assertEqual('image-1', images[0].name)
|
||||||
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[1].id)
|
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[1].id)
|
||||||
self.assertEqual('image-2', images[1].name)
|
self.assertEqual('image-2', images[1].name)
|
||||||
|
|
||||||
def test_list_images_paginated(self):
|
def test_list_images_paginated(self):
|
||||||
# NOTE(bcwaldon):cast to list since the controller returns a generator
|
images = self.controller.list(page_size=1)
|
||||||
images = list(self.controller.list(page_size=1))
|
|
||||||
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id)
|
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id)
|
||||||
self.assertEqual('image-1', images[0].name)
|
self.assertEqual('image-1', images[0].name)
|
||||||
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[1].id)
|
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[1].id)
|
||||||
self.assertEqual('image-2', images[1].name)
|
self.assertEqual('image-2', images[1].name)
|
||||||
|
|
||||||
def test_list_images_paginated_with_limit(self):
|
def test_list_images_paginated_with_limit(self):
|
||||||
# NOTE(bcwaldon):cast to list since the controller returns a generator
|
images = self.controller.list(limit=3, page_size=2)
|
||||||
images = list(self.controller.list(limit=3, page_size=2))
|
|
||||||
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id)
|
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', images[0].id)
|
||||||
self.assertEqual('image-1', images[0].name)
|
self.assertEqual('image-1', images[0].name)
|
||||||
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[1].id)
|
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[1].id)
|
||||||
@ -562,40 +561,40 @@ class TestController(testtools.TestCase):
|
|||||||
self.assertEqual(3, len(images))
|
self.assertEqual(3, len(images))
|
||||||
|
|
||||||
def test_list_images_with_marker(self):
|
def test_list_images_with_marker(self):
|
||||||
images = list(self.controller.list(limit=1,
|
images = self.controller.list(
|
||||||
marker='3a4560a1-e585-443e-9b39-553b46ec92d1'))
|
limit=1, marker='3a4560a1-e585-443e-9b39-553b46ec92d1')
|
||||||
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[0].id)
|
self.assertEqual('6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', images[0].id)
|
||||||
self.assertEqual('image-2', images[0].name)
|
self.assertEqual('image-2', images[0].name)
|
||||||
|
|
||||||
def test_list_images_visibility_public(self):
|
def test_list_images_visibility_public(self):
|
||||||
filters = {'filters': {'visibility': 'public'}}
|
filters = {'filters': {'visibility': 'public'}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(_PUBLIC_ID, images[0].id)
|
self.assertEqual(_PUBLIC_ID, images[0].id)
|
||||||
|
|
||||||
def test_list_images_visibility_private(self):
|
def test_list_images_visibility_private(self):
|
||||||
filters = {'filters': {'visibility': 'private'}}
|
filters = {'filters': {'visibility': 'private'}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(_PRIVATE_ID, images[0].id)
|
self.assertEqual(_PRIVATE_ID, images[0].id)
|
||||||
|
|
||||||
def test_list_images_visibility_shared(self):
|
def test_list_images_visibility_shared(self):
|
||||||
filters = {'filters': {'visibility': 'shared'}}
|
filters = {'filters': {'visibility': 'shared'}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(_SHARED_ID, images[0].id)
|
self.assertEqual(_SHARED_ID, images[0].id)
|
||||||
|
|
||||||
def test_list_images_member_status_rejected(self):
|
def test_list_images_member_status_rejected(self):
|
||||||
filters = {'filters': {'member_status': 'rejected'}}
|
filters = {'filters': {'member_status': 'rejected'}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(_STATUS_REJECTED_ID, images[0].id)
|
self.assertEqual(_STATUS_REJECTED_ID, images[0].id)
|
||||||
|
|
||||||
def test_list_images_for_owner(self):
|
def test_list_images_for_owner(self):
|
||||||
filters = {'filters': {'owner': _OWNER_ID}}
|
filters = {'filters': {'owner': _OWNER_ID}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(_OWNED_IMAGE_ID, images[0].id)
|
self.assertEqual(_OWNED_IMAGE_ID, images[0].id)
|
||||||
|
|
||||||
def test_list_images_for_checksum_single_image(self):
|
def test_list_images_for_checksum_single_image(self):
|
||||||
fake_id = '3a4560a1-e585-443e-9b39-553b46ec92d1'
|
fake_id = '3a4560a1-e585-443e-9b39-553b46ec92d1'
|
||||||
filters = {'filters': {'checksum': _CHKSUM}}
|
filters = {'filters': {'checksum': _CHKSUM}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(1, len(images))
|
self.assertEqual(1, len(images))
|
||||||
self.assertEqual('%s' % fake_id, images[0].id)
|
self.assertEqual('%s' % fake_id, images[0].id)
|
||||||
|
|
||||||
@ -603,32 +602,32 @@ class TestController(testtools.TestCase):
|
|||||||
fake_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
fake_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
fake_id2 = '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810'
|
fake_id2 = '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810'
|
||||||
filters = {'filters': {'checksum': _CHKSUM1}}
|
filters = {'filters': {'checksum': _CHKSUM1}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % fake_id1, images[0].id)
|
self.assertEqual('%s' % fake_id1, images[0].id)
|
||||||
self.assertEqual('%s' % fake_id2, images[1].id)
|
self.assertEqual('%s' % fake_id2, images[1].id)
|
||||||
|
|
||||||
def test_list_images_for_wrong_checksum(self):
|
def test_list_images_for_wrong_checksum(self):
|
||||||
filters = {'filters': {'checksum': 'wrong'}}
|
filters = {'filters': {'checksum': 'wrong'}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(0, len(images))
|
self.assertEqual(0, len(images))
|
||||||
|
|
||||||
def test_list_images_for_bogus_owner(self):
|
def test_list_images_for_bogus_owner(self):
|
||||||
filters = {'filters': {'owner': _BOGUS_ID}}
|
filters = {'filters': {'owner': _BOGUS_ID}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual([], images)
|
self.assertEqual([], images)
|
||||||
|
|
||||||
def test_list_images_for_bunch_of_filters(self):
|
def test_list_images_for_bunch_of_filters(self):
|
||||||
filters = {'filters': {'owner': _BOGUS_ID,
|
filters = {'filters': {'owner': _BOGUS_ID,
|
||||||
'visibility': 'shared',
|
'visibility': 'shared',
|
||||||
'member_status': 'pending'}}
|
'member_status': 'pending'}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(_EVERYTHING_ID, images[0].id)
|
self.assertEqual(_EVERYTHING_ID, images[0].id)
|
||||||
|
|
||||||
def test_list_images_filters_encoding(self):
|
def test_list_images_filters_encoding(self):
|
||||||
filters = {"owner": u"ni\xf1o"}
|
filters = {"owner": u"ni\xf1o"}
|
||||||
try:
|
try:
|
||||||
list(self.controller.list(filters=filters))
|
self.controller.list(filters=filters)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# NOTE(flaper87): It raises KeyError because there's
|
# NOTE(flaper87): It raises KeyError because there's
|
||||||
# no fixture supporting this query:
|
# no fixture supporting this query:
|
||||||
@ -640,7 +639,7 @@ class TestController(testtools.TestCase):
|
|||||||
def test_list_images_for_tag_single_image(self):
|
def test_list_images_for_tag_single_image(self):
|
||||||
img_id = '3a4560a1-e585-443e-9b39-553b46ec92d1'
|
img_id = '3a4560a1-e585-443e-9b39-553b46ec92d1'
|
||||||
filters = {'filters': {'tag': [_TAG1]}}
|
filters = {'filters': {'tag': [_TAG1]}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(1, len(images))
|
self.assertEqual(1, len(images))
|
||||||
self.assertEqual('%s' % img_id, images[0].id)
|
self.assertEqual('%s' % img_id, images[0].id)
|
||||||
|
|
||||||
@ -648,7 +647,7 @@ class TestController(testtools.TestCase):
|
|||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
img_id2 = '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810'
|
img_id2 = '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810'
|
||||||
filters = {'filters': {'tag': [_TAG2]}}
|
filters = {'filters': {'tag': [_TAG2]}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[0].id)
|
self.assertEqual('%s' % img_id1, images[0].id)
|
||||||
self.assertEqual('%s' % img_id2, images[1].id)
|
self.assertEqual('%s' % img_id2, images[1].id)
|
||||||
@ -656,33 +655,32 @@ class TestController(testtools.TestCase):
|
|||||||
def test_list_images_for_multi_tags(self):
|
def test_list_images_for_multi_tags(self):
|
||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
filters = {'filters': {'tag': [_TAG1, _TAG2]}}
|
filters = {'filters': {'tag': [_TAG1, _TAG2]}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(1, len(images))
|
self.assertEqual(1, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[0].id)
|
self.assertEqual('%s' % img_id1, images[0].id)
|
||||||
|
|
||||||
def test_list_images_for_non_existent_tag(self):
|
def test_list_images_for_non_existent_tag(self):
|
||||||
filters = {'filters': {'tag': ['fake']}}
|
filters = {'filters': {'tag': ['fake']}}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(0, len(images))
|
self.assertEqual(0, len(images))
|
||||||
|
|
||||||
def test_list_images_for_invalid_tag(self):
|
def test_list_images_for_invalid_tag(self):
|
||||||
filters = {'filters': {'tag': [[]]}}
|
filters = {'filters': {'tag': [[]]}}
|
||||||
|
|
||||||
self.assertRaises(exc.HTTPBadRequest,
|
self.assertRaises(exc.HTTPBadRequest,
|
||||||
list,
|
self.controller.list, **filters)
|
||||||
self.controller.list(**filters))
|
|
||||||
|
|
||||||
def test_list_images_with_single_sort_key(self):
|
def test_list_images_with_single_sort_key(self):
|
||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
sort_key = 'name'
|
sort_key = 'name'
|
||||||
images = list(self.controller.list(sort_key=sort_key))
|
images = self.controller.list(sort_key=sort_key)
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[0].id)
|
self.assertEqual('%s' % img_id1, images[0].id)
|
||||||
|
|
||||||
def test_list_with_multiple_sort_keys(self):
|
def test_list_with_multiple_sort_keys(self):
|
||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
sort_key = ['name', 'id']
|
sort_key = ['name', 'id']
|
||||||
images = list(self.controller.list(sort_key=sort_key))
|
images = self.controller.list(sort_key=sort_key)
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[0].id)
|
self.assertEqual('%s' % img_id1, images[0].id)
|
||||||
|
|
||||||
@ -690,8 +688,7 @@ class TestController(testtools.TestCase):
|
|||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
sort_key = 'id'
|
sort_key = 'id'
|
||||||
sort_dir = 'desc'
|
sort_dir = 'desc'
|
||||||
images = list(self.controller.list(sort_key=sort_key,
|
images = self.controller.list(sort_key=sort_key, sort_dir=sort_dir)
|
||||||
sort_dir=sort_dir))
|
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[1].id)
|
self.assertEqual('%s' % img_id1, images[1].id)
|
||||||
|
|
||||||
@ -699,8 +696,7 @@ class TestController(testtools.TestCase):
|
|||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
sort_key = ['name', 'id']
|
sort_key = ['name', 'id']
|
||||||
sort_dir = 'desc'
|
sort_dir = 'desc'
|
||||||
images = list(self.controller.list(sort_key=sort_key,
|
images = self.controller.list(sort_key=sort_key, sort_dir=sort_dir)
|
||||||
sort_dir=sort_dir))
|
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[1].id)
|
self.assertEqual('%s' % img_id1, images[1].id)
|
||||||
|
|
||||||
@ -708,61 +704,50 @@ class TestController(testtools.TestCase):
|
|||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
sort_key = ['name', 'id']
|
sort_key = ['name', 'id']
|
||||||
sort_dir = ['desc', 'asc']
|
sort_dir = ['desc', 'asc']
|
||||||
images = list(self.controller.list(sort_key=sort_key,
|
images = self.controller.list(sort_key=sort_key, sort_dir=sort_dir)
|
||||||
sort_dir=sort_dir))
|
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[1].id)
|
self.assertEqual('%s' % img_id1, images[1].id)
|
||||||
|
|
||||||
def test_list_images_with_new_sorting_syntax(self):
|
def test_list_images_with_new_sorting_syntax(self):
|
||||||
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1'
|
||||||
sort = 'name:desc,size:asc'
|
sort = 'name:desc,size:asc'
|
||||||
images = list(self.controller.list(sort=sort))
|
images = self.controller.list(sort=sort)
|
||||||
self.assertEqual(2, len(images))
|
self.assertEqual(2, len(images))
|
||||||
self.assertEqual('%s' % img_id1, images[1].id)
|
self.assertEqual('%s' % img_id1, images[1].id)
|
||||||
|
|
||||||
def test_list_images_sort_dirs_fewer_than_keys(self):
|
def test_list_images_sort_dirs_fewer_than_keys(self):
|
||||||
sort_key = ['name', 'id', 'created_at']
|
sort_key = ['name', 'id', 'created_at']
|
||||||
sort_dir = ['desc', 'asc']
|
sort_dir = ['desc', 'asc']
|
||||||
self.assertRaises(exc.HTTPBadRequest,
|
self.assertRaises(exc.HTTPBadRequest, self.controller.list,
|
||||||
list,
|
sort_key=sort_key, sort_dir=sort_dir)
|
||||||
self.controller.list(
|
|
||||||
sort_key=sort_key,
|
|
||||||
sort_dir=sort_dir))
|
|
||||||
|
|
||||||
def test_list_images_combined_syntax(self):
|
def test_list_images_combined_syntax(self):
|
||||||
sort_key = ['name', 'id']
|
sort_key = ['name', 'id']
|
||||||
sort_dir = ['desc', 'asc']
|
sort_dir = ['desc', 'asc']
|
||||||
sort = 'name:asc'
|
sort = 'name:asc'
|
||||||
self.assertRaises(exc.HTTPBadRequest,
|
self.assertRaises(exc.HTTPBadRequest,
|
||||||
list,
|
self.controller.list, sort=sort, sort_key=sort_key,
|
||||||
self.controller.list(
|
sort_dir=sort_dir)
|
||||||
sort=sort,
|
|
||||||
sort_key=sort_key,
|
|
||||||
sort_dir=sort_dir))
|
|
||||||
|
|
||||||
def test_list_images_new_sorting_syntax_invalid_key(self):
|
def test_list_images_new_sorting_syntax_invalid_key(self):
|
||||||
sort = 'INVALID:asc'
|
sort = 'INVALID:asc'
|
||||||
self.assertRaises(exc.HTTPBadRequest,
|
self.assertRaises(exc.HTTPBadRequest, self.controller.list,
|
||||||
list,
|
sort=sort)
|
||||||
self.controller.list(
|
|
||||||
sort=sort))
|
|
||||||
|
|
||||||
def test_list_images_new_sorting_syntax_invalid_direction(self):
|
def test_list_images_new_sorting_syntax_invalid_direction(self):
|
||||||
sort = 'name:INVALID'
|
sort = 'name:INVALID'
|
||||||
self.assertRaises(exc.HTTPBadRequest,
|
self.assertRaises(exc.HTTPBadRequest, self.controller.list,
|
||||||
list,
|
sort=sort)
|
||||||
self.controller.list(
|
|
||||||
sort=sort))
|
|
||||||
|
|
||||||
def test_list_images_for_property(self):
|
def test_list_images_for_property(self):
|
||||||
filters = {'filters': dict([('os_distro', 'NixOS')])}
|
filters = {'filters': dict([('os_distro', 'NixOS')])}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(1, len(images))
|
self.assertEqual(1, len(images))
|
||||||
|
|
||||||
def test_list_images_for_non_existent_property(self):
|
def test_list_images_for_non_existent_property(self):
|
||||||
filters = {'filters': dict([('my_little_property',
|
filters = {'filters': dict([('my_little_property',
|
||||||
'cant_be_this_cute')])}
|
'cant_be_this_cute')])}
|
||||||
images = list(self.controller.list(**filters))
|
images = self.controller.list(**filters)
|
||||||
self.assertEqual(0, len(images))
|
self.assertEqual(0, len(images))
|
||||||
|
|
||||||
def test_get_image(self):
|
def test_get_image(self):
|
||||||
@ -804,7 +789,7 @@ class TestController(testtools.TestCase):
|
|||||||
None)]
|
None)]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
|
|
||||||
def reactivate_image(self):
|
def test_reactivate_image(self):
|
||||||
id_image = '87b634c1-f893-33c9-28a9-e5673c99239a'
|
id_image = '87b634c1-f893-33c9-28a9-e5673c99239a'
|
||||||
self.controller.reactivate(id_image)
|
self.controller.reactivate(id_image)
|
||||||
expect = [('POST',
|
expect = [('POST',
|
||||||
@ -868,12 +853,12 @@ class TestController(testtools.TestCase):
|
|||||||
|
|
||||||
def test_download_no_data(self):
|
def test_download_no_data(self):
|
||||||
resp = utils.FakeResponse(headers={}, status_code=204)
|
resp = utils.FakeResponse(headers={}, status_code=204)
|
||||||
self.controller.http_client.get = mock.Mock(return_value=(resp, None))
|
self.controller.controller.http_client.get = mock.Mock(
|
||||||
body = self.controller.data('image_id')
|
return_value=(resp, None))
|
||||||
self.assertIsNone(body)
|
self.controller.data('image_id')
|
||||||
|
|
||||||
def test_download_forbidden(self):
|
def test_download_forbidden(self):
|
||||||
self.controller.http_client.get = mock.Mock(
|
self.controller.controller.http_client.get = mock.Mock(
|
||||||
side_effect=exc.HTTPForbidden())
|
side_effect=exc.HTTPForbidden())
|
||||||
try:
|
try:
|
||||||
self.controller.data('image_id')
|
self.controller.data('image_id')
|
||||||
@ -893,7 +878,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -912,7 +898,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -931,7 +918,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -953,7 +941,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -974,7 +963,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -999,7 +989,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -1016,7 +1007,8 @@ class TestController(testtools.TestCase):
|
|||||||
expect = [
|
expect = [
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id, {}, None),
|
||||||
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
('PATCH', '/v2/images/%s' % image_id, expect_hdrs, expect_body),
|
||||||
('GET', '/v2/images/%s' % image_id, {}, None),
|
('GET', '/v2/images/%s' % image_id,
|
||||||
|
{'x-openstack-request-id': 'req-1234'}, None),
|
||||||
]
|
]
|
||||||
self.assertEqual(expect, self.api.calls)
|
self.assertEqual(expect, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
@ -1040,8 +1032,9 @@ class TestController(testtools.TestCase):
|
|||||||
image_id, url, meta)
|
image_id, url, meta)
|
||||||
self.assertIn(estr, str(e))
|
self.assertIn(estr, str(e))
|
||||||
|
|
||||||
def _empty_get(self, image_id):
|
def _empty_get(self, image_id, headers=None):
|
||||||
return ('GET', '/v2/images/%s' % image_id, {}, None)
|
return ('GET', '/v2/images/%s' % image_id,
|
||||||
|
headers or {}, None)
|
||||||
|
|
||||||
def _patch_req(self, image_id, patch_body):
|
def _patch_req(self, image_id, patch_body):
|
||||||
c_type = 'application/openstack-images-v2.1-json-patch'
|
c_type = 'application/openstack-images-v2.1-json-patch'
|
||||||
@ -1055,9 +1048,11 @@ class TestController(testtools.TestCase):
|
|||||||
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'
|
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'
|
||||||
new_loc = {'url': 'http://spam.com/', 'metadata': {'spam': 'ham'}}
|
new_loc = {'url': 'http://spam.com/', 'metadata': {'spam': 'ham'}}
|
||||||
add_patch = {'path': '/locations/-', 'value': new_loc, 'op': 'add'}
|
add_patch = {'path': '/locations/-', 'value': new_loc, 'op': 'add'}
|
||||||
|
headers = {'x-openstack-request-id': 'req-1234'}
|
||||||
self.controller.add_location(image_id, **new_loc)
|
self.controller.add_location(image_id, **new_loc)
|
||||||
self.assertEqual([self._patch_req(image_id, [add_patch]),
|
self.assertEqual([self._patch_req(image_id, [add_patch]),
|
||||||
self._empty_get(image_id)], self.api.calls)
|
self._empty_get(image_id, headers=headers)],
|
||||||
|
self.api.calls)
|
||||||
|
|
||||||
@mock.patch.object(images.Controller, '_send_image_update_request',
|
@mock.patch.object(images.Controller, '_send_image_update_request',
|
||||||
side_effect=exc.HTTPBadRequest)
|
side_effect=exc.HTTPBadRequest)
|
||||||
@ -1092,6 +1087,7 @@ class TestController(testtools.TestCase):
|
|||||||
def test_update_location(self):
|
def test_update_location(self):
|
||||||
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'
|
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'
|
||||||
new_loc = {'url': 'http://foo.com/', 'metadata': {'spam': 'ham'}}
|
new_loc = {'url': 'http://foo.com/', 'metadata': {'spam': 'ham'}}
|
||||||
|
headers = {'x-openstack-request-id': 'req-1234'}
|
||||||
fixture_idx = '/v2/images/%s' % (image_id)
|
fixture_idx = '/v2/images/%s' % (image_id)
|
||||||
orig_locations = data_fixtures[fixture_idx]['GET'][1]['locations']
|
orig_locations = data_fixtures[fixture_idx]['GET'][1]['locations']
|
||||||
loc_map = dict([(l['url'], l) for l in orig_locations])
|
loc_map = dict([(l['url'], l) for l in orig_locations])
|
||||||
@ -1101,12 +1097,13 @@ class TestController(testtools.TestCase):
|
|||||||
self.controller.update_location(image_id, **new_loc)
|
self.controller.update_location(image_id, **new_loc)
|
||||||
self.assertEqual([self._empty_get(image_id),
|
self.assertEqual([self._empty_get(image_id),
|
||||||
self._patch_req(image_id, mod_patch),
|
self._patch_req(image_id, mod_patch),
|
||||||
self._empty_get(image_id)],
|
self._empty_get(image_id, headers=headers)],
|
||||||
self.api.calls)
|
self.api.calls)
|
||||||
|
|
||||||
def test_update_tags(self):
|
def test_update_tags(self):
|
||||||
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'
|
image_id = 'a2b83adc-888e-11e3-8872-78acc0b951d8'
|
||||||
tag_map = {'tags': ['tag01', 'tag02', 'tag03']}
|
tag_map = {'tags': ['tag01', 'tag02', 'tag03']}
|
||||||
|
headers = {'x-openstack-request-id': 'req-1234'}
|
||||||
|
|
||||||
image = self.controller.update(image_id, **tag_map)
|
image = self.controller.update(image_id, **tag_map)
|
||||||
|
|
||||||
@ -1115,7 +1112,7 @@ class TestController(testtools.TestCase):
|
|||||||
expected = [
|
expected = [
|
||||||
self._empty_get(image_id),
|
self._empty_get(image_id),
|
||||||
self._patch_req(image_id, expected_body),
|
self._patch_req(image_id, expected_body),
|
||||||
self._empty_get(image_id)
|
self._empty_get(image_id, headers=headers)
|
||||||
]
|
]
|
||||||
self.assertEqual(expected, self.api.calls)
|
self.assertEqual(expected, self.api.calls)
|
||||||
self.assertEqual(image_id, image.id)
|
self.assertEqual(image_id, image.id)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import image_members
|
from glanceclient.v2 import image_members
|
||||||
|
|
||||||
@ -80,12 +81,12 @@ class TestController(testtools.TestCase):
|
|||||||
super(TestController, self).setUp()
|
super(TestController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = image_members.Controller(self.api, self.schema_api)
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
|
image_members.Controller)
|
||||||
|
|
||||||
def test_list_image_members(self):
|
def test_list_image_members(self):
|
||||||
image_id = IMAGE
|
image_id = IMAGE
|
||||||
# NOTE(iccha): cast to list since the controller returns a generator
|
image_members = self.controller.list(image_id)
|
||||||
image_members = list(self.controller.list(image_id))
|
|
||||||
self.assertEqual(IMAGE, image_members[0].image_id)
|
self.assertEqual(IMAGE, image_members[0].image_id)
|
||||||
self.assertEqual(MEMBER, image_members[0].member_id)
|
self.assertEqual(MEMBER, image_members[0].member_id)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import metadefs
|
from glanceclient.v2 import metadefs
|
||||||
|
|
||||||
@ -542,83 +543,79 @@ class TestNamespaceController(testtools.TestCase):
|
|||||||
super(TestNamespaceController, self).setUp()
|
super(TestNamespaceController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = metadefs.NamespaceController(self.api,
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
self.schema_api)
|
metadefs.NamespaceController)
|
||||||
|
|
||||||
def test_list_namespaces(self):
|
def test_list_namespaces(self):
|
||||||
namespaces = list(self.controller.list())
|
namespaces = self.controller.list()
|
||||||
|
|
||||||
self.assertEqual(2, len(namespaces))
|
self.assertEqual(2, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
||||||
self.assertEqual(NAMESPACE2, namespaces[1]['namespace'])
|
self.assertEqual(NAMESPACE2, namespaces[1]['namespace'])
|
||||||
|
|
||||||
def test_list_namespaces_paginate(self):
|
def test_list_namespaces_paginate(self):
|
||||||
namespaces = list(self.controller.list(page_size=1))
|
namespaces = self.controller.list(page_size=1)
|
||||||
|
|
||||||
self.assertEqual(2, len(namespaces))
|
self.assertEqual(2, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
||||||
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
||||||
|
|
||||||
def test_list_with_limit_greater_than_page_size(self):
|
def test_list_with_limit_greater_than_page_size(self):
|
||||||
namespaces = list(self.controller.list(page_size=1, limit=2))
|
namespaces = self.controller.list(page_size=1, limit=2)
|
||||||
self.assertEqual(2, len(namespaces))
|
self.assertEqual(2, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
||||||
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
||||||
|
|
||||||
def test_list_with_marker(self):
|
def test_list_with_marker(self):
|
||||||
namespaces = list(self.controller.list(marker=NAMESPACE6, page_size=2))
|
namespaces = self.controller.list(marker=NAMESPACE6, page_size=2)
|
||||||
self.assertEqual(2, len(namespaces))
|
self.assertEqual(2, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE7, namespaces[0]['namespace'])
|
||||||
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
self.assertEqual(NAMESPACE8, namespaces[1]['namespace'])
|
||||||
|
|
||||||
def test_list_with_sort_dir(self):
|
def test_list_with_sort_dir(self):
|
||||||
namespaces = list(self.controller.list(sort_dir='asc', limit=1))
|
namespaces = self.controller.list(sort_dir='asc', limit=1)
|
||||||
self.assertEqual(1, len(namespaces))
|
self.assertEqual(1, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
||||||
|
|
||||||
def test_list_with_sort_dir_invalid(self):
|
def test_list_with_sort_dir_invalid(self):
|
||||||
# NOTE(TravT): The clients work by returning an iterator.
|
# NOTE(TravT): The clients work by returning an iterator.
|
||||||
# Invoking the iterator is what actually executes the logic.
|
# Invoking the iterator is what actually executes the logic.
|
||||||
ns_iterator = self.controller.list(sort_dir='foo')
|
self.assertRaises(ValueError, self.controller.list, sort_dir='foo')
|
||||||
self.assertRaises(ValueError, next, ns_iterator)
|
|
||||||
|
|
||||||
def test_list_with_sort_key(self):
|
def test_list_with_sort_key(self):
|
||||||
namespaces = list(self.controller.list(sort_key='created_at', limit=1))
|
namespaces = self.controller.list(sort_key='created_at', limit=1)
|
||||||
self.assertEqual(1, len(namespaces))
|
self.assertEqual(1, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE1, namespaces[0]['namespace'])
|
||||||
|
|
||||||
def test_list_with_sort_key_invalid(self):
|
def test_list_with_sort_key_invalid(self):
|
||||||
# NOTE(TravT): The clients work by returning an iterator.
|
# NOTE(TravT): The clients work by returning an iterator.
|
||||||
# Invoking the iterator is what actually executes the logic.
|
# Invoking the iterator is what actually executes the logic.
|
||||||
ns_iterator = self.controller.list(sort_key='foo')
|
self.assertRaises(ValueError, self.controller.list, sort_key='foo')
|
||||||
self.assertRaises(ValueError, next, ns_iterator)
|
|
||||||
|
|
||||||
def test_list_namespaces_with_one_resource_type_filter(self):
|
def test_list_namespaces_with_one_resource_type_filter(self):
|
||||||
namespaces = list(self.controller.list(
|
namespaces = self.controller.list(
|
||||||
filters={
|
filters={
|
||||||
'resource_types': [RESOURCE_TYPE1]
|
'resource_types': [RESOURCE_TYPE1]
|
||||||
}
|
}
|
||||||
))
|
)
|
||||||
|
|
||||||
self.assertEqual(1, len(namespaces))
|
self.assertEqual(1, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE3, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE3, namespaces[0]['namespace'])
|
||||||
|
|
||||||
def test_list_namespaces_with_multiple_resource_types_filter(self):
|
def test_list_namespaces_with_multiple_resource_types_filter(self):
|
||||||
namespaces = list(self.controller.list(
|
namespaces = self.controller.list(
|
||||||
filters={
|
filters={
|
||||||
'resource_types': [RESOURCE_TYPE1, RESOURCE_TYPE2]
|
'resource_types': [RESOURCE_TYPE1, RESOURCE_TYPE2]
|
||||||
}
|
}
|
||||||
))
|
)
|
||||||
|
|
||||||
self.assertEqual(1, len(namespaces))
|
self.assertEqual(1, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE4, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE4, namespaces[0]['namespace'])
|
||||||
|
|
||||||
def test_list_namespaces_with_visibility_filter(self):
|
def test_list_namespaces_with_visibility_filter(self):
|
||||||
namespaces = list(self.controller.list(
|
namespaces = self.controller.list(
|
||||||
filters={
|
filters={
|
||||||
'visibility': 'private'
|
'visibility': 'private'
|
||||||
}
|
}
|
||||||
))
|
)
|
||||||
|
|
||||||
self.assertEqual(1, len(namespaces))
|
self.assertEqual(1, len(namespaces))
|
||||||
self.assertEqual(NAMESPACE5, namespaces[0]['namespace'])
|
self.assertEqual(NAMESPACE5, namespaces[0]['namespace'])
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import six
|
import six
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import metadefs
|
from glanceclient.v2 import metadefs
|
||||||
|
|
||||||
@ -263,11 +264,11 @@ class TestObjectController(testtools.TestCase):
|
|||||||
super(TestObjectController, self).setUp()
|
super(TestObjectController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = metadefs.ObjectController(self.api, self.schema_api)
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
|
metadefs.ObjectController)
|
||||||
|
|
||||||
def test_list_object(self):
|
def test_list_object(self):
|
||||||
objects = list(self.controller.list(NAMESPACE1))
|
objects = self.controller.list(NAMESPACE1)
|
||||||
|
|
||||||
actual = [obj.name for obj in objects]
|
actual = [obj.name for obj in objects]
|
||||||
self.assertEqual([OBJECT1, OBJECT2], actual)
|
self.assertEqual([OBJECT1, OBJECT2], actual)
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import metadefs
|
from glanceclient.v2 import metadefs
|
||||||
|
|
||||||
@ -238,12 +239,11 @@ class TestPropertyController(testtools.TestCase):
|
|||||||
super(TestPropertyController, self).setUp()
|
super(TestPropertyController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = metadefs.PropertyController(self.api,
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
self.schema_api)
|
metadefs.PropertyController)
|
||||||
|
|
||||||
def test_list_property(self):
|
def test_list_property(self):
|
||||||
properties = list(self.controller.list(NAMESPACE1))
|
properties = self.controller.list(NAMESPACE1)
|
||||||
|
|
||||||
actual = [prop.name for prop in properties]
|
actual = [prop.name for prop in properties]
|
||||||
self.assertEqual(sorted([PROPERTY1, PROPERTY2]), sorted(actual))
|
self.assertEqual(sorted([PROPERTY1, PROPERTY2]), sorted(actual))
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import metadefs
|
from glanceclient.v2 import metadefs
|
||||||
|
|
||||||
@ -151,18 +152,17 @@ class TestResoureTypeController(testtools.TestCase):
|
|||||||
super(TestResoureTypeController, self).setUp()
|
super(TestResoureTypeController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = metadefs.ResourceTypeController(self.api,
|
self.controller = base.BaseResourceTypeController(
|
||||||
self.schema_api)
|
self.api, self.schema_api, metadefs.ResourceTypeController)
|
||||||
|
|
||||||
def test_list_resource_types(self):
|
def test_list_resource_types(self):
|
||||||
resource_types = list(self.controller.list())
|
resource_types = self.controller.list()
|
||||||
names = [rt.name for rt in resource_types]
|
names = [rt.name for rt in resource_types]
|
||||||
self.assertEqual([RESOURCE_TYPE1, RESOURCE_TYPE2], names)
|
self.assertEqual([RESOURCE_TYPE1, RESOURCE_TYPE2], names)
|
||||||
|
|
||||||
def test_get_resource_types(self):
|
def test_get_resource_types(self):
|
||||||
resource_types = list(self.controller.get(NAMESPACE1))
|
resource_types = self.controller.get(NAMESPACE1)
|
||||||
names = [rt.name for rt in resource_types]
|
self.assertEqual([RESOURCE_TYPE3, RESOURCE_TYPE4], resource_types)
|
||||||
self.assertEqual([RESOURCE_TYPE3, RESOURCE_TYPE4], names)
|
|
||||||
|
|
||||||
def test_associate_resource_types(self):
|
def test_associate_resource_types(self):
|
||||||
resource_types = self.controller.associate(NAMESPACE1,
|
resource_types = self.controller.associate(NAMESPACE1,
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import metadefs
|
from glanceclient.v2 import metadefs
|
||||||
|
|
||||||
@ -134,11 +135,11 @@ class TestTagController(testtools.TestCase):
|
|||||||
super(TestTagController, self).setUp()
|
super(TestTagController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = metadefs.TagController(self.api, self.schema_api)
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
|
metadefs.TagController)
|
||||||
|
|
||||||
def test_list_tag(self):
|
def test_list_tag(self):
|
||||||
tags = list(self.controller.list(NAMESPACE1))
|
tags = self.controller.list(NAMESPACE1)
|
||||||
|
|
||||||
actual = [tag.name for tag in tags]
|
actual = [tag.name for tag in tags]
|
||||||
self.assertEqual([TAG1, TAG2], actual)
|
self.assertEqual([TAG1, TAG2], actual)
|
||||||
|
|
||||||
@ -155,8 +156,7 @@ class TestTagController(testtools.TestCase):
|
|||||||
'tags': [TAGNEW2, TAGNEW3]
|
'tags': [TAGNEW2, TAGNEW3]
|
||||||
}
|
}
|
||||||
tags = self.controller.create_multiple(NAMESPACE1, **properties)
|
tags = self.controller.create_multiple(NAMESPACE1, **properties)
|
||||||
actual = [tag.name for tag in tags]
|
self.assertEqual([TAGNEW2, TAGNEW3], tags)
|
||||||
self.assertEqual([TAGNEW2, TAGNEW3], actual)
|
|
||||||
|
|
||||||
def test_update_tag(self):
|
def test_update_tag(self):
|
||||||
properties = {
|
properties = {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import image_tags
|
from glanceclient.v2 import image_tags
|
||||||
|
|
||||||
@ -54,7 +55,8 @@ class TestController(testtools.TestCase):
|
|||||||
super(TestController, self).setUp()
|
super(TestController, self).setUp()
|
||||||
self.api = utils.FakeAPI(data_fixtures)
|
self.api = utils.FakeAPI(data_fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = image_tags.Controller(self.api, self.schema_api)
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
|
image_tags.Controller)
|
||||||
|
|
||||||
def test_update_image_tag(self):
|
def test_update_image_tag(self):
|
||||||
image_id = IMAGE
|
image_id = IMAGE
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from glanceclient.tests.unit.v2 import base
|
||||||
from glanceclient.tests import utils
|
from glanceclient.tests import utils
|
||||||
from glanceclient.v2 import tasks
|
from glanceclient.v2 import tasks
|
||||||
|
|
||||||
@ -252,11 +253,11 @@ class TestController(testtools.TestCase):
|
|||||||
super(TestController, self).setUp()
|
super(TestController, self).setUp()
|
||||||
self.api = utils.FakeAPI(fixtures)
|
self.api = utils.FakeAPI(fixtures)
|
||||||
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
self.schema_api = utils.FakeSchemaAPI(schema_fixtures)
|
||||||
self.controller = tasks.Controller(self.api, self.schema_api)
|
self.controller = base.BaseController(self.api, self.schema_api,
|
||||||
|
tasks.Controller)
|
||||||
|
|
||||||
def test_list_tasks(self):
|
def test_list_tasks(self):
|
||||||
# NOTE(flwang): cast to list since the controller returns a generator
|
tasks = self.controller.list()
|
||||||
tasks = list(self.controller.list())
|
|
||||||
self.assertEqual(_PENDING_ID, tasks[0].id)
|
self.assertEqual(_PENDING_ID, tasks[0].id)
|
||||||
self.assertEqual('import', tasks[0].type)
|
self.assertEqual('import', tasks[0].type)
|
||||||
self.assertEqual('pending', tasks[0].status)
|
self.assertEqual('pending', tasks[0].status)
|
||||||
@ -265,8 +266,7 @@ class TestController(testtools.TestCase):
|
|||||||
self.assertEqual('processing', tasks[1].status)
|
self.assertEqual('processing', tasks[1].status)
|
||||||
|
|
||||||
def test_list_tasks_paginated(self):
|
def test_list_tasks_paginated(self):
|
||||||
# NOTE(flwang): cast to list since the controller returns a generator
|
tasks = self.controller.list(page_size=1)
|
||||||
tasks = list(self.controller.list(page_size=1))
|
|
||||||
self.assertEqual(_PENDING_ID, tasks[0].id)
|
self.assertEqual(_PENDING_ID, tasks[0].id)
|
||||||
self.assertEqual('import', tasks[0].type)
|
self.assertEqual('import', tasks[0].type)
|
||||||
self.assertEqual(_PROCESSING_ID, tasks[1].id)
|
self.assertEqual(_PROCESSING_ID, tasks[1].id)
|
||||||
@ -274,38 +274,38 @@ class TestController(testtools.TestCase):
|
|||||||
|
|
||||||
def test_list_tasks_with_status(self):
|
def test_list_tasks_with_status(self):
|
||||||
filters = {'filters': {'status': 'processing'}}
|
filters = {'filters': {'status': 'processing'}}
|
||||||
tasks = list(self.controller.list(**filters))
|
tasks = self.controller.list(**filters)
|
||||||
self.assertEqual(_OWNED_TASK_ID, tasks[0].id)
|
self.assertEqual(_OWNED_TASK_ID, tasks[0].id)
|
||||||
|
|
||||||
def test_list_tasks_with_wrong_status(self):
|
def test_list_tasks_with_wrong_status(self):
|
||||||
filters = {'filters': {'status': 'fake'}}
|
filters = {'filters': {'status': 'fake'}}
|
||||||
tasks = list(self.controller.list(**filters))
|
tasks = self.controller.list(**filters)
|
||||||
self.assertEqual(0, len(tasks))
|
self.assertEqual(0, len(tasks))
|
||||||
|
|
||||||
def test_list_tasks_with_type(self):
|
def test_list_tasks_with_type(self):
|
||||||
filters = {'filters': {'type': 'import'}}
|
filters = {'filters': {'type': 'import'}}
|
||||||
tasks = list(self.controller.list(**filters))
|
tasks = self.controller.list(**filters)
|
||||||
self.assertEqual(_OWNED_TASK_ID, tasks[0].id)
|
self.assertEqual(_OWNED_TASK_ID, tasks[0].id)
|
||||||
|
|
||||||
def test_list_tasks_with_wrong_type(self):
|
def test_list_tasks_with_wrong_type(self):
|
||||||
filters = {'filters': {'type': 'fake'}}
|
filters = {'filters': {'type': 'fake'}}
|
||||||
tasks = list(self.controller.list(**filters))
|
tasks = self.controller.list(**filters)
|
||||||
self.assertEqual(0, len(tasks))
|
self.assertEqual(0, len(tasks))
|
||||||
|
|
||||||
def test_list_tasks_for_owner(self):
|
def test_list_tasks_for_owner(self):
|
||||||
filters = {'filters': {'owner': _OWNER_ID}}
|
filters = {'filters': {'owner': _OWNER_ID}}
|
||||||
tasks = list(self.controller.list(**filters))
|
tasks = self.controller.list(**filters)
|
||||||
self.assertEqual(_OWNED_TASK_ID, tasks[0].id)
|
self.assertEqual(_OWNED_TASK_ID, tasks[0].id)
|
||||||
|
|
||||||
def test_list_tasks_for_fake_owner(self):
|
def test_list_tasks_for_fake_owner(self):
|
||||||
filters = {'filters': {'owner': _FAKE_OWNER_ID}}
|
filters = {'filters': {'owner': _FAKE_OWNER_ID}}
|
||||||
tasks = list(self.controller.list(**filters))
|
tasks = self.controller.list(**filters)
|
||||||
self.assertEqual(tasks, [])
|
self.assertEqual(tasks, [])
|
||||||
|
|
||||||
def test_list_tasks_filters_encoding(self):
|
def test_list_tasks_filters_encoding(self):
|
||||||
filters = {"owner": u"ni\xf1o"}
|
filters = {"owner": u"ni\xf1o"}
|
||||||
try:
|
try:
|
||||||
list(self.controller.list(filters=filters))
|
self.controller.list(filters=filters)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# NOTE(flaper87): It raises KeyError because there's
|
# NOTE(flaper87): It raises KeyError because there's
|
||||||
# no fixture supporting this query:
|
# no fixture supporting this query:
|
||||||
@ -316,34 +316,33 @@ class TestController(testtools.TestCase):
|
|||||||
self.assertEqual(b"ni\xc3\xb1o", filters["owner"])
|
self.assertEqual(b"ni\xc3\xb1o", filters["owner"])
|
||||||
|
|
||||||
def test_list_tasks_with_marker(self):
|
def test_list_tasks_with_marker(self):
|
||||||
tasks = list(self.controller.list(marker=_PENDING_ID, page_size=1))
|
tasks = self.controller.list(marker=_PENDING_ID, page_size=1)
|
||||||
self.assertEqual(1, len(tasks))
|
self.assertEqual(1, len(tasks))
|
||||||
self.assertEqual(_PROCESSING_ID, tasks[0]['id'])
|
self.assertEqual(_PROCESSING_ID, tasks[0]['id'])
|
||||||
|
|
||||||
def test_list_tasks_with_single_sort_key(self):
|
def test_list_tasks_with_single_sort_key(self):
|
||||||
tasks = list(self.controller.list(sort_key='type'))
|
tasks = self.controller.list(sort_key='type')
|
||||||
self.assertEqual(2, len(tasks))
|
self.assertEqual(2, len(tasks))
|
||||||
self.assertEqual(_PENDING_ID, tasks[0].id)
|
self.assertEqual(_PENDING_ID, tasks[0].id)
|
||||||
|
|
||||||
def test_list_tasks_with_invalid_sort_key(self):
|
def test_list_tasks_with_invalid_sort_key(self):
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
list,
|
self.controller.list, sort_key='invalid')
|
||||||
self.controller.list(sort_key='invalid'))
|
|
||||||
|
|
||||||
def test_list_tasks_with_desc_sort_dir(self):
|
def test_list_tasks_with_desc_sort_dir(self):
|
||||||
tasks = list(self.controller.list(sort_key='id', sort_dir='desc'))
|
tasks = self.controller.list(sort_key='id', sort_dir='desc')
|
||||||
self.assertEqual(2, len(tasks))
|
self.assertEqual(2, len(tasks))
|
||||||
self.assertEqual(_PENDING_ID, tasks[1].id)
|
self.assertEqual(_PENDING_ID, tasks[1].id)
|
||||||
|
|
||||||
def test_list_tasks_with_asc_sort_dir(self):
|
def test_list_tasks_with_asc_sort_dir(self):
|
||||||
tasks = list(self.controller.list(sort_key='id', sort_dir='asc'))
|
tasks = self.controller.list(sort_key='id', sort_dir='asc')
|
||||||
self.assertEqual(2, len(tasks))
|
self.assertEqual(2, len(tasks))
|
||||||
self.assertEqual(_PENDING_ID, tasks[0].id)
|
self.assertEqual(_PENDING_ID, tasks[0].id)
|
||||||
|
|
||||||
def test_list_tasks_with_invalid_sort_dir(self):
|
def test_list_tasks_with_invalid_sort_dir(self):
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError,
|
||||||
list,
|
self.controller.list,
|
||||||
self.controller.list(sort_dir='invalid'))
|
sort_dir='invalid')
|
||||||
|
|
||||||
def test_get_task(self):
|
def test_get_task(self):
|
||||||
task = self.controller.get(_PENDING_ID)
|
task = self.controller.get(_PENDING_ID)
|
||||||
|
@ -113,6 +113,7 @@ class FakeResponse(object):
|
|||||||
self.reason = reason
|
self.reason = reason
|
||||||
self.version = version
|
self.version = version
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
|
self.headers['x-openstack-request-id'] = 'req-1234'
|
||||||
self.status_code = status_code
|
self.status_code = status_code
|
||||||
self.raw = RawRequest(headers, body=body, reason=reason,
|
self.raw = RawRequest(headers, body=body, reason=reason,
|
||||||
version=version, status=status_code)
|
version=version, status=status_code)
|
||||||
|
@ -32,24 +32,29 @@ class Controller(object):
|
|||||||
schema = self.schema_client.get('member')
|
schema = self.schema_client.get('member')
|
||||||
return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel)
|
return warlock.model_factory(schema.raw(), schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, image_id):
|
def list(self, image_id):
|
||||||
url = '/v2/images/%s/members' % image_id
|
url = '/v2/images/%s/members' % image_id
|
||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
for member in body['members']:
|
for member in body['members']:
|
||||||
yield self.model(member)
|
yield self.model(member), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, image_id, member_id):
|
def delete(self, image_id, member_id):
|
||||||
self.http_client.delete('/v2/images/%s/members/%s' %
|
resp, body = self.http_client.delete('/v2/images/%s/members/%s' %
|
||||||
(image_id, member_id))
|
(image_id, member_id))
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def update(self, image_id, member_id, member_status):
|
def update(self, image_id, member_id, member_status):
|
||||||
url = '/v2/images/%s/members/%s' % (image_id, member_id)
|
url = '/v2/images/%s/members/%s' % (image_id, member_id)
|
||||||
body = {'status': member_status}
|
body = {'status': member_status}
|
||||||
resp, updated_member = self.http_client.put(url, data=body)
|
resp, updated_member = self.http_client.put(url, data=body)
|
||||||
return self.model(updated_member)
|
return self.model(updated_member), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, image_id, member_id):
|
def create(self, image_id, member_id):
|
||||||
url = '/v2/images/%s/members' % image_id
|
url = '/v2/images/%s/members' % image_id
|
||||||
body = {'member': member_id}
|
body = {'member': member_id}
|
||||||
resp, created_member = self.http_client.post(url, data=body)
|
resp, created_member = self.http_client.post(url, data=body)
|
||||||
return self.model(created_member)
|
return self.model(created_member), resp
|
||||||
|
@ -30,6 +30,7 @@ class Controller(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def update(self, image_id, tag_value):
|
def update(self, image_id, tag_value):
|
||||||
"""Update an image with the given tag.
|
"""Update an image with the given tag.
|
||||||
|
|
||||||
@ -37,8 +38,10 @@ class Controller(object):
|
|||||||
:param tag_value: value of the tag.
|
:param tag_value: value of the tag.
|
||||||
"""
|
"""
|
||||||
url = '/v2/images/%s/tags/%s' % (image_id, tag_value)
|
url = '/v2/images/%s/tags/%s' % (image_id, tag_value)
|
||||||
self.http_client.put(url)
|
resp, body = self.http_client.put(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, image_id, tag_value):
|
def delete(self, image_id, tag_value):
|
||||||
"""Delete the tag associated with the given image.
|
"""Delete the tag associated with the given image.
|
||||||
|
|
||||||
@ -46,4 +49,5 @@ class Controller(object):
|
|||||||
:param tag_value: tag value to be deleted.
|
:param tag_value: tag value to be deleted.
|
||||||
"""
|
"""
|
||||||
url = '/v2/images/%s/tags/%s' % (image_id, tag_value)
|
url = '/v2/images/%s/tags/%s' % (image_id, tag_value)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
@ -81,6 +81,7 @@ class Controller(object):
|
|||||||
raise exc.HTTPBadRequest(msg)
|
raise exc.HTTPBadRequest(msg)
|
||||||
return sort
|
return sort
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, **kwargs):
|
def list(self, **kwargs):
|
||||||
"""Retrieve a listing of Image objects.
|
"""Retrieve a listing of Image objects.
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ class Controller(object):
|
|||||||
|
|
||||||
def paginate(url, page_size, limit=None):
|
def paginate(url, page_size, limit=None):
|
||||||
next_url = url
|
next_url = url
|
||||||
|
req_id_hdr = {}
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
if limit and page_size > limit:
|
if limit and page_size > limit:
|
||||||
@ -105,7 +107,12 @@ class Controller(object):
|
|||||||
next_url = next_url.replace("limit=%s" % page_size,
|
next_url = next_url.replace("limit=%s" % page_size,
|
||||||
"limit=%s" % limit)
|
"limit=%s" % limit)
|
||||||
|
|
||||||
resp, body = self.http_client.get(next_url)
|
resp, body = self.http_client.get(next_url, headers=req_id_hdr)
|
||||||
|
# NOTE(rsjethani): Store curent request id so that it can be
|
||||||
|
# used in subsequent requests. Refer bug #1525259
|
||||||
|
req_id_hdr['x-openstack-request-id'] = \
|
||||||
|
utils._extract_request_id(resp)
|
||||||
|
|
||||||
for image in body['images']:
|
for image in body['images']:
|
||||||
# NOTE(bcwaldon): remove 'self' for now until we have
|
# NOTE(bcwaldon): remove 'self' for now until we have
|
||||||
# an elegant way to pass it into the model constructor
|
# an elegant way to pass it into the model constructor
|
||||||
@ -114,7 +121,7 @@ class Controller(object):
|
|||||||
# We do not validate the model when listing.
|
# We do not validate the model when listing.
|
||||||
# This prevents side-effects of injecting invalid
|
# This prevents side-effects of injecting invalid
|
||||||
# schema values via v1.
|
# schema values via v1.
|
||||||
yield self.unvalidated_model(**image)
|
yield self.unvalidated_model(**image), resp
|
||||||
if limit:
|
if limit:
|
||||||
limit -= 1
|
limit -= 1
|
||||||
if limit <= 0:
|
if limit <= 0:
|
||||||
@ -173,17 +180,23 @@ class Controller(object):
|
|||||||
if isinstance(kwargs.get('marker'), six.string_types):
|
if isinstance(kwargs.get('marker'), six.string_types):
|
||||||
url = '%s&marker=%s' % (url, kwargs['marker'])
|
url = '%s&marker=%s' % (url, kwargs['marker'])
|
||||||
|
|
||||||
for image in paginate(url, page_size, limit):
|
for image, resp in paginate(url, page_size, limit):
|
||||||
yield image
|
yield image, resp
|
||||||
|
|
||||||
def get(self, image_id):
|
@utils.add_req_id_to_object()
|
||||||
|
def _get(self, image_id, header=None):
|
||||||
url = '/v2/images/%s' % image_id
|
url = '/v2/images/%s' % image_id
|
||||||
resp, body = self.http_client.get(url)
|
header = header or {}
|
||||||
|
resp, body = self.http_client.get(url, headers=header)
|
||||||
# NOTE(bcwaldon): remove 'self' for now until we have an elegant
|
# NOTE(bcwaldon): remove 'self' for now until we have an elegant
|
||||||
# way to pass it into the model constructor without conflict
|
# way to pass it into the model constructor without conflict
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.unvalidated_model(**body)
|
return self.unvalidated_model(**body), resp
|
||||||
|
|
||||||
|
def get(self, image_id):
|
||||||
|
return self._get(image_id)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def data(self, image_id, do_checksum=True):
|
def data(self, image_id, do_checksum=True):
|
||||||
"""Retrieve data of an image.
|
"""Retrieve data of an image.
|
||||||
|
|
||||||
@ -194,7 +207,7 @@ class Controller(object):
|
|||||||
url = '/v2/images/%s/file' % image_id
|
url = '/v2/images/%s/file' % image_id
|
||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
if resp.status_code == codes.no_content:
|
if resp.status_code == codes.no_content:
|
||||||
return None
|
return None, resp
|
||||||
|
|
||||||
checksum = resp.headers.get('content-md5', None)
|
checksum = resp.headers.get('content-md5', None)
|
||||||
content_length = int(resp.headers.get('content-length', 0))
|
content_length = int(resp.headers.get('content-length', 0))
|
||||||
@ -202,8 +215,9 @@ class Controller(object):
|
|||||||
if do_checksum and checksum is not None:
|
if do_checksum and checksum is not None:
|
||||||
body = utils.integrity_iter(body, checksum)
|
body = utils.integrity_iter(body, checksum)
|
||||||
|
|
||||||
return utils.IterableWithLength(body, content_length)
|
return utils.IterableWithLength(body, content_length), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def upload(self, image_id, image_data, image_size=None):
|
def upload(self, image_id, image_data, image_size=None):
|
||||||
"""Upload the data for an image.
|
"""Upload the data for an image.
|
||||||
|
|
||||||
@ -214,13 +228,17 @@ class Controller(object):
|
|||||||
url = '/v2/images/%s/file' % image_id
|
url = '/v2/images/%s/file' % image_id
|
||||||
hdrs = {'Content-Type': 'application/octet-stream'}
|
hdrs = {'Content-Type': 'application/octet-stream'}
|
||||||
body = image_data
|
body = image_data
|
||||||
self.http_client.put(url, headers=hdrs, data=body)
|
resp, body = self.http_client.put(url, headers=hdrs, data=body)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, image_id):
|
def delete(self, image_id):
|
||||||
"""Delete an image."""
|
"""Delete an image."""
|
||||||
url = '/v2/images/%s' % image_id
|
url = '/v2/images/%s' % image_id
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
"""Create an image."""
|
"""Create an image."""
|
||||||
url = '/v2/images'
|
url = '/v2/images'
|
||||||
@ -236,17 +254,21 @@ class Controller(object):
|
|||||||
# NOTE(esheffield): remove 'self' for now until we have an elegant
|
# NOTE(esheffield): remove 'self' for now until we have an elegant
|
||||||
# way to pass it into the model constructor without conflict
|
# way to pass it into the model constructor without conflict
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def deactivate(self, image_id):
|
def deactivate(self, image_id):
|
||||||
"""Deactivate an image."""
|
"""Deactivate an image."""
|
||||||
url = '/v2/images/%s/actions/deactivate' % image_id
|
url = '/v2/images/%s/actions/deactivate' % image_id
|
||||||
return self.http_client.post(url)
|
resp, body = self.http_client.post(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def reactivate(self, image_id):
|
def reactivate(self, image_id):
|
||||||
"""Reactivate an image."""
|
"""Reactivate an image."""
|
||||||
url = '/v2/images/%s/actions/reactivate' % image_id
|
url = '/v2/images/%s/actions/reactivate' % image_id
|
||||||
return self.http_client.post(url)
|
resp, body = self.http_client.post(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
def update(self, image_id, remove_props=None, **kwargs):
|
def update(self, image_id, remove_props=None, **kwargs):
|
||||||
"""Update attributes of an image.
|
"""Update attributes of an image.
|
||||||
@ -276,12 +298,16 @@ class Controller(object):
|
|||||||
|
|
||||||
url = '/v2/images/%s' % image_id
|
url = '/v2/images/%s' % image_id
|
||||||
hdrs = {'Content-Type': 'application/openstack-images-v2.1-json-patch'}
|
hdrs = {'Content-Type': 'application/openstack-images-v2.1-json-patch'}
|
||||||
self.http_client.patch(url, headers=hdrs, data=image.patch)
|
resp, _ = self.http_client.patch(url, headers=hdrs, data=image.patch)
|
||||||
|
# Get request id from `patch` request so it can be passed to the
|
||||||
|
# following `get` call
|
||||||
|
req_id_hdr = {
|
||||||
|
'x-openstack-request-id': utils._extract_request_id(resp)}
|
||||||
|
|
||||||
# NOTE(bcwaldon): calling image.patch doesn't clear the changes, so
|
# NOTE(bcwaldon): calling image.patch doesn't clear the changes, so
|
||||||
# we need to fetch the image again to get a clean history. This is
|
# we need to fetch the image again to get a clean history. This is
|
||||||
# an obvious optimization for warlock
|
# an obvious optimization for warlock
|
||||||
return self.get(image_id)
|
return self._get(image_id, req_id_hdr)
|
||||||
|
|
||||||
def _get_image_with_locations_or_fail(self, image_id):
|
def _get_image_with_locations_or_fail(self, image_id):
|
||||||
image = self.get(image_id)
|
image = self.get(image_id)
|
||||||
@ -290,10 +316,13 @@ class Controller(object):
|
|||||||
'API access to image locations')
|
'API access to image locations')
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def _send_image_update_request(self, image_id, patch_body):
|
def _send_image_update_request(self, image_id, patch_body):
|
||||||
url = '/v2/images/%s' % image_id
|
url = '/v2/images/%s' % image_id
|
||||||
hdrs = {'Content-Type': 'application/openstack-images-v2.1-json-patch'}
|
hdrs = {'Content-Type': 'application/openstack-images-v2.1-json-patch'}
|
||||||
self.http_client.patch(url, headers=hdrs, data=json.dumps(patch_body))
|
resp, body = self.http_client.patch(url, headers=hdrs,
|
||||||
|
data=json.dumps(patch_body))
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
def add_location(self, image_id, url, metadata):
|
def add_location(self, image_id, url, metadata):
|
||||||
"""Add a new location entry to an image's list of locations.
|
"""Add a new location entry to an image's list of locations.
|
||||||
@ -308,8 +337,11 @@ class Controller(object):
|
|||||||
"""
|
"""
|
||||||
add_patch = [{'op': 'add', 'path': '/locations/-',
|
add_patch = [{'op': 'add', 'path': '/locations/-',
|
||||||
'value': {'url': url, 'metadata': metadata}}]
|
'value': {'url': url, 'metadata': metadata}}]
|
||||||
self._send_image_update_request(image_id, add_patch)
|
response = self._send_image_update_request(image_id, add_patch)
|
||||||
return self.get(image_id)
|
# Get request id from the above update request and pass the same to
|
||||||
|
# following get request
|
||||||
|
req_id_hdr = {'x-openstack-request-id': response.request_ids[0]}
|
||||||
|
return self._get(image_id, req_id_hdr)
|
||||||
|
|
||||||
def delete_locations(self, image_id, url_set):
|
def delete_locations(self, image_id, url_set):
|
||||||
"""Remove one or more location entries of an image.
|
"""Remove one or more location entries of an image.
|
||||||
@ -332,7 +364,7 @@ class Controller(object):
|
|||||||
url_indices.sort(reverse=True)
|
url_indices.sort(reverse=True)
|
||||||
patches = [{'op': 'remove', 'path': '/locations/%s' % url_idx}
|
patches = [{'op': 'remove', 'path': '/locations/%s' % url_idx}
|
||||||
for url_idx in url_indices]
|
for url_idx in url_indices]
|
||||||
self._send_image_update_request(image_id, patches)
|
return self._send_image_update_request(image_id, patches)
|
||||||
|
|
||||||
def update_location(self, image_id, url, metadata):
|
def update_location(self, image_id, url, metadata):
|
||||||
"""Update an existing location entry in an image's list of locations.
|
"""Update an existing location entry in an image's list of locations.
|
||||||
@ -359,6 +391,9 @@ class Controller(object):
|
|||||||
patches = [{'op': 'replace',
|
patches = [{'op': 'replace',
|
||||||
'path': '/locations',
|
'path': '/locations',
|
||||||
'value': list(url_map.values())}]
|
'value': list(url_map.values())}]
|
||||||
self._send_image_update_request(image_id, patches)
|
response = self._send_image_update_request(image_id, patches)
|
||||||
|
# Get request id from the above update request and pass the same to
|
||||||
|
# following get request
|
||||||
|
req_id_hdr = {'x-openstack-request-id': response.request_ids[0]}
|
||||||
|
|
||||||
return self.get(image_id)
|
return self._get(image_id, req_id_hdr)
|
||||||
|
@ -37,6 +37,7 @@ class NamespaceController(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
"""Create a namespace.
|
"""Create a namespace.
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ class NamespaceController(object):
|
|||||||
|
|
||||||
resp, body = self.http_client.post(url, data=namespace)
|
resp, body = self.http_client.post(url, data=namespace)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
def update(self, namespace_name, **kwargs):
|
def update(self, namespace_name, **kwargs):
|
||||||
"""Update a namespace.
|
"""Update a namespace.
|
||||||
@ -72,23 +73,34 @@ class NamespaceController(object):
|
|||||||
del namespace[elem]
|
del namespace[elem]
|
||||||
|
|
||||||
url = '/v2/metadefs/namespaces/{0}'.format(namespace_name)
|
url = '/v2/metadefs/namespaces/{0}'.format(namespace_name)
|
||||||
self.http_client.put(url, data=namespace)
|
# Pass the original wrapped value to http client.
|
||||||
|
resp, _ = self.http_client.put(url, data=namespace.wrapped)
|
||||||
return self.get(namespace.namespace)
|
# Get request id from `put` request so it can be passed to the
|
||||||
|
# following `get` call
|
||||||
|
req_id_hdr = {
|
||||||
|
'x-openstack-request-id': utils._extract_request_id(resp)
|
||||||
|
}
|
||||||
|
return self._get(namespace.namespace, header=req_id_hdr)
|
||||||
|
|
||||||
def get(self, namespace, **kwargs):
|
def get(self, namespace, **kwargs):
|
||||||
|
return self._get(namespace, **kwargs)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
|
def _get(self, namespace, header=None, **kwargs):
|
||||||
"""Get one namespace."""
|
"""Get one namespace."""
|
||||||
query_params = parse.urlencode(kwargs)
|
query_params = parse.urlencode(kwargs)
|
||||||
if kwargs:
|
if kwargs:
|
||||||
query_params = '?%s' % query_params
|
query_params = '?%s' % query_params
|
||||||
|
|
||||||
url = '/v2/metadefs/namespaces/{0}{1}'.format(namespace, query_params)
|
url = '/v2/metadefs/namespaces/{0}{1}'.format(namespace, query_params)
|
||||||
resp, body = self.http_client.get(url)
|
header = header or {}
|
||||||
|
resp, body = self.http_client.get(url, headers=header)
|
||||||
# NOTE(bcwaldon): remove 'self' for now until we have an elegant
|
# NOTE(bcwaldon): remove 'self' for now until we have an elegant
|
||||||
# way to pass it into the model constructor without conflict
|
# way to pass it into the model constructor without conflict
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, **kwargs):
|
def list(self, **kwargs):
|
||||||
"""Retrieve a listing of Namespace objects.
|
"""Retrieve a listing of Namespace objects.
|
||||||
|
|
||||||
@ -117,7 +129,7 @@ class NamespaceController(object):
|
|||||||
# an elegant way to pass it into the model constructor
|
# an elegant way to pass it into the model constructor
|
||||||
# without conflict.
|
# without conflict.
|
||||||
namespace.pop('self', None)
|
namespace.pop('self', None)
|
||||||
yield self.model(**namespace)
|
yield self.model(**namespace), resp
|
||||||
# NOTE(zhiyan): In order to resolve the performance issue
|
# NOTE(zhiyan): In order to resolve the performance issue
|
||||||
# of JSON schema validation for image listing case, we
|
# of JSON schema validation for image listing case, we
|
||||||
# don't validate each image entry but do it only on first
|
# don't validate each image entry but do it only on first
|
||||||
@ -132,8 +144,8 @@ class NamespaceController(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
for namespace in paginate(next_url):
|
for namespace, resp in paginate(next_url):
|
||||||
yield namespace
|
yield namespace, resp
|
||||||
|
|
||||||
filters = kwargs.get('filters', {})
|
filters = kwargs.get('filters', {})
|
||||||
filters = {} if filters is None else filters
|
filters = {} if filters is None else filters
|
||||||
@ -170,13 +182,15 @@ class NamespaceController(object):
|
|||||||
|
|
||||||
url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters)
|
url = '/v2/metadefs/namespaces?%s' % parse.urlencode(filters)
|
||||||
|
|
||||||
for namespace in paginate(url):
|
for namespace, resp in paginate(url):
|
||||||
yield namespace
|
yield namespace, resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, namespace):
|
def delete(self, namespace):
|
||||||
"""Delete a namespace."""
|
"""Delete a namespace."""
|
||||||
url = '/v2/metadefs/namespaces/{0}'.format(namespace)
|
url = '/v2/metadefs/namespaces/{0}'.format(namespace)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
|
||||||
class ResourceTypeController(object):
|
class ResourceTypeController(object):
|
||||||
@ -190,6 +204,7 @@ class ResourceTypeController(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def associate(self, namespace, **kwargs):
|
def associate(self, namespace, **kwargs):
|
||||||
"""Associate a resource type with a namespace."""
|
"""Associate a resource type with a namespace."""
|
||||||
try:
|
try:
|
||||||
@ -201,14 +216,17 @@ class ResourceTypeController(object):
|
|||||||
res_type)
|
res_type)
|
||||||
resp, body = self.http_client.post(url, data=res_type)
|
resp, body = self.http_client.post(url, data=res_type)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def deassociate(self, namespace, resource):
|
def deassociate(self, namespace, resource):
|
||||||
"""Deassociate a resource type with a namespace."""
|
"""Deassociate a resource type with a namespace."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/resource_types/{1}'. \
|
url = '/v2/metadefs/namespaces/{0}/resource_types/{1}'. \
|
||||||
format(namespace, resource)
|
format(namespace, resource)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self):
|
def list(self):
|
||||||
"""Retrieve a listing of available resource types.
|
"""Retrieve a listing of available resource types.
|
||||||
|
|
||||||
@ -218,14 +236,15 @@ class ResourceTypeController(object):
|
|||||||
url = '/v2/metadefs/resource_types'
|
url = '/v2/metadefs/resource_types'
|
||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
for resource_type in body['resource_types']:
|
for resource_type in body['resource_types']:
|
||||||
yield self.model(**resource_type)
|
yield self.model(**resource_type), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def get(self, namespace):
|
def get(self, namespace):
|
||||||
url = '/v2/metadefs/namespaces/{0}/resource_types'.format(namespace)
|
url = '/v2/metadefs/namespaces/{0}/resource_types'.format(namespace)
|
||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
for resource_type in body['resource_type_associations']:
|
for resource_type in body['resource_type_associations']:
|
||||||
yield self.model(**resource_type)
|
yield self.model(**resource_type), resp
|
||||||
|
|
||||||
|
|
||||||
class PropertyController(object):
|
class PropertyController(object):
|
||||||
@ -239,6 +258,7 @@ class PropertyController(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, namespace, **kwargs):
|
def create(self, namespace, **kwargs):
|
||||||
"""Create a property.
|
"""Create a property.
|
||||||
|
|
||||||
@ -254,7 +274,7 @@ class PropertyController(object):
|
|||||||
|
|
||||||
resp, body = self.http_client.post(url, data=prop)
|
resp, body = self.http_client.post(url, data=prop)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
def update(self, namespace, prop_name, **kwargs):
|
def update(self, namespace, prop_name, **kwargs):
|
||||||
"""Update a property.
|
"""Update a property.
|
||||||
@ -272,18 +292,29 @@ class PropertyController(object):
|
|||||||
|
|
||||||
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
|
||||||
prop_name)
|
prop_name)
|
||||||
self.http_client.put(url, data=prop)
|
# Pass the original wrapped value to http client.
|
||||||
|
resp, _ = self.http_client.put(url, data=prop.wrapped)
|
||||||
|
# Get request id from `put` request so it can be passed to the
|
||||||
|
# following `get` call
|
||||||
|
req_id_hdr = {
|
||||||
|
'x-openstack-request-id': utils._extract_request_id(resp)}
|
||||||
|
|
||||||
return self.get(namespace, prop.name)
|
return self._get(namespace, prop.name, req_id_hdr)
|
||||||
|
|
||||||
def get(self, namespace, prop_name):
|
def get(self, namespace, prop_name):
|
||||||
|
return self._get(namespace, prop_name)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
|
def _get(self, namespace, prop_name, header=None):
|
||||||
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
|
||||||
prop_name)
|
prop_name)
|
||||||
resp, body = self.http_client.get(url)
|
header = header or {}
|
||||||
|
resp, body = self.http_client.get(url, headers=header)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
body['name'] = prop_name
|
body['name'] = prop_name
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, namespace, **kwargs):
|
def list(self, namespace, **kwargs):
|
||||||
"""Retrieve a listing of metadata properties.
|
"""Retrieve a listing of metadata properties.
|
||||||
|
|
||||||
@ -295,18 +326,22 @@ class PropertyController(object):
|
|||||||
|
|
||||||
for key, value in body['properties'].items():
|
for key, value in body['properties'].items():
|
||||||
value['name'] = key
|
value['name'] = key
|
||||||
yield self.model(value)
|
yield self.model(value), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, namespace, prop_name):
|
def delete(self, namespace, prop_name):
|
||||||
"""Delete a property."""
|
"""Delete a property."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/properties/{1}'.format(namespace,
|
||||||
prop_name)
|
prop_name)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete_all(self, namespace):
|
def delete_all(self, namespace):
|
||||||
"""Delete all properties in a namespace."""
|
"""Delete all properties in a namespace."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace)
|
url = '/v2/metadefs/namespaces/{0}/properties'.format(namespace)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
|
||||||
class ObjectController(object):
|
class ObjectController(object):
|
||||||
@ -320,6 +355,7 @@ class ObjectController(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, namespace, **kwargs):
|
def create(self, namespace, **kwargs):
|
||||||
"""Create an object.
|
"""Create an object.
|
||||||
|
|
||||||
@ -335,7 +371,7 @@ class ObjectController(object):
|
|||||||
|
|
||||||
resp, body = self.http_client.post(url, data=obj)
|
resp, body = self.http_client.post(url, data=obj)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
def update(self, namespace, object_name, **kwargs):
|
def update(self, namespace, object_name, **kwargs):
|
||||||
"""Update an object.
|
"""Update an object.
|
||||||
@ -359,17 +395,28 @@ class ObjectController(object):
|
|||||||
|
|
||||||
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
|
||||||
object_name)
|
object_name)
|
||||||
self.http_client.put(url, data=obj)
|
# Pass the original wrapped value to http client.
|
||||||
|
resp, _ = self.http_client.put(url, data=obj.wrapped)
|
||||||
|
# Get request id from `put` request so it can be passed to the
|
||||||
|
# following `get` call
|
||||||
|
req_id_hdr = {
|
||||||
|
'x-openstack-request-id': utils._extract_request_id(resp)}
|
||||||
|
|
||||||
return self.get(namespace, obj.name)
|
return self._get(namespace, obj.name, req_id_hdr)
|
||||||
|
|
||||||
def get(self, namespace, object_name):
|
def get(self, namespace, object_name):
|
||||||
|
return self._get(namespace, object_name)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
|
def _get(self, namespace, object_name, header=None):
|
||||||
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
|
||||||
object_name)
|
object_name)
|
||||||
resp, body = self.http_client.get(url)
|
header = header or {}
|
||||||
|
resp, body = self.http_client.get(url, headers=header)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, namespace, **kwargs):
|
def list(self, namespace, **kwargs):
|
||||||
"""Retrieve a listing of metadata objects.
|
"""Retrieve a listing of metadata objects.
|
||||||
|
|
||||||
@ -379,18 +426,22 @@ class ObjectController(object):
|
|||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
|
|
||||||
for obj in body['objects']:
|
for obj in body['objects']:
|
||||||
yield self.model(obj)
|
yield self.model(obj), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, namespace, object_name):
|
def delete(self, namespace, object_name):
|
||||||
"""Delete an object."""
|
"""Delete an object."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/objects/{1}'.format(namespace,
|
||||||
object_name)
|
object_name)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete_all(self, namespace):
|
def delete_all(self, namespace):
|
||||||
"""Delete all objects in a namespace."""
|
"""Delete all objects in a namespace."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace)
|
url = '/v2/metadefs/namespaces/{0}/objects'.format(namespace)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
|
||||||
class TagController(object):
|
class TagController(object):
|
||||||
@ -404,6 +455,7 @@ class TagController(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, namespace, tag_name):
|
def create(self, namespace, tag_name):
|
||||||
"""Create a tag.
|
"""Create a tag.
|
||||||
|
|
||||||
@ -416,8 +468,9 @@ class TagController(object):
|
|||||||
|
|
||||||
resp, body = self.http_client.post(url)
|
resp, body = self.http_client.post(url)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def create_multiple(self, namespace, **kwargs):
|
def create_multiple(self, namespace, **kwargs):
|
||||||
"""Create the list of tags.
|
"""Create the list of tags.
|
||||||
|
|
||||||
@ -440,7 +493,7 @@ class TagController(object):
|
|||||||
resp, body = self.http_client.post(url, data=tags)
|
resp, body = self.http_client.post(url, data=tags)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
for tag in body['tags']:
|
for tag in body['tags']:
|
||||||
yield self.model(tag)
|
yield self.model(tag), resp
|
||||||
|
|
||||||
def update(self, namespace, tag_name, **kwargs):
|
def update(self, namespace, tag_name, **kwargs):
|
||||||
"""Update a tag.
|
"""Update a tag.
|
||||||
@ -464,17 +517,28 @@ class TagController(object):
|
|||||||
|
|
||||||
url = '/v2/metadefs/namespaces/{0}/tags/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/tags/{1}'.format(namespace,
|
||||||
tag_name)
|
tag_name)
|
||||||
self.http_client.put(url, data=tag)
|
# Pass the original wrapped value to http client.
|
||||||
|
resp, _ = self.http_client.put(url, data=tag.wrapped)
|
||||||
|
# Get request id from `put` request so it can be passed to the
|
||||||
|
# following `get` call
|
||||||
|
req_id_hdr = {
|
||||||
|
'x-openstack-request-id': utils._extract_request_id(resp)}
|
||||||
|
|
||||||
return self.get(namespace, tag.name)
|
return self._get(namespace, tag.name, req_id_hdr)
|
||||||
|
|
||||||
def get(self, namespace, tag_name):
|
def get(self, namespace, tag_name):
|
||||||
|
return self._get(namespace, tag_name)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
|
def _get(self, namespace, tag_name, header=None):
|
||||||
url = '/v2/metadefs/namespaces/{0}/tags/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/tags/{1}'.format(namespace,
|
||||||
tag_name)
|
tag_name)
|
||||||
resp, body = self.http_client.get(url)
|
header = header or {}
|
||||||
|
resp, body = self.http_client.get(url, headers=header)
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, namespace, **kwargs):
|
def list(self, namespace, **kwargs):
|
||||||
"""Retrieve a listing of metadata tags.
|
"""Retrieve a listing of metadata tags.
|
||||||
|
|
||||||
@ -484,15 +548,19 @@ class TagController(object):
|
|||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
|
|
||||||
for tag in body['tags']:
|
for tag in body['tags']:
|
||||||
yield self.model(tag)
|
yield self.model(tag), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete(self, namespace, tag_name):
|
def delete(self, namespace, tag_name):
|
||||||
"""Delete a tag."""
|
"""Delete a tag."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/tags/{1}'.format(namespace,
|
url = '/v2/metadefs/namespaces/{0}/tags/{1}'.format(namespace,
|
||||||
tag_name)
|
tag_name)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def delete_all(self, namespace):
|
def delete_all(self, namespace):
|
||||||
"""Delete all tags in a namespace."""
|
"""Delete all tags in a namespace."""
|
||||||
url = '/v2/metadefs/namespaces/{0}/tags'.format(namespace)
|
url = '/v2/metadefs/namespaces/{0}/tags'.format(namespace)
|
||||||
self.http_client.delete(url)
|
resp, body = self.http_client.delete(url)
|
||||||
|
return (resp, body), resp
|
||||||
|
@ -38,6 +38,7 @@ class Controller(object):
|
|||||||
return warlock.model_factory(schema.raw(),
|
return warlock.model_factory(schema.raw(),
|
||||||
base_class=schemas.SchemaBasedModel)
|
base_class=schemas.SchemaBasedModel)
|
||||||
|
|
||||||
|
@utils.add_req_id_to_generator()
|
||||||
def list(self, **kwargs):
|
def list(self, **kwargs):
|
||||||
"""Retrieve a listing of Task objects.
|
"""Retrieve a listing of Task objects.
|
||||||
|
|
||||||
@ -48,14 +49,14 @@ class Controller(object):
|
|||||||
def paginate(url):
|
def paginate(url):
|
||||||
resp, body = self.http_client.get(url)
|
resp, body = self.http_client.get(url)
|
||||||
for task in body['tasks']:
|
for task in body['tasks']:
|
||||||
yield task
|
yield task, resp
|
||||||
try:
|
try:
|
||||||
next_url = body['next']
|
next_url = body['next']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
for task in paginate(next_url):
|
for task, resp in paginate(next_url):
|
||||||
yield task
|
yield task, resp
|
||||||
|
|
||||||
filters = kwargs.get('filters', {})
|
filters = kwargs.get('filters', {})
|
||||||
|
|
||||||
@ -88,12 +89,13 @@ class Controller(object):
|
|||||||
filters[param] = encodeutils.safe_encode(value)
|
filters[param] = encodeutils.safe_encode(value)
|
||||||
|
|
||||||
url = '/v2/tasks?%s' % six.moves.urllib.parse.urlencode(filters)
|
url = '/v2/tasks?%s' % six.moves.urllib.parse.urlencode(filters)
|
||||||
for task in paginate(url):
|
for task, resp in paginate(url):
|
||||||
# NOTE(flwang): remove 'self' for now until we have an elegant
|
# NOTE(flwang): remove 'self' for now until we have an elegant
|
||||||
# way to pass it into the model constructor without conflict
|
# way to pass it into the model constructor without conflict
|
||||||
task.pop('self', None)
|
task.pop('self', None)
|
||||||
yield self.model(**task)
|
yield self.model(**task), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def get(self, task_id):
|
def get(self, task_id):
|
||||||
"""Get a task based on given task id."""
|
"""Get a task based on given task id."""
|
||||||
url = '/v2/tasks/%s' % task_id
|
url = '/v2/tasks/%s' % task_id
|
||||||
@ -101,8 +103,9 @@ class Controller(object):
|
|||||||
# NOTE(flwang): remove 'self' for now until we have an elegant
|
# NOTE(flwang): remove 'self' for now until we have an elegant
|
||||||
# way to pass it into the model constructor without conflict
|
# way to pass it into the model constructor without conflict
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
|
||||||
|
@utils.add_req_id_to_object()
|
||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
"""Create a new task."""
|
"""Create a new task."""
|
||||||
url = '/v2/tasks'
|
url = '/v2/tasks'
|
||||||
@ -118,4 +121,4 @@ class Controller(object):
|
|||||||
# NOTE(flwang): remove 'self' for now until we have an elegant
|
# NOTE(flwang): remove 'self' for now until we have an elegant
|
||||||
# way to pass it into the model constructor without conflict
|
# way to pass it into the model constructor without conflict
|
||||||
body.pop('self', None)
|
body.pop('self', None)
|
||||||
return self.model(**body)
|
return self.model(**body), resp
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Added support to return "x-openstack-request-id" header in request_ids attribute
|
||||||
|
for better tracing.
|
||||||
|
|
||||||
|
| For ex.
|
||||||
|
| >>> from glanceclient import Client
|
||||||
|
| >>> glance = Client('2', endpoint='OS_IMAGE_ENDPOINT', token='OS_AUTH_TOKEN')
|
||||||
|
| >>> res = glance.images.get('<image_id>')
|
||||||
|
| >>> res.request_ids
|
@ -10,3 +10,4 @@ warlock!=1.3.0,<2,>=1.0.1 # Apache-2.0
|
|||||||
six>=1.9.0 # MIT
|
six>=1.9.0 # MIT
|
||||||
oslo.utils>=3.18.0 # Apache-2.0
|
oslo.utils>=3.18.0 # Apache-2.0
|
||||||
oslo.i18n>=2.1.0 # Apache-2.0
|
oslo.i18n>=2.1.0 # Apache-2.0
|
||||||
|
wrapt>=1.7.0 # BSD License
|
||||||
|
Loading…
Reference in New Issue
Block a user