Files
mesh-catalog/modules/mesh-build-image/cmd/mesh-build-image/asks_test.go
T
jschoubben d13f74df40 A node that cannot open /dev/net/tun takes no image build, and every node loads tun at boot and keeps its running kernel's modules
An image build node up 24 days had lost its running kernel's modules to a linux-lts upgrade, so tun
could not load and every RUN line failed in pasta. mesh-build-image now proves the tun device and,
whatever its look refuses, judges its node not eligible (capacity 0 with the reason), so the asks go
to a node that can build them. The kernel module loads tun at boot and declares kernel-modules-hook,
which keeps the running kernel's modules across an upgrade. Needs mesh-sdk fix/ace-tun (Puller.Eligible).
2026-10-28 12:44:58 +01:00

88 lines
3.4 KiB
Go

package main
import (
"context"
"strings"
"testing"
"time"
"git.novox.be/novox/mesh-sdk/go/buildstep"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
const askCommit = "0123456789abcdef0123456789abcdef01234567"
// 1887/A3image: a pulled image ask copies a pinned image with no fetch, then fetches and builds the module's own, and its
// key <node>.<ask id> names each reference; the seat's verbs are served.
func TestAPulledImageAskCopiesThenBuilds(t *testing.T) {
states := newStates()
m := moduleWith(t, newFake(t), states)
m.Capacity = func() int { return 1 }
var calls []string
answer := func(name string, out any) StepTool {
return StepTool{Name: name, Run: func(ctx context.Context, args map[string]any) (any, error) {
calls = append(calls, name)
return out, nil
}}
}
steps := []StepTool{
answer("build_image_fetch", map[string]any{"workspace": "ws1"}),
answer("build_image_build", map[string]any{"digest": "sha256:cc", "reference": "registry/m/server@sha256:cc"}),
answer("build_image_copy", map[string]any{"digest": "sha256:dd", "reference": "registry/m/base@sha256:dd"}),
}
src := buildstep.NewFakeAsks()
a := delivery.StepAsk{ID: buildstep.NewID(), Kind: delivery.AskDelivery, Language: delivery.AskImage, Asker: "mesh-delivery-builder",
At: time.Now(), Build: &delivery.BuildJob{Module: "m", Path: "modules/m", Publish: true,
Fetch: map[string]any{"repository": "novox/mesh-catalog", "commit": askCommit},
Artifacts: []delivery.AskArtifact{{Artifact: "base", From: "docker.io/library/alpine@sha256:00"}, {Artifact: "server"}}}}
_ = src.PublishAsk(a)
p := m.Puller(steps, src)
p.PullWait = 10 * time.Millisecond
ctx, stop := context.WithCancel(context.Background())
defer stop()
go p.Pull(ctx)
key, _ := delivery.AskStepKey("ace", a.ID)
var step delivery.Step
for deadline := time.Now().Add(3 * time.Second); ; time.Sleep(5 * time.Millisecond) {
states.mu.Lock()
v := states.steps[key]
states.mu.Unlock()
if len(v) > 0 && v[len(v)-1].State != delivery.StepRunning {
step = v[len(v)-1]
break
}
if time.Now().After(deadline) {
t.Fatalf("the ask's step never ended: calls %v", calls)
}
}
if step.State != delivery.StepPassed || !strings.Contains(string(step.Result), "registry/m/server@sha256:cc") ||
!strings.Contains(string(step.Result), "registry/m/base@sha256:dd") {
t.Fatalf("the step = %+v", step)
}
if got := strings.Join(calls, ","); got != "build_image_copy,build_image_fetch,build_image_build" {
t.Errorf("calls = %s", got)
}
served := map[string]bool{}
for _, tool := range m.SeatTools(p) {
served[tool.Name] = true
}
for _, verb := range []string{"current", "pause", "resume"} {
if !served[Seat+"."+verb] {
t.Errorf("%s.%s is not served", Seat, verb)
}
}
// A node without /dev/net/tun (a build node, 2026-10-28) takes no ask: its capacity is 0 and says why, so the ask goes to a node
// that can build it instead of failing in buildah's network setup; once it is there again, the capacity is back.
tun := m.Tun
m.Tun = t.TempDir() + "/none"
_ = m.Check(context.Background())
if c := p.CapacityDetail(); c.Effective != 0 || !strings.Contains(c.Why, "not eligible: "+m.Tun+" cannot be opened") {
t.Errorf("without /dev/net/tun the capacity = %+v", c)
}
m.Tun = tun
_ = m.Check(context.Background())
if c := p.CapacityDetail(); c.Effective != 1 || c.Ineligible != "" {
t.Errorf("with /dev/net/tun again the capacity = %+v", c)
}
}