Read the outcome of a provider that makes no credential per consumer from its own have, so its consumers' keys turn provided once it runs healthy at its wanted build (issue 1954)
Failed is failed with the have's words; anything else stays asked, saying what it waits for. Providers that make a credential per consumer keep their bound entries.
This commit is contained in:
@@ -306,7 +306,7 @@ type entry struct {
|
||||
func (h *Holder) outcome(key string, p *provisions.Provision) {
|
||||
p.Ask, p.Warrant = "", nil
|
||||
if !keepsEntries(p.Provider.Module) {
|
||||
p.State, p.Why = provisions.Asked, p.Provider.Module+" writes no outcome yet: provided once it says it in its own entry"
|
||||
h.haveOutcome(p)
|
||||
return
|
||||
}
|
||||
e, err := h.Store.Get(boundRead(p.Provider.Module), key)
|
||||
@@ -343,6 +343,43 @@ func (h *Holder) outcome(key string, p *provisions.Provision) {
|
||||
}
|
||||
}
|
||||
|
||||
// haveOutcome is the outcome of a provider that makes no credential per consumer: its own have on its node (the lead's
|
||||
// reading of ADR 0570 clause 3, recorded as an insight). Running with health ok at the build its want names is
|
||||
// provided; failed is failed with the have's words; anything else is asked, waiting for the provider to run.
|
||||
func (h *Holder) haveOutcome(p *provisions.Provision) {
|
||||
where := p.Provider.Module + " on " + p.Provider.Node
|
||||
key := p.Provider.Node + "." + p.Provider.Module
|
||||
e, err := h.Store.Get(HaveRead, key)
|
||||
if err != nil {
|
||||
p.State, p.Why = provisions.Asked, "the have of "+where+" cannot be read: "+err.Error()
|
||||
return
|
||||
}
|
||||
if e == nil {
|
||||
p.State, p.Why = provisions.Asked, "waits for "+where+" to run: it says nothing yet"
|
||||
return
|
||||
}
|
||||
have, err := delivery.DecodeHave(e.Value)
|
||||
if err != nil {
|
||||
p.State, p.Why = provisions.Asked, "the have of "+where+" is not readable"
|
||||
return
|
||||
}
|
||||
wantFP := ""
|
||||
if we, err := h.Store.Get(WantsRead, "want."+key); err == nil && we != nil {
|
||||
if w, err := delivery.DecodeWant(we.Value); err == nil && !w.Removed {
|
||||
wantFP = w.FP
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case have.Phase == delivery.PhaseFailed || have.Health == delivery.HealthFailed:
|
||||
p.State, p.Why = provisions.Failed, orSaid(have.Detail, where+" failed")
|
||||
case have.Phase == delivery.PhaseRunning && have.Health == delivery.HealthOK && (wantFP == "" || have.FP == wantFP):
|
||||
p.State, p.Why = provisions.Provided, ""
|
||||
default:
|
||||
p.State, p.Why = provisions.Asked, fmt.Sprintf("waits for %s to run healthy at the build its want names (it is %s, "+
|
||||
"health %s)", where, have.Phase, have.Health)
|
||||
}
|
||||
}
|
||||
|
||||
func keepsEntries(module string) bool {
|
||||
for _, m := range Providers {
|
||||
if m == module {
|
||||
|
||||
@@ -140,9 +140,26 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) {
|
||||
if p := m.state(t, key); p.Reference == nil || p.Reference.ID != "pair/gitea-postgres" || p.Reference.Generation != 3 {
|
||||
t.Errorf("the vault's generation does not reach the reference: %+v", p.Reference)
|
||||
}
|
||||
// The holder never sets provided by itself: a provider writing no outcome leaves its key asked (clause 3).
|
||||
if p := m.state(t, "g14.gitea.split-dns"); p.State != provisions.Asked || !strings.Contains(p.Why, "writes no outcome") {
|
||||
t.Errorf("a provider writing no outcome: %+v", p)
|
||||
// A provider making no credential per consumer reports through its own have (clause 3): never provided by the
|
||||
// holder alone.
|
||||
split := "g14.gitea.split-dns"
|
||||
for _, row := range []struct{ have, want, state, why string }{
|
||||
{"", "", provisions.Asked, "says nothing yet"},
|
||||
{`{"v":1,"fp":"src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","phase":"applying","health":"unknown"}`, "", provisions.Asked, "applying"},
|
||||
{`{"v":1,"fp":"src2:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","phase":"running","health":"ok"}`, `{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","self":true}`, provisions.Asked, "build its want"},
|
||||
{`{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","phase":"failed","health":"failed","detail":"the unit did not start"}`, "", provisions.Failed, "did not start"},
|
||||
{`{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","phase":"running","health":"ok"}`, `{"v":1,"fp":"src2:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","self":true}`, provisions.Provided, ""},
|
||||
} {
|
||||
if row.have != "" {
|
||||
m.s.write(t, HaveRead, "g14.systemd-resolved", row.have)
|
||||
}
|
||||
if row.want != "" {
|
||||
m.s.write(t, WantsRead, "want.g14.systemd-resolved", row.want)
|
||||
}
|
||||
m.compose(t, "g14")
|
||||
if p := m.state(t, split); p.State != row.state || !strings.Contains(p.Why, row.why) {
|
||||
t.Errorf("the provider's have %s: %+v, want %s", row.have, p, row.state)
|
||||
}
|
||||
}
|
||||
if e, _ := m.s.Get(PlansState, "g14.gitea"); e == nil {
|
||||
t.Error("the plan is not written")
|
||||
|
||||
Reference in New Issue
Block a user