A build made from the source every machine running it runs is marked sent and sent nothing, yet the tier's wait asked each machine for a report after that marking. None follows, and the walk waited for ever. Each machine is now judged by whether it answered its last send, the one whose builds made the build no move.
88 lines
3.5 KiB
Go
88 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// A tier whose module is no move — made from the source every machine running it runs, so nothing is
|
|
// sent — is not waited on for a report after its marking (novox/hq issue 648). Its machines answered the
|
|
// send that last carried that build before the walk got there, and nothing will make them report again:
|
|
// the walk asks the next tier in the same step, rather than "waiting for app on anchor, laptop" for ever.
|
|
func TestANoMoveTierWaitsForNoNewReport(t *testing.T) {
|
|
judgeLeavesAsTheCore(t)
|
|
g := aGateMesh(t)
|
|
ctx := t.Context()
|
|
inv := g.open.inventory
|
|
|
|
// app is the build machine, so a module of the next tier is built by it: the tier gates the next on app
|
|
// running on its machines.
|
|
for _, m := range []catalogue.Manifest{
|
|
{Module: "app", Version: "c2", Claims: []catalogue.Claim{{Name: "node-build-agent", Scope: catalogue.ScopeNode}}},
|
|
{Module: "web", Version: "w1"},
|
|
} {
|
|
if err := inv.RegisterModule(ctx, m, inventory.Source{Repository: "novox/mesh-catalog", Seat: "git",
|
|
Path: "modules/" + m.Module, BuiltFrom: m.Version, Head: m.Version, Asked: time.Now().Add(-time.Minute)}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
// What anchor and laptop were last sent (c1) was made from the source the plan's build of c2 is.
|
|
for _, b := range []inventory.Build{
|
|
{ID: "build-1s", Module: "app", Commit: "c1", SourceFingerprint: "src1:app",
|
|
Asked: time.Now().Add(-30 * time.Second), At: time.Now().Add(-30 * time.Second)},
|
|
{ID: "build-2s", Module: "app", Commit: "c2", SourceFingerprint: "src1:app", Asked: time.Now(), At: time.Now()},
|
|
} {
|
|
b.Manifest, _ = json.Marshal(catalogue.Manifest{Module: "app", Version: "1"})
|
|
if err := inv.RecordBuild(ctx, b); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
// Each machine answered that send, applied, before the walk's tier was built.
|
|
for _, n := range []string{"anchor", "laptop"} {
|
|
if _, err := inv.RecordDoing(ctx, nodeID(t, g.open, n), inventory.Doing{Node: n,
|
|
Outcome: inventory.OutcomeApplied, Declared: "d-" + n + "-c1", Applied: 1,
|
|
At: time.Now().Add(-10 * time.Second)}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
built := time.Now().UTC()
|
|
p := g.plan(t)
|
|
p.Tiers = [][]string{{"app"}, {"web"}}
|
|
p.Modules["app"].Build, p.Modules["app"].BuiltAt = "build-2s", &built
|
|
if err := inv.SavePlan(ctx, &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
advancePlans(ctx, g.open)
|
|
|
|
if len(g.sent) != 0 {
|
|
t.Fatalf("a no-move build was sent: %v", g.sent)
|
|
}
|
|
p = g.plan(t)
|
|
if s := p.Modules["app"]; s == nil || !strings.HasPrefix(s.Why, "no move") {
|
|
t.Fatalf("the build was not marked no move: %+v", s)
|
|
}
|
|
if p.Tier < 1 || strings.Contains(p.Note, "waiting for app") {
|
|
t.Fatalf("the walk waits on a no-move tier for a report nothing will cause: tier %d, %s %q", p.Tier, p.State, p.Note)
|
|
}
|
|
|
|
// A machine that has not answered its last send is still waited on: no move is not "never sent".
|
|
p.Tier, p.State, p.Note = 0, inventory.PlanRolling, ""
|
|
if err := inv.RecordSent(ctx, nodeID(t, g.open, "laptop"), "d-laptop-later", map[string]string{"app": "c1"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.SavePlan(ctx, &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
advancePlans(ctx, g.open)
|
|
p = g.plan(t)
|
|
if p.Tier != 0 || !strings.Contains(p.Note, "waiting for app on laptop") {
|
|
t.Fatalf("a machine that has not answered its last send was not waited on: tier %d, %q", p.Tier, p.Note)
|
|
}
|
|
}
|