Merge pull request #346 from jhoekx/improve-varreplace

Support nested variables in varReplace
This commit is contained in:
Michael DeHaan 2012-05-09 17:25:07 -07:00
commit cb6f0f4284
3 changed files with 173 additions and 5 deletions

View file

@ -545,7 +545,7 @@ class Runner(object):
source_data = codecs.open(utils.path_dwim(self.basedir, source), encoding="utf8").read() source_data = codecs.open(utils.path_dwim(self.basedir, source), encoding="utf8").read()
resultant = '' resultant = ''
try: 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: except Exception, e:
return (host, False, dict(failed=True, msg=str(e)), '') return (host, False, dict(failed=True, msg=str(e)), '')
xfered = self._transfer_str(conn, tmp, 'source', resultant) xfered = self._transfer_str(conn, tmp, 'source', resultant)

View file

@ -199,7 +199,19 @@ def parse_json(data):
return { "failed" : True, "parsed" : False, "msg" : data } return { "failed" : True, "parsed" : False, "msg" : data }
return results 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<complex>\{){0,1}((?(complex)[\w\.]+|\w+))(?(complex)\})")
# if { -> complex if complex, allow . and need trailing }
def varReplace(raw, vars): def varReplace(raw, vars):
'''Perform variable replacement of $vars '''Perform variable replacement of $vars
@ -221,8 +233,9 @@ def varReplace(raw, vars):
# Determine replacement value (if unknown variable then preserve # Determine replacement value (if unknown variable then preserve
# original) # original)
varname = m.group(1).lower() varname = m.group(2).lower()
replacement = str(vars.get(varname, m.group()))
replacement = str(varLookup(varname, vars) or m.group())
start, end = m.span() start, end = m.span()
done.append(raw[:start]) # Keep stuff leading up to token done.append(raw[:start]) # Keep stuff leading up to token
@ -231,7 +244,7 @@ def varReplace(raw, vars):
return ''.join(done) 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 ''' ''' run a text buffer through the templating engine '''
vars = vars.copy() vars = vars.copy()
text = varReplace(unicode(text), vars) text = varReplace(unicode(text), vars)

155
test/TestUtils.py Normal file
View file

@ -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'