However… 
Even when I define a dummy backup dictionary in my test inventory, I still get an error on “dump hostvars to local file” task, because hostvars contains a bunch of unresolved variables in templates.
For example, we have a docker-swarm role, executed in an earlier play using import_role.
docker-swarm’s vars/main.yml is:
docker_package_version: 5:28.1.1-1
The role’s tasks/main.yml file includes vars at the very beginning:
- name: Include variables based on distribution
include_vars: "{{ item }}"
with_first_found:
- "{{ ansible_facts['distribution'] | lower }}-{{ ansible_facts['distribution_major_version'] }}.yml"
- "{{ ansible_facts['distribution'] | lower }}.yml"
Since I’m testing on Ubuntu 24.04, we have vars/ubuntu-24.yml:
docker_package_version_string: "{{ docker_package_version }}~ubuntu.24.04~noble"
The “dump to file” task errors out on Ansible 2.20:
TASK [elasticsearch : Dump dictionary as formatted YAML] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
[ERROR]: Task failed: Finalization of task args for 'ansible.builtin.copy' failed: Error while resolving value for 'content': 'docker_package_version' is undefined
Task failed.
Origin: <path>/roles/elasticsearch/tasks/main.yml:179:3
177
178
179 - name: Dump dictionary as formatted YAML
^ column 3
<<< caused by >>>
Finalization of task args for 'ansible.builtin.copy' failed.
Origin: <path>/roles/elasticsearch/tasks/main.yml:180:3
178
179 - name: Dump dictionary as formatted YAML
180 copy:
^ column 3
<<< caused by >>>
Error while resolving value for 'content'.
Origin: <path>/roles/elasticsearch/tasks/main.yml:181:14
179 - name: Dump dictionary as formatted YAML
180 copy:
181 content: "{{ groups['docker-swarm'] | map('extract', hostvars) | list | to_nice_yaml }}"
^ column 14
<<< caused by >>>
'docker_package_version' is undefined
Origin: <path>/roles/docker-swarm/vars/ubuntu-24.yml:4:32
2 ---
3
4 docker_package_version_string: "{{ docker_package_version }}~ubuntu.24.04~noble"
^ column 32
fatal: [host01.example.com -> localhost]: FAILED! => {"changed": false, "msg": "Task failed: Finalization of task args for 'ansible.builtin.copy' failed: Error while resolving value for 'content': 'docker_package_version' is undefined"}
fatal: [host02.example.com -> localhost]: FAILED! => {"changed": false, "msg": "Task failed: Finalization of task args for 'ansible.builtin.copy' failed: Error while resolving value for 'content': 'docker_package_version' is undefined"}
fatal: [host03.example.com -> localhost]: FAILED! => {"changed": false, "msg": "Task failed: Finalization of task args for 'ansible.builtin.copy' failed: Error while resolving value for 'content': 'docker_package_version' is undefined"}
On Ansible 2.18, I see this in the dump file:
docker_package_version_string: '{{ docker_package_version }}~ubuntu.24.04~noble'
The three relevant roles in our playbook are: gluster, docker-swarm and elasticsearch, executed in that order, each in a separate play.
The hostvars variable is first accessed in the gluster role, but there we extract individual variables, something like this:
gluster_nodes: "{{ ansible_play_batch | map('extract', hostvars, 'inventory_hostname_short') | list }}"
elasticsearch role is the only place where we access the entire hostvars variable in that loop:
loop: "{{ groups['docker-swarm'] | map('extract', hostvars) | list }}"
If I change that loop to extract the single variable we actually use in that task, the loop works fine.
I do hit another templating issue further down the elasticsearch role, need to investigate that one, too. I suspect it’s something similar.