如何将变量类型更改为整数?

3
我正在从CSV文件中读取数据,注册一个变量并循环遍历其中的列表。就像下面这个简单的例子一样:
---
- 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 }}"


现在让我们来探讨一下这个问题。当触发最后一个任务时,需要为an_integeranother_integer提供整数类型的变量,否则下面的API将会失败。
问题所在:Jinja2模板引擎总是返回字符串。例如,an_integer: "{{ item.val | int }}"并不能改变这种行为。
正如您从第3个任务(调试)的输出中可以看到的那样,在从csv/注册表中读取时,值已经是字符串类型了。
ok: [localhost] => {
    "vms": {
        "changed": false,
        "dict": {},
        "failed": false,
        "list": [
            {
                "some": "string",
                "ues": "2",
                "val": "1"
            }
        ]
    }
}

如何强制一个模块参数设置为整数?


3
为什么您认为“an_integer: "{{ item.val | int }}"不会改变那种行为”? - Vladimir Botka
我已经明确地尝试过了。底层API响应说该字段必须是整数。另一种验证方法是使用debug模块。 - jay
1
您可以将项目转换为整数。请参见下面的答案。但是,提供整数或将字符串转换为整数之间没有区别,这一点令人担忧。 - Vladimir Botka
2个回答

2
列表中的项是字符串。例如:
    - debug:
        msg: |
          vms.list.0.val: {{ vms.list.0.val }} {{ vms.list.0.val|type_debug }}

使用yaml回调插件提供(请参见 shell> ansible-doc -t callback yaml

  msg: |-
    vms.list.0.val: 1 AnsibleUnicode

将列表中的项目转换为整数。先创建一个列表,例如:

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

提供

  _list:
  - some: string
    ues: 2
    val: 1

然后更新字典中的列表。
    - set_fact:
        vms: "{{ vms|combine({'list': _list}) }}"

提供

  vms:
    changed: false
    dict: {}
    failed: false
    list:
    - some: string
      ues: 2
      val: 1

调试任务将显示类型现在为整数

  msg: |-
    vms.list.0.val: 1 int

转换步骤按预期工作,将值转换为整数。但是在第4个任务中,当我必须将这些值传递给模块参数时,它就会出现问题。我所知道的唯一符号是“{{ item.val }}”,它将返回一个字符串,然后在底层API中失败。也许有另一种符号可以将变量传递给模块参数,但我不知道? - jay
解决方案可能是用正确的数据类型构建字典,然后直接将其传递给“extra_vars”,而不是为每个单独参数这样做。现在将尝试并稍后报告。 - jay

0

感谢 Vladimir 的答案,本解决方案基于此。

工作示例

不要逐个传递每个参数,而是构建一个字典并将其直接传递给 extra_vars,如下所示。

    - 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 }}"

这将保持字典的值类型,使API更加稳定。


错误示例

以下示例将无法工作

    - 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 }}"

正如调试输出所示,它将值转换为字符串,即使您添加了 int 过滤器。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接