diff --git a/changelogs/fragments/ansible-test-main-check.yml b/changelogs/fragments/ansible-test-main-check.yml new file mode 100644 index 00000000000..d063682a302 --- /dev/null +++ b/changelogs/fragments/ansible-test-main-check.yml @@ -0,0 +1,6 @@ +minor_changes: + - ansible-test - The ``validate-modules`` sanity test no longer enforces the ``missing-if-name-main``, ``last-line-main-call`` or ``missing-main-call`` checks + on non-deleted Ansible modules. Modules are still required to instantiate ``AnsibleModule`` when ``__name__ == '__main__'``. + - ansible-test - The ``import`` sanity test now requires that Ansible modules guard instantiation of ``AnsibleModule`` with a ``if __name__ == '__main__'`` + conditional, or equivalent logic. + - ansible-test - The ``import`` sanity test now requires that non-modules do not instantiate ``AnsibleModule`` on import. diff --git a/test/lib/ansible_test/_data/sanity/import/importer.py b/test/lib/ansible_test/_data/sanity/import/importer.py index 5fae766c68c..0757b677ddc 100755 --- a/test/lib/ansible_test/_data/sanity/import/importer.py +++ b/test/lib/ansible_test/_data/sanity/import/importer.py @@ -238,6 +238,8 @@ def main(): capture_normal = Capture() capture_main = Capture() + run_module_ok = False + try: with monitor_sys_modules(path, messages): with restrict_imports(path, name, messages, restrict_to_module_paths): @@ -245,13 +247,19 @@ def main(): import_module(name) if run_main: + run_module_ok = is_ansible_module + with monitor_sys_modules(path, messages): with restrict_imports(path, name, messages, restrict_to_module_paths): with capture_output(capture_main): runpy.run_module(name, run_name='__main__', alter_sys=True) except ImporterAnsibleModuleException: # module instantiated AnsibleModule without raising an exception - pass + if not run_module_ok: + if is_ansible_module: + report_message(path, 0, 0, 'module-guard', "AnsibleModule instantiation not guarded by `if __name__ == '__main__'`", messages) + else: + report_message(path, 0, 0, 'non-module', "AnsibleModule instantiated by import of non-module", messages) except BaseException as ex: # pylint: disable=locally-disabled, broad-except # intentionally catch all exceptions, including calls to sys.exit exc_type, _exc, exc_tb = sys.exc_info() diff --git a/test/lib/ansible_test/_data/sanity/validate-modules/validate_modules/main.py b/test/lib/ansible_test/_data/sanity/validate-modules/validate_modules/main.py index 8b8fceab55a..865a05681ab 100644 --- a/test/lib/ansible_test/_data/sanity/validate-modules/validate_modules/main.py +++ b/test/lib/ansible_test/_data/sanity/validate-modules/validate_modules/main.py @@ -545,7 +545,7 @@ class ModuleValidator(Validator): **options['error'] ) - def _find_module_utils(self, main): + def _find_module_utils(self): linenos = [] found_basic = False for child in self.ast.body: @@ -2228,8 +2228,7 @@ class ModuleValidator(Validator): self._validate_ansible_module_call(docs) self._check_for_sys_exit() self._find_rejectlist_imports() - main = self._find_main_call() - self._find_module_utils(main) + self._find_module_utils() self._find_has_import() first_callable = self._get_first_callable() self._ensure_imports_below_docs(doc_info, first_callable)