From 99a3346de6d3af335c9f1487e1251807b1e2c273 Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Thu, 29 May 2025 11:51:12 +0200 Subject: [PATCH] dnf5 - handle all specific libdnf5 exceptions (#85175) Fixes #84634 --- .../fragments/84634-dnf5-all-exceptions.yml | 2 ++ lib/ansible/modules/dnf5.py | 36 ++++++++----------- test/integration/targets/dnf/tasks/repo.yml | 27 ++++++++++++++ 3 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 changelogs/fragments/84634-dnf5-all-exceptions.yml diff --git a/changelogs/fragments/84634-dnf5-all-exceptions.yml b/changelogs/fragments/84634-dnf5-all-exceptions.yml new file mode 100644 index 00000000000..f84a93c2ed0 --- /dev/null +++ b/changelogs/fragments/84634-dnf5-all-exceptions.yml @@ -0,0 +1,2 @@ +bugfixes: + - "dnf5 - handle all libdnf5 specific exceptions (https://github.com/ansible/ansible/issues/84634)" diff --git a/lib/ansible/modules/dnf5.py b/lib/ansible/modules/dnf5.py index 0f11a21ca15..a0e4a4ef5aa 100644 --- a/lib/ansible/modules/dnf5.py +++ b/lib/ansible/modules/dnf5.py @@ -365,7 +365,7 @@ from ansible.module_utils.yumdnf import YumDnf, yumdnf_argument_spec libdnf5 = None # Through dnf5-5.2.12 all exceptions raised through swig became RuntimeError -LIBDNF5_ERROR = RuntimeError +LIBDNF5_ERRORS = RuntimeError def is_installed(base, spec): @@ -423,7 +423,9 @@ def is_newer_version_installed(base, spec): try: spec_nevra = next(iter(libdnf5.rpm.Nevra.parse(spec))) - except (LIBDNF5_ERROR, StopIteration): + except LIBDNF5_ERRORS: + return False + except StopIteration: return False spec_version = spec_nevra.get_version() @@ -517,7 +519,7 @@ class Dnf5Module(YumDnf): os.environ["LANGUAGE"] = os.environ["LANG"] = locale global libdnf5 - global LIBDNF5_ERROR + global LIBDNF5_ERRORS has_dnf = True try: import libdnf5 # type: ignore[import] @@ -526,7 +528,7 @@ class Dnf5Module(YumDnf): try: import libdnf5.exception # type: ignore[import-not-found] - LIBDNF5_ERROR = libdnf5.exception.Error + LIBDNF5_ERRORS = (libdnf5.exception.Error, libdnf5.exception.NonLibdnf5Exception) except (ImportError, AttributeError): pass @@ -581,15 +583,7 @@ class Dnf5Module(YumDnf): if self.conf_file: conf.config_file_path = self.conf_file - try: - base.load_config() - except LIBDNF5_ERROR as e: - self.module.fail_json( - msg=str(e), - conf_file=self.conf_file, - failures=[], - rc=1, - ) + base.load_config() if self.releasever is not None: variables = base.get_vars() @@ -745,19 +739,13 @@ class Dnf5Module(YumDnf): goal.add_install(spec, settings) elif self.state in {"absent", "removed"}: for spec in self.names: - try: - goal.add_remove(spec, settings) - except LIBDNF5_ERROR as e: - self.module.fail_json(msg=str(e), failures=[], rc=1) + goal.add_remove(spec, settings) if self.autoremove: for pkg in get_unneeded_pkgs(base): goal.add_rpm_remove(pkg, settings) goal.set_allow_erasing(self.allowerasing) - try: - transaction = goal.resolve() - except LIBDNF5_ERROR as e: - self.module.fail_json(msg=str(e), failures=[], rc=1) + transaction = goal.resolve() if transaction.get_problems(): failures = [] @@ -833,7 +821,11 @@ def main(): auto_install_module_deps=dict(type="bool", default=True), ) ) - Dnf5Module(AnsibleModule(**yumdnf_argument_spec)).run() + module = AnsibleModule(**yumdnf_argument_spec) + try: + Dnf5Module(module).run() + except LIBDNF5_ERRORS as e: + module.fail_json(msg=str(e), failures=[], rc=1) if __name__ == "__main__": diff --git a/test/integration/targets/dnf/tasks/repo.yml b/test/integration/targets/dnf/tasks/repo.yml index 4c758883119..302b01eee92 100644 --- a/test/integration/targets/dnf/tasks/repo.yml +++ b/test/integration/targets/dnf/tasks/repo.yml @@ -629,3 +629,30 @@ loop: - provides-package - provided-package + +- name: Test failures occured during loading repositories are properly handled + vars: + repo_name: test-non-existing-gpgkey-file + block: + - yum_repository: + name: "{{ repo_name }}" + baseurl: "file://{{ repodir }}" + description: "{{ repo_name }}" + repo_gpgcheck: true + skip_if_unavailable: false + + - dnf: + name: dinginessentail + enablerepo: "{{ repo_name }}" + disablerepo: "*" + ignore_errors: true + register: r + + - assert: + that: + - r is failed + - r.msg is contains("Couldn't open file") + always: + - file: + name: /etc/yum.repos.d/{{ repo_name }}.repo + state: absent