]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Move parsing of parameters out of template parser
authorZane Bitter <zbitter@redhat.com>
Sun, 17 Jun 2012 14:05:57 +0000 (16:05 +0200)
committerZane Bitter <zbitter@redhat.com>
Sun, 17 Jun 2012 16:25:23 +0000 (18:25 +0200)
The format of the params received by the manager is a property of the Heat
API protocol, not of the template, so it makes sense not to have the parser
extracting the template parameter data from them. This simplifies the
implementation of #123 (Nested Stacks).

Change-Id: I8eaf50caf79f69359cbc8ee1f0193c08d7944d1c
Signed-off-by: Zane Bitter <zbitter@redhat.com>
heat/engine/manager.py
heat/engine/parser.py
heat/tests/test_manager.py [new file with mode: 0644]
heat/tests/test_resources.py

index 1faad3bc6c898ec858ac222727c22ff73ec3e44d..51271b233060ec17fc1ba0b0ff3a04eb644cefd2 100644 (file)
@@ -20,6 +20,7 @@ import logging
 import webob
 import json
 import urlparse
+import re
 import httplib
 import eventlet
 
@@ -39,6 +40,25 @@ from novaclient.exceptions import AuthorizationFailure
 logger = logging.getLogger('heat.engine.manager')
 greenpool = eventlet.GreenPool()
 
