Ansible Handler and when condition - ansible

I am trying to find a logic to check if the service is running, if Not Running, then start it. Below is the logic I have written, but for some reason the notify is not calling the handler?
---
- name: Executing the play to start the service
hosts: nodes
become: yes
gather_facts: False
tasks:
- name: Executing the Shell task to check the status of the wso2 instance
shell: myMsg=$(sudo service wso2esb status| grep Active | awk '{print $3}');if [[ $myMsg == "(dead)" ]]; then echo "Not Running";else echo "Running";fi
ignore_errors: yes
register: result
notify: handl
when: result.stdout == "Not Running" (I even tried 'changed_when', but the same error)
handlers:
- name: handl
service: name=wso2esb state=started
$ ansible-playbook -i inventories/hosts.sit start.yml -b -k
SSH password:
PLAY [Executing the play to start the wso2 service] ***********************************************
TASK [Executing the Shell task to check the status of the instance] *******************************
fatal: [mpstest01]: FAILED! => {"msg": "The conditional check 'result.stdout == \"Not Running\"' failed. The error was: error while evaluating conditional (result.stdout == \"Not Running\"): **'result' is undefined**\n\nThe error appears to have been in '/home/ansible1/start.yml': line 9, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Executing the Shell task to check the status of the instance\n ^ here\n"}
...ignoring
PLAY RECAP ****************************************************************************************
mpstest01 : ok=1 changed=0 unreachable=0 failed=0

That all seems unnecessary. You don't need to "check if the service is running, if Not Running, then start it"; that's exactly what the service module does. Just put the service module in a task, and don't bother with the handler:
- name: start service if it isn't already running
service: name=wso2esb state=started
Although I would prefer YAML syntax rather than the key=value syntax:
- name: start service if it isn't already running
service:
name: wso2esb
state: started
In any case, the service module will check if the service is running, and if not, it will start it.

Related

Search for a regular expression in a file in Ansible

