fix(network): correct adoptDockerSubnet comment + guard ipAllocation double-INSERT

Two latent issues uncovered while designing network-drift detection:

- adoptDockerSubnet's comment claimed apps' IPs stay inside docker's
  subnet after adoption. False: IPs are pinned to the old subnet's first
  three octets, so adopting a different /24 base strands every app IP
  out-of-subnet. Document the real behaviour + the heal paths.

- ipAllocation fell through from the existing-row branch to the
  unconditional INSERT, which would violate UNIQUE(app,type,service).
  Unreachable on today's reset path (rows are deleted first) but a hazard
  for any direct caller; add an explicit return after reuse/reset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
librelad 2026-06-02 15:52:55 +01:00
parent 287c13a311
commit d23ad87246
2 changed files with 13 additions and 5 deletions

View File

@ -1,11 +1,14 @@
#!/bin/bash
# CFG↔docker subnet adoption: if the docker network already exists with a
# different /24 than CFG, treat docker's value as the truth and update CFG.
# Apps' allocated IPs are still inside docker's subnet, so nothing else needs
# re-IPing. (A genuine user-initiated subnet change is a `libreportal app
# install <name> --reset-network` per app — fresh compose + fresh IPs from
# the new subnet via the standard idempotent install path.)
# different subnet than CFG, treat docker's value as the truth and update CFG.
# This realigns CFG ONLY — it does NOT touch already-allocated per-app IPs.
# Because IPs are pinned to the first three octets of the old subnet
# (ipFindAvailable), adopting a different /24 base strands every existing app
# IP outside docker's real subnet. Those apps need re-IPing from the corrected
# subnet: automatically via the network-drift detector + `libreportal system
# network heal`, or manually per app via `libreportal app install <name>
# --reset-network` (fresh compose + fresh IPs through the idempotent install).
adoptDockerSubnet()
{
local current_subnet="$1"

View File

@ -23,6 +23,7 @@ ipAllocation()
if [[ -z "$available_ip" ]]; then
isError "No available IP addresses in pool"
allocated_ip="$existing_ip"
return 1
fi
sqlite3 "$docker_dir/$db_file" \
"UPDATE network_resources \
@ -33,6 +34,10 @@ ipAllocation()
else
allocated_ip="$existing_ip"
fi
# An active row already exists for this app+service — reused or reset in
# place above. Don't fall through to the INSERT below: that second write
# would violate UNIQUE(app_name,resource_type,service_name).
return 0
fi
ipFindAvailable