diff --git a/changelogs/fragments/hostvars_fix.yml b/changelogs/fragments/hostvars_fix.yml new file mode 100644 index 00000000000..b9b3c33f5f8 --- /dev/null +++ b/changelogs/fragments/hostvars_fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - templating hostvars under native jinja will not cause serialization errors anymore. diff --git a/lib/ansible/vars/hostvars.py b/lib/ansible/vars/hostvars.py index a76811b516a..0cd620334fe 100644 --- a/lib/ansible/vars/hostvars.py +++ b/lib/ansible/vars/hostvars.py @@ -20,6 +20,7 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type from collections.abc import Mapping +from functools import cached_property from ansible import constants as C from ansible.template import Templar, AnsibleUndefined @@ -117,9 +118,12 @@ class HostVarsVars(Mapping): def __init__(self, variables, loader): self._vars = variables self._loader = loader + + @cached_property + def _templar(self): # NOTE: this only has access to the host's own vars, # so templates that depend on vars in other scopes will not work. - self._templar = Templar(variables=self._vars, loader=self._loader) + return Templar(variables=self._vars, loader=self._loader) def __getitem__(self, var): return self._templar.template(self._vars[var], fail_on_undefined=False, static_vars=C.INTERNAL_STATIC_VARS) @@ -136,3 +140,10 @@ class HostVarsVars(Mapping): def __repr__(self): return repr(self._templar.template(self._vars, fail_on_undefined=False, static_vars=C.INTERNAL_STATIC_VARS)) + + def __getstate__(self): + ''' override serialization here to avoid + pickle issues with templar and Jinja native''' + state = self.__dict__.copy() + state.pop('_templar', None) + return state diff --git a/test/integration/targets/template/runme.sh b/test/integration/targets/template/runme.sh index e8141104bef..b37467a2719 100755 --- a/test/integration/targets/template/runme.sh +++ b/test/integration/targets/template/runme.sh @@ -55,3 +55,5 @@ do ANSIBLE_CONFIG="./${badcfg}.cfg" ansible-config dump --only-changed done +# ensure we picle hostvarscorrectly with native https://github.com/ansible/ansible/issues/83503 +ANSIBLE_JINJA2_NATIVE=1 ansible -m debug -a "msg={{ groups.all | map('extract', hostvars) }}" -i testhost, all -c local -v "$@"