From daecaaad82f910a82799b2b0cfa2a4705fa99ec6 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Thu, 19 Mar 2026 09:28:18 -0600 Subject: [PATCH] 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. Create a task file tests/tasks/run_role_with_clear_facts.yml to do the tasks to clear the facts and run the role. Note that this means we don't need to use `gather_facts` for the tests. Some 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`. This is typically done for blocks that have a `when` condition that uses `ansible_facts` and the block has a role invocation using run_role_with_clear_facts.yml These have been rewritten to define the `when` condition using `set_fact`. 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 --- tests/tasks/clone_kernel.yml | 6 ++-- tests/tasks/run_role_with_clear_facts.yml | 37 +++++++++++++++++++++++ tests/tests_add_rm.yml | 13 +++----- tests/tests_bool_null_not_allowed.yml | 9 ++---- tests/tests_default.yml | 4 +-- tests/tests_include_vars_from_parent.yml | 1 - tests/tests_password.yml | 10 ++---- tests/tests_settings.yml | 13 +++----- 8 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 tests/tasks/run_role_with_clear_facts.yml diff --git a/tests/tasks/clone_kernel.yml b/tests/tasks/clone_kernel.yml index f3c8d78f..69e0f781 100644 --- a/tests/tasks/clone_kernel.yml +++ b/tests/tasks/clone_kernel.yml @@ -28,8 +28,7 @@ state: present - copy_default: "{{ __bootloader_copy_default }}" default: "{{ __bootloader_make_default | d(false) }}" - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Flush handlers meta: flush_handlers @@ -41,5 +40,4 @@ - name: Get bootloader_facts vars: bootloader_gather_facts: true - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml diff --git a/tests/tasks/run_role_with_clear_facts.yml b/tests/tasks/run_role_with_clear_facts.yml new file mode 100644 index 00000000..a6e1ca43 --- /dev/null +++ b/tests/tasks/run_role_with_clear_facts.yml @@ -0,0 +1,37 @@ +--- +# Task file: clear_facts, run linux-system-roles.bootloader. +# Include this with include_tasks or import_tasks +# Input: +# - __sr_tasks_from: tasks_from to run - same as tasks_from in include_role +# - __sr_public: export private vars from role - same as public in include_role +# - __sr_failed_when: set to false to ignore role errors - same as failed_when in include_role +- name: Clear facts + meta: clear_facts + +# note that you can use failed_when with import_role but not with include_role +# so this simulates the __sr_failed_when false case +# Q: Why do we need a separate task to run the role normally? Why not just +# run the role in the block and rethrow the error in the rescue block? +# A: Because you cannot rethrow the error in exactly the same way as the role does. +# It might be possible to exactly reconstruct ansible_failed_result but it's not worth the effort. +- name: Run the role with __sr_failed_when false + when: + - __sr_failed_when is defined + - not __sr_failed_when + block: + - name: Run the role + include_role: + name: linux-system-roles.bootloader + tasks_from: "{{ __sr_tasks_from | default('main') }}" + public: "{{ __sr_public | default(false) }}" + rescue: + - name: Ignore the failure when __sr_failed_when is false + debug: + msg: Ignoring failure when __sr_failed_when is false + +- name: Run the role normally + include_role: + name: linux-system-roles.bootloader + tasks_from: "{{ __sr_tasks_from | default('main') }}" + public: "{{ __sr_public | default(false) }}" + when: __sr_failed_when | d(true) diff --git a/tests/tests_add_rm.yml b/tests/tests_add_rm.yml index 59a78690..3d0c0951 100644 --- a/tests/tests_add_rm.yml +++ b/tests/tests_add_rm.yml @@ -2,7 +2,6 @@ --- - name: Test creating, modifying, and removing kernels hosts: all - gather_facts: false tags: - tests::reboot vars: @@ -16,8 +15,7 @@ - name: Get bootloader_facts vars: bootloader_gather_facts: true - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Skip test on ostree systems meta: end_host @@ -92,8 +90,7 @@ - kernel: path: "{{ __default_kernel.kernel }}_clone2" default: true - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Unreachable task fail: @@ -118,8 +115,7 @@ state: present - copy_default: true state: absent - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Remove Clone2 kernel with kernel path vars: @@ -128,8 +124,7 @@ - kernel: path: "{{ __default_kernel.kernel }}_clone2" state: absent - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Verify that kernel is removed {{ item }} assert: diff --git a/tests/tests_bool_null_not_allowed.yml b/tests/tests_bool_null_not_allowed.yml index b0825024..4394fbf5 100644 --- a/tests/tests_bool_null_not_allowed.yml +++ b/tests/tests_bool_null_not_allowed.yml @@ -9,8 +9,7 @@ - name: Validate no boolean true values for bootloader values block: - name: Try to pass boolean true for bootloader values - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml vars: bootloader_settings: - kernel: ALL @@ -39,8 +38,7 @@ - name: Validate no boolean false values for bootloader values block: - name: Try to pass boolean false for bootloader values - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml vars: bootloader_settings: - kernel: ALL @@ -69,8 +67,7 @@ - name: Validate no boolean null values for bootloader values block: - name: Try to pass boolean null for bootloader values - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml vars: bootloader_settings: - kernel: ALL diff --git a/tests/tests_default.yml b/tests/tests_default.yml index e02f2717..d36d72d3 100644 --- a/tests/tests_default.yml +++ b/tests/tests_default.yml @@ -2,11 +2,9 @@ --- - name: Ensure that the role runs with default parameters hosts: all - gather_facts: false # for testing the role fact gathering tasks: - name: Skip on s390x architecture include_tasks: tasks/skip_on_s390x.yml - name: Run with default parameters - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml diff --git a/tests/tests_include_vars_from_parent.yml b/tests/tests_include_vars_from_parent.yml index 175814b6..0c53a4c5 100644 --- a/tests/tests_include_vars_from_parent.yml +++ b/tests/tests_include_vars_from_parent.yml @@ -1,7 +1,6 @@ --- - name: Test role include variable override hosts: all - gather_facts: true tasks: - name: Skip on s390x architecture include_tasks: tasks/skip_on_s390x.yml diff --git a/tests/tests_password.yml b/tests/tests_password.yml index 3f32ada4..d7778880 100644 --- a/tests/tests_password.yml +++ b/tests/tests_password.yml @@ -2,7 +2,6 @@ --- - name: Test bootloader_settings variable hosts: all - gather_facts: false tasks: - name: Skip on s390x architecture include_tasks: tasks/skip_on_s390x.yml @@ -12,8 +11,7 @@ - name: Set boot loader password vars: bootloader_password: test-pass - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Get contents of {{ __bootloader_user_conf }} command: cat {{ __bootloader_user_conf }} @@ -26,8 +24,7 @@ - name: Remove boot loader password vars: bootloader_remove_password: true - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Get stat of {{ __bootloader_user_conf }} stat: @@ -41,5 +38,4 @@ - name: Remove boot loader password vars: bootloader_remove_password: true - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml diff --git a/tests/tests_settings.yml b/tests/tests_settings.yml index 9b8a0dbb..061d50f3 100644 --- a/tests/tests_settings.yml +++ b/tests/tests_settings.yml @@ -2,7 +2,6 @@ --- - name: Test bootloader_settings variable hosts: all - gather_facts: false tags: - tests::reboot vars: @@ -16,8 +15,7 @@ - name: Get bootloader_facts vars: bootloader_gather_facts: true - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Skip test on ostree systems meta: end_host @@ -83,8 +81,7 @@ path: "{{ __default_kernel.kernel }}" default: true bootloader_timeout: 6 - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Flush handlers meta: flush_handlers @@ -129,8 +126,7 @@ - name: option_with_value state: absent bootloader_timeout: 4 - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Flush handlers meta: flush_handlers @@ -168,8 +164,7 @@ value: tty0 state: present bootloader_timeout: 4 - include_role: - name: linux-system-roles.bootloader + include_tasks: tasks/run_role_with_clear_facts.yml - name: Flush handlers meta: flush_handlers