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).
88 lines
3.4 KiB
Go
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)
|
|
}
|
|
}
|