diff --git a/glanceclient/v2/metadefs.py b/glanceclient/v2/metadefs.py index 3dc7efc2..8d9512bc 100644 --- a/glanceclient/v2/metadefs.py +++ b/glanceclient/v2/metadefs.py @@ -22,6 +22,8 @@ from glanceclient.openstack.common import strutils from glanceclient.v2 import schemas DEFAULT_PAGE_SIZE = 20 +SORT_DIR_VALUES = ('asc', 'desc') +SORT_KEY_VALUES = ('created_at', 'namespace') class NamespaceController(object): @@ -88,8 +90,17 @@ class NamespaceController(object): def list(self, **kwargs): """Retrieve a listing of Namespace objects - - :param page_size: Number of namespaces to request in each request + :param page_size: Number of items to request in each paginated request + :param limit: Use to request a specific page size. Expect a response + to a limited request to return between zero and limit + items. + :param marker: Specifies the namespace of the last-seen namespace. + The typical pattern of limit and marker is to make an + initial limited request and then to use the last + namespace from the response as the marker parameter + in a subsequent limited request. + :param sort_key: The field to sort on (for example, 'created_at') + :param sort_dir: The direction to sort ('asc' or 'desc') :returns generator over list of Namespaces """ @@ -129,6 +140,25 @@ class NamespaceController(object): else: filters['limit'] = kwargs['page_size'] + if 'marker' in kwargs: + filters['marker'] = kwargs['marker'] + + sort_key = kwargs.get('sort_key') + if sort_key is not None: + if sort_key in SORT_KEY_VALUES: + filters['sort_key'] = sort_key + else: + raise ValueError('sort_key must be one of the following: %s.' + % ', '.join(SORT_KEY_VALUES)) + + sort_dir = kwargs.get('sort_dir') + if sort_dir is not None: + if sort_dir in SORT_DIR_VALUES: + filters['sort_dir'] = sort_dir + else: + raise ValueError('sort_dir must be one of the following: %s.' + % ', '.join(SORT_DIR_VALUES)) + for param, value in six.iteritems(filters): if isinstance(value, list): filters[param] = strutils.safe_encode(','.join(value)) diff --git a/tests/v2/test_metadefs_namespaces.py b/tests/v2/test_metadefs_namespaces.py index 4267dd95..b03dcd15 100644 --- a/tests/v2/test_metadefs_namespaces.py +++ b/tests/v2/test_metadefs_namespaces.py @@ -89,7 +89,7 @@ data_fixtures = { "GET": ( {}, { - "first": "/v2/metadefs/namespaces?limit=1", + "first": "/v2/metadefs/namespaces?limit=2", "namespaces": [ _get_namespace_fixture(NAMESPACE8), ], @@ -97,6 +97,43 @@ data_fixtures = { } ) }, + "/v2/metadefs/namespaces?limit=2&marker=%s" % NAMESPACE6: { + "GET": ( + {}, + { + "first": "/v2/metadefs/namespaces?limit=2", + "namespaces": [ + _get_namespace_fixture(NAMESPACE7), + _get_namespace_fixture(NAMESPACE8), + ], + "schema": "/v2/schemas/metadefs/namespaces" + } + ) + }, + "/v2/metadefs/namespaces?limit=20&sort_dir=asc": { + "GET": ( + {}, + { + "first": "/v2/metadefs/namespaces?limit=1", + "namespaces": [ + _get_namespace_fixture(NAMESPACE1), + ], + "schema": "/v2/schemas/metadefs/namespaces" + } + ) + }, + "/v2/metadefs/namespaces?limit=20&sort_key=created_at": { + "GET": ( + {}, + { + "first": "/v2/metadefs/namespaces?limit=1", + "namespaces": [ + _get_namespace_fixture(NAMESPACE1), + ], + "schema": "/v2/schemas/metadefs/namespaces" + } + ) + }, "/v2/metadefs/namespaces?limit=20&resource_types=%s" % RESOURCE_TYPE1: { "GET": ( {}, @@ -269,7 +306,7 @@ data_fixtures = { "updated_at": "2014-08-14T09:07:06Z", } ), - } + }, } schema_fixtures = { @@ -521,6 +558,40 @@ class TestNamespaceController(testtools.TestCase): self.assertEqual(NAMESPACE7, namespaces[0]['namespace']) self.assertEqual(NAMESPACE8, namespaces[1]['namespace']) + def test_list_with_limit_greater_than_page_size(self): + namespaces = list(self.controller.list(page_size=1, limit=2)) + self.assertEqual(2, len(namespaces)) + self.assertEqual(NAMESPACE7, namespaces[0]['namespace']) + self.assertEqual(NAMESPACE8, namespaces[1]['namespace']) + + def test_list_with_marker(self): + namespaces = list(self.controller.list(marker=NAMESPACE6, page_size=2)) + self.assertEqual(2, len(namespaces)) + self.assertEqual(NAMESPACE7, namespaces[0]['namespace']) + self.assertEqual(NAMESPACE8, namespaces[1]['namespace']) + + def test_list_with_sort_dir(self): + namespaces = list(self.controller.list(sort_dir='asc', limit=1)) + self.assertEqual(1, len(namespaces)) + self.assertEqual(NAMESPACE1, namespaces[0]['namespace']) + + def test_list_with_sort_dir_invalid(self): + # NOTE(TravT): The clients work by returning an iterator. + # Invoking the iterator is what actually executes the logic. + ns_iterator = self.controller.list(sort_dir='foo') + self.assertRaises(ValueError, next, ns_iterator) + + def test_list_with_sort_key(self): + namespaces = list(self.controller.list(sort_key='created_at', limit=1)) + self.assertEqual(1, len(namespaces)) + self.assertEqual(NAMESPACE1, namespaces[0]['namespace']) + + def test_list_with_sort_key_invalid(self): + # NOTE(TravT): The clients work by returning an iterator. + # Invoking the iterator is what actually executes the logic. + ns_iterator = self.controller.list(sort_key='foo') + self.assertRaises(ValueError, next, ns_iterator) + def test_list_namespaces_with_one_resource_type_filter(self): namespaces = list(self.controller.list( filters={