Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idempotence and Random Variables in Ansible

Tags:

cron

ansible

Is there a way to guarantee idempotence for playbooks that use randomly generated variables?

For example, I want to setup my crontabs to trigger emails on multiple servers at different times, so I create random integers using ansible's set_fact module:

  tasks:
  - set_fact:
      first_run_30="{{ 30 | random }}"
    run_once: yes

Then apply those generated variables to my crontab using ansible like so:

   - name: Setup cron30job
    cron: name=cron30job minute={{first_run_30}},{{first_run_30 | int + 30}} job='/bin/bash /cron30job.sh' state=present user=root
    environment:
      MAILTO: '[email protected]'
      MAILFROM: '[email protected]'

This works very well, however, ansible's indempotence principle is, I believe, broken using this strategy because each time a play is made you see a change:

TASK: [Setup cron30job] ***************************************** 
changed: [127.0.0.1]

Further, in the crontab checking under root each time during three separate runs:

[ansible]# cat /var/spool/cron/root 
#Ansible: cron30job
5,35 * * * * /bin/bash /sw/test/cron30job.sh
#Ansible: cron30job
9,39 * * * * /bin/bash /sw/test/cron30job.sh
#Ansible: cron30job
6,36 * * * * /bin/bash /sw/test/cron30job.sh

If there is a workaround, or maybe indempotence just will not be possible in my scenario, I would like to know.

like image 548
Jake88 Avatar asked Oct 27 '15 22:10

Jake88


People also ask

What does Idempotent mean in ansible?

The resource models are idempotent meaning change commands are not run unless needed, and Ansible will bring the system back to a desired state regardless of the actual state – rather than you having to tell it how to get to the state.

What is Idempotent playbook?

Idempotence is a term given to certain operations in mathematics and computer science whereby: an action which, when performed multiple times, has no further effect on its subject after the first time it is performed.

How do you achieve Idempotency in ansible?

Introducing Idempotence using Ansible Handlers One way of making our task's working idempotent is to ensure it runs only based on a certain condition. In our case, we can consider restarting HTTPD only if the configuration file of the target node is being changed in any way.

How are variables defined in ansible?

To define a variable in a playbook, simply use the keyword vars before writing your variables with indentation. To access the value of the variable, place it between the double curly braces enclosed with quotation marks. In the above playbook, the greeting variable is substituted by the value Hello world!


1 Answers

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" }
like image 86
René Pijl Avatar answered Sep 27 '22 19:09

René Pijl