Note: This is a public test instance of Red Hat Bugzilla. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback at bugzilla.redhat.com.

Bug 1967925

Summary: [RFE] Provide API to set repo configuration options as string
Product: [Fedora] Fedora Reporter: Jiri Konecny <jkonecny>
Component: dnfAssignee: Jaroslav Rohel <jrohel>
Status: POST --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: dmach, jmracek, jrohel, mblaha, mhatina, ngompa13, packaging-team-maint, pkratoch, rpm-software-management, vmukhame, vponcova
Target Milestone: ---Keywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1665453    

Description Jiri Konecny 2021-06-04 12:41:50 UTC
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

Comment 1 Jaroslav Rohel 2021-06-14 15:48:36 UTC
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.

Comment 2 Jaroslav Rohel 2021-06-14 16:51:57 UTC
`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.

Comment 3 Jaroslav Rohel 2021-06-18 09:27:20 UTC
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