diff --git a/changelogs/fragments/yum-enable-missing-repo.yaml b/changelogs/fragments/yum-enable-missing-repo.yaml new file mode 100644 index 0000000000..15cc854f75 --- /dev/null +++ b/changelogs/fragments/yum-enable-missing-repo.yaml @@ -0,0 +1,3 @@ +--- +bugfixes: + - "yum - gracefully handle failure case of enabling a non existent repo, as the yum cli does (Fixes https://github.com/ansible/ansible/issues/52582)" diff --git a/lib/ansible/modules/packaging/os/yum.py b/lib/ansible/modules/packaging/os/yum.py index f765538a14..b16dcaa31d 100644 --- a/lib/ansible/modules/packaging/os/yum.py +++ b/lib/ansible/modules/packaging/os/yum.py @@ -332,7 +332,7 @@ EXAMPLES = ''' ''' from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native +from ansible.module_utils._text import to_native, to_text from ansible.module_utils.urls import fetch_url from ansible.module_utils.yumdnf import YumDnf, yumdnf_argument_spec @@ -390,6 +390,26 @@ class YumModule(YumDnf): self.pkg_mgr_name = "yum" self.lockfile = '/var/run/yum.pid' + def _enablerepos_with_error_checking(self, yumbase): + # NOTE: This seems unintuitive, but it mirrors yum's CLI bahavior + if len(self.enablerepo) == 1: + try: + yumbase.repos.enableRepo(self.enablerepo[0]) + except yum.Errors.YumBaseError as e: + if u'repository not found' in to_text(e): + self.module.fail_json(msg="Repository %s not found." % self.enablerepo[0]) + else: + raise e + else: + for rid in self.enablerepo: + try: + yumbase.repos.enableRepo(rid) + except yum.Errors.YumBaseError as e: + if u'repository not found' in to_text(e): + self.module.warn("Repository %s not found." % rid) + else: + raise e + def yum_base(self): my = yum.YumBase() my.preconf.debuglevel = 0 @@ -459,8 +479,7 @@ class YumModule(YumDnf): my = self.yum_base() for rid in self.disablerepo: my.repos.disableRepo(rid) - for rid in self.enablerepo: - my.repos.enableRepo(rid) + self._enablerepos_with_error_checking(my) e, m, _ = my.rpmdb.matchPackageNames([pkgspec]) pkgs = e + m @@ -514,8 +533,7 @@ class YumModule(YumDnf): my = self.yum_base() for rid in self.disablerepo: my.repos.disableRepo(rid) - for rid in self.enablerepo: - my.repos.enableRepo(rid) + self._enablerepos_with_error_checking(my) e, m, _ = my.pkgSack.matchPackageNames([pkgspec]) pkgs = e + m @@ -554,8 +572,7 @@ class YumModule(YumDnf): my = self.yum_base() for rid in self.disablerepo: my.repos.disableRepo(rid) - for rid in self.enablerepo: - my.repos.enableRepo(rid) + self._enablerepos_with_error_checking(my) pkgs = my.returnPackagesByDep(pkgspec) + my.returnInstalledPackagesByDep(pkgspec) if not pkgs: @@ -595,8 +612,7 @@ class YumModule(YumDnf): my = self.yum_base() for rid in self.disablerepo: my.repos.disableRepo(rid) - for rid in self.enablerepo: - my.repos.enableRepo(rid) + self._enablerepos_with_error_checking(my) try: pkgs = my.returnPackagesByDep(req_spec) + my.returnInstalledPackagesByDep(req_spec) @@ -1438,8 +1454,7 @@ class YumModule(YumDnf): current_repos = my.repos.repos.keys() if self.enablerepo: try: - for rid in self.enablerepo: - my.repos.enableRepo(rid) + self._enablerepos_with_error_checking(my) new_repos = my.repos.repos.keys() for i in new_repos: if i not in current_repos: diff --git a/test/integration/targets/yum/tasks/yum.yml b/test/integration/targets/yum/tasks/yum.yml index 29da992560..12027d7a2f 100644 --- a/test/integration/targets/yum/tasks/yum.yml +++ b/test/integration/targets/yum/tasks/yum.yml @@ -92,6 +92,43 @@ - "yum_result is success" - "not yum_result is changed" +# This test case is unfortunately distro specific because we have to specify +# repo names which are not the same across Fedora/RHEL/CentOS for base/updates +- name: install sos again with missing repo enablerepo + yum: + name: sos + state: present + enablerepo: + - "thisrepodoesnotexist" + - "base" + - "updates" + disablerepo: "*" + register: yum_result + when: ansible_distribution == 'CentOS' +- name: verify no change on fourth install with missing repo enablerepo (yum) + assert: + that: + - "yum_result is success" + - "yum_result is not changed" + when: ansible_distribution == 'CentOS' + +- name: install sos again with only missing repo enablerepo + yum: + name: sos + state: present + enablerepo: "thisrepodoesnotexist" + ignore_errors: true + register: yum_result +- name: verify no change on fifth install with only missing repo enablerepo (yum) + assert: + that: + - "yum_result is not success" + when: ansible_pkg_mgr == 'yum' +- name: verify no change on fifth install with only missing repo enablerepo (dnf) + assert: + that: + - "yum_result is success" + when: ansible_pkg_mgr == 'dnf' # INSTALL AGAIN WITH LATEST - name: install sos again with state latest in check mode