summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-01-07 03:59:43 +0000
committerGerrit Code Review <review@openstack.org>2016-01-07 03:59:43 +0000
commitf15918318c8b9f645ebc0b5fe672d10fce3e4d03 (patch)
tree84f3a90fcb5232a379c7d96d6f7736bbfa768168
parent411ab2ef2d82fda170bac9b1ef74ed5706d4be77 (diff)
parentc28d40814962b3a8ccb81e5e7d7f832c8f0a3c9a (diff)
downloadpython-keystoneclient-f15918318c8b9f645ebc0b5fe672d10fce3e4d03.tar.gz
Merge "Support `truncated` flag returned by keystone"
-rw-r--r--keystoneclient/base.py22
-rw-r--r--keystoneclient/tests/unit/v3/utils.py41
2 files changed, 55 insertions, 8 deletions
diff --git a/keystoneclient/base.py b/keystoneclient/base.py
index e10d888..4dd16d7 100644
--- a/keystoneclient/base.py
+++ b/keystoneclient/base.py
@@ -20,6 +20,7 @@ Base utilities to build API operation managers and objects on top of.
"""
import abc
+import collections
import copy
import functools
import warnings
@@ -76,6 +77,23 @@ def filter_kwargs(f):
return func
+class KeystoneReturnedList(collections.Sequence):
+ """A list of entities with additional attributes."""
+
+ def __init__(self, collection, truncated=False):
+ self.collection = collection
+ self.truncated = truncated
+
+ def __getitem__(self, i):
+ return self.collection[i]
+
+ def __len__(self):
+ return len(self.collection)
+
+ def sort(self, *args, **kwargs):
+ return self.collection.sort(*args, **kwargs)
+
+
class Manager(object):
"""Basic manager type providing common operations.
@@ -127,6 +145,7 @@ class Manager(object):
obj_class = self.resource_class
data = body[response_key]
+ truncated = body.get('truncated', False)
# NOTE(ja): keystone returns values as list as {'values': [ ... ]}
# unlike other services which just return the list...
try:
@@ -134,7 +153,8 @@ class Manager(object):
except (KeyError, TypeError):
pass
- return [obj_class(self, res, loaded=True) for res in data if res]
+ objects = [obj_class(self, res, loaded=True) for res in data if res]
+ return KeystoneReturnedList(objects, truncated=truncated)
def _get(self, url, response_key, **kwargs):
"""Get an object from collection.
diff --git a/keystoneclient/tests/unit/v3/utils.py b/keystoneclient/tests/unit/v3/utils.py
index 2a02b49..d573608 100644
--- a/keystoneclient/tests/unit/v3/utils.py
+++ b/keystoneclient/tests/unit/v3/utils.py
@@ -196,11 +196,16 @@ class CrudTests(object):
kwargs.setdefault(uuid.uuid4().hex, uuid.uuid4().hex)
return kwargs
- def encode(self, entity):
+ def encode(self, entity, truncated=None):
+ encoded = {}
+ if truncated is not None:
+ encoded['truncated'] = truncated
if isinstance(entity, dict):
- return {self.key: entity}
+ encoded[self.key] = entity
+ return encoded
if isinstance(entity, list):
- return {self.collection_key: entity}
+ encoded[self.collection_key] = entity
+ return encoded
raise NotImplementedError('Are you sure you want to encode that?')
def stub_entity(self, method, parts=None, entity=None, id=None, **kwargs):
@@ -291,14 +296,22 @@ class CrudTests(object):
self.assertRaises(TypeError, self.manager.list, **filter_kwargs)
- def test_list(self, ref_list=None, expected_path=None,
- expected_query=None, **filter_kwargs):
+ def _test_list(self, ref_list=None, expected_path=None,
+ expected_query=None, truncated=None, **filter_kwargs):
ref_list = ref_list or [self.new_ref(), self.new_ref()]
expected_path = self._get_expected_path(expected_path)
- self.requests_mock.get(urlparse.urljoin(self.TEST_URL, expected_path),
- json=self.encode(ref_list))
+ # We want to catch all cases: when `truncated` is not returned by the
+ # server, when it's False and when it's True.
+ # Attribute `truncated` of the returned list-like object should exist
+ # in all these cases. It should be False if the server returned a list
+ # without the flag.
+ expected_truncated = False
+ if truncated:
+ expected_truncated = truncated
+ self.requests_mock.get(urlparse.urljoin(self.TEST_URL, expected_path),
+ json=self.encode(ref_list, truncated=truncated))
returned_list = self.manager.list(**filter_kwargs)
self.assertEqual(len(ref_list), len(returned_list))
[self.assertIsInstance(r, self.model) for r in returned_list]
@@ -317,6 +330,20 @@ class CrudTests(object):
for key in qs_args:
self.assertIn(key, qs_args_expected)
+ self.assertEqual(expected_truncated, returned_list.truncated)
+
+ def test_list(self, ref_list=None, expected_path=None,
+ expected_query=None, **filter_kwargs):
+ # test simple list, without any truncation
+ self._test_list(ref_list, expected_path, expected_query,
+ **filter_kwargs)
+ # test when a server returned a list with truncated=False
+ self._test_list(ref_list, expected_path, expected_query,
+ truncated=False, **filter_kwargs)
+ # test when a server returned a list with truncated=True
+ self._test_list(ref_list, expected_path, expected_query,
+ truncated=True, **filter_kwargs)
+
def test_list_params(self):
ref_list = [self.new_ref()]
filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex}