Idempotence and Random Variables in Ansible

Just in case you don't have ansible >= 2.3 available, a hashed approach using jinja2:

{{ (inventory_hostname |hash('md5')|int(0, 16)) % 60 }}

As of Ansible version 2.3, it’s possible to initialize the random number generator from a seed. This way, you can create random-but-idempotent numbers:

"{{ 59 |random(seed=inventory_hostname) }} * * * * root /script/from/cron"

Source: random number filter

I've used this pattern to produce random cron start times with:

  1. different minutes on different target servers
  2. different minutes for different days on the same server (randomness)
  3. the same minute for the same day and server when repeatedly running Ansible (idempotence)

Requires Ansible >=2.3:

 cron:
    name: "{{some_name}}_{{item.day}}"
    state: present
    job: "{{some_job}}"
    weekday: "{{item.day}}"
    hour: "{{item.hour}}"
    minute: "{{59|random(seed=inventory_hostname + item.dow)}}"
  with_items:
 - { day: 0, hour: 3, dow: "sunday" }
 - { day: 1, hour: 7, dow: "monday" }
 - { day: 2, hour: 1, dow: "tuesday" }
 - { day: 3, hour: 5, dow: "wednesday" }
 - { day: 4, hour: 2, dow: "thursday" }
 - { day: 5, hour: 4, dow: "friday" }
 - { day: 6, hour: 7, dow: "saturday" }

Instead of a random value, you could get something related to the node, like an hash of the hostname or the last byte of the ip address.

This is an example:

- name: Get a pseudo-random minute 
  shell: expr $((16#`echo "{{inventory_hostname}}" | md5sum | cut -c 1-4`)) % 30
  register: minute
  changed_when: false

Tags:

Cron

Ansible