D49 = A follow-ups: (A) the undo copy is released only after a stable start — 3 min of running, healthy, no restart, one rule for the first verdict and the late-start watch; a watch ends only for a restore begun after it; (B, R-1279) the .fab import downloads first with the restores' D48 helper, before it removes anything. Red-proved. Commit only.
gates / gates (push) Successful in 1m26s
gates / gates (push) Successful in 1m26s
This commit is contained in:
1 parent
e8d2151a77
commit
7720439440
16 files changed
+549
-27
No files matched your search
@@ -2093,6 +2093,10 @@ func main() {
|
||||
// this the export path would be the uncovered sibling of two covered ones, which is how a reader
|
||||
// concludes the whole class is handled (§2.2).
|
||||
appExporter.SetStopGuard(exportStopGuard{g: appStopGuard})
|
||||
// R-1279 (D48 for the import): the import downloads first, with the restores' helper and sentences.
|
||||
if backupMgr != nil {
|
||||
appExporter.SetImagePreparer(backupMgr.PrepareRestoreImages)
|
||||
}
|
||||
apiRouter.SetDebug(cfg.Logging.Level == "debug")
|
||||
|
||||
// --- Initialize web server ---
|
||||
@@ -3439,6 +3443,38 @@ func (a *stackAdapter) StartStackServices(name string, services []string) error
|
||||
return a.mgr.StartStackServices(name, services)
|
||||
}
|
||||
|
||||
// ContainerSamples (R-1270 follow-up, fix A) reads each container of the stack: running, its RestartCount, its health
|
||||
// ("" without a healthcheck) — the stable-start rule's sample (backup.containerSampler). Read-only docker calls.
|
||||
func (a *stackAdapter) ContainerSamples(name string) ([]backup.ContainerSample, error) {
|
||||
out, err := dockerexec.Command("docker", "ps", "-a", "-q", "--no-trunc", "--filter", "label=com.docker.compose.project="+name).Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ids := strings.Fields(string(out))
|
||||
if len(ids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
args := append([]string{"inspect", "-f", "{{.Id}} {{.State.Status}} {{.RestartCount}} {{if .State.Health}}{{.State.Health.Status}}{{end}}"}, ids...)
|
||||
out, err = dockerexec.Command("docker", args...).Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []backup.ContainerSample
|
||||
for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 3 {
|
||||
continue
|
||||
}
|
||||
n, _ := strconv.Atoi(f[2])
|
||||
c := backup.ContainerSample{ID: f[0], Running: f[1] == "running", RestartCount: n}
|
||||
if len(f) > 3 {
|
||||
c.Health = f[3]
|
||||
}
|
||||
res = append(res, c)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// RefreshAndIsRunning forces a docker ps scan before checking state.
|
||||
// Called during post-restore health check (~every 5s for up to 90s).
|
||||
// Full refresh is acceptable here since restores are rare operations.
|
||||
|
||||
Reference in new issue
Block a user