Support Pagination for namespace list
The rest api metadefs/namespaces supports pagination using the parameters of limit, marker, sort_dir, & sort_key. However, the glance client isn't passing those parameters through (they come in as kwargs). This is preventing pagination from working properly in horizon. This is affecting Horizon support: https://review.openstack.org/#/c/104063/ Change-Id: Ib349cf3a3a437eb1711f350b37d0bd0e7d01330a Closes-Bug: 1381816
This commit is contained in:
		@@ -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))
 | 
			
		||||
 
 | 
			
		||||
@@ -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={
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user