diff --git a/keystone/common/driver_hints.py b/keystone/common/driver_hints.py index d6eed36ea5..9731de462a 100644 --- a/keystone/common/driver_hints.py +++ b/keystone/common/driver_hints.py @@ -38,7 +38,7 @@ def truncated(f): _('Cannot truncate a driver call without hints list as ' 'first parameter after self ')) - if hints.limit is None: + if hints.limit is None or hints.filters: return f(self, hints, *args, **kwargs) # A limit is set, so ask for one more entry than we need diff --git a/keystone/common/sql/core.py b/keystone/common/sql/core.py index a8301ddac8..b7c36203ea 100644 --- a/keystone/common/sql/core.py +++ b/keystone/common/sql/core.py @@ -371,7 +371,11 @@ def _limit(query, hints): # If we satisfied all the filters, set an upper limit if supplied if hints.limit: - query = query.limit(hints.limit['limit']) + original_len = query.count() + limit_query = query.limit(hints.limit['limit']) + if limit_query.count() < original_len: + hints.limit['truncated'] = True + query = limit_query return query diff --git a/keystone/tests/unit/test_v3_catalog.py b/keystone/tests/unit/test_v3_catalog.py index aedf1f01f4..22bef50a50 100644 --- a/keystone/tests/unit/test_v3_catalog.py +++ b/keystone/tests/unit/test_v3_catalog.py @@ -345,12 +345,13 @@ class CatalogTestCase(test_v3.RestfulTestCase): def test_filter_list_services_by_name(self): """Call ``GET /services?name=``.""" - target_ref = self._create_random_service() - # create unrelated services self._create_random_service() self._create_random_service() + # create the desired service + target_ref = self._create_random_service() + response = self.get('/services?name=' + target_ref['name']) self.assertValidServiceListResponse(response, ref=target_ref) @@ -360,6 +361,12 @@ class CatalogTestCase(test_v3.RestfulTestCase): filtered_service = filtered_service_list[0] self.assertEqual(target_ref['name'], filtered_service['name']) + def test_filter_list_services_by_name_with_list_limit(self): + """Call ``GET /services?name=``.""" + self.config_fixture.config(list_limit=1) + + self.test_filter_list_services_by_name() + def test_get_head_service(self): """Call ``GET & HEAD /services/{service_id}``.""" resource_url = '/services/%(service_id)s' % { diff --git a/releasenotes/notes/bug-1594482-52a5dd1d8477b694.yaml b/releasenotes/notes/bug-1594482-52a5dd1d8477b694.yaml new file mode 100644 index 0000000000..656d2f697c --- /dev/null +++ b/releasenotes/notes/bug-1594482-52a5dd1d8477b694.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - > + [`bug 1594482 `_] + When using list_limit config option, the GET /services?name={service_name} + API was first truncating the list and afterwards filtering by name. + The API was fixed to first filter by name and only afterwards truncate the + result list to the desired limit.