首页 > 解决方案 > Ansible:列表未定义时跳过循环

问题描述

示例剧本 -

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

解决方案


真正的问题是loop 需要一个列表,即使它是一个空列表。

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

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

由于您的 var 已定义,但None您需要使用第二个可选参数来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 声明。


推荐阅读