Ansible Task: with_dict statement got triggered, even if the when-clause should prevent this

292 Views Asked by At

I'am trying to automate the creation of the smart_[diskdevice] links to

/usr/share/munin/plugins/smart_

during the installation of the munin node via ansible.

The code here works partially, except there is no diskdevice to link on the target machine. Then I got a fatal failure with

{"msg": "with_dict expects a dict"}

I've review the ansible documentation and tried to search the problem in the web. For my understanding, the whole "file" directive should not be executed if the "when"-statement fails.

---
- name: Install Munin Node
  any_errors_fatal: true
  block:
...

# drives config
    - file:
        src: /usr/share/munin/plugins/smart_
        dest: /etc/munin/plugins/smart_{{ item.key }}
        state: link
      with_dict: "{{ ansible_devices }}"
      when: "item.value.host.startswith('SATA')"
      notify:
        - restart munin-node

On targets with a SATA-Drive, the code works. Drives like "sda" are found and the links are created. Loop- and other soft-Devices are ignored (as intended) Only on a Raspberry with no SATA-Drive at all i got the fatal failure.

1

There are 1 best solutions below

0
guzmonne On

You are using the with_dict option to set the loop. This sets the value of the item variable for each iteration as a dictionary with two keys:

  1. key: The name of the current key in the dict.
  2. value: The value of the existing key in the dict.

You are then running the when option that checks the item variable on each iteration. So check if that is the behavior you want.

Regarding your error, it is being thrown because for some reason, ansible_devices is not a dict as the error says. And Ansible checks for the validity of the with_dict type before resolving the when condition.

Check the following example:

---
- name: Diff test
  hosts: local
  connection: local
  gather_facts: no
  vars:
    dict:
      value: True
      name: "dict"
  tasks:
    - debug: var=item
      when: dict.value == False
      with_dict: '{{ dict }}'

    - debug: var=item
      when: dict.value == True
      with_dict: '{{ dict }}'

    - debug: var=item
      when: dict.value == False
      with_dict: "Not a dict"

The first two task will succeed because they have a valid dict on the with_dict option and a correct condition on the when option. The last one will fail because the with_dict value has the wrong type, even though the when condition resolves correctly and should guarantee to skip the task.

I hope it helps.