A changed maintenance window is a changed spec (hq ADR 0189)
containerSpec says a changed cadence moves the marker so the install is reported updated and re-established. Which containers are held still is the same kind of statement, and a declaration that changed it while the machine reported no change would be a machine quietly holding yesterday's containers.
This commit is contained in:
@@ -1707,6 +1707,13 @@ func containerSpecReading(r *declaration.Container, declares, reads map[string]s
|
||||
// The cadence is part of what was declared, so a changed schedule is a changed spec — the marker
|
||||
// moves and the install is reported "updated" and re-established. Added only when present, so no
|
||||
// ordinary container's or run-once step's digest moves for a field it does not set.
|
||||
// And which of its module's containers it holds still while it runs (novox/hq ADR 0189), for
|
||||
// the same reason: a declaration that changed the window while the machine reported no change
|
||||
// would be a machine quietly holding yesterday's containers. In declared order, which is the
|
||||
// order they are stopped in.
|
||||
for _, id := range r.WhileStopped {
|
||||
b.WriteString("while-stopped " + id + "\n")
|
||||
}
|
||||
if r.Schedule != "" {
|
||||
b.WriteString("schedule " + r.Schedule + "\n")
|
||||
}
|
||||
|
||||
@@ -194,3 +194,45 @@ func TestAMaintenanceWindowIsRefusedWhereItCannotMean(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A changed window is a changed declaration, and the install says so.
|
||||
//
|
||||
// The cadence already works this way: "a changed schedule is a changed spec — the marker moves and
|
||||
// the install is reported updated and re-established" (containerSpec). Which containers are held
|
||||
// still for the run is the same kind of statement, and a declaration that changed it while the
|
||||
// machine reported no change would be a machine quietly running the old window.
|
||||
func TestAChangedWindowMovesTheSpec(t *testing.T) {
|
||||
one := parseTrusted(t, `{"declaration":1,"resources":[
|
||||
{"id":"store","type":"container","name":"mesh-registry","image":"`+pinned+`"},
|
||||
{"id":"other","type":"container","name":"other","image":"`+pinned+`"},
|
||||
{"id":"collect","type":"container","name":"collect","image":"`+pinned+`",
|
||||
"schedule":"30 3 * * *","while-stopped":["store"]}
|
||||
]}`)
|
||||
two := parseTrusted(t, `{"declaration":1,"resources":[
|
||||
{"id":"store","type":"container","name":"mesh-registry","image":"`+pinned+`"},
|
||||
{"id":"other","type":"container","name":"other","image":"`+pinned+`"},
|
||||
{"id":"collect","type":"container","name":"collect","image":"`+pinned+`",
|
||||
"schedule":"30 3 * * *","while-stopped":["store","other"]}
|
||||
]}`)
|
||||
stepOf := func(d *declaration.Declaration) *declaration.Container {
|
||||
for _, r := range d.Resources {
|
||||
if c, ok := r.(*declaration.Container); ok && c.ID == "collect" {
|
||||
return c
|
||||
}
|
||||
}
|
||||
t.Fatal("no step in the fixture")
|
||||
return nil
|
||||
}
|
||||
if containerSpec(stepOf(one), inputs{}) == containerSpec(stepOf(two), inputs{}) {
|
||||
t.Fatal("the window changed and the spec did not; the machine would report no change " +
|
||||
"and keep holding the containers it held yesterday")
|
||||
}
|
||||
// And a container with no window is untouched by the field existing at all.
|
||||
plain := parseTrusted(t, `{"declaration":1,"resources":[
|
||||
{"id":"store","type":"container","name":"mesh-registry","image":"`+pinned+`"}
|
||||
]}`)
|
||||
spec := containerSpec(plain.Resources[0].(*declaration.Container), inputs{})
|
||||
if strings.Contains(spec, "while-stopped") || strings.Contains(spec, "held") {
|
||||
t.Errorf("an ordinary container's spec mentions a field it does not set:\n%s", spec)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user