Getting error with ansible_date_time.epoch when subtracting dates

Viewed 136

I am using ansible_date_time.epoch to calculate days since a server was built. I get the build date information from a csv file and trying to do a calculation, but I am getting an error.

serverInventory.csv:

serverA,,,,,2019-04-24 19:57:34
serverB,,,,,2019-04-26 19:47:01
serverC,,,,,2020-08-20 23:30:25

Hosts:

serverA
serverB
serverC

Tasks:

- name: List Server in current play
  debug:
    msg: "Item is {{ item }} Build date {{ lookup('csvfile', item + ' file=serverInventory.csv delimiter=, col=5') }}"
  loop: "{{ ansible_play_batch }}"

- name: Calculate  days since server build
  debug:
    msg:"{{ ((ansible_date_time.epoch | to_datetime('%Y-%m-%d %H:%M:%S')) - svrBuildDate).days }}"
  vars:
    svrBuildDate: "{{ lookup('csvfile', inventory_hostname + ' file=serverInventory.csv delimiter=, col=5')  }}"

Output:

TASK [common : List Server in current play] *********************************************************************************************************************************************
ok: [serverA] => {
    "msg": "Item is serverA Build date 2019-04-24 19:57:34"
}
ok: [serverB] => {
    "msg": "Item is serverB Build date 2019-04-26 19:47:01"
}
ok: [serverC] => {
    "msg": "Item is serverC Build date 2020-08-20 23:30:25"
}

TASK [common : Calculate  days since server build] **************************************************************************************************************************************
fatal: [serverA]: FAILED! => {"msg": "the field 'args' has an invalid value ({'_variable_params': u'msg:\"{{ ((ansible_date_time.epoch | to_datetime(\\'%Y-%m-%d %H:%M:%S\\')) - svrBuildDate).days }}\"'}), and could not be converted to an dict.The error was: time data '1655353270' does not match format '%Y-%m-%d %H:%M:%S'\n\nThe error appears to be in '/ansible/server_build/roles/common/tasks/main.yml': line 25, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Calculate  days since server build\n  ^ here\n"}
fatal: [serverB]: FAILED! => {"msg": "the field 'args' has an invalid value ({'_variable_params': u'msg:\"{{ ((ansible_date_time.epoch | to_datetime(\\'%Y-%m-%d %H:%M:%S\\')) - svrBuildDate).days }}\"'}), and could not be converted to an dict.The error was: time data '1655353271' does not match format '%Y-%m-%d %H:%M:%S'\n\nThe error appears to be in '/ansible/server_build/roles/common/tasks/main.yml': line 25, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Calculate  days since server build\n  ^ here\n"}
fatal: [serverC]: FAILED! => {"msg": "the field 'args' has an invalid value ({'_variable_params': u'msg:\"{{ ((ansible_date_time.epoch | to_datetime(\\'%Y-%m-%d %H:%M:%S\\')) - svrBuildDate).days }}\"'}), and could not be converted to an dict.The error was: time data '1655353273' does not match format '%Y-%m-%d %H:%M:%S'\n\nThe error appears to be in '/ansible/server_build/roles/common/tasks/main.yml': line 25, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Calculate  days since server build\n  ^ here\n"}
        to retry, use: --limit @/ansible/server_build/site.retry

PLAY RECAP ******************************************************************************************************************************************************************************
serverA             : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
serverB             : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
serverC             : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
1 Answers

In order to do computation on date, you need both elements to be datetime.
In your task, you are trying to subtract a string, from your CSV, to an epoch, which is of type AnsibleUnsafeText.

So you need:

  1. The current date, in a datetime format, which can be achieved with
    '%Y-%m-%d %H:%M:%S' | strftime | to_datetime
    
  2. The date from your CSV converted in a datetime, which can be achieved with
    lookup(
      'csvfile', inventory_hostname,
      file='serverInventory.csv', delimiter=',', col=5
    ) | to_datetime
    
  3. Then only you can subtract the two of them

So, we end up with a task like:

- name: Calculate  days since server build
  debug:
    msg: >-
      {{ 
         (
           currentDate | to_datetime 
           - dateFromInventory  | to_datetime
         ).days 
      }}
  vars:
    currentDate: "{{ '%Y-%m-%d %H:%M:%S' | strftime }}"
    dateFromInventory: >-
      {{
        lookup(
          'csvfile', inventory_hostname,
          file='serverInventory.csv', delimiter=',', col=5
        )
      }}

Which would, on your example CSV, yield:

ok: [serverA] => 
  msg: '1148'
ok: [serverB] => 
  msg: '1146'
ok: [serverC] => 
  msg: '664'
Related