diff --git a/lib/ansible/utils.py b/lib/ansible/utils.py index 92c7aea7c1..8385280407 100644 --- a/lib/ansible/utils.py +++ b/lib/ansible/utils.py @@ -198,7 +198,19 @@ def parse_json(data): return { "failed" : True, "parsed" : False, "msg" : data } return results -_KEYCRE = re.compile(r"\$(\w+)") +def varLookup(name, vars): + ''' find the contents of a possibly complex variable in vars. ''' + path = name.split('.') + space = vars + for part in path: + if part in space: + space = space[part] + else: + return + return space + +_KEYCRE = re.compile(r"\$(?P\{){0,1}((?(complex)[\w\.]+|\w+))(?(complex)\})") +# if { -> complex if complex, allow . and need trailing } def varReplace(raw, vars): '''Perform variable replacement of $vars @@ -220,8 +232,9 @@ def varReplace(raw, vars): # Determine replacement value (if unknown variable then preserve # original) - varname = m.group(1).lower() - replacement = str(vars.get(varname, m.group())) + varname = m.group(2).lower() + + replacement = str(varLookup(varname, vars) or m.group()) start, end = m.span() done.append(raw[:start]) # Keep stuff leading up to token diff --git a/test/TestUtils.py b/test/TestUtils.py new file mode 100644 index 0000000000..23459d84a2 --- /dev/null +++ b/test/TestUtils.py @@ -0,0 +1,155 @@ +import os +import unittest + +import ansible.utils + +class TestUtils(unittest.TestCase): + + ##################################### + ### varLookup function tests + + def test_varLookup_list(self): + vars = { + 'data': { + 'who': ['joe', 'jack', 'jeff'] + } + } + + res = ansible.utils.varLookup('data.who', vars) + + assert sorted(res) == sorted(vars['data']['who']) + + ##################################### + ### varReplace function tests + + def test_varReplace_simple(self): + template = 'hello $who' + vars = { + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world' + + def test_varReplace_multiple(self): + template = '$what $who' + vars = { + 'what': 'hello', + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world' + + def test_varReplace_middle(self): + template = 'hello $who!' + vars = { + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world!' + + def test_varReplace_alternative(self): + template = 'hello ${who}' + vars = { + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world' + + def test_varReplace_almost_alternative(self): + template = 'hello $who}' + vars = { + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world}' + + def test_varReplace_almost_alternative2(self): + template = 'hello ${who' + vars = { + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == template + + def test_varReplace_alternative_greed(self): + template = 'hello ${who} }' + vars = { + 'who': 'world', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world }' + + def test_varReplace_notcomplex(self): + template = 'hello $mydata.who' + vars = { + 'data': { + 'who': 'world', + }, + } + + res = ansible.utils.varReplace(template, vars) + + print res + assert res == template + + def test_varReplace_nested(self): + template = 'hello ${data.who}' + vars = { + 'data': { + 'who': 'world' + }, + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello world' + + def test_varReplace_nested_int(self): + template = '$what ${data.who}' + vars = { + 'data': { + 'who': 2 + }, + 'what': 'hello', + } + + res = ansible.utils.varReplace(template, vars) + + assert res == 'hello 2' + + ##################################### + ### Template function tests + + def test_template_basic(self): + template = 'hello {{ who }}' + vars = { + 'who': 'world', + } + + res = ansible.utils.template(template, vars, {}) + + assert res == 'hello world' + + def test_template_whitespace(self): + template = 'hello {{ who }}\n' + vars = { + 'who': 'world', + } + + res = ansible.utils.template(template, vars, {}) + + assert res == 'hello world\n'