VM-Updates: EINEN einheitlichen Bulk-Flow (immer Auswahl-Tabelle + Bestätigung, kanonisch bulk-job) — 3 Pfade konsolidieren #123

Closed
opened 2026-06-22 08:17:58 +00:00 by chinux · 1 comment
Owner

Problem

Der VM-Update-Flow ist dreifach zersplittert und verhaelt sich je nach Einstieg unterschiedlich — "da macht er so, da so, da so". Konkret beobachtet: Im NodeCard startet "Alle X aktualisieren" sofort den Run (running/pending, keine Tabelle), im Node→VMs-Panel landet man dagegen im Bulk-Modus mit Auswahl-Tabelle. Erwartet war ueberall der Auswahl-Modus.

Ist-Zustand (verifiziert @ 915fc87)

Backend — 3 parallele Pfade (update_router.py):

  • POST /bulk-job + GET /bulk-job/{id} + /cancel-item (async Job + Polling) ← Panel
  • POST /bulk-run + GET /bulk-run/{id} + /cancel (anderer async Run) ← NodeCard (bulkRunApi)
  • POST /vms/bulk-update + /vms/bulk-preview (synchroner Batch) ← Panel-Vorschau

Frontend — 2 Einstiege, unterschiedliches Verhalten:

  • NodeCard (+page.svelte:849-922, bulkRunByNode): nur confirm()sofort bulkRunApi.start + Poll. Keine Tabelle, keine Auswahl.
  • NodeUpdatesPanel (NodeUpdatesPanel.svelte): enterBulkSelectAll() → Bulk-Modus mit Tabelle (vorselektiert, abwaehlbar) → "Vorschau"/"Updates ausfuehren".

Soll-Zustand (Entscheidung)

EIN einziger, ueberall identischer Update-Flow. Immer Bulk-Modus.

  1. Kanonischer Backend-Pfad: bulk-job (+ getBulkJob-Polling, cancel-item). bulk-run und der synchrone bulk-update-Run werden entfernt (bulk-preview kann als Vorschau-Helfer bleiben, wenn vom Bulk-Modus genutzt — sonst auch raus).
  2. NodeCard-Button "Alle X aktualisieren" startet NICHTS direkt — er oeffnet/navigiert in denselben Panel-Bulk-Modus (gleiche Komponente/State), kein eigener Flow.
  3. Immer Auswahl-Tabelle (alle aktualisierbaren VMs vorselektiert, einzeln abwaehlbar) — auch bei nur 1 VM (keine Sonderbehandlung Einzel-VM; der bestehende Einzel-/vms/{vmid}/update darf intern bleiben, aber der Nutzer-Flow ist immer Bulk).
  4. Bestaetigungs-Schritt vor Start (immer): explizite Bestaetigung ("N VMs aktualisieren?") nach Auswahl, bevor der bulk-job startet.
  5. Ein gemeinsames Frontend-Modul fuer den Bulk-Modus (State + Tabelle + Run + Polling), das sowohl NodeCard als auch der VMs-Tab benutzen — Single Source of Truth, kein dupliziertes Verhalten.

Aufgaben

  • Bulk-Logik in eine wiederverwendbare Komponente/Store ziehen (z. B. BulkUpdateMode.svelte + Store), von NodeCard und NodeUpdatesPanel genutzt.
  • NodeCard bulkRunByNode (+page.svelte:849-922) entfernen; Button ruft nur noch "enter Bulk-Modus (alle vorselektiert)".
  • Auf bulk-job vereinheitlichen; bulkRunApi (/bulk-run*), BulkRunModal.svelte, BulkHistoryModal.svelte sowie /bulk-update (sofern nicht als Vorschau gebraucht) entfernen — inkl. toter Backend-Endpoints.
  • Bestaetigungs-Dialog vor startBulkJob.
  • Bulk-Modus auch fuer 1 VM (keine Abkuerzung).
  • CT und VM gleich behandeln (Kandidatenliste konsistent — kein Sonderpfad).
  • localStorage-Run-Resume (BULK_LS_KEY / bulk_job_id_*) auf den einen Pfad vereinheitlichen.

Akzeptanz

  • Egal ob NodeCard "Alle X aktualisieren" oder VMs-Tab: identischer Bulk-Modus mit Tabelle, Vorselektion, Abwahl, Bestaetigung, dann Run via bulk-job.
  • Kein Direktstart mehr ohne Auswahl/Bestaetigung.
  • Nur noch ein Bulk-Backend-Pfad existiert; tote Endpoints/Komponenten entfernt.
  • Verhalten bei 1 VM == bei N VMs (immer Bulk).

