Ansible "obj must be a list of dicts or a nested dict" error, conditional check does not work

Viewed 112

I have some host variables defined:

x_firewall_ports_v4:
  - port: '3306'
    rules:
      - ip: '1.2.3.4/32'
        proto: 'tcp'
        action: 'ACCEPT'
      - ip: '2.3.4.5/32'
        proto: 'tcp'
        action: 'ACCEPT'

and a playbook which now just write out the items:

- debug:
    msg: "IP: {{ item.1.ip }}"
  loop: "{{ x_firewall_ports_v4 | subelements('rules') }}"
  when: x_firewall_ports_v4 is defined

and this works fine. Because I don't want to setup firewall rules all of my servers, there is the conditional check at the end. But after I delete x_firewall_ports_v4 from my host definition, I get this runtime error:

TASK [firewall : debug] ********************************************************
fatal: [sql]: FAILED! => {"msg": "obj must be a list of dicts or a nested dict"}

I think the problem might be that x_firewall_ports_v4 has subelements also. But I'm right, how can I test for x_firewall_ports_v4 variable exists or not? Tried the conditional with quotes, double quotes but obviously it doesn't work.

1 Answers

The when: clause is evaluated on each iteration which implies that the loop: clause is evaluated before the condition. Hence your problem is not the condition but the loop expression which tries to create a subelement query on an undefined variable.

An easy fix is to give an empty list as default value to your var in the loop and ignore missing subelements so that it creates an empty list:

- debug:
    msg: "IP: {{ item.1.ip }}"
  loop: "{{ x_firewall_ports_v4 | d([]) | subelements('rules', skip_missing=true) }}"

Note that you don't even need the where clause since the empty list result will lead to no iteration at all.

Related