Over the past month I have been rewriting some cron scripts to enhance monitoring and observability. I’ve also been refactoring my ansible playbooks to handle deploying these scripts in a consistent fashion. Ansible ships with the cron module which makes this process a breeze. The cron module has all of the familiar cron attributes (hour, minute, second, program to run, etc.) and takes the following form:
- name: Cron job to prune old elasticsearch indexes
cron:
name: cleanup-elasticsearch-indexes
minute: 0
hour: 0
job: /scripts/curator/curator_clean_logs.sh
state: present
user: curator
When I first played around with this module I noticed that each playbook run would result in a cron entry being added. So instead of getting one curator log cleanup job when the play is executed I would get a one entry per run. This is obviously very bad. When I read back through the cron module documentation I came across this little nugget for the “name” parameter:
Note that if name is not set and state=present, then a new crontab entry will always be created, regardless of existing ones.
Ansible uses the name to tag the entry and if the tag already exists a new cron job won’t be added to the system (in case your interested this is implemented by the find_job() method in cron.py). Small subtleties like this really bring to light the importance of a robust test environment. I am currently using vagrant to solve this problem but there are also a number of solutions documented in the Ansible testing strategies guide.