1. failed_when and changed_when (Full Conditional Expressions)
These two directives are explicitly designed to take a conditional Jinja2 expression, allowing you to check variables, return codes, and other outputs from the registered task result.
How to read it:
failed_when: <condition> in Ansible should be read as: Fail the task WHEN this condition is true.
failed_when: false, here the task is considered failed WHEN this expression evaluates to TRUE.
The task fails when false is true ,but the false is never true and the task can never fail.
In Yaml false is a Boolean literal, It already has a value and no comparison or evaluation needed .
Similarly:
changed_when: false - Mark the task as CHANGED when this expression evaluates to TRUE.Mark this task as changed when false is true, but false is never true, and the task never marked as CHANGED.
changed_when: <condition> - Mark this task as CHANGED when <condition> evaluates to TRUE.
I'm modifying the playbook to have conditional expression , lets stop the listener first from the managed node.
[oracle@oelggvm01 dbhome_1]$ lsnrctl stop
LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 14-DEC-2025 06:30:41
Copyright (c) 1991, 2025, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.111)(PORT=1521)))
The command completed successfully
[oracle@oelggvm01 dbhome_1]$
[oracle@oelggvm01 dbhome_1]$ lsnrctl status >/dev/null 2>&1; echo $?
1
[oracle@oelggvm01 dbhome_1]$
[oracle@oel01db ansible-project]$ cat ./playbooks/changed.failed.conditinal.yml
---
- name: Oracle Listener Health Check (Best Practice)
hosts: db_servers
become_user: oracle
gather_facts: no
tasks:
- name: Check listener status
environment:
ORACLE_HOME: /u01/app/oracle/product/19.0.0/dbhome_1
PATH: /u01/app/oracle/product/19.0.0/dbhome_1/bin
shell: lsnrctl status
register: listener_status
# 🔵 Health check → never mark it has CHANGED
changed_when: false
# 🔴 Fail only for unexpected error other than listener error
failed_when: >
listener_status.rc != 0 and
'TNS-12541' not in listener_status.stdout
# 🟢 Do not stop play even if failure occurs -no really needed here
ignore_errors: yes
- name: Print listener status
debug:
msg: |
RC={{ listener_status.rc }}
Listener Down={{ 'TNS-12541' in listener_status.stdout }}
- name: Stop listener (best-effort, may already be down)
environment:
ORACLE_HOME: /u01/app/oracle/product/19.0.0/dbhome_1
PATH: /u01/app/oracle/product/19.0.0/dbhome_1/bin
shell: lsnrctl stop
register: stop_result
# 🔵 Cleanup step → ignore failures
ignore_errors: yes
# 🔵 Changed only if listener was actually stopped
changed_when: >
'The command completed successfully' in stop_result.stdout
- name: Start listener if it is down
environment:
ORACLE_HOME: /u01/app/oracle/product/19.0.0/dbhome_1
PATH: /u01/app/oracle/product/19.0.0/dbhome_1/bin
shell: lsnrctl start
register: start_result
# 🔵 Start only when listener was detected as down
when: "'TNS-12541' in listener_status.stdout"
# 🔵 Mark changed only on successful start
changed_when: >
'The command completed successfully' in start_result.stdout
# 🔴 Fail if start genuinely fails
failed_when: >
start_result.rc != 0
[oracle@oel01db ansible-project]$
Note:
failed_when: >
listener_status.rc != 0 and
'TNS-12541' not in listener_status.stdout
This is a specific, business-logic-driven instruction that tells Ansible:
"FAIL the task ONLY IF:
The command technically failed (the return code is not 0, listener_status.rc != 0) AND the failure was not due to the Oracle Listener being down (the text 'TNS-12541' is not present in the output).
**Using failed_when: false means the task will never be marked as failed, regardless of the reason for the error. As a result, all failures are suppressed, making it impossible to distinguish between expected conditions (such as the listener being down) and genuine problems (such as an invalid ORACLE_HOME or missing binaries).
To achieve the required precision—to fail the task when the command returned an error AND the error is NOT 'listener down'—we must use a conditional failed_when expression.
Verify the listener status
[oracle@oelggvm01 dbhome_1]$ lsnrctl status >/dev/null 2>&1; echo $?
0
[oracle@oelggvm01 dbhome_1]$
The expression {{ 'TNS-12541' in listener_status.stdout }} is a boolean test
It literally means: “Is the string TNS-12541 present inside listener_status.stdout?”
So the result can be true or false and hence we have the output Listener Down=True
No comments:
Post a Comment