# dynamic variable content

**URL:** <https://forum.ansible.com/t/dynamic-variable-content/37804>\
**Category:** Ansible Project\
**Created:** [March 23, 2023, 9:58am UTC](https://forum.ansible.com/t/dynamic-variable-content/37804 "2023-03-23T09:58:45Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dulhaver](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dulhaver/32/1061_2.png) [@dulhaver](https://forum.ansible.com/u/dulhaver)\
**Post date:** [March 23, 2023, 9:58am UTC](https://forum.ansible.com/t/dynamic-variable-content/37804/1 "2023-03-23T09:58:45Z")

</div>

I am trying to define a variable in defaults.yml with some kind of dynamic. Conrete creating a directory with the current timestamp at the end of the name.

&nbsp;&nbsp;&nbsp;data\_dir: /file/to/dir\_$(date +%F\_%H%M%S)

gives me exactly the directory name 'dir\_$(date +%F\_%H%M%S)' and not dir\_2023\_03\_23\_115122.

How can I achieve such?

---

<div class="post-metadata">

**Author:** ![dnmvisser](https://avatars.discourse-cdn.com/v4/letter/d/8e8cbc/32.png) [@dnmvisser](https://forum.ansible.com/u/dnmvisser)\
**Post date:** [March 23, 2023, 10:18am UTC](https://forum.ansible.com/t/dynamic-variable-content/37804/2 "2023-03-23T10:18:51Z")

</div>

You are using shell command inside an ansible vars file. That will not work.  
Take a look at [https://docs.ansible.com/ansible/latest/collections/ansible/builtin/strftime\_filter.html](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/strftime_filter.html)

---

<div class="post-metadata">

**Author:** ![Lnx\_Gnome](https://avatars.discourse-cdn.com/v4/letter/l/96bed5/32.png) [@Lnx\_Gnome](https://forum.ansible.com/u/Lnx_Gnome)\
**Post date:** [March 23, 2023, 11:05am UTC](https://forum.ansible.com/t/dynamic-variable-content/37804/3 "2023-03-23T11:05:13Z")

</div>

Templating + now()

➜ cat defaults.yml  
current: “{{ now(‘True’,‘%F\_%H%M%S’) }}”

➜ cat datetime.yml

# make a variable with the current date

- hosts: localhost  
vars\_files:
- ./defaults.yml  
tasks:
- name: echo  
ansible.builtin.debug:

var: current

➜ ansible-adhoc ansible-playbook ./datetime.yml  
…  
TASK [echo] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost] =\> {  
“current”: “2023-03-23\_110205”  
}

---

<div class="post-metadata">

**Author:** ![dulhaver](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/dulhaver/32/1061_2.png) [@dulhaver](https://forum.ansible.com/u/dulhaver)\
**Post date:** [March 23, 2023, 5:19pm UTC](https://forum.ansible.com/t/dynamic-variable-content/37804/4 "2023-03-23T17:19:18Z")

</div>

ok that works to some extent. But I probably seem to need someting not toooo dynamic after all :-/

I did not get this entirely when we started.

I need to create the variable value once at the beginning of the playbook but need to get back to it later down the road with the same initial value. So more like it works inside a bash script (despite the fact it's a playbook).

I can think of a workaround for my current task, but still would be wondering whether this can be done.

---

<div class="post-metadata">

**Author:** ![Lnx\_Gnome](https://avatars.discourse-cdn.com/v4/letter/l/96bed5/32.png) [@Lnx\_Gnome](https://forum.ansible.com/u/Lnx_Gnome)\
**Post date:** [March 24, 2023, 2:20am UTC](https://forum.ansible.com/t/dynamic-variable-content/37804/5 "2023-03-24T02:20:17Z")

</div>

If you can use a file (defaults.yml or whatever) for only this variable, it’s easy to check for the file’s existence, write to it if it doesn’t exist, and then just use it again and again later on. It will persist until removed.

# make a variable with the current date

- name: preflight  
hosts: localhost  
tasks:

- name: check for existing date\_saved yaml file  
stat:  
path: ./defaults.yml  
register: date\_saved

- name: write current date to date.saved file  
when: not date\_saved.stat.exists  
copy:  
content: “data\_dir: "/file/to/dir\_{{ now(‘True’,‘%F\_%H%M%S’) }}"”  
dest: ./defaults.yml

- name: main  
hosts: localhost  
vars\_files:

- ./defaults.yml

tasks:

- name: echo  
ansible.builtin.debug:  
var: data\_dir

➜ **rm defaults.yml**  
➜ **ansible-playbook ./datetime.yml**  
PLAY [preflight] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [check for existing date\_saved yaml file] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost]

TASK [write current date to date.saved file] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
**changed** : [localhost]

PLAY [main] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [echo] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost] =\> {  
“data\_dir”: “/file/to/dir\_2023-03-24\_021041”  
}

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
localhost : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

➜ **ansible-playbook ./datetime.yml**  
PLAY [preflight] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [check for existing date\_saved yaml file] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost]

TASK [write current date to date.saved file] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
**skipping** : [localhost]

PLAY [main] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [echo] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
ok: [localhost] =\> {  
“data\_dir”: “/file/to/dir\_2023-03-24\_021041”  
}

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 24, 2023, 3:30pm UTC](https://forum.ansible.com/t/dynamic-variable-content/37804/6 "2023-03-24T15:30:29Z")

</div>

There is an undocumented\* but intentional interaction between **ansible.builtin.set\_fact** and the **run\_once** parameter. You are in luck, because it solves exactly this problem in a clean way. When you use **set\_fact** to create a variable with **run\_once: true** , it sets the variable for all hosts in the play. So you can say:

```auto
 **- name: Snarf the playbook start time on all host** <b>s
</b> **ansible.builtin.set_fact:** **ansible_playbook_starttime: "{{ now('True', '%F_%H%M%S') }}"**  **run_once: true**

```

After this step runs, all hosts will have the same **ansible\_playbook\_starttime** variable with a fully templated out value.

This differs from, say, setting the same variable in **group\_vars/all** or in your playbook’s **vars:** section. If you create the variable any of these other ways, “lazy evaluation” will cause the variable’s template to be re-evaluated each time it is used. In contrast, **set\_fact** will produce ‘static’ values, i.e. not subject to or requiring further template evaluation on subsequent uses.

\*Arguably one could read **ansible-doc -t module set\_fact** with a lawyer’s eye and discern this behavior, but I’ve read it a dozen or more times and never once did it occur to me that **run\_once: true** would have this effect across all hosts. There is a [bug report](https://github.com/ansible/ansible/issues/47509) about it from October 2018 that spells it out. Otherwise it’s one of those serendipitous discoveries that either makes your day or ruins your weekend.
