Ansible any_errors_fatal does not work as expected. Need Fix

I’m on the latest version of ansible while the python version is 2.7.5

Hi,

Ansible any_errors_fatal module does not work as expected. Below is my ansible playbook which is expected to terminate execution as soon as it encounters the first error.

more test.yml

---
- name: "Find the details here {{ Dest_IP }}"

  hosts: localhost
  tasks:
   - add_host: name={{ item }}
               groups=dest_nodes
     with_items: "{{ Dest_IP.split(',') }}"

- name: "Configure Destination nodes"
  hosts: dest_nodes
  any_errors_fatal: True
  tags: validate
  vars:
    ansible_ssh_private_key_file: /app/misc_automation/ssh_keys/axmw_id_rsa

  tasks:

   - command: "touch /app{{item}}"
     with_items:
       - "{{ Source_Filenames.split(',') }}"

I run the playbook using command:

ansible-playbook test.yml -e "Source_Filenames=/app/Jenkins/file1.mrt,/opt/work/file2.sql Dest_IP=10.9.9.83,10.9.9.85"

I wish to terminate the Playbook once the touch command fails/errors for the first file on the first host.

However, as you can see in the output the execution continues for all hosts and all files despiteany_errors_fatal set to ‘True’.

Output:

PLAY [Find the details here 10.9.9.83,10.9.9.85] *************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [localhost]

TASK [add_host] *********************************************************************************************************************************************
changed: [localhost] => (item=10.9.9.83)
changed: [localhost] => (item=10.9.9.85)

PLAY [Configure Destination nodes] **************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [10.9.9.85]
ok: [10.9.9.83]

TASK [command] **********************************************************************************************************************************************
 [WARNING]: Consider using the file module with state=touch rather than running 'touch'.  If you need to use command because file is insufficient you can
add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.

failed: [10.9.9.85] (item=/app/Jenkins/file1.mrt) => {"ansible_loop_var": "item", "changed": true, "cmd": ["touch", "/app/app/Jenkins/file1.mrt"], "delta": "0:00:00.102396", "end": "2019-08-02 17:02:34.917484", "item": "/app/Jenkins/file1.mrt", "msg": "non-zero return code", "rc": 1, "start": "2019-08-02 17:02:34.815088", "stderr": "touch: cannot touch â/app/app/Jenkins/file1.mrtâ: No such file or directory", "stderr_lines": ["touch: cannot touch â/app/app/Jenkins/file1.mrtâ: No such file or directory"], "stdout": "", "stdout_lines": []}
failed: [10.9.9.83] (item=/app/Jenkins/file1.mrt) => {"ansible_loop_var": "item", "changed": true, "cmd": ["touch", "/app/app/Jenkins/file1.mrt"], "delta": "0:00:00.123176", "end": "2019-08-02 17:03:15.911345", "item": "/app/Jenkins/file1.mrt", "msg": "non-zero return code", "rc": 1, "start": "2019-08-02 17:03:15.788169", "stderr": "touch: cannot touch â/app/app/Jenkins/file1.mrt: No such file or directory", "stderr_lines": ["touch: cannot touch â/app/app/Jenkins/file1.mrt: No such file or directory"], "stdout": "", "stdout_lines": []}
failed: [10.9.9.85] (item=/opt/work/file2.sql) => {"ansible_loop_var": "item", "changed": true, "cmd": ["touch", "/app/opt/work/file2.sql"], "delta": "0:00:00.106283", "end": "2019-08-02 17:02:35.580783", "item": "/opt/work/file2.sql", "msg": "non-zero return code", "rc": 1, "start": "2019-08-02 17:02:35.474500", "stderr": "touch: cannot touch â/app/opt/work/file2.sqlâ: No such file or directory", "stderr_lines": ["touch: cannot touch â/app/opt/work/file2.sqlâ: No such file or directory"], "stdout": "", "stdout_lines": []}
failed: [10.9.9.83] (item=/opt/work/file2.sql) => {"ansible_loop_var": "item", "changed": true, "cmd": ["touch", "/app/opt/work/file2.sql"], "delta": "0:00:00.097038", "end": "2019-08-02 17:03:16.663050", "item": "/opt/work/file2.sql", "msg": "non-zero return code", "rc": 1, "start": "2019-08-02 17:03:16.566012", "stderr": "touch: cannot touch â/app/opt/work/file2.sqlâ: No such file or directory", "stderr_lines": ["touch: cannot touch â/app/opt/work/file2.sqlâ: No such file or directory"], "stdout": "", "stdout_lines": []}

NO MORE HOSTS LEFT ******************************************************************************************************************************************

PLAY RECAP **************************************************************************************************************************************************
10.9.9.83                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
10.9.9.85                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Can you please suggest what the issue could be ? If this is a BUG please suggest any workarounds.

Regards;

Hi

So, if I understand you correctly there is no feature to abort the entire playbook run incase of a single error encountered?
The only solution that seems; is to have a when condition check on every tasks of a playbook.
The ansible documentation in this regards have been questioned in the past and seems confusing.

Documentation says: The any_errors_fatal play option will mark all hosts as failed if any fails, causing an immediate abort:

Now, if you look at my output any_errors_fatal does not mark all hosts as failed if the first one errors out; but checks explicitly for all hosts and all tasks. Sadly, There is no immediate abort contrary to the documentation!!

Hi,

So, if I understand you correctly there is no feature to abort the entire playbook run incase of a single error encountered?

There is afaik no feature immediatly aborting the current task for all
hosts, when an error is encountered on a single host. any_errors_fatal
will, as I said and the docs say, stop any further tasks from being
executed on any host.

The way Ansible works here, is for each task:

Send a python script and the data specified to the remote node and
execute it there. The data contains your full loop, it's not transferred
for each item of the loop.

That's done in parallel for X hosts. So Ansible has no reliable way to
stop a task that is already running.

As you can see from my example, in the first playbook, the second task
is not executed for any host, because host abc fails the first task.

If you want your loop to skip all remaining items on that task on that
host once an error has occured you can use my second example. If you add
any_errors_fatal all hosts won't execute any other tasks.

Sebastian