HOT parameter validation model translation

Translate hot parameters into heat parameter model.

Change-Id: I6733be7c13e2e9fdbed27d5c21044fb5f457ed17
Implements: blueprint hot-parameters
This commit is contained in:
JUN JIE NAN 2013-07-23 08:47:38 +08:00
parent 07a2840585
commit 929c9edd5c
2 changed files with 179 additions and 28 deletions

View File

@ -81,35 +81,64 @@ class HOTemplate(template.Template):
return default
@staticmethod
def _snake_to_camel(name):
tokens = []
if name:
tokens = name.split('_')
for i in xrange(len(tokens)):
tokens[i] = tokens[i].capitalize()
return "".join(tokens)
def _translate_constraints(self, constraints):
param = {}
def add_constraint(key, val, desc):
cons = param.get(key, [])
cons.append((val, desc))
param[key] = cons
def add_min_max(key, val, desc):
minv = val.get('min')
maxv = val.get('max')
if minv:
add_constraint('Min%s' % key, minv, desc)
if maxv:
add_constraint('Max%s' % key, maxv, desc)
for constraint in constraints:
desc = constraint.get('description')
for key, val in constraint.iteritems():
key = self._snake_to_camel(key)
if key == 'Description':
continue
elif key == 'Range':
add_min_max('Value', val, desc)
elif key == 'Length':
add_min_max(key, val, desc)
else:
add_constraint(key, val, desc)
return param
def _translate_parameters(self, parameters):
"""Get the parameters of the template translated into CFN format."""
HOT_TO_CFN_ATTRS = {'type': 'Type',
'default': 'Default',
'description': 'Description'}
HOT_TO_CFN_TYPES = {'string': 'String'}
cfn_params = {}
for param_name, attrs in parameters.iteritems():
cfn_param = {}
for attr, attr_value in attrs.iteritems():
cfn_attr = self._translate(attr, HOT_TO_CFN_ATTRS, attr)
if attr == 'type':
# try to translate type; if no translation found, keep
# original value and let engine throw an error for an
# unsupported type
attr_value = self._translate(attr_value, HOT_TO_CFN_TYPES,
attr_value)
cfn_param[cfn_attr] = attr_value
if len(cfn_param) > 0:
cfn_params[param_name] = cfn_param
return cfn_params
params = {}
for name, attrs in parameters.iteritems():
param = {}
for key, val in attrs.iteritems():
key = self._snake_to_camel(key)
if key == 'Type':
val = self._snake_to_camel(val)
elif key == 'Constraints':
param.update(self._translate_constraints(val))
continue
elif key == 'Hidden':
key = 'NoEcho'
param[key] = val
if len(param) > 0:
params[name] = param
return params
def _translate_resources(self, resources):
"""Get the resources of the template translated into CFN format."""

View File

@ -86,11 +86,133 @@ class HOTemplateTest(HeatTestCase):
''')
expected = {'param1': {'Description': 'foo',
'Type': 'unsupported_type'}}
'Type': 'UnsupportedType'}}
tmpl = parser.Template(hot_tpl)
self.assertEqual(tmpl[hot.PARAMETERS], expected)
def test_translate_parameters_length_range(self):
hot_tpl = template_format.parse('''
heat_template_version: 2013-05-23
parameters:
wait_time:
description: application wait time
type: number
default: 150
constraints:
- range: { min: 120, max: 600}
description: min value 120 seconds, max value 600 seconds
key_name:
description: Name of an existing EC2 KeyPair
type: string
default: heat_key
constraints:
- length: {min: 1, max: 32}
description: length should be between 1 and 32
''')
expected = {
'wait_time': {
'Description': 'application wait time',
'Type': 'Number',
'Default': 150,
'MaxValue': [
(600, 'min value 120 seconds, max value 600 seconds')],
'MinValue': [
(120, 'min value 120 seconds, max value 600 seconds')]
},
'key_name': {
'Description': 'Name of an existing EC2 KeyPair',
'Type': 'String',
'Default': 'heat_key',
'MaxLength': [(32, u'length should be between 1 and 32')],
'MinLength': [(1, u'length should be between 1 and 32')]
}}
tmpl = parser.Template(hot_tpl)
self.assertEqual(expected, tmpl[hot.PARAMETERS])
def test_translate_parameters_allowed_values(self):
hot_tpl = template_format.parse('''
heat_template_version: 2013-05-23
parameters:
instance_type:
description: instance type
type: string
default: m1.small
constraints:
- allowed_values: ["m1.tiny",
"m1.small",
"m1.medium", "m1.large", "m1.xlarge"]
description: must be a valid EC2 instance type.
''')
expected = {
'instance_type': {
'Description': 'instance type',
'Type': 'String',
'Default': 'm1.small',
'AllowedValues': [(["m1.tiny",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge"],
'must be a valid EC2 instance type.')]}}
tmpl = parser.Template(hot_tpl)
self.assertEqual(expected, tmpl[hot.PARAMETERS])
def test_translate_parameters_allowed_patterns(self):
hot_tpl = template_format.parse('''
heat_template_version: 2013-05-23
parameters:
db_name:
description: The WordPress database name
type: string
default: wordpress
constraints:
- length: { min: 1, max: 64 }
description: string lenght should between 1 and 64
- allowed_pattern: "[a-zA-Z]+"
description: Value must consist of characters only
- allowed_pattern: "[a-z]+[a-zA-Z]*"
description: Value must start with a lowercase character
''')
expected = {
'db_name': {
'Description': 'The WordPress database name',
'Type': 'String',
'Default': 'wordpress',
'MinLength': [(1, 'string lenght should between 1 and 64')],
'MaxLength': [(64, 'string lenght should between 1 and 64')],
'AllowedPattern': [
('[a-zA-Z]+',
'Value must consist of characters only'),
('[a-z]+[a-zA-Z]*',
'Value must start with a lowercase character')]}}
tmpl = parser.Template(hot_tpl)
self.assertEqual(expected, tmpl[hot.PARAMETERS])
def test_translate_parameters_hidden(self):
hot_tpl = template_format.parse('''
heat_template_version: 2013-05-23
parameters:
user_roles:
description: User roles
type: comma_delimited_list
default: guest,newhire
hidden: TRUE
''')
expected = {
'user_roles': {
'Description': 'User roles',
'Type': 'CommaDelimitedList',
'Default': 'guest,newhire',
'NoEcho': True
}}
tmpl = parser.Template(hot_tpl)
self.assertEqual(expected, tmpl[hot.PARAMETERS])
def test_translate_resources(self):
"""Test translation of resources into internal engine format."""