Bezug

#122 (hatte das Auswahl-Modal entfernt — wird hier neu/anders geloest), #94 (NodeCard lebt im 4.158-Z. +page.svelte → diese Konsolidierung zahlt auf die Zerlegung ein), #95.

Branch

refactor/unify-vm-bulk-update-flow

## Problem Der VM-Update-Flow ist **dreifach zersplittert** und verhaelt sich je nach Einstieg unterschiedlich — "da macht er so, da so, da so". Konkret beobachtet: Im NodeCard startet "Alle X aktualisieren" **sofort** den Run (running/pending, keine Tabelle), im Node→VMs-Panel landet man dagegen im Bulk-Modus **mit** Auswahl-Tabelle. Erwartet war ueberall der Auswahl-Modus. ## Ist-Zustand (verifiziert @ 915fc87) **Backend — 3 parallele Pfade** (`update_router.py`): - `POST /bulk-job` + `GET /bulk-job/{id}` + `/cancel-item` (async Job + Polling) ← Panel - `POST /bulk-run` + `GET /bulk-run/{id}` + `/cancel` (anderer async Run) ← NodeCard (`bulkRunApi`) - `POST /vms/bulk-update` + `/vms/bulk-preview` (synchroner Batch) ← Panel-Vorschau **Frontend — 2 Einstiege, unterschiedliches Verhalten:** - **NodeCard** (`+page.svelte:849-922`, `bulkRunByNode`): nur `confirm()` → **sofort `bulkRunApi.start` + Poll**. Keine Tabelle, keine Auswahl. - **NodeUpdatesPanel** (`NodeUpdatesPanel.svelte`): `enterBulkSelectAll()` → Bulk-Modus mit Tabelle (vorselektiert, abwaehlbar) → "Vorschau"/"Updates ausfuehren". ## Soll-Zustand (Entscheidung) **EIN einziger, ueberall identischer Update-Flow. Immer Bulk-Modus.** 1. **Kanonischer Backend-Pfad: `bulk-job`** (+ `getBulkJob`-Polling, `cancel-item`). `bulk-run` und der synchrone `bulk-update`-Run werden **entfernt** (bulk-preview kann als Vorschau-Helfer bleiben, wenn vom Bulk-Modus genutzt — sonst auch raus). 2. **NodeCard-Button "Alle X aktualisieren" startet NICHTS direkt** — er oeffnet/navigiert in **denselben** Panel-Bulk-Modus (gleiche Komponente/State), kein eigener Flow. 3. **Immer Auswahl-Tabelle** (alle aktualisierbaren VMs vorselektiert, einzeln abwaehlbar) — **auch bei nur 1 VM** (keine Sonderbehandlung Einzel-VM; der bestehende Einzel-`/vms/{vmid}/update` darf intern bleiben, aber der Nutzer-Flow ist immer Bulk). 4. **Bestaetigungs-Schritt vor Start** (immer): explizite Bestaetigung ("N VMs aktualisieren?") nach Auswahl, bevor der bulk-job startet. 5. Ein gemeinsames Frontend-Modul fuer den Bulk-Modus (State + Tabelle + Run + Polling), das **sowohl** NodeCard als auch der VMs-Tab benutzen — Single Source of Truth, kein dupliziertes Verhalten. ## Aufgaben - [ ] Bulk-Logik in **eine** wiederverwendbare Komponente/Store ziehen (z. B. `BulkUpdateMode.svelte` + Store), von NodeCard **und** NodeUpdatesPanel genutzt. - [ ] NodeCard `bulkRunByNode` (+page.svelte:849-922) entfernen; Button ruft nur noch "enter Bulk-Modus (alle vorselektiert)". - [ ] Auf `bulk-job` vereinheitlichen; `bulkRunApi` (`/bulk-run*`), `BulkRunModal.svelte`, `BulkHistoryModal.svelte` sowie `/bulk-update` (sofern nicht als Vorschau gebraucht) **entfernen** — inkl. toter Backend-Endpoints. - [ ] Bestaetigungs-Dialog vor `startBulkJob`. - [ ] Bulk-Modus auch fuer 1 VM (keine Abkuerzung). - [ ] CT **und** VM gleich behandeln (Kandidatenliste konsistent — kein Sonderpfad). - [ ] localStorage-Run-Resume (`BULK_LS_KEY` / `bulk_job_id_*`) auf den einen Pfad vereinheitlichen. ## Akzeptanz - Egal ob NodeCard "Alle X aktualisieren" oder VMs-Tab: **identischer** Bulk-Modus mit Tabelle, Vorselektion, Abwahl, Bestaetigung, dann Run via `bulk-job`. - Kein Direktstart mehr ohne Auswahl/Bestaetigung. - Nur noch **ein** Bulk-Backend-Pfad existiert; tote Endpoints/Komponenten entfernt. - Verhalten bei 1 VM == bei N VMs (immer Bulk). ## Bezug #122 (hatte das Auswahl-Modal entfernt — wird hier neu/anders geloest), #94 (NodeCard lebt im 4.158-Z. +page.svelte → diese Konsolidierung zahlt auf die Zerlegung ein), #95. ## Branch `refactor/unify-vm-bulk-update-flow`
Author
Owner

