Improve behavior with error_on_undefined_vars enabled

Pass fail_on_undefined flag to recursive calls to `template` function,
so more undefined variables are detected.

Works only for Jinja style variables. Undefined legacy variables are
never detected.
This commit is contained in:
Petr Svoboda 2013-07-22 15:21:55 +02:00 committed by James Cammarata
parent 0747d41e76
commit fff4f1da33

View file

@ -325,11 +325,11 @@ def template(basedir, varname, vars, lookup_fatal=True, depth=0, expand_lists=Tr
return legacy_varReplace(basedir, varname, vars, lookup_fatal, depth, expand_lists) return legacy_varReplace(basedir, varname, vars, lookup_fatal, depth, expand_lists)
elif isinstance(varname, (list, tuple)): elif isinstance(varname, (list, tuple)):
return [template(basedir, v, vars, lookup_fatal, depth, expand_lists) for v in varname] return [template(basedir, v, vars, lookup_fatal, depth, expand_lists, fail_on_undefined=fail_on_undefined) 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(basedir, v, vars, lookup_fatal, depth, expand_lists) d[k] = template(basedir, v, vars, lookup_fatal, depth, expand_lists, fail_on_undefined=fail_on_undefined)
return d return d
else: else:
return varname return varname
@ -351,10 +351,11 @@ class _jinja2_vars(object):
extras is a list of locals to also search for variables. extras is a list of locals to also search for variables.
''' '''
def __init__(self, basedir, vars, globals, *extras): def __init__(self, basedir, vars, globals, fail_on_undefined, *extras):
self.basedir = basedir self.basedir = basedir
self.vars = vars self.vars = vars
self.globals = globals self.globals = globals
self.fail_on_undefined = fail_on_undefined
self.extras = extras self.extras = extras
def __contains__(self, k): def __contains__(self, k):
@ -381,7 +382,7 @@ class _jinja2_vars(object):
if isinstance(var, dict) and type(var) != dict: if isinstance(var, dict) and type(var) != dict:
return var return var
else: else:
return template(self.basedir, var, self.vars) return template(self.basedir, var, self.vars, fail_on_undefined=self.fail_on_undefined)
def add_locals(self, locals): def add_locals(self, locals):
''' '''
@ -390,7 +391,7 @@ class _jinja2_vars(object):
''' '''
if locals is None: if locals is None:
return self return self
return _jinja2_vars(self.basedir, self.vars, self.globals, locals, *self.extras) return _jinja2_vars(self.basedir, self.vars, self.globals, self.fail_on_undefined, locals, *self.extras)
class J2Template(jinja2.environment.Template): class J2Template(jinja2.environment.Template):
''' '''
@ -467,7 +468,7 @@ def template_from_file(basedir, path, vars):
# Ideally, this could use some API where setting shared=True and the object won't get # Ideally, this could use some API where setting shared=True and the object won't get
# passed through dict(o), but I have not found that yet. # passed through dict(o), but I have not found that yet.
try: try:
res = jinja2.utils.concat(t.root_render_func(t.new_context(_jinja2_vars(basedir, vars, t.globals), shared=True))) res = jinja2.utils.concat(t.root_render_func(t.new_context(_jinja2_vars(basedir, vars, t.globals, fail_on_undefined), shared=True)))
except jinja2.exceptions.UndefinedError, e: except jinja2.exceptions.UndefinedError, e:
raise errors.AnsibleUndefinedVariable("One or more undefined variables: %s" % str(e)) raise errors.AnsibleUndefinedVariable("One or more undefined variables: %s" % str(e))
@ -508,12 +509,11 @@ def template_from_string(basedir, data, vars, fail_on_undefined=False):
t.globals['lookup'] = my_lookup t.globals['lookup'] = my_lookup
res = jinja2.utils.concat(t.root_render_func(t.new_context(_jinja2_vars(basedir, vars, t.globals), shared=True))) res = jinja2.utils.concat(t.root_render_func(t.new_context(_jinja2_vars(basedir, vars, t.globals, fail_on_undefined), shared=True)))
return res return res
except jinja2.exceptions.UndefinedError: except jinja2.exceptions.UndefinedError:
if fail_on_undefined: if fail_on_undefined:
raise raise
else: else:
# this shouldn't happen due to undeclared check above
return data return data