使用 ansible_facts 时,ansible AND 运算与 WHEN 失败

使用 ansible_facts 时,ansible AND 运算与 WHEN 失败

团队:当节点上有两个条件不满足时,我尝试使任务失败。ansible_facts['distribution_version']ansible_facts['distribution']

我正在传递两个节点。一个节点是20.xubuntu,另一个是18.x

变量/main.yml

os_distribution: "Ubuntu"
os_version: "20.04"

任务如下

- name: "Check Base OS Version maps to expected distribution version {{ os_version }}"
  fail:
    msg: "Task failed as unexpected OS version found: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} on {{ inventory_hostname }}"
  when:
    - ansible_facts['distribution_version'] is version(os_version, '<')
    - os_distribution != ansible_facts['distribution']

结果

TASK [node-validation : Check Base OS Version maps to expected distribution version 20.04] ***
Tuesday 23 November 2021  20:11:32 +0000 (0:00:17.570)       0:00:17.690 ****** 
skipping: [node1]
skipping: [node2]
    

预期输出:观察下面的 18.x,不确定我缺少什么才能得到它。

fatal: [node2]: FAILED! => {"changed": false, "msg": "Task failed as unexpected OS version found: Ubuntu 18.04 on node2"}

当我删除时- os_distribution != ansible_facts['distribution'],我得到了如下所示的预期结果,但我想满足两个条件而不仅仅是一个。

[fatal: [node2]: FAILED! => {"changed": false, "msg": "Task failed as unexpected OS version found: Ubuntu 18.04 on node2 }}"}

参考 ansible_facts

20.x 的事实

10:17:59  [0;32m        "distribution": "Ubuntu",[0m
10:17:59  [0;32m        "distribution_file_parsed": true,[0m
10:17:59  [0;32m        "distribution_file_path": "/etc/os-release",[0m
10:17:59  [0;32m        "distribution_file_variety": "Debian",[0m
10:17:59  [0;32m        "distribution_major_version": "18",[0m
10:17:59  [0;32m        "distribution_release": "bionic",[0m
10:17:59  [0;32m        "distribution_version": "18.04",[0m

20.x 的事实

10:23:43  [0;32m        "distribution": "Ubuntu",[0m
10:23:43  [0;32m        "distribution_file_parsed": true,[0m
10:23:43  [0;32m        "distribution_file_path": "/etc/os-release",[0m
10:23:43  [0;32m        "distribution_file_variety": "Debian",[0m
10:23:43  [0;32m        "distribution_major_version": "20",[0m
10:23:43  [0;32m        "distribution_release": "focal",[0m
10:23:43  [0;32m        "distribution_version": "20.04",[0m

答案1

当您提供列表时,它会执行两个表达式。这是标准的 AND 真值表。

条件 1 条件 2 结果
错误的 错误的 错误的
错误的 真的 错误的
真的 错误的 错误的
真的 真的 真的

考虑你有

os_distribution: "Ubuntu"             # variable
ansible_facts.distribution: "Ubuntu"  # fact

表达式"Ubuntu" != "Ubuntu"False,并且根据真值表,如果任一条件为假,则最终结果为假。只有当结果为真时,Ansible 才会执行任务。

无论如何,我怀疑要得到你想要的结果应该改变你when或者,而不是使用 AND 连接的列表。

when:
  ansible_facts['distribution_version'] is version(os_version, '<') or
  os_distribution != ansible_facts['distribution']

演示剧本 + 输出

---
- hosts: localhost
  vars:
    os_distribution: "Ubuntu"
    os_version: "20.04"
    ansible_facts:
      distribution: "Ubuntu"
      distribution_file_parsed: True
      distribution_file_path: "/etc/os-release"
      distribution_file_variety: "Debian"
      distribution_major_version: "18"
      distribution_release: "bionic"
      distribution_version: "18.04"

  tasks:
  - debug:
      msg: >-
        {{ os_distribution }} {{ansible_facts['distribution'] }}
        {{ os_distribution != ansible_facts['distribution'] }}
  - debug:
      msg: >-
        {{ ansible_facts['distribution_version'] }} {{ os_version }}
        {{ ansible_facts['distribution_version'] is version(os_version, '<') }}

  - name: "Check Base OS Version maps to expected distribution version {{ os_version }}"
    debug:
      msg: "Task failed as unexpected OS version found: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} on {{ inventory_hostname }}"
    when:
      ansible_facts['distribution_version'] is version(os_version, '<') or
      os_distribution != ansible_facts['distribution']

- hosts: localhost
  vars:
    os_distribution: "Ubuntu"
    os_version: "20.04"
    ansible_facts:
      distribution: "Ubuntu"
      distribution_file_parsed: true
      distribution_file_path: "/etc/os-release"
      distribution_file_variety: "Debian"
      distribution_major_version: "20"
      distribution_release: "focal"
      distribution_version: "20.04"

  tasks:
  - debug:
      msg: >-
        {{ os_distribution }} {{ansible_facts['distribution'] }}
        {{ os_distribution != ansible_facts['distribution'] }}
  - debug:
      msg: >-
        {{ ansible_facts['distribution_version'] }} {{ os_version }}
        {{ ansible_facts['distribution_version'] is version(os_version, '<') }}

  - name: "Check Base OS Version maps to expected distribution version {{ os_version }}"
    debug:
      msg: "Task failed as unexpected OS version found: {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }} on {{ inventory_hostname }}"
    when:
      ansible_facts['distribution_version'] is version(os_version, '<') or
      os_distribution != ansible_facts['distribution']

# Output

# TASK [debug] ***************************************************************************************************************************
# ok: [localhost] => {
#     "msg": "Ubuntu Ubuntu False"
# }
#
# TASK [debug] ***************************************************************************************************************************
# ok: [localhost] => {
#     "msg": "18.04 20.04 True"
# }
#
# TASK [Check Base OS Version maps to expected distribution version 20.04] ***************************************************************
# ok: [localhost] => {
#     "msg": "Task failed as unexpected OS version found: Ubuntu 18.04 on localhost"
# }
#
# PLAY [localhost] ***********************************************************************************************************************
#
# TASK [debug] ***************************************************************************************************************************
# ok: [localhost] => {
#     "msg": "Ubuntu Ubuntu False"
# }
#
# TASK [debug] ***************************************************************************************************************************
# ok: [localhost] => {
#     "msg": "20.04 20.04 False"
# }
#
# TASK [Check Base OS Version maps to expected distribution version 20.04] ***************************************************************
# skipping: [localhost]
#

PS,如果你想知道为什么在否定时从 AND 转换为 OR,请参阅德摩根定律

相关内容