From 40ea8371378b64dd042ee6e749718e940105ba2c Mon Sep 17 00:00:00 2001 From: Thomas Herve Date: Thu, 12 Jan 2017 19:20:35 +0100 Subject: [PATCH] Ignore dependency errors with conditions If a resource is conditionally defined, depending on it raises an error in the case it's not defined. This patch fixes that by checking if the resource is present in the template regardless of the conditions. Change-Id: Iefae1fcea720bee4ed69ad1a5fe403d52d54433c Closes-Bug: #1649900 (cherry picked from commit e1aeabaa032c607b07aa835526c06aad0d1e21c5) --- heat/engine/rsrc_defn.py | 9 +++++++-- heat/tests/test_hot.py | 19 +++++++++++++++++++ heat/tests/test_rsrc_defn.py | 15 +++++++++++++-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/heat/engine/rsrc_defn.py b/heat/engine/rsrc_defn.py index 4efff2fd1f..4cb5a82d88 100644 --- a/heat/engine/rsrc_defn.py +++ b/heat/engine/rsrc_defn.py @@ -208,6 +208,10 @@ class ResourceDefinitionCore(object): def get_resource(res_name): if res_name not in stack: + if res_name in stack.t.get(stack.t.RESOURCES): + # The resource is conditionally defined, allow dependencies + # on it + return raise exception.InvalidTemplateReference(resource=res_name, key=self.name) return stack[res_name] @@ -231,8 +235,9 @@ class ResourceDefinitionCore(object): ) return itertools.chain() - return itertools.chain((get_resource(dep) for dep in explicit_depends), - prop_deps, metadata_deps) + return itertools.chain( + filter(None, (get_resource(dep) for dep in explicit_depends)), + prop_deps, metadata_deps) def properties(self, schema, context=None): """Return a Properties object representing the resource properties. diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index 422cbcdc8a..30a9fc55ee 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -1665,6 +1665,25 @@ conditions: self.assertEqual(hot_tpl['resources'], empty.t['resources']) + def test_depends_condition(self): + hot_tpl = template_format.parse(''' + heat_template_version: 2016-10-14 + resources: + one: + type: OS::Heat::None + two: + type: OS::Heat::None + condition: False + three: + type: OS::Heat::None + depends_on: two + ''') + + tmpl = template.Template(hot_tpl) + stack = parser.Stack(utils.dummy_context(), 'test_stack', tmpl) + stack.validate() + self.assertEqual({'one', 'three'}, set(stack.resources)) + class HotStackTest(common.HeatTestCase): """Test stack function when stack was created from HOT template.""" diff --git a/heat/tests/test_rsrc_defn.py b/heat/tests/test_rsrc_defn.py index e5bb2b4ee1..ee995eac62 100644 --- a/heat/tests/test_rsrc_defn.py +++ b/heat/tests/test_rsrc_defn.py @@ -35,6 +35,16 @@ resources: type: OS::Heat::TestResource ''' +TEMPLATE_WITH_INVALID_EXPLICIT_DEPEND = ''' +heat_template_version: 2016-10-14 +resources: + test1: + type: OS::Heat::TestResource + test3: + type: OS::Heat::TestResource + depends_on: test2 +''' + class ResourceDefinitionTest(common.HeatTestCase): @@ -105,8 +115,9 @@ class ResourceDefinitionTest(common.HeatTestCase): self.assertEqual([], list(rsrc.t.dependencies(stack))) def test_dependencies_explicit_invalid(self): - rd = rsrc_defn.ResourceDefinition('rsrc', 'SomeType', depends=['baz']) - stack = {'foo': 'FOO', 'bar': 'BAR'} + t = template_format.parse(TEMPLATE_WITH_INVALID_EXPLICIT_DEPEND) + stack = utils.parse_stack(t) + rd = stack.t.resource_definitions(stack)['test3'] self.assertRaises(exception.InvalidTemplateReference, lambda: list(rd.dependencies(stack)))