Add offset & limit docs & tests

A number of endpoints enable pagination via 'limit' & 'offset' query
parameters, but don't document or test this functionality.

 - os-cells
 - os-security-groups
 - os-server-groups
 - os-snapshots
 - os-virtual-interfaces
 - os-volume-attachments
 - os-volumes

Change-Id: I5b0ad25f7282f4a13bbb6f21b76e986e1008936a
This commit is contained in:
Diana Clarke 2016-12-15 13:20:32 -05:00
parent 551fa18d2d
commit fdba403d09
11 changed files with 146 additions and 9 deletions

View File

@ -29,6 +29,8 @@ Request
.. rest_parameters:: parameters.yaml
- tenant_id: tenant_id
- limit: limit_simple
- offset: offset_simple
.. TODO(cdent): How do we indicate optionality of a URI parameter?
@ -80,6 +82,14 @@ Normal response codes: 200
Error response codes: badRequest(400), unauthorized(401), forbidden(403),
NotImplemented(501)
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit_simple
- offset: offset_simple
Response
--------

View File

@ -28,6 +28,14 @@ Normal response codes: 200
Error response codes: unauthorized(401), forbidden(403), itemNotFound(404)
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit_simple
- offset: offset_simple
Response
--------

View File

@ -35,6 +35,8 @@ Request
- server_id: server_id_path
- limit: limit_simple
- offset: offset_simple
Response
--------

View File

@ -25,6 +25,8 @@ Request
.. rest_parameters:: parameters.yaml
- server_id: server_id_path
- limit: limit_simple
- offset: offset_simple
Response
--------

View File

@ -26,6 +26,14 @@ Normal response codes: 200
Error response codes: unauthorized(401), forbidden(403)
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit_simple
- offset: offset_simple
Response
--------
@ -126,6 +134,14 @@ Normal response codes: 200
Error response codes: unauthorized(401), forbidden(403)
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit_simple
- offset: offset_simple
Response
--------
@ -237,6 +253,14 @@ Normal response codes: 200
Error response codes: unauthorized(401), forbidden(403)
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit_simple
- offset: offset_simple
Response
--------
@ -315,6 +339,14 @@ Normal response codes: 200
Error response codes: unauthorized(401), forbidden(403)
Request
-------
.. rest_parameters:: parameters.yaml
- limit: limit_simple
- offset: offset_simple
Response
--------

View File

@ -114,6 +114,16 @@ class CellsTestV21(BaseCellsTest):
self.assertNotIn('capabilities', cell)
self.assertNotIn('password', cell)
def test_index_offset_and_limit(self):
req = self._get_request('cells?offset=1&limit=1')
res_dict = self.controller.index(req)
self.assertEqual(len(res_dict['cells']), 1)
cell = res_dict['cells'][0]
self.assertEqual(cell['name'], self.fake_cells[1]['name'])
self.assertNotIn('capabilities', cell)
self.assertNotIn('password', cell)
def test_detail(self):
req = self._get_request("cells/detail")
res_dict = self.controller.detail(req)
@ -124,6 +134,16 @@ class CellsTestV21(BaseCellsTest):
self.assertEqual(cell['capabilities'], self.fake_capabilities[i])
self.assertNotIn('password', cell)
def test_detail_offset_and_limit(self):
req = self._get_request("cells/detail?offset=1&limit=1")
res_dict = self.controller.detail(req)
self.assertEqual(len(res_dict['cells']), 1)
cell = res_dict['cells'][0]
self.assertEqual(cell['name'], self.fake_cells[1]['name'])
self.assertEqual(cell['capabilities'], self.fake_capabilities[1])
self.assertNotIn('password', cell)
def test_show_bogus_cell_raises(self):
req = self._get_request("cells/bogus")
self.assertRaises(exc.HTTPNotFound, self.controller.show, req, 'bogus')

View File

@ -138,6 +138,13 @@ class TestNeutronSecurityGroupsV21(
list_dict = self.controller.index(req)
self.assertEqual(len(list_dict['security_groups']), 2)
def test_get_security_group_list_offset_and_limit(self):
path = '/v2/fake/os-security-groups?offset=1&limit=1'
self._create_sg_template().get('security_group')
req = fakes.HTTPRequest.blank(path)
list_dict = self.controller.index(req)
self.assertEqual(len(list_dict['security_groups']), 1)
def test_get_security_group_list_all_tenants(self):
pass

View File

@ -317,6 +317,12 @@ class TestSecurityGroupsV21(test.TestCase):
self.req, {'security_group': sg})
def test_get_security_group_list(self):
self._test_get_security_group_list()
def test_get_security_group_list_offset_and_limit(self):
self._test_get_security_group_list(limited=True)
def _test_get_security_group_list(self, limited=False):
groups = []
for i, name in enumerate(['default', 'test']):
sg = security_group_template(id=i + 1,
@ -324,7 +330,10 @@ class TestSecurityGroupsV21(test.TestCase):
description=name + '-desc',
rules=[])
groups.append(sg)
expected = {'security_groups': groups}
if limited:
expected = {'security_groups': [groups[1]]}
else:
expected = {'security_groups': groups}
def return_security_groups(context, project_id):
return [security_group_db(sg) for sg in groups]
@ -332,7 +341,12 @@ class TestSecurityGroupsV21(test.TestCase):
self.stub_out('nova.db.security_group_get_by_project',
return_security_groups)
res_dict = self.controller.index(self.req)
path = '/v2/fake/os-security-groups'
if limited:
path += '?offset=1&limit=1'
req = fakes.HTTPRequest.blank(path, use_admin_context=True)
res_dict = self.controller.index(req)
self.assertEqual(res_dict, expected)

