From 04b654247783c8946194e61f2e67abe03c3cd7de Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Thu, 19 Mar 2026 17:23:54 -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/run_role_with_clear_facts.yml | 37 +++++++++++++++++++++++ tests/tests_additional_packages.yml | 4 +-- tests/tests_all_options.yml | 4 +-- tests/tests_backup.yml | 6 ++-- tests/tests_custom_config.yml | 3 +- tests/tests_custom_drop_in.yml | 4 +-- tests/tests_custom_with_defaults.yml | 3 +- tests/tests_default.yml | 8 +++-- tests/tests_global_config.yml | 4 +-- tests/tests_global_config_mode.yml | 4 +-- tests/tests_global_drop_in.yml | 4 +-- tests/tests_global_drop_in_role.yml | 23 +++++++------- tests/tests_include_vars_from_parent.yml | 1 - tests/tests_indentation.yml | 4 +-- tests/tests_match.yml | 4 +-- tests/tests_no_skip_defaults.yml | 4 +-- tests/tests_precedence.yml | 4 +-- tests/tests_regenerate_defaults.yml | 4 +-- tests/tests_user_config.yml | 4 +-- 19 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 tests/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..4c53b858 --- /dev/null +++ b/tests/tasks/run_role_with_clear_facts.yml @@ -0,0 +1,37 @@ +--- +# Task file: clear_facts, run linux-system-roles.ssh,. +# 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.ssh + 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.ssh + tasks_from: "{{ __sr_tasks_from | default('main') }}" + public: "{{ __sr_public | default(false) }}" + when: __sr_failed_when | d(true) diff --git a/tests/tests_additional_packages.yml b/tests/tests_additional_packages.yml index 096eec5f..b5955030 100644 --- a/tests/tests_additional_packages.yml +++ b/tests/tests_additional_packages.yml @@ -1,7 +1,6 @@ --- - name: Verify default packages as well as additional are installed hosts: all - gather_facts: true vars: additional_package: >- {% if ansible_facts['distribution'] in [ 'RedHat', 'CentOS' ] and @@ -16,8 +15,7 @@ {% endif %} tasks: - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_additional_packages: - "{{ additional_package | trim }}" diff --git a/tests/tests_all_options.yml b/tests/tests_all_options.yml index 2619508e..56e0e835 100644 --- a/tests/tests_all_options.yml +++ b/tests/tests_all_options.yml @@ -1,7 +1,6 @@ --- - name: Test we can handle all configuration options documented in manual page hosts: all - gather_facts: true vars: ssh_c: {} pkg_mgr: "{{ (ansible_facts['distribution_version'] | int > 7) | @@ -102,8 +101,7 @@ "{{ ssh_options.stdout_lines }}" - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: __ssh_supports_validate: false ssh_config_file: /etc/test_ssh_config diff --git a/tests/tests_backup.yml b/tests/tests_backup.yml index 95c258ea..20feb1f2 100644 --- a/tests/tests_backup.yml +++ b/tests/tests_backup.yml @@ -22,8 +22,7 @@ with_items: "{{ backup_files.files }}" - name: Configure ssh without creating backup - ansible.builtin.include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_backup: false @@ -34,8 +33,7 @@ register: no_backup - name: Configure ssh again with different configuration and with backup - ansible.builtin.include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_ForwardX11Trusted: 'yes' # noqa var-naming register: second_run diff --git a/tests/tests_custom_config.yml b/tests/tests_custom_config.yml index bf9bc472..8ac2a20a 100644 --- a/tests/tests_custom_config.yml +++ b/tests/tests_custom_config.yml @@ -3,8 +3,7 @@ hosts: all tasks: - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh: Compression: true diff --git a/tests/tests_custom_drop_in.yml b/tests/tests_custom_drop_in.yml index 16484ab1..5dae1aae 100644 --- a/tests/tests_custom_drop_in.yml +++ b/tests/tests_custom_drop_in.yml @@ -1,7 +1,6 @@ --- - name: Test we can write any other configuration file as a drop-in hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /tmp/ssh_config.d_00-ansible.conf @@ -21,8 +20,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh: Compression: true diff --git a/tests/tests_custom_with_defaults.yml b/tests/tests_custom_with_defaults.yml index 1748dcf1..02c2930d 100644 --- a/tests/tests_custom_with_defaults.yml +++ b/tests/tests_custom_with_defaults.yml @@ -3,8 +3,7 @@ hosts: all tasks: - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh: Compression: true diff --git a/tests/tests_default.yml b/tests/tests_default.yml index 7e92fb08..b1f457d2 100644 --- a/tests/tests_default.yml +++ b/tests/tests_default.yml @@ -11,9 +11,11 @@ - name: Ensure that the role runs with default parameters hosts: all - gather_facts: false - roles: - - linux-system-roles.ssh + tasks: + - name: Run role + include_tasks: tasks/run_role_with_clear_facts.yml + vars: + __sr_public: true - name: Restore configuration files hosts: all diff --git a/tests/tests_global_config.yml b/tests/tests_global_config.yml index 2a014c36..e159a1e0 100644 --- a/tests/tests_global_config.yml +++ b/tests/tests_global_config.yml @@ -1,6 +1,5 @@ --- - name: Test we can write global config with default configuration - gather_facts: true hosts: all vars: __ssh_test_backup_files: @@ -12,8 +11,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: # noqa var-naming ssh: diff --git a/tests/tests_global_config_mode.yml b/tests/tests_global_config_mode.yml index a417c7eb..70b0344a 100644 --- a/tests/tests_global_config_mode.yml +++ b/tests/tests_global_config_mode.yml @@ -1,7 +1,6 @@ --- - name: Test we can write global config with given permissions hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/00-ansible.conf @@ -16,8 +15,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh: Compression: true diff --git a/tests/tests_global_drop_in.yml b/tests/tests_global_drop_in.yml index 01f61383..5117cdb3 100644 --- a/tests/tests_global_drop_in.yml +++ b/tests/tests_global_drop_in.yml @@ -1,7 +1,6 @@ --- - name: Test forced creation of the configuration snippet in drop in directory hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/99-last.conf @@ -20,8 +19,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_drop_in_name: 99-last ssh: diff --git a/tests/tests_global_drop_in_role.yml b/tests/tests_global_drop_in_role.yml index b6d51612..da7cbcb5 100644 --- a/tests/tests_global_drop_in_role.yml +++ b/tests/tests_global_drop_in_role.yml @@ -1,7 +1,6 @@ --- - name: Test forced creation of the configuration snippet in drop in directory hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/99-last.conf @@ -12,16 +11,18 @@ - name: Run role hosts: all - roles: - - linux-system-roles.ssh - vars: - ssh_drop_in_name: 99-last - ssh: - GSSAPIAuthentication: false - Host: - Condition: example - Hostname: example.com - User: somebody + tasks: + - name: Run role + include_tasks: tasks/run_role_with_clear_facts.yml + vars: + __sr_public: true + ssh_drop_in_name: 99-last + ssh: + GSSAPIAuthentication: false + Host: + Condition: example + Hostname: example.com + User: somebody - name: Verify drop in file configuration hosts: all diff --git a/tests/tests_include_vars_from_parent.yml b/tests/tests_include_vars_from_parent.yml index ed74fdfb..59243b13 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: Create var file in caller that can override the one in called role delegate_to: localhost diff --git a/tests/tests_indentation.yml b/tests/tests_indentation.yml index 15dff2ef..2746bbb5 100644 --- a/tests/tests_indentation.yml +++ b/tests/tests_indentation.yml @@ -1,6 +1,5 @@ --- - name: Test indentation - gather_facts: true hosts: all vars: ssh_config_file: /tmp/ssh_config @@ -9,8 +8,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: # noqa var-naming ssh: diff --git a/tests/tests_match.yml b/tests/tests_match.yml index caeb582e..0c6c260d 100644 --- a/tests/tests_match.yml +++ b/tests/tests_match.yml @@ -1,7 +1,6 @@ --- - name: Verify Match and Host keywords are rendered as expected hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/00-ansible.conf @@ -12,8 +11,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: # noqa var-naming ssh: diff --git a/tests/tests_no_skip_defaults.yml b/tests/tests_no_skip_defaults.yml index a1a1ec76..f34fd892 100644 --- a/tests/tests_no_skip_defaults.yml +++ b/tests/tests_no_skip_defaults.yml @@ -1,7 +1,6 @@ --- - name: Test we can write global config with default configuration hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/00-ansible.conf @@ -22,8 +21,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_skip_defaults: false ssh_config_file: /tmp/ssh_config_with_defaults diff --git a/tests/tests_precedence.yml b/tests/tests_precedence.yml index 8f91d513..133bb3ac 100644 --- a/tests/tests_precedence.yml +++ b/tests/tests_precedence.yml @@ -1,7 +1,6 @@ --- - name: Test options precedence when mixing ssh dict and ssh_* variables hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/00-ansible.conf @@ -12,8 +11,7 @@ include_tasks: tasks/backup.yml - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: # noqa var-naming ssh: diff --git a/tests/tests_regenerate_defaults.yml b/tests/tests_regenerate_defaults.yml index bfbd4f04..26b164c3 100644 --- a/tests/tests_regenerate_defaults.yml +++ b/tests/tests_regenerate_defaults.yml @@ -1,7 +1,6 @@ --- - name: Regenerate default configuration file hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/00-ansible.conf @@ -36,8 +35,7 @@ path: /etc/ssh/ssh_config - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_config_file: /etc/ssh/ssh_config ssh_skip_defaults: false diff --git a/tests/tests_user_config.yml b/tests/tests_user_config.yml index 5c4ac4df..d56e8b69 100644 --- a/tests/tests_user_config.yml +++ b/tests/tests_user_config.yml @@ -1,7 +1,6 @@ --- - name: Test a creation of configuration file in the user directory hosts: all - gather_facts: true vars: __ssh_test_backup_files: - /etc/ssh/ssh_config.d/00-ansible.conf @@ -23,8 +22,7 @@ group: "{{ username }}" - name: Run role - include_role: - name: linux-system-roles.ssh + include_tasks: tasks/run_role_with_clear_facts.yml vars: ssh_user: "{{ username }}" ssh: