Resolve variable references inside variables

Fixes the case where variable x is '$y' and y is a dict(foo='bar') and
an attempt to access ${x.foo} is made.
parent 073fb21b
...@@ -64,6 +64,10 @@ def _varFindLimitSpace(basedir, vars, space, part, lookup_fatal, depth): ...@@ -64,6 +64,10 @@ def _varFindLimitSpace(basedir, vars, space, part, lookup_fatal, depth):
else: else:
return None return None
# if space is a string, check if it's a reference to another variable
if isinstance(space, basestring):
space = template_ds(basedir, space, vars, lookup_fatal, depth)
return space return space
def _varFind(basedir, text, vars, lookup_fatal, depth=0): def _varFind(basedir, text, vars, lookup_fatal, depth=0):
...@@ -210,26 +214,26 @@ def varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lists=Fals ...@@ -210,26 +214,26 @@ def varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lists=Fals
return ''.join(done) return ''.join(done)
def template_ds(basedir, varname, vars, lookup_fatal=True): def template_ds(basedir, varname, vars, lookup_fatal=True, depth=0):
''' templates a data structure by traversing it and substituting for other data structures ''' ''' templates a data structure by traversing it and substituting for other data structures '''
if isinstance(varname, basestring): if isinstance(varname, basestring):
m = _varFind(basedir, varname, vars, lookup_fatal) m = _varFind(basedir, varname, vars, lookup_fatal, depth)
if not m: if not m:
return varname return varname
if m['start'] == 0 and m['end'] == len(varname): if m['start'] == 0 and m['end'] == len(varname):
if m['replacement'] is not None: if m['replacement'] is not None:
return template_ds(basedir, m['replacement'], vars, lookup_fatal) return template_ds(basedir, m['replacement'], vars, lookup_fatal, depth)
else: else:
return varname return varname
else: else:
return template(basedir, varname, vars, lookup_fatal) return template(basedir, varname, vars, lookup_fatal)
elif isinstance(varname, (list, tuple)): elif isinstance(varname, (list, tuple)):
return [template_ds(basedir, v, vars, lookup_fatal) for v in varname] return [template_ds(basedir, v, vars, lookup_fatal, depth) for v in varname]
elif isinstance(varname, dict): elif isinstance(varname, dict):
d = {} d = {}
for (k, v) in varname.iteritems(): for (k, v) in varname.iteritems():
d[k] = template_ds(basedir, v, vars, lookup_fatal) d[k] = template_ds(basedir, v, vars, lookup_fatal, depth)
return d return d
else: else:
return varname return varname
......
...@@ -260,6 +260,17 @@ class TestUtils(unittest.TestCase): ...@@ -260,6 +260,17 @@ class TestUtils(unittest.TestCase):
res = ansible.utils.varReplace(None, template, vars) res = ansible.utils.varReplace(None, template, vars)
assert res == 'test result' assert res == 'test result'
def test_varReplace_var_complex_var(self):
vars = {
'x': '$y',
'y': {
'foo': 'result',
},
}
template = '${x.foo}'
res = ansible.utils.template(None, template, vars)
assert res == 'result'
def test_template_varReplace_iterated(self): def test_template_varReplace_iterated(self):
template = 'hello $who' template = 'hello $who'
vars = { vars = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment