Ansible 中列表为空时如何跳过循环

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

我正在运行 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”:“”}

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

docker loops ansible yaml jinja2
3个回答
15
投票

您可以将

when
语句
iterable
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
的数据的有效性。

现在,您可以在循环声明本身中使用条件表达式来解决这个问题:

- 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 [] }}"

2
投票

谢谢大家。我的 group_vars 文件中有一行,我已注释掉所有 docker_registries 用户名和密码等,但我没有注释

docker_registries:
行本身。这就是为什么我得到 None 而不是空列表。


0
投票

Ansible 和 Jinja 有一些令人惊讶的行为:

  1. loop
    表达式在when条件之前
    进行计算,所以这没有帮助。
  2. {{ none | default('something') }}
     评估为无。 
    {{ none | default('something', true) }}
     评估为“某物”。
即您必须将 true 作为第二个参数传递给 default()。

考虑到这一点,解决方案就很简单了:

- name: Log into additional docker registries, when required command: docker login -u {{item.username}} -p {{item.password}} {{item.server}} become: true loop: "{{ docker_registries | default([], true) }}"
还有:

  • {{ '' is iterable }}
     返回 true,因此如果可能的话,您还必须检查字符串。
  • None (Python) 在 Jinja2 评估中应该是小写的 none。
© www.soinside.com 2019 - 2024. All rights reserved.