Skip to content

Commit 7e9ea09

Browse files
committed
test: ensure role gathers the facts it uses by having test clear_facts before include_role
The role gathers the facts it uses. For example, if the user uses `ANSIBLE_GATHERING=explicit`, the role uses the `setup` module with the facts and subsets it requires. This change allows us to test this. Before every role invocation, the test will use `meta: clear_facts` so that the role starts with no facts. However, since the tests use facts, we save and restore the facts used by the test. Create a task file tests/tasks/run_role_with_clear_facts.yml to do the tasks to save, clear, run the role, and restore the facts. Any vars defined using `ansible_facts` have been changed to be defined with `set_fact` instead. This is because of the fact that `vars` are lazily evaluated - the var might be referenced when the facts have been cleared, and will issue an error like `ansible_facts["distribution"] is undefined`. Any blocks with a `when` condition that uses `ansible_facts` has been rewritten. This is because the `when` condition is evaluated every time a task is invoked in the block, and if the facts are cleared, this will raise an undefined variable error. Signed-off-by: Rich Megginson <rmeggins@redhat.com>
1 parent 0b22e88 commit 7e9ea09

59 files changed

Lines changed: 780 additions & 168 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

tests/ensure_provider_tests.py

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
GET_NM_VERSION = """
1313
- name: Install NetworkManager and get NetworkManager version
1414
when:
15-
- ansible_facts['distribution_major_version'] != '6'
15+
- __network_distro_major_version != '6'
1616
tags:
1717
- always
1818
block:
@@ -30,8 +30,7 @@
3030
ansible_facts.packages['NetworkManager'][0]['version'] }}"
3131
"""
3232

33-
MINIMUM_NM_VERSION_CHECK = """
34-
- networkmanager_version is version({minimum_nm_version}, '>=')
33+
MINIMUM_NM_VERSION_CHECK = """ - networkmanager_version is version({minimum_nm_version}, '>=')
3534
"""
3635

3736
EXTRA_RUN_CONDITION_PREFIX = " - "
@@ -51,31 +50,72 @@
5150
network_provider: nm
5251
tags:
5352
- always
53+
- name: Include distro variables
54+
include_vars: vars/rh_distros_vars.yml
55+
- name: Set platform facts
56+
set_fact:
57+
__network_distro_major_version: "{{{{ ansible_facts['distribution_major_version'] }}}}"
58+
__network_is_rhel: "{{{{ ansible_facts['distribution'] == 'RedHat' }}}}"
59+
__network_is_fedora: "{{{{ ansible_facts['distribution'] == 'Fedora' }}}}"
60+
__network_is_centos: "{{{{ ansible_facts['distribution'] == 'CentOS' }}}}"
61+
__network_is_os_family_rhel: "{{{{ ansible_facts['os_family'] == 'RedHat' }}}}"
5462
{get_nm_version}
5563
5664
# The test requires or should run with NetworkManager, therefore it cannot run
5765
# on RHEL/CentOS 6
5866
{comment}- name: Import the playbook '{test_playbook}'
5967
import_playbook: {test_playbook}
6068
when:
61-
- ansible_facts['distribution_major_version'] != '6'
69+
- __network_distro_major_version != '6'
6270
{minimum_nm_version_check}{extra_run_condition}"""
6371

