rpm-software-management / dnf

Package manager based on libdnf and libsolv. Replaces YUM.
GNU General Public License v2.0
1.24k stars 413 forks source link

[API] Add option to skip or disable faulty repos in Base.fill_sack() #1925

Closed EmersonPrado closed 1 year ago

EmersonPrado commented 1 year ago

I intend to write a Puppet external custom fact, using DNF's Python API, which would collect all DNF modules data and output as YAML data, ready to be consumed by Puppet Facter.

If any of the DNF repository fails, the DNF Python API fails in the fill_sack step.

My code relevant excerpt:

base = Base()
base.read_all_repos()
base.fill_sack()

This last call fails with:

Traceback (most recent call last):
  File "/tmp/vagrant-puppet/modules-f66d94f6e6659fdb4d59d354e75134fe/dnf_modules/facts.d/dnf_modules.py", line 50, in <module>
    dnf_module_objs = list_module_objs()
  File "/tmp/vagrant-puppet/modules-f66d94f6e6659fdb4d59d354e75134fe/dnf_modules/facts.d/dnf_modules.py", line 27, in list_module_objs
    base.fill_sack()
  File "/usr/lib/python3.9/site-packages/dnf/base.py", line 401, in fill_sack
    self._add_repo_to_sack(r)
  File "/usr/lib/python3.9/site-packages/dnf/base.py", line 141, in _add_repo_to_sack
    repo.load()
  File "/usr/lib/python3.9/site-packages/dnf/repo.py", line 580, in load
    raise dnf.exceptions.RepoError(str(e))
dnf.exceptions.RepoError: Failed to download metadata for repo 'baseos': Cannot prepare internal mirrorlist: Status code: 404 for https://mirrors.rockylinux.org/mirrorlist?arch=x86_64&repo=BaseOS-9$rltype (IP: 151.101.206.132)

I understand the repo issue has to be dealt with. But I'd like my Python code to keep running, with the working repos, to yield useful information, while the repo is fixed elsewhere.

Method Base.fill_sack already uses attribute Base.repos.iter_enabled.skip_if_unavailable or something like that for the purpose I need. But I think this attribute is not available for the Base.fill_sack caller:

    def fill_sack(self, load_system_repo=True, load_available_repos=True):
        ...
                for r in self.repos.iter_enabled():
                    try:
                        self._add_repo_to_sack(r)
                        ...
                    except dnf.exceptions.RepoError as e:
                        ...
                        if r.skip_if_unavailable is False:
                            raise

So my request is a parameter in Base.fill_sack which could set skip_if_unavailable to True

kontura commented 1 year ago

You can already configure this (and a lot more other things) with the API using the dnf.conf.Conf. You can check the docs: https://dnf.readthedocs.io/en/latest/api_conf.html, for a list of all configuration options (both main dnf config and repo specific config) you can check: https://dnf.readthedocs.io/en/latest/conf_ref.html.

skip_if_unavailable is an option for both main and repo so assuming your repo configuration doesn't override the value to False you can do:

import dnf

base = dnf.Base()
conf = base.conf
conf.skip_if_unavailable = True
base.read_all_repos()
base.fill_sack()
EmersonPrado commented 1 year ago

Perfect! Thanks a lot!