Reputation: 5489
I am learning Ansible. I have a playbook to clean up resources, and I want the playbook to ignore every error and keep going on till the end , and then fail at the end if there were errors.
I can ignore errors with
ignore_errors: yes
If it was one task, I could do something like ( from ansible error catching)
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
ignore_errors: True
- name: fail the play if the previous command did not succeed
fail: msg="the command failed"
when: "'FAILED' in command_result.stderr"
How do I fail at the end ? I have several tasks, what would my "When" condition be?
Upvotes: 83
Views: 288509
Reputation: 649
I would recommend using the "block", "rescue" and "always" functions. It´s like a try/catch/finally handling from other programming languages. https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_blocks.html
Example:
- name: Do complex stuff
block:
- name: Task 1
ansible.builtin.debug:
msg: 'execute task 1'
- name: Task 2
ansible.builtin.debug:
msg: 'execute task 2'
rescue:
- name: Complex stuf block failed
ansible.builtin.debug:
msg: 'handle failure'
always:
- name: Clean up task
ansible.builtin.debug:
msg: "run always"
Upvotes: 0
Reputation: 2480
Use Fail module.
- fail: msg="The execution has failed because of errors." when: flag == "failed"
Update:
Use register to store the result of a task like you have shown in your example. Then, use a task like this:
- name: Set flag
set_fact: flag = failed
when: "'FAILED' in command_result.stderr"
Upvotes: 57
Reputation: 11
In my case, command_result.stderr: "". I kept looking and the 'FAILED' output was at command_result.stdout. So i changed the last "when" to it:
when: "'FAILED' in command_result.stdout"
Hope i can help someone. I am a begginer too.
Upvotes: 0
Reputation: 1369
I found this to be helpful:
https://medium.com/opsops/anternative-way-to-handle-errors-in-ansible-245a066c340
In your task you want to register the task.
register: some_name
Then add ignore_errors: yes
Then use set_fact
to get each register attribute:
- set_fact:
success: '{{ not([e1, e2]|map(attribute="failed")|max) }}'
Then place this at the end of your block:
- name: Fail server build
command: >
bash scripts/test_file.sh
when: success == false
ignore_errors: yes
The block above would only be executed when success is false
. The key is using ignore_errors
and making a register. From the link I posted and from my testing the task attribute is registered if it fails or not.
Example output:
PLAY [localhost] ***********************************************************************************************
TASK [Gathering Facts] *****************************************************************************************
ok: [localhost]
TASK [Task 1 test] *********************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["bash", "scripts/unknown_file.sh"], "delta": "0:00:00.004343", "end": "2021-10-20 14:20:59.320389", "msg": "non-zero return code", "rc": 127, "start": "2021-10-20 14:20:59.316046", "stderr": "bash: scripts/unknown_file.sh: No such file or directory", "stderr_lines": ["bash: scripts/unknown_file.sh: No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Task 2 test] *********************************************************************************************
changed: [localhost]
TASK [set_fact] ************************************************************************************************
ok: [localhost]
TASK [Fail server build] ***************************************************************************************
changed: [localhost]
TASK [debug] ***************************************************************************************************
ok: [localhost] => {
"success": false
}
PLAY RECAP *****************************************************************************************************
localhost : ok=6 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
Upvotes: 2
Reputation: 1379
try failed_when
- name: Fail task when the command error output prints FAILED
ansible.builtin.command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
Upvotes: 4
Reputation: 1022
You can wrap all tasks which can fail in block, and use ignore_errors: yes
with that block.
tasks:
- name: ls
command: ls -la
- name: pwd
command: pwd
- block:
- name: ls non-existing txt file
command: ls -la no_file.txt
- name: ls non-existing pic
command: ls -la no_pic.jpg
ignore_errors: yes
Read more about error handling in blocks here.
Upvotes: 40
Reputation: 589
Fail module works great! Thanks.
I had to define my fact before checking it, otherwise I'd get an undefined variable error.
And I had issues when doing setting the fact with quotes and without spaces.
This worked:
set_fact: flag="failed"
This threw errors:
set_fact: flag = failed
Upvotes: 3