diff options
author | Angus Salkeld <asalkeld@redhat.com> | 2013-10-09 17:12:45 +1100 |
---|---|---|
committer | Steven Hardy <shardy@redhat.com> | 2013-10-10 17:24:44 +0100 |
commit | f5b1d2ff20a194e64ea55afc5a2faeea0f1b62d0 (patch) | |
tree | 053d5efd7326529178c60e17d6882f23bf4313b8 | |
parent | 243b872d2c935c6fb7fbb22fb4951f36de8bab6d (diff) | |
download | heat-f5b1d2ff20a194e64ea55afc5a2faeea0f1b62d0.tar.gz |
Make templateResource not replace on update
Updating a template resource is never destructive
as it defers to the nested stack to determine if any
sub-resources needs to be replaced.
Closes-bug: #1236676
Change-Id: Iae7e6b7e2f41d2f5bd9e75256be7533c15762d9f
-rw-r--r-- | heat/engine/resources/template_resource.py | 17 | ||||
-rw-r--r-- | heat/tests/test_provider_template.py | 71 |
2 files changed, 88 insertions, 0 deletions
diff --git a/heat/engine/resources/template_resource.py b/heat/engine/resources/template_resource.py index 0c1f26c75..a1fa1cad6 100644 --- a/heat/engine/resources/template_resource.py +++ b/heat/engine/resources/template_resource.py @@ -63,6 +63,12 @@ class TemplateResource(stack_resource.StackResource): self.attributes_schema = (attributes.Attributes .schema_from_outputs(tmpl[template.OUTPUTS])) + self.update_allowed_keys = ('Properties',) + # assume all properties are updatable, as they just get passed to + # the nested stack and that handles the updating/replacing. + self.update_allowed_properties = [pname + for pname in self.properties_schema] + super(TemplateResource, self).__init__(name, json_snippet, stack) def _to_parameters(self): @@ -174,6 +180,17 @@ class TemplateResource(stack_resource.StackResource): return self.create_with_template(self.parsed_nested, self._to_parameters()) + def handle_update(self, json_snippet, tmpl_diff, prop_diff): + # The stack template may be changed even if the prop_diff is empty. + self.properties = properties.Properties( + self.properties_schema, + json_snippet.get('Properties', {}), + self.stack.resolve_runtime_data, + self.name) + + return self.update_with_template(self.parsed_nested, + self._to_parameters()) + def handle_delete(self): return self.delete_nested() diff --git a/heat/tests/test_provider_template.py b/heat/tests/test_provider_template.py index 08c96af79..500cc5979 100644 --- a/heat/tests/test_provider_template.py +++ b/heat/tests/test_provider_template.py @@ -24,6 +24,7 @@ from heat.engine import parser from heat.engine import properties from heat.engine import resource from heat.engine import resources +from heat.engine import scheduler from heat.engine.resources import template_resource from heat.openstack.common import uuidutils @@ -495,3 +496,73 @@ class ProviderTemplateTest(HeatTestCase): stack) self.assertRaises(exception.StackValidationFailed, temp_res.validate) self.m.VerifyAll() + + def create_stack(self, template): + t = template_format.parse(template) + stack = self.parse_stack(t) + stack.create() + self.assertEqual(stack.state, (stack.CREATE, stack.COMPLETE)) + return stack + + def parse_stack(self, t): + ctx = utils.dummy_context('test_username', 'aaaa', 'password') + stack_name = 'test_stack' + tmpl = parser.Template(t) + stack = parser.Stack(ctx, stack_name, tmpl) + stack.store() + return stack + + def test_template_resource_update(self): + # assertion: updating a template resource is never destructive + # as it defers to the nested stack to determine if anything + # needs to be replaced. + + utils.setup_dummy_db() + resource._register_class('GenericResource', + generic_rsrc.GenericResource) + + templ_resource_name = 'http://server.test/the.yaml' + test_template = ''' +HeatTemplateFormatVersion: '2012-12-12' +Resources: + the_nested: + Type: %s + Properties: + one: myname +''' % templ_resource_name + + self.m.StubOutWithMock(urlfetch, "get") + urlfetch.get(templ_resource_name, + allowed_schemes=('http', + 'https')).MultipleTimes().\ + AndReturn(''' +HeatTemplateFormatVersion: '2012-12-12' +Parameters: + one: + Type: String +Resources: + NestedResource: + Type: GenericResource +Outputs: + Foo: + Value: {Ref: one} +''') + + self.m.ReplayAll() + + stack = self.create_stack(test_template) + templ_resource = stack['the_nested'] + self.assertEqual('myname', templ_resource.FnGetAtt('Foo')) + + update_snippet = { + "Type": templ_resource_name, + "Properties": { + "one": "yourname" + } + } + # test that update() does NOT raise UpdateReplace. + updater = scheduler.TaskRunner(templ_resource.update, update_snippet) + self.assertEqual(None, updater()) + self.assertEqual('yourname', templ_resource.FnGetAtt('Foo')) + + self.m.VerifyAll() |