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:
parent
1709206382
commit
c8293a3143
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue