All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 12m38s
- apps/prometheus was kapot: het koppelde een lege map op /etc/prometheus en startte met --config.file naar een bestand dat er nooit kwam. Er zit nu een startconfiguratie bij, met koppelvelden naar node-exporter en cAdvisor - De meeste apps van deze ronde zijn de ontbrekende helft van wat er al stond: node-exporter, cAdvisor en Alertmanager maken Prometheus bruikbaar; Loki en Alloy bewaren logs waar Dozzle alleen live meekijkt; Unbound zoekt DNS zelf op in plaats van door te vragen aan Google of Cloudflare - Domeinen die ontbraken: evcc (energie), Healthchecks (cronbewaking), Infisical (geheimen voor applicaties), Music Assistant, pgAdmin - Verder Crafty, Manyfold, ErsatzTV, FitTrackee, ComfyUI, Omada, en de zwaardere Zabbix, Graylog, Wazuh, NetBox, Seafile en OpenCloud. Van 218 naar 241 apps - Nieuw tools/controleer_images.py: controleert of elk image echt bestaat. De ad-hoc versie draaide met zestien verzoeken tegelijk en meldde negen ontbrekende images die alle negen wel bestonden -- registries knijpen af, en dat is niet te onderscheiden van een ontbrekend image. Nu vier tegelijk met opnieuw proberen, en als stap in de drie workflows Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9eqpADJSRs49SoGGr4NAy
77 lines
2.6 KiB
Python
77 lines
2.6 KiB
Python
"""Controleer of elk image in de catalogus echt bestaat bij zijn registry.
|
|
|
|
Aanleiding: `ghcr.io/plexguide/huntarr` stond in de ARR-stack terwijl dat project
|
|
offline was gehaald en het image niet meer bestond. Daarna bleken ook Forgejo,
|
|
Planka en Baby Buddy naar tags te wijzen die er niet zijn. Zulke fouten merk je
|
|
anders pas als iemand op installeren drukt.
|
|
|
|
python3 tools/controleer_images.py [--json]
|
|
|
|
**Waarom dit langzaam gaat.** Registries knijpen af bij te veel verzoeken achter
|
|
elkaar, en een afgeknepen verzoek ziet er precies zo uit als een image dat niet
|
|
bestaat. Eén ronde met zestien tegelijk leverde negen valse meldingen op — waarop
|
|
je bijna een werkend sjabloon gaat "repareren". Daarom weinig tegelijk, en wat
|
|
niet meteen lukt gaat opnieuw met oplopende pauzes.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import concurrent.futures as cf
|
|
import json
|
|
import re
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
WORTEL = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(WORTEL / "server-up" / "core"))
|
|
|
|
import registry # noqa: E402
|
|
|
|
TEGELIJK = 4
|
|
POGINGEN = 3
|
|
IMAGE_RE = re.compile(r"^\s*image:\s*(\S+)\s*$", re.M)
|
|
|
|
|
|
def images() -> dict[str, list[str]]:
|
|
"""Elk image in de catalogus, met de apps die het gebruiken."""
|
|
uit: dict[str, list[str]] = {}
|
|
for pad in sorted((WORTEL / "apps").glob("*/files/*.yaml")):
|
|
for m in IMAGE_RE.finditer(pad.read_text(encoding="utf-8")):
|
|
naam = m.group(1)
|
|
if "<<" in naam: # nog niet gerenderd
|
|
continue
|
|
uit.setdefault(naam, []).append(pad.parent.parent.name)
|
|
return uit
|
|
|
|
|
|
def bestaat(image: str) -> bool:
|
|
for poging in range(POGINGEN):
|
|
try:
|
|
if registry.manifest_digest(image):
|
|
return True
|
|
except Exception:
|
|
pass
|
|
if poging < POGINGEN - 1:
|
|
time.sleep(2 ** poging) # 1s, 2s
|
|
return False
|
|
|
|
|
|
def main() -> int:
|
|
alles = images()
|
|
with cf.ThreadPoolExecutor(TEGELIJK) as ex:
|
|
uitslag = dict(zip(alles, ex.map(bestaat, alles)))
|
|
|
|
fout = {i: alles[i] for i, ok in uitslag.items() if not ok}
|
|
if "--json" in sys.argv:
|
|
print(json.dumps({"gecontroleerd": len(alles), "fout": fout}, indent=2))
|
|
else:
|
|
print(f"{len(alles)} unieke images gecontroleerd")
|
|
for image, apps in sorted(fout.items()):
|
|
print(f" ✖ {image} ({', '.join(sorted(set(apps)))})")
|
|
if not fout:
|
|
print(" alle images bestaan")
|
|
return 1 if fout else 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|