heat engine : Ensure properties validation is caught

Rework usage of properties.validate() so that we always
catch the error and set the resource state to failed when
a properties validation error occurs

fixes bug 1146529

Change-Id: I4c5b24cc29a19a5170852aa7626031f9612b3272
This commit is contained in:
Steven Hardy 2013-03-05 15:16:59 +00:00
parent 269c397be2
commit c541b05f31
4 changed files with 18 additions and 16 deletions

View File

@ -16,6 +16,8 @@
import collections
import re
from heat.common import exception
SCHEMA_KEYS = (
REQUIRED, IMPLEMENTED, DEFAULT, TYPE, SCHEMA,
@ -175,17 +177,18 @@ class Properties(collections.Mapping):
try:
self[key]
except ValueError as e:
return str(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:
return (self.error_prefix +
'%s Property not implemented yet' % key)
msg = "Property %s not implemented yet" % key
raise exception.StackValidationFailed(message=msg)
for key in self.data:
if key not in self.props:
return (self.error_prefix +
'Unknown Property "%s"' % key)
msg = "Unknown Property %s" % key
raise exception.StackValidationFailed(message=msg)
def __getitem__(self, key):
if key not in self:

View File

@ -294,9 +294,7 @@ class Resource(object):
self.stack.resolve_runtime_data,
self.name)
try:
err = self.properties.validate()
if err:
return err
self.properties.validate()
self.state_set(self.CREATE_IN_PROGRESS)
if callable(getattr(self, 'handle_create', None)):
self.handle_create()
@ -344,9 +342,7 @@ class Resource(object):
json_snippet.get('Properties', {}),
self.stack.resolve_runtime_data,
self.name)
err = properties.validate()
if err:
raise ValueError(err)
properties.validate()
if callable(getattr(self, 'handle_update', None)):
result = self.handle_update(json_snippet)
except Exception as ex:

View File

@ -17,6 +17,7 @@ import unittest
from nose.plugins.attrib import attr
from heat.engine import properties
from heat.common import exception
@attr(tag=['unit', 'properties'])
@ -316,7 +317,7 @@ class PropertiesValidationTest(unittest.TestCase):
def test_missing_required(self):
schema = {'foo': {'Type': 'String', 'Required': True}}
props = properties.Properties(schema, {})
self.assertEqual(props.validate(), 'Property foo not assigned')
self.assertRaises(exception.StackValidationFailed, props.validate)
def test_missing_unimplemented(self):
schema = {'foo': {'Type': 'String', 'Implemented': False}}
@ -326,7 +327,7 @@ class PropertiesValidationTest(unittest.TestCase):
def test_present_unimplemented(self):
schema = {'foo': {'Type': 'String', 'Implemented': False}}
props = properties.Properties(schema, {'foo': 'bar'})
self.assertEqual(props.validate(), 'foo Property not implemented yet')
self.assertRaises(exception.StackValidationFailed, props.validate)
def test_missing(self):
schema = {'foo': {'Type': 'String'}}
@ -336,9 +337,9 @@ class PropertiesValidationTest(unittest.TestCase):
def test_bad_data(self):
schema = {'foo': {'Type': 'String'}}
props = properties.Properties(schema, {'foo': 42})
self.assertEqual(props.validate(), 'foo Value must be a string')
self.assertRaises(exception.StackValidationFailed, props.validate)
def test_unknown_typo(self):
schema = {'foo': {'Type': 'String'}}
props = properties.Properties(schema, {'food': 42})
self.assertNotEqual(props.validate(), None)
self.assertRaises(exception.StackValidationFailed, props.validate)

View File

@ -19,6 +19,7 @@ import mox
from nose.plugins.attrib import attr
from heat.tests.v1_1 import fakes
from heat.common import exception
from heat.common import template_format
from heat.engine.resources import instance as instances
from heat.engine import service
@ -240,7 +241,8 @@ class validateTest(unittest.TestCase):
self.m.ReplayAll()
volumeattach = stack.resources['MountPoint']
self.assertTrue(volumeattach.validate())
self.assertRaises(exception.StackValidationFailed,
volumeattach.validate)
def test_validate_ref_valid(self):
t = template_format.parse(test_template_ref % 'WikiDatabase')