homelab: Update-Weg je App (Knopf nur, wo das Community-Script die App wirklich aktualisiert), Version von PVE Scripts Local aus der App selbst
Nachgelesen in ct/<app>.sh: AdGuard und PVE Scripts Local verweisen auf ihren eingebauten Updater, Gitea/NetBird/NPMplus aktualisieren wirklich, PBS ueber die Pakete. /root/.proxmoxve-local stand noch auf 0.5.8, die App selbst schon auf der neuesten Veroeffentlichung (v1.2.1, untagged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
56df849455
commit
528198de60
@@ -1,6 +1,13 @@
|
||||
"""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, zeigt die Übersicht
|
||||
sie ohne Versionsvergleich und ohne Webprüfung — nachtragen genügt.
|
||||
"""
|
||||
@@ -17,20 +24,22 @@ class App:
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
"arcane": App("arcane", "Arcane (Docker)", port=3552, weg="eigene-oberflaeche"),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,6 +83,13 @@ def _app_baustein(gast: dict, app: apps.App, zid: str) -> BausteinStand:
|
||||
stand.zustand, stand.grund = "unbekannt", "Die neueste Version ist gerade nicht abrufbar (GitHub)."
|
||||
return stand
|
||||
stand.verfuegbar = neu["version"]
|
||||
if installiert and installiert.startswith("untagged-"):
|
||||
# Manche Projekte veröffentlichen ohne Versions-Tag; die App kennt dann nur dieses Tag (PVE Scripts Local).
|
||||
if installiert == neu.get("tag_roh"):
|
||||
stand.installiert = neu["version"]
|
||||
return stand
|
||||
stand.zustand, stand.grund = "unbekannt", "Die installierte Fassung lässt sich keiner Version zuordnen."
|
||||
return stand
|
||||
if app.vergleich == "datum":
|
||||
# Docker-Image ohne Versionsnummer: neuer, wenn die Veröffentlichung jünger ist als das Image.
|
||||
bild = re.search(r"\d{4}-\d{2}-\d{2}", installiert or "")
|
||||
@@ -91,6 +98,9 @@ def _app_baustein(gast: dict, app: apps.App, zid: str) -> BausteinStand:
|
||||
ist_neuer = neuer(neu["version"], installiert) if installiert else None
|
||||
if ist_neuer is None:
|
||||
stand.zustand, stand.grund = "unbekannt", "Die installierte Version ließ sich nicht lesen."
|
||||
elif ist_neuer and app.weg != "skript":
|
||||
stand.zustand, stand.kurz = "neu", f"{installiert} → {neu['version']}"
|
||||
stand.grund = f"{app.name} aktualisiert sich über die eigene Oberfläche; das Community-Script tut es nicht."
|
||||
elif ist_neuer:
|
||||
stand.zustand, stand.kurz = "neu", f"{installiert} → {neu['version']}"
|
||||
rueckweg = ("Vorher wird ein Snapshot angelegt; ist die Prüfung danach rot, geht es von selbst zurück."
|
||||
|
||||
@@ -244,6 +244,9 @@ def starten(ziel_id: str, baustein: str) -> dict:
|
||||
return {"ok": False, "detail": "Dieses Gerät ist nicht freigegeben (Etikett watcher fehlt)."}
|
||||
app = apps.app_fuer((gast.get("app") or {}).get("kennung"), gast.get("name"))
|
||||
name = app.name if app else str(gast.get("name"))
|
||||
if baustein == "app" and (not app or app.weg != "skript"):
|
||||
return {"ok": False, "detail": f"{name} aktualisiert sich nicht über das Community-Script "
|
||||
"(eigene Oberfläche oder Pakete)."}
|
||||
lauf = _neuer_lauf(ziel_id, baustein, name)
|
||||
ziel = _host_lauf if gast is None else (lambda lf: _gast_lauf(lf, gast))
|
||||
threading.Thread(target=ziel, args=(lauf,), name=f"homelab-{ziel_id}", daemon=True).start()
|
||||
|
||||
Reference in New Issue
Block a user