HOT parameter validation model translation
Translate hot parameters into heat parameter model. Change-Id: I6733be7c13e2e9fdbed27d5c21044fb5f457ed17 Implements: blueprint hot-parameters
This commit is contained in:
parent
07a2840585
commit
929c9edd5c
@ -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."""
|
||||
|
@ -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."""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user