From 546c45de0e0dc8afb19062adae008bf2969760f8 Mon Sep 17 00:00:00 2001 From: Steven Hardy Date: Thu, 23 Apr 2015 14:14:26 +1000 Subject: [PATCH] Fix ResourceGroup validate when there are removal_policies We can't call child_template() from a validate in ResourceGroup as it accesses nested(). So move the validation to validate_nested_stack() so we can control the test template used for validation. Unfortunately coverage for this got removed during recent test rework and it looks like the interface has got broken. Co-Authored-by: Angus Salkeld Change-Id: Ibea738a343847736b041cc49a2c486fa71e562d9 Closes-Bug: #1446861 --- .../openstack/heat/resource_group.py | 21 +++++++-- .../functional/test_resource_group.py | 45 ++++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/heat/engine/resources/openstack/heat/resource_group.py b/heat/engine/resources/openstack/heat/resource_group.py index a3a7f6a7b..adad46bd7 100644 --- a/heat/engine/resources/openstack/heat/resource_group.py +++ b/heat/engine/resources/openstack/heat/resource_group.py @@ -182,7 +182,13 @@ class ResourceGroup(stack_resource.StackResource): ), } - def validate(self): + def validate_nested_stack(self): + # Only validate the resource definition (which may be a + # nested template) if count is non-zero, to enable folks + # to disable features via a zero count if they wish + if not self.properties.get(self.COUNT): + return + test_tmpl = self._assemble_nested(["0"], include_all=True) val_templ = template.Template(test_tmpl) res_def = val_templ.resource_definitions(self.stack)["0"] @@ -193,8 +199,17 @@ class ResourceGroup(stack_resource.StackResource): # its a template resource pass - # validate the nested template definition - super(ResourceGroup, self).validate() + try: + name = "%s-%s" % (self.stack.name, self.name) + nested_stack = self._parse_nested_stack( + name, + test_tmpl, + self.child_params()) + nested_stack.strict_validate = False + nested_stack.validate() + except Exception as ex: + msg = _("Failed to validate: %s") % six.text_type(ex) + raise exception.StackValidationFailed(message=msg) def _name_blacklist(self): """Resolve the remove_policies to names for removal.""" diff --git a/heat_integrationtests/functional/test_resource_group.py b/heat_integrationtests/functional/test_resource_group.py index f6157fc33..a41f84106 100644 --- a/heat_integrationtests/functional/test_resource_group.py +++ b/heat_integrationtests/functional/test_resource_group.py @@ -109,9 +109,12 @@ resources: environment=env, files=files) self.assertIn(expected_err, six.text_type(ex)) - def _validate_resources(self, stack_identifier, expected_count): + def _list_group_resources(self, stack_identifier): nested_identifier = self._group_nested_identifier(stack_identifier) - resources = self.list_resources(nested_identifier) + return self.list_resources(nested_identifier) + + def _validate_resources(self, stack_identifier, expected_count): + resources = self._list_group_resources(stack_identifier) self.assertEqual(expected_count, len(resources)) expected_resources = dict( (str(idx), 'My::RandomString') @@ -168,6 +171,44 @@ resources: # verify that the resource group has 3 resources self._validate_resources(stack_identifier, 3) + def test_update_removal_policies(self): + rp_template = ''' +heat_template_version: 2014-10-16 +resources: + random_group: + type: OS::Heat::ResourceGroup + properties: + count: 5 + removal_policies: [] + resource_def: + type: OS::Heat::RandomString +''' + + # create stack with resource group, initial count 5 + stack_identifier = self.stack_create(template=rp_template) + self.assertEqual({u'random_group': u'OS::Heat::ResourceGroup'}, + self.list_resources(stack_identifier)) + group_resources = self._list_group_resources(stack_identifier) + expected_resources = {u'0': u'OS::Heat::RandomString', + u'1': u'OS::Heat::RandomString', + u'2': u'OS::Heat::RandomString', + u'3': u'OS::Heat::RandomString', + u'4': u'OS::Heat::RandomString'} + self.assertEqual(expected_resources, group_resources) + + # Remove three, specifying the middle resources to be removed + update_template = rp_template.replace( + 'removal_policies: []', + 'removal_policies: [{resource_list: [\'1\', \'2\', \'3\']}]') + self.update_stack(stack_identifier, update_template) + group_resources = self._list_group_resources(stack_identifier) + expected_resources = {u'0': u'OS::Heat::RandomString', + u'4': u'OS::Heat::RandomString', + u'5': u'OS::Heat::RandomString', + u'6': u'OS::Heat::RandomString', + u'7': u'OS::Heat::RandomString'} + self.assertEqual(expected_resources, group_resources) + def test_props_update(self): """Test update of resource_def properties behaves as expected."""