D48: a restore downloads first — every restore path resolves and pulls every image of the definition that will run before the stop, under the image-work lock held until the restore returns; a failed pull refuses with the app untouched (a deleted version and a busy registry read differently), one operator line. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s

This commit is contained in:
2026-10-25 09:38:28 +01:00
parent b680db85cb
commit 2d71270858
16 changed files with 404 additions and 3 deletions
+9
View File
@@ -79,6 +79,15 @@ func (m *Manager) RestoreApp(stackName, snapshotID string) error {
}
}
// D48: the live definition's images are on the box before the stop, or the restore is refused untouched.
if composePath, ok := m.stackProvider.GetStackComposePath(stackName); ok && composePath != "" {
releaseImages, pErr := m.prepareRestoreImages(stackName, composePath)
if pErr != nil {
return pErr
}
defer releaseImages()
}
// Stop the app before restore
if m.isDebug() {
m.logger.Printf("[DEBUG] RestoreApp: step 1/4 — stopping app %s", stackName)