I have this playbook:
- name: "This works"
hosts: localhost
tasks:
- debug:
msg: "{{ lookup('dict', foo) | map(attribute='key') | list}}"
vars:
foo:
bar:
type: v1
baz:
type: v2
- name: "This does not work"
hosts: localhost
tasks:
- debug:
msg: "{{ lookup('dict', foo) | map(attribute='key') | list}}"
vars:
foo:
bar:
type: v1
When running this, I get the following output:
PLAY [This works] *******************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"bar",
"baz"
]
}
PLAY [This does not work] ***********************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "[AnsibleUndefined, AnsibleUndefined]"
You see, it prints out bar
and baz
as list in the first example, but instead of a list containing just bar
in the second example, I get some AnsibleUndefined
output.
What do I have to change to make these filters also work with a single-item dict?
This is because lookup
does not always return a list. And in your second case, if you debug, you'll see it returns one single object which is not inside a list:
{
"key": "bar",
"value": {
"type": "v1"
}
}
2 solutions to get around the problem:
lookup
you want a listmsg: {{ lookup('dict', foo, wantlist=true) | map(attribute='key') | list }}
query
in place of lookup
which always returns a list and is better suited for this kind of processing (loops, mapping)msg: {{ query('dict', foo) | map(attribute='key') | list }}
Reference: