From 35853f5223bd91e76b2064bc47b04c0caccaed6b Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Fri, 2 Jan 2015 18:16:40 +0000 Subject: [PATCH] Add a strict_validate flag to Stacks Enables optionally disabling strict validation, which atm just disables the value part of properties validation. This is needed for a similar reason to bug #1347571, which conditionally disables value validation when inter-resource references cause a default pre-create value to be evaluated by a custom constraint (e.g the default resource name returned by get_resource until a resource is actually created). This flag enables a similar fix for StackResource, so we avoid strictly validating before create, otherwise the nested stack validation fails when the default resource name is passed in during validation, even though create-time validation would succeed. Change-Id: I80b5b8969007319e9a8fa1d104f4eb4fcbf7ebad Partial-Bug: #1407100 --- heat/engine/resource.py | 2 +- heat/engine/stack.py | 3 ++- heat/tests/test_resource.py | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 94c1d05b8..99e19e7b0 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -840,7 +840,7 @@ class Resource(object): function.validate(self.t) self.validate_deletion_policy(self.t.deletion_policy()) - return self.properties.validate() + return self.properties.validate(with_value=self.stack.strict_validate) @classmethod def validate_deletion_policy(cls, policy): diff --git a/heat/engine/stack.py b/heat/engine/stack.py index 9f3f203fa..6a076ea48 100644 --- a/heat/engine/stack.py +++ b/heat/engine/stack.py @@ -79,7 +79,7 @@ class Stack(collections.Mapping): created_time=None, updated_time=None, user_creds_id=None, tenant_id=None, use_stored_context=False, username=None, - nested_depth=0): + nested_depth=0, strict_validate=True): ''' Initialise from a context, name, Template object and (optionally) Environment object. The database ID may also be initialised, if the @@ -117,6 +117,7 @@ class Stack(collections.Mapping): self.updated_time = updated_time self.user_creds_id = user_creds_id self.nested_depth = nested_depth + self.strict_validate = strict_validate if use_stored_context: self.context = self.stored_context() diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index 3abf44e75..46ed0adb4 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -1407,6 +1407,29 @@ class ResourceDependenciesTest(common.HeatTestCase): stack.validate) self.assertIn('"baz" (in bar.Properties.Foo)', six.text_type(ex)) + def test_validate_value_fail(self): + tmpl = template.Template({ + 'heat_template_version': '2013-05-23', + 'resources': { + 'bar': { + 'type': 'ResourceWithPropsType', + 'properties': { + 'FooInt': 'notanint', + } + } + } + }) + stack = parser.Stack(utils.dummy_context(), 'test', tmpl) + ex = self.assertRaises(exception.StackValidationFailed, + stack.validate) + expected = "FooInt Value 'notanint' is not an integer" + self.assertIn(expected, six.text_type(ex)) + + # You can turn off value validation via strict_validate + stack_novalidate = parser.Stack(utils.dummy_context(), 'test', tmpl, + strict_validate=False) + self.assertIsNone(stack_novalidate.validate()) + def test_getatt(self): tmpl = template.Template({ 'HeatTemplateFormatVersion': '2012-12-12',