Description of problem: Anaconda now have KS commands for setting up repository configuration options. We are using these commands to set options to the DNF repo configuration objects. From time to time we have a request to add an option which is needed for a specific use-case and wouldn't be that useful otherwise (mostly to build an ISO). We want to avoid these getting in because the `repo` KS command is getting bigger and bigger and we have to support these. To solve these requests we would like to add something generic which would take this configuration as "key=value" and we would then just pass this to DNF. From my understanding DNF already have somehow similar code to read command-line configurations, so we are asking for adding this to the DNF API where we could use this functionality in Anaconda. Actual results: DNF don't have API to set repo configuration as "key=value" string. Expected results: DNF will add an API to set repo configuration as "key=value" or another similar format. Additional info: Upstream PR requested to add "priority" and "modules_hotfixes" configuration where this idea started. https://github.com/pykickstart/pykickstart/pull/378
I'm thinking about how to achieve the required functionality with the current DNF API. A possible solution: dnf.repo.Repo object allows to get/set repository configuration options using getattr/setattr. Example of a function using the existing DNF API: ``` def repo_set_opt(dnf_repo_object, option_name, option_value): if hasattr(dnf_repo_object, option_name): setattr(dnf_repo_object, option_name, option_value) else: raise Exception('Unknown option: {}'.format(option_name)) ``` Example of use (description of result in comment): repo_set_opt(repo, 'metadata_expire', '4d') # sets `metadata_expire` to 4 days repo_set_opt(repo, 'metadata_expire', '4dr') # dnf.exceptions.ConfigError: Error parsing '4dr': could not convert '4dr' to seconds repo_set_opt(repo, 'm_expire', '4d') # Exception: Unknown option: m_expire repo_set_opt(repo, 'enabled', '1') # Sets boolean value `enabled` to True repo_set_opt(repo, 'enabled', 'ewe') # dnf.exceptions.ConfigError: Error parsing 'ewe': invalid boolean value 'ewe' repo_set_opt(repo, 'excludepkgs', 'pkg1,pkg2') # sets `excludepkgs` list print(getattr(repo,'excludepkgs')) # test of previous action, prints list "['pkg1', 'pkg2']" Note: The same parser (rules for parsing values) is used as for the `--setopt` DNF argument and configuration values in the files.
`setattr` is a very powerful function. I give a safer example. Added test to prevent object methods from being overwritten. ``` def repo_set_opt(dnf_repo_object, option_name, option_value): if hasattr(dnf_repo_object, option_name) and not callable(getattr(dnf_repo_object, option_name)): setattr(dnf_repo_object, option_name, option_value) else: raise Exception('Unknown option: {}'.format(option_name)) ``` It is still not a perfect solution. But it could be enough.
As I wrote, `setattr` is still not perfect. E.g. "append" type options (eg "excludepkgs") are handled as general (not append) options. So, I created an API for setting configuration options using string arguments. The API also works for setting global configuration options, not just repositories. https://github.com/rpm-software-management/dnf/pull/1779
FEDORA-2021-e14e416a38 has been pushed to the Fedora 36 stable repository. If problem still persists, please make note of it in this bug report.