Hello fellow dev.to readers!
Should you read this?
Today, I am writing about a smaller issue which occurred to us recently. More precisely, I will show you the pitfall and how we dealt with it.
If you have written a cron job within Ansible's playbook, but have never updated its values afterwards, you are a perfect reader for this post. Other than that, if you are interested in Ansible and want to learn something new, read on!
Cron job example
---
- hosts: all
tasks:
- name: Send emails about expiry dates
cron:
name: "Send expiry date emails (runs each day, 15 minutes after midnight)"
minute: "15"
hour: "0"
job: "php path/to/console email-expiry-dates/send-email"
So, what do we have here?
It's a simple job which runs every day at 00:15 per server's time and executes a command which sends some emails.
If we would want to get a list of all cron's on the server, we could execute crontab -l
on the server, and get something like this:
#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight)
15 0 * * * php path/to/console email-expiry-dates/send-email
Updating cron job
Let's say that server's current time zone is UTC+00:00, and a change request comes up for the existing cron job, something like:
Emails should be delivered right after midnight in New York's time zone
What did we do to implement necessary changes? Updated cron job's execution time, but also its name (or we can say, the description):
---
- hosts: all
tasks:
- name: Send emails about expiry dates
cron:
name: "Send expiry date emails (runs each day, 15 minutes after midnight in New York's time zone)"
minute: "15"
hour: "5"
job: "php path/to/console email-expiry-dates/send-email"
After deploying and listing server's cron jobs, we expected to have a single job as before, but with updated values, respectively. This was the actual result:
#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight)
15 0 * * * php path/to/console email-expiry-dates/send-email
#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight in New York's time zone)"
15 5 * * * php path/to/console email-expiry-dates/send-email
What happened after update?
The result was 2 cron jobs. The old one stayed as is and the new one, with different parameters, was added to the list. Therefore, the same command was being executed 2 times a day, which definitely was not part of the acceptance criteria.
Since the name was changed, Ansible recognised this as a new cron job. This resulted in an unsynchronised state between server's and playbook's cron jobs.
Fixing the unexpected problem
---
- hosts: all
tasks:
- name: Old (Send emails about expiry dates)
cron:
name: "Send expiry date emails (runs each day, 15 minutes after midnight)"
minute: "15"
hour: "0"
job: "php path/to/console email-expiry-dates/send-email"
state: absent
- name: Send emails about expiry dates
cron:
name: "Send expiry date emails (runs each day, 15 minutes after midnight in New York's time zone)"
minute: "15"
hour: "5"
job: "php path/to/console email-expiry-dates/send-email"
As visible above, we tried to be in sync with the server, by adding another cron job (with old values). Besides that, we added an additional parameter to the old cron job - state: absent
, which disabled its execution by removing it from the list of cron jobs on the server.
After deploying this fix to the server, this was a final result after listing cron jobs:
#Ansible: Send expiry date emails (runs each day, 15 minutes after midnight in New York's time zone)"
15 5 * * * php path/to/console email-expiry-dates/send-email
Yaay! A single cron job with all parameters set correctly 🎉
Conclusion
Changing a cron job's name will not result in an update of the existing cron job. Its name is some sort of an ID, and therefore should not be changed (in most cases). But, what we can do, is play around with tasks' name property, since it will not lead to the problem we occurred :)
Do you have any tips regarding this topic? I would be glad to hear them!
Top comments (5)
Interesting, thanks for the wrap-up! Btw. I'd highly recommend using different files instead, via the cron_file parameter. This way, the jobs are isolated in /etc/cron.d (of course, applicable to other configurations as well) and you don't run into the trouble of having leftovers in a file, which could potentially be managed by multiple tasks. (happened to me ;)
Hey Thomas, thanks for mentioning
cron_file
parameter, haven't seen it before!If I encounter this situation again, this could be very handy, especially regarding leftovers :)
Thanks for sharing! As I am currently learning to use Ansible, this will surely come in handy.
The fix is also pretty elegant 👍🏻
Glad to be of help!
Good luck in your "Ansible adventures" 💪🏻
Nice article !