API support for Environments

Support "Environment" section in the create/update body.
We the roll up the parameters and the environment and send
that as json using the rpc "params" argument. So no changes
to the rpc layer are needed. The engine knows how to deal
with both formats in the Environments class.

blueprint envirnonments
Change-Id: I6d6085d5c052a5f9115ecd46891b00d2fad4d1db
This commit is contained in:
Angus Salkeld 2013-06-17 14:39:19 +10:00
parent c28f12d94f
commit 95ac80a0d5
3 changed files with 87 additions and 18 deletions

View File

@ -142,6 +142,12 @@
</p></doc>
</param>
<param name="environment" style="plain" required="true">
<doc><p xmlns="http://www.w3.org/1999/xhtml">
A JSON envionment for the stack.
</p></doc>
</param>
<param name="param_name-n" style="plain" required="true">
<doc><p xmlns="http://www.w3.org/1999/xhtml">
User-defined parameter names to pass to the template.
@ -226,6 +232,12 @@
</p></doc>
</param>
<param name="environment" style="plain" required="true">
<doc><p xmlns="http://www.w3.org/1999/xhtml">
A JSON envionment for the stack.
</p></doc>
</param>
<param name="param_name-n" style="plain" required="true">
<doc><p xmlns="http://www.w3.org/1999/xhtml">
User-defined parameter names to pass to the template.

View File

@ -44,11 +44,13 @@ class InstantiationData(object):
PARAM_TEMPLATE,
PARAM_TEMPLATE_URL,
PARAM_USER_PARAMS,
PARAM_ENVIRONMENT,
) = (
'stack_name',
'template',
'template_url',
'parameters',
'environment',
)
def __init__(self, data):
@ -99,11 +101,33 @@ class InstantiationData(object):
return self.format_parse(template_data, 'Template')
def user_params(self):
def environment(self):
"""
Get the user-supplied parameters for the stack in JSON format.
Get the user-supplied environment for the stack in YAML format.
If the user supplied Parameters then merge these into the
environment global options.
"""
return self.data.get(self.PARAM_USER_PARAMS, {})
env = {}
if self.PARAM_ENVIRONMENT in self.data:
env_data = self.data[self.PARAM_ENVIRONMENT]
if isinstance(env_data, dict):
env = env_data
else:
env = self.format_parse(env_data,
'Environment',
add_template_sections=False)
for field in env:
if field not in ('parameters', 'resource_registry'):
reason = _("%s not in valid in the environment") % field
raise exc.HTTPBadRequest(reason)
if self.PARAM_USER_PARAMS not in env:
env[self.PARAM_USER_PARAMS] = {}
parameters = self.data.get(self.PARAM_USER_PARAMS, {})
env[self.PARAM_USER_PARAMS].update(parameters)
return env
def args(self):
"""
@ -180,7 +204,7 @@ class StackController(object):
result = self.engine.create_stack(req.context,
data.stack_name(),
data.template(),
data.user_params(),
data.environment(),
data.args())
except rpc_common.RemoteError as ex:
return util.remote_error(ex)
@ -255,7 +279,7 @@ class StackController(object):
res = self.engine.update_stack(req.context,
identity,
data.template(),
data.user_params(),
data.environment(),
data.args())
except rpc_common.RemoteError as ex:
return util.remote_error(ex)

View File

@ -114,21 +114,54 @@ blarg: wibble
data = stacks.InstantiationData(body)
self.assertRaises(webob.exc.HTTPBadRequest, data.template)
def test_user_params(self):
def test_parameters(self):
params = {'foo': 'bar', 'blarg': 'wibble'}
body = {'parameters': params}
data = stacks.InstantiationData(body)
self.assertEqual(data.user_params(), params)
self.assertEqual(data.environment(), body)
def test_user_params_missing(self):
params = {'foo': 'bar', 'blarg': 'wibble'}
body = {'not the parameters': params}
def test_environment_only_params(self):
env = {'parameters': {'foo': 'bar', 'blarg': 'wibble'}}
body = {'environment': env}
data = stacks.InstantiationData(body)
self.assertEqual(data.user_params(), {})
self.assertEqual(data.environment(), env)
def test_environment_and_parameters(self):
body = {'parameters': {'foo': 'bar'},
'environment': {'parameters': {'blarg': 'wibble'}}}
expect = {'parameters': {'blarg': 'wibble',
'foo': 'bar'}}
data = stacks.InstantiationData(body)
self.assertEqual(data.environment(), expect)
def test_parameters_override_environment(self):
# This tests that the cli parameters will override
# any parameters in the environment.
body = {'parameters': {'foo': 'bar',
'tester': 'Yes'},
'environment': {'parameters': {'blarg': 'wibble',
'tester': 'fail'}}}
expect = {'parameters': {'blarg': 'wibble',
'foo': 'bar',
'tester': 'Yes'}}
data = stacks.InstantiationData(body)
self.assertEqual(data.environment(), expect)
def test_environment_bad_format(self):
body = {'environment': {'somethingnotsupported': {'blarg': 'wibble'}}}
data = stacks.InstantiationData(body)
self.assertRaises(webob.exc.HTTPBadRequest, data.environment)
def test_environment_missing(self):
env = {'foo': 'bar', 'blarg': 'wibble'}
body = {'not the environment': env}
data = stacks.InstantiationData(body)
self.assertEqual(data.environment(), {'parameters': {}})
def test_args(self):
body = {
'parameters': {},
'environment': {},
'stack_name': 'foo',
'template': {},
'template_url': 'http://example.com/',
@ -324,7 +357,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'create_stack',
'args': {'stack_name': identity.stack_name,
'template': template,
'params': parameters,
'params': {'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndReturn(dict(identity))
@ -358,7 +391,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'params': parameters,
'params': {'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndRaise(rpc_common.RemoteError("AttributeError"))
@ -367,7 +400,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'params': parameters,
'params': {'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndRaise(rpc_common.RemoteError("UnknownUserParameter"))
@ -401,7 +434,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'params': parameters,
'params': {'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndRaise(rpc_common.RemoteError("StackExists"))
@ -430,7 +463,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'create_stack',
'args': {'stack_name': stack_name,
'template': template,
'params': parameters,
'params': {'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndRaise(rpc_common.RemoteError(
@ -719,7 +752,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'update_stack',
'args': {'stack_identity': dict(identity),
'template': template,
'params': parameters,
'params': {'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndReturn(dict(identity))
@ -751,7 +784,7 @@ class StackControllerTest(ControllerTest, HeatTestCase):
'method': 'update_stack',
'args': {'stack_identity': dict(identity),
'template': template,
'params': parameters,
'params': {u'parameters': parameters},
'args': {'timeout_mins': 30}},
'version': self.api_version},
None).AndRaise(rpc_common.RemoteError("StackNotFound"))