- Fri 02 January 2015
- Linux
- James Oguya
- #linux, #ansible, #tomcat
An awesome feature in Chef that is not available in Ansible is immediate notification i.e. notifies :immediately
. Ansible has notification handlers but they are only triggered at the end of the current playbook unlike Chef's notifications which can be triggered immediately! Moreover, you can configure Chef's notifications to be triggered at specific times e.g. at the very end of a chef-client run i.e. notifies :delayed
or immediately i.e. notifies :immediately
.
Now, why I'm going into all these boring theories? Well, when installing tomcat on Ubuntu, dpkg starts it automatically once the process is complete. But in my case, I wanted to stop tomcat7 service first, configure it, deploy its webapps & finally start it. So on my ansible tasks file, after installing tomcat7 I added a notification action to call a task that stops tomcat7 service. Here's a snippet from the ansible task file:
tomcat.yml:
- hosts: all
sudo: yes
tasks:
- name: Install tomcat7
apt: name={{ item }} install_recommends=no update_cache=yes state=present
with_items:
- tomcat7
- tomcat7-admin
notify:
- Temporarily stop tomcat7
handlers:
- name: Temporarily stop tomcat7
service: name=tomcat7 state=stopped
OK so the task file looks great, but did it work ? Unfortunately, no! Ansible notifications trigger tasks in handlers section to run only at the end of a playbook. So I had to come up with a quick fix for this issue.
'Prompt' Handlers
My quick fix involved registering a variable in the task that installs tomcat packages i.e. register: tomcat_installed
, then the next task to stop tomcat service would be executed only if the registered variable has changed i.e. if tomcat7 has been installed - when: tomcat_installed|changed
. Basically, ansible notifications use a similar concept to this.
Here's a snippet from the playbook showing the quick fix:
tomcat.yml:
- hosts: all
sudo: yes
tasks:
- name: Install tomcat7
apt: name={{ item }} install_recommends=no update_cache=yes state=present
with_items:
- tomcat7
- tomcat7-admin
register: tomcat_installed
- name: Temporarily stop tomcat7
service: name=tomcat7 state=stopped
when: tomcat_installed|changed
As you can see from the snippet, I've not used a handler. Yes that's right, inorder to achieve the effect of an 'immediate' handler, I moved the task that stops tomcat7 service from the handler section to the tasks section.
Conclusion
Though I'm sure there are better solutions out there, I think the concept behind my quick fix can be useful in tackling other ansible-related issues.