From fbe9ec58c7f48d2cef4a49ba96e84bce5933d654 Mon Sep 17 00:00:00 2001 From: Denis Dupeyron Date: Wed, 9 Aug 2017 12:01:31 -0500 Subject: [PATCH] template: fix KeyError: 'undefined variable: 0 Fixes: https://github.com/ansible/ansible/issues/20494 Based on a patch by Zac Medico at: https://github.com/zmedico/ansible/pull/1/commits/32e5613a95e525c3a25b8cd5aa1beaa75a4b0d5c --- lib/ansible/template/template.py | 10 ++++++++-- lib/ansible/template/vars.py | 14 +++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/ansible/template/template.py b/lib/ansible/template/template.py index 55936f4..fe11471 100644 --- a/lib/ansible/template/template.py +++ b/lib/ansible/template/template.py @@ -33,5 +33,11 @@ class AnsibleJ2Template(jinja2.environment.Template): ''' def new_context(self, vars=None, shared=False, locals=None): - return self.environment.context_class(self.environment, vars.add_locals(locals), self.name, self.blocks) - + if vars is not None: + if isinstance(vars, dict): + vars = vars.copy() + if locals is not None: + vars.update(locals) + else: + vars = vars.add_locals(locals) + return self.environment.context_class(self.environment, vars, self.name, self.blocks) diff --git a/lib/ansible/template/vars.py b/lib/ansible/template/vars.py index fc6140c..2bf95ac 100644 --- a/lib/ansible/template/vars.py +++ b/lib/ansible/template/vars.py @@ -19,6 +19,8 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +from collections import Mapping + from ansible.compat.six import iteritems from jinja2.utils import missing from ansible.module_utils._text import to_native @@ -27,7 +29,7 @@ from ansible.module_utils._text import to_native __all__ = ['AnsibleJ2Vars'] -class AnsibleJ2Vars: +class AnsibleJ2Vars(Mapping): ''' Helper class to template all variable content before jinja2 sees it. This is done by hijacking the variable storage that jinja2 uses, and overriding __contains__ @@ -68,6 +70,16 @@ class AnsibleJ2Vars: return True return False + def __iter__(self): + keys = set() + keys.update(self._templar._available_variables, self._locals, self._globals, *self._extras) + return iter(keys) + + def __len__(self): + keys = set() + keys.update(self._templar._available_variables, self._locals, self._globals, *self._extras) + return len(keys) + def __getitem__(self, varname): if varname not in self._templar._available_variables: if varname in self._locals: -- 2.13.3