I am working on a role where I want one task to be run at the end of the tasks file if and only if any of the previous tasks in that task file have changed.
For example, I have:
- name: install package
apt: name=mypackage state=latest
- name: modify a file
lineinfile: do stuff
- name: modify a second file
lineinfile: other stuff
- name: restart if anything changed
service: name=mypackage state=restarted
... and I want to only restart the service if an update has been installed or any of the config files have been changed.
How can I do this?
Best practice here is to use handlers.
In your role create a file handlers/main.yml
with the content:
- name: restart mypackage
service: name=mypackage state=restarted
Then notify this handler from all tasks. The handler will be notified only if a task reports a changed state (=yellow output)
- name: install package
apt: name=mypackage state=latest
notify: restart mypackage
- name: modify a file
lineinfile: do stuff
notify: restart mypackage
- name: modify a second file
lineinfile: other stuff
notify: restart mypackage
Handlers will be executed at the very end of your play. If you have other roles involved which depend on the restarted mypackage service, you might want to flush all handlers at the end of the role:
- meta: flush_handlers
Additionally have a look at the force_handlers setting. In case an error happens in any other role processed after your mypackge role, the handler would not be triggered. Set force_handlers=True
in your ansible.cfg
to still force your handlers to be executed after errors. This is a very important topic since when you run your playbook the next time the files will not be changed and therefore the handler not get notified, hence your service never restarted.
You can also do this without handlers but this is very ugly. You need to register the output of every single task so you can later check the state in the condition applied to the restart task.
- name: install package
apt: name=mypackage state=latest
register: mypackage_1
- name: modify a file
lineinfile: do stuff
register: mypackage_2
- name: modify a second file
lineinfile: other stuff
register: mypackage_3
- name: restart if anything changed
service: name=mypackage state=restarted
when: mypackage_1 is changed or mypackage_2 is changed or mypackage_3 is changed
It was possible to use mypackage_1 | changed till ansible 2.9
See also the answer to Ansible Handler notify vs register.