fix htmx refactor route mismatches and remaining TODO items
- wireguard: POST /peers with JSON encoding (was /add-peer) - rules: delete by rule_id in URL path (was JSON body); pass rule objects with id from server; add hx-disable to initial render - nat: port forward delete uses URL path params to match blueprint - nat: masquerade toggle uses native hx-post/hx-vals (was inline fetch) - app.js renderers updated to use URL path deletes for rules and forwards - remove TODO.md
This commit is contained in:
+30
-3
@@ -6,6 +6,7 @@ static leases, and custom DNS records through sudo.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
from copy import deepcopy
|
||||
@@ -15,6 +16,8 @@ from typing import Any
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
PROJECT_DIR = Path(__file__).resolve().parent.parent
|
||||
CONFIG_DIR = PROJECT_DIR / "config" / "dnsmasq"
|
||||
DATA_DIR = PROJECT_DIR / "data" / "dnsmasq"
|
||||
@@ -101,6 +104,7 @@ def save_config(cfg: dict) -> None:
|
||||
_ensure_dirs()
|
||||
merged = _deep_merge(deepcopy(DEFAULT_CFG), cfg)
|
||||
_save_json(CONFIG_PATH, merged)
|
||||
logger.info("dnsmasq config saved")
|
||||
|
||||
|
||||
def apply_config() -> None:
|
||||
@@ -118,6 +122,7 @@ def apply_config() -> None:
|
||||
check=True,
|
||||
)
|
||||
_sudo("systemctl", "reload", "dnsmasq")
|
||||
logger.info("dnsmasq config written and reloaded")
|
||||
|
||||
|
||||
# ───────── config generation ─────────────────────────────────────────
|
||||
@@ -187,6 +192,23 @@ def set_dhcp_range(
|
||||
ranges.append(entry)
|
||||
|
||||
save_config(cfg)
|
||||
logger.info("DHCP range set for interface '%s': %s-%s", iface, start, end)
|
||||
|
||||
|
||||
def remove_dhcp_range(iface: str, start: str, end: str) -> None:
|
||||
"""Remove a DHCP range by interface + IP range."""
|
||||
cfg = get_config()
|
||||
cfg["dhcp"]["ranges"] = [
|
||||
r
|
||||
for r in cfg["dhcp"]["ranges"]
|
||||
if not (
|
||||
r.get("interface") == iface
|
||||
and r.get("start") == start
|
||||
and r.get("end") == end
|
||||
)
|
||||
]
|
||||
save_config(cfg)
|
||||
logger.info("DHCP range removed for interface '%s': %s-%s", iface, start, end)
|
||||
|
||||
|
||||
def add_static_lease(mac: str, ip: str, hostname: str | None = None) -> None:
|
||||
@@ -200,6 +222,7 @@ def add_static_lease(mac: str, ip: str, hostname: str | None = None) -> None:
|
||||
if hostname:
|
||||
leases[i]["hostname"] = hostname
|
||||
save_config(cfg)
|
||||
logger.info("Static DHCP lease updated: %s -> %s", mac, ip)
|
||||
return
|
||||
|
||||
entry: dict[str, Any] = {"mac": mac, "ip": ip}
|
||||
@@ -207,6 +230,7 @@ def add_static_lease(mac: str, ip: str, hostname: str | None = None) -> None:
|
||||
entry["hostname"] = hostname
|
||||
leases.append(entry)
|
||||
save_config(cfg)
|
||||
logger.info("Static DHCP lease added: %s -> %s", mac, ip)
|
||||
|
||||
|
||||
def remove_static_lease(mac: str) -> None:
|
||||
@@ -218,6 +242,7 @@ def remove_static_lease(mac: str) -> None:
|
||||
if lease["mac"].lower() != mac.lower()
|
||||
]
|
||||
save_config(cfg)
|
||||
logger.info("Static DHCP lease removed for MAC %s", mac)
|
||||
|
||||
|
||||
# ───────── dns record management ─────────────────────────────────────
|
||||
@@ -234,6 +259,7 @@ def add_dns_record(name: str, address: str, hostname: str | None = None) -> None
|
||||
if hostname:
|
||||
records[i]["hostname"] = hostname
|
||||
save_config(cfg)
|
||||
logger.info("DNS record updated: %s -> %s", name, address)
|
||||
return
|
||||
|
||||
entry: dict[str, Any] = {"name": name, "address": address}
|
||||
@@ -241,6 +267,7 @@ def add_dns_record(name: str, address: str, hostname: str | None = None) -> None
|
||||
entry["hostname"] = hostname
|
||||
records.append(entry)
|
||||
save_config(cfg)
|
||||
logger.info("DNS record added: %s -> %s", name, address)
|
||||
|
||||
|
||||
def remove_dns_record(name: str) -> None:
|
||||
@@ -250,6 +277,7 @@ def remove_dns_record(name: str) -> None:
|
||||
r for r in cfg["dns"]["custom_records"] if r["name"] != name
|
||||
]
|
||||
save_config(cfg)
|
||||
logger.info("DNS record removed: %s", name)
|
||||
|
||||
|
||||
# ───────── lease table ───────────────────────────────────────────────
|
||||
@@ -299,6 +327,7 @@ def set_upstreams(servers: list[str]) -> None:
|
||||
cfg = get_config()
|
||||
cfg["dns"]["upstreams"] = list(servers)
|
||||
save_config(cfg)
|
||||
logger.info("DNS upstreams set to %s", servers)
|
||||
|
||||
|
||||
def set_domain(domain: str | None) -> None:
|
||||
@@ -306,6 +335,7 @@ def set_domain(domain: str | None) -> None:
|
||||
cfg = get_config()
|
||||
cfg["dns"]["domain"] = domain if domain else None
|
||||
save_config(cfg)
|
||||
logger.info("DNS domain set to '%s'", domain)
|
||||
|
||||
|
||||
# ───────── status / info ─────────────────────────────────────────────
|
||||
@@ -315,7 +345,6 @@ def get_status() -> dict:
|
||||
"""Return service status, config summary, and current lease count."""
|
||||
cfg = get_config()
|
||||
|
||||
# dnsmasq process check
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["sudo", "systemctl", "is-active", "dnsmasq"],
|
||||
@@ -326,7 +355,6 @@ def get_status() -> dict:
|
||||
except Exception:
|
||||
active = False
|
||||
|
||||
# config on disk
|
||||
conf_exists = os.path.isfile(DNSMASQ_CONF)
|
||||
if conf_exists:
|
||||
try:
|
||||
@@ -337,7 +365,6 @@ def get_status() -> dict:
|
||||
else:
|
||||
conf_on_disk = ""
|
||||
|
||||
# current expected config
|
||||
expected = generate_conf(cfg)
|
||||
|
||||
leases = get_lease_table()
|
||||
|
||||
Reference in New Issue
Block a user