0

Team: I am trying to fail a task when two conditions are not met on a node. ansible_facts['distribution_version'] and ansible_facts['distribution'].

I am passing in two nodes. one node is 20.x ubuntu and other is 18.x.

vars/main.yml

os_distribution: "Ubuntu"
os_version: "20.04"

task is below

- 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']

result

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]
    

expected output: observe 18.x below not sure what am i missing to get that.

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

When I remove - os_distribution != ansible_facts['distribution'] then I get expected result as below but I want to satisfy two conditions not just one.

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

reference to ansible_facts

FACTS for 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

FACTS for 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
AhmFM
  • 119
  • 5

1 Answers1

0

When you provide a when a list it performs an AND of the two expressions. And here is the standard AND truth table.

Condition 1 Condition 2 Result
False False False
False True False
True False False
True True True

Consider your have

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

The Expression "Ubuntu" != "Ubuntu" is False, and since per the truth table if either of the conditions are false, the final result is false. Ansible will only execute the task when the result is true.

Anyway, I suspect to get the result you want should change your when to an OR, instead of having a list that is joined by an AND.

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

Demonstration playbook + output

---
- 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, if you want the math on why you switch from an AND to an OR on negation see De_Morgan's_laws

vidarlo
  • 6,654
  • 2
  • 18
  • 31
Zoredache
  • 130,897
  • 41
  • 276
  • 420
  • agree and I believe that is what i thought am doing? I have one node1 that is TT and other is TF. so I should have got failure for node2 that prints message and skip on node1 that has TT with no message. but am getting skip and no message in both situations – AhmFM Nov 23 '21 at 21:47
  • If you need more added an example playbook and output that may help, and you can use to test more. – Zoredache Nov 23 '21 at 21:53