Skip to content

Commit 8049b18

Browse files
committed
facts.yum/dnf/zypper: include source filename in repositories fact
Cat the repo files with a per-file marker so the parser can attach the originating path to each repo entry, enabling callers to locate the .repo file (needed by yum.repo(present=False)). Closes #1042.
1 parent 0e8c348 commit 8049b18

9 files changed

Lines changed: 65 additions & 21 deletions

File tree

src/pyinfra/facts/dnf.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
from pyinfra.api import FactBase
66

7-
from .util import make_cat_files_command
8-
from .util.packaging import parse_yum_repositories
7+
from .util import make_cat_files_command_with_markers
8+
from .util.packaging import REPO_FILENAME_MARKER, parse_yum_repositories
99

1010

1111
class DnfRepositories(FactBase):
@@ -24,14 +24,16 @@ class DnfRepositories(FactBase):
2424
"countme": "1",
2525
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9",
2626
"metadata_expire": "86400",
27-
"enabled_metadata": "1"
27+
"enabled_metadata": "1",
28+
"filename": "/etc/yum.repos.d/almalinux.repo"
2829
},
2930
]
3031
"""
3132

3233
@override
3334
def command(self) -> str:
34-
return make_cat_files_command(
35+
return make_cat_files_command_with_markers(
36+
REPO_FILENAME_MARKER,
3537
"/etc/dnf.conf",
3638
"/etc/dnf.repos.d/*.repo",
3739
"/etc/yum.repos.d/*.repo",

src/pyinfra/facts/util/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,17 @@ def make_cat_files_command(*filenames: Iterable[str]) -> str:
1515
commands = ["({0})".format(command) for command in commands]
1616

1717
return " && ".join(commands)
18+
19+
20+
def make_cat_files_command_with_markers(marker: str, *filenames: str) -> str:
21+
"""
22+
Build a shell command that cats each file prefixed by a marker line naming the file.
23+
Globs are expanded by the shell; missing files (including unexpanded globs) are skipped.
24+
"""
25+
26+
args = " ".join(filenames)
27+
return (
28+
"for f in {args}; do "
29+
'[ -f "$f" ] && {{ printf "{marker} %s\\n" "$f"; cat "$f"; }}; '
30+
"done || true"
31+
).format(args=args, marker=marker)

src/pyinfra/facts/util/packaging.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,27 @@ def parse_packages(regex: str, output: Iterable[str]) -> PackageVersionDict:
2020
return packages
2121

2222

23+
REPO_FILENAME_MARKER = "#pyinfra-filename:"
24+
25+
2326
def _parse_yum_or_zypper_repositories(output):
2427
repos = []
2528

2629
current_repo: dict[str, str] = {}
30+
current_file: str | None = None
2731
for line in output:
2832
line = line.strip()
29-
if not line or line.startswith("#"):
33+
if not line:
34+
continue
35+
36+
if line.startswith(REPO_FILENAME_MARKER):
37+
if current_repo:
38+
repos.append(current_repo)
39+
current_repo = {}
40+
current_file = line[len(REPO_FILENAME_MARKER) :].strip() or None
41+
continue
42+
43+
if line.startswith("#"):
3044
continue
3145

3246
if line.startswith("["):
@@ -36,6 +50,8 @@ def _parse_yum_or_zypper_repositories(output):
3650

3751
current_repo["repoid"] = line[1:-1]
3852
current_repo["name"] = line[1:-1]
53+
if current_file is not None:
54+
current_repo["filename"] = current_file
3955

4056
if current_repo and "=" in line:
4157
key, value = re.split(r"\s*=\s*", line, maxsplit=1)

src/pyinfra/facts/yum.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
from pyinfra.api import FactBase
66

7-
from .util import make_cat_files_command
8-
from .util.packaging import parse_yum_repositories
7+
from .util import make_cat_files_command_with_markers
8+
from .util.packaging import REPO_FILENAME_MARKER, parse_yum_repositories
99

1010

1111
class YumRepositories(FactBase):
@@ -24,14 +24,16 @@ class YumRepositories(FactBase):
2424
"countme": "1",
2525
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9",
2626
"metadata_expire": "86400",
27-
"enabled_metadata": "1"
27+
"enabled_metadata": "1",
28+
"filename": "/etc/yum.repos.d/almalinux.repo"
2829
},
2930
]
3031
"""
3132

