Is there some Ansible equivalent to failed_when for success
I think maybe assert module is what you want.
New in version 1.5
Examples:
- assert: { that: "ansible_os_family != 'RedHat'" }
Ansible: simulating a passed when module
Have a look here:
Is there some Ansible equivalent to "failed_when" for success
- name: ping pong redis
command: redis-cli ping
register: command_result
failed_when:
- "'PONG' not in command_result.stderr"
- "command_result.rc != 0"
- will not fail if return code is 0 and there is no 'PONG' in stderr.
- will not fail if there is "PONG" in stderr.
So it passes if any of the list is False
How to print debug message for success and failure in ansible wait_for module to test firewall?
TL;DR;
Here is the debug
you are looking for:
- debug:
msg: "{{ 'Failed with message: ' ~ wait_result.msg if wait_result.failed else 'Success connecting to Firewall' }}"
You can always register
the result of a task in Ansible.
Then based on this result, you can actually act, or print something.
Here is how I would have approached it: I don't know from the top of my head what a task will give me as a result, but I know for a fact that I can register
it and debug
it.
So I made this playbook:
- hosts: local
gather_facts: no
tasks:
- name: Check Firewall Connectivity
wait_for:
host: 10.200.12.2
port: 2041
state: started
delay: 0
timeout: 3
ignore_errors: yes
register: wait_result
- debug:
msg: "{{ wait_result }}"
It resulted in this recap:
PLAY [local] *******************************************************************
TASK [Check Firewall Connectivity] *********************************************
fatal: [local]: FAILED! => {"changed": false, "elapsed": 3, "msg": "Timeout when waiting for 127.0.0.1:22"}
...ignoring
TASK [debug] *******************************************************************
ok: [local] => {
"msg": {
"changed": false,
"elapsed": 3,
"failed": true,
"msg": "Timeout when waiting for 127.0.0.1:22"
}
}
PLAY RECAP *********************************************************************
local : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
So based on this recap, I know that my result have a property failed
this is going to be true
if the wait_for
task fails.
And I even get a msg
of failure for it.
So now, with the help of the inline if expression of Jinja, I can create this task:
- debug:
msg: "{{ 'Failed with message: ' ~ wait_result.msg if wait_result.failed else 'Success connecting to Firewall' }}"
This will result in either the recap:
TASK [debug] *******************************************************************
ok: [local] => {
"msg": "Success connecting to Firewall"
}
or the recap:
TASK [debug] *******************************************************************
ok: [local] => {
"msg": "Failed with message: Timeout when waiting for 10.200.12.2:2041"
}
assert module: Is it possible to fail if string is found only once?
TL;DR
- name: "File output | verification"
vars:
watch_regex: '(?:^|\W)(test)(?:$|\W)'
assert:
that:
- testing_parse.stdout | regex_findall(watch_regex) | length > 1
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
Why the in
test is not appropriate
in
returns a boolean
Let's first see what we get back from the in
test in several situations
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='a test'"
localhost | SUCCESS => {
"msg": true
}
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='a test and an other test'"
localhost | SUCCESS => {
"msg": true
}
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='no word we look for'"
localhost | SUCCESS => {
"msg": false
}
As you can see, it will always return a boolean depending on the presence or not of the needle in the haystack.
in
does not find words
Note also that in
is not very good at finding words (since you mentioned that) as demonstrated below:
# It will match a substring in a middle of an other word
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e my_test="blahtesttoto"
localhost | SUCCESS => {
"msg": true
}
# It will not match a word inside an element of a list...
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e '{"my_test":["this is", "a test"]}'
localhost | SUCCESS => {
"msg": false
}
# ... but only an exact match of an element of a list
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e '{"my_test":["a", "test"]}'
localhost | SUCCESS => {
"msg": true
}
Your expression is wrong anyway
To end with, let's look at your try when you wrote the expression:
'test' in testing_parse.stdout >= '2'
This means:
- check if the string
testing_parse.stdout
is lexically superior or equal to the string'2'
. - now check if the string
'test'
is found inside the preceding boolean result.
As you can now guess with the explanation, there is absolutely no chance this will ever return true
.
regex_findall
to the rescue
A way to look for a specific word is to use a regex. The following will look for the test
word i.e. the "test"
string preceded and followed by any non-word character (end of line, beginning of line, white space, tab, punctuation....).
(?:^|\W)(test)(?:$|\W)
If you are not familiar with regular expressions, see this answer for a specific explanation and https://www.regextutorial.org/ for a general resource (I'm not affiliated, you can find others using your favorite search engine).
The regex_find_all
filter can return all matches of a regex against a string into a list
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\\W)(test)(?:$|\\W)') }}" \
-e "my_test='test'"
localhost | SUCCESS => {
"msg": [
"test"
]
}
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\\W)(test)(?:$|\\W)') }}" \
-e "my_test='test and an other test but not blahtesttoto yet test'"
localhost | SUCCESS => {
"msg": [
"test",
"test",
"test"
]
}
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\\W)(test)(?:$|\\W)') }}" \
-e "my_test='notest'"
localhost | SUCCESS => {
"msg": []
}
Once we have that, we only need to count the number of elements in the returned list whith the length
filter.
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\\W)(test)(?:$|\\W)') | length }}" \
-e "my_test='test and an other test but not blahtesttoto yet test'"
localhost | SUCCESS => {
"msg": "3"
}
And finally we can fix your assert
task according to your requirement:
- name: "File output | verification"
vars:
watch_regex: '(?:^|\W)(test)(?:$|\W)'
assert:
that:
- testing_parse.stdout | regex_findall(watch_regex) | length > 1
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
How can I configure Ansible playbook to ignore certain error codes?
You can use a better mechanism than ignore_errors
in this case, it is failed_when
.
With it, you can fine grain the failure of a task to exactly what you want.
In your case it would be something like:
- name: Call MOS Windows Service Endpoint
uri:
url: https://example.org/api
## reduced the uri for brevity
register: trigger_backup_response
failed_when: trigger_backup_response.status not in [202, 400, 422]
This will cause the codes 202
, 400
and 422
to have a successful task, all other status code would, then, fail.
Next to this, in order to handle the tasks based on the return of that API call, you can either use a block
:
- block:
- debug:
msg: First task upon receiving a return form the API
- debug:
msg: Second task upon receiving a return form the API
- debug:
msg: Third task upon receiving a return form the API
when: trigger_backup_response.status == 202
Or, stop the execution totally, with the help of the meta
module.
The task here under will stop the play, on an host basis, if the the return code of the API is either 400
or 422
.
- meta: end_host
when: trigger_backup_response.status in [400, 422]
So, having a scenario like:
- name: Call API
uri:
url: https://example.org/api
register: trigger_backup_response
failed_when: trigger_backup_response.status not in [202, 400, 422]
- name: End play for hosts with detached volumes
meta: end_host
when: trigger_backup_response.status in [400, 422]
## From now on, it is safe to assume
## we are only dealing with API answer status being 202
- name: Display volume IDs
debug:
var: backup_properties.volume_ids
Ansible conditional based on stdout of result?
Try checking to see it if equals a blank string or not?
- hosts: myhosts
tasks:
- name: echo hello
command: echo hello
register: result
- command: somecommand {{ result.stdout }}
when: result.stdout != ""
- command: someothercommand
when: result.stdout == ""
Is it possible to have ansible retry only on certain conditions, success/fail on others?
Use an until
loop with a generated list of all the 2xx codes as status_code
.
The generated list can be done with the range
function of Jinja.
This way, you will get an immediate a success for all 2xx code, an immediate failure for all other codes and a retry for the status code 409.
Here is an example:
- uri:
url: https://httpbin.org/status/409
## List containing all the 2xx codes that should be successful
status_code: "{{ range(200, 300) }}"
register: results
retries: 1
delay: 30
until: results.status != 409
Using https://httpbin.org/, you can adapt the status code in the URL to see how the task reacts to different status codes.
Related Topics
Linux Shell Script - Find All Files and Run a Command on Each One of Them
Awk: Sum Up Column Values Across Multiple Files with Identical Column Layout
How to Switch Between Different Versions of Julia (Specifically Between V0.3 and V0.4 on Ubuntu)
Linux Script Telnet Head Request
Extract/See Content of a Specific File Inside a .War File
How to Boot with My Latest Rpi-3.18.0 Kernel and Enabling The Device Tree
Removing First 3 Characters of File Names in Linux
Posix: Pipe Syscall in Freebsd Vs Linux
How Is The Linux Calculating Memfree
Linux Compile for Enable Uart2
How to Increase a Date Within a Loop in Bash
How to Continue Next Iteration When an Error Occurs in Bash
Is There Some Cases in Which Sigkill Will Not Work