【问题标题】:Ansible: Skip loop when list is undefinedAnsible:列表未定义时跳过循环
【发布时间】:2020-09-22 11:00:52
【问题描述】:

示例剧本 -

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

【问题讨论】:

  • “loop”指令在“when”条件之前计算。

标签: ansible


【解决方案1】:

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

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

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

由于您的 var 已定义但 None 您需要使用 second optional parameter to default 以便也替换空/假值

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

     - 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 声明。

【讨论】:

  • 只有对我有用的答案
【解决方案2】:

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)

【讨论】:

  • 感谢您的回复。我对此进行了测试,但仍然出现相同的错误。我的 ansible 版本是 2.9.4。
  • lessons.students 存在但为 None 时这将不起作用(如 OP 的答案,您是否理解),因为首先评估循环并将触发错误(即“我需要一个列表!! !!") 在达到任何条件之前。看我的回答。
猜你喜欢
  • 2020-06-28
  • 1970-01-01
  • 2016-10-24
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 2019-08-30
  • 1970-01-01
相关资源
最近更新 更多