I am trying to figure it out how to stop instantly my playbook when tests are failed for specific branch, master
in this case.
This is my Ansible code:
- name: 'Run Tests'
shell: testing.sh | tee "testing.log"
register: testing
- name: 'Show log'
debug:
msg: "{{ testing.stdout_lines }}"
- name: 'Set fact'
set_fact:
tests: >-
{{
testing.stdout_lines | join(' ') | regex_findall('(\d+)\s*failed') | map('int') | max == 0
}}
For example, given the script for testng
shell> cat /tmp/testing.sh
#!/usr/bin/sh
echo 101 ${1}
echo 102 ${2}
echo 103 ${3}
gives
shell> /tmp/testing.sh ok failed failed
101 ok
102 failed
103 failed
In the play for testing, declare the number of failed lines and terminate the play if any test fails
shell> cat pb.yml
- hosts: localhost
vars:
test_regex: '\d+\s*failed'
tests_failed: "{{ out.stdout_lines | select('search', test_regex) | length }}"
tasks:
- command: "/tmp/testing.sh {{ p1 }} {{ p2 }} {{ p3 }}"
register: out
- debug:
var: out.stdout_lines
- debug:
var: tests_failed
- assert:
that: tests_failed == 0
fail_msg: "ERR number of failed tests: {{ tests_failed }}"
gives, for example
shell> ansible-playbook pb.yml -e "p1=ok p2=failed p3=failed"
PLAY [localhost] ****************************************************************************************************
TASK [command] ******************************************************************************************************
changed: [localhost]
TASK [debug] ********************************************************************************************************
ok: [localhost] =>
out.stdout_lines:
- 101 ok
- 102 failed
- 103 failed
TASK [debug] ********************************************************************************************************
ok: [localhost] =>
tests_failed: '2'
TASK [assert] *******************************************************************************************************
fatal: [localhost]: FAILED! =>
assertion: tests_failed == 0
changed: false
evaluated_to: false
msg: 'ERR number of failed tests: 2'
PLAY RECAP **********************************************************************************************************
localhost: ok=3 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
If you sum the selected numbers
test_regex: '(\d+)\s*failed'
tests_failed: "{{ out.stdout_lines | map('regex_findall', test_regex)
| flatten
| map('int')
| sum }}"
the play will fail
msg: 'ERR number of failed tests: 205'
Notes:
Use rc
to return the error code. For example, the script
shell> cat /tmp/testing.sh
#!/usr/bin/sh
$1
returns 0
shell> /tmp/testing.sh true
shell> echo $?
0
or 1
shell> /tmp/testing.sh false
shell> echo $?
1
In a play, let the task fail if rc > 1
shell> cat pb.yml
- hosts: localhost
tasks:
- command: "/tmp/testing.sh {{ param | d('true') }}"
register: out
failed_when: out.rc > 1
- debug:
var: out.rc
gives (abridged) 0
shell> > ansible-playbook pb.yml
...
ok: [localhost] =>
out.rc: '0'
or 1
shell> > ansible-playbook pb.yml -e param=false
...
ok: [localhost] =>
out.rc: '1'
Now, you can stop the play instantly. For example,
- assert:
that: out.rc < 2
fail_msg: "ERR rc={{ out.rc }}"
Fit the script rc
and conditions to your needs.
Example of a complete playbook for testing
- hosts: localhost
tasks:
- command: "/tmp/testing.sh {{ param | d('true') }}"
register: out
failed_when: out.rc > 1
- debug:
var: out.rc
- assert:
that: out.rc < 2
fail_msg: "ERR rc={{ out.rc }}"
Create rc
codes in your script. For example,
shell> cat /tmp/testing2.sh
#!/usr/bin/sh
# Partameter undefined or empty
if [ -z "${1}" ]; then
return 2
fi
# File does not exist
if [ ! -e "${1}" ]; then
return 3
fi
# File not executable
if [ ! -x "${1}" ]; then
return 4
fi
${1}
and use them in a play. For example,
shell> cat pb.yml
- hosts: localhost
vars:
err:
2: Partameter undefined or empty.
3: File does not exist.
4: File not executable.
tasks:
- command: "/tmp/testing2.sh {{ param | d('') }}"
register: out
failed_when: out.rc > 4
- debug:
var: out.rc
- assert:
that: out.rc < 2
fail_msg: "ERR {{ err[out.rc] }}"