72+
73+
RUN_PLAYBOOK_WITH_INITSCRIPTS = """# SPDX-License-Identifier: BSD-3-Clause
74+
# This file was generated by ensure_provider_tests.py
75+
---
76+
# yamllint disable rule:line-length
77+
- name: Run playbook '{test_playbook}' with initscripts as provider
78+
hosts: all
79+
tasks:
80+
- name: Include the task 'el_repo_setup.yml'
81+
include_tasks: tasks/el_repo_setup.yml
82+
- name: Set network provider to 'initscripts'
83+
set_fact:
84+
network_provider: initscripts
85+
tags:
86+
- always
87+
- name: Include distro variables
88+
include_vars: vars/rh_distros_vars.yml
89+
- name: Set platform facts
90+
set_fact:
91+
__network_distro_major_version: "{{{{ ansible_facts['distribution_major_version'] }}}}"
92+
__network_is_rhel: "{{{{ ansible_facts['distribution'] == 'RedHat' }}}}"
93+
__network_is_fedora: "{{{{ ansible_facts['distribution'] == 'Fedora' }}}}"
94+
__network_is_centos: "{{{{ ansible_facts['distribution'] == 'CentOS' }}}}"
95+
__network_is_os_family_rhel: "{{{{ ansible_facts['os_family'] == 'RedHat' }}}}"
96+
- name: Import the playbook '{test_playbook}'
97+
import_playbook: {test_playbook}
98+
when:
99+
- __network_is_rh_distro
100+
- __network_distro_major_version | int < 9
101+
"""
102+
103+
64104
MINIMUM_VERSION = "minimum_version"
65105
EXTRA_RUN_CONDITION = "extra_run_condition"
66106
NM_ONLY_TESTS = {
67107
"playbooks/tests_802_1x_updated.yml": {
68108
EXTRA_RUN_CONDITION: (
69-
"(ansible_facts['distribution'] != 'RedHat' and\n"
70-
" ansible_facts['distribution_major_version'] | int > 7) or\n"
71-
" ansible_facts['distribution_major_version'] | int == 8"
109+
"(not __network_is_rhel and\n"
110+
" __network_distro_major_version | int > 7) or\n"
111+
" __network_distro_major_version | int == 8"
72112
),
73113
},
74114
"playbooks/tests_802_1x.yml": {
75115
EXTRA_RUN_CONDITION: (
76-
"(ansible_facts['distribution'] != 'RedHat' and\n"
77-
" ansible_facts['distribution_major_version'] | int > 7) or\n"
78-
" ansible_facts['distribution_major_version'] | int == 8"
116+
"(not __network_is_rhel and\n"
117+
" __network_distro_major_version | int > 7) or\n"
118+
" __network_distro_major_version | int == 8"
79119
),
80120
},
81121
"playbooks/tests_ignore_auto_dns.yml": {},
@@ -92,20 +132,20 @@
92132
},
93133
"playbooks/tests_provider.yml": {
94134
MINIMUM_VERSION: "'1.20.0'",
95-
"comment": "# NetworKmanager 1.20.0 added support for forgetting profiles",
135+
"comment": "# NetworkManager 1.20.0 added support for forgetting profiles",
96136
EXTRA_RUN_CONDITION: (
97-
"(ansible_facts['distribution'] == 'Fedora'\n"
98-
" and ansible_facts['distribution_major_version'] | int < 41)\n"
99-
" or ansible_facts['distribution'] not in ['RedHat', 'CentOS', 'Fedora']\n"
100-
" or ansible_facts['distribution_major_version'] | int < 9"
137+
"(__network_is_fedora and\n"
138+
" __network_distro_major_version | int < 41)\n"
139+
" or not __network_is_os_family_rhel\n"
140+
" or __network_distro_major_version | int < 9"
101141
),
102142
},
103143
"playbooks/tests_eth_pci_address_match.yml": {
104144
MINIMUM_VERSION: "'1.26.0'",
105145
"comment": "# NetworkManager 1.26.0 added support for match.path setting",
106146
},
107147
"playbooks/tests_network_state.yml": {
108-
EXTRA_RUN_CONDITION: "ansible_facts['distribution_major_version'] | int > 7",
148+
EXTRA_RUN_CONDITION: "__network_distro_major_version | int > 7",
109149
},
110150
"playbooks/tests_reapply.yml": {},
111151
"playbooks/tests_route_table.yml": {},
@@ -117,30 +157,30 @@
117157
"playbooks/tests_routing_rules.yml": {},
118158
# teaming support dropped in EL10
119159
"playbooks/tests_team.yml": {
120-
EXTRA_RUN_CONDITION: "ansible_facts['distribution'] not in ['RedHat', 'CentOS'] or\n ansible_facts['distribution_major_version'] | int < 10",
160+
EXTRA_RUN_CONDITION: "not __network_is_rh_distro or\n __network_distro_major_version | int < 10",
121161
},
122162
"playbooks/tests_team_plugin_installation.yml": {
123-
EXTRA_RUN_CONDITION: "ansible_facts['distribution'] not in ['RedHat', 'CentOS'] or\n ansible_facts['distribution_major_version'] | int < 10",
163+
EXTRA_RUN_CONDITION: "not __network_is_rh_distro or\n __network_distro_major_version | int < 10",
124164
},
125165
# mac80211_hwsim (used for tests_wireless) only seems to be available
126166
# and working on RHEL/CentOS 7
127167
"playbooks/tests_wireless.yml": {
128-
EXTRA_RUN_CONDITION: "ansible_facts['distribution_major_version'] == '7'",
168+
EXTRA_RUN_CONDITION: "__network_distro_major_version == '7'",
129169
},
130170
"playbooks/tests_wireless_and_network_restart.yml": {},
131171
"playbooks/tests_wireless_plugin_installation.yml": {},
132172
"playbooks/tests_wireless_wpa3_owe.yml": {
133173
"comment": "# OWE has not been supported by NetworkManager 1.18.8 on \
134174
RHEL 7(dist-tag). Failed in setting up mock wifi on RHEL 8",
135-
EXTRA_RUN_CONDITION: "ansible_facts['distribution_major_version'] > '7' and \
136-
ansible_facts['distribution'] == 'CentOS' or\n ansible_facts['distribution_major_version'] > '32' \
137-
and ansible_facts['distribution'] == 'Fedora'",
175+
EXTRA_RUN_CONDITION: "__network_distro_major_version | int > 7 and \
176+
__network_is_centos or\n __network_distro_major_version | int > 32 \
177+
and __network_is_fedora",
138178
},
139179
"playbooks/tests_wireless_wpa3_sae.yml": {
140180
"comment": "# SAE has not been supported by NetworkManager 1.18.8 on \
141181
RHEL 7. Failed in setting up mock wifi on RHEL 8",
142-
EXTRA_RUN_CONDITION: "ansible_facts['distribution_major_version'] != '7' and \
143-
ansible_facts['distribution'] != 'RedHat'",
182+
EXTRA_RUN_CONDITION: "__network_distro_major_version != '7' and \
183+
not __network_is_rhel",
144184
},
145185
}
146186
# NM_CONDITIONAL_TESTS is used to store the test playbooks which are demanding for NM
@@ -168,28 +208,6 @@
168208
"playbooks/tests_switch_provider.yml",
169209
]
170210

