Validate properties against the schema in validate_template

Change-Id: I81457d8d363226b90b2a878ec2c93f88b376dc83
Fixes: bug #1154722
This commit is contained in:
Thomas Herve 2013-04-29 17:21:42 +02:00
parent 2db9b282a0
commit 25dfc5f062
3 changed files with 95 additions and 6 deletions

View File

@ -172,13 +172,14 @@ class Properties(collections.Mapping):
else:
self.error_prefix = parent_name + ': '
def validate(self):
def validate(self, with_value=True):
for (key, prop) in self.props.items():
try:
self[key]
except ValueError as e:
msg = "Property error : %s" % str(e)
raise exception.StackValidationFailed(message=msg)
if with_value:
try:
self[key]
except ValueError as e:
msg = "Property error : %s" % str(e)
raise exception.StackValidationFailed(message=msg)
# are there unimplemented Properties
if not prop.implemented() and key in self.data:

View File

@ -28,6 +28,7 @@ from heat.common import exception
from heat.common import identifier
from heat.engine import parameters
from heat.engine import parser
from heat.engine import properties
from heat.engine import resource
from heat.engine import resources # pyflakes_bypass review 23102
from heat.engine import watchrule
@ -286,6 +287,13 @@ class EngineService(service.Service):
if not res.get('Type'):
return {'Error':
'Every Resources object must contain a Type member.'}
ResourceClass = resource.get_class(res['Type'])
props = properties.Properties(ResourceClass.properties_schema,
res.get('Properties', {}))
try:
props.validate(with_value=False)
except Exception as ex:
return {'Error': str(ex)}
tmpl_params = parser.Parameters(None, tmpl)
format_validate_parameter = lambda p: dict(p.schema)

View File

@ -207,6 +207,64 @@ test_template_findinmap_invalid = '''
}
'''
test_template_invalid_property = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "test.",
"Parameters" : {
"KeyName" : {
''' + \
'"Description" : "Name of an existing EC2' + \
'KeyPair to enable SSH access to the instances",' + \
'''
"Type" : "String"
}
},
"Resources" : {
"WikiDatabase": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "image_name",
"InstanceType": "m1.large",
"KeyName": { "Ref" : "KeyName" },
"UnknownProperty": "unknown"
}
}
}
}
'''
test_template_unimplemented_property = '''
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "test.",
"Parameters" : {
"KeyName" : {
''' + \
'"Description" : "Name of an existing EC2' + \
'KeyPair to enable SSH access to the instances",' + \
'''
"Type" : "String"
}
},
"Resources" : {
"WikiDatabase": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "image_name",
"InstanceType": "m1.large",
"KeyName": { "Ref" : "KeyName" },
"SourceDestCheck": "false"
}
}
}
}
'''
@attr(tag=['unit', 'validate'])
@attr(speed='fast')
@ -302,3 +360,25 @@ class validateTest(unittest.TestCase):
'Type': 'String',
'Description': 'Name of an existing EC2KeyPair to enable SSH '
'access to the instances'}})
def test_validate_properties(self):
t = template_format.parse(test_template_invalid_property)
self.m.StubOutWithMock(instances.Instance, 'nova')
instances.Instance.nova().AndReturn(self.fc)
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
self.assertEqual(res, {'Error': 'Unknown Property UnknownProperty'})
def test_unimplemented_property(self):
t = template_format.parse(test_template_unimplemented_property)
self.m.StubOutWithMock(instances.Instance, 'nova')
instances.Instance.nova().AndReturn(self.fc)
self.m.ReplayAll()
engine = service.EngineService('a', 't')
res = dict(engine.validate_template(None, t))
self.assertEqual(
res,
{'Error': 'Property SourceDestCheck not implemented yet'})