lib.Distro.verify(): Add method
jw-base verify pipes the output of rpm -qV for all janware packages into a grep for md5 mismatches and missing files. The same capability, distribution-independent, belongs in the Distro abstraction so that tools like jw-nettools can check the integrity of the packages they install on a fleet of hosts. - Add Distro.verify(), which verifies the given package names, or all packages selected by the package filter when none are given, and returns the flagged files - Add Distro._verify() as the distribution hook - Add FlaggedFile, the record for a flagged file: package, file, and the package manager's verify status line - not distribution independent as of today, but it's a start - pm/rpm.py: parse_verify_output() parses the output of `rpm -qV` and reports md5 mismatches and missing files, the latter reported with the literal word "missing" in the flag field; size, mode, mtime, user, and group mismatches are noise on dev machines and are ignored. verify_packages() runs `rpm -qV` per package and collects the findings - pm/dpkg.py: parse_verify_output() parses the output of `dpkg -V` and reports md5sum (P) mismatches and missing files (M); verify_packages() runs `dpkg -V` per package - The SUSE, Red Hat, and Debian Distro classes implement _verify() with the respective pm helpers; the Arch Distro raises NotImplementedError, like its other package manager hooks Signed-off-by: Jan Lindemann <jan@janware.com> Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v1.2.0
This commit is contained in:
parent
2fad5d189c
commit
cae983479c
3 changed files with 371 additions and 4 deletions
4
test/unit/python/jw/pkg/lib/pm/Makefile
Normal file
4
test/unit/python/jw/pkg/lib/pm/Makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
TOPDIR = ../../../../../../..
|
||||
|
||||
include $(TOPDIR)/make/proj.mk
|
||||
include $(JWBDIR)/make/dirs.mk
|
||||
7
test/unit/python/jw/pkg/lib/pm/rpm/Makefile
Normal file
7
test/unit/python/jw/pkg/lib/pm/rpm/Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
TOPDIR = ../../../../../../../..
|
||||
|
||||
include $(TOPDIR)/make/proj.mk
|
||||
include $(JWBDIR)/make/py-run.mk
|
||||
|
||||
all:
|
||||
test: run
|
||||
58
test/unit/python/jw/pkg/lib/pm/rpm/test.py
Normal file
58
test/unit/python/jw/pkg/lib/pm/rpm/test.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from jw.pkg.lib.FlaggedFile import FlaggedFile
|
||||
from jw.pkg.lib.pm.rpm import _parse_verify_output
|
||||
|
||||
# -- _parse_verify_output --
|
||||
|
||||
# -- A clean line is not reported
|
||||
assert _parse_verify_output('pkg', '.....UG.. /usr/bin/foo\n') == []
|
||||
|
||||
# -- Mismatches in size, mode, mtime, user, and group are noise
|
||||
assert _parse_verify_output('pkg', 'SM...UGT. c /etc/foo\n') == []
|
||||
|
||||
# -- A content (md5) mismatch is reported, with the flags preserved
|
||||
ret = _parse_verify_output('pkg', 'SM5....T. c /etc/foo\n')
|
||||
assert len(ret) == 1
|
||||
assert ret[0].pkg == 'pkg'
|
||||
assert ret[0].file == '/etc/foo'
|
||||
assert ret[0].flags == 'SM5....T.'
|
||||
|
||||
# -- The 8-character flag layout of older rpm versions is understood
|
||||
ret = _parse_verify_output('pkg', 'SM5....T /etc/foo\n')
|
||||
assert len(ret) == 1
|
||||
assert ret[0].flags == 'SM5....T'
|
||||
|
||||
# -- A missing file is reported, config files included
|
||||
ret = _parse_verify_output('pkg', 'missing /etc/opt/jw-ws/pi\n')
|
||||
assert len(ret) == 1
|
||||
assert ret[0].file == '/etc/opt/jw-ws/pi'
|
||||
assert ret[0].flags == 'missing'
|
||||
ret = _parse_verify_output('pkg', 'missing c /etc/opt/jw-ws/pi/models.json\n')
|
||||
assert len(ret) == 1
|
||||
assert ret[0].file == '/etc/opt/jw-ws/pi/models.json'
|
||||
|
||||
# -- A trailing parenthesized annotation is not part of the file
|
||||
# name
|
||||
ret = _parse_verify_output(
|
||||
'pkg', 'missing c /etc/phpMyAdmin/config.inc.php.jw-tmpl (Permission denied)\n'
|
||||
)
|
||||
assert len(ret) == 1
|
||||
assert ret[0].file == '/etc/phpMyAdmin/config.inc.php.jw-tmpl'
|
||||
|
||||
# -- Lines without a file name and foreign output are ignored
|
||||
assert _parse_verify_output('pkg', '.....UG..\n') == []
|
||||
assert _parse_verify_output('pkg', 'package foo is not installed\n') == []
|
||||
assert _parse_verify_output('pkg', 'error: rpm verify failed\n') == []
|
||||
|
||||
# -- The output of several files is accumulated
|
||||
ret = _parse_verify_output(
|
||||
'pkg', 'SM5....T. c /etc/foo\nmissing c /etc/bar\n.....UG.. c /etc/baz\n'
|
||||
)
|
||||
assert [f.file for f in ret] == ['/etc/foo', '/etc/bar']
|
||||
|
||||
# -- FlaggedFile renders as pkg file flags
|
||||
f = FlaggedFile('pkg', '/etc/foo', 'SM5....T.')
|
||||
assert repr(f) == 'pkg /etc/foo SM5....T.'
|
||||
|
||||
print('All rpm pm tests passed')
|
||||
Loading…
Reference in a new issue