controller v0.242.0: a removed app is listed with its kept backup; five small ones (R-487 R-491 R-490 R-489 R-476 R-456)
gates / gates (push) Successful in 14s

R-487: the local backup lists are keyed on the drives, not on what is
deployed — a removed app whose unit was kept is listed with the restore
that reinstalls it, the picker answers for it, and the restore opens the
unit where it sits. R-491: a removal clears the app's update hold.
R-490: /api/system/info reaches the API router and reads the default
storage path. R-489: volumes_removed is the real before/after difference,
[] when none. R-476: a Tier-2 copy is dated by its data, not its manifest.
R-456: the boot-orphan rule is pinned. Every fix red-proofed.
This commit is contained in:
2026-09-13 22:50:18 +02:00
parent c1f62ddae8
commit d698ce343b
22 changed files with 838 additions and 13 deletions
+24
View File
@@ -1090,6 +1090,8 @@ func (s *Server) backupsRestoreHandler(w http.ResponseWriter, r *http.Request) {
// page listed these, so they accumulated invisibly and the only way to find them was SSH.
if s.backupMgr != nil {
data["OffsiteRestoreCopies"] = s.backupMgr.ListOffsiteRestoreCopies()
// R-487: removed apps whose unit was kept join the local restore picker.
data["RemovedApps"] = s.backupMgr.ListRemovedAppUnits()
}
// R-237: the restore list is driven by the STORE, not by what is deployed and toggled. A rebuilt
// box has neither, and used to be shown nothing at all while its snapshots sat in the repository.
@@ -1209,6 +1211,11 @@ type AppBackupRow struct {
// Drive disconnected — app's home drive is currently disconnected
DriveDisconnected bool
// Removed (R-487) — the app is NOT deployed; this row stands for a recovery unit kept on a
// drive after „Töröld az adataimat is" with the backups kept. Its one action is the unit restore,
// which reinstalls (R-253). RemovedUnitTime is the unit's newest artifact, RFC3339.
Removed bool
RemovedUnitTime string
// Tier2 destination drive is currently disconnected (backup paused, not failed)
Tier2DestDisconnected bool
// Tier2 destination drive is inactive (Schedulable=false, backup paused)
@@ -1458,6 +1465,23 @@ func (s *Server) buildAppBackupRows(status *backup.FullBackupStatus) []AppBackup
rows = append(rows, row)
}
// R-487: the list is keyed on the DRIVES, not on what is deployed — a removed app whose unit was
// kept is listed after the deployed ones, with the restore that brings it back.
if s.backupMgr != nil {
for _, u := range s.backupMgr.ListRemovedAppUnits() {
rows = append(rows, AppBackupRow{
StackName: u.StackName,
DisplayName: u.DisplayName,
Slug: u.StackName,
StorageLabel: u.DriveLabel,
Status: "yellow",
StatusText: "Eltávolított alkalmazás — a mentése megvan, visszaállítható",
Removed: true,
RemovedUnitTime: u.Time,
Tier1LastRun: u.Time,
})
}
}
return rows
}