From cd8ce16d4830782063692d897e57bd0af33ab5db Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Wed, 6 Nov 2019 15:25:43 +0100 Subject: [PATCH] template lookup: fix regression when templating hostvars (#64070) This fixes a regression that was caused by switching from copy() to deepcopy() when 'saving' variables before templating. Since HostVars did not implement the __deepcopy__() method, deepcopy returned incorrect results when host vars were present in the variables. Fixes #63940 --- .../63940-template-lookup-hostvars-regression.yml | 2 ++ lib/ansible/vars/hostvars.py | 6 ++++++ test/integration/targets/lookups/runme.sh | 2 ++ .../targets/lookups/template_deepcopy/hosts | 1 + .../targets/lookups/template_deepcopy/playbook.yml | 10 ++++++++++ .../targets/lookups/template_deepcopy/template.in | 1 + 6 files changed, 22 insertions(+) create mode 100644 changelogs/fragments/63940-template-lookup-hostvars-regression.yml create mode 100644 test/integration/targets/lookups/template_deepcopy/hosts create mode 100644 test/integration/targets/lookups/template_deepcopy/playbook.yml create mode 100644 test/integration/targets/lookups/template_deepcopy/template.in diff --git a/changelogs/fragments/63940-template-lookup-hostvars-regression.yml b/changelogs/fragments/63940-template-lookup-hostvars-regression.yml new file mode 100644 index 00000000000000..2eefdcf01e9d7f --- /dev/null +++ b/changelogs/fragments/63940-template-lookup-hostvars-regression.yml @@ -0,0 +1,2 @@ +bugfixes: + - template lookup - fix regression when templating hostvars (https://github.com/ansible/ansible/issues/63940) diff --git a/lib/ansible/vars/hostvars.py b/lib/ansible/vars/hostvars.py index db0e0591065b32..1d3c5ef94320cd 100644 --- a/lib/ansible/vars/hostvars.py +++ b/lib/ansible/vars/hostvars.py @@ -111,6 +111,12 @@ def __repr__(self): out[host] = self.get(host) return repr(out) + def __deepcopy__(self, memo): + # We do not need to deepcopy because HostVars is immutable, + # however we have to implement the method so we can deepcopy + # variables' dicts that contain HostVars. + return self + class HostVarsVars(Mapping): diff --git a/test/integration/targets/lookups/runme.sh b/test/integration/targets/lookups/runme.sh index e92afab462d7d5..698ff190456663 100755 --- a/test/integration/targets/lookups/runme.sh +++ b/test/integration/targets/lookups/runme.sh @@ -11,3 +11,5 @@ pip install passlib ANSIBLE_ROLES_PATH=../ ansible-playbook lookups.yml "$@" ansible-playbook template_lookup_vaulted.yml --vault-password-file test_vault_pass "$@" + +ansible-playbook -i template_deepcopy/hosts template_deepcopy/playbook.yml "$@" diff --git a/test/integration/targets/lookups/template_deepcopy/hosts b/test/integration/targets/lookups/template_deepcopy/hosts new file mode 100644 index 00000000000000..ecd3b9665b3284 --- /dev/null +++ b/test/integration/targets/lookups/template_deepcopy/hosts @@ -0,0 +1 @@ +h1 ansible_connection=local host_var=foo diff --git a/test/integration/targets/lookups/template_deepcopy/playbook.yml b/test/integration/targets/lookups/template_deepcopy/playbook.yml new file mode 100644 index 00000000000000..da55c16752bdc3 --- /dev/null +++ b/test/integration/targets/lookups/template_deepcopy/playbook.yml @@ -0,0 +1,10 @@ +- hosts: h1 + gather_facts: no + tasks: + - set_fact: + templated_foo: "{{ lookup('template', 'template.in') }}" + + - name: Test that the hostvar was templated correctly + assert: + that: + - templated_foo == "foo\n" diff --git a/test/integration/targets/lookups/template_deepcopy/template.in b/test/integration/targets/lookups/template_deepcopy/template.in new file mode 100644 index 00000000000000..77de0adf82736c --- /dev/null +++ b/test/integration/targets/lookups/template_deepcopy/template.in @@ -0,0 +1 @@ +{{hostvars['h1'].host_var}}