Merge "Adds the ability to sort images with multiple keys"
This commit is contained in:
commit
c3126c65e7
|
@ -88,7 +88,7 @@ class ImagesController(object):
|
|||
|
||||
return image
|
||||
|
||||
def index(self, req, marker=None, limit=None, sort_key='created_at',
|
||||
def index(self, req, marker=None, limit=None, sort_key=['created_at'],
|
||||
sort_dir='desc', filters=None, member_status='accepted'):
|
||||
result = {}
|
||||
if filters is None:
|
||||
|
@ -102,7 +102,8 @@ class ImagesController(object):
|
|||
image_repo = self.gateway.get_repo(req.context)
|
||||
try:
|
||||
images = image_repo.list(marker=marker, limit=limit,
|
||||
sort_key=sort_key, sort_dir=sort_dir,
|
||||
sort_key=sort_key,
|
||||
sort_dir=sort_dir,
|
||||
filters=filters,
|
||||
member_status=member_status)
|
||||
if len(images) != 0 and len(images) == limit:
|
||||
|
@ -590,9 +591,15 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
|||
while 'tag' in params:
|
||||
tags.append(params.pop('tag').strip())
|
||||
|
||||
# NOTE (mfedosin) Do the same with sorting keys
|
||||
# v2/images?sort_key=name&sort_key=size
|
||||
|
||||
sort_keys = []
|
||||
while 'sort_key' in params:
|
||||
sort_keys.append(self._validate_sort_key(
|
||||
params.pop('sort_key').strip()))
|
||||
|
||||
query_params = {
|
||||
'sort_key': self._validate_sort_key(
|
||||
params.pop('sort_key', 'created_at')),
|
||||
'sort_dir': self._validate_sort_dir(sort_dir),
|
||||
'filters': self._get_filters(params),
|
||||
'member_status': self._validate_member_status(member_status),
|
||||
|
@ -607,6 +614,13 @@ class RequestDeserializer(wsgi.JSONRequestDeserializer):
|
|||
if tags:
|
||||
query_params['filters']['tags'] = tags
|
||||
|
||||
# NOTE(mfedosin): param is still called sort_key, instead of sort_keys
|
||||
# It's done because in v1 it's still a single value.
|
||||
if sort_keys:
|
||||
query_params['sort_key'] = sort_keys
|
||||
else:
|
||||
query_params['sort_key'] = ['created_at']
|
||||
|
||||
return query_params
|
||||
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class ImageRepo(object):
|
|||
image = self._format_image_from_db(db_api_image, tags)
|
||||
return ImageProxy(image, self.context, self.db_api)
|
||||
|
||||
def list(self, marker=None, limit=None, sort_key='created_at',
|
||||
def list(self, marker=None, limit=None, sort_key=['created_at'],
|
||||
sort_dir='desc', filters=None, member_status='accepted'):
|
||||
db_api_images = self.db_api.image_get_all(
|
||||
self.context, filters=filters, marker=marker, limit=limit,
|
||||
|
|
|
@ -118,7 +118,7 @@ def is_image_visible(context, image, status=None):
|
|||
|
||||
@_get_client
|
||||
def image_get_all(client, filters=None, marker=None, limit=None,
|
||||
sort_key='created_at', sort_dir='desc',
|
||||
sort_key=['created_at'], sort_dir='desc',
|
||||
member_status='accepted', is_public=None,
|
||||
admin_as_user=False, return_tag=False):
|
||||
"""
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# under the License.
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import functools
|
||||
import uuid
|
||||
|
||||
|
@ -339,13 +340,29 @@ def _do_pagination(context, images, marker, limit, show_deleted,
|
|||
|
||||
|
||||
def _sort_images(images, sort_key, sort_dir):
|
||||
reverse = False
|
||||
if images and not (sort_key in images[0]):
|
||||
raise exception.InvalidSortKey()
|
||||
keyfn = lambda x: (x[sort_key] if x[sort_key] is not None else '',
|
||||
x['created_at'], x['id'])
|
||||
reverse = sort_dir == 'desc'
|
||||
images.sort(key=keyfn, reverse=reverse)
|
||||
|
||||
for key in ['created_at', 'id']:
|
||||
if key not in sort_key:
|
||||
sort_key.append(key)
|
||||
|
||||
for key in sort_key:
|
||||
if images and not (key in images[0]):
|
||||
raise exception.InvalidSortKey()
|
||||
|
||||
def sort_func(element):
|
||||
keys = []
|
||||
for key in sort_key:
|
||||
if element[key] is not None:
|
||||
keys.append(element[key])
|
||||
else:
|
||||
if key in ['created_at', 'updated_at', 'deleted_at']:
|
||||
keys.append(datetime.datetime.min)
|
||||
else:
|
||||
keys.append('')
|
||||
return tuple(keys)
|
||||
|
||||
images.sort(key=sort_func, reverse=reverse)
|
||||
|
||||
return images
|
||||
|
||||
|
@ -377,7 +394,7 @@ def image_get(context, image_id, session=None, force_show_deleted=False):
|
|||
|
||||
@log_call
|
||||
def image_get_all(context, filters=None, marker=None, limit=None,
|
||||
sort_key='created_at', sort_dir='desc',
|
||||
sort_key=['created_at'], sort_dir='desc',
|
||||
member_status='accepted', is_public=None,
|
||||
admin_as_user=False, return_tag=False):
|
||||
filters = filters or {}
|
||||
|
@ -977,7 +994,6 @@ def _sort_tasks(tasks, sort_key, sort_dir):
|
|||
x['created_at'], x['id'])
|
||||
reverse = sort_dir == 'desc'
|
||||
tasks.sort(key=keyfn, reverse=reverse)
|
||||
|
||||
return tasks
|
||||
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ def _select_images_query(context, image_conditions, admin_as_user,
|
|||
|
||||
|
||||
def image_get_all(context, filters=None, marker=None, limit=None,
|
||||
sort_key='created_at', sort_dir='desc',
|
||||
sort_key=['created_at'], sort_dir='desc',
|
||||
member_status='accepted', is_public=None,
|
||||
admin_as_user=False, return_tag=False):
|
||||
"""
|
||||
|
@ -536,7 +536,7 @@ def image_get_all(context, filters=None, marker=None, limit=None,
|
|||
filters on the image properties attribute
|
||||
:param marker: image id after which to start page
|
||||
:param limit: maximum number of images to return
|
||||
:param sort_key: image attribute by which results should be sorted
|
||||
:param sort_key: list of image attributes by which results should be sorted
|
||||
:param sort_dir: direction in which results should be sorted (asc, desc)
|
||||
:param member_status: only return shared images that have this membership
|
||||
status
|
||||
|
@ -586,11 +586,12 @@ def image_get_all(context, filters=None, marker=None, limit=None,
|
|||
marker,
|
||||
force_show_deleted=showing_deleted)
|
||||
|
||||
sort_keys = ['created_at', 'id']
|
||||
sort_keys.insert(0, sort_key) if sort_key not in sort_keys else sort_keys
|
||||
for key in ['created_at', 'id']:
|
||||
if key not in sort_key:
|
||||
sort_key.append(key)
|
||||
|
||||
query = _paginate_query(query, models.Image, limit,
|
||||
sort_keys,
|
||||
sort_key,
|
||||
marker=marker_image,
|
||||
sort_dir=sort_dir)
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ class Controller(object):
|
|||
params = {
|
||||
'filters': self._get_filters(req),
|
||||
'limit': self._get_limit(req),
|
||||
'sort_key': self._get_sort_key(req),
|
||||
'sort_key': [self._get_sort_key(req)],
|
||||
'sort_dir': self._get_sort_dir(req),
|
||||
'marker': self._get_marker(req),
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ class Controller(object):
|
|||
|
||||
def _get_sort_key(self, req):
|
||||
"""Parse a sort key query param from the request object."""
|
||||
sort_key = req.params.get('sort_key', None)
|
||||
sort_key = req.params.get('sort_key', 'created_at')
|
||||
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,)
|
||||
|
|
|
@ -546,7 +546,7 @@ class DriverTests(object):
|
|||
'owner': TENANT1})
|
||||
|
||||
images = self.db_api.image_get_all(ctxt1, marker=UUIDX,
|
||||
sort_key='name',
|
||||
sort_key=['name'],
|
||||
sort_dir='desc')
|
||||
image_ids = [image['id'] for image in images]
|
||||
expected = []
|
||||
|
@ -568,7 +568,7 @@ class DriverTests(object):
|
|||
'owner': TENANT1})
|
||||
|
||||
images = self.db_api.image_get_all(ctxt1, marker=UUIDX,
|
||||
sort_key='disk_format',
|
||||
sort_key=['disk_format'],
|
||||
sort_dir='desc')
|
||||
image_ids = [image['id'] for image in images]
|
||||
expected = []
|
||||
|
@ -590,7 +590,7 @@ class DriverTests(object):
|
|||
'owner': TENANT1})
|
||||
|
||||
images = self.db_api.image_get_all(ctxt1, marker=UUIDX,
|
||||
sort_key='container_format',
|
||||
sort_key=['container_format'],
|
||||
sort_dir='desc')
|
||||
image_ids = [image['id'] for image in images]
|
||||
expected = []
|
||||
|
@ -612,7 +612,7 @@ class DriverTests(object):
|
|||
'owner': TENANT1})
|
||||
|
||||
images = self.db_api.image_get_all(ctxt1, marker=UUIDX,
|
||||
sort_key='name',
|
||||
sort_key=['name'],
|
||||
sort_dir='asc')
|
||||
image_ids = [image['id'] for image in images]
|
||||
expected = [UUID3, UUID2, UUID1]
|
||||
|
@ -634,7 +634,7 @@ class DriverTests(object):
|
|||
'owner': TENANT1})
|
||||
|
||||
images = self.db_api.image_get_all(ctxt1, marker=UUIDX,
|
||||
sort_key='disk_format',
|
||||
sort_key=['disk_format'],
|
||||
sort_dir='asc')
|
||||
image_ids = [image['id'] for image in images]
|
||||
expected = [UUID3, UUID2, UUID1]
|
||||
|
@ -656,7 +656,7 @@ class DriverTests(object):
|
|||
'owner': TENANT1})
|
||||
|
||||
images = self.db_api.image_get_all(ctxt1, marker=UUIDX,
|
||||
sort_key='container_format',
|
||||
sort_key=['container_format'],
|
||||
sort_dir='asc')
|
||||
image_ids = [image['id'] for image in images]
|
||||
expected = [UUID3, UUID2, UUID1]
|
||||
|
@ -822,7 +822,7 @@ class DriverTests(object):
|
|||
|
||||
def test_image_get_all_invalid_sort_key(self):
|
||||
self.assertRaises(exception.InvalidSortKey, self.db_api.image_get_all,
|
||||
self.context, sort_key='blah')
|
||||
self.context, sort_key=['blah'])
|
||||
|
||||
def test_image_get_all_limit_marker(self):
|
||||
images = self.db_api.image_get_all(self.context, limit=2)
|
||||
|
|
|
@ -119,7 +119,7 @@ class TestSqlAlchemyDBDataIntegrity(base.TestDriver,
|
|||
|
||||
self.stubs.Set(self.db_api, '_paginate_query',
|
||||
fake_paginate_query)
|
||||
self.db_api.image_get_all(self.context, sort_key='created_at')
|
||||
self.db_api.image_get_all(self.context, sort_key=['created_at'])
|
||||
|
||||
def test_paginate_non_redundant_sort_keys(self):
|
||||
original_method = self.db_api._paginate_query
|
||||
|
@ -132,7 +132,7 @@ class TestSqlAlchemyDBDataIntegrity(base.TestDriver,
|
|||
|
||||
self.stubs.Set(self.db_api, '_paginate_query',
|
||||
fake_paginate_query)
|
||||
self.db_api.image_get_all(self.context, sort_key='name')
|
||||
self.db_api.image_get_all(self.context, sort_key=['name'])
|
||||
|
||||
|
||||
class TestSqlAlchemyTask(base.TaskTests,
|
||||
|
|
|
@ -302,10 +302,29 @@ class TestImageRepo(test_utils.BaseTestCase):
|
|||
self.assertEqual(set([UUID1, UUID3]), image_ids)
|
||||
|
||||
def test_sorted_list(self):
|
||||
images = self.image_repo.list(sort_key='size', sort_dir='asc')
|
||||
images = self.image_repo.list(sort_key=['size'], sort_dir='asc')
|
||||
image_ids = [i.image_id for i in images]
|
||||
self.assertEqual([UUID1, UUID2, UUID3], image_ids)
|
||||
|
||||
def test_sorted_list_with_multiple_keys(self):
|
||||
temp_id = 'd80a1a6c-bd1f-41c5-90ee-81afedb1d58d'
|
||||
image = _db_fixture(temp_id, owner=TENANT1, checksum=CHECKSUM,
|
||||
name='1', size=1024,
|
||||
is_public=True, status='active',
|
||||
locations=[{'url': UUID1_LOCATION,
|
||||
'metadata': UUID1_LOCATION_METADATA,
|
||||
'status': 'active'}])
|
||||
self.db.image_create(None, image)
|
||||
images = self.image_repo.list(sort_key=['name', 'size'],
|
||||
sort_dir='asc')
|
||||
image_ids = [i.image_id for i in images]
|
||||
self.assertEqual([UUID1, temp_id, UUID2, UUID3], image_ids)
|
||||
|
||||
images = self.image_repo.list(sort_key=['size', 'name'],
|
||||
sort_dir='asc')
|
||||
image_ids = [i.image_id for i in images]
|
||||
self.assertEqual([UUID1, UUID2, temp_id, UUID3], image_ids)
|
||||
|
||||
def test_add_image(self):
|
||||
image = self.image_factory.new_image(name='added image')
|
||||
self.assertEqual(image.updated_at, image.created_at)
|
||||
|
|
|
@ -214,7 +214,8 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||
self.config(limit_param_default=1, api_limit_max=3)
|
||||
request = unit_test_utils.get_fake_request()
|
||||
output = self.controller.index(request, marker=UUID3, limit=1,
|
||||
sort_key='created_at', sort_dir='desc')
|
||||
sort_key=['created_at'],
|
||||
sort_dir='desc')
|
||||
self.assertEqual(1, len(output['images']))
|
||||
actual = set([image.image_id for image in output['images']])
|
||||
expected = set([UUID2])
|
||||
|
@ -423,7 +424,20 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||
def test_index_with_sort_key(self):
|
||||
path = '/images'
|
||||
request = unit_test_utils.get_fake_request(path)
|
||||
output = self.controller.index(request, sort_key='created_at', limit=3)
|
||||
output = self.controller.index(request, sort_key=['created_at'],
|
||||
limit=3)
|
||||
actual = [image.image_id for image in output['images']]
|
||||
self.assertEqual(3, len(actual))
|
||||
self.assertEqual(UUID3, actual[0])
|
||||
self.assertEqual(UUID2, actual[1])
|
||||
self.assertEqual(UUID1, actual[2])
|
||||
|
||||
def test_index_with_multiple_sort_keys(self):
|
||||
path = '/images'
|
||||
request = unit_test_utils.get_fake_request(path)
|
||||
output = self.controller.index(request,
|
||||
sort_key=['created_at', 'name'],
|
||||
limit=3)
|
||||
actual = [image.image_id for image in output['images']]
|
||||
self.assertEqual(3, len(actual))
|
||||
self.assertEqual(UUID3, actual[0])
|
||||
|
@ -441,7 +455,7 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||
path = '/images'
|
||||
request = unit_test_utils.get_fake_request(path)
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.controller.index, request, sort_key='foo')
|
||||
self.controller.index, request, sort_key=['foo'])
|
||||
|
||||
def test_index_zero_images(self):
|
||||
self.db.reset()
|
||||
|
@ -2433,7 +2447,7 @@ class TestImagesDeserializer(test_utils.BaseTestCase):
|
|||
request = unit_test_utils.get_fake_request(path)
|
||||
expected = {'limit': 1,
|
||||
'marker': marker,
|
||||
'sort_key': 'created_at',
|
||||
'sort_key': ['created_at'],
|
||||
'sort_dir': 'desc',
|
||||
'member_status': 'pending',
|
||||
'filters': {}}
|
||||
|
@ -2481,7 +2495,7 @@ class TestImagesDeserializer(test_utils.BaseTestCase):
|
|||
def test_index_zero_limit(self):
|
||||
request = unit_test_utils.get_fake_request('/images?limit=0')
|
||||
expected = {'limit': 0,
|
||||
'sort_key': 'created_at',
|
||||
'sort_key': ['created_at'],
|
||||
'member_status': 'accepted',
|
||||
'sort_dir': 'desc',
|
||||
'filters': {}}
|
||||
|
@ -2525,18 +2539,38 @@ class TestImagesDeserializer(test_utils.BaseTestCase):
|
|||
request = unit_test_utils.get_fake_request('/images?sort_key=id')
|
||||
output = self.deserializer.index(request)
|
||||
expected = {
|
||||
'sort_key': 'id',
|
||||
'sort_key': ['id'],
|
||||
'sort_dir': 'desc',
|
||||
'member_status': 'accepted',
|
||||
'filters': {}
|
||||
}
|
||||
self.assertEqual(expected, output)
|
||||
|
||||
def test_index_multiple_sort_keys(self):
|
||||
request = unit_test_utils.get_fake_request('/images?'
|
||||
'sort_key=name&'
|
||||
'sort_key=size')
|
||||
output = self.deserializer.index(request)
|
||||
expected = {
|
||||
'sort_key': ['name', 'size'],
|
||||
'sort_dir': 'desc',
|
||||
'member_status': 'accepted',
|
||||
'filters': {}
|
||||
}
|
||||
self.assertEqual(expected, output)
|
||||
|
||||
def test_index_invalid_multiple_sort_keys(self):
|
||||
request = unit_test_utils.get_fake_request('/images?'
|
||||
'sort_key=name&'
|
||||
'sort_key=blah')
|
||||
self.assertRaises(webob.exc.HTTPBadRequest,
|
||||
self.deserializer.index, request)
|
||||
|
||||
def test_index_sort_dir_asc(self):
|
||||
request = unit_test_utils.get_fake_request('/images?sort_dir=asc')
|
||||
output = self.deserializer.index(request)
|
||||
expected = {
|
||||
'sort_key': 'created_at',
|
||||
'sort_key': ['created_at'],
|
||||
'sort_dir': 'asc',
|
||||
'member_status': 'accepted',
|
||||
'filters': {}}
|
||||
|
|
|
@ -264,7 +264,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': 'name',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': ['name'],
|
||||
'sort_dir': 'asc'},
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -297,7 +297,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': 'name',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': ['name'],
|
||||
'sort_dir': 'desc'},
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -330,7 +330,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': 'disk_format',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': ['disk_format'],
|
||||
'sort_dir': 'asc'},
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -363,7 +363,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': 'disk_format',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': ['disk_format'],
|
||||
'sort_dir': 'desc'},
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -396,7 +396,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': 'container_format',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': ['container_format'],
|
||||
'sort_dir': 'asc'},
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -429,7 +429,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': 'container_format',
|
||||
'kwargs': {'marker': UUID3, 'sort_key': ['container_format'],
|
||||
'sort_dir': 'desc'},
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -831,7 +831,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'name', 'sort_dir': 'asc'}
|
||||
'kwargs': {'sort_key': ['name'], 'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
res = req.get_response(self.api)
|
||||
|
@ -883,7 +883,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'status', 'sort_dir': 'asc'}
|
||||
'kwargs': {'sort_key': ['status'], 'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
res = req.get_response(self.api)
|
||||
|
@ -934,7 +934,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'disk_format', 'sort_dir': 'asc'}
|
||||
'kwargs': {'sort_key': ['disk_format'], 'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
res = req.get_response(self.api)
|
||||
|
@ -985,7 +985,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'container_format',
|
||||
'kwargs': {'sort_key': ['container_format'],
|
||||
'sort_dir': 'desc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -1033,7 +1033,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'size',
|
||||
'kwargs': {'sort_key': ['size'],
|
||||
'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -1088,7 +1088,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'created_at',
|
||||
'kwargs': {'sort_key': ['created_at'],
|
||||
'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -1143,7 +1143,7 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': 'updated_at',
|
||||
'kwargs': {'sort_key': ['updated_at'],
|
||||
'sort_dir': 'desc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
|
@ -1158,6 +1158,94 @@ class TestRegistryRPC(base.IsolatedUnitTest):
|
|||
self.assertEqual(UUID2, images[2]['id'])
|
||||
self.assertEqual(UUID1, images[3]['id'])
|
||||
|
||||
def test_get_index_sort_multiple_keys(self):
|
||||
"""
|
||||
Tests that the registry API returns list of
|
||||
public images sorted by name-size and size-name.
|
||||
"""
|
||||
uuid4_time = timeutils.utcnow() + datetime.timedelta(seconds=10)
|
||||
uuid3_time = uuid4_time + datetime.timedelta(seconds=5)
|
||||
|
||||
UUID3 = _gen_uuid()
|
||||
extra_fixture = {'id': UUID3,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 19,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'updated_at': uuid3_time}
|
||||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
UUID4 = _gen_uuid()
|
||||
extra_fixture = {'id': UUID4,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'xyz',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'updated_at': uuid4_time}
|
||||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
UUID5 = _gen_uuid()
|
||||
extra_fixture = {'id': UUID5,
|
||||
'status': 'active',
|
||||
'is_public': True,
|
||||
'disk_format': 'vhd',
|
||||
'container_format': 'ovf',
|
||||
'name': 'asdf',
|
||||
'size': 20,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'updated_at': uuid4_time}
|
||||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
req = webob.Request.blank('/rpc')
|
||||
req.method = "POST"
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': ['name', 'size'],
|
||||
'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(200, res.status_int)
|
||||
res_dict = jsonutils.loads(res.body)[0]
|
||||
|
||||
images = res_dict
|
||||
self.assertEqual(5, len(images))
|
||||
self.assertEqual(UUID3, images[0]['id'])
|
||||
self.assertEqual(UUID5, images[1]['id'])
|
||||
self.assertEqual(UUID1, images[2]['id'])
|
||||
self.assertEqual(UUID2, images[3]['id'])
|
||||
self.assertEqual(UUID4, images[4]['id'])
|
||||
|
||||
cmd = [{
|
||||
'command': 'image_get_all',
|
||||
'kwargs': {'sort_key': ['size', 'name'],
|
||||
'sort_dir': 'asc'}
|
||||
}]
|
||||
req.body = jsonutils.dumps(cmd)
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(200, res.status_int)
|
||||
res_dict = jsonutils.loads(res.body)[0]
|
||||
|
||||
images = res_dict
|
||||
self.assertEqual(5, len(images))
|
||||
self.assertEqual(UUID1, images[0]['id'])
|
||||
self.assertEqual(UUID3, images[1]['id'])
|
||||
self.assertEqual(UUID2, images[2]['id'])
|
||||
self.assertEqual(UUID5, images[3]['id'])
|
||||
self.assertEqual(UUID4, images[4]['id'])
|
||||
|
||||
def test_create_image(self):
|
||||
"""Tests that the registry API creates the image"""
|
||||
fixture = {'name': 'fake public image',
|
||||
|
|
|
@ -116,7 +116,8 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='name', sort_dir='asc')
|
||||
images = self.client.image_get_all(sort_key=['name'],
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEqualImages(images, (UUID3, UUID1, UUID2, UUID4),
|
||||
unjsonify=False)
|
||||
|
@ -140,7 +141,8 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='status', sort_dir='desc')
|
||||
images = self.client.image_get_all(sort_key=['status'],
|
||||
sort_dir='desc')
|
||||
|
||||
self.assertEqualImages(images, (UUID3, UUID4, UUID2, UUID1),
|
||||
unjsonify=False)
|
||||
|
@ -163,7 +165,7 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='disk_format',
|
||||
images = self.client.image_get_all(sort_key=['disk_format'],
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEqualImages(images, (UUID1, UUID3, UUID4, UUID2),
|
||||
|
@ -188,7 +190,7 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='container_format',
|
||||
images = self.client.image_get_all(sort_key=['container_format'],
|
||||
sort_dir='desc')
|
||||
|
||||
self.assertEqualImages(images, (UUID2, UUID4, UUID3, UUID1),
|
||||
|
@ -215,7 +217,7 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='size', sort_dir='asc')
|
||||
images = self.client.image_get_all(sort_key=['size'], sort_dir='asc')
|
||||
|
||||
self.assertEqualImages(images, (UUID4, UUID1, UUID2, UUID3),
|
||||
unjsonify=False)
|
||||
|
@ -238,7 +240,7 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='created_at',
|
||||
images = self.client.image_get_all(sort_key=['created_at'],
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEqualImages(images, (UUID1, UUID2, UUID4, UUID3),
|
||||
|
@ -264,12 +266,48 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key='updated_at',
|
||||
images = self.client.image_get_all(sort_key=['updated_at'],
|
||||
sort_dir='desc')
|
||||
|
||||
self.assertEqualImages(images, (UUID3, UUID4, UUID2, UUID1),
|
||||
unjsonify=False)
|
||||
|
||||
def test_get_image_details_sort_multiple_keys(self):
|
||||
"""
|
||||
Tests that a detailed call returns list of
|
||||
public images sorted alphabetically by name-size and
|
||||
size-name in ascending order.
|
||||
"""
|
||||
UUID3 = _gen_uuid()
|
||||
extra_fixture = self.get_fixture(id=UUID3, name='asdf',
|
||||
size=19)
|
||||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
UUID4 = _gen_uuid()
|
||||
extra_fixture = self.get_fixture(id=UUID4, name='xyz',
|
||||
size=20)
|
||||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
UUID5 = _gen_uuid()
|
||||
extra_fixture = self.get_fixture(id=UUID5, name='asdf',
|
||||
size=20)
|
||||
|
||||
db_api.image_create(self.context, extra_fixture)
|
||||
|
||||
images = self.client.image_get_all(sort_key=['name', 'size'],
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEqualImages(images, (UUID3, UUID5, UUID1, UUID2, UUID4),
|
||||
unjsonify=False)
|
||||
|
||||
images = self.client.image_get_all(sort_key=['size', 'name'],
|
||||
sort_dir='asc')
|
||||
|
||||
self.assertEqualImages(images, (UUID1, UUID3, UUID2, UUID5, UUID4),
|
||||
unjsonify=False)
|
||||
|
||||
def test_image_get_index_marker(self):
|
||||
"""Test correct set of images returned with marker param."""
|
||||
uuid4_time = timeutils.utcnow() + datetime.timedelta(seconds=10)
|
||||
|
|
Loading…
Reference in New Issue