package catalogue import ( "encoding/json" "strings" "testing" ) // A scheduled step may hold its module's own containers still while it runs (novox/hq ADR 0189). // // The host judges what it receives — whether each id is a container on that machine. What the // definition is the only place to see is judged here, near whoever wrote it. func aStoreManifest(step map[string]any) []byte { m := map[string]any{ "module": "distribution", "version": "1", "resources": []any{ map[string]any{"id": "store", "type": "container", "name": "mesh-registry", "image": "registry@sha256:" + strings.Repeat("a", 64)}, step, }, } raw, _ := json.Marshal(m) return raw } func TestAMaintenanceWindowOnItsOwnModulesContainerIsAccepted(t *testing.T) { raw := aStoreManifest(map[string]any{ "id": "collect", "type": "container", "name": "mesh-registry-collect", "image": "registry@sha256:" + strings.Repeat("a", 64), "schedule": "30 3 * * *", "while-stopped": []any{"store"}, }) if _, err := ParseManifest(raw); err != nil { t.Fatalf("a step holding its own module's container still was refused: %v", err) } } func TestAMaintenanceWindowIsRefusedWhereTheDefinitionShowsItCannotMean(t *testing.T) { for _, c := range []struct { name string step map[string]any says string }{ { "on a step with no schedule", map[string]any{"id": "collect", "type": "container", "name": "c", "image": "registry@sha256:" + strings.Repeat("a", 64), "while-stopped": []any{"store"}}, "gates what is declared after it", }, { "on a run-once step, which already has order", map[string]any{"id": "collect", "type": "container", "name": "c", "image": "registry@sha256:" + strings.Repeat("a", 64), "run-once": true, "while-stopped": []any{"store"}}, "A maintenance window is for a recurring step", }, { "naming a container this module does not declare", map[string]any{"id": "collect", "type": "container", "name": "c", "image": "registry@sha256:" + strings.Repeat("a", 64), "schedule": "30 3 * * *", "while-stopped": []any{"the-broker"}}, "could quiesce a neighbour could stop the mesh", }, { "naming itself", map[string]any{"id": "collect", "type": "container", "name": "c", "image": "registry@sha256:" + strings.Repeat("a", 64), "schedule": "30 3 * * *", "while-stopped": []any{"collect"}}, "naming itself", }, { "written as something that is not a list", map[string]any{"id": "collect", "type": "container", "name": "c", "image": "registry@sha256:" + strings.Repeat("a", 64), "schedule": "30 3 * * *", "while-stopped": "store"}, "a list of this module's container ids", }, } { _, err := ParseManifest(aStoreManifest(c.step)) if err == nil { t.Errorf("%s was accepted", c.name) continue } if !strings.Contains(err.Error(), c.says) { t.Errorf("%s: the refusal does not say %q:\n%v", c.name, c.says, err) } } }