首页 > 解决方案 > 如何处理 Ansible 循环中的空列表

问题描述

community.windows.win_dns_record上下文是在循环中使用跨不同服务器修改许多 DNS 区域记录。每个 DNS 服务器都有一个 var 文件host_vars。记录更改列表的变量是zone_records

有时服务器上没有任何更改,我想保留zone_records变量未定义,但我愿意将其设置为空列表或空字符串。

这里尝试通过以下方式使循环短路when: zone_records is iterable

- name: Remove zone records
  community.windows.win_dns_record:
    computer_name: "{{ remove.server_name }}"
    zone: "{{ remove.zone }}"
    name: "{{ remove.name }}"
    state: "{{ remove.state }}"
    type: "{{ remove.type }}"
  loop:
    "{{ query('dict', zone_records) }}"
  when:
    - zone_records is iterable
    - remove.state == 'absent'
  loop_control:
    loop_var: remove

上面的失败取决于zone_records是未定义,还是字符串而不是列表。
在后一种情况下,错误是:

传递给“循环”的无效数据,它需要一个列表

在有时没有列表或空列表的循环中应该如何处理列表?

标签: ansible

解决方案


这会发生,因为循环将在条件被考虑之前被处理。

也因为字符串在 Python中是可迭代的,因为简单地说,它是一个字符列表。

可迭代
一个能够一次返回其成员的对象。可迭代对象的示例包括所有序列类型(例如liststrtuple)和一些非序列类型(例如dict、文件对象)以及您使用__iter__()方法或使用__getitem__()实现序列语义的方法定义的任何类的对象。

来源:https ://docs.python.org/3/glossary.html#term-iterable

您可以使用循环定义本身中的条件表达式来解决此问题:

- hosts: all
  gather_facts: no
      
  tasks:
    - debug: 
        msg: "{{ item }}"
      loop: "{{ foo if foo is iterable and foo is not string else [] }}"
      vars:
        foo: 'bar'

将以跳过主机结束(因为else在条件表达式中传递了一个空列表):

PLAY [all] *******************************************************************************************************

TASK [debug] *****************************************************************************************************

PLAY RECAP *******************************************************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

尽管:

- hosts: all
  gather_facts: no
      
  tasks:
    - debug: 
        msg: "{{ item }}"
      loop: "{{ foo if foo is iterable and foo is not string else [] }}"
      vars:
        foo: 
          - 'bar'
          - 'baz'

将以预期结束:

PLAY [all] *******************************************************************************************************

TASK [debug] *****************************************************************************************************
ok: [localhost] => (item=bar) => {
    "msg": "bar"
}
ok: [localhost] => (item=baz) => {
    "msg": "baz"
}

PLAY RECAP *******************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

推荐阅读