为什么Ansible将列表转换为字符串?

时间:2018-09-05 08:02:07

标签: ansible jinja2

Ansible在合并列表时意外地将列表转换为字符串,有人可以帮我解释原因吗?

剧本:

---
- hosts: localhost
  vars:
    list1:
      - aaa: 'aaa'
  tasks:
    - set_fact:
        a: 'asdfg'
    - set_fact:
        list2: "{{ list1|d([]) + [ hostvars['localhost']['a']] }}"
    - debug: var=list2
    - set_fact:
        list3: "{{ list1|d([]) + [ hostvars['localhost']['undefined variable']] }}"
    - debug: var=list3

这是播放结果(忽略了不必要的部分):

TASK [debug] *************************************************************************************************************************************************************************************************************************************************
Wednesday 05 September 2018  09:52:31 +0200 (0:00:00.071)       0:00:00.203 ***
ok: [localhost] => {
    "list2": [
        {
            "aaa": "aaa"
        },
        "asdfg"
    ]
}

...

TASK [debug] *************************************************************************************************************************************************************************************************************************************************
Wednesday 05 September 2018  09:52:31 +0200 (0:00:00.085)       0:00:00.345 ***
ok: [localhost] => {
    "list3": "[{'aaa': 'aaa'}, Undefined]"
}

PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=5    changed=0    unreachable=0    failed=0

第二个调试任务输出字符串而不是预期的dict。这是我不理解的正确行为,还是应该提交错误?

1 个答案:

答案 0 :(得分:2)

此答案描述了高达2.6.x的Ansible的状态。 Ansible v2.7中有一个movement支持native Python objects


  

Ansible为什么将列表转换为字符串?

Ansible是在您的示例中将任何列表转换为字符串。


Ansible获取数据:

  1. 来自YAML解析器

    这些可以是:列表,字典,标量(字符串,布尔值或数字值)。

  2. 来自其他来源(例如:Jinja2,清单,CLI Extravars)

    任何其他来源的数据都是字符串


由于Jinja2总是返回字符串,因此您可以在头部计算结果并将值作为YAML引用的标量(由Ansible解释为字符串)传递:

  • 上面的第一个任务等效于:

    - set_fact:
        list2: "[{'aaa': 'aaa'}, 'asdfg']"
    

    Ansible获取字符串(不是列表)并尝试解释它。它会找到与列表匹配的JSON字符串,并创建一个列表对象。

  • 第二项任务等同于:

    - set_fact:
        list3: "[{'aaa': 'aaa'}, Undefined]"
    

    您在这里观察到的是Jinja2用带有字符串Undefined(并且不引用该字符串)的具有未定义值的元素替换列表。

    Ansible获取字符串,并尝试对其进行解释。它找不到合适的数据结构 * ,并创建了一个字符串对象。


* 在一种特殊情况下,如果存在一个名为Undefined的变量,则Ansible将用该变量值替换未引用的Undefined并创建一个列表对象。