From 2d88c70cd52a7bfa4bd268e7c3854b939a6d3235 Mon Sep 17 00:00:00 2001 From: Stoned Elipot Date: Sun, 7 Jul 2013 19:18:32 +0200 Subject: [PATCH] Introduce exception AnsibleFilterError and use it in Jinja filters. Ignore this exception when trying to find the name of a task for display (callback) purpose. --- lib/ansible/errors.py | 3 + lib/ansible/playbook/__init__.py | 2 +- lib/ansible/runner/filter_plugins/core.py | 2 +- lib/ansible/utils/template.py | 70 ++++++++++++----------- 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/lib/ansible/errors.py b/lib/ansible/errors.py index de0e6e38f3c..acbec4714f4 100644 --- a/lib/ansible/errors.py +++ b/lib/ansible/errors.py @@ -35,3 +35,6 @@ class AnsibleYAMLValidationFailed(AnsibleError): class AnsibleUndefinedVariable(AnsibleError): pass + +class AnsibleFilterError(AnsibleError): + pass diff --git a/lib/ansible/playbook/__init__.py b/lib/ansible/playbook/__init__.py index f554bd3e319..876074c4a87 100644 --- a/lib/ansible/playbook/__init__.py +++ b/lib/ansible/playbook/__init__.py @@ -326,7 +326,7 @@ class PlayBook(object): ansible.callbacks.set_task(self.callbacks, task) ansible.callbacks.set_task(self.runner_callbacks, task) - self.callbacks.on_task_start(template(play.basedir, task.name, task.module_vars, lookup_fatal=False), is_handler) + self.callbacks.on_task_start(template(play.basedir, task.name, task.module_vars, lookup_fatal=False, filter_fatal=False), is_handler) if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task: ansible.callbacks.set_task(self.callbacks, None) ansible.callbacks.set_task(self.runner_callbacks, None) diff --git a/lib/ansible/runner/filter_plugins/core.py b/lib/ansible/runner/filter_plugins/core.py index 107c5e1fcb5..01feb9f5109 100644 --- a/lib/ansible/runner/filter_plugins/core.py +++ b/lib/ansible/runner/filter_plugins/core.py @@ -33,7 +33,7 @@ def to_nice_json(*a, **kw): def failed(*a, **kw): item = a[0] if type(item) != dict: - raise errors.AnsibleError("|failed expects a dictionary") + raise errors.AnsibleFilterError("|failed expects a dictionary") rc = item.get('rc',0) failed = item.get('failed',False) if rc != 0 or failed: diff --git a/lib/ansible/utils/template.py b/lib/ansible/utils/template.py index 8adb4845959..f1f2bb9c8c3 100644 --- a/lib/ansible/utils/template.py +++ b/lib/ansible/utils/template.py @@ -295,42 +295,48 @@ def legacy_varReplace(basedir, raw, vars, lookup_fatal=True, depth=0, expand_lis # TODO: varname is misnamed here -def template(basedir, varname, vars, lookup_fatal=True, depth=0, expand_lists=True, convert_bare=False, fail_on_undefined=False): +def template(basedir, varname, vars, lookup_fatal=True, depth=0, expand_lists=True, convert_bare=False, fail_on_undefined=False, filter_fatal=True): ''' templates a data structure by traversing it and substituting for other data structures ''' - if convert_bare and isinstance(varname, basestring): - first_part = varname.split(".")[0].split("[")[0] - if first_part in vars and '{{' not in varname and '$' not in varname: - varname = "{{%s}}" % varname - - if isinstance(varname, basestring): - if '{{' in varname or '{%' in varname: - varname = template_from_string(basedir, varname, vars, fail_on_undefined) - if not '$' in varname: - return varname - - m = _legacy_varFind(basedir, varname, vars, lookup_fatal, depth, expand_lists) - if not m: - return varname - if m['start'] == 0 and m['end'] == len(varname): - if m['replacement'] is not None: - Flags.LEGACY_TEMPLATE_WARNING = True - return template(basedir, m['replacement'], vars, lookup_fatal, depth, expand_lists) - else: + try: + if convert_bare and isinstance(varname, basestring): + first_part = varname.split(".")[0].split("[")[0] + if first_part in vars and '{{' not in varname and '$' not in varname: + varname = "{{%s}}" % varname + + if isinstance(varname, basestring): + if '{{' in varname or '{%' in varname: + varname = template_from_string(basedir, varname, vars, fail_on_undefined) + if not '$' in varname: + return varname + + m = _legacy_varFind(basedir, varname, vars, lookup_fatal, depth, expand_lists) + if not m: return varname + if m['start'] == 0 and m['end'] == len(varname): + if m['replacement'] is not None: + Flags.LEGACY_TEMPLATE_WARNING = True + return template(basedir, m['replacement'], vars, lookup_fatal, depth, expand_lists) + else: + return varname + else: + Flags.LEGACY_TEMPLATE_WARNING = True + return legacy_varReplace(basedir, varname, vars, lookup_fatal, depth, expand_lists) + + elif isinstance(varname, (list, tuple)): + return [template(basedir, v, vars, lookup_fatal, depth, expand_lists) for v in varname] + elif isinstance(varname, dict): + d = {} + for (k, v) in varname.iteritems(): + d[k] = template(basedir, v, vars, lookup_fatal, depth, expand_lists) + return d else: - Flags.LEGACY_TEMPLATE_WARNING = True - return legacy_varReplace(basedir, varname, vars, lookup_fatal, depth, expand_lists) - - elif isinstance(varname, (list, tuple)): - return [template(basedir, v, vars, lookup_fatal, depth, expand_lists) for v in varname] - elif isinstance(varname, dict): - d = {} - for (k, v) in varname.iteritems(): - d[k] = template(basedir, v, vars, lookup_fatal, depth, expand_lists) - return d - else: - return varname + return varname + except errors.AnsibleFilterError: + if filter_fatal: + raise + else: + return varname class _jinja2_vars(object):