Merge "Expose resource attributes in the API"

This commit is contained in:
Jenkins 2014-12-10 02:59:26 +00:00 committed by Gerrit Code Review
commit ce5bee0b8d
5 changed files with 83 additions and 16 deletions

View File

@ -96,9 +96,12 @@ class ResourceController(object):
Gets detailed information for a resource
"""
whitelist = {'with_attr': 'multi'}
params = util.get_allowed_params(req.params, whitelist)
res = self.rpc_client.describe_stack_resource(req.context,
identity,
resource_name)
resource_name,
**params)
return {'resource': format_resource(req, res)}

View File

@ -332,16 +332,20 @@ class EngineClient(object):
sort_keys=sort_keys,
sort_dir=sort_dir))
def describe_stack_resource(self, ctxt, stack_identity, resource_name):
def describe_stack_resource(self, ctxt, stack_identity, resource_name,
with_attr=None):
"""
Get detailed resource information about a particular resource.
:param ctxt: RPC context.
:param stack_identity: Name of the stack.
:param resource_name: the Resource.
"""
return self.call(ctxt, self.make_msg('describe_stack_resource',
return self.call(ctxt,
self.make_msg('describe_stack_resource',
stack_identity=stack_identity,
resource_name=resource_name))
resource_name=resource_name,
with_attr=with_attr),
version='1.2')
def find_physical_resource(self, ctxt, physical_resource_id):
"""

View File

@ -1410,9 +1410,10 @@ class CfnStackControllerTest(common.HeatTestCase):
args = {
'stack_identity': identity,
'resource_name': dummy_req.params.get('LogicalResourceId'),
'with_attr': None,
}
rpc_client.EngineClient.call(
dummy_req.context, ('describe_stack_resource', args)
dummy_req.context, ('describe_stack_resource', args), version='1.2'
).AndReturn(engine_resp)
self.m.ReplayAll()
@ -1474,9 +1475,10 @@ class CfnStackControllerTest(common.HeatTestCase):
args = {
'stack_identity': identity,
'resource_name': dummy_req.params.get('LogicalResourceId'),
'with_attr': None,
}
rpc_client.EngineClient.call(
dummy_req.context, ('describe_stack_resource', args)
dummy_req.context, ('describe_stack_resource', args), version='1.2'
).AndRaise(heat_exception.ResourceNotFound(
resource_name='test', stack_name='test'))

View File

@ -2145,7 +2145,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndReturn(engine_resp)
self.m.ReplayAll()
@ -2207,7 +2209,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndReturn(engine_resp)
self.m.ReplayAll()
@ -2240,7 +2244,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndRaise(to_remote_error(error))
self.m.ReplayAll()
@ -2255,6 +2261,47 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
self.assertEqual('StackNotFound', resp.json['error']['type'])
self.m.VerifyAll()
def test_show_with_single_attribute(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'show', True)
res_name = 'WikiDatabase'
stack_identity = identifier.HeatIdentifier(self.tenant, 'foo', '1')
res_identity = identifier.ResourceIdentifier(resource_name=res_name,
**stack_identity)
mock_describe = mock.Mock(return_value={'foo': 'bar'})
self.controller.rpc_client.describe_stack_resource = mock_describe
req = self._get(res_identity._tenant_path(), {'with_attr': 'baz'})
resp = self.controller.show(req, tenant_id=self.tenant,
stack_name=stack_identity.stack_name,
stack_id=stack_identity.stack_id,
resource_name=res_name)
self.assertEqual({'resource': {'foo': 'bar'}}, resp)
args, kwargs = mock_describe.call_args
self.assertIn('baz', kwargs['with_attr'])
def test_show_with_multiple_attributes(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'show', True)
res_name = 'WikiDatabase'
stack_identity = identifier.HeatIdentifier(self.tenant, 'foo', '1')
res_identity = identifier.ResourceIdentifier(resource_name=res_name,
**stack_identity)
mock_describe = mock.Mock(return_value={'foo': 'bar'})
self.controller.rpc_client.describe_stack_resource = mock_describe
req = self._get(res_identity._tenant_path())
req.environ['QUERY_STRING'] = 'with_attr=a1&with_attr=a2&with_attr=a3'
resp = self.controller.show(req, tenant_id=self.tenant,
stack_name=stack_identity.stack_name,
stack_id=stack_identity.stack_id,
resource_name=res_name)
self.assertEqual({'resource': {'foo': 'bar'}}, resp)
args, kwargs = mock_describe.call_args
self.assertIn('a1', kwargs['with_attr'])
self.assertIn('a2', kwargs['with_attr'])
self.assertIn('a3', kwargs['with_attr'])
def test_show_nonexist_resource(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'show', True)
res_name = 'Wibble'
@ -2270,7 +2317,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndRaise(to_remote_error(error))
self.m.ReplayAll()
@ -2300,7 +2349,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndRaise(to_remote_error(error))
self.m.ReplayAll()
@ -2363,7 +2414,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndReturn(engine_resp)
self.m.ReplayAll()
@ -2392,7 +2445,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndRaise(to_remote_error(error))
self.m.ReplayAll()
@ -2422,7 +2477,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
rpc_client.EngineClient.call(
req.context,
('describe_stack_resource',
{'stack_identity': stack_identity, 'resource_name': res_name})
{'stack_identity': stack_identity, 'resource_name': res_name,
'with_attr': None}),
version='1.2'
).AndRaise(to_remote_error(error))
self.m.ReplayAll()

View File

@ -208,7 +208,8 @@ class EngineRpcAPITestCase(testtools.TestCase):
def test_describe_stack_resource(self):
self._test_engine_api('describe_stack_resource', 'call',
stack_identity=self.identity,
resource_name='LogicalResourceId')
resource_name='LogicalResourceId',
with_attr=None)
def test_find_physical_resource(self):
self._test_engine_api('find_physical_resource', 'call',