From f0179c0f0c4e07379532cce6cae7ee8614e4d601 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Mon, 8 Jul 2024 17:12:45 -0400 Subject: [PATCH] hostvars templating fix, override serialization (#83509) (#83516) fixes #82872 nicer implementation courtesy of nitzmahone (cherry picked from commit 6c0f4c8a2df78e0863723bffa06f6594b9bdd540) --- changelogs/fragments/hostvars_fix.yml | 2 ++ lib/ansible/vars/hostvars.py | 13 ++++++++++++- test/integration/targets/template/runme.sh | 2 ++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/hostvars_fix.yml 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 "$@"