fix: clean-install bugs — Tor false-installed, WG port-check honesty, encrypted backup upload
Unit Tests / test (push) Successful in 13m7s
Unit Tests / test (push) Successful in 13m7s
Three independent bugs surfaced during pic1 clean-install testing: 1. Tor _exit_status hardcoded configured=True regardless of whether Tor was actually installed. Status now flows through the same store-installed / container-running bridge used by every other optional service, so Tor only reports installed when the container is present and running. 2. check_port_open compared the port from wg0.conf against the kernel-reported listening port, causing false "port closed" results whenever the conf and the running container were momentarily out of sync. The function is now an honest liveness check: any wg0 interface that is up and has a "listening port:" line in `wg show` is considered open. The check-port API endpoint now also returns the actual kernel listening_port and a port_mismatch flag so the UI can inform the user when a container recreate is needed. (The recreate machinery already exists via the port-change pending-restart path; this fix makes the mismatch visible rather than silently lying about reachability.) 3. upload_backup only handled .zip archives; encrypted .age blobs were rejected with a generic error. The endpoint now calls backup_crypto.is_encrypted() to detect Age-encrypted blobs and stores them verbatim as <id>.tar.gz.age with mode 0600 so they can be uploaded and then restored with a passphrase. The plaintext zip path is unchanged. Tests added/updated: test_connectivity_manager.py (Tor status bridge), test_wireguard_manager.py + test_wireguard_endpoints.py (port-check liveness and mismatch flag), test_config_backup_restore_http.py (encrypted upload round-trip). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1037,11 +1037,35 @@ class TestExitStatus(unittest.TestCase):
|
||||
self.assertIn('status', item)
|
||||
self.assertIn(item['status'], ('active', 'configured', 'not_configured'))
|
||||
|
||||
def test_tor_defaults_to_configured(self):
|
||||
def test_tor_not_configured_when_not_installed_or_running(self):
|
||||
# Tor must not report configured just because it has no per-cell config;
|
||||
# it flows through the store-installed / container-running bridge.
|
||||
mgr = self._mgr()
|
||||
with patch.object(cm_module, 'subprocess') as mock_sp:
|
||||
mock_sp.run.return_value = MagicMock(returncode=1, stdout='', stderr='')
|
||||
info = mgr._exit_status('tor')
|
||||
self.assertFalse(info['configured'])
|
||||
self.assertEqual(info['status'], 'not_configured')
|
||||
|
||||
def test_tor_configured_when_store_installed(self):
|
||||
mgr = self._mgr(installed={'tor': {'manifest': {'id': 'tor'}}})
|
||||
with patch.object(cm_module, 'subprocess') as mock_sp:
|
||||
mock_sp.run.return_value = MagicMock(returncode=1, stdout='', stderr='')
|
||||
info = mgr._exit_status('tor')
|
||||
self.assertTrue(info['configured'])
|
||||
self.assertEqual(info['status'], 'configured')
|
||||
|
||||
def test_tor_configured_when_container_running(self):
|
||||
mgr = self._mgr()
|
||||
|
||||
def fake_run(cmd, **kwargs):
|
||||
if 'inspect' in cmd:
|
||||
return MagicMock(returncode=0, stdout='true\n', stderr='')
|
||||
return MagicMock(returncode=1, stdout='', stderr='')
|
||||
|
||||
with patch.object(cm_module, 'subprocess') as mock_sp:
|
||||
mock_sp.run.side_effect = fake_run
|
||||
info = mgr._exit_status('tor')
|
||||
self.assertTrue(info['configured'])
|
||||
self.assertEqual(info['status'], 'configured')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user