Implement connectivity store services (wireguard-ext, openvpn-client, tor)
Unit Tests / test (push) Successful in 11m31s

- ConnectivityManager: move config dirs to data_dir/services/<id>/config so
  Docker can bind-mount them into store-service containers (Docker resolves
  bind-mount paths on the host, not inside the API container).  Add
  _migrate_legacy_configs to copy existing files from the old config_dir
  location on first boot.

- manifest_validator: add allow_host_network parameter to
  validate_rendered_compose.  When True, waives the external-network
  requirement, permits network_mode: host, and allows devices: — all needed
  by VPN/Tor containers that must share the host network namespace to create
  tun/wg interfaces.  Non-host services are unaffected.

- service_composer: read requires_host_network from the manifest and pass
  allow_host_network=True to validate_rendered_compose for connectivity
  services.

- Tests: update file-path assertions to new data_dir layout; add
  TestMigrateLegacyConfigs, TestValidateRenderedComposeHostNetwork, and
  two TestWriteCompose cases for the host-network path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 10:06:48 -04:00
parent 60601eb4af
commit 7d5c5421f1
6 changed files with 306 additions and 29 deletions
+40
View File
@@ -210,6 +210,46 @@ class TestWriteCompose(unittest.TestCase):
path = os.path.join(tmpdir, 'services', 'myservice', 'docker-compose.yml')
self.assertTrue(os.path.exists(path))
def test_requires_host_network_manifest_allows_host_mode_template(self):
"""write_compose passes when manifest has requires_host_network: true and template uses network_mode: host."""
with tempfile.TemporaryDirectory() as tmpdir:
composer = ServiceComposer(config_manager=_make_cm(), data_dir=tmpdir)
manifest = _make_manifest()
manifest['requires_host_network'] = True
template = (
'services:\n'
' wireguard-ext:\n'
' image: git.pic.ngo/roof/svc-wireguard-ext:latest\n'
' container_name: cell-wg-ext\n'
' network_mode: host\n'
' cap_add:\n'
' - NET_ADMIN\n'
' volumes:\n'
f' - {tmpdir}/services/wireguard-ext/config:/etc/wireguard\n'
)
# Should not raise
composer.write_compose('wireguard-ext', manifest, template)
path = os.path.join(tmpdir, 'services', 'wireguard-ext', 'docker-compose.yml')
self.assertTrue(os.path.exists(path))
def test_requires_host_network_false_rejects_host_mode_template(self):
"""write_compose raises when manifest does NOT have requires_host_network but template uses network_mode: host."""
with tempfile.TemporaryDirectory() as tmpdir:
composer = ServiceComposer(config_manager=_make_cm(), data_dir=tmpdir)
manifest = _make_manifest()
manifest['requires_host_network'] = False
template = (
'services:\n'
' svc:\n'
' image: git.pic.ngo/roof/svc-foo:latest\n'
' network_mode: host\n'
'networks:\n'
' cell-network:\n'
' external: true\n'
)
with self.assertRaises(ValueError):
composer.write_compose('svc', manifest, template)
# ── Secrets ───────────────────────────────────────────────────────────────────