adding support to registry server and client for sort_key and sort_dir params
This commit is contained in:
parent
f341891ce4
commit
23a4049477
|
@ -44,46 +44,52 @@ class RegistryClient(BaseClient):
|
|||
port = port or self.DEFAULT_PORT
|
||||
super(RegistryClient, self).__init__(host, port, use_ssl)
|
||||
|
||||
def get_images(self, filters=None, marker=None, limit=None):
|
||||
def get_images(self, **kwargs):
|
||||
"""
|
||||
Returns a list of image id/name mappings from Registry
|
||||
|
||||
:param filters: dict of keys & expected values to filter results
|
||||
:param marker: image id after which to start page
|
||||
:param limit: max number of images to return
|
||||
:param sort_key: results will be ordered by this image attribute
|
||||
:param sort_dir: direction in which to to order results (asc, desc)
|
||||
"""
|
||||
params = filters or {}
|
||||
|
||||
if marker != None:
|
||||
params['marker'] = marker
|
||||
|
||||
if limit != None:
|
||||
params['limit'] = limit
|
||||
|
||||
params = kwargs.get('filters', {})
|
||||
params.update(self._extract_get_params(kwargs))
|
||||
res = self.do_request("GET", "/images", params=params)
|
||||
data = json.loads(res.read())['images']
|
||||
return data
|
||||
|
||||
def get_images_detailed(self, filters=None, marker=None, limit=None):
|
||||
def get_images_detailed(self, **kwargs):
|
||||
"""
|
||||
Returns a list of detailed image data mappings from Registry
|
||||
|
||||
:param filters: dict of keys & expected values to filter results
|
||||
:param marker: image id after which to start page
|
||||
:param limit: max number of images to return
|
||||
:param sort_key: results will be ordered by this image attribute
|
||||
:param sort_dir: direction in which to to order results (asc, desc)
|
||||
"""
|
||||
params = filters or {}
|
||||
|
||||
if marker != None:
|
||||
params['marker'] = marker
|
||||
|
||||
if limit != None:
|
||||
params['limit'] = limit
|
||||
|
||||
params = kwargs.get('filters', {})
|
||||
params.update(self._extract_get_params(kwargs))
|
||||
res = self.do_request("GET", "/images/detail", params=params)
|
||||
data = json.loads(res.read())['images']
|
||||
return data
|
||||
|
||||
def _extract_get_params(self, params):
|
||||
"""
|
||||
Attempts to extract a subset of keys from the input dictionary.
|
||||
|
||||
:param params: dict of values to filter
|
||||
:retval subset of 'params' dict
|
||||
"""
|
||||
SUPPORTED_GET_PARAMS = ['marker', 'limit', 'sort_key', 'sort_dir']
|
||||
result = {}
|
||||
for PARAM in SUPPORTED_GET_PARAMS:
|
||||
if PARAM in params:
|
||||
result[PARAM] = params[PARAM]
|
||||
return result
|
||||
|
||||
def get_image(self, image_id):
|
||||
"""Returns a mapping of image metadata from Registry"""
|
||||
res = self.do_request("GET", "/images/%s" % image_id)
|
||||
|
|
|
@ -129,7 +129,8 @@ def image_get(context, image_id, session=None):
|
|||
raise exception.NotFound("No image found with ID %s" % image_id)
|
||||
|
||||
|
||||
def image_get_all_public(context, filters=None, marker=None, limit=None):
|
||||
def image_get_all_public(context, filters=None, marker=None, limit=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
"""Get all public images that match zero or more filters.
|
||||
|
||||
:param filters: dict of filter keys and values. If a 'properties'
|
||||
|
|
|
@ -39,6 +39,11 @@ DISPLAY_FIELDS_IN_INDEX = ['id', 'name', 'size',
|
|||
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
|
||||
'size_min', 'size_max']
|
||||
|
||||
SUPPORTED_SORT_KEYS = ['name', 'status', 'container_format', 'disk_format',
|
||||
'size', 'id', 'created_at', 'updated_at']
|
||||
|
||||
SUPPORTED_SORT_DIRS = ['asc', 'desc']
|
||||
|
||||
MAX_ITEM_LIMIT = 25
|
||||
|
||||
|
||||
|
@ -69,14 +74,7 @@ class Controller(wsgi.Controller):
|
|||
}
|
||||
|
||||
"""
|
||||
params = {
|
||||
'filters': self._get_filters(req),
|
||||
'limit': self._get_limit(req),
|
||||
}
|
||||
|
||||
if 'marker' in req.str_params:
|
||||
params['marker'] = self._get_marker(req)
|
||||
|
||||
params = self._get_query_params(req)
|
||||
images = db_api.image_get_all_public(None, **params)
|
||||
|
||||
results = []
|
||||
|
@ -99,19 +97,29 @@ class Controller(wsgi.Controller):
|
|||
all image model fields.
|
||||
|
||||
"""
|
||||
params = {
|
||||
'filters': self._get_filters(req),
|
||||
'limit': self._get_limit(req),
|
||||
}
|
||||
|
||||
if 'marker' in req.str_params:
|
||||
params['marker'] = self._get_marker(req)
|
||||
|
||||
params = self._get_query_params(req)
|
||||
images = db_api.image_get_all_public(None, **params)
|
||||
|
||||
image_dicts = [make_image_dict(i) for i in images]
|
||||
return dict(images=image_dicts)
|
||||
|
||||
def _get_query_params(self, req):
|
||||
"""Extract necessary query parameters from http request.
|
||||
|
||||
:param req: the Request object coming from the wsgi layer
|
||||
:retval dictionary of filters to apply to list of images
|
||||
|
||||
"""
|
||||
params = {
|
||||
'filters': self._get_filters(req),
|
||||
'limit': self._get_limit(req),
|
||||
'sort_key': self._get_sort_key(req),
|
||||
'sort_dir': self._get_sort_dir(req),
|
||||
'marker': self._get_marker(req),
|
||||
}
|
||||
|
||||
return params
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""Return a dictionary of query param filters from the request
|
||||
|
||||
|
@ -148,12 +156,35 @@ class Controller(wsgi.Controller):
|
|||
|
||||
def _get_marker(self, req):
|
||||
"""Parse a marker query param into something usable."""
|
||||
marker = req.str_params.get('marker', None)
|
||||
|
||||
if marker is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
marker = int(req.str_params.get('marker', None))
|
||||
marker = int(marker)
|
||||
except ValueError:
|
||||
raise exc.HTTPBadRequest("marker param must be an integer")
|
||||
return marker
|
||||
|
||||
def _get_sort_key(self, req):
|
||||
"""Parse a sort key query param from the request object."""
|
||||
sort_key = req.str_params.get('sort_key', None)
|
||||
if sort_key is not None and sort_key not in SUPPORTED_SORT_KEYS:
|
||||
_keys = '. '.join(SUPPORTED_SORT_KEYS)
|
||||
msg = "Unsupported sort_key. Acceptable values: %s" % (_keys,)
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
return sort_key
|
||||
|
||||
def _get_sort_dir(self, req):
|
||||
"""Parse a sort direction query param from the request object."""
|
||||
sort_dir = req.str_params.get('sort_dir', None)
|
||||
if sort_dir is not None and sort_dir not in SUPPORTED_SORT_DIRS:
|
||||
_keys = '. '.join(SUPPORTED_SORT_DIRS)
|
||||
msg = "Unsupported sort_dir. Acceptable values: %s" % (_keys,)
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
return sort_dir
|
||||
|
||||
def show(self, req, id):
|
||||
"""Return data about the given image id."""
|
||||
try:
|
||||
|
|
|
@ -388,8 +388,8 @@ def stub_out_registry_db_image_api(stubs):
|
|||
else:
|
||||
return images[0]
|
||||
|
||||
def image_get_all_public(self, _context, filters=None,
|
||||
marker=None, limit=1000):
|
||||
def image_get_all_public(self, _context, filters=None, marker=None,
|
||||
limit=1000, sort_key=None, sort_dir=None):
|
||||
images = [f for f in self.images if f['is_public'] == True]
|
||||
|
||||
if 'size_min' in filters:
|
||||
|
@ -414,16 +414,24 @@ def stub_out_registry_db_image_api(stubs):
|
|||
for k, v in filters.items():
|
||||
images = [f for f in images if f[k] == v]
|
||||
|
||||
# sorted func expects func that compares in descending order
|
||||
def image_cmp(x, y):
|
||||
if x['created_at'] > y['created_at']:
|
||||
return 1
|
||||
elif x['created_at'] == y['created_at']:
|
||||
_sort_dir = sort_dir or 'desc'
|
||||
multiplier = {
|
||||
'asc': -1,
|
||||
'desc': 1,
|
||||
}[_sort_dir]
|
||||
|
||||
_sort_key = sort_key or 'created_at'
|
||||
if x[_sort_key] > y[_sort_key]:
|
||||
return 1 * multiplier
|
||||
elif x[_sort_key] == y[_sort_key]:
|
||||
if x['id'] > y['id']:
|
||||
return 1
|
||||
return 1 * multiplier
|
||||
else:
|
||||
return -1
|
||||
return -1 * multiplier
|
||||
else:
|
||||
return -1
|
||||
return -1 * multiplier
|
||||
|
||||
images = sorted(images, cmp=image_cmp)
|
||||
images.reverse()
|
||||
|
|
|
@ -285,6 +285,398 @@ class TestRegistryAPI(unittest.TestCase):
|
|||
for image in images:
|
||||
self.assertEqual('new name! #123', image['name'])
|
||||
|
||||
def test_get_index_sort_default_created_at_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images that conforms to a default sort key/dir
|
||||
|
||||
"""
|
||||
time1 = datetime.datetime.utcnow() + datetime.timedelta(seconds=5)
|
||||
time2 = datetime.datetime.utcnow()
|
||||
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 19,
|
||||
'checksum': None,
|
||||
'created_at': time1}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': time1}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 5,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': time2}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images')
|
||||
res = req.get_response(self.api)
|
||||
res_dict = json.loads(res.body)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 4)
|
||||
self.assertEquals(int(images[0]['id']), 4)
|
||||
self.assertEquals(int(images[1]['id']), 3)
|
||||
self.assertEquals(int(images[2]['id']), 5)
|
||||
self.assertEquals(int(images[3]['id']), 2)
|
||||
|
||||
def test_get_index_bad_sort_key(self):
|
||||
"""Ensure a 400 is returned when a bad sort_key is provided."""
|
||||
req = webob.Request.blank('/images?sort_key=asdf')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_get_index_bad_sort_dir(self):
|
||||
"""Ensure a 400 is returned when a bad sort_dir is provided."""
|
||||
req = webob.Request.blank('/images?sort_dir=asdf')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_get_index_sort_id_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by id in descending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images?sort_key=id&sort_dir=desc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 4)
|
||||
self.assertEquals(int(images[1]['id']), 3)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_index_sort_name_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by name in
|
||||
ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images?sort_key=name&sort_dir=asc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 2)
|
||||
self.assertEquals(int(images[2]['id']), 4)
|
||||
|
||||
def test_get_index_sort_status_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by status in
|
||||
descending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'killed',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images?sort_key=status&sort_dir=desc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_index_sort_disk_format_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by disk_format in
|
||||
ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vdi',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images?sort_key=disk_format&sort_dir=asc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_index_sort_container_format_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by container_format in
|
||||
descending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'iso',
|
||||
'container_format': 'bare',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
url = '/images?sort_key=container_format&sort_dir=desc'
|
||||
req = webob.Request.blank(url)
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 2)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 3)
|
||||
|
||||
def test_get_index_sort_size_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by size in ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 100,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'iso',
|
||||
'container_format': 'bare',
|
||||
'name': 'xyz',
|
||||
'size': 2,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
url = '/images?sort_key=size&sort_dir=asc'
|
||||
req = webob.Request.blank(url)
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 4)
|
||||
self.assertEquals(int(images[1]['id']), 2)
|
||||
self.assertEquals(int(images[2]['id']), 3)
|
||||
|
||||
def test_get_index_sort_created_at_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by created_at in ascending order.
|
||||
|
||||
"""
|
||||
now = datetime.datetime.utcnow()
|
||||
time1 = now + datetime.timedelta(seconds=5)
|
||||
time2 = now
|
||||
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 19,
|
||||
'checksum': None,
|
||||
'created_at': time1}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': time2}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images?sort_key=created_at&sort_dir=asc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 2)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 3)
|
||||
|
||||
def test_get_index_sort_updated_at_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by updated_at in descending order.
|
||||
|
||||
"""
|
||||
now = datetime.datetime.utcnow()
|
||||
time1 = now + datetime.timedelta(seconds=5)
|
||||
time2 = now
|
||||
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 19,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'created_at': time1}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'updated_at': time2}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images?sort_key=updated_at&sort_dir=desc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_details(self):
|
||||
"""Tests that the /images/detail registry API returns
|
||||
a mapping containing a list of detailed image information
|
||||
|
@ -668,6 +1060,47 @@ class TestRegistryAPI(unittest.TestCase):
|
|||
for image in images:
|
||||
self.assertEqual('v a', image['properties']['prop_123'])
|
||||
|
||||
def test_get_details_sort_name_asc(self):
|
||||
"""Tests that the /images/details registry API returns list of
|
||||
public images sorted alphabetically by name in
|
||||
ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/images/detail?sort_key=name&sort_dir=asc')
|
||||
res = req.get_response(self.api)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
res_dict = json.loads(res.body)
|
||||
|
||||
images = res_dict['images']
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 2)
|
||||
self.assertEquals(int(images[2]['id']), 4)
|
||||
|
||||
|
||||
|
||||
def test_create_image(self):
|
||||
"""Tests that the /images POST registry API creates the image"""
|
||||
fixture = {'name': 'fake public image',
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import stubout
|
||||
|
@ -70,6 +71,299 @@ class TestRegistryClient(unittest.TestCase):
|
|||
for k, v in fixture.items():
|
||||
self.assertEquals(v, images[0][k])
|
||||
|
||||
def test_get_index_sort_id_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by id in descending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='id', sort_dir='desc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 4)
|
||||
self.assertEquals(int(images[1]['id']), 3)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_index_sort_name_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by name in
|
||||
ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='name', sort_dir='asc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 2)
|
||||
self.assertEquals(int(images[2]['id']), 4)
|
||||
|
||||
def test_get_index_sort_status_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by status in
|
||||
descending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'killed',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='status', sort_dir='desc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_index_sort_disk_format_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by disk_format in
|
||||
ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vdi',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='disk_format',
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
def test_get_index_sort_container_format_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted alphabetically by container_format in
|
||||
descending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'iso',
|
||||
'container_format': 'bare',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='container_format',
|
||||
sort_dir='desc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 2)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 3)
|
||||
|
||||
def test_get_index_sort_size_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by size in ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 100,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'iso',
|
||||
'container_format': 'bare',
|
||||
'name': 'xyz',
|
||||
'size': 2,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='size', sort_dir='asc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 4)
|
||||
self.assertEquals(int(images[1]['id']), 2)
|
||||
self.assertEquals(int(images[2]['id']), 3)
|
||||
|
||||
def test_get_index_sort_created_at_asc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by created_at in ascending order.
|
||||
|
||||
"""
|
||||
now = datetime.datetime.utcnow()
|
||||
time1 = now + datetime.timedelta(seconds=5)
|
||||
time2 = now
|
||||
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 19,
|
||||
'checksum': None,
|
||||
'created_at': time1}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': time2}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='created_at', sort_dir='asc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 2)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 3)
|
||||
|
||||
def test_get_index_sort_updated_at_desc(self):
|
||||
"""Tests that the /images registry API returns list of
|
||||
public images sorted by updated_at in descending order.
|
||||
|
||||
"""
|
||||
now = datetime.datetime.utcnow()
|
||||
time1 = now + datetime.timedelta(seconds=5)
|
||||
time2 = now
|
||||
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 19,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'created_at': time1}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'new name! #123',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'updated_at': time2}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images(sort_key='updated_at', sort_dir='desc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
|
||||
def test_get_image_index_marker(self):
|
||||
"""Test correct set of images returned with marker param."""
|
||||
extra_fixture = {'id': 3,
|
||||
|
@ -170,7 +464,7 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images({'name': 'new name! #123'})
|
||||
images = self.client.get_images(filters={'name': 'new name! #123'})
|
||||
self.assertEquals(len(images), 1)
|
||||
|
||||
for image in images:
|
||||
|
@ -236,7 +530,8 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'name': 'new name! #123'})
|
||||
filters = {'name': 'new name! #123'}
|
||||
images = self.client.get_images_detailed(filters=filters)
|
||||
self.assertEquals(len(images), 1)
|
||||
|
||||
for image in images:
|
||||
|
@ -255,7 +550,7 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'status': 'saving'})
|
||||
images = self.client.get_images_detailed(filters={'status': 'saving'})
|
||||
self.assertEquals(len(images), 1)
|
||||
|
||||
for image in images:
|
||||
|
@ -274,7 +569,8 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'container_format': 'ovf'})
|
||||
filters = {'container_format': 'ovf'}
|
||||
images = self.client.get_images_detailed(filters=filters)
|
||||
self.assertEquals(len(images), 2)
|
||||
|
||||
for image in images:
|
||||
|
@ -293,7 +589,8 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'disk_format': 'vhd'})
|
||||
filters = {'disk_format': 'vhd'}
|
||||
images = self.client.get_images_detailed(filters=filters)
|
||||
self.assertEquals(len(images), 2)
|
||||
|
||||
for image in images:
|
||||
|
@ -312,7 +609,7 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'size_max': 20})
|
||||
images = self.client.get_images_detailed(filters={'size_max': 20})
|
||||
self.assertEquals(len(images), 1)
|
||||
|
||||
for image in images:
|
||||
|
@ -331,7 +628,7 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'size_min': 20})
|
||||
images = self.client.get_images_detailed(filters={'size_min': 20})
|
||||
self.assertEquals(len(images), 1)
|
||||
|
||||
for image in images:
|
||||
|
@ -351,12 +648,50 @@ class TestRegistryClient(unittest.TestCase):
|
|||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed({'property-p a': 'v a'})
|
||||
filters = {'property-p a': 'v a'}
|
||||
images = self.client.get_images_detailed(filters=filters)
|
||||
self.assertEquals(len(images), 1)
|
||||
|
||||
for image in images:
|
||||
self.assertEquals('v a', image['properties']['p a'])
|
||||
|
||||
def test_get_image_details_sort_disk_format_asc(self):
|
||||
"""Tests that a detailed call returns list of
|
||||
public images sorted alphabetically by disk_format in
|
||||
ascending order.
|
||||
|
||||
"""
|
||||
extra_fixture = {'id': 3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'ami',
|
||||
'container_format': 'ami',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
extra_fixture = {'id': 4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vdi',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None}
|
||||
|
||||
glance.registry.db.api.image_create(None, extra_fixture)
|
||||
|
||||
images = self.client.get_images_detailed(sort_key='disk_format',
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEquals(len(images), 3)
|
||||
self.assertEquals(int(images[0]['id']), 3)
|
||||
self.assertEquals(int(images[1]['id']), 4)
|
||||
self.assertEquals(int(images[2]['id']), 2)
|
||||
|
||||
|
||||
def test_get_image(self):
|
||||
"""Tests that the detailed info about an image returned"""
|
||||
fixture = {'id': 1,
|
||||
|
|
Loading…
Reference in New Issue