#!/usr/bin/env python3 """Pure manifest preparation tests, not installed-manager acceptance.""" import json from pathlib import Path import subprocess import sys import tempfile import unittest from fixture_manifests import manifests ROOT = Path(__file__).resolve().parent class FixtureManifests(unittest.TestCase): def args(self): return ['a'*64,'b'*64,'c'*64,'d'*64,'/var/lib/archipelago/fixture-podsteadr-test'] def render(self): return manifests(*self.args()) def test_requires_exact_images_and_explicit_public_service_key(self): for index, invalid in ((0,'app:latest'),(1,'abc123'),(2,''),(3,''),(3,'npub1invalid'),(3,'d'*64+'\nOTHER=value')): args = self.args(); args[index] = invalid with self.subTest(index=index, invalid=invalid), self.assertRaises(ValueError): manifests(*args) def test_live_paths_and_traversal_refused(self): for value in ('/var/lib/archipelago/podsteadr','/var/lib/archipelago/fixture-podsteadr-test/../live','relative','/tmp/other'): args = self.args(); args[4] = value with self.subTest(value=value), self.assertRaises(ValueError): manifests(*args) def test_all_three_pin_images_nonroot_data_and_loopback_ports(self): rendered = self.render() self.assertEqual(set(rendered),{'podsteadr','podsteadr-mediamtx','podsteadr-blossom'}) for document in rendered.values(): app = document['app'] self.assertEqual(app['container']['pull_policy'],'never') self.assertTrue(app['container']['image'].startswith('sha256:')) self.assertEqual(app['container']['data_uid'],'1000:1000') self.assertNotIn('user',app['container'], 'No unsupported runtime-user field') self.assertEqual(app['security']['capabilities'],[]) self.assertTrue(app['security']['readonly_root']) self.assertTrue(app['security']['no_new_privileges']) self.assertNotIn('hooks',app) self.assertNotIn('secret_env',app['container']) self.assertNotIn('generated_secrets',app['container']) self.assertTrue(all(port['bind']=='127.0.0.1' for port in app['ports'])) self.assertTrue(all(not file['overwrite'] for file in app.get('files',[]))) def test_native_admin_and_distinct_service_key_bindings(self): docs = self.render() app = docs['podsteadr']['app']; blossom = docs['podsteadr-blossom']['app'] self.assertEqual(app['container']['derived_env'],[{'key':'PODSTEADR_ADMIN_PUBKEYS','template':'{{NODE_IDENTITY_PUBKEYS}}'}]) self.assertEqual(blossom['container']['derived_env'],[{'key':'ARCHY_BLOSSOM_PUBKEYS','template':'{{NODE_IDENTITY_PUBKEYS}},'+'d'*64}]) self.assertNotIn('server-nostr-key',json.dumps(docs)) self.assertIn('NOSTR_RELAYS=',app['environment']) self.assertIn('CASHU_MINT_URL_DEFAULT=http://127.0.0.1:9996',app['environment']) def test_matching_paths_recording_permissions_and_no_root_copy_hook(self): docs = self.render() volumes = {key:{v['target']:v for v in doc['app']['volumes']} for key,doc in docs.items()} self.assertEqual(volumes['podsteadr']['/recordings']['options'],['ro']) self.assertEqual(volumes['podsteadr-mediamtx']['/recordings']['options'],['rw']) self.assertEqual(volumes['podsteadr']['/recordings']['source'],volumes['podsteadr-mediamtx']['/recordings']['source']) blossom = volumes['podsteadr-blossom'] self.assertEqual(blossom['/config/config.json']['options'],['ro']) self.assertEqual(blossom['/bridge']['options'],['ro']) self.assertNotIn('/app/data',blossom) config = docs['podsteadr-mediamtx']['app']['files'][0]['content'] self.assertIn('authHTTPAddress: http://podsteadr-app:8095/api/mediamtx/auth',config) self.assertIn('recordPath: /recordings/',config) self.assertNotIn('runOn',config) def test_canonical_parser_samples_match_generator_exactly(self): for app_id, expected in self.render().items(): actual = json.loads((ROOT/'manifest-samples'/app_id/'manifest.yml').read_text()) self.assertEqual(actual, expected) def test_large_upload_is_explicit_and_does_not_change_other_services(self): baseline = self.render() large = manifests(*self.args(), large_upload_candidate=True) self.assertEqual(baseline['podsteadr-blossom']['app']['environment'], []) self.assertEqual(large['podsteadr-blossom']['app']['environment'], ['ARCHY_BLOSSOM_MAX_UPLOAD_BYTES=2147483648']) self.assertEqual(large['podsteadr-blossom']['app']['version'], '6.4.1-fixture.large1') for service in ('podsteadr', 'podsteadr-mediamtx'): self.assertEqual(large[service], baseline[service]) self.assertEqual(large['podsteadr-blossom']['app']['container'], baseline['podsteadr-blossom']['app']['container']) def test_cli_refuses_existing_output_and_leaves_it_untouched(self): with tempfile.TemporaryDirectory() as directory: args = self.args() command = [sys.executable,str(ROOT/'fixture_manifests.py')] for name,value in zip(('app-image','mtx-image','blossom-image','server-pubkey','data-root'),args): command += ['--'+name,value] command += ['--output',directory] first = subprocess.run(command,capture_output=True,text=True) self.assertEqual(first.returncode,0,first.stderr) before = {str(p.relative_to(directory)):p.read_bytes() for p in Path(directory).rglob('manifest.yml')} self.assertEqual(len(before),3) second = subprocess.run(command,capture_output=True,text=True) self.assertNotEqual(second.returncode,0) self.assertEqual(before,{str(p.relative_to(directory)):p.read_bytes() for p in Path(directory).rglob('manifest.yml')}) if __name__ == '__main__': unittest.main()