From aabb3392b30e4905e8b780bec4c819ec6058b2b6 Mon Sep 17 00:00:00 2001 From: rabi Date: Thu, 18 Jan 2018 12:53:57 +0530 Subject: [PATCH] Fix nested template genearation when attribute path is not string When determining attributes to cache, we seem to be assuming the paths to be strings. If there are resource references in outputs it would be None during validation. As we've the same code snippet in all group resources ex. ResourceGroup, ResourceChain and heat AutoScalingGroup, this fixes it in all those places. Change-Id: I36d623b183d01632041113f7bff63bf255f5d53c Closes-Bug: #1719603 --- heat/engine/resources/openstack/heat/autoscaling_group.py | 2 +- heat/engine/resources/openstack/heat/resource_chain.py | 2 +- heat/engine/resources/openstack/heat/resource_group.py | 2 +- heat/tests/autoscaling/test_heat_scaling_group.py | 7 +++++++ heat/tests/openstack/heat/test_resource_chain.py | 6 ++++++ heat/tests/openstack/heat/test_resource_group.py | 8 ++++++++ 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/heat/engine/resources/openstack/heat/autoscaling_group.py b/heat/engine/resources/openstack/heat/autoscaling_group.py index 1eb4976305..5b31a240e9 100644 --- a/heat/engine/resources/openstack/heat/autoscaling_group.py +++ b/heat/engine/resources/openstack/heat/autoscaling_group.py @@ -226,7 +226,7 @@ class AutoScalingResourceGroup(aws_asg.AutoScalingGroup): output_name = attr else: key, path = attr[0], list(attr[1:]) - output_name = ', '.join(attr) + output_name = ', '.join(six.text_type(a) for a in attr) if key.startswith("resource."): keycomponents = key.split('.', 2) diff --git a/heat/engine/resources/openstack/heat/resource_chain.py b/heat/engine/resources/openstack/heat/resource_chain.py index 0d3973348c..42362584e3 100644 --- a/heat/engine/resources/openstack/heat/resource_chain.py +++ b/heat/engine/resources/openstack/heat/resource_chain.py @@ -166,7 +166,7 @@ class ResourceChain(stack_resource.StackResource): output_name = attr else: key, path = attr[0], list(attr[1:]) - output_name = ', '.join(attr) + output_name = ', '.join(six.text_type(a) for a in attr) if key.startswith("resource."): keycomponents = key.split('.', 2) diff --git a/heat/engine/resources/openstack/heat/resource_group.py b/heat/engine/resources/openstack/heat/resource_group.py index 5e81858cd8..c8fa82f1be 100644 --- a/heat/engine/resources/openstack/heat/resource_group.py +++ b/heat/engine/resources/openstack/heat/resource_group.py @@ -488,7 +488,7 @@ class ResourceGroup(stack_resource.StackResource): output_name = attr else: key, path = attr[0], list(attr[1:]) - output_name = ', '.join(attr) + output_name = ', '.join(six.text_type(a) for a in attr) if key.startswith("resource."): keycomponents = key.split('.', 2) diff --git a/heat/tests/autoscaling/test_heat_scaling_group.py b/heat/tests/autoscaling/test_heat_scaling_group.py index 50e7517b26..5c434ba5c6 100644 --- a/heat/tests/autoscaling/test_heat_scaling_group.py +++ b/heat/tests/autoscaling/test_heat_scaling_group.py @@ -42,6 +42,13 @@ class TestAutoScalingGroupValidation(common.HeatTestCase): self.assertRaises(exception.StackValidationFailed, stack['my-group'].validate) + def test_validate_reference_attr_with_none_ref(self): + stack = utils.parse_stack(self.parsed) + group = stack['my-group'] + self.patchobject(group, 'referenced_attrs', + return_value=set([('something', None)])) + self.assertIsNone(group.validate()) + class TestScalingGroupTags(common.HeatTestCase): def setUp(self): diff --git a/heat/tests/openstack/heat/test_resource_chain.py b/heat/tests/openstack/heat/test_resource_chain.py index f352ec5614..10ab7f0e6e 100644 --- a/heat/tests/openstack/heat/test_resource_chain.py +++ b/heat/tests/openstack/heat/test_resource_chain.py @@ -129,6 +129,12 @@ class ResourceChainTest(common.HeatTestCase): chain = self._create_chain(TEMPLATE) chain.validate_nested_stack() + def test_validate_reference_attr_with_none_ref(self): + chain = self._create_chain(TEMPLATE) + self.patchobject(chain, 'referenced_attrs', + return_value=set([('config', None)])) + self.assertIsNone(chain.validate()) + def test_validate_incompatible_properties(self): # Tests a resource in the chain that does not support the properties # specified to each resource. diff --git a/heat/tests/openstack/heat/test_resource_group.py b/heat/tests/openstack/heat/test_resource_group.py index 1ae264355d..b0dd63ca69 100644 --- a/heat/tests/openstack/heat/test_resource_group.py +++ b/heat/tests/openstack/heat/test_resource_group.py @@ -507,6 +507,14 @@ class ResourceGroupTest(common.HeatTestCase): resgrp = resource_group.ResourceGroup('test', snip, stack) self.assertIsNone(resgrp.validate()) + def test_validate_reference_attr_with_none_ref(self): + stack = utils.parse_stack(template_attr) + snip = stack.t.resource_definitions(stack)['group1'] + resgrp = resource_group.ResourceGroup('test', snip, stack) + self.patchobject(resgrp, 'referenced_attrs', + return_value=set([('nested_dict', None)])) + self.assertIsNone(resgrp.validate()) + def test_invalid_removal_policies_nolist(self): """Test that error raised for malformed removal_policies.""" tmp = copy.deepcopy(template)