Files
felhom.eu/documentation/audits/release-2026-10-26/tools/repoint.py
T

86 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""repoint.py drill|live|status — (release 2026-10-26 copy: TARGET=9202, Homepage family_gate expected) point the box's controller at the drill catalog, or put the saved
controller.yaml back byte for byte.
The drill repo on Gitea is PRIVATE (R-992) and the box holds no catalog credential, so the drill is MIRRORED onto the
box: a bare git repository in the controller's own data volume, loaded from a git bundle, and
`git.repo_url: file:///opt/docker/felhom-controller/drill-catalog.git` — the method of
`audits/burndown-3-2026-10-17/tools/repoint.py`. The first version of this file set repo_url to the Gitea URL and
believed the repo public; the box's clone then failed („could not read Username", 21:18:11) and the controller ran on
the templates it already had — the first drill pass proved nothing (README, „Drill fixes").
`drill` ends with a POSITIVE check, not the absence of an error: the box's catalog cache must be at the drill's main
commit, and every `EXPECT` line must be in the box's copy of that template. Prints repo_url, never a token."""
import os, subprocess, sys, time
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools"))
os.environ.setdefault("TARGET", "9202")
import box_walk as w
DRILL = "/mnt/5_hdd/felhom.eu/drill/app-catalog-drill"
VOL = "/var/lib/docker/volumes/felhom-controller-data/_data" # guest path of the controller's data volume
CVOL = "/opt/docker/felhom-controller" # the same, inside the controller container
SAVE = f"{VOL}/controller.yaml.pre-release1026-drill"
MIRROR_URL = f"file://{CVOL}/drill-catalog.git"
EXPECT = [("n8n/docker-compose.yml", "N8N_DIAGNOSTICS_ENABLED=false"), ("opengist/docker-compose.yml", "256M"), ("homepage/.felhom.yml", "family_gate: true")]
def status():
print(w.guest(f"""grep -n 'repo_url' {VOL}/controller.yaml; ls -l {SAVE} 2>&1 | tail -1
docker exec felhom-controller sh -c 'git -C {CVOL}/drill-catalog.git log -1 --format="mirror main %h" main 2>&1;
git -C {CVOL}/data/catalog-cache log -1 --format="cache HEAD %h" 2>&1; git -C {CVOL}/data/catalog-cache remote get-url origin'"""))
def mirror():
b = f"/tmp/drill-rel1026-{os.getpid()}.bundle"
subprocess.run(["git", "-C", DRILL, "bundle", "create", b, "main"], check=True, capture_output=True)
subprocess.run(["scp", "-q", "-o", "StrictHostKeyChecking=accept-new", b, f"{w._T['ssh']}:{b}"], check=True)
subprocess.run(w.ssh_args() + [f"pct push {w.GUEST} {b} {VOL}/{os.path.basename(b)} && rm -f {b}"], check=True)
print(w.guest(f"""set -e
docker exec felhom-controller sh -c 'test -d {CVOL}/drill-catalog.git || git init -q --bare -b main {CVOL}/drill-catalog.git
git -C {CVOL}/drill-catalog.git fetch -q {CVOL}/{os.path.basename(b)} +main:main && rm -f {CVOL}/{os.path.basename(b)}
git -C {CVOL}/drill-catalog.git log -1 --format="mirror main %h" main'"""))
os.remove(b)
def restart_sync():
w.guest("docker restart felhom-controller >/dev/null")
for _ in range(60):
time.sleep(3)
try:
w.login()
break
except SystemExit:
continue
w.sync_rescan()
time.sleep(5)
print(w.guest("docker logs --since 3m felhom-controller 2>&1 | grep -E '\\[sync\\]' | grep -v DEBUG | tail -6 | cut -c1-200"))
def drill():
head = subprocess.run(["git", "-C", DRILL, "rev-parse", "--short=7", "main"], capture_output=True, text=True).stdout.strip()
mirror()
print(w.guest(f"""set -e
test -f {SAVE} || cp -p {VOL}/controller.yaml {SAVE}
sed -i -E 's#^(\\s+repo_url: ).*$#\\1{MIRROR_URL}#' {VOL}/controller.yaml
grep -n 'repo_url' {VOL}/controller.yaml"""))
restart_sync()
cache = w.guest(f"docker exec felhom-controller git -C {CVOL}/data/catalog-cache log -1 --format=%h").strip()
ok = cache.startswith(head)
for f, want in EXPECT:
got = w.guest(f"docker exec felhom-controller grep -c -- '{want}' {CVOL}/data/catalog-cache/templates/{f} || true").strip()
print(f" expect {f} ∋ {want}: {got}")
ok = ok and got not in ("", "0")
print(f"drill main {head}, box cache {cache}: " + ("DRILL-CONFIRMED" if ok else "DRILL-NOT-CONFIRMED"))
sys.exit(0 if ok else 1)
def live():
print(w.guest(f"""set -e
cp -p {SAVE} {VOL}/controller.yaml
cmp {SAVE} {VOL}/controller.yaml && echo RESTORED-IDENTICAL; grep -n 'repo_url' {VOL}/controller.yaml"""))
restart_sync()
status()
{"drill": drill, "live": live, "status": status}[sys.argv[1]]()