I am trying to convert a small bash code snippet to Ansible but I am finding it hard to implement. Basically, it is first checking if /etc/redhat-release exists. If yes, it is looking for a regex pattern *release 6.8*. If the pattern is found, then it is checking for another file /bin/login.ori. If it exists, then it performs a couple of operations.
#fixed RHEL6.8/CentOS6.8 rlogin issue
if [ -f /etc/redhat-release ]; then
case `cat /etc/redhat-release` in
*'release 6.8'*)
if [ ! -e /bin/login.ori ]; then
cp -f
/bin/login /bin/login.ori
cp -f $MDIR/login.bin.68 /bin/login
restorecon /bin/login
fi
;;
esac
fi
Here is what I have tried so far:
- name: Fix RHEL6.8/CentOS6.8 rlogin issue
stat:
path: /etc/redhat-release
register: redhat_file
- debug:
msg: "File exists: {{ redhat_file }}"
when: redhat_file.stat.exists
- name: Check whether /etc/redhat-release contains "*release 6.8*"
lineinfile:
path: /etc/redhat-release
line: '*release 7.3*'
# insertafter: [main]
register: checkmyconf
when: redhat_file.stat.exists
- name: Greet the world if /etc/redhat-release contains "*release 6.8*"
debug:
msg: "{{ checkmyconf }}"
when: checkmyconf.stdout | match('*release 7.3.1611*')
But I am getting below error. Kindly help.
TASK [qsc/hack/v1 : Check whether /etc/redhat-release contains "*release 6.8*"] *******************************************************
ok: [ansible-poc-cos6]
ok: [ansible-poc-rhel6]
ok: [ansible-poc-centos7]
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|match` use `result is match`. This feature will
be removed in version 2.9. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
TASK [qsc/hack/v1 : Greet the world if /etc/redhat-release contains "*release 6.8*"] **************************************************
fatal: [ansible-poc-cos6]: FAILED! => {"msg": "The conditional check 'checkmyconf.stdout | match('*release 7.3.1611*')' failed. The error was: nothing to repeat\n\nThe error appears to have been in '/remote/us01home53/subburat/snps-ansible/roles/qsc/hack/v1/tasks/main.yml': line 31, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Greet the world if /etc/redhat-release contains \"*release 6.8*\"\n ^ here\n"}
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|match` use `result is match`. This feature will
be removed in version 2.9. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
fatal: [ansible-poc-rhel6]: FAILED! => {"msg": "The conditional check 'checkmyconf.stdout | match('*release 7.3.1611*')' failed. The error was: nothing to repeat\n\nThe error appears to have been in '/remote/us01home53/subburat/snps-ansible/roles/qsc/hack/v1/tasks/main.yml': line 31, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Greet the world if /etc/redhat-release contains \"*release 6.8*\"\n ^ here\n"}
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|match` use `result is match`. This feature will
be removed in version 2.9. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
fatal: [ansible-poc-centos7]: FAILED! => {"msg": "The conditional check 'checkmyconf.stdout | match('*release 7.3.1611*')' failed. The error was: nothing to repeat\n\nThe error appears to have been in '/remote/us01home53/subburat/snps-ansible/roles/qsc/hack/v1/tasks/main.yml': line 31, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Greet the world if /etc/redhat-release contains \"*release 6.8*\"\n ^ here\n"}
to retry, use: --limit #/remote/us01home53/subburat/snps-ansible/push-full.retry
PLAY RECAP ****************************************************************************************************************************
ansible-poc-centos7 : ok=3 changed=0 unreachable=0 failed=1
ansible-poc-cos6 : ok=3 changed=0 unreachable=0 failed=1
ansible-poc-rhel6 : ok=3 changed=0 unreachable=0 failed=1
Note: I have tried all the suggestions in this link but it does not work for this use-case as the line attribute in my use-case is dynamic.
This is the equivalent
- stat:
path: /bin/login.ori
register: result
- block:
- copy:
src: /bin/login
dest: /bin/login.ori
remote_src: true
- copy:
src: "{{ ansible_env.MDIR }}/login.bin.68"
dest: /bin/login
remote_src: true
force: true
- command: restorecon /bin/login
when:
- ansible_distribution == 'Red Hat Enterprise Linux'
- ansible_distribution_version == '6.8'
- not result.stat.exists|bool
(not tested)
Notes
gather_facts must be enabled to collect ansible_* variables.
It's not necessary to "force" the first copy because the "dest" does not exist.
I'm not sure if the requirement to fix both "RHEL6.8/CentOS6.8" and testing the existence of "/etc/redhat-release" only is consistent (I have no access to 6.8 atm). Fit the conditions in the block to your needs.

echo message based on ansible stdout value

Team,
Not sure why my message with echo is not getting printed. I want to print a text if command that ran before for stopping process was successful.
In my case am checking for apache2 process status. Basically, if stdout is empty it passed and if stderr exists it failed. I also referred this link but no luck..
https://stackoverflow.com/questions/26142343/ansible-conditional-based-on-stdout-of-result
- name: stop apache2 process
command: systemctl stop apache2
ignore_errors: no
changed_when: false
register: service_apache2_status
become: true
- debug:
var: service_apache2_status.stdout
- name: Check if apache2 stopped
command: echo "Successfully Stopped Apache2"
# when: service_apache2_status.stdout == " "
when: service_apache2_status.stdout | length == 0
Actual output:
TASK [diskcache_prerequisites : stop apache2 process] **********************************************************************************
ok: [localhost]
TASK [diskcache_prerequisites : debug] *************************************************************************************************
ok: [localhost] => {
"service_apache2_status.stdout": ""
}
TASK [diskcache_prerequisites : Check if apache2 stopped] ******************************************************************************
changed: [localhost]
expected output:
TASK [diskcache_prerequisites : Check if apache2 stopped] ******************************************************************************
changed: [localhost]
Successfully Stopped Apache2
You don't need the "check if apache2 stopped" at all if you use the systemd module instead of trying to use command: to call systemctl by hand
As for your question: if you want to see output, that's what - debug: msg="Successfully stopped Apache2" is for; the command: module is not a general purpose debugging tool, it's for running commands

How to print only the stderr_lines when shell command execution fails in ansible playbook task

In my ansible playbook I have a task that executes a shell command. One of the parameters of that command is password. When the shell command fails, ansible prints the whole json object that includes the command having password. If I use no_log: True then I get censored output and not able to get stderr_lines. Is there a way to customize the output when shell command execution fails?
You can take advantage of ansible blocks and their error handling feature.
Here is an example playbook
---
- name: Block demo for shell
hosts: localhost
gather_facts: false
tasks:
- block:
- name: my command
shell: my_command is bad
register: cmdresult
no_log: true
rescue:
- name: show error
debug:
msg: "{{ cmdresult.stderr }}"
- name: fail the playbook
fail:
msg: Error on command. See debug of stderr above
which gives the following result:
PLAY [Block demo for shell] *********************************************************************************************************************************************************************************************************************************************
TASK [my command] *******************************************************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": true}
TASK [show error] *******************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "/bin/sh: 1: my_command: not found"
}
TASK [fail the playbook] ************************************************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Error on command. See debug of stderr above"}
PLAY RECAP **************************************************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=1 ignored=0
You can utilize something like this :
- name: Running it
hosts: localhost
tasks:
- name: failing the task
shell: sh a.sh > output.txt
ignore_errors: true
register: abc
- name: now failing
command: rm output.txt
when: abc|succeeded
stdout will be written to a file. If it's a failure you can check the file and debug it, if it's a success then file will be deleted.

Ansible when statement with variable from another task

can someone help me please?
I want to create a folder at host "cfme_tester-0".
For this I check variable "osp_version" from "undercloud-0" host and based on the result I should create a folder at the "cfme_tester-0" host.
Here is my playbook:
- name: take openstack version
hosts: undercloud-0
become: true
become_user: stack
tasks:
- name: creating flavor
shell: |
source /home/stack/stackrc
cat /etc/rhosp-release | egrep -o '[0-9]+' | head -1
register: osp_version
ignore_errors: True
- debug: msg="{{ osp_version.stdout }}"
- name: set up CFME tester
hosts: cfme_tester-0
become: yes
become_user: root
tasks:
- name: Run prepare script for OSP10
debug:
shell: |
cd /tmp/cfme/ && mkdir osp10
when: "'10' in osp_version.stdout"
- name: Run prepare script for OSP13
debug:
shell: |
cd /tmp/cfme/ && mkdir osp13
when: "'13' in osp_version.stdout"
But an error occurs:
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [undercloud-0] => {
"msg": "10"
}
PLAY [set up CFME tester] *****************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [cfme_tester-0]
TASK [Run prepare script for OSP10] *******************************************************************************************************************************************************************************
fatal: [cfme_tester-0]: FAILED! => {"msg": "The conditional check ''10' in osp_version.stdout' failed. The error was: error while evaluating conditional ('10' in osp_version.stdout): 'osp_version' is undefined\n\nThe error appears to have been in '/root/infrared/rhos-qe-core-installer/playbooks/my_setup.yaml': line 20, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n tasks:\n - name: Run prepare script for OSP10\n ^ here\n"}
to retry, use: --limit #/root/infrared/rhos-qe-core-installer/playbooks/my_setup.retry
PLAY RECAP ********************************************************************************************************************************************************************************************************
cfme_tester-0 : ok=1 changed=0 unreachable=0 failed=1
undercloud-0 : ok=3 changed=1 unreachable=0 failed=0
Variables are per-host (because otherwise, what happens when you run a task on multiple hosts and register a variable?). In your first task, you are setting the osp_version variable for host undercloud-0.
If you want to use this variable in your second play, which is running on cfme_tester-0, then you should read the Magic Variables, and How To Access Information About Other Hosts section of the Ansible documentation. You'll need to refer to the variable via the hostvars dictionary, so your second play will look like:
- name: set up CFME tester
hosts: cfme_tester-0
become: yes
become_user: root
tasks:
- name: Run prepare script for OSP10
shell: |
cd /tmp/cfme/ && mkdir osp10
when: "'10' in hostvars['undercloud-0'].osp_version.stdout"
- name: Run prepare script for OSP13
shell: |
cd /tmp/cfme/ && mkdir osp13
when: "'13' in hostvars['undercloud-0'].osp_version.stdout"
...but note that if you're just creating a directory, you would be better off just using the file module instead:
- name: Run prepare script for OSP10
file:
path: /tmp/cfme/osp10
state: directory
when: "'10' in hostvars['undercloud-0'].osp_version.stdout"

Why notify tasks aren't getting executed in ansible?

The problem I am facing is quite common, but the other solutions didn't work for me. As the question suggests, when I run my playbook, only the first notify handler gets executed. i.e. only firewalld is restarted, but updated bash profile isn't sourced.
Some people suggested notify chaining, but I wouldn't like to merge two tasks with completely different objectives. For example, one task could be adding ports to firewalld and then restarting it; another could be update my bash profile to display date with history command output.
N.B. the above snippet isn't my full .yml, only a part of it, so this may or may not work. But, the original file does work.
---
tasks
- name: add port-80 to firewalld
firewalld: zone=drop port=80/tcp permanent=true state=enabled
- name: add port-443 to firewalld
firewalld: zone=drop port=443/tcp permanent=true state=enabled
- shell: firewall-cmd --reload
notify:
- Restart firewalld
- name: Enabling time display in history
blockinfile:
dest: ~/.bash_profile
block: |
export HISTTIMEFORMAT="%d/%m/%y %T "
notify:
- Source the updated Bash profile
handlers:
- name: Restart firewalld
service: name=firewalld state=restarted
- name: Source the updated Bash profile
shell: source ~/.bash_profile
...
Finally, I have figured out the problem with the help of comments.
The notify handler will be executed if and only if state is changed as a result of the task.
The mistake I am doing is trying to install a package that is already installed. So, state wasn't getting changed.
Let's see it with an example,
---
- hosts: varnish
remote_user: root
tasks:
- name: Install tree
yum: name=tree state=absent
notify:
- Do an echo
handlers:
- name: Do an echo
debug: msg="This will be printed"
...
We will run the play book two times.
After first run, we will get:
TASK [Install tree] ************************************************************
changed: [192.***.***.**]
RUNNING HANDLER [Do an echo] ***************************************************
ok: [192.***.***.**] => {
"msg": "This will be printed"
}
PLAY RECAP *********************************************************************
192.***.***.** : ok=1 changed=1 unreachable=0 failed=0
As the state is changed ( Look at the changed=1 part ), debug message will be printed.
After second run, we will get:
TASK [Install tree] ************************************************************
ok: [192.***.***.**]
PLAY RECAP *********************************************************************
192.***.***.** : ok=0 changed=0 unreachable=0 failed=0
The thing to look at is handler isn't called unlike first run, because state isn't changed in the second run ( tree is already installed ).
I have posted it as an answer, it may help the fellow users.

Resources