some float assigned via set_fact is converted to string

Viewed 312

I'm lost here. Using ansible-2.9.9-1.fc30.noarch and I do not understand why this somedata.aaa is converted to string by Ansible:

- hosts: localhost
  remote_user: root
  gather_facts: no
  vars:
    aaa:
      - 1.111
      - 2.222
      - 3.333
    bbb: 4.444
  roles:
  tasks:
    - set_fact:
        somedata:
          aaa: "{{ aaa | max | float }}"
          bbb: "{{ bbb }}"
    - debug:
        msg: "orig: {{ aaa | max | type_debug }}   aaa: {{ somedata.aaa | type_debug }}   bbb: {{ somedata.bbb | type_debug }}"
    - debug:
        var: somedata
    - debug:
         msg: "{{ somedata | to_nice_json }}"

This is the output:

TASK [debug] ******************************************************************
Monday 08 June 2020  17:06:32 +0200 (0:00:00.350)       0:00:00.376 *********** 
ok: [localhost] => {
    "msg": "orig: float   aaa: str   bbb: float"
}

TASK [debug] ******************************************************************
Monday 08 June 2020  17:06:33 +0200 (0:00:00.332)       0:00:00.708 *********** 
ok: [localhost] => {
    "somedata": {
        "aaa": "3.333",
        "bbb": 4.444
    }
}

TASK [debug] ******************************************************************
Monday 08 June 2020  17:06:33 +0200 (0:00:00.318)       0:00:01.027 *********** 
ok: [localhost] => {
    "msg": "{\n    \"aaa\": \"3.333\",\n    \"bbb\": 4.444\n}"
}

Why is somedata.aaa string and not a float? How to make it float?

1 Answers

max and float are jinja operations and by default jinja will always return a string. Note that float IS converting the number internally, jinja then just drops it in a string.

You can see this if you change 3.333 to 3:

aaa:
  - 1.111
  - 2.222
  - 3

With your code it converts to 3.0 - a float value:

"somedata": {
        "aaa": "3.0",
        "bbb": 4.444
}

You can force jinja to always return native types by adding jinja2_native = True to the defaults section of ansible.cfg. The code should now return what you expect:

TASK [debug] *************************
    "somedata": {
        "aaa": 3.333,
        "bbb": 4.444
    }
}

TASK [debug] *************************
    "msg": "{\n    \"aaa\": 3.333,\n    \"bbb\": 4.444\n}"
}

Just bear in mind this might have knock on affects on other parts of your code.

Related