docs: add docstrings to all API endpoints and daemon handlers

Add comprehensive docstrings to firewall, DHCP, proxy, wireguard, certs,
and logs API endpoints. Document parameters, return values, and error cases
for the documentation system.
This commit is contained in:
2026-05-30 16:15:45 +00:00
parent bd98830638
commit 2f215793e9
17 changed files with 1550 additions and 28 deletions
+75
View File
@@ -35,12 +35,14 @@ DEFAULT_CFG: dict[str, Any] = {
def _get_state() -> dict[str, Any] | None:
"""Retrieve cached dnsmasq state from the state store."""
from lib.state import state as state_store
return state_store.get("dnsmasq")
def _get_config() -> dict[str, Any]:
"""Load dnsmasq config from JSON, merging with defaults."""
ensure_dirs(CONFIG_DIR, DATA_DIR, FRAGMENTS_DIR)
raw = load_json(CONFIG_PATH)
if not raw:
@@ -49,12 +51,14 @@ def _get_config() -> dict[str, Any]:
def _save_config(cfg: dict[str, Any]) -> None:
"""Persist dnsmasq config to JSON after merging with defaults."""
ensure_dirs(CONFIG_DIR, DATA_DIR, FRAGMENTS_DIR)
merged = deep_merge(deepcopy(DEFAULT_CFG), cfg)
save_json(CONFIG_PATH, merged)
def _generate_conf(cfg: dict[str, Any]) -> str:
"""Render dnsmasq.conf from Jinja template and config dict."""
dhcp_cfg = cfg.get("dhcp", {})
dns_cfg = cfg.get("dns", {})
interfaces = [
@@ -71,6 +75,7 @@ def _generate_conf(cfg: dict[str, Any]) -> str:
def _get_dnsmasq_state() -> dict[str, Any]:
"""Return cached dnsmasq state, or empty dict if unset."""
dm = _get_state()
if dm is None:
return {}
@@ -83,6 +88,11 @@ def _get_dnsmasq_state() -> dict[str, Any]:
@registry.register("GET", "/dnsmasq/config")
def get_config(_request: Any, _body: Any) -> dict[str, Any]:
"""\
Endpoint: GET /dnsmasq/config
Returns cached config if available, otherwise loads from disk.
"""
dm = _get_dnsmasq_state()
if dm:
return dm.get("config", {})
@@ -91,6 +101,11 @@ def get_config(_request: Any, _body: Any) -> dict[str, Any]:
@registry.register("POST", "/dnsmasq/config")
def save_config_handler(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/config
Save full config. Raises ValueError on missing body.
"""
if not body:
raise ValueError("Request body required")
_save_config(body)
@@ -100,6 +115,11 @@ def save_config_handler(_request: Any, body: dict[str, Any] | None) -> dict[str,
@registry.register("PATCH", "/dnsmasq/config")
def patch_config(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: PATCH /dnsmasq/config
Merge partial update into existing config. Raises ValueError on missing body.
"""
if not body:
raise ValueError("Request body required")
current = _get_config()
@@ -111,6 +131,11 @@ def patch_config(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
@registry.register("POST", "/dnsmasq/apply")
def apply_config(_request: Any, _body: Any) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/apply
Render config to dnsmasq.conf, write to disk, and reload dnsmasq service via sudo.
"""
cfg = _get_config()
conf_text = _generate_conf(cfg)
ensure_dirs(CONFIG_DIR, DATA_DIR, FRAGMENTS_DIR)
@@ -129,6 +154,11 @@ def apply_config(_request: Any, _body: Any) -> dict[str, Any]:
@registry.register("GET", "/dnsmasq/status")
def get_status(_request: Any, _body: Any) -> dict[str, Any]:
"""\
Endpoint: GET /dnsmasq/status
Returns cached dnsmasq status object, or empty dict if unavailable.
"""
dm = _get_dnsmasq_state()
if dm and "status" in dm:
return dm["status"]
@@ -137,6 +167,11 @@ def get_status(_request: Any, _body: Any) -> dict[str, Any]:
@registry.register("POST", "/dnsmasq/ranges/add")
def set_dhcp_range(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/ranges/add
Add or update a DHCP pool range by interface. Raises ValueError on invalid input.
"""
if not body:
raise ValueError("Request body required")
iface = body.get("interface", "").strip() or ""
@@ -181,6 +216,11 @@ def set_dhcp_range(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]
@registry.register("DELETE", "/dnsmasq/ranges/remove")
def remove_dhcp_range(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: DELETE /dnsmasq/ranges/remove
Remove DHCP range matching interface + start + end. Raises NotFoundError if missing.
"""
if not body:
raise ValueError("Request body required")
iface = body.get("interface", "").strip() or ""
@@ -211,6 +251,11 @@ def remove_dhcp_range(_request: Any, body: dict[str, Any] | None) -> dict[str, A
@registry.register("GET", "/dnsmasq/leases")
def get_leases(_request: Any, _body: Any) -> list[dict[str, Any]]:
"""\
Endpoint: GET /dnsmasq/leases
Returns cached DHCP lease list from state, or empty list if unavailable.
"""
dm = _get_dnsmasq_state()
if dm:
return dm.get("leases", [])
@@ -219,6 +264,11 @@ def get_leases(_request: Any, _body: Any) -> list[dict[str, Any]]:
@registry.register("POST", "/dnsmasq/static-lease/add")
def add_static_lease(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/static-lease/add
Add or update a static DHCP lease by MAC address. Raises ValueError on invalid input.
"""
if not body:
raise ValueError("Request body required")
mac = body.get("mac", "").strip()
@@ -247,6 +297,11 @@ def add_static_lease(_request: Any, body: dict[str, Any] | None) -> dict[str, An
@registry.register("DELETE", "/dnsmasq/static-lease/remove")
def remove_static_lease(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: DELETE /dnsmasq/static-lease/remove
Remove static lease by MAC. Raises NotFoundError if no match.
"""
if not body:
raise ValueError("Request body required")
mac = body.get("mac", "").strip()
@@ -267,6 +322,11 @@ def remove_static_lease(_request: Any, body: dict[str, Any] | None) -> dict[str,
@registry.register("POST", "/dnsmasq/dns-record/add")
def add_dns_record(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/dns-record/add
Add or update a custom DNS record by name. Raises ValueError on invalid input.
"""
if not body:
raise ValueError("Request body required")
name = body.get("name", "").strip()
@@ -295,6 +355,11 @@ def add_dns_record(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]
@registry.register("DELETE", "/dnsmasq/dns-record/remove")
def remove_dns_record(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: DELETE /dnsmasq/dns-record/remove
Remove custom DNS record by name. Raises NotFoundError if no match.
"""
if not body:
raise ValueError("Request body required")
name = body.get("name", "").strip()
@@ -313,6 +378,11 @@ def remove_dns_record(_request: Any, body: dict[str, Any] | None) -> dict[str, A
@registry.register("POST", "/dnsmasq/upstreams")
def set_upstreams(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/upstreams
Replace DNS upstream servers list. Raises ValueError if servers field missing.
"""
if not body or "servers" not in body:
raise ValueError("'servers' is required")
cfg = _get_config()
@@ -324,6 +394,11 @@ def set_upstreams(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
@registry.register("POST", "/dnsmasq/domain")
def set_domain(_request: Any, body: dict[str, Any] | None) -> dict[str, Any]:
"""\
Endpoint: POST /dnsmasq/domain
Set or clear the local DNS domain. Raises ValueError on missing body.
"""
if not body:
raise ValueError("Request body required")
domain = body.get("domain")