171-
RUN_PLAYBOOK_WITH_INITSCRIPTS = """# SPDX-License-Identifier: BSD-3-Clause
172-
# This file was generated by ensure_provider_tests.py
173-
---
174-
# yamllint disable rule:line-length
175-
- name: Run playbook '{test_playbook}' with initscripts as provider
176-
hosts: all
177-
tasks:
178-
- name: Include the task 'el_repo_setup.yml'
179-
include_tasks: tasks/el_repo_setup.yml
180-
- name: Set network provider to 'initscripts'
181-
set_fact:
182-
network_provider: initscripts
183-
tags:
184-
- always
185-
186-
- name: Import the playbook '{test_playbook}'
187-
import_playbook: {test_playbook}
188-
when: (ansible_facts['distribution'] in ['CentOS','RedHat'] and\n \
189-
ansible_facts['distribution_major_version'] | int < 9)
190-
"""
191-
192-
193211
def create_nm_playbook(test_playbook):
194212
fileroot = os.path.splitext(os.path.basename(test_playbook))[0]
195213
nm_testfile = fileroot + "_nm.yml"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Ansible module to merge saved facts with current Ansible facts.
4+
# The result is saved_facts with any keys/values overridden by current_ansible_facts.
5+
#
6+
# Created by Claude AI running in Cursor
7+
8+
from __future__ import absolute_import, division, print_function
9+
10+
__metaclass__ = type
11+
12+
from ansible.module_utils.basic import AnsibleModule
13+
14+
15+
DOCUMENTATION = r'''
16+
---
17+
module: merge_ansible_facts
18+
short_description: Merge saved facts with current Ansible facts
19+
version_added: "1.0.0"
20+
description:
21+
- Does O(saved_ansible_facts.update(current_ansible_facts)) and returns the result.
22+
author:
23+
- Linux System Roles
24+
options:
25+
current_ansible_facts:
26+
description: Current Ansible facts.
27+
type: dict
28+
required: true
29+
saved_ansible_facts:
30+
description: Previously saved facts.
31+
type: dict
32+
required: true
33+
'''
34+
35+
EXAMPLES = r'''
36+
- name: Update saved facts with current facts
37+
merge_ansible_facts:
38+
current_ansible_facts: "{{ ansible_facts }}"
39+
saved_ansible_facts: "{{ saved_ansible_facts }}"
40+
register: merged
41+
42+
- name: Use updated facts
43+
set_fact:
44+
ansible_facts: "{{ merged.ansible_facts }}"
45+
'''
46+
47+
RETURN = r'''
48+
ansible_facts:
49+
description: saved_facts with keys/values overridden by current_ansible_facts.
50+
returned: success
51+
type: dict
52+
'''
53+
54+
55+
def run_module():
56+
module_args = dict(
57+
current_ansible_facts=dict(type='dict', required=True),
58+
saved_ansible_facts=dict(type='dict', required=True),
59+
)
60+
61+
module = AnsibleModule(
62+
argument_spec=module_args,
63+
supports_check_mode=True,
64+
)
65+
66+
current = module.params['current_ansible_facts']
67+
saved = module.params['saved_ansible_facts']
68+
69+
saved.update(current)
70+
module.exit_json(ansible_facts=saved)
71+
72+
73+
def main():
74+
run_module()
75+
76+
77+
if __name__ == '__main__':
78+
main()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
# Task file: save facts, clear_facts, run linux-system-roles.network, then restore facts.
3+
# Include this with include_tasks or import_tasks; ensure tests/library is in module search path.
4+
5+
- name: Save current ansible facts
6+
set_fact:
7+
saved_facts: "{{ ansible_facts }}"
8+
9+
- name: Clear facts
10+
meta: clear_facts
11+
12+
- name: Run the role and rescue
13+
block:
14+
- name: Run the role
15+
include_role:
16+
name: linux-system-roles.network
17+
tasks_from: "{{ tasks_from | default('main') }}"
18+
public: "{{ public | default(false) }}"
19+
rescue:
20+
- name: Check if failed_when is false
21+
fail:
22+
msg: "{{ ansible_failed_result.msg }}"
23+
when: __network_failed_when | d(true)
24+
25+
- name: Reset ansible_facts (saved base with current overrides)
26+
merge_ansible_facts:
27+
current_ansible_facts: "{{ ansible_facts }}"
28+
saved_ansible_facts: "{{ saved_facts }}"

