diff --git a/heat/engine/manager.py b/heat/engine/manager.py index 1faad3bc6c..51271b2330 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 a215dc76f1..5b0f3b38ea 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 0000000000..a9943c186a --- /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 59a1075e1e..dededd0968 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',