refactor: introduce two-user daemon architecture with socket-based communication
- Add daemon/ module with aiohttp server, sync client, and handler registry - Add daemon/handlers/ for privileged operations (acme, dnsmasq, firewall, logs, nginx, wireguard) - Add system/acme-deploy.py, vacuum-walld sudoers and systemd service - Update API routes to use daemon client instead of lib/ directly - Update lib/, tests/, and webui/ for new architecture - Update docs and deployment scripts
This commit is contained in:
@@ -167,3 +167,103 @@ class TestUpstreamsAndDomain:
|
||||
dnsmasq.set_domain(None)
|
||||
cfg = dnsmasq.get_config()
|
||||
assert cfg["dns"]["domain"] is None
|
||||
|
||||
|
||||
# ── Daemon handler tests (NotFoundError on missing resources) ──
|
||||
|
||||
|
||||
class TestDaemonRemoveStaticLease:
|
||||
@patch("daemon.handlers.dnsmasq._get_config")
|
||||
@patch("daemon.handlers.dnsmasq._save_config")
|
||||
def test_raises_not_found_when_missing(self, mock_save, mock_get):
|
||||
from daemon.handlers import dnsmasq as daemon_dnsmasq
|
||||
|
||||
mock_get.return_value = {"dhcp": {"static_leases": []}, "dns": {}}
|
||||
with pytest.raises(Exception, match="not found"):
|
||||
daemon_dnsmasq.remove_static_lease(None, {"mac": "FF:FF:FF"})
|
||||
|
||||
@patch("daemon.handlers.dnsmasq._get_config")
|
||||
@patch("daemon.handlers.dnsmasq._save_config")
|
||||
def test_succeeds_when_exists(self, mock_save, mock_get):
|
||||
from daemon.handlers import dnsmasq as daemon_dnsmasq
|
||||
|
||||
mock_get.return_value = {
|
||||
"dhcp": {"static_leases": [{"mac": "aa:bb:cc", "ip": "10.0.0.1"}]},
|
||||
"dns": {},
|
||||
}
|
||||
result = daemon_dnsmasq.remove_static_lease(None, {"mac": "AA:BB:CC"})
|
||||
assert result["mac"] == "AA:BB:CC"
|
||||
|
||||
|
||||
class TestDaemonRemoveDnsRecord:
|
||||
@patch("daemon.handlers.dnsmasq._get_config")
|
||||
@patch("daemon.handlers.dnsmasq._save_config")
|
||||
def test_raises_not_found_when_missing(self, mock_save, mock_get):
|
||||
from daemon.handlers import dnsmasq as daemon_dnsmasq
|
||||
|
||||
mock_get.return_value = {
|
||||
"dhcp": {},
|
||||
"dns": {"custom_records": []},
|
||||
}
|
||||
with pytest.raises(Exception, match="not found"):
|
||||
daemon_dnsmasq.remove_dns_record(None, {"name": "nonexistent"})
|
||||
|
||||
@patch("daemon.handlers.dnsmasq._get_config")
|
||||
@patch("daemon.handlers.dnsmasq._save_config")
|
||||
def test_succeeds_when_exists(self, mock_save, mock_get):
|
||||
from daemon.handlers import dnsmasq as daemon_dnsmasq
|
||||
|
||||
mock_get.return_value = {
|
||||
"dhcp": {},
|
||||
"dns": {"custom_records": [{"name": "host", "address": "10.0.0.1"}]},
|
||||
}
|
||||
result = daemon_dnsmasq.remove_dns_record(None, {"name": "host"})
|
||||
assert result["name"] == "host"
|
||||
|
||||
|
||||
class TestDaemonRemoveDhcpRange:
|
||||
@patch("daemon.handlers.dnsmasq._get_config")
|
||||
@patch("daemon.handlers.dnsmasq._save_config")
|
||||
def test_raises_not_found_when_missing(self, mock_save, mock_get):
|
||||
from daemon.handlers import dnsmasq as daemon_dnsmasq
|
||||
|
||||
mock_get.return_value = {
|
||||
"dhcp": {"ranges": []},
|
||||
"dns": {},
|
||||
}
|
||||
with pytest.raises(Exception, match="not found"):
|
||||
daemon_dnsmasq.remove_dhcp_range(
|
||||
None,
|
||||
{
|
||||
"interface": "eth0",
|
||||
"start": "10.0.0.100",
|
||||
"end": "10.0.0.200",
|
||||
},
|
||||
)
|
||||
|
||||
@patch("daemon.handlers.dnsmasq._get_config")
|
||||
@patch("daemon.handlers.dnsmasq._save_config")
|
||||
def test_succeeds_when_exists(self, mock_save, mock_get):
|
||||
from daemon.handlers import dnsmasq as daemon_dnsmasq
|
||||
|
||||
mock_get.return_value = {
|
||||
"dhcp": {
|
||||
"ranges": [
|
||||
{
|
||||
"interface": "eth0",
|
||||
"start": "10.0.0.100",
|
||||
"end": "10.0.0.200",
|
||||
}
|
||||
]
|
||||
},
|
||||
"dns": {},
|
||||
}
|
||||
result = daemon_dnsmasq.remove_dhcp_range(
|
||||
None,
|
||||
{
|
||||
"interface": "eth0",
|
||||
"start": "10.0.0.100",
|
||||
"end": "10.0.0.200",
|
||||
},
|
||||
)
|
||||
assert result["interface"] == "eth0"
|
||||
|
||||
Reference in New Issue
Block a user