Bulk-Flow vereinheitlicht — ein einziger Weg (bulk-job) über alle Einstiege.

Commits (main):

  • 7291a19 feat(updates): unified BulkUpdateMode component + bulkUpdate store (#123)
  • 1bbac96 refactor(updates): NodeUpdatesPanel uses BulkUpdateMode (#123)
  • 58748f8 refactor(updates): NodeCard + global dropdown use BulkUpdateMode, drop direct-start (#123)
  • e3924fa refactor(updates): remove dead bulk-run + sync bulk-update paths (#123)

Architektur (zahlt auf #94 ein):

  • Neu frontend/src/lib/stores/bulkUpdate.svelte.ts — Runes-Class-Singleton, EIN aktiver Job, ein localStorage-Key theprox.bulkJob, Phasen idle/select/running/done, Poll @1s über getBulkJob, bei Abschluss scan der „done"-Items + Event theprox:bulk-done, resume() nach Reload.
  • Neu frontend/src/lib/components/updates/BulkUpdateMode.svelte — EIN globales Modal (einmal in +page.svelte gerendert): Auswahl-Tabelle (vorselektiert, einzeln abwählbar, Node-Spalte nur bei >1 Node, Preview) → Bestätigung → Live-Fortschritt (cancel-item pro VM). Tabellen-Optik 1:1 aus dem Panel übernommen.
  • NodeUpdatesPanel „Bulk-Modus", NodeCard „Alle X aktualisieren" und das globale Cross-Tenant-Dropdown öffnen dasselbe Modal/State. Single Source of Truth.

Akzeptanzkriterien:

  • NodeCard == VMs-Tab == globales Dropdown: identischer Bulk-Modus (gleiche Komponente).
  • IMMER Auswahl-Tabelle (vorselektiert, abwählbar) + Bestätigung, dann Run via bulk-job. Auch bei genau 1 VM (keine Sonderbehandlung).
  • Kein Direktstart mehr (per-node startNodeBulkUpdate/bulkJobByNode-Direktlauf entfernt).
  • Nur noch EIN Bulk-Backend-Pfad. Verbleibend in update_router.py: bulk-preview, bulk-job (+get/cancel-item), neu GET /bulk-candidates?scope= (ersetzt die /bulk-run-Discovery, nutzt _collect_pending_items). Entfernt: /bulk-run*, /bulk-runs, synchroner /vms/bulk-update, Frontend bulkRunApi, BulkRunModal.svelte, BulkHistoryModal.svelte, services/bulk_update_runner.py. BulkRun-Model + Tabelle bleiben (keine Migration/kein Table-Drop).
  • Cross-Tenant-Funktion erhalten: globales Dropdown sammelt via /bulk-candidates alle aktualisierbaren VMs über die sichtbaren Nodes und öffnet damit denselben Bulk-Modus (bulk-job ist multi-node).
  • CT und VM in einer Kandidatenliste, kein Sonderpfad.

Single-VM-User-Flow: per-Zeilen-„Update"-Button im Panel entfernt (read-only „Preview" bleibt). /vms/{vmid}/update bleibt intern (von bulk-job pro Item genutzt).

Hinweis / offen für Maintainer-Entscheid: CT-Kandidaten-Parität. Per-Node-Einstieg (NodeCard/Panel) selektiert wie bisher updates_available > 0 → CTs ohne Update-Count erscheinen dort nicht; das /bulk-candidates-Backend listet laufende CTs immer mit. Bewusst nicht „neu erfunden" (kein neues Verhalten außer Vereinheitlichung) — falls exakte Parität gewünscht: per-node CTs ebenfalls immer einschließen. Kurzer Follow-up.

svelte-check: 3 Errors → 3 Errors (alle vorbestehend, fremde Dateien), Warnings 236 → 230. Backend parst. +page.svelte 1810 → 1696.

**Bulk-Flow vereinheitlicht** — ein einziger Weg (bulk-job) über alle Einstiege. Commits (`main`): - `7291a19` feat(updates): unified BulkUpdateMode component + bulkUpdate store (#123) - `1bbac96` refactor(updates): NodeUpdatesPanel uses BulkUpdateMode (#123) - `58748f8` refactor(updates): NodeCard + global dropdown use BulkUpdateMode, drop direct-start (#123) - `e3924fa` refactor(updates): remove dead bulk-run + sync bulk-update paths (#123) **Architektur (zahlt auf #94 ein):** - Neu `frontend/src/lib/stores/bulkUpdate.svelte.ts` — Runes-Class-Singleton, EIN aktiver Job, ein localStorage-Key `theprox.bulkJob`, Phasen idle/select/running/done, Poll @1s über `getBulkJob`, bei Abschluss `scan` der „done"-Items + Event `theprox:bulk-done`, `resume()` nach Reload. - Neu `frontend/src/lib/components/updates/BulkUpdateMode.svelte` — EIN globales Modal (einmal in `+page.svelte` gerendert): Auswahl-Tabelle (vorselektiert, einzeln abwählbar, Node-Spalte nur bei >1 Node, Preview) → Bestätigung → Live-Fortschritt (cancel-item pro VM). Tabellen-Optik 1:1 aus dem Panel übernommen. - NodeUpdatesPanel „Bulk-Modus", NodeCard „Alle X aktualisieren" und das globale Cross-Tenant-Dropdown öffnen **dasselbe** Modal/State. Single Source of Truth. **Akzeptanzkriterien:** - ✅ NodeCard == VMs-Tab == globales Dropdown: identischer Bulk-Modus (gleiche Komponente). - ✅ IMMER Auswahl-Tabelle (vorselektiert, abwählbar) + Bestätigung, dann Run via `bulk-job`. Auch bei genau 1 VM (keine Sonderbehandlung). - ✅ Kein Direktstart mehr (per-node `startNodeBulkUpdate`/`bulkJobByNode`-Direktlauf entfernt). - ✅ Nur noch EIN Bulk-Backend-Pfad. Verbleibend in `update_router.py`: `bulk-preview`, `bulk-job` (+get/cancel-item), neu `GET /bulk-candidates?scope=` (ersetzt die `/bulk-run`-Discovery, nutzt `_collect_pending_items`). **Entfernt:** `/bulk-run*`, `/bulk-runs`, synchroner `/vms/bulk-update`, Frontend `bulkRunApi`, `BulkRunModal.svelte`, `BulkHistoryModal.svelte`, `services/bulk_update_runner.py`. `BulkRun`-Model + Tabelle bleiben (keine Migration/kein Table-Drop). - ✅ Cross-Tenant-Funktion erhalten: globales Dropdown sammelt via `/bulk-candidates` alle aktualisierbaren VMs über die sichtbaren Nodes und öffnet damit denselben Bulk-Modus (bulk-job ist multi-node). - ✅ CT und VM in einer Kandidatenliste, kein Sonderpfad. Single-VM-User-Flow: per-Zeilen-„Update"-Button im Panel entfernt (read-only „Preview" bleibt). `/vms/{vmid}/update` bleibt intern (von bulk-job pro Item genutzt). **Hinweis / offen für Maintainer-Entscheid:** CT-Kandidaten-Parität. Per-Node-Einstieg (NodeCard/Panel) selektiert wie bisher `updates_available > 0` → CTs ohne Update-Count erscheinen dort nicht; das `/bulk-candidates`-Backend listet laufende CTs immer mit. Bewusst nicht „neu erfunden" (kein neues Verhalten außer Vereinheitlichung) — falls exakte Parität gewünscht: per-node CTs ebenfalls immer einschließen. Kurzer Follow-up. svelte-check: 3 Errors → 3 Errors (alle vorbestehend, fremde Dateien), Warnings 236 → 230. Backend parst. `+page.svelte` 1810 → 1696.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chinux/theProx#123
No description provided.