My development team has used “complex variables” (i.e., references to specific dictionary fields) in loops over the debug task for a long time. Example:
- debug:
var: "{{ item }}"
with_items:
- result.rc
- result.stdout
- result.stderr
We have done this in order to avoid dumping the whole dictionary, which can be much longer. Recently, we were unexpectedly upgraded from Ansible 2.14.2 to Ansible 2.16. We find that this behavior no longer works. Instead of printing the values for each field in the list, it now prints something that looks like a recursive reference error (i.e., “dict.field” is displayed as “{{ dict.field }}”).
A simple playbook (shown below, with output from both versions) demonstrates the change in behavior. (While trying to find a workaround, we have found that replacing “with_items” with “loop” gives us a workaround in both versions, but we’re not sure why.)
This happens even if we just put the dictionary variable as a single entry in the loop.
Is the use of a dictionary field (instead of just a plain, undecorated variable name) allowed in the debug task? Can loops be applied to the debug task? Is the change in behavior expected?
Thank you.
Playbook:
- hosts: installer
gather_facts: false
vars:
result:
rc: 0
stdout: 'TASK OUTPUT'
stderr: 'ERROR OUTPUT'
tasks:
- debug:
var: "{{ item }}"
with_items:
- result.rc
- result.stdout
- result.stderr
- debug:
var: "{{ item }}"
loop:
- result.rc
- result.stdout
- result.stderr
Results on 2.14.2 (got what I expected)
PLAY [installer] ***************************************************************
TASK [debug] *******************************************************************
ok: [paas-installer] => (item=result.rc) => {
"ansible_loop_var": "item",
"item": "result.rc",
"result.rc": "0"
}
ok: [paas-installer] => (item=result.stdout) => {
"ansible_loop_var": "item",
"item": "result.stdout",
"result.stdout": "TASK OUTPUT"
}
ok: [paas-installer] => (item=result.stderr) => {
"ansible_loop_var": "item",
"item": "result.stderr",
"result.stderr": "ERROR OUTPUT"
}
TASK [debug] *******************************************************************
ok: [paas-installer] => (item=result.rc) => {
"ansible_loop_var": "item",
"item": "result.rc",
"result.rc": "0"
}
ok: [paas-installer] => (item=result.stdout) => {
"ansible_loop_var": "item",
"item": "result.stdout",
"result.stdout": "TASK OUTPUT"
}
ok: [paas-installer] => (item=result.stderr) => {
"ansible_loop_var": "item",
"item": "result.stderr",
"result.stderr": "ERROR OUTPUT"
}
PLAY RECAP *********************************************************************
paas-installer : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Results on 2.16 (first debug task has unexpected results):
PLAY [installer] ***************************************************************
TASK [debug] *******************************************************************
ok: [paas-installer] => (item=result.rc) => {
"ansible_loop_var": "item",
"item": "result.rc",
"result.rc": "{{result.rc}}"
}
ok: [paas-installer] => (item=result.stdout) => {
"ansible_loop_var": "item",
"item": "result.stdout",
"result.stdout": "{{result.stdout}}"
}
ok: [paas-installer] => (item=result.stderr) => {
"ansible_loop_var": "item",
"item": "result.stderr",
"result.stderr": "{{result.stderr}}"
}
TASK [debug] *******************************************************************
ok: [paas-installer] => (item=result.rc) => {
"ansible_loop_var": "item",
"item": "result.rc",
"result.rc": "0"
}
ok: [paas-installer] => (item=result.stdout) => {
"ansible_loop_var": "item",
"item": "result.stdout",
"result.stdout": "TASK OUTPUT"
}
ok: [paas-installer] => (item=result.stderr) => {
"ansible_loop_var": "item",
"item": "result.stderr",
"result.stderr": "ERROR OUTPUT"
}
PLAY RECAP *********************************************************************
paas-installer : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Version details:
2.14.2 installation
ansible [core 2.14.2]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/var/paas/tmp/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.11/site-packages/ansible
ansible collection location = /var/paas/tmp/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.11.5 (main, Sep 22 2023, 15:34:29) [GCC 8.5.0 20210514 (Red Hat 8.5.0-20)] (/usr/bin/python3.11)
jinja version = 3.1.2
libyaml = True
Upgraded 2.16 installation
ansible [core 2.16.3]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/var/paas/tmp/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.12/site-packages/ansible
ansible collection location = /var/paas/tmp/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.12.1 (main, Feb 21 2024, 10:25:11) [GCC 8.5.0 20210514 (Red Hat 8.5.0-21)] (/usr/bin/python3.12)
jinja version = 3.1.2
libyaml = True