Skip to content

Commit dc1ec48

Browse files
committed
src/konflux-rpm-lockfile: update baseurl dynamically
Until now, we tackled the DNF5 issue [1] by prioritizing the URL location of the repo 'coreos-pool' when multiple repo were found for the say locked NEVRA. But, if that locked NEVRA has only one URL location coming from the fedora repos i.e: fedora, fedora-updates, then the repoquery command returns a broken URL location for ppc64le and s390x arches because of the DNF5 issue. It returns the URL from the first item defined in baseurl, whereas the resolution worked with the second item i.e fedora-secondary repo where the RPMs for ppc64le and s390x are available. This patch fixes this until the issue [1] is fixed upstream. It's designed to work only with the main fedora baseurl FQDN i.e dl.fedoraproject.org and for ppc64le/s390x arches. It basically updates the repos to use the fedora-secondary URL as the main one as we know the RPMs for those arches lives there. [1] rpm-software-management/dnf5#1673
1 parent eef1c19 commit dc1ec48

File tree

1 file changed

+53
-8
lines changed

1 file changed

+53
-8
lines changed

src/konflux-rpm-lockfile

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,58 @@ import os
66
import sys
77
import subprocess
88
import yaml
9+
import shutil
10+
import tempfile
11+
import re
12+
from pathlib import Path
913

1014
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
1115
from cosalib.cmdlib import get_basearch
1216

1317

18+
# TODO: remove the use of this function once the DNF5 issue is fixed
19+
# c.f https://github.com/rpm-software-management/dnf5/issues/2466
20+
def copy_repo_files_to_temp_repo(context_dir, arch):
21+
"""
22+
If the architecture is 'ppc64le' or 's390x', then we copy all '.repo' files
23+
from contextdir to a new temporary directory. We then edit the baseurls.
24+
If not, then we return context_dir without processing anything.
25+
"""
26+
if arch not in ['ppc64le', 's390x']:
27+
return context_dir
28+
temp_repo_dir = Path(tempfile.mkdtemp())
29+
context_path = Path(context_dir)
30+
for source_path in context_path.rglob('*.repo'):
31+
destination_path = temp_repo_dir / source_path.name
32+
shutil.copy2(source_path, destination_path)
33+
update_repo_baseurls(str(destination_path))
34+
return str(temp_repo_dir)
35+
36+
37+
# TODO: remove the use of this function once the DNF5 issue is fixed
38+
# c.f https://github.com/rpm-software-management/dnf5/issues/2466
39+
# This is fragile as it relies on the repo definitions we are defining in the config dir
40+
# but also on the Fedora URL structure that might evolve in the future.
41+
def update_repo_baseurls(repo_path):
42+
"""
43+
Updates the baseurl in the repo file to use the fedora-secondary repo which
44+
provides the RPMs for ppc64le and s390x arches.
45+
"""
46+
old_baseurl_pattern = r"(baseurl=https?://dl\.fedoraproject\.org/)(.*)fedora/linux(.*)"
47+
new_baseurl_replacement = r"\1\2fedora-secondary\3"
48+
with open(repo_path, 'r', encoding='utf-8') as f:
49+
content = f.read()
50+
new_content, count = re.subn(
51+
old_baseurl_pattern,
52+
new_baseurl_replacement,
53+
content,
54+
flags=re.IGNORECASE | re.MULTILINE
55+
)
56+
if count > 0:
57+
with open(repo_path, 'w', encoding='utf-8') as f:
58+
f.write(new_content)
59+
60+
1461
def format_packages_with_repoid(pkgs, repos):
1562
"""
1663
Takes a list of package URLs and repos and returns a list
@@ -117,13 +164,8 @@ def query_packages_location(locks, repoquery_args):
117164
if not line:
118165
continue
119166
name, url = line.split(' ')
120-
# Prioritize the url from fedora-coreos-pool
121-
# there is a bug in dnf here where the url returned is incorrect when the
122-
# repofile have more than one baseurl, which causes ppc64le and s390x
123-
# urls comming from fedora and fedora-updates to be invalid
124-
# See https://github.com/rpm-software-management/dnf5/issues/2466
125167
existing_url = processed_urls.get(name, None)
126-
if 'coreos-pool' in url or not existing_url:
168+
if not existing_url:
127169
processed_urls[name] = url
128170

129171
pkg_urls = list(processed_urls.values())
@@ -179,7 +221,7 @@ def generate_main(args):
179221
repos += manifest_data.get('lockfile-repos', [])
180222

181223
# Tell dnf to load repos files from $contextdir
182-
repoquery_args = ["--refresh", "--quiet", f"--setopt=reposdir={contextdir}"]
224+
repoquery_args = ["--refresh", "--quiet"]
183225
repoquery_args.extend([f"--repo={','.join(repos)}"])
184226

185227
if releasever is None:
@@ -195,13 +237,16 @@ def generate_main(args):
195237
sys.exit(1)
196238
print(f"Resolving packages for {arch}...")
197239
arch_args = []
240+
repos_dir = copy_repo_files_to_temp_repo(contextdir, arch)
198241
if arch is not get_basearch():
199242
# append noarch as well because otherwise those packages get excluded from results
200243
# We use --forcearch here because otherwise dnf still respect the system basearch
201244
# we have to specify both --arch and --forcearch to get both result for $arch and $noarch
202-
arch_args = ['--forcearch', arch, '--arch', arch, '--arch', 'noarch']
245+
arch_args = [f"--setopt=reposdir={repos_dir}", '--forcearch', arch, '--arch', arch, '--arch', 'noarch']
203246
pkg_urls = query_packages_location(locks, repoquery_args + arch_args)
204247
packages.append({'arch': arch, 'packages': pkg_urls})
248+
if repos_dir != contextdir:
249+
shutil.rmtree(repos_dir)
205250

206251
lockfile = write_hermeto_lockfile(packages, repos)
207252

0 commit comments

Comments
 (0)