From 82144fd543ee520535f197db4428dda8d7023d40 Mon Sep 17 00:00:00 2001 From: Jeroen Hoekx Date: Wed, 9 May 2012 16:05:06 +0200 Subject: [PATCH 1/2] Support nested variables in varReplace. --- lib/ansible/utils.py | 19 +++++- test/TestUtils.py | 155 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 test/TestUtils.py 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' From 2bbc05185e6e988594cc6dda7c006329406713d4 Mon Sep 17 00:00:00 2001 From: Jeroen Hoekx Date: Wed, 9 May 2012 16:13:20 +0200 Subject: [PATCH 2/2] Make no_engine the default templating action. --- lib/ansible/runner.py | 2 +- lib/ansible/utils.py | 2 +- test/TestUtils.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ansible/runner.py b/lib/ansible/runner.py index 135130c575..aef135b3c5 100644 --- a/lib/ansible/runner.py +++ b/lib/ansible/runner.py @@ -545,7 +545,7 @@ class Runner(object): source_data = file(utils.path_dwim(self.basedir, source)).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 8385280407..6fb4c78aa4 100644 --- a/lib/ansible/utils.py +++ b/lib/ansible/utils.py @@ -243,7 +243,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(str(text), vars) diff --git a/test/TestUtils.py b/test/TestUtils.py index 23459d84a2..42953b854a 100644 --- a/test/TestUtils.py +++ b/test/TestUtils.py @@ -140,7 +140,7 @@ class TestUtils(unittest.TestCase): 'who': 'world', } - res = ansible.utils.template(template, vars, {}) + res = ansible.utils.template(template, vars, {}, no_engine=False) assert res == 'hello world' @@ -150,6 +150,6 @@ class TestUtils(unittest.TestCase): 'who': 'world', } - res = ansible.utils.template(template, vars, {}) + res = ansible.utils.template(template, vars, {}, no_engine=False) assert res == 'hello world\n'