Merge "support list resources with details"
This commit is contained in:
commit
8dd3d7888a
@ -79,23 +79,34 @@ class ResourceController(object):
|
||||
self.options = options
|
||||
self.rpc_client = rpc_client.EngineClient()
|
||||
|
||||
def _extract_to_param(self, req, rpc_param, extractor, default):
|
||||
key = rpc_param
|
||||
if key in req.params:
|
||||
try:
|
||||
return extractor(key, req.params[key])
|
||||
except ValueError as e:
|
||||
raise exc.HTTPBadRequest(six.text_type(e))
|
||||
else:
|
||||
return default
|
||||
|
||||
@util.identified_stack
|
||||
def index(self, req, identity):
|
||||
"""
|
||||
Lists summary information for all resources
|
||||
Lists information for all resources
|
||||
"""
|
||||
|
||||
nested_depth = 0
|
||||
key = rpc_api.PARAM_NESTED_DEPTH
|
||||
if key in req.params:
|
||||
try:
|
||||
nested_depth = param_utils.extract_int(key, req.params[key])
|
||||
except ValueError as e:
|
||||
raise exc.HTTPBadRequest(six.text_type(e))
|
||||
nested_depth = self._extract_to_param(req,
|
||||
rpc_api.PARAM_NESTED_DEPTH,
|
||||
param_utils.extract_int,
|
||||
default=0)
|
||||
with_detail = self._extract_to_param(req,
|
||||
rpc_api.PARAM_WITH_DETAIL,
|
||||
param_utils.extract_bool,
|
||||
default=False)
|
||||
|
||||
res_list = self.rpc_client.list_stack_resources(req.context,
|
||||
identity,
|
||||
nested_depth)
|
||||
nested_depth,
|
||||
with_detail)
|
||||
|
||||
return {'resources': [format_resource(req, res) for res in res_list]}
|
||||
|
||||
|
@ -267,7 +267,7 @@ class EngineService(service.Service):
|
||||
by the RPC caller.
|
||||
"""
|
||||
|
||||
RPC_API_VERSION = '1.11'
|
||||
RPC_API_VERSION = '1.12'
|
||||
|
||||
def __init__(self, host, topic, manager=None):
|
||||
super(EngineService, self).__init__()
|
||||
@ -1256,12 +1256,13 @@ class EngineService(service.Service):
|
||||
if resource_name is None or name == resource_name]
|
||||
|
||||
@context.request_context
|
||||
def list_stack_resources(self, cnxt, stack_identity, nested_depth=0):
|
||||
def list_stack_resources(self, cnxt, stack_identity,
|
||||
nested_depth=0, with_detail=False):
|
||||
s = self._get_stack(cnxt, stack_identity, show_deleted=True)
|
||||
stack = parser.Stack.load(cnxt, stack=s)
|
||||
depth = min(nested_depth, cfg.CONF.max_nested_stack_depth)
|
||||
|
||||
return [api.format_stack_resource(resource, detail=False)
|
||||
return [api.format_stack_resource(resource, detail=with_detail)
|
||||
for resource in stack.iter_resources(depth)]
|
||||
|
||||
@context.request_context
|
||||
|
@ -19,13 +19,13 @@ PARAM_KEYS = (
|
||||
PARAM_SHOW_DELETED, PARAM_SHOW_NESTED, PARAM_EXISTING,
|
||||
PARAM_CLEAR_PARAMETERS, PARAM_GLOBAL_TENANT, PARAM_LIMIT,
|
||||
PARAM_NESTED_DEPTH, PARAM_TAGS, PARAM_SHOW_HIDDEN, PARAM_TAGS_ANY,
|
||||
PARAM_NOT_TAGS, PARAM_NOT_TAGS_ANY, TEMPLATE_TYPE,
|
||||
PARAM_NOT_TAGS, PARAM_NOT_TAGS_ANY, TEMPLATE_TYPE, PARAM_WITH_DETAIL
|
||||
) = (
|
||||
'timeout_mins', 'disable_rollback', 'adopt_stack_data',
|
||||
'show_deleted', 'show_nested', 'existing',
|
||||
'clear_parameters', 'global_tenant', 'limit',
|
||||
'nested_depth', 'tags', 'show_hidden', 'tags_any',
|
||||
'not_tags', 'not_tags_any', 'template_type',
|
||||
'not_tags', 'not_tags_any', 'template_type', 'with_detail',
|
||||
)
|
||||
|
||||
STACK_KEYS = (
|
||||
|
@ -32,6 +32,7 @@ class EngineClient(object):
|
||||
1.9 - Add template_type option to generate_template()
|
||||
1.10 - Add support for software config list
|
||||
1.11 - Add support for template versions list
|
||||
1.12 - Add with_detail option for stack resources list
|
||||
'''
|
||||
|
||||
BASE_RPC_API_VERSION = '1.0'
|
||||
@ -421,16 +422,21 @@ class EngineClient(object):
|
||||
stack_identity=stack_identity,
|
||||
resource_name=resource_name))
|
||||
|
||||
def list_stack_resources(self, ctxt, stack_identity, nested_depth=0):
|
||||
def list_stack_resources(self, ctxt, stack_identity,
|
||||
nested_depth=0, with_detail=False):
|
||||
"""
|
||||
List the resources belonging to a stack.
|
||||
:param ctxt: RPC context.
|
||||
:param stack_identity: Name of the stack.
|
||||
:param nested_depth: Levels of nested stacks of which list resources.
|
||||
:param with_detail: show detail for resoruces in list.
|
||||
"""
|
||||
return self.call(ctxt, self.make_msg('list_stack_resources',
|
||||
stack_identity=stack_identity,
|
||||
nested_depth=nested_depth))
|
||||
return self.call(ctxt,
|
||||
self.make_msg('list_stack_resources',
|
||||
stack_identity=stack_identity,
|
||||
nested_depth=nested_depth,
|
||||
with_detail=with_detail),
|
||||
version='1.12')
|
||||
|
||||
def stack_suspend(self, ctxt, stack_identity):
|
||||
return self.call(ctxt, self.make_msg('stack_suspend',
|
||||
|
@ -1598,7 +1598,9 @@ class CfnStackControllerTest(common.HeatTestCase):
|
||||
rpc_client.EngineClient.call(
|
||||
dummy_req.context,
|
||||
('list_stack_resources', {'stack_identity': identity,
|
||||
'nested_depth': 0})
|
||||
'nested_depth': 0,
|
||||
'with_detail': False}),
|
||||
version='1.12'
|
||||
).AndReturn(engine_resp)
|
||||
|
||||
self.m.ReplayAll()
|
||||
|
@ -2237,7 +2237,10 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
|
||||
rpc_client.EngineClient.call(
|
||||
req.context,
|
||||
('list_stack_resources', {'stack_identity': stack_identity,
|
||||
'nested_depth': 0})
|
||||
'nested_depth': 0,
|
||||
'with_detail': False,
|
||||
}),
|
||||
version='1.12'
|
||||
).AndReturn(engine_resp)
|
||||
self.m.ReplayAll()
|
||||
|
||||
@ -2274,13 +2277,16 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
|
||||
rpc_client.EngineClient.call(
|
||||
req.context,
|
||||
('list_stack_resources', {'stack_identity': stack_identity,
|
||||
'nested_depth': 0})
|
||||
'nested_depth': 0,
|
||||
'with_detail': False}),
|
||||
version='1.12'
|
||||
).AndRaise(to_remote_error(error))
|
||||
self.m.ReplayAll()
|
||||
|
||||
resp = request_with_middleware(fault.FaultWrapper,
|
||||
self.controller.index,
|
||||
req, tenant_id=self.tenant,
|
||||
req,
|
||||
tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id)
|
||||
|
||||
@ -2300,7 +2306,9 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
|
||||
rpc_client.EngineClient.call(
|
||||
req.context,
|
||||
('list_stack_resources', {'stack_identity': stack_identity,
|
||||
'nested_depth': 99})
|
||||
'nested_depth': 99,
|
||||
'with_detail': False}),
|
||||
version='1.12'
|
||||
).AndReturn([])
|
||||
self.m.ReplayAll()
|
||||
|
||||
@ -2348,6 +2356,80 @@ class ResourceControllerTest(ControllerTest, common.HeatTestCase):
|
||||
self.assertEqual(403, resp.status_int)
|
||||
self.assertIn('403 Forbidden', six.text_type(resp))
|
||||
|
||||
def test_index_detail(self, mock_enforce):
|
||||
self._mock_enforce_setup(mock_enforce, 'index', True)
|
||||
res_name = 'WikiDatabase'
|
||||
stack_identity = identifier.HeatIdentifier(self.tenant,
|
||||
'wordpress', '1')
|
||||
res_identity = identifier.ResourceIdentifier(resource_name=res_name,
|
||||
**stack_identity)
|
||||
|
||||
req = self._get(stack_identity._tenant_path() + '/resources',
|
||||
{'with_detail': 'true'})
|
||||
|
||||
resp_parameters = {
|
||||
"OS::project_id": "3ab5b02fa01f4f95afa1e254afc4a435",
|
||||
"network": "cf05086d-07c7-4ed6-95e5-e4af724677e6",
|
||||
"OS::stack_name": "s1", "admin_pass": "******",
|
||||
"key_name": "kk", "image": "fa5d387e-541f-4dfb-ae8a-83a614683f84",
|
||||
"db_port": "50000",
|
||||
"OS::stack_id": "723d7cee-46b3-4433-9c21-f3378eb0bfc4",
|
||||
"flavor": "1"
|
||||
},
|
||||
|
||||
engine_resp = [
|
||||
{
|
||||
u'resource_identity': dict(res_identity),
|
||||
u'stack_name': stack_identity.stack_name,
|
||||
u'resource_name': res_name,
|
||||
u'resource_status_reason': None,
|
||||
u'updated_time': u'2012-07-23T13:06:00Z',
|
||||
u'stack_identity': stack_identity,
|
||||
u'resource_action': u'CREATE',
|
||||
u'resource_status': u'COMPLETE',
|
||||
u'physical_resource_id':
|
||||
u'a3455d8c-9f88-404d-a85b-5315293e67de',
|
||||
u'resource_type': u'AWS::EC2::Instance',
|
||||
u'parameters': resp_parameters,
|
||||
u'description': u'Hello description',
|
||||
u'stack_user_project_id': u'6f38bcfebbc4400b82d50c1a2ea3057d',
|
||||
}
|
||||
]
|
||||
self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
|
||||
rpc_client.EngineClient.call(
|
||||
req.context,
|
||||
('list_stack_resources', {'stack_identity': stack_identity,
|
||||
'nested_depth': 0,
|
||||
'with_detail': True}),
|
||||
version='1.12'
|
||||
).AndReturn(engine_resp)
|
||||
self.m.ReplayAll()
|
||||
|
||||
result = self.controller.index(req, tenant_id=self.tenant,
|
||||
stack_name=stack_identity.stack_name,
|
||||
stack_id=stack_identity.stack_id)
|
||||
|
||||
expected = {
|
||||
'resources': [{'links': [{'href': self._url(res_identity),
|
||||
'rel': 'self'},
|
||||
{'href': self._url(stack_identity),
|
||||
'rel': 'stack'}],
|
||||
u'resource_name': res_name,
|
||||
u'logical_resource_id': res_name,
|
||||
u'resource_status_reason': None,
|
||||
u'updated_time': u'2012-07-23T13:06:00Z',
|
||||
u'resource_status': u'CREATE_COMPLETE',
|
||||
u'physical_resource_id':
|
||||
u'a3455d8c-9f88-404d-a85b-5315293e67de',
|
||||
u'resource_type': u'AWS::EC2::Instance',
|
||||
u'parameters': resp_parameters,
|
||||
u'description': u'Hello description',
|
||||
u'stack_user_project_id':
|
||||
u'6f38bcfebbc4400b82d50c1a2ea3057d'}]}
|
||||
|
||||
self.assertEqual(expected, result)
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_show(self, mock_enforce):
|
||||
self._mock_enforce_setup(mock_enforce, 'show', True)
|
||||
res_name = 'WikiDatabase'
|
||||
|
@ -39,7 +39,7 @@ class ServiceEngineTest(common.HeatTestCase):
|
||||
|
||||
def test_make_sure_rpc_version(self):
|
||||
self.assertEqual(
|
||||
'1.11',
|
||||
'1.12',
|
||||
service.EngineService.RPC_API_VERSION,
|
||||
('RPC version is changed, please update this test to new version '
|
||||
'and make sure additional test cases are added for RPC APIs '
|
||||
|
@ -230,7 +230,8 @@ class EngineRpcAPITestCase(common.HeatTestCase):
|
||||
def test_list_stack_resources(self):
|
||||
self._test_engine_api('list_stack_resources', 'call',
|
||||
stack_identity=self.identity,
|
||||
nested_depth=0)
|
||||
nested_depth=0,
|
||||
with_detail=False)
|
||||
|
||||
def test_stack_suspend(self):
|
||||
self._test_engine_api('stack_suspend', 'call',
|
||||
|
Loading…
Reference in New Issue
Block a user