assigner, view, watchman: provisions come from meshprovisionerclient, not mesh-sdk go/provisions (ADR 0634 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -37,13 +37,13 @@ import (
|
|||||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||||
"git.novox.be/novox/mesh-sdk/go/buscompose"
|
"git.novox.be/novox/mesh-sdk/go/buscompose"
|
||||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||||
"git.novox.be/novox/mesh-sdk/go/health"
|
"git.novox.be/novox/mesh-sdk/go/health"
|
||||||
"git.novox.be/novox/mesh-sdk/go/process"
|
"git.novox.be/novox/mesh-sdk/go/process"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
"mesh-delivery-assigner/internal/judge"
|
"mesh-delivery-assigner/internal/judge"
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||||
@@ -526,15 +526,15 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) {
|
|||||||
appDigest := b.manifest(t, "app", `{"module":"app","version":"1","requires":["database"]}`)
|
appDigest := b.manifest(t, "app", `{"module":"app","version":"1","requires":["database"]}`)
|
||||||
toolDigest := b.manifest(t, "tool", `{"module":"tool","version":"1"}`)
|
toolDigest := b.manifest(t, "tool", `{"module":"tool","version":"1"}`)
|
||||||
asked := func(state, why string) {
|
asked := func(state, why string) {
|
||||||
raw, err := provisions.Encode(provisions.Provision{V: provisions.Version, Provision: "database", Consumer: provisions.End{Module: "app", Node: "ace"},
|
raw, err := meshprovisionerclient.Encode(meshprovisionerclient.Provision{V: meshprovisionerclient.Version, Provision: "database", Consumer: meshprovisionerclient.End{Module: "app", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "db", Node: "ace"}, State: state, Why: why, At: time.Now()})
|
Provider: meshprovisionerclient.End{Module: "db", Node: "ace"}, State: state, Why: why, At: time.Now()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
b.putJSON(t, provisions.ProvisionsBucket, "ace.app.database", raw)
|
b.putJSON(t, meshprovisionerclient.ProvisionsBucket, "ace.app.database", raw)
|
||||||
}
|
}
|
||||||
// The provisioner keys it from the manifests, as soon as they are known and whether the provider is placed yet or not.
|
// The provisioner keys it from the manifests, as soon as they are known and whether the provider is placed yet or not.
|
||||||
asked(provisions.Asked, "the provider's build is not done")
|
asked(meshprovisionerclient.Asked, "the provider's build is not done")
|
||||||
fpOf := func(c byte) string { return meshcatalogclient.SourcePrefix2 + strings.Repeat(string(c), 64) }
|
fpOf := func(c byte) string { return meshcatalogclient.SourcePrefix2 + strings.Repeat(string(c), 64) }
|
||||||
toolOld := fpOf('1')
|
toolOld := fpOf('1')
|
||||||
for module, row := range map[string]struct {
|
for module, row := range map[string]struct {
|
||||||
@@ -565,7 +565,7 @@ func TestWantsAreWrittenAndNoDifferenceIs(t *testing.T) {
|
|||||||
if e, err := b.buckets[buckets.Wants].Get(b.ctx, "want.ace.app"); err == nil {
|
if e, err := b.buckets[buckets.Wants].Get(b.ctx, "want.ace.app"); err == nil {
|
||||||
t.Errorf("app was wanted while its provision was asked: %s", e.Value())
|
t.Errorf("app was wanted while its provision was asked: %s", e.Value())
|
||||||
}
|
}
|
||||||
asked(provisions.Provided, "")
|
asked(meshprovisionerclient.Provided, "")
|
||||||
if w := b.wantNow(t, "ace", "app", "the consumer's want once its provision is provided", func(w mwc.Want) bool { return w.Fp == fpOf('3') }); w.Fp != fpOf('3') {
|
if w := b.wantNow(t, "ace", "app", "the consumer's want once its provision is provided", func(w mwc.Want) bool { return w.Fp == fpOf('3') }); w.Fp != fpOf('3') {
|
||||||
t.Errorf("app's want = %+v", w)
|
t.Errorf("app's want = %+v", w)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ import (
|
|||||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||||
"git.novox.be/novox/mesh-sdk/go/health"
|
"git.novox.be/novox/mesh-sdk/go/health"
|
||||||
"git.novox.be/novox/mesh-sdk/go/process"
|
"git.novox.be/novox/mesh-sdk/go/process"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||||
"git.novox.be/novox/mesh-sdk/go/views"
|
"git.novox.be/novox/mesh-sdk/go/views"
|
||||||
@@ -64,7 +64,7 @@ var readBuckets = []string{
|
|||||||
buckets.Builds,
|
buckets.Builds,
|
||||||
buckets.Presence,
|
buckets.Presence,
|
||||||
buckets.Have,
|
buckets.Have,
|
||||||
provisions.ProvisionsBucket,
|
meshprovisionerclient.ProvisionsBucket,
|
||||||
buckets.Source,
|
buckets.Source,
|
||||||
buckets.Merges,
|
buckets.Merges,
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ func open(ctx context.Context, js process.BucketOpener, logf func(string, ...any
|
|||||||
logf("the bucket %s cannot be opened (%v): it is bound once the bus says it was made", name, err)
|
logf("the bucket %s cannot be opened (%v): it is bound once the bus says it was made", name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if name == provisions.ProvisionsBucket && err != nil {
|
if name == meshprovisionerclient.ProvisionsBucket && err != nil {
|
||||||
// The seat mesh-provisioner's state, with its own delivery (ADR 0570 §4): bound once the bus says it was made;
|
// The seat mesh-provisioner's state, with its own delivery (ADR 0570 §4): bound once the bus says it was made;
|
||||||
// until then no want waits for a provision, as before.
|
// until then no want waits for a provision, as before.
|
||||||
logf("the bucket %s cannot be opened (%v): it is bound once the bus says it was made", name, err)
|
logf("the bucket %s cannot be opened (%v): it is bound once the bus says it was made", name, err)
|
||||||
@@ -187,7 +187,7 @@ func open(ctx context.Context, js process.BucketOpener, logf func(string, ...any
|
|||||||
// states and those new with a delivery of their own, bound once made, and the two that choose the grants' source.
|
// states and those new with a delivery of their own, bound once made, and the two that choose the grants' source.
|
||||||
func startsWithout(name string) bool {
|
func startsWithout(name string) bool {
|
||||||
switch name {
|
switch name {
|
||||||
case plc.SeatHoldersBucket, provisions.ProvisionsBucket, assign.PoliciesBucket, assign.FindingsBucket,
|
case plc.SeatHoldersBucket, meshprovisionerclient.ProvisionsBucket, assign.PoliciesBucket, assign.FindingsBucket,
|
||||||
buckets.Puts, buckets.Source, buckets.Merges, engineReadsBucket:
|
buckets.Puts, buckets.Source, buckets.Merges, engineReadsBucket:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ var watched = []string{
|
|||||||
buckets.Differences,
|
buckets.Differences,
|
||||||
buckets.Wants,
|
buckets.Wants,
|
||||||
assign.PoliciesBucket,
|
assign.PoliciesBucket,
|
||||||
provisions.ProvisionsBucket,
|
meshprovisionerclient.ProvisionsBucket,
|
||||||
plc.SeatHoldersBucket,
|
plc.SeatHoldersBucket,
|
||||||
buckets.Source,
|
buckets.Source,
|
||||||
buckets.Merges,
|
buckets.Merges,
|
||||||
@@ -428,7 +428,7 @@ func follow(ctx context.Context, js jetstream.JetStream, nc process.Subscriber,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// And the two that choose where grants are read from, with the same delivery as the grants part that writes one.
|
// And the two that choose where grants are read from, with the same delivery as the grants part that writes one.
|
||||||
for _, name := range []string{buckets.Grants, assign.PoliciesBucket, provisions.ProvisionsBucket, plc.SeatHoldersBucket} {
|
for _, name := range []string{buckets.Grants, assign.PoliciesBucket, meshprovisionerclient.ProvisionsBucket, plc.SeatHoldersBucket} {
|
||||||
if kvs[name] == nil && js != nil {
|
if kvs[name] == nil && js != nil {
|
||||||
name := name
|
name := name
|
||||||
process.AwaitBucket(ctx, js, nc, name, "until then the bucket is not read",
|
process.AwaitBucket(ctx, js, nc, name, "until then the bucket is not read",
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||||
|
|
||||||
@@ -940,37 +940,37 @@ func chosenOf(chosen map[string]catalogue.PersonPolicy, module string) *catalogu
|
|||||||
// mesh-provisioner's state; nil while the state is not read (the seat not delivered yet), so no want waits on it. A failed
|
// mesh-provisioner's state; nil while the state is not read (the seat not delivered yet), so no want waits on it. A failed
|
||||||
// provision is also said as the assigner's finding `provider.<key>.provision-failed` (a waiting one is the watchman's
|
// provision is also said as the assigner's finding `provider.<key>.provision-failed` (a waiting one is the watchman's
|
||||||
// needs-operator), deleted once it is no longer failed.
|
// needs-operator), deleted once it is no longer failed.
|
||||||
func (p *passer) provisionsOf() func(module string) func(node string) map[string]provisions.Provision {
|
func (p *passer) provisionsOf() func(module string) func(node string) map[string]meshprovisionerclient.Provision {
|
||||||
if p.kvs[provisions.ProvisionsBucket] == nil {
|
if p.kvs[meshprovisionerclient.ProvisionsBucket] == nil {
|
||||||
return func(string) func(string) map[string]provisions.Provision { return nil }
|
return func(string) func(string) map[string]meshprovisionerclient.Provision { return nil }
|
||||||
}
|
}
|
||||||
by := map[string]map[string]map[string]provisions.Provision{} // module, node, key
|
by := map[string]map[string]map[string]meshprovisionerclient.Provision{} // module, node, key
|
||||||
failed := map[string]provisions.Provision{}
|
failed := map[string]meshprovisionerclient.Provision{}
|
||||||
for key, raw := range p.w.read(provisions.ProvisionsBucket) {
|
for key, raw := range p.w.read(meshprovisionerclient.ProvisionsBucket) {
|
||||||
pr, err := provisions.Decode(raw)
|
pr, err := meshprovisionerclient.Decode(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
node, module := pr.Consumer.Node, pr.Consumer.Module
|
node, module := pr.Consumer.Node, pr.Consumer.Module
|
||||||
if by[module] == nil {
|
if by[module] == nil {
|
||||||
by[module] = map[string]map[string]provisions.Provision{}
|
by[module] = map[string]map[string]meshprovisionerclient.Provision{}
|
||||||
}
|
}
|
||||||
if by[module][node] == nil {
|
if by[module][node] == nil {
|
||||||
by[module][node] = map[string]provisions.Provision{}
|
by[module][node] = map[string]meshprovisionerclient.Provision{}
|
||||||
}
|
}
|
||||||
by[module][node][key] = pr
|
by[module][node][key] = pr
|
||||||
if pr.State == provisions.Failed {
|
if pr.State == meshprovisionerclient.Failed {
|
||||||
failed[key] = pr
|
failed[key] = pr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.provisionFindings(failed)
|
p.provisionFindings(failed)
|
||||||
return func(module string) func(string) map[string]provisions.Provision {
|
return func(module string) func(string) map[string]meshprovisionerclient.Provision {
|
||||||
return func(node string) map[string]provisions.Provision { return by[module][node] }
|
return func(node string) map[string]meshprovisionerclient.Provision { return by[module][node] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// provisionFindings writes the finding of each failed provision and deletes the ones no longer failed.
|
// provisionFindings writes the finding of each failed provision and deletes the ones no longer failed.
|
||||||
func (p *passer) provisionFindings(failed map[string]provisions.Provision) {
|
func (p *passer) provisionFindings(failed map[string]meshprovisionerclient.Provision) {
|
||||||
if p.findings.Put == nil {
|
if p.findings.Put == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ import (
|
|||||||
|
|
||||||
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
mmac "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||||
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
mma "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||||
"git.novox.be/novox/mesh-sdk/go/health"
|
"git.novox.be/novox/mesh-sdk/go/health"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
"github.com/nats-io/nats.go/jetstream"
|
"github.com/nats-io/nats.go/jetstream"
|
||||||
|
|
||||||
"mesh-delivery-assigner/internal/assign"
|
"mesh-delivery-assigner/internal/assign"
|
||||||
@@ -325,23 +325,23 @@ func TestTheSeatsVerbs(t *testing.T) {
|
|||||||
})
|
})
|
||||||
t.Run("1954/D1: a failed provision is the assigner's finding until it is provided", func(t *testing.T) {
|
t.Run("1954/D1: a failed provision is the assigner's finding until it is provided", func(t *testing.T) {
|
||||||
findings := map[string][]byte{}
|
findings := map[string][]byte{}
|
||||||
p := &passer{w: newWorld(), logf: func(string, ...any) {}, kvs: kvSet{provisions.ProvisionsBucket: nil}, findings: assign.Findings{
|
p := &passer{w: newWorld(), logf: func(string, ...any) {}, kvs: kvSet{meshprovisionerclient.ProvisionsBucket: nil}, findings: assign.Findings{
|
||||||
Put: func(k string, v []byte) error { findings[k] = v; return nil },
|
Put: func(k string, v []byte) error { findings[k] = v; return nil },
|
||||||
Delete: func(k string) error { delete(findings, k); return nil }}}
|
Delete: func(k string) error { delete(findings, k); return nil }}}
|
||||||
failed, _ := provisions.Encode(provisions.Provision{Provision: "db", Consumer: provisions.End{Module: "photos", Node: "ace"},
|
failed, _ := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "db", Consumer: meshprovisionerclient.End{Module: "photos", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "postgres", Node: "novox"}, State: provisions.Failed, Why: "the role exists already"})
|
Provider: meshprovisionerclient.End{Module: "postgres", Node: "novox"}, State: meshprovisionerclient.Failed, Why: "the role exists already"})
|
||||||
p.w.putEntry(provisions.ProvisionsBucket, "ace.photos.db", failed, 1, time.Now())
|
p.w.putEntry(meshprovisionerclient.ProvisionsBucket, "ace.photos.db", failed, 1, time.Now())
|
||||||
p.kvs[provisions.ProvisionsBucket] = &memKV{}
|
p.kvs[meshprovisionerclient.ProvisionsBucket] = &memKV{}
|
||||||
of := p.provisionsOf()
|
of := p.provisionsOf()
|
||||||
if got := of("photos")("ace"); got["ace.photos.db"].State != provisions.Failed {
|
if got := of("photos")("ace"); got["ace.photos.db"].State != meshprovisionerclient.Failed {
|
||||||
t.Fatalf("provisions = %+v", got)
|
t.Fatalf("provisions = %+v", got)
|
||||||
}
|
}
|
||||||
if _, ok := findings[assign.ProvisionFailedKey("ace.photos.db")]; !ok || len(findings) != 1 {
|
if _, ok := findings[assign.ProvisionFailedKey("ace.photos.db")]; !ok || len(findings) != 1 {
|
||||||
t.Fatalf("findings = %v", findings)
|
t.Fatalf("findings = %v", findings)
|
||||||
}
|
}
|
||||||
provided, _ := provisions.Encode(provisions.Provision{Provision: "db", Consumer: provisions.End{Module: "photos", Node: "ace"},
|
provided, _ := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "db", Consumer: meshprovisionerclient.End{Module: "photos", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "postgres", Node: "novox"}, State: provisions.Provided})
|
Provider: meshprovisionerclient.End{Module: "postgres", Node: "novox"}, State: meshprovisionerclient.Provided})
|
||||||
p.w.putEntry(provisions.ProvisionsBucket, "ace.photos.db", provided, 2, time.Now())
|
p.w.putEntry(meshprovisionerclient.ProvisionsBucket, "ace.photos.db", provided, 2, time.Now())
|
||||||
p.provisionsOf()
|
p.provisionsOf()
|
||||||
if len(findings) != 0 {
|
if len(findings) != 0 {
|
||||||
t.Errorf("findings after provided = %v", findings)
|
t.Errorf("findings after provided = %v", findings)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module mesh-delivery-assigner
|
|||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient v0.0.0
|
git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient v0.0.0
|
||||||
git.novox.be/novox/mesh-contracts/placement/go/seats/meshwants v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/placement/go/seats/meshwants v0.0.0-00010101000000-000000000000
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
occ "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||||
"git.novox.be/novox/mesh-sdk/go/health"
|
"git.novox.be/novox/mesh-sdk/go/health"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A person's upgrade policy is the assigner's (novox/hq ADR 0565 §7, §8, issue 1953 D4, D5): kept in its state `policies`, one
|
// A person's upgrade policy is the assigner's (novox/hq ADR 0565 §7, §8, issue 1953 D4, D5): kept in its state `policies`, one
|
||||||
@@ -65,7 +65,7 @@ func ProvisionFailedKey(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ProvisionFailedFinding is the finding of a failed provision, naming its consumer, its provider and why.
|
// ProvisionFailedFinding is the finding of a failed provision, naming its consumer, its provider and why.
|
||||||
func ProvisionFailedFinding(key string, p provisions.Provision, at time.Time) ([]byte, error) {
|
func ProvisionFailedFinding(key string, p meshprovisionerclient.Provision, at time.Time) ([]byte, error) {
|
||||||
summary := fmt.Sprintf("%s for %s on %s failed at %s on %s: %s, so %s is not moved there until it is provided", p.Provision,
|
summary := fmt.Sprintf("%s for %s on %s failed at %s on %s: %s, so %s is not moved there until it is provided", p.Provision,
|
||||||
p.Consumer.Module, p.Consumer.Node, p.Provider.Module, p.Provider.Node, p.Why, p.Consumer.Module)
|
p.Consumer.Module, p.Consumer.Node, p.Provider.Module, p.Provider.Node, p.Why, p.Consumer.Module)
|
||||||
return health.EncodeFinding(health.Finding{Key: ProvisionFailedKey(key), Kind: KindProvisionFailed,
|
return health.EncodeFinding(health.Finding{Key: ProvisionFailedKey(key), Kind: KindProvisionFailed,
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/forms"
|
"git.novox.be/novox/mesh-delivery/sdk/forms"
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||||
@@ -40,7 +40,7 @@ type Module struct {
|
|||||||
Manifest catalogue.Manifest
|
Manifest catalogue.Manifest
|
||||||
// Provisions is the seat mesh-provisioner's provisions this module consumes on a node, by key (ADR 0570 §4): the want
|
// Provisions is the seat mesh-provisioner's provisions this module consumes on a node, by key (ADR 0570 §4): the want
|
||||||
// waits until each is provided. Nil: the seat's state is not read (not delivered yet), and nothing waits on it.
|
// waits until each is provided. Nil: the seat's state is not read (not delivered yet), and nothing waits on it.
|
||||||
Provisions func(node string) map[string]provisions.Provision
|
Provisions func(node string) map[string]meshprovisionerclient.Provision
|
||||||
// Answering is the manifests of the modules placed somewhere that provide a provision: what catalogue.Awaited
|
// Answering is the manifests of the modules placed somewhere that provide a provision: what catalogue.Awaited
|
||||||
// judges a want's provisions by (issue 774). Nil: none known, and no key is waited for that is not there.
|
// judges a want's provisions by (issue 774). Nil: none known, and no key is waited for that is not there.
|
||||||
Answering func(provision string) []catalogue.Manifest
|
Answering func(provision string) []catalogue.Manifest
|
||||||
@@ -242,7 +242,7 @@ func (m Module) provisionWaiting(node string) (string, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, key := range slices.Sorted(maps.Keys(keyed)) {
|
for _, key := range slices.Sorted(maps.Keys(keyed)) {
|
||||||
if p := keyed[key]; p.State != provisions.Provided && slices.Contains(needed, p.Provision) {
|
if p := keyed[key]; p.State != meshprovisionerclient.Provided && slices.Contains(needed, p.Provision) {
|
||||||
words := fmt.Sprintf("the provision %s of %s on %s is %s, not provided", key, m.Name, node, p.State)
|
words := fmt.Sprintf("the provision %s of %s on %s is %s, not provided", key, m.Name, node, p.State)
|
||||||
if p.Why != "" {
|
if p.Why != "" {
|
||||||
words += ": " + p.Why
|
words += ": " + p.Why
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||||
)
|
)
|
||||||
@@ -81,8 +81,8 @@ func TestEachRuleHoldsTheWantBack(t *testing.T) {
|
|||||||
},
|
},
|
||||||
// 1954/D1 (ADR 0570 §4): a provision of the module on that node still asked holds its want.
|
// 1954/D1 (ADR 0570 §4): a provision of the module on that node still asked holds its want.
|
||||||
mwc.RuleProvisions: func(m *Module, _ *Nodes) {
|
mwc.RuleProvisions: func(m *Module, _ *Nodes) {
|
||||||
m.Provisions = func(node string) map[string]provisions.Provision {
|
m.Provisions = func(node string) map[string]meshprovisionerclient.Provision {
|
||||||
return map[string]provisions.Provision{node + ".mail.database": {Provision: "database", State: provisions.Asked}, node + ".mail.oidc": {Provision: "oidc", State: provisions.Provided}}
|
return map[string]meshprovisionerclient.Provision{node + ".mail.database": {Provision: "database", State: meshprovisionerclient.Asked}, node + ".mail.oidc": {Provision: "oidc", State: meshprovisionerclient.Provided}}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
@@ -103,9 +103,9 @@ func TestEachRuleHoldsTheWantBack(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 1954/D1: every provision provided, the want moves; with the seat's state not read, nothing waits on it.
|
// 1954/D1: every provision provided, the want moves; with the seat's state not read, nothing waits on it.
|
||||||
for _, all := range []func(string) map[string]provisions.Provision{
|
for _, all := range []func(string) map[string]meshprovisionerclient.Provision{
|
||||||
func(node string) map[string]provisions.Provision {
|
func(node string) map[string]meshprovisionerclient.Provision {
|
||||||
return map[string]provisions.Provision{node + ".mail.database": {Provision: "database", State: provisions.Provided}}
|
return map[string]meshprovisionerclient.Provision{node + ".mail.database": {Provision: "database", State: meshprovisionerclient.Provided}}
|
||||||
}, nil} {
|
}, nil} {
|
||||||
m, n := ready()
|
m, n := ready()
|
||||||
m.Provisions = all
|
m.Provisions = all
|
||||||
@@ -216,13 +216,13 @@ func TestEachRuleHoldsTheWantBack(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
state, older string
|
state, older string
|
||||||
moves bool
|
moves bool
|
||||||
}{{"the replaced edge provided, the older edge retiring", provisions.Provided, provisions.Retiring, true},
|
}{{"the replaced edge provided, the older edge retiring", meshprovisionerclient.Provided, meshprovisionerclient.Retiring, true},
|
||||||
{"the replaced edge provided, the older edge asked", provisions.Provided, provisions.Asked, true},
|
{"the replaced edge provided, the older edge asked", meshprovisionerclient.Provided, meshprovisionerclient.Asked, true},
|
||||||
{"the replaced edge asked, the older edge retiring", provisions.Asked, provisions.Retiring, false}} {
|
{"the replaced edge asked, the older edge retiring", meshprovisionerclient.Asked, meshprovisionerclient.Retiring, false}} {
|
||||||
m, n := ready()
|
m, n := ready()
|
||||||
m.Manifest.Requires = []string{"oidc"}
|
m.Manifest.Requires = []string{"oidc"}
|
||||||
m.Provisions = func(node string) map[string]provisions.Provision {
|
m.Provisions = func(node string) map[string]meshprovisionerclient.Provision {
|
||||||
return map[string]provisions.Provision{node + ".mail.oidc": {Provision: "oidc", State: c.state},
|
return map[string]meshprovisionerclient.Provision{node + ".mail.oidc": {Provision: "oidc", State: c.state},
|
||||||
node + ".mail.database": {Provision: "database", State: c.older, Why: "the operator's answer"}}
|
node + ".mail.database": {Provision: "database", State: c.older, Why: "the operator's answer"}}
|
||||||
}
|
}
|
||||||
out := Wants(m, n, wantedOld(), nil)
|
out := Wants(m, n, wantedOld(), nil)
|
||||||
@@ -267,7 +267,9 @@ func TestEachRuleHoldsTheWantBack(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
m, n := ready()
|
m, n := ready()
|
||||||
m.Manifest, m.Answering = c.manifest, answering
|
m.Manifest, m.Answering = c.manifest, answering
|
||||||
m.Provisions = func(string) map[string]provisions.Provision { return map[string]provisions.Provision{} }
|
m.Provisions = func(string) map[string]meshprovisionerclient.Provision {
|
||||||
|
return map[string]meshprovisionerclient.Provision{}
|
||||||
|
}
|
||||||
out := Wants(m, n, wantedOld(), nil)
|
out := Wants(m, n, wantedOld(), nil)
|
||||||
if c.missing == "" {
|
if c.missing == "" {
|
||||||
if out.Wants["g14"].Fp != fNew || len(m.MissingProvisions("g14")) != 0 {
|
if out.Wants["g14"].Fp != fNew || len(m.MissingProvisions("g14")) != 0 {
|
||||||
@@ -292,7 +294,9 @@ func TestEachRuleHoldsTheWantBack(t *testing.T) {
|
|||||||
m.Manifest.Requires = []string{c.requires}
|
m.Manifest.Requires = []string{c.requires}
|
||||||
m.Answering = func(string) []catalogue.Manifest { return nil }
|
m.Answering = func(string) []catalogue.Manifest { return nil }
|
||||||
m.Offered = func(p string) bool { return c.offered && p == c.requires }
|
m.Offered = func(p string) bool { return c.offered && p == c.requires }
|
||||||
m.Provisions = func(string) map[string]provisions.Provision { return map[string]provisions.Provision{} }
|
m.Provisions = func(string) map[string]meshprovisionerclient.Provision {
|
||||||
|
return map[string]meshprovisionerclient.Provision{}
|
||||||
|
}
|
||||||
out := Wants(m, n, wantedOld(), nil)
|
out := Wants(m, n, wantedOld(), nil)
|
||||||
if got := out.Wants["g14"].Fp == fNew; got != c.offered || (!c.offered && (out.Rules["g14"].Rule != mwc.RuleProvisions ||
|
if got := out.Wants["g14"].Fp == fNew; got != c.offered || (!c.offered && (out.Rules["g14"].Rule != mwc.RuleProvisions ||
|
||||||
!strings.Contains(out.Rules["g14"].Words, "no module offers database yet") || !strings.Contains(out.Rules["g14"].Words, "past its bound"))) {
|
!strings.Contains(out.Rules["g14"].Words, "no module offers database yet") || !strings.Contains(out.Rules["g14"].Words, "past its bound"))) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
|
||||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-view/viewstate"
|
||||||
@@ -21,7 +22,6 @@ import (
|
|||||||
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
"git.novox.be/novox/mesh-delivery/sdk/enginereads"
|
||||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||||
"git.novox.be/novox/mesh-sdk/go/busretry"
|
"git.novox.be/novox/mesh-sdk/go/busretry"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
"git.novox.be/novox/mesh-sdk/go/views"
|
"git.novox.be/novox/mesh-sdk/go/views"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ func main() {
|
|||||||
r.ConditionsState, r.AttemptsState = read(stdio.State(view.StatusConditionsState)), read(stdio.State(view.StatusAttemptsState))
|
r.ConditionsState, r.AttemptsState = read(stdio.State(view.StatusConditionsState)), read(stdio.State(view.StatusAttemptsState))
|
||||||
r.PresenceState, r.StuckState = read(stdio.State(view.StatusPresenceState)), read(stdio.State(view.StatusStuckState))
|
r.PresenceState, r.StuckState = read(stdio.State(view.StatusPresenceState)), read(stdio.State(view.StatusStuckState))
|
||||||
r.SourceState = read(stdio.State(view.GateModule + ".source"))
|
r.SourceState = read(stdio.State(view.GateModule + ".source"))
|
||||||
r.ProvisionsState = read(stdio.State(provisions.ProvisionsRead))
|
r.ProvisionsState = read(stdio.State(meshprovisionerclient.ProvisionsRead))
|
||||||
r.BuildLog = stdio.Log(builds.BuildLogRead).Since
|
r.BuildLog = stdio.Log(builds.BuildLogRead).Since
|
||||||
r.Pending = pendingOf
|
r.Pending = pendingOf
|
||||||
u := view.UsageReader{Haves: r.HavesState, Resolved: read(stdio.State("mesh-config.resolved")), Tries: read(stdio.State("mesh-delivery-checker.tries")),
|
u := view.UsageReader{Haves: r.HavesState, Resolved: read(stdio.State("mesh-config.resolved")), Tries: read(stdio.State("mesh-delivery-checker.tries")),
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ import (
|
|||||||
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
|
||||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
||||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// encoded is v as its contract's encoder writes it, failing the test when it refuses.
|
// encoded is v as its contract's encoder writes it, failing the test when it refuses.
|
||||||
@@ -85,9 +85,9 @@ func tiersToolSaysEachModulesWait(t *testing.T) {
|
|||||||
}.reader().State
|
}.reader().State
|
||||||
r.WantsState.History = func(string) ([]view.Revision, error) { return []view.Revision{{At: since}}, nil }
|
r.WantsState.History = func(string) ([]view.Revision, error) { return []view.Revision{{At: since}}, nil }
|
||||||
r.HavesState = fake{key(nodeengineclient.HaveKey("ace", "db")): have(nodeengine.HaveByNodeModuleValue{Fp: fp("a"), Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK})}.reader().State
|
r.HavesState = fake{key(nodeengineclient.HaveKey("ace", "db")): have(nodeengine.HaveByNodeModuleValue{Fp: fp("a"), Phase: nodeengineclient.PhaseRunning, Health: nodeengineclient.HealthOK})}.reader().State
|
||||||
p, err := provisions.Encode(provisions.Provision{Provision: "database", Consumer: provisions.End{Module: "web", Node: "ace"},
|
p, err := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "database", Consumer: meshprovisionerclient.End{Module: "web", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "db", Node: "ace"}, State: provisions.Asked, Why: "the build db runs does not offer it", At: since})
|
Provider: meshprovisionerclient.End{Module: "db", Node: "ace"}, State: meshprovisionerclient.Asked, Why: "the build db runs does not offer it", At: since})
|
||||||
r.ProvisionsState = fake{key(provisions.Key("ace", "web", "database", "")): encoded(t, p, err)}.reader().State
|
r.ProvisionsState = fake{key(meshprovisionerclient.Key("ace", "web", "database", "")): encoded(t, p, err)}.reader().State
|
||||||
off, err := meshwatchdogsclient.EncodeNodePresence(meshwatchdogsclient.NodePresence{Online: false})
|
off, err := meshwatchdogsclient.EncodeNodePresence(meshwatchdogsclient.NodePresence{Online: false})
|
||||||
r.PresenceState = fake{key(meshwatchdogsclient.PresenceNodeKey("g14")): encoded(t, off, err)}.reader().State
|
r.PresenceState = fake{key(meshwatchdogsclient.PresenceNodeKey("g14")): encoded(t, off, err)}.reader().State
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module mesh-delivery-view
|
|||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/identity-and-access/go/clients/meshvaultclient v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/identity-and-access/go/clients/meshvaultclient v0.0.0-00010101000000-000000000000
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ import (
|
|||||||
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
"git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient"
|
||||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
||||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshwantsclient"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||||
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
"git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
"git.novox.be/novox/mesh-delivery/sdk/graph"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// The tiers of a source revision are a view, worked out at each call and never stored (novox/hq ADR 0603 §1, §6): the
|
// The tiers of a source revision are a view, worked out at each call and never stored (novox/hq ADR 0603 §1, §6): the
|
||||||
@@ -389,7 +389,7 @@ func provisionWaits(node, module, a string, provided map[string]json.RawMessage,
|
|||||||
if perr != nil {
|
if perr != nil {
|
||||||
return []TierWait{{Edge: edge, Node: node, Words: "the provisioner's keys cannot be read: " + perr.Error()}}
|
return []TierWait{{Edge: edge, Node: node, Words: "the provisioner's keys cannot be read: " + perr.Error()}}
|
||||||
}
|
}
|
||||||
prefix, _ := provisions.Key(node, module, a, "")
|
prefix, _ := meshprovisionerclient.Key(node, module, a, "")
|
||||||
var out []TierWait
|
var out []TierWait
|
||||||
found := false
|
found := false
|
||||||
for _, key := range slices.Sorted(maps.Keys(provided)) {
|
for _, key := range slices.Sorted(maps.Keys(provided)) {
|
||||||
@@ -397,12 +397,12 @@ func provisionWaits(node, module, a string, provided map[string]json.RawMessage,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
found = true
|
found = true
|
||||||
p, err := provisions.Decode(provided[key])
|
p, err := meshprovisionerclient.Decode(provided[key])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out = append(out, TierWait{Edge: edge, Node: node, Words: "the provision key " + key + " does not read: " + err.Error()})
|
out = append(out, TierWait{Edge: edge, Node: node, Words: "the provision key " + key + " does not read: " + err.Error()})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if p.State == provisions.Provided {
|
if p.State == meshprovisionerclient.Provided {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
words := "the provision " + key + " is " + p.State
|
words := "the provision " + key + " is " + p.State
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ import (
|
|||||||
"github.com/nats-io/nats.go/jetstream"
|
"github.com/nats-io/nats.go/jetstream"
|
||||||
|
|
||||||
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient"
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
"git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient"
|
||||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-indexer/takein"
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
|
|
||||||
"mesh-delivery-watchman/internal/socket"
|
"mesh-delivery-watchman/internal/socket"
|
||||||
"mesh-delivery-watchman/internal/watch"
|
"mesh-delivery-watchman/internal/watch"
|
||||||
@@ -382,21 +382,21 @@ func run(ctx context.Context, getenv func(string) string, logOut io.Writer) erro
|
|||||||
provisionsWatch := func(kv jetstream.KeyValue) (jetstream.KeyWatcher, error) {
|
provisionsWatch := func(kv jetstream.KeyValue) (jetstream.KeyWatcher, error) {
|
||||||
pw, err := settle(ctx, kv, func(e jetstream.KeyValueEntry) { w.Provision(e.Key(), e.Value(), opOf(e)) })
|
pw, err := settle(ctx, kv, func(e jetstream.KeyValueEntry) { w.Provision(e.Key(), e.Value(), opOf(e)) })
|
||||||
if err == nil {
|
if err == nil {
|
||||||
w.ReadWhole(provisions.ProvisionsBucket)
|
w.ReadWhole(meshprovisionerclient.ProvisionsBucket)
|
||||||
}
|
}
|
||||||
return pw, err
|
return pw, err
|
||||||
}
|
}
|
||||||
var provWatch jetstream.KeyWatcher
|
var provWatch jetstream.KeyWatcher
|
||||||
if kv, err := js.KeyValue(ctx, provisions.ProvisionsBucket); err == nil {
|
if kv, err := js.KeyValue(ctx, meshprovisionerclient.ProvisionsBucket); err == nil {
|
||||||
if provWatch, err = provisionsWatch(kv); err != nil {
|
if provWatch, err = provisionsWatch(kv); err != nil {
|
||||||
process.NotWatched(logger.Printf, provisions.ProvisionsBucket, err, "no provision waiting for the operator is said until the watchman starts again")
|
process.NotWatched(logger.Printf, meshprovisionerclient.ProvisionsBucket, err, "no provision waiting for the operator is said until the watchman starts again")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
process.AwaitBucket(ctx, js, conn, provisions.ProvisionsBucket, "no provision waiting for the operator is said",
|
process.AwaitBucket(ctx, js, conn, meshprovisionerclient.ProvisionsBucket, "no provision waiting for the operator is said",
|
||||||
logger.Printf).Ready(func(kv jetstream.KeyValue) {
|
logger.Printf).Ready(func(kv jetstream.KeyValue) {
|
||||||
pw, err := provisionsWatch(kv)
|
pw, err := provisionsWatch(kv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
process.NotWatched(logger.Printf, provisions.ProvisionsBucket, err, "no provision waiting for the operator is said until the watchman starts again")
|
process.NotWatched(logger.Printf, meshprovisionerclient.ProvisionsBucket, err, "no provision waiting for the operator is said until the watchman starts again")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module mesh-delivery-watchman
|
|||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/go/seats/nodeengine v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/go/seats/nodeengine v0.0.0-00010101000000-000000000000
|
||||||
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient v0.0.0-00010101000000-000000000000
|
git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshwatchdogsclient v0.0.0-00010101000000-000000000000
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import (
|
|||||||
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||||
"git.novox.be/novox/mesh-sdk/go/health"
|
"git.novox.be/novox/mesh-sdk/go/health"
|
||||||
|
|
||||||
|
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||||
"git.novox.be/novox/mesh-delivery/sdk/heard"
|
"git.novox.be/novox/mesh-delivery/sdk/heard"
|
||||||
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustEncode(t *testing.T, f Finding) []byte {
|
func mustEncode(t *testing.T, f Finding) []byte {
|
||||||
@@ -474,20 +474,20 @@ func TestTheWatchmansFindings(t *testing.T) {
|
|||||||
}, map[string]string{"module.fail2ban.novox.unhealthy": Warning}},
|
}, map[string]string{"module.fail2ban.novox.unhealthy": Warning}},
|
||||||
{"1954/D2: a provision in waits is its consumer's needs-operator; provided, it ends", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) {
|
{"1954/D2: a provision in waits is its consumer's needs-operator; provided, it ends", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) {
|
||||||
enc := func(state, why string) []byte {
|
enc := func(state, why string) []byte {
|
||||||
b, err := provisions.Encode(provisions.Provision{Provision: "oidc", Consumer: provisions.End{Module: "photos", Node: "ace"},
|
b, err := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "oidc", Consumer: meshprovisionerclient.End{Module: "photos", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "keycloak", Node: "novox"}, State: state, Why: why, At: t0})
|
Provider: meshprovisionerclient.End{Module: "keycloak", Node: "novox"}, State: state, Why: why, At: t0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
w.Provision("ace.photos.oidc", enc(provisions.Waits, "the operator gives the client's redirect"), Put)
|
w.Provision("ace.photos.oidc", enc(meshprovisionerclient.Waits, "the operator gives the client's redirect"), Put)
|
||||||
w.Provision("ace.photos.db", enc(provisions.Provided, ""), Put)
|
w.Provision("ace.photos.db", enc(meshprovisionerclient.Provided, ""), Put)
|
||||||
if f := o.findings["module.photos.ace.needs-operator"]; !strings.Contains(f.Summary, "redirect") || f.Machine != "ace" {
|
if f := o.findings["module.photos.ace.needs-operator"]; !strings.Contains(f.Summary, "redirect") || f.Machine != "ace" {
|
||||||
t.Fatalf("findings = %v", o.findings)
|
t.Fatalf("findings = %v", o.findings)
|
||||||
}
|
}
|
||||||
w.Provision("ace.photos.oidc", enc(provisions.Provided, ""), Put)
|
w.Provision("ace.photos.oidc", enc(meshprovisionerclient.Provided, ""), Put)
|
||||||
w.Provision("ace.web.oidc", enc(provisions.Waits, "x"), Put)
|
w.Provision("ace.web.oidc", enc(meshprovisionerclient.Waits, "x"), Put)
|
||||||
w.Provision("ace.web.oidc", nil, Delete)
|
w.Provision("ace.web.oidc", nil, Delete)
|
||||||
}, map[string]string{}},
|
}, map[string]string{}},
|
||||||
{"774: a node's own report: its network, the resolver file rewritten, failed units, a relogin, a directory used as found, a login fallen back", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) {
|
{"774: a node's own report: its network, the resolver file rewritten, failed units, a relogin, a directory used as found, a login fallen back", func(t *testing.T, w *Watchman, o *fakeOut, c *clock) {
|
||||||
@@ -674,10 +674,10 @@ func TestTheWatchmansFindings(t *testing.T) {
|
|||||||
w.SetStepBound(30 * time.Minute)
|
w.SetStepBound(30 * time.Minute)
|
||||||
held, _ := meshwantsclient.EncodeWant(meshwantsclient.Want{Fp: fpOld, Self: true, Newest: fpNew, Rule: meshwantsclient.RuleCanary, Words: "the canary ace does not run it yet"})
|
held, _ := meshwantsclient.EncodeWant(meshwantsclient.Want{Fp: fpOld, Self: true, Newest: fpNew, Rule: meshwantsclient.RuleCanary, Words: "the canary ace does not run it yet"})
|
||||||
released, _ := meshwantsclient.EncodeWant(meshwantsclient.Want{Fp: fpNew, Self: true})
|
released, _ := meshwantsclient.EncodeWant(meshwantsclient.Want{Fp: fpNew, Self: true})
|
||||||
asked, _ := provisions.Encode(provisions.Provision{Provision: "oidc", Consumer: provisions.End{Module: "photos", Node: "ace"},
|
asked, _ := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "oidc", Consumer: meshprovisionerclient.End{Module: "photos", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "keycloak", Node: "novox"}, State: provisions.Asked, At: t0})
|
Provider: meshprovisionerclient.End{Module: "keycloak", Node: "novox"}, State: meshprovisionerclient.Asked, At: t0})
|
||||||
provided, _ := provisions.Encode(provisions.Provision{Provision: "oidc", Consumer: provisions.End{Module: "photos", Node: "ace"},
|
provided, _ := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "oidc", Consumer: meshprovisionerclient.End{Module: "photos", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "keycloak", Node: "novox"}, State: provisions.Provided, At: t0})
|
Provider: meshprovisionerclient.End{Module: "keycloak", Node: "novox"}, State: meshprovisionerclient.Provided, At: t0})
|
||||||
bkey, _ := builds.BuilderBuildKey("web", fpNew)
|
bkey, _ := builds.BuilderBuildKey("web", fpNew)
|
||||||
queued, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildQueued, Waits: "mesh-sdk@v0.1.14"})
|
queued, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildQueued, Waits: "mesh-sdk@v0.1.14"})
|
||||||
building, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildBuilding, By: "n1"})
|
building, _ := builds.EncodeBuilderBuild(builds.BuilderBuild{State: builds.BuildBuilding, By: "n1"})
|
||||||
@@ -685,15 +685,15 @@ func TestTheWatchmansFindings(t *testing.T) {
|
|||||||
w.Want("want.ace.web", held, Put, t0)
|
w.Want("want.ace.web", held, Put, t0)
|
||||||
w.Provision("ace.photos.oidc", asked, Put)
|
w.Provision("ace.photos.oidc", asked, Put)
|
||||||
w.Build(bkey, queued, Put, t0)
|
w.Build(bkey, queued, Put, t0)
|
||||||
waits := map[string]string{AssignerWantsBucket: "want.ace.web", provisions.ProvisionsBucket: "ace.photos.oidc", BuilderBuildsBucket: bkey}
|
waits := map[string]string{AssignerWantsBucket: "want.ace.web", meshprovisionerclient.ProvisionsBucket: "ace.photos.oidc", BuilderBuildsBucket: bkey}
|
||||||
if len(o.pulses) != 3 || len(o.findings) != 0 {
|
if len(o.pulses) != 3 || len(o.findings) != 0 {
|
||||||
t.Fatalf("pulses %v findings %v", o.pulses, o.findings)
|
t.Fatalf("pulses %v findings %v", o.pulses, o.findings)
|
||||||
}
|
}
|
||||||
// The keys are written again as their parts move on, with new words and a new time: the wait still began at t0.
|
// The keys are written again as their parts move on, with new words and a new time: the wait still began at t0.
|
||||||
c.t = c.t.Add(20 * time.Minute)
|
c.t = c.t.Add(20 * time.Minute)
|
||||||
held2, _ := meshwantsclient.EncodeWant(meshwantsclient.Want{Fp: fpOld, Self: true, Newest: fpNew, Rule: meshwantsclient.RuleCanary, Words: "the canary ace runs it, not healthy yet"})
|
held2, _ := meshwantsclient.EncodeWant(meshwantsclient.Want{Fp: fpOld, Self: true, Newest: fpNew, Rule: meshwantsclient.RuleCanary, Words: "the canary ace runs it, not healthy yet"})
|
||||||
asked2, _ := provisions.Encode(provisions.Provision{Provision: "oidc", Consumer: provisions.End{Module: "photos", Node: "ace"},
|
asked2, _ := meshprovisionerclient.Encode(meshprovisionerclient.Provision{Provision: "oidc", Consumer: meshprovisionerclient.End{Module: "photos", Node: "ace"},
|
||||||
Provider: provisions.End{Module: "keycloak", Node: "novox"}, State: provisions.Asked, Why: "the provider is applying", At: c.t})
|
Provider: meshprovisionerclient.End{Module: "keycloak", Node: "novox"}, State: meshprovisionerclient.Asked, Why: "the provider is applying", At: c.t})
|
||||||
w.Want("want.ace.web", held2, Put, c.t)
|
w.Want("want.ace.web", held2, Put, c.t)
|
||||||
w.Provision("ace.photos.oidc", asked2, Put)
|
w.Provision("ace.photos.oidc", asked2, Put)
|
||||||
w.Build(bkey, queued, Put, c.t)
|
w.Build(bkey, queued, Put, c.t)
|
||||||
|
|||||||
Reference in New Issue
Block a user