Ansible – Using Command Output in ini_file Value

ansible

I wanted to set a value inside a ini_file, but this value is an MD5 hash of the current time. (I am not afraid of accidentally replacing the value, or magically running it twice and having the same value in two different servers.)

This is what I tried, but got only the command as the value in the file (not sure why I thought it would work…):

- name: Replace HardwareID with new MD5
      ini_file:
        path: /etc/app/config.ini
        section: DEFAULT
        option: hardware_token
        value: $(date | md5sum | cut -d" " -f1)

Is there a simple way to make it work?

Best Answer

Q: "How to use the output of command inside Ansible ini_file value?"

A: Register the result of the command and use it as the value, e.g.

- hosts: test_24
  gather_facts: false
  tasks:
    - shell: 'date | md5sum | cut -d" " -f1'
      register: result
      check_mode: false
    - debug:
        var: result
    - name: Replace HardwareID with new MD5
      ini_file:
        path: etc/app/config.ini
        section: DEFAULT
        option: hardware_token
        value: "{{ result.stdout }}"

gives (running with --check --diff)

TASK [Replace HardwareID with new MD5] ***********************************
--- before: etc/app/config.ini (content)
+++ after: etc/app/config.ini (content)
@@ -0,0 +1,3 @@
+
+[DEFAULT]
+hardware_token = ba3f11c4f1ecfe9d1e805dc8c8c8b149

changed: [test_24]

It's easier to use Ansible facts if you want to use data and time as the input. For example, the dictionary ansible_date_time keeps the date and time if you gather the facts. In the playbook, we set gather_facts: false. ​Therefore the dictionary is not defined

    - debug:
        var: ansible_date_time.iso8601

gives

ok: [test_24] => 
  ansible_date_time.iso8601: VARIABLE IS NOT DEFINED!

You'll have to either gather the facts gather_facts: true when you start the play or run setup, e.g.

    - setup:
        gather_subset: min
    - debug:
        var: ansible_date_time.iso8601

gives

ok: [test_24] => 
  ansible_date_time.iso8601: '2021-07-29T21:32:26Z'

This is not very practical because to get the current time you have to run setup. Instead, the filter strftime gives you always the current time, e.g.

    - debug:
        msg: "{{ '%Y-%m-%d %H:%M:%S' | strftime }}"

    - name: Replace HardwareID with new MD5
      ini_file:
        path: etc/app/config.ini
        section: DEFAULT
        option: hardware_token
        value: "{{'%Y-%m-%d' | strftime | hash('md5') }}"

gives

TASK [debug] ***************************************************************
ok: [test_24] => 
  msg: '2021-07-29'

TASK [Replace HardwareID with new MD5] *************************************
--- before: etc/app/config.ini (content)
+++ after: etc/app/config.ini (content)
@@ -0,0 +1,3 @@
+
+[DEFAULT]
+hardware_token = 5847924805aa614957022ed73d517e7e

As a side note: Using this hash might be very quick searching if the date-time (in granularity of seconds) is the index.