Files
archy/scripts/tests/qualify_uat_oci.py

104 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""Actual-archive packaging/import fixture; NOT full candidate or live D09 UAT.
Run under release-heavy.lock and a CPU2/8G scope. Only a fresh explicit VFS
root/runroot/config/network/tmp are used. No containers are started.
"""
import argparse
import importlib.util
import json
import os
from pathlib import Path
import shutil
import subprocess
import sys
SCRIPTS = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(SCRIPTS))
import uat_oci
def load(name):
spec = importlib.util.spec_from_file_location(name, SCRIPTS / (name + '.py'))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--evidence', type=Path, required=True)
parser.add_argument('--output', type=Path, required=True)
args = parser.parse_args()
out = args.output.resolve()
if os.geteuid() == 0 or not out.is_relative_to(Path('/tmp/opencode')):
parser.error('non-root fixture under /tmp/opencode required')
out.mkdir(exist_ok=False)
builder, importer = load('build-iso-uat'), load('import-uat-oci')
staged = out / 'staged'
staged.mkdir()
for source, target in [('lnd-tor-20261101-amd64.oci.tar', 'lnd_tor_oci'),
('identity.json', 'lnd_tor_identity'), ('final-source.json', 'lnd_tor_sources')]:
shutil.copyfile(args.evidence / source, staged / target)
companion = builder.companion_identity(SCRIPTS.parent)
# Null source identity explicitly marks this as dirty-tree packaging evidence,
# never a qualified candidate receipt or deployable full candidate bundle.
bundle = builder.stage_oci(SCRIPTS.parent, staged, {'source_commit': None, 'companion': companion})
proof = uat_oci.bundle(bundle)['oci']
payload = out / 'payload/archipelago/unsigned-uat-oci'
shutil.copytree(bundle, payload)
count = 0
def command(argv, env=None):
nonlocal count
count += 1
prefix = out / f'command-{count:02}'
prefix.with_suffix('.json').write_text(json.dumps([str(x) for x in argv]) + '\n')
process = subprocess.run([str(x) for x in argv], capture_output=True, env=env, timeout=300)
prefix.with_suffix('.stdout').write_bytes(process.stdout)
prefix.with_suffix('.stderr').write_bytes(process.stderr)
if process.returncode:
raise RuntimeError(f'fixture command failed ({process.returncode}); see {prefix}')
return process.stdout.decode()
iso = out / 'NONBOOTABLE-OCI-PACKAGING-FIXTURE.iso'
command(['xorriso', '-as', 'mkisofs', '-R', '-o', iso, out / 'payload'])
command(['xorriso', '-osirrox', 'on', '-indev', iso, '-extract', '/', out / 'extracted'])
extracted = out / 'extracted/archipelago/unsigned-uat-oci'
uat_oci.bundle(extracted, uat_oci.sha(bundle / 'BUNDLE.json'))
staged_result = importer.stage(extracted, out / 'installed-fixture')
for name in ('storage', 'run', 'network', 'tmp', 'home', 'xdg-data', 'xdg-config'):
(out / name).mkdir()
conf = out / 'storage.conf'
storage = {'storage': {'driver': 'vfs', 'graphroot': str(out / 'storage'), 'runroot': str(out / 'run')}}
conf.write_text('[storage]\ndriver="vfs"\ngraphroot=' + json.dumps(str(out / 'storage')) + '\nrunroot=' + json.dumps(str(out / 'run')) + '\n')
containers = out / 'containers.conf'
containers.write_text('[containers]\nkeyring=false\n[engine]\nevents_logger="file"\n')
env = dict(os.environ, HOME=str(out / 'home'), XDG_DATA_HOME=str(out / 'xdg-data'),
XDG_CONFIG_HOME=str(out / 'xdg-config'), CONTAINERS_STORAGE_CONF=str(conf),
CONTAINERS_CONF=str(containers), TMPDIR=str(out / 'tmp'))
for key in ('CONTAINER_HOST', 'CONTAINER_CONNECTION', 'CONTAINERS_CONF_OVERRIDE'):
env.pop(key, None)
prefix = ['/usr/bin/podman', '--root', out / 'storage', '--runroot', out / 'run',
'--storage-driver', 'vfs', '--network-config-dir', out / 'network', '--tmpdir', out / 'tmp']
def podman(argv):
return command(prefix + argv, env)
info = json.loads(podman(['info', '--format', 'json']))
importer.storage_check(info, {'graphroot': str(out / 'storage'), 'runtime_dir': str(out)}, storage, conf)
if json.loads(podman(['images', '--format', 'json'])) or json.loads(podman(['ps', '-a', '--format', 'json'])):
raise ValueError('fixture store was not empty')
imported = importer.import_image(podman, extracted / 'lnd-tor.oci.tar', proof)
after = json.loads(podman(['info', '--format', 'json']))
importer.storage_check(after, {'graphroot': str(out / 'storage'), 'runtime_dir': str(out)}, storage, conf)
if json.loads(podman(['ps', '-a', '--format', 'json'])):
raise ValueError('unexpected fixture container')
result = dict(status='actual-archive-packaging-isolated-import-passed', source_qualified=False,
full_candidate_built=False, live_d09_import_tested=False, companion=companion,
archive=proof, imported=imported, staged=staged_result,
fixture_iso_sha256=uat_oci.sha(iso), bundle_sha256=uat_oci.sha(bundle / 'BUNDLE.json'),
store=after['store'], runtime_uid=os.geteuid(), containers_created=0)
(out / 'result.json').write_text(json.dumps(result, sort_keys=True, indent=2) + '\n')
print(json.dumps(result, sort_keys=True))
if __name__ == '__main__':
main()