【问题标题】:Ansible how to skip the loop if the list is empty如果列表为空,Ansible 如何跳过循环
【发布时间】:2020-06-28 17:26:53
【问题描述】:

我正在运行 Ansible,并尝试完成此任务。我已经将变量“docker_registries”的默认值定义为一个空列表:docker_registries: [] 我注意到如果列表为空,我会在运行 ansible playbook 时出错。这是我得到的错误:

致命:[***.cloudapp.azure.com]:失败! => {“msg”:“传递给'循环'的无效数据,它需要一个列表,而是得到这个:无。提示:如果您传递了一个只有一个元素的列表/字典,请尝试将wantlist = True添加到您的查找调用中或者使用 q/query 而不是查找。"}

我正在尝试添加条件,即如果“docker_registries”为空,则任务继续执行而不会引发错误。 这是此任务的代码:

- name: Log into additional docker registries, when required
  command: docker login -u {{item.username}} -p {{item.password}} {{item.server}}
  become: true
  loop: "{{docker_registries}}"

我尝试将循环更改为loop: "{{ lookup(docker_registries, {'skip_missing': True})}}" 但我得到了错误

任务执行期间发生异常。看到完整的 回溯,使用 -vvv。错误是:AttributeError:'NoneType'对象 没有属性“低”致命: [***.cloudapp.azure.com]:失败! => {"msg": "模块执行过程中出现意外失败。", "stdout": ""}

我对此很陌生。有人可以帮忙吗?

【问题讨论】:

  • 至少根据错误,您实际上并没有将空列表传递给loop:,而是传递了null 值(又名None);无论哪种情况,您都可以使用default filter 取得一些成功,如loop: "{{ docker_registries | default([]) }}"
  • 我之前确实添加了默认值,但没有运气。添加后出现此错误:致命:[atefeh-atefeh-domain-lm0.centralus.cloudapp.azure.com]:失败! => {"msg": "传递给“循环”的无效数据,它需要一个列表,而是得到这个:. 提示:如果您传递了一个只有一个元素的列表/字典,请尝试将 wantlist=True 添加到您的查找调用或使用 q/query 而不是查找。"}
  • 如果您共享定义空列表的默认值或将空列表的默认值传递给 docker_registries 变量的位置,将会有所帮助。如果它是空列表,它将完全跳过任务。如果它是无,那么你会得到错误。
  • 快速问题:@mdaniel 的想法在这种情况下是否有效,变量已定义但值为 Nonedefault 过滤器会应用还是默认只适用于完全未定义的变量?
  • 可以,但需要将the "boolean" argument 设置为true:hello {{ None | default("world", True) }}

标签: loops variables ansible yaml jinja2


【解决方案1】:

您可以将when statementiterable Jinja 测试结合使用。
因为,好吧,如果你想循环你的变量,那么它应该是可迭代的。

- name: Log into additional docker registries, when required
  command: docker login -u {{ item.username }} -p {{ item.password }} {{ item.server }}
  become: true
  loop: "{{ docker_registries }}"
  when: docker_registries is iterable

根据变量的内容,when 条件仍然无法解决问题,因为传递给loop 的数据的有效性将首先被考虑。

也就是说,您可以在循环声明本身中使用conditional expression 来解决这个问题:

- name: Log into additional docker registries, when required
  command: docker login -u {{ item.username }} -p {{ item.password }} {{ item.server }}
  become: true
  loop: "{{ docker_registries if docker_registries is iterable else [] }}"

还要注意,字符串 在 Python 中是可迭代的,因为它们简单地说就是一个字符列表。

所以你可能想去:

- name: Log into additional docker registries, when required
  command: docker login -u {{ item.username }} -p {{ item.password }} {{ item.server }}
  become: true
  loop: "{{ docker_registries if docker_registries is iterable and docker_registries is not string else [] }}"

【讨论】:

  • 我仍然遇到同样的错误:致命:[***.cloudapp.azure.com]:失败! => {“msg”:“传递给'循环'的无效数据,它需要一个列表,而是得到这个:无。提示:如果您传递的列表/字典只有一个元素,请尝试将 wantlist=True 添加到您的查找调用或使用 q/query 而不是查找。"}
【解决方案2】:

谢谢大家。我的 group_vars 文件中有一行注释掉了所有 docker_registries 用户名和密码等,但我没有注释 docker_registries: 行本身。这就是为什么我得到的是 None 而不是空列表。

【讨论】:

  • +1 因为我在使用 AWX 时偶然发现了这个问题。我在调查中询问了变量值,并将默认设置为空白。这导致我的变量确实被定义但值为“无”。所以是的,你自己的回答帮助了我,谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-06
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多