dynamic variable content

36 views
Skip to first unread message

dulh...@mailbox.org

unread,
Mar 23, 2023, 5:59:04 AM3/23/23
to ansible...@googlegroups.com
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.

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?

Dick Visser

unread,
Mar 23, 2023, 6:19:40 AM3/23/23
to ansible...@googlegroups.com
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
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/403472752.247990.1679565525283%40office.mailbox.org.

Lnx Gnome

unread,
Mar 23, 2023, 7:05:35 AM3/23/23
to ansible...@googlegroups.com
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"
}




dulh...@mailbox.org

unread,
Mar 23, 2023, 1:19:36 PM3/23/23
to ansible...@googlegroups.com
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.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/CAF8BbLb-QBXJpjBwwXbZR84NCVh7eXFCAgcpEok4tXt2uCahRQ%40mail.gmail.com.

---
gunnar wagner | fichtestr. 1, 19386 lübz | fon: 0176 7808 9090

LnxGnome

unread,
Mar 23, 2023, 10:20:17 PM3/23/23
to Ansible Project
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"
}


On Thursday, March 23, 2023 at 1:19:36 PM UTC-4 dulh...@mailbox.org wrote:
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.

Todd Lewis

unread,
Mar 24, 2023, 11:30:44 AM3/24/23
to ansible...@googlegroups.com, uto...@gmail.com
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:
    - name: Snarf the playbook start time on all hosts
      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 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.


On 3/23/23 1:19 PM, dulhaver via Ansible Project wrote:
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.


On 03/23/2023 11:18 AM CET Dick Visser <dnmv...@gmail.com> wrote:

 
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


On Thu, 23 Mar 2023 at 10:58, dulhaver via Ansible Project
<ansible...@googlegroups.com> wrote:
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.

   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?
-- 
Todd
Reply all
Reply to author
Forward
0 new messages