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.
Related
I have a lot of tasks running for the user and superuser. Most of them load configs via the template module. Question:
Is it possible to complete somehow the same task for both a regular user and a superuser? Those. do not do two tasks, one with become: no, and the other with yes.
Are there any conditions for template to distinguish become, so that at least one template is used.
I have quite a lot of experience with ansible and have read a lot of documentation and googled. Probably what I need is simply impossible, but suddenly someone came up with a crutch.
Thanks.
Ansible evaluates the become statement only once for the task, so if
you were to write a task like this:
- become: "{{ item|bool }}"
command: id
register: result
loop:
- false
- true
It would always run with become: false; if you were to switch the
order of the items in the loop, it would always run with become: true. However, the become_user setting can be set from a loop
variable, so you can do something like this:
- become: true
become_user: "{{ item }}"
command: id
register: result
loop:
- root
- "{{ ansible_user_id }}"
- debug:
var: result.results|map(attribute='stdout')|list
Running these tasks on my local system results in the following output:
TASK [command] *****************************************************************
changed: [localhost] => (item=root)
changed: [localhost] => (item=lars)
TASK [debug] *******************************************************************
ok: [localhost] => {
"result.results|map(attribute='stdout')|list": [
"uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023",
"uid=1000(lars) gid=1000(lars) groups=1000(lars),10(wheel),18(dialout),983(libvirt) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023"
]
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
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.
Network guy pretending to "code"...(insert laughter/shame here).
I am trying to create a playbook full of STIG requirements. I would like to be able to run this playbook against network devices, then easily copy the results into our the .ckl files.
In case it's not completely and utterly apparent, I have been using Ansible for less than a week.
*First I am having ansible register the output of a command.
*Then I would like ansible to validate certain words or phrases are in the output of the register.
*Then of course have a debug message state "Not a Finding {insert register here}", or "Open {insert register here}"
I cannot seem to get the "when {this pharse} (is (or not) in) register.stdout" to work.
Using Ansible 2.9
- hosts: ios
connection: network_cli
gather_facts: no
tasks:
- name: Gather Username Configuration Lines
ios_command:
commands: show run | i username localadmin
register: output
- debug:
msg: "{{ output.stdout }}"
- name: Username has correct privilege level
block:
- debug:
msg: "{{ output.stdout }}"
when: "'privilege 15' in output.stdout"
Output:
$ ansible-playbook ciscouserprivcheck.yml -u localadmin -k
SSH password:
PLAY [ios] *************************************************************************************************************************************
TASK [Gather Username Configuration Lines] *****************************************************************************************************
ok: [Cisco1]
TASK [debug] ***********************************************************************************************************************************
ok: [Cisco1] =>
msg:
- username localadmin privilege 15 secret 5 $1$o1t2$VoZhNwm3bMfsTJ6e8RIdl1
TASK [debug] ***********************************************************************************************************************************
skipping: [Cisco1]
PLAY RECAP *************************************************************************************************************************************
Cisco1 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
I want to list the java processes running in the mentioned hosts. However am not getting the desired o/p
Have created a ansible-playbook file to read the shell commands.
name: 'Check the running java processes'
hosts: all
tasks:
- name: 'check running processes'
shell: ps -ef | grep -i java```
output: PLAY [Check the running java processes] ****************************************
TASK [setup] *******************************************************************
ok: [target1]
ok: [target2]
TASK [check running processes] *************************************************
changed: [target1]
changed: [target2]
PLAY RECAP *********************************************************************
target1 : ok=2 changed=1 unreachable=0 failed=0
target2 : ok=2 changed=1 unreachable=0 failed=0
However, it's not listing the processes.
You could see the result with your actual playbook by running ansible in verbose mode.
However, the good way to do this is to register the output of your task and display its content in a debug task (or use it in any other task/loop).
To know how your registered var looks like, you can read the doc about common and shell's specific return values... or you can simply debug the full var in your playbook and have a look at it.
Here is an example just to get the full stdout of the command:
---
- name: Check the running java processes
hosts: all
tasks:
- name: Check running processes
shell: ps -ef | grep -i java
register: ps_cmd
- name: Show captured processes
debug:
var: ps_cmd.stdout
The docs says:
Since handlers are tasks too, you can also include handler files from the ‘handlers:’ section.
What I do, playbook.yml:
- hosts: all
handlers:
- include: handlers.yml
# - name: h1
# debug: msg=h1
tasks:
- debug: msg=test
notify: h1
changed_when: true
handlers.yml:
- name: h1
debug: msg=h1
Then,
$ ansible-playbook playbook.yml -i localhost, -k -e ansible_python_interpreter=python2 -v
...
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "test"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0
...
But when I uncomment the lines, I see
$ ansible-playbook playbook.yml -i localhost, -k -e ansible_python_interpreter=python2 -v
...
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "test"
}
RUNNING HANDLER [h1] ***********************************************************
ok: [localhost] => {
"msg": "h1"
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0
...
I'm running ansible-2.1.0.0.
What am I doing wrong? That's the first thing I'd like to know. Workarounds come second.
UPD
Includes can also be used in the ‘handlers’ section, for instance, if you want to define how to restart apache, you only have to do that once for all of your playbooks. You might make a handlers.yml that looks like:
---
# this might be in a file like handlers/handlers.yml
- name: restart apache
service: name=apache state=restarted
And in your main playbook file, just include it like so, at the bottom of a play:
handlers:
- include: handlers/handlers.yml
Depending on the size of your plays a better solution might be to use roles. Ansible has some discussion why roles are a good idea.
Tasks go in roles/mystuff/tasks/main.yml and roles/somethingelse/tasks/main.yml. You can share handlers between the roles, by creating a role containing only handlers roles/myhandlers/handlers/main.yml and make both roles depend on the myhandlers role:
roles/mystuff/meta/main.yml and roles/somethingelse/meta/main.yml:
---
dependencies:
- myhandlers
More on dependencies in https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html#using-role-dependencies
To moderators. Read my question carefully please. That's the answer to my question. And I'm totally aware that SO is not a forum.
That's a bug in ansible-2.1. The credit goes to udondan who found the issue.