Home > Mobile >  How to ignore errors inside a task and keep Ansible running
How to ignore errors inside a task and keep Ansible running

Time:11-15

I try to go through some interfaces and turn the promiscuous mode on if it's not already. However, on some nodes, the interfaces doesn't exist and that's fine, however if one interface is failing on the host, the whole tasks will fail for this specific one, and the other present interfaces will be ignored too.

Here is my playbook:

---
- hosts: all
  gather_facts: no
  tasks:
   - name: Check promisc mode on
     shell:
       "ip a | grep '{{ item.1.name }}'"
     register: promisc
     notify: check promiscuous
     with_subelements:
     - "{{ interface }}"
     - client
 handlers:
   - name: check promisc
     loop: "{{ promisc.results | rejectattr('stdout','contains','PROMISC') | map(attribute='item') | list }}"
     shell:
       "ip l set dev '{{ item.1.name }}' promisc on"

Output:

changed: [host1] => (item=[{}, {'name': 'eth0'}])
changed: [host2] => (item=[{}, {'name': 'eth0'}])
changed: [host1] => (item=[{}, {'name': 'eth1'}])
failed: [host2] (item=[{}, {'name': 'eth1'}]) => {"ansible_loop_var": "item", "changed": true, "cmd": "ip a | grep 'eth1'", "delta": "0:00:00.007615", "end": "2022-11-14 10:05:33.972555", "item": [{}, {"name": "eth1"}], "msg": "non-zero return code", "rc": 1, "start": "2022-11-14 10:05:33.964940", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
changed: [host1] => (item=[{}, {'name': 'eth2' }])
changed: [host2] => (item=[{}, {'name': 'eth2'}])

RUNNING HANDLER [check promiscuous] *********************************************************************************************************************************************

PLAY RECAP ******************************************************************************************************************************************************************
host1         : ok=1    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
host2         : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

It is ignoring the handlers for the other 2 "changed" on host2 because one has failed inside this task. It doesn't run the handler on host1 because all interfaces have the promiscuous mode on on every interfaces, but I know that on host2 none of them have the promiscuous mode on.

I have then try to get only the "rc" items that get an output of 0, by setting up a set_fact:

- set_fact:
    res: "{{ promiscuous.results | selectattr('rc','defined') | map(attribute='rc') | list }}"

Gives:

ok: [host1] => {
    "res": [
       0,
       0,
       0,
    ]
}

I have also tried to add "ignore_errors", but it gives me the same output as the host1 for host2, with obviously one difference (0, 1, 0).

I would like to loop through this result if there is no other way, but I am already using a "with_subelements" loop in my task, and another loop in my handler so I'm not sure how I could accomplish that...

I have already read about the "rescue" module within a block but I'm not sure I could use that, as I don't want to rollback any change.

CodePudding user response:

I think you're trying to configure promisc for every interface, with value on.

You can achieve it by so:

---
- hosts: all
  gather_facts: true
  become: true
  tasks:
    - name: enable promisc when it is off
      shell: "ip l set {{ item }} promisc on"
      when: not hostvars[inventory_hostname]['ansible_%s' | format(item)]['promisc']
      loop: "{{ ansible_interfaces | difference('lo') }}"

This task is idempotent, so you can run it every 5 min.

  • Related