diff --git a/lib/ansible/runner.py b/lib/ansible/runner.py index b66535933f..95b04cb1a4 100644 --- a/lib/ansible/runner.py +++ b/lib/ansible/runner.py @@ -545,7 +545,7 @@ class Runner(object): source_data = codecs.open(utils.path_dwim(self.basedir, source), encoding="utf8").read() resultant = '' try: - resultant = utils.template(source_data, inject, self.setup_cache) + resultant = utils.template(source_data, inject, self.setup_cache, no_engine=False) except Exception, e: return (host, False, dict(failed=True, msg=str(e)), '') xfered = self._transfer_str(conn, tmp, 'source', resultant) diff --git a/lib/ansible/utils.py b/lib/ansible/utils.py index 1c396f30c3..55b7a55f31 100644 --- a/lib/ansible/utils.py +++ b/lib/ansible/utils.py @@ -199,7 +199,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 @@ -221,8 +233,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 @@ -231,7 +244,7 @@ def varReplace(raw, vars): return ''.join(done) -def template(text, vars, setup_cache, no_engine=False): +def template(text, vars, setup_cache, no_engine=True): ''' run a text buffer through the templating engine ''' vars = vars.copy() text = varReplace(unicode(text), vars) diff --git a/test/TestUtils.py b/test/TestUtils.py new file mode 100644 index 0000000000..42953b854a --- /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, {}, no_engine=False) + + assert res == 'hello world' + + def test_template_whitespace(self): + template = 'hello {{ who }}\n' + vars = { + 'who': 'world', + } + + res = ansible.utils.template(template, vars, {}, no_engine=False) + + assert res == 'hello world\n'