fix: split-horizon DNS zone uses WireGuard IP, not Docker bridge IP
Unit Tests / test (push) Successful in 7m31s

VPN peers can reach Caddy via the host's WireGuard interface (10.0.0.1),
not via the Docker bridge IP (172.20.0.2) which is unreachable outside
the container network. _bootstrap_dns now calls _get_wg_server_ip()
instead of ip_utils.get_service_ips() so the internal zone returns a
routable address for service subdomains.

Also log config save failures instead of silently swallowing them —
the silent PermissionError/OSError was masking write failures and
making it impossible to diagnose why installed services disappeared
after container restarts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 02:11:01 -04:00
parent e4c80149f4
commit bd71466a87
4 changed files with 94 additions and 4 deletions
+33
View File
@@ -260,6 +260,39 @@ class TestConfigManager(unittest.TestCase):
"import must not inject zero-filled entries for absent services")
class TestSaveAllConfigs(unittest.TestCase):
"""_save_all_configs must log errors instead of silently swallowing them."""
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.config_file = os.path.join(self.temp_dir, 'cell_config.json')
self.data_dir = os.path.join(self.temp_dir, 'data')
os.makedirs(self.data_dir, exist_ok=True)
self.cm = ConfigManager(self.config_file, self.data_dir)
def tearDown(self):
shutil.rmtree(self.temp_dir)
def test_save_failure_is_logged_not_silenced(self):
"""When the config file cannot be written, _save_all_configs must log an error."""
with patch('builtins.open', side_effect=OSError('disk full')):
with self.assertLogs('config_manager', level='ERROR') as log:
self.cm._save_all_configs()
self.assertTrue(
any('write failed' in msg or 'NOT persisted' in msg for msg in log.output),
f'Expected error about write failure in logs, got: {log.output}',
)
def test_save_success_does_not_log_error(self):
"""A successful save must not produce error logs."""
import logging
with self.assertLogs('config_manager', level='DEBUG') as cm:
logging.getLogger('config_manager').debug('sentinel')
self.cm._save_all_configs()
errors = [m for m in cm.output if 'ERROR' in m and 'write failed' in m]
self.assertEqual(errors, [], 'Unexpected write-failure error on a successful save')
class TestGetEffectiveDomain(unittest.TestCase):
"""Tests for ConfigManager.get_effective_domain and get_internal_domain."""