Ansible lookup filter works only if more than one item in hashmap

Viewed 589

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?

1 Answers

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:

  1. instruct lookup you want a list
msg: {{ lookup('dict', foo, wantlist=true) | map(attribute='key') | list }}
  1. use 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:

Related