Resolve arguments to 'repeat' function at runtime
This fixes a regression caused by a7c4b2332f
in evaluating the 'for_each' argument too early (at parse time - before the
result of runtime functions like get_attr are available), while preserving
the fix for bug 1466748 in allowing intrinsic functions to be used in the
argument.
Change-Id: If1e9c754ef372de2f7edd32a9a8247eb271c5871
Closes-Bug: #1553306
Related-Bug: #1466748
This commit is contained in:
parent
7d61fce04e
commit
bf60398c90
|
@ -530,7 +530,7 @@ class Repeat(function.Function):
|
|||
self.fn_name)
|
||||
|
||||
try:
|
||||
for_each = function.resolve(self.args['for_each'])
|
||||
for_each = self.args['for_each']
|
||||
template = self.args['template']
|
||||
except (KeyError, TypeError):
|
||||
example = ('''repeat:
|
||||
|
@ -540,13 +540,14 @@ class Repeat(function.Function):
|
|||
raise KeyError(_('"repeat" syntax should be %s') %
|
||||
example)
|
||||
|
||||
if not isinstance(for_each, collections.Mapping):
|
||||
raise TypeError(_('The "for_each" argument to "%s" must contain '
|
||||
'a map') % self.fn_name)
|
||||
for v in six.itervalues(for_each):
|
||||
if not isinstance(v, list):
|
||||
raise TypeError(_('The values of the "for_each" argument to '
|
||||
'"%s" must be lists') % self.fn_name)
|
||||
if not isinstance(for_each, function.Function):
|
||||
if not isinstance(for_each, collections.Mapping):
|
||||
raise TypeError(_('The "for_each" argument to "%s" must '
|
||||
'contain a map') % self.fn_name)
|
||||
for v in six.itervalues(for_each):
|
||||
if not isinstance(v, (list, function.Function)):
|
||||
raise TypeError(_('The values of the "for_each" argument '
|
||||
'to "%s" must be lists') % self.fn_name)
|
||||
|
||||
return for_each, template
|
||||
|
||||
|
@ -564,9 +565,15 @@ class Repeat(function.Function):
|
|||
for (k, v) in template.items())
|
||||
|
||||
def result(self):
|
||||
keys = list(six.iterkeys(self._for_each))
|
||||
lists = [self._for_each[key] for key in keys]
|
||||
for_each = function.resolve(self._for_each)
|
||||
keys = list(six.iterkeys(for_each))
|
||||
lists = [for_each[key] for key in keys]
|
||||
if not all(isinstance(l, list) for l in lists):
|
||||
raise TypeError(_('The values of the "for_each" argument to '
|
||||
'"%s" must be lists') % self.fn_name)
|
||||
|
||||
template = function.resolve(self._template)
|
||||
|
||||
return [self._do_replacement(keys, items, template)
|
||||
for items in itertools.product(*lists)]
|
||||
|
||||
|
|
|
@ -835,6 +835,16 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
|
||||
def test_repeat(self):
|
||||
"""Test repeat function."""
|
||||
snippet = {'repeat': {'template': 'this is %var%',
|
||||
'for_each': {'%var%': ['a', 'b', 'c']}}}
|
||||
snippet_resolved = ['this is a', 'this is b', 'this is c']
|
||||
|
||||
tmpl = template.Template(hot_kilo_tpl_empty)
|
||||
|
||||
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl))
|
||||
|
||||
def test_repeat_get_param(self):
|
||||
"""Test repeat function with get_param function as an argument."""
|
||||
hot_tpl = template_format.parse('''
|
||||
heat_template_version: 2015-04-30
|
||||
parameters:
|
||||
|
@ -1197,6 +1207,22 @@ class HotStackTest(common.HeatTestCase):
|
|||
def resolve(self, snippet):
|
||||
return function.resolve(self.stack.t.parse(self.stack, snippet))
|
||||
|
||||
def test_repeat_get_attr(self):
|
||||
"""Test repeat function with get_attr function as an argument."""
|
||||
tmpl = template.Template(hot_tpl_complex_attrs_all_attrs)
|
||||
self.stack = parser.Stack(self.ctx, 'test_repeat_get_attr', tmpl)
|
||||
|
||||
snippet = {'repeat': {'template': 'this is %var%',
|
||||
'for_each': {'%var%': {'get_attr': ['resource1', 'list']}}}}
|
||||
repeat = self.stack.t.parse(self.stack, snippet)
|
||||
|
||||
self.stack.store()
|
||||
self.stack.create()
|
||||
self.assertEqual((parser.Stack.CREATE, parser.Stack.COMPLETE),
|
||||
self.stack.state)
|
||||
self.assertEqual(['this is foo', 'this is bar'],
|
||||
function.resolve(repeat))
|
||||
|
||||
def test_get_attr_multiple_rsrc_status(self):
|
||||
"""Test resolution of get_attr occurrences in HOT template."""
|
||||
|
||||
|
|
Loading…
Reference in New Issue