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 <zbitter@redhat.com>
This commit is contained in:
parent
892b99bff4
commit
582b8b29cb
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue