Wednesday, July 20, 2022

[FIXED] How to change var type to integer?

Issue

I am reading from a CSV file, register a variable and loop through the variable's list. It's as easy as below example:

---
- hosts: localhost
  vars:
    csv: |
      some;val;ues
      string;1;2
  tasks:
        
    - name: copy
      copy:
        content: "{{csv}}"
        dest: "vm.csv"
        
    - name: read csv
      community.general.read_csv:
        path: "vm.csv"
        delimiter: ";"
      register: vms
        
    - name: debug
      debug:
        var: vms

    - name: Trigger AWX
      awx.awx.workflow_launch:
        name: "Do the job!"
        extra_vars:
          some_string: "{{ item.some }}"
          an_integer: "{{ item.val }}"
          another_integer: "{{ item.ues }}"
      with_items: "{{ vms.list }}"

Now let's get into the issue. When triggering the last task, integers are required for an_integer and another_integer. Otherwise the API below will fail.

The problem: the Jinja2 template engine will ALWAYS return a string. an_integer: "{{ item.val | int }}", for example, won't change that behavior.

As you can see from the output of task 3 (debug), the values are already string when read from csv / registered.

ok: [localhost] => {
    "vms": {
        "changed": false,
        "dict": {},
        "failed": false,
        "list": [
            {
                "some": "string",
                "ues": "2",
                "val": "1"
            }
        ]
    }
}

How can I force a module parameter to be set as integer?


Solution

Thanks to Vladimir for his answer, on which this solution is based on.

Working example

Instead of passing each parameter on its own, the solution is to build a dictionary and pass it directly to extra_vars like below.

    - set_fact:
        vm_list: "{{ vm_list|d([]) + [vm] }}"
      loop: "{{ vms.list }}"
      vars:
        vm: "{{ {
          'some_string': item.some,
          'val': item.val|int,
          'ues': item.ues|int
          } }}"

    - name: Trigger AWX
      awx.awx.workflow_launch:
        name: "Do the job!"
        extra_vars: "{{ item }}"
      with_items: "{{ vm_list }}"

This keeps the dictionaries' value types and the API is happy.


Not working example

The below example will not work!

    - set_fact:
        vm_list: "{{ vm_list|d([]) + [vm] }}"
      loop: "{{ vms.list }}"
      vars:
        vm: "{{ {
          'some': item.some,
          'val': item.val|int,
          'ues': item.ues|int
          } }}"

    - name: Trigger AWX
      awx.awx.workflow_launch:
        name: "Do the job!"
        extra_vars:
          some_string: "{{ item.some }}"
          val: "{{ item.val|int }}"
          ues: "{{ item.ues|int }}"
      with_items: "{{ vm_list }}"

As the debug output shows it converts the values into strings, even if you add the int filter.

[...]
            "extra_vars": {
                "some_string": "string",
                "ues": "2",
                "val": "1"
[...]
    },
    "item": {
        "some": "string",
        "ues": 2,
        "val": 1
    },
[...]


Answered By - jay
Answer Checked By - Cary Denson (PHPFixing Admin)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.