I've been looking around like crazy to find a solution to this but so far I've been unsuccessful : Calculate number of days between an inventory variable and an Ansible fact.
I have no issue when I manually set both variable, both are recognized as a date and I can work my may around from there like so : (this is the expected output)
Task working between 2 manually set variables:
---
- hosts: localhost
vars:
prev_date: 2020-12-01
cur_date: 2020-12-31
tasks:
- name: prev_date debug
debug:
msg:
- "prev_date: {{ prev_date }}"
- "prev_date type: {{ prev_date | type_debug }}"
- name: cur_date debug
debug:
msg:
- "cur_date: {{ cur_date }}"
- "cur_date type: {{ cur_date | type_debug }}"
# This is the output I want to get but I want cur_date from a dynamic source (fact or shell through register)
- name: Calculate number of days between prev_date and cur_date (intended result)
debug:
msg: "Number of days = {{ (cur_date - prev_date).days }}"
Working output:
TASK [prev_date debug] *************************************************************************************************************************************************
Thursday 31 December 2020 12:55:28 +0100 (0:00:00.227) 0:00:00.227 *****
ok: [localhost] => {
"msg": [
"prev_date: 2020-12-01",
"prev_date type: date"
]
}
TASK [cur_date debug] **************************************************************************************************************************************************
Thursday 31 December 2020 12:55:29 +0100 (0:00:00.249) 0:00:00.476 *****
ok: [localhost] => {
"msg": [
"cur_date: 2020-12-31",
"cur_date type: date"
]
}
TASK [Calculate number of days between prev_date and cur_date (intended result)] ***************************************************************************************
Thursday 31 December 2020 12:55:29 +0100 (0:00:00.144) 0:00:00.621 *****
ok: [localhost] => {
"msg": "Number of days = 30"
}
Now when I want to use ansible fact to get the current date dynamically on each run (ansible_date_time.date
) because of the variables type
Sample of tasks to reproduce the error
- name: Value and type of ansible_date_time.date
debug:
msg:
- "ansible_date_time.date: {{ ansible_date_time.date }}"
- "ansible_date_time.date type: {{ ansible_date_time.date | type_debug }}"
# Failing due to conditional not working with attribute not being date on ansible_date_time.date
- name: Calculate number of days between ansible_date_time.date
debug:
msg:
- "Number of days = {{ (ansible_date_time.date - prev_date).days }}"
I get the following output and error:
TASK [New source ansible fact date] ************************************************************************************************************************************
Thursday 31 December 2020 13:06:41 +0100 (0:00:00.143) 0:00:00.741 *****
ok: [localhost] => {
"msg": [
"ansible_date_time.date: 2020-12-31",
"ansible_date_time.date type: AnsibleUnsafeText"
]
}
TASK [Calculate number of days between ansible_date_time.date] *********************************************************************************************************
Thursday 31 December 2020 13:06:41 +0100 (0:00:00.150) 0:00:00.892 *****
fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on (Number of days = {{ (ansible_date_time.date - prev_date).days }}): unsupported operand type(s) for -: 'AnsibleUnsafeText' and 'datetime.date'"}
I tried find ways to create a new variable out of ansible_date_time.date
but I was unable to convert it to datetime.date
if that's even possible.
ansible_date_time.date
is a string, so you will have to convert it to a date
or a datetime
.
Surprisingly enough, Ansible does not have any means to convert a string to a date
right away, but you can convert it to a datetime
using the to_datetime
filter.
Then, because prev_date
contains a date
and not a datetime
, you can convert the datetime
you just created to a date
via the date()
function of Python's datetime
.
So the playbook would be:
- hosts: all
gather_subset:
- min
tasks:
- debug:
msg: >-
{{
(
(ansible_date_time.date | to_datetime('%Y-%m-%d')).date()
- prev_date
).days
}}
vars:
prev_date: 2020-12-01
Which will give:
ok: [localhost] =>
msg: '30'