3233
@override
3334
def command(self) -> str:
34-
return make_cat_files_command(
35+
return make_cat_files_command_with_markers(
36+
REPO_FILENAME_MARKER,
3537
"/etc/yum.conf",
3638
"/etc/yum.repos.d/*.repo",
3739
)

src/pyinfra/facts/zypper.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
from pyinfra.api import FactBase
66

7-
from .util import make_cat_files_command
8-
from .util.packaging import parse_zypper_repositories
7+
from .util import make_cat_files_command_with_markers
8+
from .util.packaging import REPO_FILENAME_MARKER, parse_zypper_repositories
99

1010

1111
class ZypperRepositories(FactBase):
@@ -20,14 +20,16 @@ class ZypperRepositories(FactBase):
2020
"name": "Main Repository",
2121
"enabled": "1",
2222
"autorefresh": "1",
23-
"baseurl": "http://download.opensuse.org/distribution/leap/$releasever/repo/oss/"
23+
"baseurl": "http://download.opensuse.org/distribution/leap/$releasever/repo/oss/",
24+
"filename": "/etc/zypp/repos.d/oss.repo"
2425
},
2526
]
2627
"""
2728

2829
@override
2930
def command(self) -> str:
30-
return make_cat_files_command(
31+
return make_cat_files_command_with_markers(
32+
REPO_FILENAME_MARKER,
3133
"/etc/zypp/repos.d/*.repo",
3234
)
3335

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
{
2-
"command": "(! test -f /etc/dnf.conf || cat /etc/dnf.conf) && (cat /etc/dnf.repos.d/*.repo || true) && (cat /etc/yum.repos.d/*.repo || true)",
2+
"command": "for f in /etc/dnf.conf /etc/dnf.repos.d/*.repo /etc/yum.repos.d/*.repo; do [ -f \"$f\" ] && { printf \"#pyinfra-filename: %s\\n\" \"$f\"; cat \"$f\"; }; done || true",
33
"requires_command": "dnf",
44
"output": [
5+
"#pyinfra-filename: /etc/yum.repos.d/rhel-atomic.repo",
56
"[rhel-atomic-7-cdk-3.6-source-rpms]",
67
"name = Red Hat Container Development Kit 3.6 /(Source RPMs)"
78
],
89
"fact": [
910
{
1011
"repoid": "rhel-atomic-7-cdk-3.6-source-rpms",
11-
"name": "Red Hat Container Development Kit 3.6 /(Source RPMs)"
12+
"name": "Red Hat Container Development Kit 3.6 /(Source RPMs)",
13+
"filename": "/etc/yum.repos.d/rhel-atomic.repo"
1214
}
1315
]
1416
}
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
{
2-
"command": "(! test -f /etc/dnf.conf || cat /etc/dnf.conf) && (cat /etc/dnf.repos.d/*.repo || true) && (cat /etc/yum.repos.d/*.repo || true)",
2+
"command": "for f in /etc/dnf.conf /etc/dnf.repos.d/*.repo /etc/yum.repos.d/*.repo; do [ -f \"$f\" ] && { printf \"#pyinfra-filename: %s\\n\" \"$f\"; cat \"$f\"; }; done || true",
33
"requires_command": "dnf",
44
"output": [
5+
"#pyinfra-filename: /etc/yum.repos.d/somerepo.repo",
56
"",
67
"[somerepo]",
78
"baseurl=abc",
9+
"#pyinfra-filename: /etc/yum.repos.d/anotherrepo.repo",
810
"",
911
"[anotherrepo]"
1012
],
1113
"fact": [
1214
{
1315
"repoid": "somerepo",
1416
"name": "somerepo",
17+
"filename": "/etc/yum.repos.d/somerepo.repo",
1518
"baseurl": "abc"
1619
},
1720
{
1821
"repoid": "anotherrepo",
19-
"name": "anotherrepo"
22+
"name": "anotherrepo",
23+
"filename": "/etc/yum.repos.d/anotherrepo.repo"
2024
}
2125
]
2226
}

tests/facts/yum.YumRepositories/repos.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
{
2-
"command": "(! test -f /etc/yum.conf || cat /etc/yum.conf) && (cat /etc/yum.repos.d/*.repo || true)",
2+
"command": "for f in /etc/yum.conf /etc/yum.repos.d/*.repo; do [ -f \"$f\" ] && { printf \"#pyinfra-filename: %s\\n\" \"$f\"; cat \"$f\"; }; done || true",
33
"requires_command": "yum",
44
"output": [
5+
"#pyinfra-filename: /etc/yum.repos.d/somerepo.repo",
56
"# comment line",
67
" # comment line with whitespaces",
78
"[somerepo]",
89
"baseurl=abc"
9-
1010
],
1111
"fact": [
1212
{
1313
"repoid": "somerepo",
1414
"name": "somerepo",
15+
"filename": "/etc/yum.repos.d/somerepo.repo",
1516
"baseurl": "abc"
1617
}
1718
]

tests/facts/zypper.ZypperRepositories/repos.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
{
2-
"command": "cat /etc/zypp/repos.d/*.repo || true",
2+
"command": "for f in /etc/zypp/repos.d/*.repo; do [ -f \"$f\" ] && { printf \"#pyinfra-filename: %s\\n\" \"$f\"; cat \"$f\"; }; done || true",
33
"requires_command": "zypper",
44
"output": [
5+
"#pyinfra-filename: /etc/zypp/repos.d/somerepo.repo",
56
"# comment line",
67
" # comment line with whitespaces",
78
"[somerepo]",
89
"baseurl=abc"
9-
1010
],
1111
"fact": [
1212
{
1313
"repoid": "somerepo",
1414
"name": "somerepo",
15+
"filename": "/etc/zypp/repos.d/somerepo.repo",
1516
"baseurl": "abc"
1617
}
1718
]

0 commit comments

Comments
 (0)