From: Zane Bitter Date: Sun, 17 Jun 2012 14:05:57 +0000 (+0200) Subject: Move parsing of parameters out of template parser X-Git-Tag: 2014.1~1717 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=582b8b29cb443410ee87f8518e648aefdc42014f;p=openstack-build%2Fheat-build.git Move parsing of parameters out of template parser 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 --- diff --git a/heat/engine/manager.py b/heat/engine/manager.py index 1faad3bc..51271b23 100644 --- a/heat/engine/manager.py +++ b/heat/engine/manager.py @@ -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 diff --git a/heat/engine/parser.py b/heat/engine/parser.py index a215dc76..5b0f3b38 100644 --- a/heat/engine/parser.py +++ b/heat/engine/parser.py @@ -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 index 00000000..a9943c18 --- /dev/null +++ b/heat/tests/test_manager.py @@ -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) diff --git a/heat/tests/test_resources.py b/heat/tests/test_resources.py index 59a1075e..dededd09 100644 --- a/heat/tests/test_resources.py +++ b/heat/tests/test_resources.py @@ -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',