Handle HOT param constraints in provider templates

When HOT templates are used as provider templates, parameter constraints
have to be translated into provider resource properties correctly. The
properties Schema class has been design to cover both CFN and HOT, but
the code in Schema.from_parameter has to distinguish between CFN and
HOT parameter constraints to correctly build the schema.

This patch fixes the handling of HOT parameters.

Change-Id: I59027d3b51e5d6dcc2a867cc5b5015cd6c88051c
Closes-Bug: #1224111
This commit is contained in:
Thomas Spatzier 2013-09-23 18:47:42 +02:00 committed by Gerrit Code Review
parent 1709206382
commit c8293a3143
2 changed files with 202 additions and 7 deletions

View File

@ -18,6 +18,7 @@ import re
from heat.common import exception
from heat.engine import parameters
from heat.engine import hot
SCHEMA_KEYS = (
REQUIRED, IMPLEMENTED, DEFAULT, TYPE, SCHEMA,
@ -191,13 +192,13 @@ class Schema(collections.Mapping):
parameters.JSON: MAP
}
def constraints():
def get_num(key):
val = param.get(key)
if val is not None:
val = Property.str_to_num(val)
return val
def get_num(key, context=param):
val = context.get(key)
if val is not None:
val = Property.str_to_num(val)
return val
def constraints():
desc = param.get(parameters.CONSTRAINT_DESCRIPTION)
if parameters.MIN_VALUE in param or parameters.MAX_VALUE in param:
@ -212,10 +213,37 @@ class Schema(collections.Mapping):
if parameters.ALLOWED_PATTERN in param:
yield AllowedPattern(param[parameters.ALLOWED_PATTERN], desc)
def constraints_hot():
constraints = param.get(hot.CONSTRAINTS)
if constraints is None:
return
for constraint in constraints:
desc = constraint.get(hot.DESCRIPTION)
if hot.RANGE in constraint:
const_def = constraint.get(hot.RANGE)
yield Range(get_num(hot.MIN, const_def),
get_num(hot.MAX, const_def), desc)
if hot.LENGTH in constraint:
const_def = constraint.get(hot.LENGTH)
yield Length(get_num(hot.MIN, const_def),
get_num(hot.MAX, const_def), desc)
if hot.ALLOWED_VALUES in constraint:
const_def = constraint.get(hot.ALLOWED_VALUES)
yield AllowedValues(const_def, desc)
if hot.ALLOWED_PATTERN in constraint:
const_def = constraint.get(hot.ALLOWED_PATTERN)
yield AllowedPattern(const_def, desc)
if isinstance(param, hot.HOTParamSchema):
constraint_list = list(constraints_hot())
else:
constraint_list = list(constraints())
return cls(param_type_map.get(param[parameters.TYPE], MAP),
description=param.get(parameters.DESCRIPTION),
required=parameters.DEFAULT not in param,
constraints=list(constraints()))
constraints=constraint_list)
def validate_constraints(self, value):
for constraint in self.constraints:

View File

