Move image_meta_to_headers from images_client
Glance v1 images_client contains image_meta_to_headers() which converts a dict to headers. However, most service clients' methods don't convert like that. Then this moves image_meta_to_headers() to common place like the compute module from the service client. Partially implements blueprint consistent-service-method-names Change-Id: Id8e47fd35f7667578854bc439238a4b0f36fbb8f
This commit is contained in:
parent
f9b4068fb1
commit
02bcdf36db
@ -16,6 +16,7 @@
|
||||
import six
|
||||
|
||||
from tempest.api.compute import base
|
||||
from tempest.common import image as common_image
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
@ -55,15 +56,18 @@ class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
|
||||
super(ImagesMetadataTestJSON, cls).resource_setup()
|
||||
cls.image_id = None
|
||||
|
||||
name = data_utils.rand_name('image')
|
||||
params = {
|
||||
'name': data_utils.rand_name('image'),
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'raw'
|
||||
}
|
||||
if CONF.image_feature_enabled.api_v1:
|
||||
kwargs = dict(is_public=False)
|
||||
params.update({'is_public': False})
|
||||
params = {'headers': common_image.image_meta_to_headers(**params)}
|
||||
else:
|
||||
kwargs = dict(visibility='private')
|
||||
body = cls.glance_client.create_image(name=name,
|
||||
container_format='bare',
|
||||
disk_format='raw',
|
||||
**kwargs)
|
||||
params.update({'visibility': 'private'})
|
||||
|
||||
body = cls.glance_client.create_image(**params)
|
||||
body = body['image'] if 'image' in body else body
|
||||
cls.image_id = body['id']
|
||||
cls.images.append(cls.image_id)
|
||||
|
@ -19,6 +19,7 @@ import six
|
||||
import testtools
|
||||
|
||||
from tempest.api.compute import base
|
||||
from tempest.common import image as common_image
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
@ -58,15 +59,19 @@ class ListImageFiltersTestJSON(base.BaseV2ComputeTest):
|
||||
super(ListImageFiltersTestJSON, cls).resource_setup()
|
||||
|
||||
def _create_image():
|
||||
name = data_utils.rand_name('image')
|
||||
params = {
|
||||
'name': data_utils.rand_name('image'),
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'raw'
|
||||
}
|
||||
if CONF.image_feature_enabled.api_v1:
|
||||
kwargs = dict(is_public=False)
|
||||
params.update({'is_public': False})
|
||||
params = {'headers':
|
||||
common_image.image_meta_to_headers(**params)}
|
||||
else:
|
||||
kwargs = dict(visibility='private')
|
||||
body = cls.glance_client.create_image(name=name,
|
||||
container_format='bare',
|
||||
disk_format='raw',
|
||||
**kwargs)
|
||||
params.update({'visibility': 'private'})
|
||||
|
||||
body = cls.glance_client.create_image(**params)
|
||||
body = body['image'] if 'image' in body else body
|
||||
image_id = body['id']
|
||||
cls.images.append(image_id)
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
from six import moves
|
||||
|
||||
from tempest.common import image as common_image
|
||||
from tempest.common.utils import data_utils
|
||||
from tempest import config
|
||||
from tempest.lib.common.utils import test_utils
|
||||
@ -55,14 +56,20 @@ class BaseImageTest(tempest.test.BaseTestCase):
|
||||
super(BaseImageTest, cls).resource_cleanup()
|
||||
|
||||
@classmethod
|
||||
def create_image(cls, **kwargs):
|
||||
def create_image(cls, data=None, **kwargs):
|
||||
"""Wrapper that returns a test image."""
|
||||
|
||||
if 'name' not in kwargs:
|
||||
name = data_utils.rand_name(cls.__name__ + "-instance")
|
||||
kwargs['name'] = name
|
||||
|
||||
image = cls.client.create_image(**kwargs)
|
||||
params = cls._get_create_params(**kwargs)
|
||||
if data:
|
||||
# NOTE: On glance v1 API, the data should be passed on
|
||||
# a header. Then here handles the data separately.
|
||||
params['data'] = data
|
||||
|
||||
image = cls.client.create_image(**params)
|
||||
# Image objects returned by the v1 client have the image
|
||||
# data inside a dict that is keyed against 'image'.
|
||||
if 'image' in image:
|
||||
@ -70,6 +77,10 @@ class BaseImageTest(tempest.test.BaseTestCase):
|
||||
cls.created_images.append(image['id'])
|
||||
return image
|
||||
|
||||
@classmethod
|
||||
def _get_create_params(cls, **kwargs):
|
||||
return kwargs
|
||||
|
||||
|
||||
class BaseV1ImageTest(BaseImageTest):
|
||||
|
||||
@ -85,6 +96,10 @@ class BaseV1ImageTest(BaseImageTest):
|
||||
super(BaseV1ImageTest, cls).setup_clients()
|
||||
cls.client = cls.os.image_client
|
||||
|
||||
@classmethod
|
||||
def _get_create_params(cls, **kwargs):
|
||||
return {'headers': common_image.image_meta_to_headers(**kwargs)}
|
||||
|
||||
|
||||
class BaseV1ImageMembersTest(BaseV1ImageTest):
|
||||
|
||||
|
@ -320,8 +320,10 @@ class UpdateImageMetaTest(base.BaseV1ImageTest):
|
||||
metadata = common_image.get_image_meta_from_headers(resp)
|
||||
self.assertEqual(metadata['properties'], {'key1': 'value1'})
|
||||
metadata['properties'].update(req_metadata)
|
||||
metadata = self.client.update_image(
|
||||
self.image_id, properties=metadata['properties'])['image']
|
||||
headers = common_image.image_meta_to_headers(
|
||||
properties=metadata['properties'])
|
||||
metadata = self.client.update_image(self.image_id,
|
||||
headers=headers)['image']
|
||||
|
||||
resp = self.client.check_image(self.image_id)
|
||||
resp_metadata = common_image.get_image_meta_from_headers(resp)
|
||||
|
@ -27,17 +27,17 @@ class CreateDeleteImagesNegativeTest(base.BaseV1ImageTest):
|
||||
def test_register_with_invalid_container_format(self):
|
||||
# Negative tests for invalid data supplied to POST /images
|
||||
self.assertRaises(lib_exc.BadRequest, self.client.create_image,
|
||||
name='test',
|
||||
container_format='wrong',
|
||||
disk_format='vhd',)
|
||||
headers={'x-image-meta-name': 'test',
|
||||
'x-image-meta-container_format': 'wrong',
|
||||
'x-image-meta-disk_format': 'vhd'})
|
||||
|
||||
@test.attr(type=['negative'])
|
||||
@test.idempotent_id('993face5-921d-4e84-aabf-c1bba4234a67')
|
||||
def test_register_with_invalid_disk_format(self):
|
||||
self.assertRaises(lib_exc.BadRequest, self.client.create_image,
|
||||
name='test',
|
||||
container_format='bare',
|
||||
disk_format='wrong',)
|
||||
headers={'x-image-meta-name': 'test',
|
||||
'x-image-meta-container_format': 'bare',
|
||||
'x-image-meta-disk_format': 'wrong'})
|
||||
|
||||
@test.attr(type=['negative'])
|
||||
@test.idempotent_id('bb016f15-0820-4f27-a92d-09b2f67d2488')
|
||||
|
@ -13,6 +13,10 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
import six
|
||||
|
||||
|
||||
def get_image_meta_from_headers(resp):
|
||||
meta = {'properties': {}}
|
||||
@ -36,3 +40,23 @@ def get_image_meta_from_headers(resp):
|
||||
except ValueError:
|
||||
pass
|
||||
return meta
|
||||
|
||||
|
||||
def image_meta_to_headers(**metadata):
|
||||
headers = {}
|
||||
fields_copy = copy.deepcopy(metadata)
|
||||
|
||||
copy_from = fields_copy.pop('copy_from', None)
|
||||
if copy_from is not None:
|
||||
headers['x-glance-api-copy-from'] = copy_from
|
||||
|
||||
for key, value in six.iteritems(fields_copy.pop('properties', {})):
|
||||
headers['x-image-meta-property-%s' % key] = str(value)
|
||||
|
||||
for key, value in six.iteritems(fields_copy.pop('api', {})):
|
||||
headers['x-glance-api-property-%s' % key] = str(value)
|
||||
|
||||
for key, value in six.iteritems(fields_copy):
|
||||
headers['x-image-meta-%s' % key] = str(value)
|
||||
|
||||
return headers
|
||||
|
@ -388,6 +388,7 @@ class ScenarioTest(tempest.test.BaseTestCase):
|
||||
if CONF.image_feature_enabled.api_v1:
|
||||
params['is_public'] = 'False'
|
||||
params['properties'] = properties
|
||||
params = {'headers': common_image.image_meta_to_headers(**params)}
|
||||
else:
|
||||
params['visibility'] = 'private'
|
||||
# Additional properties are flattened out in the v2 API.
|
||||
|
@ -13,11 +13,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import functools
|
||||
|
||||
from oslo_serialization import jsonutils as json
|
||||
import six
|
||||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.common import rest_client
|
||||
@ -29,20 +27,6 @@ CHUNKSIZE = 1024 * 64 # 64kB
|
||||
class ImagesClient(rest_client.RestClient):
|
||||
api_version = "v1"
|
||||
|
||||
def _image_meta_to_headers(self, fields):
|
||||
headers = {}
|
||||
fields_copy = copy.deepcopy(fields)
|
||||
copy_from = fields_copy.pop('copy_from', None)
|
||||
if copy_from is not None:
|
||||
headers['x-glance-api-copy-from'] = copy_from
|
||||
for key, value in six.iteritems(fields_copy.pop('properties', {})):
|
||||
headers['x-image-meta-property-%s' % key] = str(value)
|
||||
for key, value in six.iteritems(fields_copy.pop('api', {})):
|
||||
headers['x-glance-api-property-%s' % key] = str(value)
|
||||
for key, value in six.iteritems(fields_copy):
|
||||
headers['x-image-meta-%s' % key] = str(value)
|
||||
return headers
|
||||
|
||||
def _create_with_data(self, headers, data):
|
||||
# We are going to do chunked transfert, so split the input data
|
||||
# info fixed-sized chunks.
|
||||
@ -74,14 +58,14 @@ class ImagesClient(rest_client.RestClient):
|
||||
self._http = self._get_http()
|
||||
return self._http
|
||||
|
||||
def create_image(self, data=None, **kwargs):
|
||||
def create_image(self, data=None, headers=None):
|
||||
"""Create an image.
|
||||
|
||||
Available params: http://developer.openstack.org/
|
||||
api-ref-image-v1.html#createImage-v1
|
||||
"""
|
||||
headers = {}
|
||||
headers.update(self._image_meta_to_headers(kwargs))
|
||||
if headers is None:
|
||||
headers = {}
|
||||
|
||||
if data is not None:
|
||||
return self._create_with_data(headers, data)
|
||||
@ -91,14 +75,14 @@ class ImagesClient(rest_client.RestClient):
|
||||
body = json.loads(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def update_image(self, image_id, data=None, **kwargs):
|
||||
def update_image(self, image_id, data=None, headers=None):
|
||||
"""Update an image.
|
||||
|
||||
Available params: http://developer.openstack.org/
|
||||
api-ref-image-v1.html#updateImage-v1
|
||||
"""
|
||||
headers = {}
|
||||
headers.update(self._image_meta_to_headers(kwargs))
|
||||
if headers is None:
|
||||
headers = {}
|
||||
|
||||
if data is not None:
|
||||
return self._update_with_data(image_id, headers, data)
|
||||
|
@ -38,3 +38,22 @@ class TestImage(base.TestCase):
|
||||
'name': 'New Http Image'
|
||||
}
|
||||
self.assertEqual(expected, observed)
|
||||
|
||||
def test_image_meta_to_headers(self):
|
||||
observed = image.image_meta_to_headers(
|
||||
name='test',
|
||||
container_format='wrong',
|
||||
disk_format='vhd',
|
||||
copy_from='http://localhost/images/10',
|
||||
properties={'foo': 'bar'},
|
||||
api={'abc': 'def'})
|
||||
|
||||
expected = {
|
||||
'x-image-meta-name': 'test',
|
||||
'x-image-meta-container_format': 'wrong',
|
||||
'x-image-meta-disk_format': 'vhd',
|
||||
'x-glance-api-copy-from': 'http://localhost/images/10',
|
||||
'x-image-meta-property-foo': 'bar',
|
||||
'x-glance-api-property-abc': 'def'
|
||||
}
|
||||
self.assertEqual(expected, observed)
|
||||
|
Loading…
Reference in New Issue
Block a user