From 20825d991e77c5aad6c596240143c48dd9e205c6 Mon Sep 17 00:00:00 2001 From: huangtianhua Date: Mon, 12 Oct 2015 11:47:57 +0800 Subject: [PATCH] Do not return None when get_attr if res is in SNAPSHOT/CHECK To get attribute instead of return None if resource is in SNAPSHOT or CHECK action. This patch allow to get_attr for hot template version '2013-05-23' also. Change-Id: I318f4c158ebe0a4afbb3f0bcbe9d856d90f0a4bb Closes-Bug: #1505054 --- heat/engine/cfn/functions.py | 2 +- heat/engine/hot/functions.py | 2 +- heat/tests/test_hot.py | 88 +++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/heat/engine/cfn/functions.py b/heat/engine/cfn/functions.py index 5302b0406..79bae591c 100644 --- a/heat/engine/cfn/functions.py +++ b/heat/engine/cfn/functions.py @@ -191,7 +191,7 @@ class GetAtt(function.Function): r = self._resource() if r.action in (r.CREATE, r.ADOPT, r.SUSPEND, r.RESUME, - r.UPDATE, r.ROLLBACK): + r.UPDATE, r.ROLLBACK, r.SNAPSHOT, r.CHECK): return r.FnGetAtt(attribute) # NOTE(sirushtim): Add r.INIT to states above once convergence # is the default. diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py index 76bf61ec8..9fc42d942 100644 --- a/heat/engine/hot/functions.py +++ b/heat/engine/hot/functions.py @@ -157,7 +157,7 @@ class GetAtt(GetAttThenSelect): r = self._resource() if (r.status in (r.IN_PROGRESS, r.COMPLETE) and r.action in (r.CREATE, r.ADOPT, r.SUSPEND, r.RESUME, - r.UPDATE)): + r.UPDATE, r.CHECK, r.SNAPSHOT)): return r.FnGetAtt(attribute, *path_components) else: return None diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index 4b4094709..d7c2de75e 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -66,6 +66,13 @@ resources: type: GenericResourceType ''') +hot_tpl_generic_resource_20141016 = template_format.parse(''' +heat_template_version: 2014-10-16 +resources: + resource1: + type: GenericResourceType +''') + hot_tpl_generic_resource_all_attrs = template_format.parse(''' heat_template_version: 2015-10-15 resources: @@ -87,6 +94,13 @@ resources: type: ResourceWithComplexAttributesType ''') +hot_tpl_complex_attrs_20141016 = template_format.parse(''' +heat_template_version: 2014-10-16 +resources: + resource1: + type: ResourceWithComplexAttributesType +''') + hot_tpl_mapped_props = template_format.parse(''' heat_template_version: 2013-05-23 resources: @@ -1294,6 +1308,7 @@ class StackAttributesTest(common.HeatTestCase): self.m.ReplayAll() scenarios = [ + # for hot template 2013-05-23, get_attr: hot_funcs.GetAttThenSelect ('get_flat_attr', dict(hot_tpl=hot_tpl_generic_resource, snippet={'Value': {'get_attr': ['resource1', 'foo']}}, @@ -1340,6 +1355,59 @@ class StackAttributesTest(common.HeatTestCase): nested_dict['dict']['a']})), ('get_attr_none', dict(hot_tpl=hot_tpl_complex_attrs, + snippet={'Value': {'get_attr': ['resource1', + 'none', + 'who_cares']}}, + resource_name='resource1', + expected={'Value': None})), + # for hot template version 2014-10-16 and 2015-04-30, + # get_attr: hot_funcs.GetAtt + ('get_flat_attr', + dict(hot_tpl=hot_tpl_generic_resource_20141016, + snippet={'Value': {'get_attr': ['resource1', 'foo']}}, + resource_name='resource1', + expected={'Value': 'resource1'})), + ('get_list_attr', + dict(hot_tpl=hot_tpl_complex_attrs_20141016, + snippet={'Value': {'get_attr': ['resource1', 'list', 0]}}, + resource_name='resource1', + expected={ + 'Value': + generic_rsrc.ResourceWithComplexAttributes.list[0]})), + ('get_flat_dict_attr', + dict(hot_tpl=hot_tpl_complex_attrs_20141016, + snippet={'Value': {'get_attr': ['resource1', + 'flat_dict', + 'key2']}}, + resource_name='resource1', + expected={ + 'Value': + generic_rsrc.ResourceWithComplexAttributes. + flat_dict['key2']})), + ('get_nested_attr_list', + dict(hot_tpl=hot_tpl_complex_attrs_20141016, + snippet={'Value': {'get_attr': ['resource1', + 'nested_dict', + 'list', + 0]}}, + resource_name='resource1', + expected={ + 'Value': + generic_rsrc.ResourceWithComplexAttributes. + nested_dict['list'][0]})), + ('get_nested_attr_dict', + dict(hot_tpl=hot_tpl_complex_attrs_20141016, + snippet={'Value': {'get_attr': ['resource1', + 'nested_dict', + 'dict', + 'a']}}, + resource_name='resource1', + expected={ + 'Value': + generic_rsrc.ResourceWithComplexAttributes. + nested_dict['dict']['a']})), + ('get_attr_none', + dict(hot_tpl=hot_tpl_complex_attrs_20141016, snippet={'Value': {'get_attr': ['resource1', 'none', 'who_cares']}}, @@ -1363,8 +1431,16 @@ class StackAttributesTest(common.HeatTestCase): (rsrc.CREATE, rsrc.COMPLETE), (rsrc.RESUME, rsrc.IN_PROGRESS), (rsrc.RESUME, rsrc.COMPLETE), + (rsrc.SUSPEND, rsrc.IN_PROGRESS), + (rsrc.SUSPEND, rsrc.COMPLETE), (rsrc.UPDATE, rsrc.IN_PROGRESS), - (rsrc.UPDATE, rsrc.COMPLETE)): + (rsrc.UPDATE, rsrc.COMPLETE), + (rsrc.SNAPSHOT, rsrc.IN_PROGRESS), + (rsrc.SNAPSHOT, rsrc.COMPLETE), + (rsrc.CHECK, rsrc.IN_PROGRESS), + (rsrc.CHECK, rsrc.COMPLETE), + (rsrc.ADOPT, rsrc.IN_PROGRESS), + (rsrc.ADOPT, rsrc.COMPLETE)): rsrc.state_set(action, status) resolved = function.resolve(self.stack.t.parse(self.stack, @@ -2006,8 +2082,16 @@ class TestGetAttAllAttributes(common.HeatTestCase): (rsrc.CREATE, rsrc.COMPLETE), (rsrc.RESUME, rsrc.IN_PROGRESS), (rsrc.RESUME, rsrc.COMPLETE), + (rsrc.SUSPEND, rsrc.IN_PROGRESS), + (rsrc.SUSPEND, rsrc.COMPLETE), (rsrc.UPDATE, rsrc.IN_PROGRESS), - (rsrc.UPDATE, rsrc.COMPLETE)): + (rsrc.UPDATE, rsrc.COMPLETE), + (rsrc.SNAPSHOT, rsrc.IN_PROGRESS), + (rsrc.SNAPSHOT, rsrc.COMPLETE), + (rsrc.CHECK, rsrc.IN_PROGRESS), + (rsrc.CHECK, rsrc.COMPLETE), + (rsrc.ADOPT, rsrc.IN_PROGRESS), + (rsrc.ADOPT, rsrc.COMPLETE)): rsrc.state_set(action, status) if self.raises is not None: