feat(updater): support updates after verified SeaweedFS migration
This commit is contained in:
@@ -47,7 +47,8 @@ const reload = () => window.location.reload()
|
||||
<p class="text-sm text-muted">Aktualisiert die gesamte Selfhost-Instanz einschließlich Docker Compose und Datenbank. Vor Änderungen wird ein Backup erstellt.</p>
|
||||
<div role="status" aria-live="polite" class="space-y-3">
|
||||
<UAlert v-if="message" :color="busy ? 'warning' : 'neutral'" variant="soft" :title="message" />
|
||||
<UAlert v-if="recovery" color="error" title="Wiederherstellung auf dem Host erforderlich" description="Weitere Updates sind gesperrt. Den letzten Auftrag und die Backups auf dem Host prüfen." />
|
||||
<UAlert v-if="recovery && overview?.storage?.migrationPending" color="warning" title="Speicherumstellung auf dem Host abschließen" description="Updates bleiben gesperrt, bis die geprüfte Migration an den neuen Host-Updater übergeben wurde. Die bestehende FEDEO-Version kann danach regulär aktualisiert werden." />
|
||||
<UAlert v-else-if="recovery" color="error" title="Wiederherstellung auf dem Host erforderlich" description="Weitere Updates sind gesperrt. Den letzten Auftrag und die Backups auf dem Host prüfen." />
|
||||
<UAlert v-if="job?.error" color="error" :title="job.error.message" />
|
||||
<UAlert v-if="job?.plan?.requiresComposeAdoption" color="warning" title="Compose-Datei zuerst auf dem Host übernehmen" description="Die bestehende Konfiguration benötigt eine manuelle Prüfung mit dem CLI-Updater. Anschließend hier erneut nach Updates suchen." />
|
||||
<p v-if="job || busy" class="text-sm font-medium">{{ statusLabel }}</p>
|
||||
@@ -58,6 +59,8 @@ const reload = () => window.location.reload()
|
||||
<div><dt class="text-muted">Commit</dt><dd class="font-mono" :title="job.plan.revision">{{ job.plan.revision?.slice(0, 8) }}</dd></div>
|
||||
<div><dt class="text-muted">Geschätztes Backup</dt><dd>{{ backupSize }}</dd></div>
|
||||
</dl>
|
||||
<p v-if="job?.plan?.storageProvider === 'seaweedfs'" class="text-sm text-muted">Dateispeicher: SeaweedFS. Die geprüfte Speicherversion bleibt erhalten und wird zusammen mit der Datenbank gesichert.</p>
|
||||
<p v-else-if="job?.plan?.storageProvider === 'minio'" class="text-sm text-muted">Dateispeicher: MinIO. Eine Umstellung auf SeaweedFS erfolgt als eigener, geprüfter Wartungsschritt auf dem Host.</p>
|
||||
<p v-if="job?.plan?.retiredServices.length" class="text-sm text-muted">Alte Matrix-Dienste werden stillgelegt; Daten und Container bleiben erhalten: {{ job.plan.retiredServices.join(', ') }}.</p>
|
||||
<p v-if="job?.requestId" class="break-all text-xs text-muted">Auftrag: {{ job.requestId }}</p>
|
||||
<section v-if="job?.requestId && !accessDenied" aria-label="Update-Protokoll" class="space-y-3 rounded-lg border border-default p-3">
|
||||
|
||||
@@ -5,13 +5,15 @@ export type UpdateState = {
|
||||
export type UpdateJob = UpdateState & {
|
||||
progress?: UpdateState; error?: { code: string; message: string };
|
||||
plan?: { version: string; revision: string; previousVersion?: string; updateAvailable: boolean;
|
||||
requiresComposeAdoption: boolean; estimatedBackupBytes?: number; retiredServices: string[] };
|
||||
requiresComposeAdoption: boolean; estimatedBackupBytes?: number; retiredServices: string[];
|
||||
storageProvider?: 'minio' | 'seaweedfs'; storageImageRetained?: boolean };
|
||||
}
|
||||
export type UpdateLogs = { requestId: string; logs: { source: 'service' | 'events' | 'commands'; content: string; truncated: boolean }[] }
|
||||
type Overview = {
|
||||
acceptingRequests: boolean; engine: UpdateState; request?: UpdateJob;
|
||||
installed: { version?: string }; backend: { version: string; revision: string };
|
||||
capabilities?: { requestLogs: boolean };
|
||||
storage?: { provider: 'seaweedfs'; migrationPending: boolean };
|
||||
}
|
||||
type Submission = { command: 'check' | 'apply'; body: { requestId: string; version?: string; checkRequestId?: string } }
|
||||
|
||||
|
||||
@@ -82,6 +82,19 @@ test('recovery, up-to-date, unmanaged compose and other active jobs prevent appl
|
||||
}
|
||||
})
|
||||
|
||||
test('a completed storage migration stays blocked until the host handover is complete', async t => {
|
||||
let state = { ...overview(check, { status: 'failed', recoveryRequired: true }),
|
||||
storage: { provider: 'seaweedfs', migrationPending: true } }
|
||||
const f = await setup(t, async path => path.endsWith('/status') ? state : state.request)
|
||||
assert.equal(f.ui.overview.value.storage.migrationPending, true)
|
||||
assert.equal(f.ui.canApply.value, false)
|
||||
state = { ...overview({ ...check, plan: { ...check.plan, storageProvider: 'seaweedfs', storageImageRetained: true } }),
|
||||
storage: { provider: 'seaweedfs', migrationPending: false } }
|
||||
await f.ui.refresh()
|
||||
assert.equal(f.ui.canApply.value, true)
|
||||
assert.equal(f.ui.job.value.plan.storageProvider, 'seaweedfs')
|
||||
})
|
||||
|
||||
test('an older polling response cannot erase a new submission whose response was lost', async t => {
|
||||
let hold = false, release
|
||||
const f = await setup(t, async (path, options) => {
|
||||
|
||||
Reference in New Issue
Block a user