furtka-gateway/control_plane/reconciler.py

33 lines
1.3 KiB
Python
Raw Normal View History

"""Diff enabled routes in the DB against Traefik dynamic-config files on
disk and repair drift.
Structural echo of furtka/furtka/reconciler.py's "declared state -> drive
external state, self-heal on drift" shape. publish_route()/unpublish_route()
already write/remove the matching file synchronously, so this isn't on the
hot path for normal operation it's the safety net for anything that made
the DB and the filesystem disagree (a crash mid-write, a file deleted by
hand, etc). Not yet wired into app.py's server loop; run it from a systemd
timer or an ad hoc `python -m control_plane.reconciler` invocation for now.
"""
from __future__ import annotations
from control_plane import traefikconf
from control_plane.db import Database
def reconcile(db: Database, cert_resolver: str | None) -> None:
wanted = db.query_all(
"SELECT r.id, r.subdomain, r.target_port, b.wg_allowed_ip "
"FROM routes r JOIN boxes b ON b.id = r.box_id "
"WHERE r.enabled = 1"
)
wanted_ids = set()
for row in wanted:
wanted_ids.add(row["id"])
target_ip = row["wg_allowed_ip"].split("/")[0]
traefikconf.write_route(row["id"], row["subdomain"], target_ip, row["target_port"], cert_resolver)
for orphan_id in traefikconf.existing_route_ids() - wanted_ids:
traefikconf.remove_route(orphan_id)