Merge "Expose resource attributes in the API"
This commit is contained in:
commit
ce5bee0b8d
@ -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)}
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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'))
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user