Skip to content

Commit dfc2ee2

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. This uses an action plugin merge_ansible_facts to merge the saved facts with any changes by the role. 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 f60df3a commit dfc2ee2

File tree

58 files changed

+461
-379
lines changed

Some content is hidden

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

58 files changed

+461
-379
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Ansible action plugin merge_ansible_facts.
4+
# Merges saved facts with current Ansible facts on the controller and returns
5+
# ansible_facts (saved_ansible_facts with current_ansible_facts overlaid).
6+
#
7+
# Copyright: (c) 2026, Red Hat, Inc.
8+
# Code mostly written by Claude model claude-4.5-opus-high
9+
10+
from __future__ import absolute_import, division, print_function
11+
12+
__metaclass__ = type
13+
14+
from ansible.plugins.action import ActionBase
15+
16+
17+
class ActionModule(ActionBase):
18+
19+
TRANSFERS_FILES = False
20+
21+
def run(self, tmp=None, task_vars=None):
22+
if task_vars is None:
23+
task_vars = {}
24+
25+
result = super(ActionModule, self).run(tmp, task_vars)
26+
result["changed"] = False
27+
28+
current = self._task.args.get("current_ansible_facts")
29+
saved = self._task.args.get("saved_ansible_facts")
30+
31+
if current is None:
32+
result["failed"] = True
33+
result["msg"] = "current_ansible_facts is required"
34+
return result
35+
if saved is None:
36+
result["failed"] = True
37+
result["msg"] = "saved_ansible_facts is required"
38+
return result
39+
40+
# Template in case args were passed as raw Jinja
41+
current = self._templar.template(current)
42+
saved = self._templar.template(saved)
43+
44+
if not isinstance(current, dict):
45+
result["failed"] = True
46+
result["msg"] = "current_ansible_facts must be a dict"
47+
return result
48+
if not isinstance(saved, dict):
49+
result["failed"] = True
50+
result["msg"] = "saved_ansible_facts must be a dict"
51+
return result
52+
53+
# Merge: start with a copy of saved, overlay current (same behavior as module)
54+
merged = dict(saved)
55+
merged.update(current)
56+
result["ansible_facts"] = merged
57+
58+
return result

tests/library

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/setup-snapshot.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
hosts: all
44
tasks:
55
- name: Set platform/version specific variables
6-
include_role:
7-
name: linux-system-roles.ha_cluster
8-
tasks_from: set_vars.yml
9-
public: true
6+
include_tasks: tasks/run_role_with_clear_facts.yml
7+
vars:
8+
__sr_tasks_from: set_vars.yml
9+
__sr_public: true
1010

1111
- name: Install cluster packages
1212
package:

tests/tasks/assert_node_options_check.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
- name: Run the role and check for errors
88
block:
99
- name: Run the role
10-
include_role:
11-
name: linux-system-roles.ha_cluster
10+
include_tasks: tasks/run_role_with_clear_facts.yml
1211

1312
- name: Fail
1413
fail:

tests/tasks/fixture_psks.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@
55
file: vars/rh_distros_vars.yml
66
when: __ha_cluster_is_rh_distro is not defined
77

8+
- name: Set variable for crypto-policies PQC block
9+
set_fact:
10+
__need_crypto_policies_pqc: >-
11+
{{ __ha_cluster_is_rh_distro | bool and (
12+
(ansible_facts['distribution'] == 'RedHat' and
13+
ansible_facts['distribution_version'] is version('9.7', '>=') and
14+
ansible_facts['distribution_version'] is version('10', '<'))
15+
or (ansible_facts['distribution'] != 'RedHat' and
16+
ansible_facts['distribution_major_version'] is version('9', '=='))
17+
) }}
18+
819
- name: Check if the managed node needs crypto-policies to be able to use PQC
9-
when:
10-
- __ha_cluster_is_rh_distro | bool
11-
- (ansible_facts["distribution"] == "RedHat" and ansible_facts["distribution_version"] is version("9.7", ">=")
12-
and ansible_facts["distribution_version"] is version("10", "<"))
13-
or (ansible_facts["distribution"] != "RedHat" and
14-
ansible_facts['distribution_major_version'] is version("9", "=="))
20+
when: __need_crypto_policies_pqc | bool
1521
block:
1622
# calling role with null will just return the current policy
1723
- name: Get current crypto policy
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
# Task file: save facts, clear_facts, run linux-system-roles.ha_cluster, then restore facts.
3+
# Include this with include_tasks or import_tasks; ensure tests/library is in module search path.
4+
# Input:
5+
# - __sr_tasks_from: tasks_from to run - same as tasks_from in include_role
6+
# - __sr_public: export private vars from role - same as public in include_role
7+
# - __sr_failed_when: set to false to ignore role errors - same as failed_when in include_role
8+
# Output:
9+
# - ansible_facts: merged saved ansible_facts with ansible_facts modified by the role, if any
10+
- name: Save current ansible facts
11+
set_fact:
12+
saved_facts: "{{ ansible_facts }}"
13+
14+
- name: Clear facts
15+
meta: clear_facts
16+
17+
# note that you can use failed_when with import_role but not with include_role
18+
# so this simulates the __sr_failed_when false case
19+
- name: Run the role with __sr_failed_when false
20+
when:
21+
- __sr_failed_when is defined
22+
- not __sr_failed_when
23+
block:
24+
- name: Run the role
25+
include_role:
26+
name: linux-system-roles.ha_cluster
27+
tasks_from: "{{ __sr_tasks_from | default('main') }}"
28+
public: "{{ __sr_public | default(false) }}"
29+
rescue:
30+
- name: Ignore the failure when __sr_failed_when is false
31+
debug:
32+
msg: Ignoring failure when __sr_failed_when is false
33+
34+
- name: Run the role normally
35+
include_role:
36+
name: linux-system-roles.ha_cluster
37+
tasks_from: "{{ __sr_tasks_from | default('main') }}"
38+
public: "{{ __sr_public | default(false) }}"
39+
when: __sr_failed_when | d(true)
40+
41+
- name: Reset ansible_facts (saved base with current overrides)
42+
merge_ansible_facts:
43+
current_ansible_facts: "{{ ansible_facts }}"
44+
saved_ansible_facts: "{{ saved_facts }}"