@ -18,6 +18,7 @@ import testtools
from heat.engine import parameters
from heat.engine import properties
from heat.engine import resources
from heat.engine import hot
from heat.common import exception
@ -1256,6 +1257,172 @@ class PropertiesTest(testtools.TestCase):
self.assertEqual(expected,
dict((n, dict(s)) for n, s in props_schemata.items()))
def test_schema_from_hot_params(self):
params_snippet = {
"KeyName": {
"Type": "String",
"Description": ("Name of an existing EC2 KeyPair to enable "
"SSH access to the instances")
},
"InstanceType": {
"Default": "m1.large",
"Type": "String",
"Description": "WebServer EC2 instance type",
"constraints": [
{"allowed_values": ["t1.micro", "m1.small", "m1.large",
"m1.xlarge", "m2.xlarge", "m2.2xlarge",
"m2.4xlarge", "c1.medium", "c1.xlarge",
"cc1.4xlarge"],
"description": "Must be a valid EC2 instance type."}
]
},
"LinuxDistribution": {
"Default": "F17",
"Type": "String",
"Description": "Distribution of choice",
"constraints": [
{"allowed_values": ["F18", "F17", "U10", "RHEL-6.1",
"RHEL-6.2", "RHEL-6.3"],
"description": "Must be a valid Linux distribution"}
]
},
"DBName": {
"Type": "String",
"Description": "The WordPress database name",
"Default": "wordpress",
"constraints": [
{"length": {"min": 1, "max": 64},
"description": "Length must be between 1 and 64"},
{"allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
"description": ("Must begin with a letter and contain "
"only alphanumeric characters.")}
]
},
"DBUsername": {
"Type": "String",
"Description": "The WordPress database admin account username",
"Default": "admin",
"NoEcho": "true",
"constraints": [
{"length": {"min": 1, "max": 16},
"description": "Length must be between 1 and 16"},
{"allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
"description": ("Must begin with a letter and only "
"contain alphanumeric characters")}
]
},
"DBPassword": {
"Type": "String",
"Description": "The WordPress database admin account password",
"Default": "admin",
"NoEcho": "true",
"constraints": [
{"length": {"min": 1, "max": 41},
"description": "Length must be between 1 and 41"},
{"allowed_pattern": "[a-zA-Z0-9]*",
"description": ("Must contain only alphanumeric "
"characters")}
]
},
"DBRootPassword": {
"Type": "String",
"Description": "Root password for MySQL",
"Default": "admin",
"NoEcho": "true",
"constraints": [
{"length": {"min": 1, "max": 41},
"description": "Length must be between 1 and 41"},
{"allowed_pattern": "[a-zA-Z0-9]*",
"description": ("Must contain only alphanumeric "
"characters")}
]
}
}
expected = {
"KeyName": {
"type": "string",
"description": ("Name of an existing EC2 KeyPair to enable "
"SSH access to the instances"),
"required": True,
},
"InstanceType": {
"type": "string",
"description": "WebServer EC2 instance type",
"required": False,
"constraints": [
{"allowed_values": ["t1.micro", "m1.small", "m1.large",
"m1.xlarge", "m2.xlarge", "m2.2xlarge",
"m2.4xlarge", "c1.medium", "c1.xlarge",
"cc1.4xlarge"],
"description": "Must be a valid EC2 instance type."},
]
},
"LinuxDistribution": {
"type": "string",
"description": "Distribution of choice",
"required": False,
"constraints": [
{"allowed_values": ["F18", "F17", "U10",
"RHEL-6.1", "RHEL-6.2", "RHEL-6.3"],
"description": "Must be a valid Linux distribution"}
]
},
"DBName": {
"type": "string",
"description": "The WordPress database name",
"required": False,
"constraints": [
{"length": {"min": 1, "max": 64},
"description": "Length must be between 1 and 64"},
{"allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
"description": ("Must begin with a letter and contain "
"only alphanumeric characters.")},
]
},
"DBUsername": {
"type": "string",
"description": "The WordPress database admin account username",
"required": False,
"constraints": [
{"length": {"min": 1, "max": 16},
"description": "Length must be between 1 and 16"},
{"allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
"description": ("Must begin with a letter and only "
"contain alphanumeric characters")},
]
},
"DBPassword": {
"type": "string",
"description": "The WordPress database admin account password",
"required": False,
"constraints": [
{"length": {"min": 1, "max": 41},
"description": "Length must be between 1 and 41"},
{"allowed_pattern": "[a-zA-Z0-9]*",
"description": ("Must contain only alphanumeric "
"characters")},
]
},
"DBRootPassword": {
"type": "string",
"description": "Root password for MySQL",
"required": False,
"constraints": [
{"length": {"min": 1, "max": 41},
"description": "Length must be between 1 and 41"},
{"allowed_pattern": "[a-zA-Z0-9]*",
"description": ("Must contain only alphanumeric "
"characters")},
]
}
}
params = dict((n, hot.HOTParamSchema(s)) for n, s
in params_snippet.items())
props_schemata = properties.Properties.schema_from_params(params)
self.assertEqual(expected,
dict((n, dict(s)) for n, s in props_schemata.items()))
class PropertiesValidationTest(testtools.TestCase):
def test_required(self):