Files
mesh-controller/cmd/mesh-controller/recorded_kept_test.go
T

93 lines
3.8 KiB
Go

package main
import (
"encoding/json"
"strings"
"testing"
"time"
"github.com/novox/mesh-controller/internal/catalogue"
"github.com/novox/mesh-controller/internal/link"
)
// A recorded build reaches a machine only by a person's push (novox/hq issue 295, ADR 0245).
// aContainerBuild is a build outcome of a module of containers, each named by id with the image and the
// health it is given; a policy when one is said.
func aContainerBuild(t *testing.T, module, commit, policy string, asked time.Time, containers map[string][2]string) link.BuildResult {
t.Helper()
var resources []any
for id, c := range containers {
r := map[string]any{"id": id, "type": "container", "name": module + "-" + id, "image": c[0]}
if c[1] != "" {
r["health"] = map[string]any{"kind": c[1]}
}
resources = append(resources, r)
}
m := map[string]any{"module": module, "version": "1", "resources": resources}
if policy != "" {
m["upgrade"] = map[string]any{"policy": policy, "why": "a provider whose restart drops every consumer"}
}
manifest, _ := json.Marshal(m)
return link.BuildResult{ID: link.NewBuildID(asked), Repository: "novox/mesh-catalog", Path: "modules/" + module,
On: "anchor", Module: module, Commit: commit, Manifest: manifest,
Source: &link.SourceOnSeat{Seat: "git", Repository: "novox/mesh-catalog"}}
}
// imageOf is the image the composed plan of a machine gives one of a module's containers.
func imageOf(t *testing.T, plan catalogue.Resolution, module, id string) string {
t.Helper()
for _, m := range plan.Modules {
if m.Module != module {
continue
}
for _, r := range m.Resources {
if r["id"] == id {
image, _ := r["image"].(string)
return image
}
}
}
t.Fatalf("%s has no container %s in the plan", module, id)
return ""
}
// Tonight's case, 2026-10-07: a catalogue merge adopting the images' own health checks rebuilt the
// database (policy record) with mail (policy roll). The plan's gated send for mail carried the
// database's new build to the control node and recreated it, unjudged, with nobody's word. A send that
// is not a person's push now composes the database at the build the machine runs and records that it
// still carries it; a person's push composes the new one; the bus step moves the bus alone.
// The send says what it recreates (ADR 0245): mail's health checks adopted recreate both its
// containers, with no new image, every one at once.
func TestASendSaysWhatItRecreates(t *testing.T) {
image := "registry.invalid:5000/mailu/smtp@sha256:" + strings.Repeat("c", 64)
from := catalogue.Manifest{Module: "mailu", Resources: []map[string]any{
{"id": "smtp", "type": "container", "image": image},
{"id": "imap", "type": "container", "image": image},
{"id": "redis", "type": "container", "image": image},
{"id": "config", "type": "file", "path": "/etc/x"}}}
to := catalogue.Manifest{Module: "mailu", Resources: []map[string]any{
{"id": "smtp", "type": "container", "image": image, "health": map[string]any{"kind": "runtime"}},
{"id": "imap", "type": "container", "image": image, "health": map[string]any{"kind": "runtime"}},
{"id": "redis", "type": "container", "image": image},
{"id": "config", "type": "file", "path": "/etc/y"}}}
r := catalogue.Recreates(from, to)
if !r.SpecOnly() || len(r.Recreated) != 2 || r.Containers != 3 {
t.Fatalf("recreation %+v", r)
}
said := r.Say("mailu")
for _, want := range []string{"recreates 2 of mailu's 3", "no new image", "imap, smtp", "interrupted"} {
if !strings.Contains(said, want) {
t.Fatalf("%q does not say %q", said, want)
}
}
if catalogue.Recreates(from, from).Say("mailu") != "" {
t.Fatal("a move that recreates nothing said something")
}
to.Resources[2]["image"] = strings.Replace(image, "c", "d", 1)
if r := catalogue.Recreates(from, to); r.SpecOnly() || len(r.Images) != 1 {
t.Fatalf("a new image read as a declaration only: %+v", r)
}
}