homelab: Arcane-Docker ehrlich zum Rückweg – Snapshot der VM nur mit Etikett watcher

Die Update-Liste zeigte bei Arcane „Snapshot vorher, bei Rot zurück“, obwohl das
Docker-Update keinen Snapshot anlegte (und der Ausführer VM 106 ohne Etikett gar
nicht anfassen darf). Jetzt:
- Gäste ohne Freigabe haben Rückweg „keiner“, Rückfrage und Plan sagen es.
- Echte Docker-Updates legen vorher einen Snapshot der VM an, wenn sie freigegeben
  ist, prüfen danach (Fehler-Container, Arcane antwortet binnen 3 min) und gehen
  bei Rot zurück – wie bei den Containern.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-25 10:29:07 +02:00
co-authored by Claude Opus 5.5
parent c37c0dccbb
commit 67ed0458a9
7 changed files with 117 additions and 25 deletions
+37
View File
@@ -284,6 +284,43 @@ def test_docker_ueber_arcane_erst_als_probelauf(ausfuehrer, monkeypatch):
assert updates.starten("vm-106", "docker")["ok"] is False
def test_docker_echt_mit_snapshot_nur_mit_etikett(ausfuehrer, monkeypatch):
starten, protokoll, meldungen, _ = ausfuehrer
monkeypatch.setenv("MC_ARCANE_KEY", "schluessel")
monkeypatch.setenv("MC_ARCANE_ECHT", "1")
monkeypatch.setattr(updates, "ARCANE_FRIST_S", 0)
monkeypatch.setattr(inventar.arcane, "images_mit_update", lambda url: [
{"name": "nginx:alpine", "aktuell": None, "neu": None, "umgebung": 0, "benutzt": ["web"]}])
ergebnis = {"local": {"checked": 7, "updated": 1, "failed": 0, "items": []}}
monkeypatch.setattr(updates.arcane, "updater", lambda url, probelauf: ergebnis)
starten("1.27.3")
# Ohne Etikett (wie VM 106 heute): kein Snapshot — Update-Liste und Rückfrage sagen es, statt einen zu versprechen.
arcane_ziel = _ziele(None)["vm-106"]
docker = {b["id"]: b for b in arcane_ziel["bausteine"]}["docker"]
assert arcane_ziel["rueckweg_art"] == "keiner" and "Etikett „watcher“ fehlt" in docker["aktion"]["frage"]
lauf = _auf_ende(updates.starten("vm-106", "docker")["lauf"])
assert (lauf["ergebnis"], protokoll) == ("eingespielt", [])
# Mit Etikett: vorher ein Snapshot der VM; ist die Prüfung rot, geht es darauf zurück.
bericht = json.loads(json.dumps(BERICHT))
next(g for g in bericht["gaeste"] if g["vmid"] == 106)["erlaubt"] = True
kanal.bericht_speichern(bericht)
arcane_ziel = next(z for z in inventar.ziele()["ziele"] if z["id"] == "vm-106")
docker = {b["id"]: b for b in arcane_ziel["bausteine"]}["docker"]
assert arcane_ziel["rueckweg_art"] == "snapshot" and "Vorher wird ein Snapshot angelegt" in docker["aktion"]["frage"]
ergebnis["local"]["failed"] = 1
lauf = _auf_ende(updates.starten("vm-106", "docker")["lauf"])
assert (lauf["ergebnis"], protokoll) == ("zurueckgerollt", ["snapshot", "zurueck"])
text, dringend = meldungen[-1]
assert dringend and "zurück auf den Snapshot mc2-20260924-190000" in text and "1 Container" in text
ergebnis["local"]["failed"] = 0
lauf = _auf_ende(updates.starten("vm-106", "docker")["lauf"])
assert lauf["ergebnis"] == "eingespielt" and protokoll[2:] == ["snapshot"]
assert meldungen[-1] == ("Arcane: 1 Container aktualisiert, Prüfung grün.", False)
def test_ausfuehrer_nur_lesen(monkeypatch):
a = _ausfuehrer_modul()
monkeypatch.setattr(a, "NUR_LESEN", True)
+4 -4
View File
@@ -123,7 +123,7 @@ def test_richtiger_schluessel_wird_gespeichert_und_gilt_sofort(daten, arcane_nac
assert datei.stat().st_mode & 0o077 == 0
assert _client().get("/api/homelab/einstellungen").json()["arcane"]["schluessel"] == "hinterlegt"
# Ohne Neustart: Die Übersicht fragt Arcane mit dem neuen Schlüssel und sieht die Images.
_, docker = inventar._arcane_bausteine(url, "vm-106")
_, docker = inventar._arcane_bausteine(url, "vm-106", {})
assert (docker.zustand, docker.kurz, docker.aktion.label) == ("neu", "1 Images", "Probelauf")
assert RICHTIG not in caplog.text
@@ -180,7 +180,7 @@ def test_loeschen(daten):
assert not (daten / "arcane.key").exists() and arcane.schluessel_quelle() == "fehlt"
assert _client().delete("/api/homelab/einstellungen/arcane-schluessel").json()["text"] == (
"Es war kein Arcane-Schlüssel hinterlegt.")
docker = inventar._arcane_bausteine("http://127.0.0.1:9", "vm-106")[1]
docker = inventar._arcane_bausteine("http://127.0.0.1:9", "vm-106", {})[1]
assert docker.zustand == "unbekannt" and docker.grund.startswith("Es fehlt ein Arcane-API-Schlüssel")
@@ -218,9 +218,9 @@ def test_echt_schalter(daten, monkeypatch):
def test_echt_schalter_macht_aus_dem_probelauf_ein_update(daten, arcane_nachbau):
url, _ = arcane_nachbau
assert einstellungen.arcane_schluessel_setzen(RICHTIG)["ok"]
assert inventar._arcane_bausteine(url, "vm-106")[1].aktion.label == "Probelauf"
assert inventar._arcane_bausteine(url, "vm-106", {})[1].aktion.label == "Probelauf"
assert einstellungen.arcane_echt_setzen(True)["ok"]
assert inventar._arcane_bausteine(url, "vm-106")[1].aktion.label == "Jetzt updaten"
assert inventar._arcane_bausteine(url, "vm-106", {})[1].aktion.label == "Jetzt updaten"
# --- Herkunftsprüfung (Middleware der App, Rolle homelab) ---------------------------------------------------------