initial commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Remove/purge the tested local package in the dedicated validation VM."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
|
||||
def sha(path):
|
||||
return hashlib.sha256(path.read_bytes()).hexdigest()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--smoke', type=Path, required=True)
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
assert os.getuid() != 0 and Path.home() == Path('/home/docview')
|
||||
smoke = json.loads((args.smoke / 'report.json').read_text())
|
||||
assert smoke['success'] and smoke['smokeConditions'] == 12
|
||||
for name, digest in smoke['executables'].items():
|
||||
assert sha(Path('/opt/docview/bin') / name) == digest
|
||||
args.output.mkdir(parents=True, exist_ok=False)
|
||||
record = {'success': False, 'runnerSha256': sha(Path(__file__)),
|
||||
'smokeReportSha256': sha(args.smoke / 'report.json'), 'commands': []}
|
||||
|
||||
def run(name, command, allowed=(0,)):
|
||||
result = subprocess.run(command, capture_output=True, text=True, timeout=180)
|
||||
log = args.output / (name + '.log')
|
||||
log.write_text(result.stdout + result.stderr)
|
||||
record['commands'].append({'name': name, 'command': command, 'exitCode': result.returncode,
|
||||
'logSha256': sha(log)})
|
||||
assert result.returncode in allowed, name
|
||||
return result.stdout
|
||||
|
||||
def profiles(label):
|
||||
return run(label, ['sudo', 'cat', '/sys/kernel/security/apparmor/profiles'])
|
||||
|
||||
bundled = 'docview-bundled-qtwebengine '
|
||||
sentinels = []
|
||||
try:
|
||||
before = profiles('profiles-installed')
|
||||
assert bundled in before and 'docview-qtwebengine ' in before
|
||||
record['installedPackage'] = run('package-installed', ['dpkg-query', '-W',
|
||||
'-f=${Package} ${Version} ${db:Status-Status} ${Installed-Size}\n', 'docview']).strip()
|
||||
assert ' installed ' in record['installedPackage']
|
||||
assert run('userns-before', ['sysctl', '-n', 'kernel.apparmor_restrict_unprivileged_userns']).strip() == '1'
|
||||
for relative in ['.config/docview', '.local/state/docview', '.local/share/docview',
|
||||
'validation/package-user-document']:
|
||||
directory = Path.home() / relative
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
path = directory / 'deb-preservation-probe.txt'
|
||||
with path.open('x') as stream:
|
||||
stream.write('DocView package removal preservation probe — 日本語\n')
|
||||
sentinels.append({'path': str(path), 'sha256': sha(path)})
|
||||
run('apt-remove', ['sudo', 'env', 'DEBIAN_FRONTEND=noninteractive', 'apt-get', '-y', 'remove', 'docview'])
|
||||
after = profiles('profiles-removed')
|
||||
assert bundled not in after and 'docview-qtwebengine ' in after
|
||||
for name in ['/opt/docview', '/usr/bin/docview', '/usr/share/applications/docview.desktop']:
|
||||
assert not Path(name).exists(), name
|
||||
assert Path('/etc/apparmor.d/docview').is_file()
|
||||
assert all(sha(Path(row['path'])) == row['sha256'] for row in sentinels)
|
||||
record['remove'] = {'payloadRemoved': True, 'profileUnloaded': True,
|
||||
'conffilePreserved': True, 'userProbesPreserved': True}
|
||||
run('apt-purge', ['sudo', 'env', 'DEBIAN_FRONTEND=noninteractive', 'apt-get', '-y', 'purge', 'docview'])
|
||||
assert not Path('/etc/apparmor.d/docview').exists()
|
||||
assert all(sha(Path(row['path'])) == row['sha256'] for row in sentinels)
|
||||
assert run('userns-after', ['sysctl', '-n', 'kernel.apparmor_restrict_unprivileged_userns']).strip() == '1'
|
||||
assert Path('/opt/docview-qt/6.11.2/gcc_64/bin/qtpaths').is_file()
|
||||
assert Path('/opt/docview-deps/lib/libqpdf.so.30').is_file()
|
||||
assert Path('/home/docview/docview-install/bin/docview').is_file()
|
||||
assert Path('/home/docview/docview-build/docview').is_file()
|
||||
record['purge'] = {'conffileRemoved': True, 'userProbesPreserved': True}
|
||||
record.update(success=True, userProbes=sentinels, originalDevelopmentPrefixesRestored=True,
|
||||
kernelUserNamespaceRestrictionUnchanged=True)
|
||||
finally:
|
||||
# Delete only these newly-created probes after preserving their hashes.
|
||||
for row in sentinels:
|
||||
path = Path(row['path'])
|
||||
if path.is_file() and sha(path) == row['sha256']:
|
||||
path.unlink()
|
||||
(args.output / 'report.json').write_text(json.dumps(record, indent=2, sort_keys=True) + '\n')
|
||||
print(json.dumps({key: record[key] for key in ('success', 'remove', 'purge')}))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user