From 674a0973fcdc3466a0cb80f6cafe8d3252e8e7cd Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Fri, 16 Feb 2024 21:01:43 +0100 Subject: [PATCH] Make "dnf4" equivalent to "dnf" And while on it, unify the `system_PM_command` with the rest of PM-specific commands. Fix the Packit/TF configuration to use the mock-deps repo. Fixes: https://github.com/rpm-software-management/mock/issues/1271 --- .packit.yaml | 7 +++ mock/docs/site-defaults.cfg | 57 +++++++++++-------- .../setup-playbook/tasks/main.yml | 4 ++ mock/mock.spec | 2 +- mock/py/mockbuild/config.py | 30 +++++++--- mock/py/mockbuild/package_manager.py | 20 ++++--- .../dnf4-config-is-alias-to-dnf.feature | 21 +++++++ 7 files changed, 100 insertions(+), 41 deletions(-) create mode 100644 releng/release-notes-next/dnf4-config-is-alias-to-dnf.feature diff --git a/.packit.yaml b/.packit.yaml index b9a3edfb5..db20bb1e0 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -63,3 +63,10 @@ jobs: - <<: *pr_test trigger: commit + +tf_extra_params: + # https://cockpit-project.org/blog/tmt-cross-project-testing.html + environments: + - artifacts: + - type: repository-file + id: https://copr.fedorainfracloud.org/coprs/g/mock/mock-deps/repo/fedora-$releasever/group_mock-mock-deps-fedora-$releasever.repo diff --git a/mock/docs/site-defaults.cfg b/mock/docs/site-defaults.cfg index 6e990004b..8d470e89b 100644 --- a/mock/docs/site-defaults.cfg +++ b/mock/docs/site-defaults.cfg @@ -91,10 +91,12 @@ # variable use_container_host_hostname or %_buildhost macro can override this # config_opts['hostname'] = 'my.own.hostname' -# The default package manager is DNF -# config_opts['package_manager'] = 'dnf' -# If you want to use DNF, set it to 'dnf'. To use DNF you need to have dnf and -# dnf-plugins-core installed +# The default package manager is DNF4. The options are: +# - 'dnf4' for DNF4 (Python) https://github.com/rpm-software-management/dnf +# - 'dnf5' for DNF5 (C++) https://github.com/rpm-software-management/dnf5 +# The major version of DNF5 will remain '5' indefinitely, see #1271. +# - 'yum' for YUM https://github.com/rpm-software-management/yum +#config_opts['package_manager'] = 'dnf4' # Number of attempts to execute package manager's action, and delay between # attempts (seconds). This is useful e.g. if the build is done against @@ -131,12 +133,9 @@ # "bootstrap" chroot we initialize the target chroot. #config_opts['use_bootstrap'] = True -#config_opts['system_yum_command'] = '/usr/bin/yum' -#config_opts['system_dnf_command'] = '/usr/bin/dnf' - # The bootstrap chroot is normally installed using a package manager from host, # but in some cases even this isn't possible (e.g. installing rather new ZSTD -# compressed dnf.rpm package by 'dnf_install_command' on epel-7 host). In such +# compressed dnf.rpm package by 'dnf4_install_command' on epel-7 host). In such # case, you may need to have "bootstrap" chroot pre-populated from a container # image first (where the package manager stack is already pre-installed, so # mock doesn't have to). @@ -476,7 +475,7 @@ # # You can configure how DNF (and other packager managers) will be used with # Mock. Each option is specific to a concrete package manager, and then it -# is appropriately prefixed by , namely `dnf5_`, `dnf_`, `yum_` or +# is appropriately prefixed by , namely `dnf5_`, `dnf4_`, `yum_` or # `microdnf_`. Mock attempts to use appropriate package manager depending on # the `package_manager` configuration option. # @@ -487,6 +486,11 @@ # path, searched both on host (to install bootstrap chroot) or in # bootstrap chroot (to install buildroot) # +# '_system_command' (e.g. yum_system_command) - the package manager +# executable searched on host only in case of _command not found. +# This may be useful for "bootstrap=off" scenarios with the package +# manager installed in a custom location. +# # '_common_opts' (e.g. dnf5_common_opts) - options that are passed to # every single command execution of the '_command' by Mock, minus # '_avoid_opts', see below @@ -508,7 +512,7 @@ # might want to use 'use_bootstrap_image' instead (then bootstrap chroot # is just "downloaded", not installed). # -# '_disable_plugins (e.g. dnf_disable_plugins) - list of package +# '_disable_plugins (e.g. dnf4_disable_plugins) - list of package # manager plugins that should be always disabled when Mock executes the # '_command' (e.g. versionlock, with Mock we always want to build # against the latest package versions available in buildroot) @@ -518,29 +522,36 @@ # build dependencies. There's no 'yum builddep' (sub)command though, # but /bin/yum-builddep. Use this option to override the default. # -# '_builddep_opts (e.g. dnf_builddep_opts) - list of additional +# '_builddep_opts (e.g. dnf5_builddep_opts) - list of additional # options to always use with the builddep command -# DNF (or DNF4, Python) - https://github.com/rpm-software-management/dnf -#config_opts['dnf_command'] = '/usr/bin/dnf-3' -#config_opts['dnf_common_opts'] = ['--setopt=deltarpm=False', '--setopt=allow_vendor_change=yes', '--allowerasing'] -# DF5 sub-command 'builddep' doesn't support the '--allowerasing' option: -# https://github.com/rpm-software-management/dnf5/issues/461 -#config_opts["dnf5_avoid_opts"] = {"builddep": ["--allowerasing"]} -#config_opts['dnf_install_command'] = 'install python3-dnf python3-dnf-plugins-core' -#config_opts['dnf_disable_plugins'] = ['local', 'spacewalk', 'versionlock'] -#config_opts['dnf_builddep_opts'] = [] +# DNF4 specific options (Fedora <= 39, EL 8, 9 and 10) +# +# Don't be confused by the '-3' suffix in the DNF4 script. This is a +# historical artifact from when it was necessary to differentiate between +# 'Python 3' and 'Python 2' scripts. +#config_opts['dnf4_command'] = '/usr/bin/dnf-3' +#config_opts['dnf4_system_command'] = '/usr/bin/dnf' +#config_opts['dnf4_common_opts'] = ['--setopt=deltarpm=False', '--setopt=allow_vendor_change=yes', '--allowerasing'] +#config_opts['dnf4_install_command'] = 'install python3-dnf python3-dnf-plugins-core' +#config_opts['dnf4_disable_plugins'] = ['local', 'spacewalk', 'versionlock'] +#config_opts['dnf4_builddep_opts'] = [] -# DNF5 (DNF4 re-written in C++) https://github.com/rpm-software-management/dnf5 -# Known issue with DNF5: --forcearch is not supported by DNF5 -# https://github.com/rpm-software-management/dnf5/issues/112 +# DNF5 specific options (Fedora 40+ https://fedoraproject.org/wiki/Changes/BuildWithDNF5) +# #config_opts['dnf5_command'] = '/usr/bin/dnf5' +#config_opts['dnf5_system_command'] = '/usr/bin/dnf5' #config_opts['dnf5_common_opts'] = ['--setopt=deltarpm=False', '--setopt=allow_vendor_change=yes', '--allowerasing'] #config_opts['dnf5_install_command'] = 'install dnf5 dnf5-plugins' #config_opts['dnf5_disable_plugins'] = [] +# DF5 sub-command 'builddep' doesn't support the '--allowerasing' option: +# https://github.com/rpm-software-management/dnf5/issues/461 +#config_opts["dnf5_avoid_opts"] = {"builddep": ["--allowerasing"]} # YUM (for RHEL7 and older) - https://github.com/rpm-software-management/yum +# #config_opts['yum_command'] = '/usr/bin/yum' +#config_opts['yum_system_command'] = '/usr/bin/yum' #config_opts['yum_common_opts'] = [] #config_opts['yum_install_command'] = 'install yum yum-utils' #config_opts['yum_builddep_command'] = '/usr/bin/yum-builddep' diff --git a/mock/integration-tests/setup-playbook/tasks/main.yml b/mock/integration-tests/setup-playbook/tasks/main.yml index 977a35145..998ec55ab 100644 --- a/mock/integration-tests/setup-playbook/tasks/main.yml +++ b/mock/integration-tests/setup-playbook/tasks/main.yml @@ -3,6 +3,10 @@ community.general.copr: name: '@mock/mock-stable' +- name: up2date mock dependencies + community.general.copr: + name: '@mock/mock-deps' + - name: install mock and other needed packages package: name={{ packages }} state=latest vars: diff --git a/mock/mock.spec b/mock/mock.spec index 49548c6ec..a310f5038 100644 --- a/mock/mock.spec +++ b/mock/mock.spec @@ -53,7 +53,7 @@ Requires: python%{python3_pkgversion}-jinja2 Requires: python%{python3_pkgversion}-requests Requires: python%{python3_pkgversion}-rpm Requires: python%{python3_pkgversion}-pyroute2 -Requires: python%{python3_pkgversion}-templated-dictionary +Requires: python%{python3_pkgversion}-templated-dictionary >= 1.5 Requires: python%{python3_pkgversion}-backoff BuildRequires: python%{python3_pkgversion}-backoff BuildRequires: python%{python3_pkgversion}-devel diff --git a/mock/py/mockbuild/config.py b/mock/py/mockbuild/config.py index 4f29d9fcb..0f8cbd5fe 100644 --- a/mock/py/mockbuild/config.py +++ b/mock/py/mockbuild/config.py @@ -51,7 +51,19 @@ def nspawn_supported(): @traceLog() def setup_default_config_opts(): "sets up default configuration." - config_opts = TemplatedDictionary(alias_spec={'dnf.conf': ['yum.conf', 'dnf5.conf']}) + + alt_opts = {'dnf.conf': ['yum.conf', 'dnf5.conf', 'dnf4.conf']} + for alt in ["dnf_command", "dnf_common_opts", "dnf_install_command", + "dnf_disable_plugins", "dnf_avoid_opts"]: + alt_opts[alt.replace("dnf", "dnf4")] = [alt] + + for pm in ["dnf4", "dnf5", "yum", "microdnf"]: + alt_opts[f"{pm}_system_command"] = [f"system_{pm}_command"] + + alt_opts["dnf4_system_command"].append("system_dnf_command") + + config_opts = TemplatedDictionary(alias_spec=alt_opts) + config_opts['config_paths'] = [] config_opts['version'] = VERSION config_opts['basedir'] = '/var/lib/mock' # root name is automatically added to this @@ -318,20 +330,20 @@ def setup_default_config_opts(): # configurable commands executables config_opts['yum_command'] = '/usr/bin/yum' - config_opts['system_yum_command'] = '/usr/bin/yum' + config_opts['yum_system_command'] = '/usr/bin/yum' config_opts['yum_install_command'] = 'install yum yum-utils' config_opts['yum_builddep_command'] = '/usr/bin/yum-builddep' config_opts["yum_avoid_opts"] = {} - config_opts['dnf_command'] = '/usr/bin/dnf-3' - config_opts['system_dnf_command'] = '/usr/bin/dnf-3' - config_opts['dnf_common_opts'] = ['--setopt=deltarpm=False', '--setopt=allow_vendor_change=yes', '--allowerasing'] - config_opts['dnf_install_command'] = 'install python3-dnf python3-dnf-plugins-core' - config_opts['dnf_disable_plugins'] = ['local', 'spacewalk', 'versionlock'] - config_opts["dnf_avoid_opts"] = {} + config_opts['dnf4_command'] = '/usr/bin/dnf-3' + config_opts['dnf4_system_command'] = '/usr/bin/dnf-3' + config_opts['dnf4_common_opts'] = ['--setopt=deltarpm=False', '--setopt=allow_vendor_change=yes', '--allowerasing'] + config_opts['dnf4_install_command'] = 'install python3-dnf python3-dnf-plugins-core' + config_opts['dnf4_disable_plugins'] = ['local', 'spacewalk', 'versionlock'] + config_opts["dnf4_avoid_opts"] = {} config_opts['dnf5_command'] = '/usr/bin/dnf5' - config_opts['system_dnf5_command'] = '/usr/bin/dnf5' + config_opts['dnf5_system_command'] = '/usr/bin/dnf5' config_opts['dnf5_common_opts'] = ['--setopt=deltarpm=False', '--setopt=allow_vendor_change=yes', '--allowerasing'] config_opts['dnf5_install_command'] = 'install dnf5 dnf5-plugins' config_opts['dnf5_disable_plugins'] = [] diff --git a/mock/py/mockbuild/package_manager.py b/mock/py/mockbuild/package_manager.py index fdaf2d2ed..af3f24a24 100644 --- a/mock/py/mockbuild/package_manager.py +++ b/mock/py/mockbuild/package_manager.py @@ -18,10 +18,11 @@ from .mounts import BindMountPoint fallbacks = { - 'dnf': ['dnf', 'dnf5', 'yum'], - 'yum': ['yum', 'dnf', 'dnf5'], - 'microdnf': ['microdnf', 'dnf','dnf5', 'yum'], - 'dnf5': ['dnf5', 'dnf', 'yum'], + 'dnf4': ['dnf4', 'dnf5', 'yum'], + 'dnf': ['dnf4', 'dnf5', 'yum'], # backward-compat + 'yum': ['yum', 'dnf4', 'dnf5'], + 'microdnf': ['microdnf', 'dnf4', 'dnf5', 'yum'], + 'dnf5': ['dnf5', 'dnf4', 'yum'], } @@ -30,7 +31,7 @@ def package_manager_from_string(name): return Dnf5 if name == 'yum': return Yum - if name == 'dnf': + if name in ['dnf4', 'dnf']: # dnf for backward compat return Dnf if name == 'microdnf': return MicroDnf @@ -45,6 +46,9 @@ def package_manager_exists(pm_class, config_opts, chroot=None): return False # resolve symlinks, and detect that e.g. /bin/yum doesn't point to /bin/dnf real_pathname = os.path.realpath(pathname) + if name == 'dnf4': + # The DNF4 used to be /bin/dnf, not /bin/dnf4 + name = 'dnf' return name in real_pathname @@ -92,7 +96,7 @@ def package_manager_class_fallback(config_opts, buildroot, fallback): return pm_class - raise Exception("No package from {} found".format(fallbacks[desired])) + raise Exception(f"No package from {fallbacks[desired]} found, desired {desired}") def package_manager(buildroot, bootstrap_buildroot, fallback): @@ -122,7 +126,7 @@ def get_command(cls, config): if config.get("use_bootstrap_image", True): return command if config.get("use_bootstrap", False): - sys_command = config.get(f"system_{cls.name}_command") + sys_command = config.get(f"{cls.name}_system_command") if sys_command: return sys_command return command @@ -671,7 +675,7 @@ def _check_missing(output): class Dnf(_PackageManager): - name = 'dnf' + name = 'dnf4' support_installroot = True def __init__(self, config, buildroot, plugins, bootstrap_buildroot): diff --git a/releng/release-notes-next/dnf4-config-is-alias-to-dnf.feature b/releng/release-notes-next/dnf4-config-is-alias-to-dnf.feature new file mode 100644 index 000000000..d875901a4 --- /dev/null +++ b/releng/release-notes-next/dnf4-config-is-alias-to-dnf.feature @@ -0,0 +1,21 @@ +Alias `dnf4` added for the `package_manager = dnf`. + +The options specific to DNF4, previously prefixed with `dnf_*`, have been +renamed to `dnf4_*` too to avoid confusion with `dnf5_*` options. For backward +compatibility, the `dnf_*` prefixed variants still work, so these config pairs +are equivalent: + +```python +config_opts['dnf4_install_cmd'] = 'install python3-dnf python3-dnf-plugins-core' +config_opts['dnf_install_cmd'] = 'install python3-dnf python3-dnf-plugins-core' + +config_opts['package_manager'] = 'dnf4' +config_opts['package_manager'] = 'dnf' +``` + +Some of the `dnf_*` options remain unchanged because they are universal and used +with DNF4, DNF5, or YUM, e.g., `dnf_vars`. + +While working on this rename, the rarely used `system__command` options have +been changed to `_system_command` to visually align with the rest of the +package-manager-specific options. The old variants are still accepted.