Add environment retrieval API
Adds a call to the REST API to retrieve the environment for a running stack. APIImpact Implements: blueprint environment-show Change-Id: I7e3577dfc854018245d79afdfee45a9d250d73a7
This commit is contained in:
parent
6483cfd5ac
commit
b0ca694dd7
@ -54,6 +54,7 @@
|
|||||||
"stacks:resource_schema": "rule:deny_stack_user",
|
"stacks:resource_schema": "rule:deny_stack_user",
|
||||||
"stacks:show": "rule:deny_stack_user",
|
"stacks:show": "rule:deny_stack_user",
|
||||||
"stacks:template": "rule:deny_stack_user",
|
"stacks:template": "rule:deny_stack_user",
|
||||||
|
"stacks:environment": "rule:deny_stack_user",
|
||||||
"stacks:update": "rule:deny_stack_user",
|
"stacks:update": "rule:deny_stack_user",
|
||||||
"stacks:update_patch": "rule:deny_stack_user",
|
"stacks:update_patch": "rule:deny_stack_user",
|
||||||
"stacks:preview_update": "rule:deny_stack_user",
|
"stacks:preview_update": "rule:deny_stack_user",
|
||||||
|
@ -170,7 +170,8 @@ class API(wsgi.Router):
|
|||||||
{
|
{
|
||||||
'name': 'stack_lookup_subpath',
|
'name': 'stack_lookup_subpath',
|
||||||
'url': '/stacks/{stack_name}/'
|
'url': '/stacks/{stack_name}/'
|
||||||
'{path:resources|events|template|actions}',
|
'{path:resources|events|template|actions'
|
||||||
|
'|environment}',
|
||||||
'action': 'lookup',
|
'action': 'lookup',
|
||||||
'method': 'GET'
|
'method': 'GET'
|
||||||
},
|
},
|
||||||
@ -193,6 +194,12 @@ class API(wsgi.Router):
|
|||||||
'action': 'template',
|
'action': 'template',
|
||||||
'method': 'GET'
|
'method': 'GET'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'stack_lookup',
|
||||||
|
'url': '/stacks/{stack_name}/{stack_id}/environment',
|
||||||
|
'action': 'environment',
|
||||||
|
'method': 'GET'
|
||||||
|
},
|
||||||
|
|
||||||
# Stack update/delete
|
# Stack update/delete
|
||||||
{
|
{
|
||||||
|
@ -453,6 +453,16 @@ class StackController(object):
|
|||||||
# TODO(zaneb): always set Content-type to application/json
|
# TODO(zaneb): always set Content-type to application/json
|
||||||
return templ
|
return templ
|
||||||
|
|
||||||
|
@util.identified_stack
|
||||||
|
def environment(self, req, identity):
|
||||||
|
"""Get the environment for an existing stack."""
|
||||||
|
env = self.rpc_client.get_environment(req.context, identity)
|
||||||
|
|
||||||
|
if env is None:
|
||||||
|
raise exc.HTTPNotFound()
|
||||||
|
|
||||||
|
return env
|
||||||
|
|
||||||
@util.identified_stack
|
@util.identified_stack
|
||||||
def update(self, req, identity, body):
|
def update(self, req, identity, body):
|
||||||
"""Update an existing stack with a new template and/or parameters."""
|
"""Update an existing stack with a new template and/or parameters."""
|
||||||
|
@ -294,7 +294,7 @@ class EngineService(service.Service):
|
|||||||
by the RPC caller.
|
by the RPC caller.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RPC_API_VERSION = '1.27'
|
RPC_API_VERSION = '1.28'
|
||||||
|
|
||||||
def __init__(self, host, topic):
|
def __init__(self, host, topic):
|
||||||
super(EngineService, self).__init__()
|
super(EngineService, self).__init__()
|
||||||
@ -1249,6 +1249,19 @@ class EngineService(service.Service):
|
|||||||
return s.raw_template.template
|
return s.raw_template.template
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@context.request_context
|
||||||
|
def get_environment(self, cnxt, stack_identity):
|
||||||
|
"""Returns the environment for an existing stack.
|
||||||
|
|
||||||
|
:param cnxt: RPC context
|
||||||
|
:param stack_identity: identifies the stack
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
s = self._get_stack(cnxt, stack_identity, show_deleted=True)
|
||||||
|
if s:
|
||||||
|
return s.raw_template.environment
|
||||||
|
return None
|
||||||
|
|
||||||
@context.request_context
|
@context.request_context
|
||||||
def list_outputs(self, cntx, stack_identity):
|
def list_outputs(self, cntx, stack_identity):
|
||||||
"""Get a list of stack outputs.
|
"""Get a list of stack outputs.
|
||||||
|
@ -48,6 +48,7 @@ class EngineClient(object):
|
|||||||
1.25 - list_stack_resource filter update
|
1.25 - list_stack_resource filter update
|
||||||
1.26 - Add mark_unhealthy
|
1.26 - Add mark_unhealthy
|
||||||
1.27 - Add check_software_deployment
|
1.27 - Add check_software_deployment
|
||||||
|
1.28 - Add environment_show call
|
||||||
"""
|
"""
|
||||||
|
|
||||||
BASE_RPC_API_VERSION = '1.0'
|
BASE_RPC_API_VERSION = '1.0'
|
||||||
@ -372,6 +373,19 @@ class EngineClient(object):
|
|||||||
return self.call(ctxt, self.make_msg('get_template',
|
return self.call(ctxt, self.make_msg('get_template',
|
||||||
stack_identity=stack_identity))
|
stack_identity=stack_identity))
|
||||||
|
|
||||||
|
def get_environment(self, context, stack_identity):
|
||||||
|
"""Returns the environment for an existing stack.
|
||||||
|
|
||||||
|
:param context: RPC context
|
||||||
|
:param stack_identity: identifies the stack
|
||||||
|
:rtype: dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.call(context,
|
||||||
|
self.make_msg('get_environment',
|
||||||
|
stack_identity=stack_identity),
|
||||||
|
version='1.28')
|
||||||
|
|
||||||
def delete_stack(self, ctxt, stack_identity, cast=True):
|
def delete_stack(self, ctxt, stack_identity, cast=True):
|
||||||
"""Deletes a given stack.
|
"""Deletes a given stack.
|
||||||
|
|
||||||
|
@ -1680,6 +1680,49 @@ class StackControllerTest(tools.ControllerTest, common.HeatTestCase):
|
|||||||
self.assertEqual(template, response)
|
self.assertEqual(template, response)
|
||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_get_environment(self, mock_enforce):
|
||||||
|
self._mock_enforce_setup(mock_enforce, 'environment', True)
|
||||||
|
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
|
||||||
|
req = self._get('/stacks/%(stack_name)s/%(stack_id)s' % identity)
|
||||||
|
env = {'parameters': {'Foo': 'bar'}}
|
||||||
|
|
||||||
|
self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
|
||||||
|
rpc_client.EngineClient.call(
|
||||||
|
req.context,
|
||||||
|
('get_environment', {'stack_identity': dict(identity)},),
|
||||||
|
version='1.28',
|
||||||
|
).AndReturn(env)
|
||||||
|
self.m.ReplayAll()
|
||||||
|
|
||||||
|
response = self.controller.environment(req, tenant_id=identity.tenant,
|
||||||
|
stack_name=identity.stack_name,
|
||||||
|
stack_id=identity.stack_id)
|
||||||
|
|
||||||
|
self.assertEqual(env, response)
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
|
def test_get_environment_no_env(self, mock_enforce):
|
||||||
|
self._mock_enforce_setup(mock_enforce, 'environment', True)
|
||||||
|
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
|
||||||
|
req = self._get('/stacks/%(stack_name)s/%(stack_id)s' % identity)
|
||||||
|
|
||||||
|
self.m.StubOutWithMock(rpc_client.EngineClient, 'call')
|
||||||
|
rpc_client.EngineClient.call(
|
||||||
|
req.context,
|
||||||
|
('get_environment', {'stack_identity': dict(identity)},),
|
||||||
|
version='1.28',
|
||||||
|
).AndReturn(None)
|
||||||
|
self.m.ReplayAll()
|
||||||
|
|
||||||
|
self.assertRaises(webob.exc.HTTPNotFound,
|
||||||
|
self.controller.environment,
|
||||||
|
req,
|
||||||
|
tenant_id=identity.tenant,
|
||||||
|
stack_name=identity.stack_name,
|
||||||
|
stack_id=identity.stack_id)
|
||||||
|
|
||||||
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_get_template_err_denied_policy(self, mock_enforce):
|
def test_get_template_err_denied_policy(self, mock_enforce):
|
||||||
self._mock_enforce_setup(mock_enforce, 'template', False)
|
self._mock_enforce_setup(mock_enforce, 'template', False)
|
||||||
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
|
identity = identifier.HeatIdentifier(self.tenant, 'wordpress', '6')
|
||||||
|
@ -40,7 +40,7 @@ class ServiceEngineTest(common.HeatTestCase):
|
|||||||
|
|
||||||
def test_make_sure_rpc_version(self):
|
def test_make_sure_rpc_version(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'1.27',
|
'1.28',
|
||||||
service.EngineService.RPC_API_VERSION,
|
service.EngineService.RPC_API_VERSION,
|
||||||
('RPC version is changed, please update this test to new version '
|
('RPC version is changed, please update this test to new version '
|
||||||
'and make sure additional test cases are added for RPC APIs '
|
'and make sure additional test cases are added for RPC APIs '
|
||||||
|
@ -1068,6 +1068,35 @@ class StackServiceTest(common.HeatTestCase):
|
|||||||
outputs = self.eng.list_outputs(self.ctx, mock.ANY)
|
outputs = self.eng.list_outputs(self.ctx, mock.ANY)
|
||||||
self.assertEqual([], outputs)
|
self.assertEqual([], outputs)
|
||||||
|
|
||||||
|
def test_get_environment(self):
|
||||||
|
# Setup
|
||||||
|
t = template_format.parse(tools.wp_template)
|
||||||
|
env = {'parameters': {'KeyName': 'EnvKey'}}
|
||||||
|
tmpl = templatem.Template(t)
|
||||||
|
stack = parser.Stack(self.ctx, 'get_env_stack', tmpl)
|
||||||
|
|
||||||
|
mock_get_stack = self.patchobject(self.eng, '_get_stack')
|
||||||
|
mock_get_stack.return_value = mock.MagicMock()
|
||||||
|
mock_get_stack.return_value.raw_template.environment = env
|
||||||
|
self.patchobject(parser.Stack, 'load', return_value=stack)
|
||||||
|
|
||||||
|
# Test
|
||||||
|
found = self.eng.get_environment(self.ctx, stack.identifier())
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
self.assertEqual(env, found)
|
||||||
|
|
||||||
|
def test_get_environment_no_env(self):
|
||||||
|
# Setup
|
||||||
|
exc = exception.EntityNotFound(entity='stack', name='missing')
|
||||||
|
self.patchobject(self.eng, '_get_stack', side_effect=exc)
|
||||||
|
|
||||||
|
# Test
|
||||||
|
self.assertRaises(dispatcher.ExpectedException,
|
||||||
|
self.eng.get_environment,
|
||||||
|
self.ctx,
|
||||||
|
'irrelevant')
|
||||||
|
|
||||||
def test_stack_show_output(self):
|
def test_stack_show_output(self):
|
||||||
t = template_format.parse(tools.wp_template)
|
t = template_format.parse(tools.wp_template)
|
||||||
t['outputs'] = {'test': {'value': 'first', 'description': 'sec'},
|
t['outputs'] = {'test': {'value': 'first', 'description': 'sec'},
|
||||||
|
@ -406,3 +406,8 @@ class EngineRpcAPITestCase(common.HeatTestCase):
|
|||||||
mark_unhealthy=True,
|
mark_unhealthy=True,
|
||||||
resource_status_reason="Any reason",
|
resource_status_reason="Any reason",
|
||||||
version='1.26')
|
version='1.26')
|
||||||
|
|
||||||
|
def test_get_environment(self):
|
||||||
|
self._test_engine_api(
|
||||||
|
'get_environment', 'call', stack_identity=self.identity,
|
||||||
|
version='1.28')
|
||||||
|
Loading…
Reference in New Issue
Block a user