From c19a3deb649b6e4c5ea933e7c0ad157f4049d185 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Tue, 4 Jun 2013 16:40:12 +1200 Subject: [PATCH] Only call FnGetAtt if resource is in acceptable state. This will give resource type authors some certainty on what error checking their FnGetAtt methods will require. Fixes bug: #1184794 Change-Id: Iec456075c14cd609cf9607f07bce23e4c6b33c0c --- heat/engine/template.py | 8 +++++- heat/tests/test_metadata_refresh.py | 3 ++- heat/tests/test_parser.py | 38 +++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/heat/engine/template.py b/heat/engine/template.py index 7c411126..070ded30 100644 --- a/heat/engine/template.py +++ b/heat/engine/template.py @@ -155,7 +155,13 @@ class Template(collections.Mapping): def handle_getatt(args): resource, att = args try: - return resources[resource].FnGetAtt(att) + r = resources[resource] + if r.state in ( + r.CREATE_IN_PROGRESS, + r.CREATE_COMPLETE, + r.UPDATE_IN_PROGRESS, + r.UPDATE_COMPLETE): + return r.FnGetAtt(att) except KeyError: raise exception.InvalidTemplateAttribute(resource=resource, key=att) diff --git a/heat/tests/test_metadata_refresh.py b/heat/tests/test_metadata_refresh.py index 26c11015..17811032 100644 --- a/heat/tests/test_metadata_refresh.py +++ b/heat/tests/test_metadata_refresh.py @@ -179,6 +179,7 @@ class MetadataRefreshTest(HeatTestCase): s2 = self.stack.resources['S2'] files = s1.metadata['AWS::CloudFormation::Init']['config']['files'] cont = files['/tmp/random_file']['content'] + self.assertEqual(s2.CREATE_COMPLETE, s2.state) self.assertEqual(cont, 's2-ip=1.2.3.5') s1.metadata_update() @@ -247,7 +248,7 @@ class WaitCondMetadataUpdateTest(HeatTestCase): def check_empty(sleep_time): self.assertEqual(watch.FnGetAtt('Data'), '{}') - self.assertEqual(inst.metadata['test'], '{}') + self.assertEqual(inst.metadata['test'], None) def update_metadata(id, data, reason): self.man.metadata_update(self.ctx, diff --git a/heat/tests/test_parser.py b/heat/tests/test_parser.py index adad9e6b..dcdff309 100644 --- a/heat/tests/test_parser.py +++ b/heat/tests/test_parser.py @@ -1203,3 +1203,41 @@ class StackTest(HeatTestCase): parser.Template({})) self.assertRaises(ValueError, parser.Stack, None, '#test', parser.Template({})) + + @stack_delete_after + def test_resource_state_get_att(self): + tmpl = { + 'Resources': {'AResource': {'Type': 'GenericResourceType'}}, + 'Outputs': {'TestOutput': {'Value': { + 'Fn::GetAtt': ['AResource', 'Foo']}} + } + } + + self.stack = parser.Stack(self.ctx, 'resource_state_get_att', + template.Template(tmpl)) + self.stack.store() + self.stack.create() + self.assertEqual(self.stack.state, parser.Stack.CREATE_COMPLETE) + self.assertTrue('AResource' in self.stack) + rsrc = self.stack['AResource'] + rsrc.resource_id_set('aaaa') + self.assertEqual('AResource', rsrc.FnGetAtt('foo')) + + for state in ( + rsrc.CREATE_IN_PROGRESS, + rsrc.CREATE_COMPLETE, + rsrc.UPDATE_IN_PROGRESS, + rsrc.UPDATE_COMPLETE): + rsrc.state = state + self.assertEqual('AResource', self.stack.output('TestOutput')) + for state in ( + rsrc.CREATE_FAILED, + rsrc.DELETE_IN_PROGRESS, + rsrc.DELETE_FAILED, + rsrc.DELETE_COMPLETE, + rsrc.UPDATE_FAILED, + None): + rsrc.state = state + self.assertEqual(None, self.stack.output('TestOutput')) + + rsrc.state = rsrc.CREATE_COMPLETE -- 2.45.2