Files

51 lines
2.9 KiB
Go

package stacks
import "log"
// carryLifeRecords copies, from the app.yaml a restore is about to replace (prior, as on disk), the records
// that describe the app's LIFE on this box rather than its definition (R-697, v0.276.0). The restore's
// write is a fresh AppConfig by design — the env, the locked fields and the pin come from the unit — and it
// used to drop these with it:
//
// - conversion_copy + earlier_conversion_copies: a kept pre-conversion datadir copy whose record is dropped
// is never released (R-697, measured on 9202). A restore does not remove the volume, so it must not
// forget it either.
// - desired_state: the household's intent. Dropped, a dead app after a restore was read as "unknown
// intent" and never alarmed (R-166's absent case).
// - failed_update_step, last_update_undone, last_auto_update: the ladder's history on THIS box; the
// automatic leg must not re-press a step that already failed here because a restore happened.
//
// NOT carried: pinned_images (the restore pins to the unit's definition right after — carrying the old pin
// would freeze a failed SetPin onto the wrong version), installed_images (an observation of what ran
// before the restore, possibly another version), restored_logins (computed per restore).
// Pinned by TestR697_ARestoreKeepsTheConversionCopyRecordSoTheCopyIsReleased.
func carryLifeRecords(logger *log.Logger, name string, prior, cfg *AppConfig) {
if prior == nil {
return
}
cfg.ConversionCopy = prior.ConversionCopy
cfg.EarlierConversionCopies = prior.EarlierConversionCopies
if cfg.DesiredState == "" {
cfg.DesiredState = prior.DesiredState
}
cfg.FailedStep = prior.FailedStep
cfg.LastUpdateUndone = prior.LastUpdateUndone
cfg.LastAutoUpdate = prior.LastAutoUpdate
cfg.AfterInstall = prior.AfterInstall // v0.279.0: what the install's one-time command did stays true after a restore
// v0.280.0 (decision 46): the setup gate is the app's life here too. A restore never re-gates an app whose gate
// opened; a gate that was still closed stays closed (its probe opens it if the restored data is set up).
// No prior record (a removed app, kept data, a rebuilt guest) = no gate: the data comes back with its admin.
cfg.SetupGate = prior.SetupGate
cfg.FamilyGate = prior.FamilyGate // v0.287.0: a restore never un-gates a family app
cfg.InstallHold = prior.InstallHold // R-741: the loop opens it when the restored record says the login was replaced
cfg.DefaultLogin = prior.DefaultLogin
cfg.AfterSetup = prior.AfterSetup
if n := len(prior.EarlierConversionCopies); prior.ConversionCopy != nil || n > 0 {
cur := ""
if prior.ConversionCopy != nil {
cur = prior.ConversionCopy.Copy
}
logger.Printf("[INFO] [stacks] %s: the restore keeps the record of the kept pre-conversion copy %q (+%d earlier) — it is released when a backup written by the converted engine is proven", name, cur, n)
}
}