Basic testing
This commit is contained in:
@@ -29,21 +29,34 @@ class Image(base.Resource):
|
|||||||
class ImageManager(base.Manager):
|
class ImageManager(base.Manager):
|
||||||
resource_class = Image
|
resource_class = Image
|
||||||
|
|
||||||
def get(self, image):
|
def _image_meta_from_headers(self, headers):
|
||||||
"""Get the metadata for a specific image.
|
|
||||||
|
|
||||||
:param image: image object or id to look up
|
|
||||||
:rtype: :class:`Image`
|
|
||||||
"""
|
|
||||||
resp, body = self.api.head("/images/%s" % base.getid(image))
|
|
||||||
meta = {'properties': {}}
|
meta = {'properties': {}}
|
||||||
for key, value in resp.iteritems():
|
for key, value in headers.iteritems():
|
||||||
if key.startswith('x-image-meta-property-'):
|
if key.startswith('x-image-meta-property-'):
|
||||||
_key = key[22:]
|
_key = key[22:]
|
||||||
meta['properties'][_key] = value
|
meta['properties'][_key] = value
|
||||||
elif key.startswith('x-image-meta-'):
|
elif key.startswith('x-image-meta-'):
|
||||||
_key = key[13:]
|
_key = key[13:]
|
||||||
meta[_key] = value
|
meta[_key] = value
|
||||||
|
return meta
|
||||||
|
|
||||||
|
def _image_meta_to_headers(self, fields):
|
||||||
|
headers = {}
|
||||||
|
for key, value in fields.iteritems():
|
||||||
|
if key == 'properties':
|
||||||
|
headers['x-image-meta-property-%s' % key] = value
|
||||||
|
else:
|
||||||
|
headers['x-image-meta-%s' % key] = value
|
||||||
|
return headers
|
||||||
|
|
||||||
|
def get(self, image):
|
||||||
|
"""Get the metadata for a specific image.
|
||||||
|
|
||||||
|
:param image: image object or id to look up
|
||||||
|
:rtype: :class:`Image`
|
||||||
|
"""
|
||||||
|
resp, body = self.api.head('/v1/images/%s' % base.getid(image))
|
||||||
|
meta = self._image_meta_from_headers(resp)
|
||||||
return Image(self, meta)
|
return Image(self, meta)
|
||||||
|
|
||||||
def list(self, limit=None, marker=None):
|
def list(self, limit=None, marker=None):
|
||||||
@@ -58,13 +71,29 @@ class ImageManager(base.Manager):
|
|||||||
params['limit'] = int(limit)
|
params['limit'] = int(limit)
|
||||||
if marker:
|
if marker:
|
||||||
params['marker'] = int(marker)
|
params['marker'] = int(marker)
|
||||||
|
query = '?%s' % urllib.urlencode(params) if params else ''
|
||||||
query = ""
|
return self._list('/v1/images/detail%s' % query, "images")
|
||||||
if params:
|
|
||||||
query = "?" + urllib.urlencode(params)
|
|
||||||
|
|
||||||
return self._list("/images/detail%s" % query, "images")
|
|
||||||
|
|
||||||
def delete(self, image):
|
def delete(self, image):
|
||||||
"""Delete an image."""
|
"""Delete an image."""
|
||||||
self._delete("/images/%s" % base.getid(image))
|
self._delete("/v1/images/%s" % base.getid(image))
|
||||||
|
|
||||||
|
def create(self, **kwargs):
|
||||||
|
"""Create an image"""
|
||||||
|
fields = {}
|
||||||
|
if 'name' in kwargs:
|
||||||
|
fields['name'] = kwargs['name']
|
||||||
|
resp, body = self.api.post('/v1/images', body={'image': fields})
|
||||||
|
meta = self._image_meta_from_headers(resp)
|
||||||
|
return Image(self, meta)
|
||||||
|
|
||||||
|
def update(self, image, **kwargs):
|
||||||
|
"""Update an image"""
|
||||||
|
fields = {}
|
||||||
|
if 'name' in kwargs:
|
||||||
|
fields['name'] = kwargs['name']
|
||||||
|
send_meta = self._image_meta_to_headers(fields)
|
||||||
|
url = '/v1/images/%s' % base.getid(image)
|
||||||
|
resp, body = self.api.put(url, headers=send_meta)
|
||||||
|
recv_meta = self._image_meta_from_headers(resp)
|
||||||
|
return Image(self, recv_meta)
|
||||||
|
@@ -50,7 +50,7 @@ function run_tests {
|
|||||||
function run_pep8 {
|
function run_pep8 {
|
||||||
echo "Running pep8..."
|
echo "Running pep8..."
|
||||||
PEP8_OPTIONS="--exclude=$PEP8_EXCLUDE --repeat"
|
PEP8_OPTIONS="--exclude=$PEP8_EXCLUDE --repeat"
|
||||||
PEP8_INCLUDE="glanceclient/* setup.py run_tests.py tools/install_venv.py"
|
PEP8_INCLUDE="glanceclient/*.py setup.py run_tests.py tools/install_venv.py"
|
||||||
${wrapper} pep8 $PEP8_OPTIONS $PEP8_INCLUDE
|
${wrapper} pep8 $PEP8_OPTIONS $PEP8_INCLUDE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
@@ -1,5 +0,0 @@
|
|||||||
import unittest
|
|
||||||
|
|
||||||
class TestCase(unittest.TestCase):
|
|
||||||
def test_one(self):
|
|
||||||
self.assertTrue(True)
|
|
0
tests/v1/__init__.py
Normal file
0
tests/v1/__init__.py
Normal file
59
tests/v1/test_images.py
Normal file
59
tests/v1/test_images.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from tests.v1 import utils
|
||||||
|
|
||||||
|
import glanceclient.v1.images
|
||||||
|
|
||||||
|
|
||||||
|
class ImageManagerTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.api = utils.FakeAPI()
|
||||||
|
self.mgr = glanceclient.v1.images.ImageManager(self.api)
|
||||||
|
|
||||||
|
def test_list(self):
|
||||||
|
images = self.mgr.list()
|
||||||
|
expect = [('GET', '/v1/images/detail', {}, None)]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
self.assertEqual(len(images), 1)
|
||||||
|
self.assertEqual(images[0].id, '1')
|
||||||
|
self.assertEqual(images[0].name, 'image-1')
|
||||||
|
self.assertEqual(images[0].properties, {'arch': 'x86_64'})
|
||||||
|
|
||||||
|
def test_list_with_limit(self):
|
||||||
|
self.mgr.list(limit=10)
|
||||||
|
expect = [('GET', '/v1/images/detail?limit=10', {}, None)]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
|
||||||
|
def test_list_with_marker(self):
|
||||||
|
self.mgr.list(marker=20)
|
||||||
|
expect = [('GET', '/v1/images/detail?marker=20', {}, None)]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
image = self.mgr.get('1')
|
||||||
|
expect = [('HEAD', '/v1/images/1', {}, None)]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
self.assertEqual(image.id, '1')
|
||||||
|
self.assertEqual(image.name, 'image-1')
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
self.mgr.delete('1')
|
||||||
|
expect = [('DELETE', '/v1/images/1', {}, None)]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
image = self.mgr.create(name='image-1')
|
||||||
|
expect = [('POST', '/v1/images', {}, {'image': {'name': 'image-1'}})]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
self.assertEqual(image.id, '1')
|
||||||
|
self.assertEqual(image.name, 'image-1')
|
||||||
|
|
||||||
|
def test_update(self):
|
||||||
|
image = self.mgr.update('1', name='image-2')
|
||||||
|
expect_hdrs = {'x-image-meta-name': 'image-2'}
|
||||||
|
expect = [('PUT', '/v1/images/1', expect_hdrs, None)]
|
||||||
|
self.assertEqual(self.api.calls, expect)
|
||||||
|
self.assertEqual(image.id, '1')
|
||||||
|
self.assertEqual(image.name, 'image-2')
|
70
tests/v1/utils.py
Normal file
70
tests/v1/utils.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
|
||||||
|
fixtures = {
|
||||||
|
'/v1/images': {
|
||||||
|
'POST': (
|
||||||
|
{
|
||||||
|
'location': '/v1/images/1',
|
||||||
|
'x-image-meta-id': '1',
|
||||||
|
'x-image-meta-name': 'image-1',
|
||||||
|
'x-image-meta-property-arch': 'x86_64',
|
||||||
|
},
|
||||||
|
None),
|
||||||
|
},
|
||||||
|
'/v1/images/detail': {
|
||||||
|
'GET': (
|
||||||
|
{},
|
||||||
|
{'images': [
|
||||||
|
{
|
||||||
|
'id': '1',
|
||||||
|
'name': 'image-1',
|
||||||
|
'properties': {'arch': 'x86_64'},
|
||||||
|
},
|
||||||
|
]},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'/v1/images/1': {
|
||||||
|
'HEAD': (
|
||||||
|
{
|
||||||
|
'x-image-meta-id': '1',
|
||||||
|
'x-image-meta-name': 'image-1',
|
||||||
|
'x-image-meta-property-arch': 'x86_64',
|
||||||
|
},
|
||||||
|
None),
|
||||||
|
'PUT': (
|
||||||
|
{
|
||||||
|
'x-image-meta-id': '1',
|
||||||
|
'x-image-meta-name': 'image-2',
|
||||||
|
'x-image-meta-property-arch': 'x86_64',
|
||||||
|
},
|
||||||
|
None),
|
||||||
|
'DELETE': ({}, None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeAPI(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.calls = []
|
||||||
|
|
||||||
|
def _request(self, method, url, headers=None, body=None):
|
||||||
|
call = (method, url, headers or {}, body)
|
||||||
|
self.calls.append(call)
|
||||||
|
# drop any query params
|
||||||
|
url = url.split('?', 1)[0]
|
||||||
|
return fixtures[url][method]
|
||||||
|
|
||||||
|
def get(self, url):
|
||||||
|
return self._request('GET', url)
|
||||||
|
|
||||||
|
def head(self, url):
|
||||||
|
return self._request('HEAD', url)
|
||||||
|
|
||||||
|
def post(self, url, headers=None, body=None):
|
||||||
|
return self._request('POST', url, headers, body)
|
||||||
|
|
||||||
|
def put(self, url, headers=None, body=None):
|
||||||
|
return self._request('PUT', url, headers, body)
|
||||||
|
|
||||||
|
def delete(self, url):
|
||||||
|
return self._request('DELETE', url)
|
Reference in New Issue
Block a user