Fail a resource when the container runtime cannot answer, instead of reading silence as nothing there (hq ADR 0100)

This commit is contained in:
2026-09-22 19:46:56 +02:00
parent 0ea646b384
commit da008460ac
2 changed files with 137 additions and 16 deletions
+79
View File
@@ -825,3 +825,82 @@ func TestMountingTheMachinesOwnPlumbingIsNotFoundData(t *testing.T) {
t.Errorf("held: %+v", state.Held)
}
}
// Defends novox/hq ADR 0100: a runtime that cannot answer is not a machine with nothing there.
// unreachable is a machine whose container runtime answers everything with a daemon that is down.
type unreachable struct{ asked []string }
func (u *unreachable) run(_ context.Context, name string, args ...string) (string, error) {
u.asked = append(u.asked, name+" "+strings.Join(args, " "))
if name == "docker" && args[0] == "info" {
return "27.0\n", nil
}
if name == "docker" {
return "", errors.New("docker exited 1: Cannot connect to the Docker daemon at unix:///var/run/docker.sock")
}
return "", nil
}
func TestARuntimeThatCannotAnswerNeverLetsTheMeshCreateOverAFoundContainer(t *testing.T) {
dir := t.TempDir()
u := &unreachable{}
d := adopted(t, untaken("hello-web.server"),
`{"id":"hello-web.server","type":"container","name":"hello-web","image":"`+pinned+`"}`)
_, state, err := ApplyKeeping(context.Background(), archHost(t), d, store.State{}, store.OriginDeclared,
u.run, nil, nil, KeepIn(dir))
if err == nil || !strings.Contains(err.Error(), "not safe to make one") {
t.Fatalf("a runtime that could not answer was read as nothing there: %v", err)
}
for _, a := range u.asked {
if strings.HasPrefix(a, "docker run") || strings.HasPrefix(a, "docker rm") {
t.Errorf("the mesh acted on a container it could not ask about: %s", a)
}
}
if len(state.Held) != 0 {
t.Errorf("something was held on an answer the machine never gave: %+v", state.Held)
}
}
func TestAHeldContainerStaysHeldWhenTheRuntimeCannotAnswer(t *testing.T) {
dir, page, m := predecessor(t)
d := adopted(t, untaken("hello-web.page", "hello-web.server"), webResources(page))
_, state := applyAdopted(t, d, store.State{}, m, dir)
if _, held := state.HeldAt("hello-web.server"); !held {
t.Fatal("the found container was not held to begin with")
}
u := &unreachable{}
_, state, err := ApplyKeeping(context.Background(), archHost(t), d, state, store.OriginDeclared,
u.run, nil, nil, KeepIn(dir))
if err == nil {
t.Fatal("a runtime that could not answer reported success")
}
if h, held := state.HeldAt("hello-web.server"); !held || h.Changed != "" {
t.Errorf("a hold was let go or called changed on an answer the machine never gave: %+v", h)
}
}
func TestAVolumeTheRuntimeCannotBeAskedAboutStopsTheContainer(t *testing.T) {
dir := t.TempDir()
run := func(_ context.Context, name string, args ...string) (string, error) {
switch {
case name == "docker" && args[0] == "info":
return "27.0\n", nil
case name == "docker" && args[0] == "volume":
return "", errors.New("docker exited 1: Cannot connect to the Docker daemon")
case name == "docker" && args[0] == "inspect":
return "", errors.New("Error: No such object: hello-web")
case name == "docker":
return "", errors.New("docker run must not happen")
}
return "", nil
}
d := adopted(t, untaken("hello-web.server"),
`{"id":"hello-web.server","type":"container","name":"hello-web","image":"`+pinned+`",
"volumes":["predecessor-data:/data"]}`)
_, _, err := ApplyKeeping(context.Background(), archHost(t), d, store.State{}, store.OriginDeclared,
run, nil, nil, KeepIn(dir))
if err == nil || !strings.Contains(err.Error(), "could not say whether the volume") {
t.Fatalf("a volume the runtime could not be asked about did not stop the container: %v", err)
}
}