The controller plans config, templates and moved providers' provisions, hands bus accounts to the vault and judges the new manifest words, on the feature's SDK and node-engine validator (feature 57, config and provisioning).
125 lines
5.6 KiB
Go
125 lines
5.6 KiB
Go
package inventory
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// A walk counts a provisioned module applied on a machine only once its files are placed (novox/hq ADR 0362, design
|
|
// 57 P6, issue 672). The walk of issue 582 (one module, three machines of the rest), with g14's send having handed
|
|
// dunst to the provisioner: g14's own report comes 5 s after its send, shanks's, the last of the others, 15 s
|
|
// after its own.
|
|
|
|
const dunstTemplates = "sha256:" + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
|
|
|
func walkHandingDunst(t *testing.T) sendRest582 {
|
|
t.Helper()
|
|
c := walk582(t)
|
|
s := c.walk.Modules["build-agent"].Rest["g14"]
|
|
s.Provisioned = map[string]string{"build-agent": dunstTemplates}
|
|
c.walk.Modules["build-agent"].Rest["g14"] = s
|
|
return c
|
|
}
|
|
|
|
// provisioning is a walk's lookup with the machines' clients saying reports.
|
|
func (w sendRest582) provisioning(reports map[string]ProvReport) AppliedLookup {
|
|
return func(node string, send SentDeclaration, walkSent time.Time) (AppliedReport, bool) {
|
|
r, ok := w.lookup(node, send, walkSent)
|
|
return ProvisionedSend(node, send, r, ok, func(node, module string) (ProvReport, bool) {
|
|
p, said := reports[node+"."+module]
|
|
return p, said
|
|
})
|
|
}
|
|
}
|
|
|
|
func restOf(w *WalkPhases, node string) RestReport {
|
|
for _, r := range w.Rest {
|
|
if r.Node == node {
|
|
return r
|
|
}
|
|
}
|
|
return RestReport{}
|
|
}
|
|
|
|
// The node-engine's report alone does not end the walk: it waits for prov.applied; with it, the walk ends, and
|
|
// its delivery time runs to the later of the two reports.
|
|
func TestAWalkWaitsForTheProvisionersReportAndEndsAtTheLater(t *testing.T) {
|
|
c := walkHandingDunst(t)
|
|
g14Sent := c.walk.Modules["build-agent"].Rest["g14"].At
|
|
|
|
w := c.walk.WalkPhases(g14Sent.Add(time.Minute), c.provisioning(nil))
|
|
if w.End != nil || restOf(w, "g14").State != RestWaiting ||
|
|
!strings.Contains(phase(w, PhaseApply, -1).Said, "waiting for g14") {
|
|
t.Fatalf("the walk did not wait for g14's prov.applied: end %v, g14 %+v, apply %+v", w.End, restOf(w, "g14"),
|
|
phase(w, PhaseApply, -1))
|
|
}
|
|
|
|
// A report on an older build of the templates is not this send's.
|
|
older := map[string]ProvReport{"g14.build-agent": {Status: ProvApplied, Templates: "sha256:" + strings.Repeat("0", 64),
|
|
At: g14Sent.Add(2 * time.Second)}}
|
|
if w := c.walk.WalkPhases(g14Sent.Add(time.Minute), c.provisioning(older)); w.End != nil {
|
|
t.Fatalf("a report on an older build ended the walk at %v", w.End)
|
|
}
|
|
|
|
placed := g14Sent.Add(50 * time.Second) // after shanks's report, 35 s after the judgement
|
|
w = c.walk.WalkPhases(g14Sent.Add(time.Hour), c.provisioning(map[string]ProvReport{
|
|
"g14.build-agent": {Status: ProvApplied, Templates: dunstTemplates, At: placed}}))
|
|
sumsUp(t, w)
|
|
if w.End == nil || !w.End.Equal(placed) {
|
|
t.Fatalf("the walk ends at %v, want the provisioner's report at %s: %+v", w.End, placed, w.Rest)
|
|
}
|
|
if g := restOf(w, "g14"); g.State != RestApplied || !g.Reported.Equal(placed) {
|
|
t.Fatalf("g14 is not applied at its later report: %+v", g)
|
|
}
|
|
}
|
|
|
|
// A failed prov.applied is the machine's failed apply, named in the walk's end with its reason.
|
|
func TestAFailedProvisioningIsAFailedApply(t *testing.T) {
|
|
c := walkHandingDunst(t)
|
|
g14Sent := c.walk.Modules["build-agent"].Rest["g14"].At
|
|
w := c.walk.WalkPhases(g14Sent.Add(time.Hour), c.provisioning(map[string]ProvReport{
|
|
"g14.build-agent": {Status: ProvFailed, Reason: "the templates cannot be fetched", At: g14Sent.Add(3 * time.Second)}}))
|
|
if w.End != nil {
|
|
t.Fatalf("a failed provisioning ended the walk: %v", w.End)
|
|
}
|
|
if g := restOf(w, "g14"); g.State != RestFailed || !strings.Contains(g.Outcome, "the templates cannot be fetched") {
|
|
t.Fatalf("g14 is not named failed with the reason: %+v", g)
|
|
}
|
|
if said := phase(w, PhaseApply, -1).Said; !strings.Contains(said, "not applied on g14 (provisioning failed (build-agent: "+
|
|
"the templates cannot be fetched))") {
|
|
t.Fatalf("the walk's end does not name g14's failure: %q", said)
|
|
}
|
|
// A failure said before the send, of no build, is not this send's.
|
|
stale := map[string]ProvReport{"g14.build-agent": {Status: ProvFailed, Reason: "old", At: g14Sent.Add(-time.Hour)}}
|
|
if g := restOf(c.walk.WalkPhases(g14Sent.Add(time.Minute), c.provisioning(stale)), "g14"); g.State != RestWaiting {
|
|
t.Fatalf("a failure from before the send was read as this send's: %+v", g)
|
|
}
|
|
}
|
|
|
|
// None within ApplySilentAfter names the machine silent, never counted applied; the others end the walk.
|
|
func TestNoProvisioningReportWithinTheBoundIsSilence(t *testing.T) {
|
|
c := walkHandingDunst(t)
|
|
g14Sent := c.walk.Modules["build-agent"].Rest["g14"].At
|
|
waiting := map[string]ProvReport{"g14.build-agent": {Status: ProvWaiting, WaitsFor: []string{"config:font-size"},
|
|
At: g14Sent.Add(3 * time.Second)}}
|
|
w := c.walk.WalkPhases(g14Sent.Add(ApplySilentAfter+time.Minute), c.provisioning(waiting))
|
|
sumsUp(t, w)
|
|
if g := restOf(w, "g14"); g.State != RestSilent {
|
|
t.Fatalf("g14 is not silent past ApplySilentAfter: %+v", g)
|
|
}
|
|
if len(w.Silent) != 1 || w.Silent[0] != "g14" || w.End == nil || !w.End.Equal(c.judged.Add(35*time.Second)) {
|
|
t.Fatalf("the walk does not end on the others, naming g14 silent: end %v, silent %v", w.End, w.Silent)
|
|
}
|
|
}
|
|
|
|
// A send that handed nothing ends on the node-engine's report alone, as before.
|
|
func TestASendThatHandedNothingEndsOnTheEnginesReport(t *testing.T) {
|
|
c := walk582(t)
|
|
before := c.walk.WalkPhases(c.judged.Add(time.Hour), c.lookup)
|
|
now := c.walk.WalkPhases(c.judged.Add(time.Hour), c.provisioning(nil))
|
|
if before.End == nil || now.End == nil || !now.End.Equal(*before.End) {
|
|
t.Fatalf("a walk handing nothing ends differently: before %v, now %v", before.End, now.End)
|
|
}
|
|
}
|