I used to have simple playbook (something like this) which I run on all over my machines (RH & Debian based) to update them, and for each machine which was updated run a script (notify handler).
Recently I tried to test a new module called group_by
, so instead using the when
condition to run yum update
when ansible_distribution == "CentOS"
, I will first gather the facts and group the host based on there ansible_pkg_mgr
as key and then I was looking to run yum update on all the hosts which the key is PackageManager_yum , see the play book example:
---
- hosts: all
gather_facts: false
remote_user: root
tasks:
- name: Gathering facts
setup:
- name: Create a group of all hosts by operating system
group_by: key=PackageManager_{{ansible_pkg_mgr}}
- hosts: PackageManager_apt
gather_facts: false
tasks:
- name: Update DEB Family
apt:
upgrade=dist
autoremove=yes
install_recommends=no
update_cache=yes
when: ansible_os_family == "Debian"
register: update_status
notify: updateX
tags:
- deb
- apt_update
- update
- hosts: PackageManager_yum
gather_facts: false
tasks:
- name: Update RPM Family
yum: name=* state=latest
when: ansible_os_family == "RedHat"
register: update_status
notify: updateX
tags:
- rpm
- yum
- yum_update
handlers:
- name: updateX
command: /usr/local/bin/update
And this is the error message I get,
PLAY [all] ********************************************************************
TASK [Gathering facts] *********************************************************
Wednesday 21 December 2016 11:26:17 +0200 (0:00:00.031) 0:00:00.031 ****
....
TASK [Create a group of all hosts by operating system] *************************
Wednesday 21 December 2016 11:26:26 +0200 (0:00:01.443) 0:00:09.242 ****
TASK [Update DEB Family] *******************************************************
Wednesday 21 December 2016 11:26:26 +0200 (0:00:00.211) 0:00:09.454 ****
ERROR! The requested handler 'updateX' was not found in either the main handlers list nor in the listening handlers list
thanks in advance.
You defined handlers only in one of your plays. It's quite clear if you look at the indentation.
The play which you execute for PackageManager_apt
does not have the handlers
at all (it has no access to the updateX
handler defined in a separate play), so Ansible complains.
If you don't want to duplicate the code, you can save the handler to a separate file (let's name it handlers.yml
) and include in both plays with:
handlers:
- name: Include common handlers
include: handlers.yml
Note: there's a remark in Handlers: Running Operations On Change section regarding including handlers:
You cannot notify a handler that is defined inside of an include. As of Ansible 2.1, this does work, however the include must be static.
Finally, you should rather consider converting your playbook to a role.
A common method to achieve what you want is to include the tasks (in tasks/main.yml
) using file names with the architecture in their names:
- include: "{{ architecture_specific_tasks_file }}"
with_first_found:
- "tasks-for-{{ ansible_distribution }}.yml"
- "tasks-for-{{ ansible_os_family }}.yml"
loop_control:
loop_var: architecture_specific_tasks_file
Handlers are then defined in handlers/main.yml
.