tests/template_qdevice.yml

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@
55
ha_cluster_cluster_name: test-cluster
66
block:
77
- name: Set up test environment
8-
include_role:
9-
name: linux-system-roles.ha_cluster
10-
tasks_from: test_setup.yml
8+
include_tasks: tasks/run_role_with_clear_facts.yml
9+
vars:
10+
__sr_tasks_from: test_setup.yml
1111

1212
- name: Clean up test environment for qnetd
13-
include_role:
14-
name: linux-system-roles.ha_cluster
15-
tasks_from: test_cleanup_qnetd.yml
13+
include_tasks: tasks/run_role_with_clear_facts.yml
14+
vars:
15+
__sr_tasks_from: test_cleanup_qnetd.yml
1616

1717
- name: Set up test environment for qnetd
18-
include_role:
19-
name: linux-system-roles.ha_cluster
20-
tasks_from: test_setup_qnetd.yml
18+
include_tasks: tasks/run_role_with_clear_facts.yml
19+
vars:
20+
__sr_tasks_from: test_setup_qnetd.yml
2121
run_once: true # noqa: run_once[task]
2222

2323
- name: Back up qnetd
@@ -27,10 +27,9 @@
2727
run_once: true # noqa: run_once[task]
2828

2929
- name: Run HA Cluster role
30-
include_role:
31-
name: linux-system-roles.ha_cluster
32-
# variables for the role are supposed to be defined in a playbook which
33-
# includes this task file
30+
include_tasks: tasks/run_role_with_clear_facts.yml
31+
# variables for the role are supposed to be defined in a playbook which
32+
# includes this task file
3433

3534
# The role removed qnetd configuration
3635
- name: Restore qnetd
@@ -63,6 +62,6 @@
6362

6463
always:
6564
- name: Clean up test environment for qnetd
66-
include_role:
67-
name: linux-system-roles.ha_cluster
68-
tasks_from: test_cleanup_qnetd.yml
65+
include_tasks: tasks/run_role_with_clear_facts.yml
66+
vars:
67+
__sr_tasks_from: test_cleanup_qnetd.yml

tests/template_sbd_all_options.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
- /etc/modules-load.d/softdog.conf
2424

2525
- name: Run HA Cluster role
26-
include_role:
27-
name: linux-system-roles.ha_cluster
28-
public: true
26+
include_tasks: tasks/run_role_with_clear_facts.yml
27+
vars:
28+
__sr_public: true
2929

3030
- name: Slurp generated SBD watchdog blocklist file
3131
slurp:

tests/tests_bootc_e2e_cluster.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@
99
when: ansible_connection | d("") == "buildah" or __bootc_validation | d(false)
1010
block:
1111
- name: Set up test environment
12-
include_role:
13-
name: linux-system-roles.ha_cluster
14-
tasks_from: test_setup.yml
12+
include_tasks: tasks/run_role_with_clear_facts.yml
13+
vars:
14+
__sr_tasks_from: test_setup.yml
1515

1616
- name: Do build time tasks and verify
1717
when: not __bootc_validation | d(false)
1818
block:
1919
- name: Run HA Cluster role
20-
include_role:
21-
name: linux-system-roles.ha_cluster
22-
public: true
20+
include_tasks: tasks/run_role_with_clear_facts.yml
21+
vars:
22+
__sr_public: true
2323
when: not __bootc_validation | d(false)
2424

2525
- name: Create QEMU deployment during bootc end-to-end test

tests/tests_bootc_e2e_qnetd.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@
1414
when: ansible_connection | d("") == "buildah" or __bootc_validation | d(false)
1515
block:
1616
- name: Set up test environment
17-
include_role:
18-
name: linux-system-roles.ha_cluster
19-
tasks_from: test_setup.yml
17+
include_tasks: tasks/run_role_with_clear_facts.yml
18+
vars:
19+
__sr_tasks_from: test_setup.yml
2020

2121
- name: Do build time tasks and verify
2222
when: not __bootc_validation | d(false)
2323
block:
2424
- name: Run HA Cluster role
25-
include_role:
26-
name: linux-system-roles.ha_cluster
27-
public: true
25+
include_tasks: tasks/run_role_with_clear_facts.yml
26+
vars:
27+
__sr_public: true
2828
when: not __bootc_validation | d(false)
2929

3030
- name: Create QEMU deployment during bootc end-to-end test

0 commit comments

Comments
 (0)