feat: Phase 2 — remove builtins layer, ServiceRegistry is installed-only
Unit Tests / test (push) Successful in 11m31s
Unit Tests / test (push) Successful in 11m31s
Builtins (email/calendar/files) are no longer baked into the API image. ServiceRegistry now only knows about installed store services. When nothing is installed, Caddy and DNS get no service routes — no hardcoded fallback. Changes: - service_registry.py: remove _BUILTINS_DIR, _builtin_ids, _builtin_manifest, _load_manifest; get() and list_all() now delegate entirely to installed services - caddy_manager.py: remove _build_core_service_routes(); remove hardcoded fallback pairs from _http01_service_pairs(); empty registry → api block only - network_manager.py: _get_service_subdomains() returns [] when no registry - api/services/builtins/: deleted (email, calendar, files manifests) - Tests updated throughout: removed builtin-dependent assertions, added installed-service fixtures, updated fallback expectations to api-only Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -500,35 +500,47 @@ class TestDNSZoneRecords:
|
||||
f"got {rec['value']}"
|
||||
)
|
||||
|
||||
def test_calendar_resolves_to_wg_server_ip(self):
|
||||
records = self._records()
|
||||
rec = next((r for r in records if r['name'] == 'calendar'), None)
|
||||
assert rec and rec['value'] == self._WG_SERVER_IP, \
|
||||
f"calendar.dev should resolve to WG server IP; got {rec}"
|
||||
def test_service_records_absent_without_registry(self):
|
||||
"""Without a registry, service subdomain records are not generated.
|
||||
|
||||
def test_files_resolves_to_wg_server_ip(self):
|
||||
Phase 2: service DNS records only exist when a service is installed
|
||||
and the registry reports it. The hardcoded fallback is gone.
|
||||
"""
|
||||
records = self._records()
|
||||
rec = next((r for r in records if r['name'] == 'files'), None)
|
||||
assert rec and rec['value'] == self._WG_SERVER_IP, \
|
||||
f"files.dev should resolve to WG server IP; got {rec}"
|
||||
names = {r['name'] for r in records}
|
||||
assert 'calendar' not in names, \
|
||||
'calendar DNS record must not appear without a registry'
|
||||
assert 'files' not in names, \
|
||||
'files DNS record must not appear without a registry'
|
||||
assert 'mail' not in names, \
|
||||
'mail DNS record must not appear without a registry'
|
||||
assert 'webmail' not in names, \
|
||||
'webmail DNS record must not appear without a registry'
|
||||
assert 'webdav' not in names, \
|
||||
'webdav DNS record must not appear without a registry'
|
||||
|
||||
def test_mail_resolves_to_wg_server_ip(self):
|
||||
records = self._records()
|
||||
rec = next((r for r in records if r['name'] == 'mail'), None)
|
||||
assert rec and rec['value'] == self._WG_SERVER_IP, \
|
||||
f"mail.dev should resolve to WG server IP; got {rec}"
|
||||
|
||||
def test_webmail_resolves_to_wg_server_ip(self):
|
||||
records = self._records()
|
||||
rec = next((r for r in records if r['name'] == 'webmail'), None)
|
||||
assert rec and rec['value'] == self._WG_SERVER_IP, \
|
||||
f"webmail.dev should resolve to WG server IP; got {rec}"
|
||||
|
||||
def test_webdav_resolves_to_wg_server_ip(self):
|
||||
records = self._records()
|
||||
rec = next((r for r in records if r['name'] == 'webdav'), None)
|
||||
assert rec and rec['value'] == self._WG_SERVER_IP, \
|
||||
f"webdav.dev should resolve to WG server IP; got {rec}"
|
||||
def test_service_records_present_with_registry(self):
|
||||
"""With a registry that provides calendar/mail/files, all resolve to WG IP."""
|
||||
from unittest.mock import MagicMock
|
||||
import network_manager as nm
|
||||
registry = MagicMock()
|
||||
registry.get_caddy_routes.return_value = [
|
||||
{'service_id': 'calendar', 'subdomain': 'calendar',
|
||||
'backend': 'cell-radicale:5232', 'extra_subdomains': [], 'extra_backends': {}},
|
||||
{'service_id': 'email', 'subdomain': 'mail',
|
||||
'backend': 'cell-rainloop:8888', 'extra_subdomains': ['webmail'], 'extra_backends': {}},
|
||||
{'service_id': 'files', 'subdomain': 'files',
|
||||
'backend': 'cell-filegator:8080', 'extra_subdomains': ['webdav'], 'extra_backends': {}},
|
||||
]
|
||||
mgr = nm.NetworkManager.__new__(nm.NetworkManager)
|
||||
mgr._service_registry = registry
|
||||
records = mgr._build_dns_records('pic0', '172.20.0.0/16')
|
||||
names = {r['name'] for r in records}
|
||||
for expected in ('calendar', 'mail', 'webmail', 'files', 'webdav'):
|
||||
assert expected in names, f'{expected} should be in DNS records with registry'
|
||||
for rec in records:
|
||||
assert rec['value'] == self._WG_SERVER_IP, \
|
||||
f"Record {rec['name']} should point to WG server IP"
|
||||
|
||||
def test_cell_name_resolves_to_wg_server_ip(self):
|
||||
records = self._records(cell_name='mypic')
|
||||
|
||||
Reference in New Issue
Block a user