ansible - 块条件被忽略

ansible - block conditionnal is ignored

我有一个关于 ansible 角色的块的问题

roles/apps_nifi/tasks/main.yml 的摘录:

- debug:
    msg: "nifi_extra_instances_name is defined"
  when: nifi_extra_instances_name  is defined

- debug:
    msg: "nifi_extra_instances_name is not defined"
  when: nifi_extra_instances_name  is not defined

- name: Import variables for extra instances of Nifi
  block:
    - set_fact:
        nifi_extra_instances_vars: "{{ item.value }}"
      when: nifi_extra_instances_name in item.key
      loop: "{{ lookup('dict', nifi_extra_instances, wantlist=True) }}"

    - set_fact:
        "{{ item.key }}": "{{ item.value }}"
      loop: "{{ lookup('dict', nifi_extra_instances_vars , wantlist=True) }}"
      when: nifi_extra_instances_vars is defined and nifi_extra_instances_vars|length > 0
  when: nifi_extra_instances_name is defined

nifi_extra_instances_name 是我在需要时调用角色时的变量设置。

手册 main.yml :

- hosts: nifi_hosts
  become: yes

  roles:
    - { role: apps_nifi, tags: nifi }
    - { role: apps_nifi-registry, tags: apps_nifi-registry }
    - { role: apps_nifi-api, tags: apps_nifi-api, become: no }
    #- { role: apps_nifi, tags: "nifi-burn", vars: { nifi_extra_instances_name: burn} }

所以这个例子中没有定义变量nifi_extra_instances_name,我希望进入“block”的代码不会被播放:

TASK [apps_nifi : debug] **********************************************************************************************************************************************
Wednesday 14 October 2020  10:39:45 +0200 (0:00:12.496)       0:00:20.193 *****
skipping: [XXXXX]

TASK [apps_nifi : debug] **********************************************************************************************************************************************
Wednesday 14 October 2020  10:39:45 +0200 (0:00:00.052)       0:00:20.245 *****
ok: [XXXXX] => {
    "msg": "nifi_extra_instances_name is not defined"
}

TASK [apps_nifi : set_fact] *******************************************************************************************************************************************
Wednesday 14 October 2020  10:39:45 +0200 (0:00:00.055)       0:00:20.300 *****
skipping: [XXXX] => (item={u'key': u'burn', u'value': {u'nifi_dir': u'/local/nifi-burn', u'nifi_web_https_port': 9445, u'nifi_ports': [u'9445:9445', u'9094:9094'], u'container_name': u'bdmpusher-burn'}})

TASK [apps_nifi : set_fact] *******************************************************************************************************************************************
Wednesday 14 October 2020  10:39:45 +0200 (0:00:00.058)       0:00:20.359 *****
fatal: [XXXXX]: FAILED! => {"msg": "An unhandled exception occurred while running the lookup plugin 'dict'. Error was a <class 'ansible.errors.AnsibleError'>, original message: with_dict expects a dict"}

有什么想法吗?

块的when条件(以及例如role节在播放级别,import_task ...)被“推送”到每个受影响的任务。换句话说,在每个任务级别评估完整块的条件。

所以下面这段代码:

- block:
    - name: do a
      debug:
        msg: a
      when: task_a_condition
    - name: do b
      debug:
        msg: b
      when: task_b_condition
  when: block_condition

完全等同于:

- name: do a
  debug:
    msg: a
  when: task_a_condition and block_condition
- name: do b
  debug:
    msg: b
  when: task_b_condition and block condition

因此,所有when条件都是在whatever case中分析的。

此外,在循环时,首先分析loop表达式以确定所需的迭代次数,然后对每个项目分析when条件。在您的情况下,它会导致错误,因为 nifi_extra_instances_vars 未定义(因此不是字典)。

您可以在需要时使用以下导致空循环的循环表达式修复该特定任务:

loop: "{{ query('dict', nifi_extra_instances | default({})) }}"

(注意:使用 query 而不是 lookup 自动 returns 一个列表)

现在,如果您真的不希望这些任务即使被跳过也根本不播放,IMO 有一个更好的解决方案:

  • 将块任务移动到单独的文件并删除 block 节。
  • 使用 include_tasks,条件与当前区块相同 when。在这种情况下,它将仅适用于 include 语句本身,而不适用于单个任务。 不要与 import_task 混淆,这会导致与当前问题的块完全相同的结果。