View File

@ -161,12 +161,16 @@ class ServerGroupTestV21(test.TestCase):
ig_uuid = self._create_instance_group(ctx, members)
return (ig_uuid, instances, members)
def _test_list_server_group_all(self, api_version='2.1'):
self._test_list_server_group(api_version=api_version, limited=False)
def _test_list_server_group_offset_and_limit(self, api_version='2.1'):
self._test_list_server_group(api_version=api_version, limited=True)
@mock.patch.object(nova.db, 'instance_group_get_all_by_project_id')
@mock.patch.object(nova.db, 'instance_group_get_all')
def _test_list_server_group_all(self,
mock_get_all,
mock_get_by_project,
api_version='2.1'):
def _test_list_server_group(self, mock_get_all, mock_get_by_project,
api_version='2.1', limited=False):
policies = ['anti-affinity']
members = []
metadata = {} # always empty
@ -202,8 +206,12 @@ class ServerGroupTestV21(test.TestCase):
tenant_groups = [sg2]
all_groups = [sg1, sg2]
all = {'server_groups': all_groups}
tenant_specific = {'server_groups': tenant_groups}
if limited:
all = {'server_groups': [sg2]}
tenant_specific = {'server_groups': []}
else:
all = {'server_groups': all_groups}
tenant_specific = {'server_groups': tenant_groups}
def return_all_server_groups():
return [server_group_db(sg) for sg in all_groups]
@ -216,7 +224,8 @@ class ServerGroupTestV21(test.TestCase):
mock_get_by_project.return_value = return_tenant_server_groups()
path = '/os-server-groups?all_projects=True'
if limited:
path += '&offset=1&limit=1'
req = fakes.HTTPRequest.blank(path, version=api_version)
admin_req = fakes.HTTPRequest.blank(path, use_admin_context=True,
version=api_version)
@ -454,6 +463,9 @@ class ServerGroupTestV21(test.TestCase):
def test_list_server_group_all(self):
self._test_list_server_group_all(api_version='2.1')
def test_list_server_group_offset_and_limit(self):
self._test_list_server_group_offset_and_limit(api_version='2.1')
def test_list_server_groups_rbac_default(self):
# test as admin
self.controller.index(self.admin_req)
@ -550,5 +562,8 @@ class ServerGroupTestV213(ServerGroupTestV21):
def test_list_server_group_all(self):
self._test_list_server_group_all(api_version='2.13')
def test_list_server_group_offset_and_limit(self):
self._test_list_server_group_offset_and_limit(api_version='2.13')
def test_list_server_group_by_tenant(self):
self._test_list_server_group_by_tenant(api_version='2.13')

View File

@ -114,12 +114,31 @@ class SnapshotApiTestV21(test.NoDBTestCase):
resp_snapshot = resp_snapshots.pop()
self.assertEqual(102, resp_snapshot['id'])
def test_snapshot_detail_offset_and_limit(self):
path = '/v2/fake/os-snapshots/detail?offset=1&limit=1'
req = fakes.HTTPRequest.blank(path)
resp_dict = self.controller.detail(req)
self.assertIn('snapshots', resp_dict)
resp_snapshots = resp_dict['snapshots']
self.assertEqual(1, len(resp_snapshots))
resp_snapshot = resp_snapshots.pop()
self.assertEqual(101, resp_snapshot['id'])
def test_snapshot_index(self):
resp_dict = self.controller.index(self.req)
self.assertIn('snapshots', resp_dict)
resp_snapshots = resp_dict['snapshots']
self.assertEqual(3, len(resp_snapshots))
def test_snapshot_index_offset_and_limit(self):
path = '/v2/fake/os-snapshots?offset=1&limit=1'
req = fakes.HTTPRequest.blank(path)
resp_dict = self.controller.index(req)
self.assertIn('snapshots', resp_dict)
resp_snapshots = resp_dict['snapshots']
self.assertEqual(1, len(resp_snapshots))
class TestSnapshotAPIDeprecation(test.NoDBTestCase):

View File

@ -85,6 +85,14 @@ class ServerVirtualInterfaceTestV21(test.NoDBTestCase):
res_dict = self.controller.index(req, 'fake_uuid')
self.assertEqual(self.expected_response, res_dict)
def test_get_virtual_interfaces_list_offset_and_limit(self):
path = '/v2/fake/os-virtual-interfaces?offset=1&limit=1'
req = fakes.HTTPRequest.blank(path, version=self.wsgi_api_version)
res_dict = self.controller.index(req, 'fake_uuid')
name = 'virtual_interfaces'
limited_response = {name: [self.expected_response[name][1]]}
self.assertEqual(limited_response, res_dict)
def test_vif_instance_not_found(self):
self.mox.StubOutWithMock(compute_api.API, 'get')
fake_context = context.RequestContext('fake', 'fake')