]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
API support for Environments
authorAngus Salkeld <asalkeld@redhat.com>
Mon, 17 Jun 2013 04:39:19 +0000 (14:39 +1000)
committerAngus Salkeld <asalkeld@redhat.com>
Mon, 17 Jun 2013 10:26:28 +0000 (20:26 +1000)
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

doc/docbkx/api-ref/src/wadls/heat-api/src/heat-api-1.0.wadl
heat/api/openstack/v1/stacks.py
heat/tests/test_api_openstack_v1.py

index 146ed7a7c4706bf70259e53d7982390ca486aaf3..be9340fee55623ea46a0593b82b000baf8992acc 100644 (file)
                 </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.
                 </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.
index 9dcec53eb1f203434ee0c99136368cc201e4cd41..6e7f897defd381a65ffb05c2867d5dd2a25dff81 100644 (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)
index b1e35b033aaea776ca8dac59f6420a21c18df5b7..4c4694c2ca7f713b29eb224c1c6f32f91b246476 100644 (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.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.user_params(), {})
+        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"))