Merge pull request #14842 from resmo/patch-4
proposal: publish/subscribe for handlers
This commit is contained in:
commit
d23c7949eb
1 changed files with 205 additions and 0 deletions
205
docs/proposals/publish-subscribe.md
Normal file
205
docs/proposals/publish-subscribe.md
Normal file
|
@ -0,0 +1,205 @@
|
|||
# Publish / Subscribe for Handlers
|
||||
|
||||
*Author*: René Moser <@resmo>
|
||||
|
||||
*Date*: 07/03/2016
|
||||
|
||||
## Motivation
|
||||
|
||||
In some use cases a publish/subscribe kind of event to run a handler is more convenient, e.g. restart services after replacing SSL certs.
|
||||
|
||||
However, ansible does not provide a built-in way to handle it yet.
|
||||
|
||||
|
||||
### Problem
|
||||
|
||||
If your SSL cert changes, you usually have to reload/restart services to use the new certificate.
|
||||
|
||||
However, If you have a ssl role or a generic ssl play, you usually don't want to add specific handlers to it.
|
||||
Instead it would be much more convenient to use a publish/subscribe kind of paradigm in the roles where the services are configured in.
|
||||
|
||||
The way we implemented it currently:
|
||||
|
||||
I use notify to set a fact where later (in different plays) we act on a fact using notify again.
|
||||
|
||||
~~~yaml
|
||||
---
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: copy an ssl cert
|
||||
shell: echo cert has been changed
|
||||
notify: publish ssl cert change
|
||||
handlers:
|
||||
- name: publish ssl cert change
|
||||
set_fact:
|
||||
ssl_cert_changed: true
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: subscribe for ssl cert change
|
||||
shell: echo cert changed
|
||||
notify: service restart one
|
||||
when: ssl_cert_changed is defined and ssl_cert_changed
|
||||
handlers:
|
||||
- name: service restart one
|
||||
shell: echo service one restarted
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: subscribe for ssl cert change
|
||||
shell: echo cert changed
|
||||
when: ssl_cert_changed is defined and ssl_cert_changed
|
||||
notify: service restart two
|
||||
handlers:
|
||||
- name: service restart two
|
||||
shell: echo service two restarted
|
||||
~~~
|
||||
|
||||
However, this looks like a workaround of a feature that ansible should provide in a much cleaner way.
|
||||
|
||||
## Approaches
|
||||
|
||||
### Approach 1:
|
||||
|
||||
Provide new `subscribe` keyword on handlers:
|
||||
|
||||
~~~yaml
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: copy an ssl cert
|
||||
shell: echo cert has been changed
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
handlers:
|
||||
- name: service restart one
|
||||
shell: echo service one restarted
|
||||
subscribe: copy an ssl cert
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
handlers:
|
||||
- name: service restart two
|
||||
shell: echo service two restarted
|
||||
subscribe: copy an ssl cert
|
||||
~~~
|
||||
|
||||
### Approach 2:
|
||||
|
||||
Provide new `subscribe` on handlers and `publish` keywords in tasks:
|
||||
|
||||
~~~yaml
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: copy an ssl cert
|
||||
shell: echo cert has been changed
|
||||
publish: yes
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
handlers:
|
||||
- name: service restart one
|
||||
shell: echo service one restarted
|
||||
subscribe: copy an ssl cert
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
handlers:
|
||||
- name: service restart two
|
||||
shell: echo service two restarted
|
||||
subscribe: copy an ssl cert
|
||||
~~~
|
||||
|
||||
### Approach 3:
|
||||
|
||||
Provide new `subscribe` module:
|
||||
|
||||
A subscribe module could consume the results of a task by name, optionally the value to react on could be specified (default: `changed`)
|
||||
|
||||
~~~yaml
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: copy an ssl cert
|
||||
shell: echo cert has been changed
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- subscribe:
|
||||
name: copy an ssl cert
|
||||
notify: service restart one
|
||||
handlers:
|
||||
- name: service restart one
|
||||
shell: echo service one restarted
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- subscribe:
|
||||
name: copy an ssl cert
|
||||
react_on: changed
|
||||
notify: service restart two
|
||||
handlers:
|
||||
- name: service restart two
|
||||
shell: echo service two restarted
|
||||
~~~
|
||||
|
||||
|
||||
### Approach 4:
|
||||
|
||||
Provide new `subscribe` module (same as Approach 3) and `publish` keyword:
|
||||
|
||||
~~~yaml
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: copy an ssl cert
|
||||
shell: echo cert has been changed
|
||||
publish: yes
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- subscribe:
|
||||
name: copy an ssl cert
|
||||
notify: service restart one
|
||||
handlers:
|
||||
- name: service restart one
|
||||
shell: echo service one restarted
|
||||
|
||||
|
||||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- subscribe:
|
||||
name: copy an ssl cert
|
||||
notify: service restart two
|
||||
handlers:
|
||||
- name: service restart two
|
||||
shell: echo service two restarted
|
||||
~~~
|
||||
|
||||
### Clarifications about role dependencies and publish
|
||||
|
||||
When using service roles having the subscription handlers and the publish task (e.g. cert change) is defined in a depended role (SSL role) only the first service role running the "cert change" task as dependency will trigger the publish.
|
||||
|
||||
In any other service role in the playbook having "SSL role" as dependency, the task won't be `changed` anymore.
|
||||
|
||||
Therefore a once published "message" should not be overwritten or so called "unpublished" by running the same task in a followed role in the playbook.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Feedback is requested to improve any of the above approaches, or provide further approaches to solve this problem.
|
Loading…
Reference in a new issue