I would like to have a timestamp variable, which is the same across across all hosts. (I include this in the name of directories: it must be the same on all hosts)
My initial idea was to add a declaration into group_vars/all.yml, since that has a relatively high precedence and should be shared.
group_vars/all.yml:
my_timestamp: "{{ ansible_date_time.date }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"
When tried, the values were different across hosts, making my directory structure inconsistent.
I suspect this is because the variable is only evaluated lazily, when the referred ansible_date_time
object already has a different value on each host, depending on the exact moment execution reaches the variable reference and resolves the value.
The same issue happens when I try to set_fact
in my playbook, at the very beginning.
site.yml:
---
# This playbook performs the deployment
- name: Prepare playbook settings
hosts: all
tasks:
- name: Generate my timestamp
set_fact:
my_timestamp: "{{ ansible_date_time.date }}{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"
The question is: how could I set a constant, shared timestamp, which is the same on all nodes during the whole execution of a playbook? What would be the clean Ansible way of generating a consistent, constant time-stamp? Without passing as a command line argument, printing to a file and the reading back the value etc.
I am on Ansible 2.9.23.
Your base problem is that, using set_fact
or not, you are parsing a value that is populated in the gathered facts for each host. Since the ssh connection to your targets will never happen at the exact same time, each host will have different values
The solution is to use one single timestamp from one single host for all of them. One way is to get it from the controller (localhost
) but you can decide to get it elsewhere (i.e. the first host in your group during your deploy play using set_facts
and run_once
for example).
Here is the idea using the controller. Adapt to your own requirements
---
- name: Make sure we gather facts from localhost
hosts: localhost
- name: Make my actual deployment
hosts: all
vars:
# declare timestamp using localhost values
my_timestamp: >-
{{
hostvars['localhost'].ansible_date_time.date
}}{{
hostvars['localhost'].ansible_date_time.hour
}}{{
hostvars['localhost'].ansible_date_time.minute
}}{{
hostvars['localhost'].ansible_date_time.second
}}
tasks:
- name: Make sure timestamp value is the same everywhere
debug:
var: my_timestamp
#... rest of your tasks...