handlers inside loops

57 views
Skip to first unread message

Jacob Weber

unread,
Feb 24, 2015, 2:04:36 PM2/24/15
to ansible...@googlegroups.com
I figured out the solution to this while writing it, but I thought I'd share anyway, in case anyone else finds it useful.

I have a task to update the config files for multiple web servers, which triggers a handler to restart them all.

# tasks/main.yml
- name: update config file
  file: src=httpd-{{ item }}.conf dest=/etc/httpd-{{ item }}.conf
  notify: restart web servers
  with_items: web_servers

# handlers/main.yml
- name: restart web servers
  service: httpd-{{ item }} state=restarted
  with_items: web_servers

This works, and restarts all web servers. But what if I want to only restart a web server when its config file changes?

The {{ item }} variable doesn't get passed to the handler, so I can't use it there. And even if it did, the handler only gets called once.

The solution is to register a variable with the results of the update. Then add a separate handler to only restart the changed servers:

# tasks/main.yml
- name: update config file
  file: src=httpd-{{ item }}.conf dest=/etc/httpd-{{ item }}.conf
  register: configs_changed
  notify: restart web servers with changed configs
  with_items: web_servers

# handlers/main.yml
- name: restart web servers with changed configs
  service: httpd-{{ item.item }} state=restarted
  when: item.changed
  with_items: configs_changed.results

The only problem is that if there are multiple tasks that might trigger a restart, you have to register a separate variable and create a separate handler for each one. So the server will get restarted multiple times. Not sure if there's a better way, but I can live with this limitation.

Jacob

Brian Coca

unread,
Feb 25, 2015, 9:06:52 AM2/25/15
to ansible...@googlegroups.com
the normal pattern is to have this taken care of by a hosts loop

- hosts: webservers
tasks:
...

but your case seems to imply having multiple webservers per host and
your use of registered vars and |changed seems to be the adequate
solution. To expand on that when you have more of these variables you
can do:

with_items:
- web_servers.results
- app_servers.results
- etc ...

which will be aggregated into 'item'.

--
Brian Coca
Reply all
Reply to author
Forward
0 new messages