Jeder Bericht wird mit einem Register bekannter Geräte verglichen; ein neuer Container oder eine neue VM erscheint im Homelab-Cockpit unter „Neu entdeckt“, und Lucy meldet ihn einmal über Telegram. Übernehmen: „Für Updates freigeben“ (der Ausführer setzt das Etikett watcher — neue Aktion etikett_setzen, sie darf nur watcher und watcher-aus setzen oder entfernen), „Nur beobachten“ oder „Nicht anfassen“ (watcher-aus). Unbekannte Community-Scripts-Kennungen trägt katalog.py aus ihrem Update-Skript nach (Name, GitHub-Projekt, Port, Weg); ein Port, der nicht antwortet, schaltet die Webprüfung nicht ein. Der Ausführer braucht ausfuehrer-einrichten.sh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
3.0 KiB
Python
62 lines
3.0 KiB
Python
"""Was in welchem Container steckt (Community-Scripts-Kennung aus /usr/bin/update im Gast).
|
|
|
|
Stand der Bestandsaufnahme vom 24.09.2026: sechs Container, alle mit dem Etikett community-script.
|
|
|
|
Wie eine App aktualisiert wird, ist je Community-Script verschieden (nachgelesen am 24.09. in ct/<app>.sh):
|
|
skript `update` im Gast spielt die App wirklich neu ein (Gitea: neues Programm von GitHub,
|
|
NetBird: apt aus dem NetBird-Repository, NPMplus: neues Docker-Image)
|
|
eigene-oberflaeche das Skript verweist auf den eingebauten Updater der App (AdGuard, PVE Scripts Local)
|
|
pakete die App kommt als Paket; das Update der Pakete im Gast ist ihr Update (PBS)
|
|
Nur beim Weg „skript“ bietet die Übersicht „Jetzt updaten“ für die App an.
|
|
Neue Container mit dem Etikett erscheinen von selbst. Fehlt ihre Kennung hier, liest katalog.py (seit 25.09.2026)
|
|
Name, GitHub-Projekt, Port und Weg aus ihrem Update-Skript; was hier von Hand steht, geht vor (etwa ein geänderter
|
|
Port wie bei AdGuard).
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class App:
|
|
kennung: str
|
|
name: str
|
|
quelle: str | None = None # GitHub owner/repo für die neueste Version; None = über die Pakete des Gasts
|
|
vergleich: str = "version" # „version“ oder „datum“ (Docker-Images ohne Versionsnummer)
|
|
port: int | None = None # Weboberfläche; None = keine (z. B. NetBird-Client)
|
|
https: bool = False
|
|
pfad: str = "/"
|
|
weg: str = "skript" # „skript“, „eigene-oberflaeche“ oder „pakete“ (siehe oben)
|
|
|
|
|
|
KATALOG: dict[str, App] = {a.kennung: a for a in (
|
|
App("adguard", "AdGuard Home", "AdguardTeam/AdGuardHome", port=8080, weg="eigene-oberflaeche"),
|
|
App("npmplus", "NPMplus", "ZoeyVid/NPMplus", vergleich="datum", port=81, https=True),
|
|
App("netbird", "NetBird", "netbirdio/netbird"),
|
|
App("pve-scripts-local", "PVE Scripts Local", "community-scripts/ProxmoxVE-Local", port=3000,
|
|
weg="eigene-oberflaeche"),
|
|
App("gitea", "Gitea", "go-gitea/gitea", port=3000),
|
|
App("proxmox-backup-server", "Proxmox Backup Server", port=8007, https=True, weg="pakete"),
|
|
)}
|
|
|
|
# Gäste, die keine Community-Scripts sind, erkennt man am Namen.
|
|
NACH_NAME: dict[str, App] = {
|
|
"arcane": App("arcane", "Arcane (Docker)", port=3552, weg="eigene-oberflaeche"),
|
|
}
|
|
|
|
|
|
def app_fuer(kennung: str | None, name: str | None) -> App | None:
|
|
if kennung and kennung in KATALOG:
|
|
return KATALOG[kennung]
|
|
if kennung:
|
|
from services.homelab import katalog # der Katalog baut Apps aus diesem Modul — erst hier
|
|
if gefunden := katalog.app(kennung):
|
|
return gefunden
|
|
return NACH_NAME.get(str(name or "").lower())
|
|
|
|
|
|
def adresse(app: App | None, ip: str | None) -> str | None:
|
|
"""Adresse der Weboberfläche, falls es eine gibt und die IP bekannt ist."""
|
|
if not app or not app.port or not ip:
|
|
return None
|
|
return f"{'https' if app.https else 'http'}://{ip}:{app.port}{app.pfad}"
|