33 lines
1.3 KiB
Python
33 lines
1.3 KiB
Python
|
|
"""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)
|