Ansible:当列表未定义时跳过循环

问题描述 投票:0回答:2

示例剧本-

---
- hosts: localhost

  vars:
    lesson:
     name: Physics
     students:
      - Bob
      - Joe

  tasks:
     - name: Display student names
       debug:
         msg: '{{ item }}'
       loop: "{{ lesson.students }}"
       when: item | default("")

上面的剧本很适合输出学生姓名。

但是,如果输入发生变化(如下所示)以至于没有定义学生姓名,则会发生错误。如果根据下面的输入未定义列表,是否有一种简单的方法可以让剧本跳过此任务?我意识到如果输入指定 students: [],它会起作用,但由于此输入来自简单用户,他们不会知道这一点。非常感谢!

  vars:
    lesson:
     name: Physics
     students:

错误:致命:[本地主机]:失败! => msg: '传递给''loop''的无效数据,它需要一个列表,取而代之的是:。提示:如果您只传递了一个元素的列表/字典,请尝试将 wantlist=True 添加到您的查找调用或使用 q/query 而不是查找。

更新 - 我尝试了以下变体,但仍然出现相同的错误 -

---
- hosts: localhost

  vars:
    lesson:
     name: Physics
     students:

  tasks:
     - name: Display student names variation 1
       debug:
         msg: '{{ item }}'
       loop: "{{ lesson.students }}"
       when: lesson.students is iterable

     - name: Display student names variation 2
       debug: 
         msg: '{{ item }}'
       loop: "{{ lesson.students }}"
       when: lesson.students is not none

     - name: Display student names variation 3
       debug: 
         msg: '{{ item }}'
       loop: "{{ lesson.students }}"
       when: ( item | default("") ) or ( item is not none )
ansible
2个回答
6
投票

真正的问题是

loop
requires一个列表,即使它是一个空列表。

如果您的 var 是未定义/无/空字符串,它存在但不是列表,并且您的 when 条件将永远不会被评估,因为循环会在到达之前触发错误。

在这种情况下,您必须将 var 默认为空列表,这将导致相当于跳过任务的 0 大小循环。

由于您的 var 已定义,但

None
您需要使用 second 可选参数
default
以便空/假值也被替换

注意:我在下面的示例中使用了短别名

d
default

     - name: Display student names
       debug:
         msg: '{{ item }}'
       loop: "{{ lesson.students | d([], true) }}"

这里可以将错误扼杀在萌芽状态的一个好做法是通过以下任一方式进行连贯的数据声明:

  1. 根本不声明密钥并使用简单的默认值,即
    # ... #
    vars:
      lesson:
        name: Physics
    # ... #
           loop: "{{ lesson.students | d([]) }}"
    
    
  2. 为键声明一个空列表而不是
    None
    值,即
    # ... #
    vars:
      lesson:
        name: Physics
        students: []
    # ... #
           loop: "{{ lesson.students }}"
    
    

无论如何,我的第一个提议在这种情况下是最安全的,并且适用于所有上述 vars 声明。


0
投票

undefined
变量与具有
None
值的变量之间存在差异。

当你设置了变量名,但右侧留空。变量已定义,但它被设置为

NoneType
.

所以你的

when:
条件应该额外检查
NoneType

- hosts: localhost

  vars:
    lesson:
     name: Physics
     students:

  tasks:
     - name: Display student names
       debug:
         msg: '{{ item }}'
       loop: "{{ lesson.students }}"
       when: ( item | default("") ) or ( item is not none )

这将给:

skipping: [localhost] => (item=None)
© www.soinside.com 2019 - 2024. All rights reserved.