Add query param to allow nested resource list

Add `nested_depth` param to OpenStack API to allow listing of
nested resources up to `nested_depth` level.

Implements: blueprint explode-nested-resources
Change-Id: I1cd6c35fe7f3eb1c5b67217e38aef53cb0b6ff76
This commit is contained in:
Anderson Mesquita 2014-07-10 18:55:09 -04:00
parent a199f46137
commit 3dea425647
5 changed files with 40 additions and 7 deletions

View File

@ -81,8 +81,12 @@ class ResourceController(object):
Lists summary information for all resources Lists summary information for all resources
""" """
# Though nested_depth is defaulted in the RPC API, this prevents empty
# strings from being passed, thus breaking the code in the engine.
nested_depth = int(req.params.get('nested_depth') or 0)
res_list = self.rpc_client.list_stack_resources(req.context, res_list = self.rpc_client.list_stack_resources(req.context,
identity) identity,
nested_depth)
return {'resources': [format_resource(req, res) for res in res_list]} return {'resources': [format_resource(req, res) for res in res_list]}

View File

@ -323,14 +323,16 @@ class EngineClient(object):
stack_identity=stack_identity, stack_identity=stack_identity,
resource_name=resource_name)) resource_name=resource_name))
def list_stack_resources(self, ctxt, stack_identity): def list_stack_resources(self, ctxt, stack_identity, nested_depth=0):
""" """
List the resources belonging to a stack. List the resources belonging to a stack.
:param ctxt: RPC context. :param ctxt: RPC context.
:param stack_identity: Name of the stack. :param stack_identity: Name of the stack.
:param nested_depth: Levels of nested stacks of which list resources.
""" """
return self.call(ctxt, self.make_msg('list_stack_resources', return self.call(ctxt, self.make_msg('list_stack_resources',
stack_identity=stack_identity)) stack_identity=stack_identity,
nested_depth=nested_depth))
def stack_suspend(self, ctxt, stack_identity): def stack_suspend(self, ctxt, stack_identity):
return self.call(ctxt, self.make_msg('stack_suspend', return self.call(ctxt, self.make_msg('stack_suspend',

View File

@ -1625,7 +1625,8 @@ class CfnStackControllerTest(HeatTestCase):
).AndReturn(identity) ).AndReturn(identity)
rpc_client.EngineClient.call( rpc_client.EngineClient.call(
dummy_req.context, dummy_req.context,
('list_stack_resources', {'stack_identity': identity}) ('list_stack_resources', {'stack_identity': identity,
'nested_depth': 0})
).AndReturn(engine_resp) ).AndReturn(engine_resp)
self.m.ReplayAll() self.m.ReplayAll()

View File

@ -1723,7 +1723,8 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
self.m.StubOutWithMock(rpc_client.EngineClient, 'call') self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
rpc_client.EngineClient.call( rpc_client.EngineClient.call(
req.context, req.context,
('list_stack_resources', {'stack_identity': stack_identity}) ('list_stack_resources', {'stack_identity': stack_identity,
'nested_depth': 0})
).AndReturn(engine_resp) ).AndReturn(engine_resp)
self.m.ReplayAll() self.m.ReplayAll()
@ -1759,7 +1760,8 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
self.m.StubOutWithMock(rpc_client.EngineClient, 'call') self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
rpc_client.EngineClient.call( rpc_client.EngineClient.call(
req.context, req.context,
('list_stack_resources', {'stack_identity': stack_identity}) ('list_stack_resources', {'stack_identity': stack_identity,
'nested_depth': 0})
).AndRaise(to_remote_error(error)) ).AndRaise(to_remote_error(error))
self.m.ReplayAll() self.m.ReplayAll()
@ -1773,6 +1775,29 @@ class ResourceControllerTest(ControllerTest, HeatTestCase):
self.assertEqual('StackNotFound', resp.json['error']['type']) self.assertEqual('StackNotFound', resp.json['error']['type'])
self.m.VerifyAll() self.m.VerifyAll()
def test_index_nested_depth(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
stack_identity = identifier.HeatIdentifier(self.tenant,
'rubbish', '1')
req = self._get(stack_identity._tenant_path() + '/resources',
{'nested_depth': '99'})
self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
rpc_client.EngineClient.call(
req.context,
('list_stack_resources', {'stack_identity': stack_identity,
'nested_depth': 99})
).AndReturn([])
self.m.ReplayAll()
result = self.controller.index(req, tenant_id=self.tenant,
stack_name=stack_identity.stack_name,
stack_id=stack_identity.stack_id)
self.assertEqual([], result['resources'])
self.m.VerifyAll()
def test_index_denied_policy(self, mock_enforce): def test_index_denied_policy(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', False) self._mock_enforce_setup(mock_enforce, 'index', False)
res_name = 'WikiDatabase' res_name = 'WikiDatabase'

View File

@ -174,7 +174,8 @@ class EngineRpcAPITestCase(testtools.TestCase):
def test_list_stack_resources(self): def test_list_stack_resources(self):
self._test_engine_api('list_stack_resources', 'call', self._test_engine_api('list_stack_resources', 'call',
stack_identity=self.identity) stack_identity=self.identity,
nested_depth=0)
def test_stack_suspend(self): def test_stack_suspend(self):
self._test_engine_api('stack_suspend', 'call', self._test_engine_api('stack_suspend', 'call',