+_param_key = re.compile(r'Parameters\.member\.(.*?)\.ParameterKey$')
+
+
+def _extract_user_params(params):
+    def get_param_pairs():
+        for k in params:
+            keymatch = _param_key.match(k)
+            if keymatch:
+                key = params[k]
+                v = 'Parameters.member.%s.ParameterValue' % keymatch.group(1)
+                try:
+                    value = params[v]
+                except KeyError:
+                    logger.error('Could not apply parameter %s' % key)
+
+                yield (key, value)
+
+    return dict(get_param_pairs())
+
 
 class EngineManager(manager.Manager):
     """
@@ -126,7 +146,7 @@ class EngineManager(manager.Manager):
         for s in stacks:
             ps = parser.Stack(context, s.name,
                               s.raw_template.parsed_template.template,
-                              s.id, params)
+                              s.id, _extract_user_params(params))
             mem = {}
             mem['StackId'] = s.id
             mem['StackName'] = s.name
@@ -152,7 +172,7 @@ class EngineManager(manager.Manager):
         if s:
             ps = parser.Stack(context, s.name,
                               s.raw_template.parsed_template.template,
-                              s.id, params)
+                              s.id, _extract_user_params(params))
             mem = {}
             mem['StackId'] = s.id
             mem['StackName'] = s.name
@@ -193,12 +213,14 @@ class EngineManager(manager.Manager):
         if db_api.stack_get_by_name(None, stack_name):
             return {'Error': 'Stack already exists with that name.'}
 
+        user_params = _extract_user_params(params)
         metadata_server = config.FLAGS.heat_metadata_server_url
         # We don't want to reset the stack template, so we are making
         # an instance just for validation.
         template_copy = deepcopy(template)
         stack_validator = parser.Stack(context, stack_name,
-                                       template_copy, 0, params,
+                                       template_copy, 0,
+                                       user_params,
                                        metadata_server=metadata_server)
         response = stack_validator.validate()
         stack_validator = None
@@ -207,7 +229,7 @@ class EngineManager(manager.Manager):
                 response['ValidateTemplateResult']['Description']:
             return response
 
-        stack = parser.Stack(context, stack_name, template, 0, params,
+        stack = parser.Stack(context, stack_name, template, 0, user_params,
                              metadata_server=metadata_server)
         rt = {}
         rt['template'] = template
@@ -253,7 +275,8 @@ class EngineManager(manager.Manager):
             return webob.exc.HTTPBadRequest(explanation=msg)
 
         try:
-            s = parser.Stack(context, 'validate', template, 0, params)
+            s = parser.Stack(context, 'validate', template, 0,
+                             _extract_user_params(params))
         except KeyError as ex:
             res = ('A Fn::FindInMap operation referenced '
                    'a non-existent map [%s]' % str(ex))
@@ -298,7 +321,7 @@ class EngineManager(manager.Manager):
 
         ps = parser.Stack(context, st.name,
                           st.raw_template.parsed_template.template,
-                          st.id, params)
+                          st.id, _extract_user_params(params))
         greenpool.spawn_n(ps.delete)
         return None
 
index a215dc76f1125143ec1ce3fba26e908a6a082c5a..5b0f3b38ea8289c93b40b621ec70dc8e06999795 100644 (file)
@@ -68,7 +68,7 @@ class Stack(object):
 
         # user Parameters
         if parms is not None:
-            self._apply_user_parameters(parms)
+            self.parms.update(parms)
 
         self.resources = dict((name,
                                Resource(name, data, self))
@@ -295,19 +295,6 @@ class Stack(object):
         # TODO(asalkeld) if any of this fails we Should
         # restart the whole stack
 
-    def _apply_user_parameters(self, parms):
-        for p in parms:
-            if 'Parameters.member.' in p and 'ParameterKey' in p:
-                s = p.split('.')
-                try:
-                    key_name = 'Parameters.member.%s.ParameterKey' % s[2]
-                    value_name = 'Parameters.member.%s.ParameterValue' % s[2]
-                    logger.debug('applying user parameter %s=%s' %
-                                 (key_name, value_name))
-                    self.parms[parms[key_name]] = parms[value_name]
-                except Exception:
-                    logger.error('Could not apply parameter %s' % p)
-
     def parameter_get(self, key):
         if not key in self.parms:
             raise exception.UserParameterMissing(key=key)
diff --git a/heat/tests/test_manager.py b/heat/tests/test_manager.py
new file mode 100644 (file)
index 0000000..a9943c1
--- /dev/null
@@ -0,0 +1,55 @@
+import nose
+import unittest
+from nose.plugins.attrib import attr
+
+import heat.engine.manager as manager
+
+
+@attr(tag=['unit', 'manager'])
+@attr(speed='fast')
+class managerTest(unittest.TestCase):
+    def test_params_extract(self):
+        p = {'Parameters.member.Foo.ParameterKey': 'foo',
+             'Parameters.member.Foo.ParameterValue': 'bar',
+             'Parameters.member.Blarg.ParameterKey': 'blarg',
+             'Parameters.member.Blarg.ParameterValue': 'wibble'}
+        params = manager._extract_user_params(p)
+        self.assertEqual(len(params), 2)
+        self.assertTrue('foo' in params)
+        self.assertEqual(params['foo'], 'bar')
+        self.assertTrue('blarg' in params)
+        self.assertEqual(params['blarg'], 'wibble')
+
+    def test_params_extract_dots(self):
+        p = {'Parameters.member.Foo.Bar.ParameterKey': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar',
+             'Parameters.member.Foo.Baz.ParameterKey': 'blarg',
+             'Parameters.member.Foo.Baz.ParameterValue': 'wibble'}
+        params = manager._extract_user_params(p)
+        self.assertEqual(len(params), 2)
+        self.assertTrue('foo' in params)
+        self.assertEqual(params['foo'], 'bar')
+        self.assertTrue('blarg' in params)
+        self.assertEqual(params['blarg'], 'wibble')
+
+    def test_params_extract_garbage(self):
+        p = {'Parameters.member.Foo.Bar.ParameterKey': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar',
+             'Foo.Baz.ParameterKey': 'blarg',
+             'Foo.Baz.ParameterValue': 'wibble'}
+        params = manager._extract_user_params(p)
+        self.assertEqual(len(params), 1)
+        self.assertTrue('foo' in params)
+        self.assertEqual(params['foo'], 'bar')
+
+    def test_params_extract_garbage_prefix(self):
+        p = {'prefixParameters.member.Foo.Bar.ParameterKey': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar'}
+        params = manager._extract_user_params(p)
+        self.assertFalse(params)
+
+    def test_params_extract_garbage_suffix(self):
+        p = {'Parameters.member.Foo.Bar.ParameterKeysuffix': 'foo',
+             'Parameters.member.Foo.Bar.ParameterValue': 'bar'}
+        params = manager._extract_user_params(p)
+        self.assertFalse(params)
index 59a1075e1e4c0968d5bfeddc159aff6738afa0d2..dededd0968542f4c64455e02a2172b75db902340 100644 (file)
@@ -34,11 +34,9 @@ class instancesTest(unittest.TestCase):
         t = json.loads(f.read())
         f.close()
 
-        params = {}
         parameters = {}
-        params['KeyStoneCreds'] = None
         t['Parameters']['KeyName']['Value'] = 'test'
-        stack = parser.Stack(None, 'test_stack', t, 0, params)
+        stack = parser.Stack(None, 'test_stack', t, 0)
 
         self.m.StubOutWithMock(db_api, 'resource_get_by_name_and_stack')
         db_api.resource_get_by_name_and_stack(None, 'test_resource_name',
@@ -82,11 +80,9 @@ class instancesTest(unittest.TestCase):
         t = json.loads(f.read())
         f.close()
 
-        params = {}
         parameters = {}
-        params['KeyStoneCreds'] = None
         t['Parameters']['KeyName']['Value'] = 'test'
-        stack = parser.Stack(None, 'test_stack', t, 0, params)
+        stack = parser.Stack(None, 'test_stack', t, 0)
 
         self.m.StubOutWithMock(db_api, 'resource_get_by_name_and_stack')
         db_api.resource_get_by_name_and_stack(None, 'test_resource_name',