A former target of a kind the host cannot remove is left in place and said, never fatal (hq issue 194)
The host delivers its own successor as an archive whose target is a new directory each version, and since mesh-host 63 the record keeps a resource's former target for the next apply to remove. An archive has no removal (issue 162), so the first host that replaced itself under that rule refused its own former version at the first step of every apply, and all four machines applied nothing from then on. A former target nobody dropped is forgotten and said; an archive the declaration dropped still refuses.
This commit is contained in:
+22
-1
@@ -199,6 +199,22 @@ func ApplyKeeping(
|
||||
} else {
|
||||
action, detail, err = remove(ctx, sys, orphan, run, made)
|
||||
}
|
||||
if errors.Is(err, errNoRemoval) && store.IsFormer(orphan.ID) {
|
||||
// **A former target of a kind the host cannot remove is left in place and forgotten,
|
||||
// never fatal.** The host's own archive is the case: every version it delivers itself
|
||||
// has a new target, so the one before is a former target on the first apply of the new
|
||||
// host — and a removal that refused there stopped every machine applying anything, the
|
||||
// moment the host that carried former targets (novox/hq ADR 0163, rule 5) first
|
||||
// replaced itself. What was written stays where it is, said, and the record no longer
|
||||
// names it; whether an archive gets a removal is issue 162's question, not this apply's.
|
||||
known.Forget(orphan.ID)
|
||||
report.Outcomes = append(report.Outcomes, Outcome{
|
||||
ID: orphan.ID, Type: orphan.Type, Target: orphan.Target,
|
||||
Action: "forgotten", Detail: "a former target left in place: " + err.Error() + " (novox/hq issue 162)",
|
||||
})
|
||||
log(fmt.Sprintf(" forgotten %s (%s): a former target left in place: %v", orphan.ID, orphan.Target, err))
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return &Error{Resource: orphan.ID, Err: err, Done: report}
|
||||
}
|
||||
@@ -1340,10 +1356,15 @@ func remove(ctx context.Context, sys system.System, a store.Applied, run Runner,
|
||||
return "removed", "no longer declared", nil
|
||||
|
||||
default:
|
||||
return "", "", fmt.Errorf("no way to remove a %q", a.Type)
|
||||
return "", "", fmt.Errorf("%w: a %q", errNoRemoval, a.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// errNoRemoval is remove's answer for a kind the host has no removal for (novox/hq issue 162): an
|
||||
// archive, among others. Fatal for an orphan the declaration dropped, so an unassignment nothing can
|
||||
// undo is never reported as done; not fatal for a former target, which was never dropped by anyone.
|
||||
var errNoRemoval = errors.New("no way to remove")
|
||||
|
||||
// ExecRunner runs a real command, with stdin closed and output captured.
|
||||
func ExecRunner(ctx context.Context, name string, args ...string) (string, error) {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
|
||||
Reference in New Issue
Block a user