Convergence: add support for the path_component
store the attr name and path so attributes don't get shadowed e.g. get_attr: [res1, attr_x, show] get_attr: [res1, attr_x, something] Change-Id: I724e91b32776aa5813d2b821c2062424e0635a69
This commit is contained in:
parent
bdfd84e19d
commit
dd0859a080
|
@ -125,6 +125,19 @@ class GetAttThenSelect(cfn_funcs.GetAtt):
|
||||||
path_components = function.resolve(self._path_components)
|
path_components = function.resolve(self._path_components)
|
||||||
return attributes.select_from_attribute(attribute, path_components)
|
return attributes.select_from_attribute(attribute, path_components)
|
||||||
|
|
||||||
|
def dep_attrs(self, resource_name):
|
||||||
|
if self._resource().name == resource_name:
|
||||||
|
path = function.resolve(self._path_components)
|
||||||
|
attr = [function.resolve(self._attribute)]
|
||||||
|
if path:
|
||||||
|
attrs = [tuple(attr + path)]
|
||||||
|
else:
|
||||||
|
attrs = attr
|
||||||
|
else:
|
||||||
|
attrs = []
|
||||||
|
return itertools.chain(function.dep_attrs(self.args, resource_name),
|
||||||
|
attrs)
|
||||||
|
|
||||||
|
|
||||||
class GetAtt(GetAttThenSelect):
|
class GetAtt(GetAttThenSelect):
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -1474,8 +1474,11 @@ class Resource(object):
|
||||||
'''
|
'''
|
||||||
if self.stack.has_cache_data(self.name):
|
if self.stack.has_cache_data(self.name):
|
||||||
# Load from cache for lightweight resources.
|
# Load from cache for lightweight resources.
|
||||||
|
complex_key = key
|
||||||
|
if path:
|
||||||
|
complex_key = tuple([key] + list(path))
|
||||||
attribute = self.stack.cache_data_resource_attribute(
|
attribute = self.stack.cache_data_resource_attribute(
|
||||||
self.name, key)
|
self.name, complex_key)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
attribute = self.attributes[key]
|
attribute = self.attributes[key]
|
||||||
|
|
|
@ -315,7 +315,10 @@ def construct_input_data(rsrc):
|
||||||
resolved_attributes = {}
|
resolved_attributes = {}
|
||||||
for attr in attributes:
|
for attr in attributes:
|
||||||
try:
|
try:
|
||||||
|
if isinstance(attr, six.string_types):
|
||||||
resolved_attributes[attr] = rsrc.FnGetAtt(attr)
|
resolved_attributes[attr] = rsrc.FnGetAtt(attr)
|
||||||
|
else:
|
||||||
|
resolved_attributes[attr] = rsrc.FnGetAtt(*attr)
|
||||||
except exception.InvalidTemplateAttribute as ita:
|
except exception.InvalidTemplateAttribute as ita:
|
||||||
LOG.info(six.text_type(ita))
|
LOG.info(six.text_type(ita))
|
||||||
|
|
||||||
|
|
|
@ -520,12 +520,15 @@ class MiscMethodsTest(common.HeatTestCase):
|
||||||
self.ctx = utils.dummy_context()
|
self.ctx = utils.dummy_context()
|
||||||
self.stack = tools.get_stack(
|
self.stack = tools.get_stack(
|
||||||
'check_workflow_create_stack', self.ctx,
|
'check_workflow_create_stack', self.ctx,
|
||||||
template=tools.string_template_five, convergence=True)
|
template=tools.attr_cache_template, convergence=True)
|
||||||
self.stack.converge_stack(self.stack.t)
|
self.stack.converge_stack(self.stack.t)
|
||||||
self.resource = self.stack['A']
|
self.resource = self.stack['A']
|
||||||
|
|
||||||
def test_construct_input_data_ok(self):
|
def test_construct_input_data_ok(self):
|
||||||
expected_input_data = {'attrs': {'value': None},
|
expected_input_data = {'attrs': {(u'flat_dict', u'key2'): 'val2',
|
||||||
|
(u'flat_dict', u'key3'): 'val3',
|
||||||
|
(u'nested_dict', u'dict', u'a'): 1,
|
||||||
|
(u'nested_dict', u'dict', u'b'): 2},
|
||||||
'id': mock.ANY,
|
'id': mock.ANY,
|
||||||
'reference_id': 'A',
|
'reference_id': 'A',
|
||||||
'name': 'A'}
|
'name': 'A'}
|
||||||
|
|
|
@ -123,6 +123,32 @@ resources:
|
||||||
salt: {get_param: salt}
|
salt: {get_param: salt}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
attr_cache_template = '''
|
||||||
|
heat_template_version: 2013-05-23
|
||||||
|
resources:
|
||||||
|
A:
|
||||||
|
type: ResourceWithComplexAttributesType
|
||||||
|
B:
|
||||||
|
type: OS::Heat::RandomString
|
||||||
|
properties:
|
||||||
|
salt: {get_attr: [A, flat_dict, key2]}
|
||||||
|
C:
|
||||||
|
type: OS::Heat::RandomString
|
||||||
|
depends_on: [A, B]
|
||||||
|
properties:
|
||||||
|
salt: {get_attr: [A, nested_dict, dict, a]}
|
||||||
|
D:
|
||||||
|
type: OS::Heat::RandomString
|
||||||
|
depends_on: C
|
||||||
|
properties:
|
||||||
|
salt: {get_attr: [A, nested_dict, dict, b]}
|
||||||
|
E:
|
||||||
|
type: OS::Heat::RandomString
|
||||||
|
depends_on: C
|
||||||
|
properties:
|
||||||
|
salt: {get_attr: [A, flat_dict, key3]}
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
def get_stack(stack_name, ctx, template=None, with_params=True,
|
def get_stack(stack_name, ctx, template=None, with_params=True,
|
||||||
convergence=False):
|
convergence=False):
|
||||||
|
|
|
@ -130,6 +130,23 @@ outputs:
|
||||||
{get_attr: [BResource, attr_B3]}]
|
{get_attr: [BResource, attr_B3]}]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
tmpl6 = """
|
||||||
|
heat_template_version: 2015-04-30
|
||||||
|
resources:
|
||||||
|
AResource:
|
||||||
|
type: ResourceWithComplexAttributesType
|
||||||
|
BResource:
|
||||||
|
type: ResourceWithPropsType
|
||||||
|
properties:
|
||||||
|
Foo: {get_attr: [AResource, list, 1]}
|
||||||
|
Doo: {get_attr: [AResource, nested_dict, dict, b]}
|
||||||
|
outputs:
|
||||||
|
out1:
|
||||||
|
value: [{get_attr: [AResource, flat_dict, key2]},
|
||||||
|
{get_attr: [AResource, nested_dict, string]},
|
||||||
|
{get_attr: [BResource, attr_B3]}]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class DepAttrsTest(common.HeatTestCase):
|
class DepAttrsTest(common.HeatTestCase):
|
||||||
|
|
||||||
|
@ -159,7 +176,14 @@ class DepAttrsTest(common.HeatTestCase):
|
||||||
'attr_A3', 'attr_A4'},
|
'attr_A3', 'attr_A4'},
|
||||||
'BResource': {'attr_B1', 'attr_B2', 'meta_B2',
|
'BResource': {'attr_B1', 'attr_B2', 'meta_B2',
|
||||||
'attr_B3'},
|
'attr_B3'},
|
||||||
'CResource': set()}))
|
'CResource': set()})),
|
||||||
|
('nested_attr',
|
||||||
|
dict(tmpl=tmpl6,
|
||||||
|
expected={'AResource': set([(u'flat_dict', u'key2'),
|
||||||
|
(u'list', 1),
|
||||||
|
(u'nested_dict', u'dict', u'b'),
|
||||||
|
(u'nested_dict', u'string')]),
|
||||||
|
'BResource': set(['attr_B3'])}))
|
||||||
]
|
]
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
Loading…
Reference in New Issue