ansibleansible-filter

How to convert an AnsibleUnsafeText HEX value to int?


I have a simple Ansible playbook that reads a HEX value (epoch time) from a log file then I would like to get the readable format using strftime but I can't get it to work.

Playbook example:

- debug:
    msg:
      - "Time = {{ '%Y-%m-%d %H:%M:%S' | strftime( item ) }}"
  with_lines: cat /tmp/log.file

I found that the returned value is defined as AnsibleUnsafeText, I tried to convert it to an integer but, still, it doesn't work.

Ansible version: 2.9


Solution

  • From your description I understand that you like to convert strings like 626698A0 into seconds. Lets assume there is hex.log file with Unix HEX timestamps

    626698A0
    626698B0
    626698C0
    626698D0
    626698E0
    626698F0
    

    and a test playbook like

    ---
    - hosts: localhost
      become: false
      gather_facts: true
    
      vars:
    
        HEX: 0x626698A0
        HEX_STRING: '626698A0'
    
      tasks:
    
      - name: Show vars type
        debug:
          msg:
            - "{{ HEX }} is {{ HEX | type_debug }} and HEX {{ '%#X' % HEX }}"
            - "{{ HEX_STRING }} is {{ HEX_STRING | type_debug }}"
    
      - name: Show values type
        debug:
          msg: "{{ item }} is {{ item | type_debug }}"
        with_lines: cat hex.log
    

    then it would result into an output of

    TASK [Show vars type] ******************
    ok: [localhost] =>
      msg:
      - 1650890912 is int and HEX 0X626698A0
      - 626698A0 is AnsibleUnicode
    
    TASK [Show values type] *************
    ok: [localhost] => (item=626698A0) =>
      msg: 626698A0 is AnsibleUnsafeText
    ok: [localhost] => (item=626698B0) =>
      msg: 626698B0 is AnsibleUnsafeText
    ok: [localhost] => (item=626698C0) =>
      msg: 626698C0 is AnsibleUnsafeText
    ok: [localhost] => (item=626698D0) =>
      msg: 626698D0 is AnsibleUnsafeText
    ok: [localhost] => (item=626698E0) =>
      msg: 626698E0 is AnsibleUnsafeText
    ok: [localhost] => (item=626698F0) =>
      msg: 626698F0 is AnsibleUnsafeText
    

    As of Ansible v2.10 it should be possible to use

    "{{ HEX_STRING | int(base=16) }}"
    

    whereby in Ansible v2.9 one would get an error

    TASK [Show values type] ************************************************************************************
    fatal: [localhost]: FAILED! =>
      msg: 'Unexpected templating type error occurred ...: do_int() got an unexpected keyword argument ''base'''
    

    Further Documentation and Q&A


    Regarding "Is there a way to convert the values coming from the log file from AnsibleUnsafeText to int?" and as a workaround in Ansible v2.9, it might be possible write an own filter plugin similar to other solutions here, in example version_sort. It would just be necessary to use an approach like in Convert HEX string to int in Python instead.

    After a short test with a hex2int.py filter plugin

    #!/usr/bin/python
    
    class FilterModule(object):
        def filters(self):
            return {
                'hex2int': self.hex2int,
            }
    
        def hex2int(self, hexString):
            intValue = int(hexString, 16)
            return intValue
    

    which one need to place under the path specified in ansible.cfg and filter_plugins =, I found it working

      - name: Show int values and type
        debug:
          msg: "{{ item | hex2int }} is {{ item | hex2int | type_debug }}"
        with_lines: cat hex.log
    

    and resulting into an output of

    TASK [Show int values and type] *************
    ok: [localhost] => (item=626698A0) =>
      msg: 1650890912 is int
    ok: [localhost] => (item=626698B0) =>
      msg: 1650890928 is int
    ok: [localhost] => (item=626698C0) =>
      msg: 1650890944 is int
    ok: [localhost] => (item=626698D0) =>
      msg: 1650890960 is int
    ok: [localhost] => (item=626698E0) =>
      msg: 1650890976 is int
    ok: [localhost] => (item=626698F0) =>
      msg: 1650890992 is int