DEV Community

Cover image for Consequences of updating cron jobs within Ansible's playbook
Maroje Macola for Bornfight

Posted on • Edited on

Consequences of updating cron jobs within Ansible's playbook

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
tamasgal profile image
Tamas Gal

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 ;)

Collapse
 
wnbsmart profile image
Maroje Macola

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 :)

Collapse
 
renatoruk profile image
Renato Ruk

Thanks for sharing! As I am currently learning to use Ansible, this will surely come in handy.
The fix is also pretty elegant 👍🏻

Collapse
 
wnbsmart profile image
Maroje Macola

Glad to be of help!
Good luck in your "Ansible adventures" 💪🏻

Collapse
 
emmanuelmeric profile image
Emmanuel Meric

Nice article !