tests/tests_802_1x_nm.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,23 @@
1313
network_provider: nm
1414
tags:
1515
- always
16+
- name: Include distro variables
17+
include_vars: vars/rh_distros_vars.yml
18+
- name: Set platform facts
19+
set_fact:
20+
__network_distro_major_version: "{{ ansible_facts['distribution_major_version'] }}"
21+
__network_is_rhel: "{{ ansible_facts['distribution'] == 'RedHat' }}"
22+
__network_is_fedora: "{{ ansible_facts['distribution'] == 'Fedora' }}"
23+
__network_is_centos: "{{ ansible_facts['distribution'] == 'CentOS' }}"
24+
__network_is_os_family_rhel: "{{ ansible_facts['os_family'] == 'RedHat' }}"
1625

1726

1827
# The test requires or should run with NetworkManager, therefore it cannot run
1928
# on RHEL/CentOS 6
2029
- name: Import the playbook 'playbooks/tests_802_1x.yml'
2130
import_playbook: playbooks/tests_802_1x.yml
2231
when:
23-
- ansible_facts['distribution_major_version'] != '6'
24-
- (ansible_facts['distribution'] != 'RedHat' and
25-
ansible_facts['distribution_major_version'] | int > 7) or
26-
ansible_facts['distribution_major_version'] | int == 8
32+
- __network_distro_major_version != '6'
33+
- (not __network_is_rhel and
34+
__network_distro_major_version | int > 7) or
35+
__network_distro_major_version | int == 8

tests/tests_802_1x_updated_nm.yml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,23 @@
1313
network_provider: nm
1414
tags:
1515
- always
16+
- name: Include distro variables
17+
include_vars: vars/rh_distros_vars.yml
18+
- name: Set platform facts
19+
set_fact:
20+
__network_distro_major_version: "{{ ansible_facts['distribution_major_version'] }}"
21+
__network_is_rhel: "{{ ansible_facts['distribution'] == 'RedHat' }}"
22+
__network_is_fedora: "{{ ansible_facts['distribution'] == 'Fedora' }}"
23+
__network_is_centos: "{{ ansible_facts['distribution'] == 'CentOS' }}"
24+
__network_is_os_family_rhel: "{{ ansible_facts['os_family'] == 'RedHat' }}"
1625

1726

1827
# The test requires or should run with NetworkManager, therefore it cannot run
1928
# on RHEL/CentOS 6
2029
- name: Import the playbook 'playbooks/tests_802_1x_updated.yml'
2130
import_playbook: playbooks/tests_802_1x_updated.yml
2231
when:
23-
- ansible_facts['distribution_major_version'] != '6'
24-
- (ansible_facts['distribution'] != 'RedHat' and
25-
ansible_facts['distribution_major_version'] | int > 7) or
26-
ansible_facts['distribution_major_version'] | int == 8
32+
- __network_distro_major_version != '6'
33+
- (not __network_is_rhel and
34+
__network_distro_major_version | int > 7) or
35+
__network_distro_major_version | int == 8

tests/tests_auto_gateway_initscripts.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,17 @@
1212
network_provider: initscripts
1313
tags:
1414
- always
15-
15+
- name: Include distro variables
16+
include_vars: vars/rh_distros_vars.yml
17+
- name: Set platform facts
18+
set_fact:
19+
__network_distro_major_version: "{{ ansible_facts['distribution_major_version'] }}"
20+
__network_is_rhel: "{{ ansible_facts['distribution'] == 'RedHat' }}"
21+
__network_is_fedora: "{{ ansible_facts['distribution'] == 'Fedora' }}"
22+
__network_is_centos: "{{ ansible_facts['distribution'] == 'CentOS' }}"
23+
__network_is_os_family_rhel: "{{ ansible_facts['os_family'] == 'RedHat' }}"
1624
- name: Import the playbook 'playbooks/tests_auto_gateway.yml'
1725
import_playbook: playbooks/tests_auto_gateway.yml
18-
when: (ansible_facts['distribution'] in ['CentOS','RedHat'] and
19-
ansible_facts['distribution_major_version'] | int < 9)
26+
when:
27+
- __network_is_rh_distro
28+
- __network_distro_major_version | int < 9

0 commit comments

Comments
 (0)