Read the seat mesh-placement's state through the sdk's PlacementKeys in mesh-conditions, mesh-config, mesh-provisioner, mesh-vault and mesh-self-check, so they read its keys per module and node and the form before alike while it is delivered (issue 774, research 072 row 37)
This commit is contained in:
@@ -216,26 +216,26 @@ func (k *Keeper) Have(key string, value []byte, deleted bool) error {
|
||||
return k.judge(node, module, "")
|
||||
}
|
||||
|
||||
// Placement takes one change of the placement: which module holds which seat on a node.
|
||||
// Placement takes one change of the placement: which module holds which seat on a node. The keys are read in either
|
||||
// form, a node key and its module keys or the form before (delivery.PlacementKeys; research 072 row 37).
|
||||
func (k *Keeper) Placement(key string, value []byte, deleted bool) {
|
||||
node, err := delivery.ParsePlacementKey(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
k.mu.Lock()
|
||||
defer k.mu.Unlock()
|
||||
k.init()
|
||||
node, err := k.placement.Put(key, value, 0, deleted)
|
||||
if node == "" {
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
k.Logf("the placement of %s is not readable as it stands, so its seats' holders are kept as last read: %v", node, err)
|
||||
}
|
||||
for hk := range k.holders {
|
||||
if strings.HasPrefix(hk, node+".") {
|
||||
delete(k.holders, hk)
|
||||
}
|
||||
}
|
||||
if deleted {
|
||||
return
|
||||
}
|
||||
p, err := delivery.DecodePlacement(value)
|
||||
if err != nil {
|
||||
k.Logf("the placement of %s is not readable, so its seats' holders are not known: %v", node, err)
|
||||
p, _, ok := k.placement.Of(node)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, h := range p.Holds {
|
||||
|
||||
@@ -113,12 +113,19 @@ func TestADeliveryHoldsItsOwnFindingsUntilItEnds(t *testing.T) {
|
||||
// A seat's finding is about the module the placement says holds the seat on that node (the lead, 2026-10-29): held
|
||||
// while the assigner is delivered on ace, though the seat is named mesh-placement.
|
||||
r := newRig()
|
||||
placed, err := delivery.EncodePlacement(delivery.Placement{Node: "ace", Modules: []delivery.PlacedModule{{Module: "mesh-delivery-assigner"}},
|
||||
// Research 072 row 37: the placement in its keys per module and node; a stale legacy key beside them is not read.
|
||||
stale, err := delivery.EncodePlacement(delivery.Placement{Node: "ace"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r.k.Placement("placement.ace", stale, false)
|
||||
placed, err := delivery.PlacementValues(delivery.Placement{Node: "ace", Modules: []delivery.PlacedModule{{Module: "mesh-delivery-assigner"}},
|
||||
Holds: []delivery.Holding{{Claim: "mesh-placement", Scope: "mesh", Module: "mesh-delivery-assigner"}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r.k.Placement("placement.ace", placed, false)
|
||||
r.k.Placement("ace.mesh-delivery-assigner", placed["ace.mesh-delivery-assigner"], false)
|
||||
r.k.Placement("ace.node", placed["ace.node"], false)
|
||||
_ = r.k.Want("want.ace.mesh-delivery-assigner", want(ctrlNext, ctrlNextComp), false)
|
||||
_ = r.k.Have("ace.mesh-delivery-assigner", have(ctrlRunning, ctrlComposed, delivery.PhaseRunning, delivery.HealthOK), false)
|
||||
seat, seatRaw := finding(t, selfCheck, health.ScopeSeat, "mesh-placement.ace", "holder-silent", "D3", health.Warning, r.now)
|
||||
|
||||
@@ -112,8 +112,10 @@ type Keeper struct {
|
||||
haves map[string]delivery.Have
|
||||
// holders are, by `<node>.<seat>`, the module the placement says holds the seat there.
|
||||
holders map[string]string
|
||||
stuck map[string]string
|
||||
held map[string]held
|
||||
// placement is the placement's keys as heard, assembled per node.
|
||||
placement *delivery.PlacementKeys
|
||||
stuck map[string]string
|
||||
held map[string]held
|
||||
// passed are the deliveries whose bound passed, by node and module, at the fingerprint wanted then; outOfHold the
|
||||
// line a key raised out of a hold says (hold.go).
|
||||
passed map[string]string
|
||||
@@ -130,6 +132,7 @@ func (k *Keeper) init() {
|
||||
map[string]string{}, map[string]held{}, map[string]clearedMemo{}
|
||||
k.takeover = health.Takeover{V: health.TakeoverVersion, Follow: health.FollowController}
|
||||
k.passed, k.outOfHold, k.holders = map[string]string{}, map[string]string{}, map[string]string{}
|
||||
k.placement = delivery.NewPlacementKeys()
|
||||
}
|
||||
if k.Now == nil {
|
||||
k.Now = time.Now
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-conditions
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030001116-2da0de75c3f0
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030001116-2da0de75c3f0 h1:lKU3HjNXGiVbLW2hUgFjU/TMTUYMlNnnmZxG5T7biQA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030001116-2da0de75c3f0/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77 h1:vMZJm3lVjq7V4SqlSMzteUokziozuoUxws8DakfbgNA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -134,34 +134,58 @@ func (m *memStore) unassign(t *testing.T, node, module string) {
|
||||
m.place(t, node, module, false)
|
||||
}
|
||||
|
||||
// place writes a node's placement as the seat writes it: its node key and module keys (research 072 row 37), and for
|
||||
// ace in the form before, `placement.ace`, which a reader still takes while the change is delivered.
|
||||
func (m *memStore) place(t *testing.T, node, module string, on bool) {
|
||||
t.Helper()
|
||||
type placed struct {
|
||||
Module string `json:"module"`
|
||||
keys := map[string][]byte{}
|
||||
for _, k := range m.keysOf(PlacementRead) {
|
||||
e, _ := m.Get(PlacementRead, k)
|
||||
keys[k] = e.Value
|
||||
}
|
||||
p := struct {
|
||||
V int `json:"v"`
|
||||
Node string `json:"node"`
|
||||
Modules []placed `json:"modules"`
|
||||
}{V: 1, Node: node}
|
||||
if e, _ := m.Get(PlacementRead, "placement."+node); e != nil {
|
||||
if err := json.Unmarshal(e.Value, &p); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
all, err := delivery.PlacementsOf(keys)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var kept []placed
|
||||
p := all[node]
|
||||
p.Node = node
|
||||
var kept []delivery.PlacedModule
|
||||
for _, x := range p.Modules {
|
||||
if x.Module != module {
|
||||
kept = append(kept, x)
|
||||
}
|
||||
}
|
||||
if on {
|
||||
kept = append(kept, placed{Module: module})
|
||||
kept = append(kept, delivery.PlacedModule{Module: module})
|
||||
}
|
||||
p.Modules = kept
|
||||
if err := m.Put(PlacementRead, "placement."+node, p); err != nil {
|
||||
for _, k := range m.keysOf(PlacementRead) {
|
||||
if n, _, _, err := delivery.ParsePlacementKey(k); err == nil && n == node {
|
||||
_ = m.Delete(PlacementRead, k)
|
||||
}
|
||||
}
|
||||
if node == "ace" {
|
||||
raw, err := delivery.EncodePlacement(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = m.Put(PlacementRead, "placement.ace", json.RawMessage(raw))
|
||||
return
|
||||
}
|
||||
values, err := delivery.PlacementValues(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for k, raw := range values {
|
||||
if err := m.Put(PlacementRead, k, json.RawMessage(raw)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *memStore) keysOf(state string) []string {
|
||||
keys, _ := m.Keys(state)
|
||||
return keys
|
||||
}
|
||||
|
||||
// manifest keeps a manifest in the indexer's manifests by its digest, as the indexer writes it, and answers the digest.
|
||||
|
||||
@@ -70,32 +70,32 @@ func (c *Config) sourcesFrom(source string) (Sources, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// readPlacement is every module the seat mesh-placement places on a node (ADR 0567 §1, §9): each node's key
|
||||
// `placement.<node>`.
|
||||
// readPlacement is every module the seat mesh-placement places on a node (ADR 0567 §1, §9), from the state's keys in
|
||||
// either form: a node key and its module keys, or the form before, `placement.<node>` (delivery.PlacementsOf;
|
||||
// research 072 row 37). By node in name order, each node's modules in the order its placement names them.
|
||||
func (c *Config) readPlacement(s *Sources) error {
|
||||
placed := map[string]bool{}
|
||||
return c.each(PlacementRead, func(key string, raw []byte) error {
|
||||
node, err := delivery.ParsePlacementKey(key)
|
||||
if err != nil {
|
||||
return nil // a key of another kind
|
||||
}
|
||||
var p struct {
|
||||
Node string `json:"node"`
|
||||
Modules []struct {
|
||||
Module string `json:"module"`
|
||||
} `json:"modules"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &p); err != nil || p.Node != node {
|
||||
return fmt.Errorf("the placement %s is not one", key)
|
||||
}
|
||||
for _, m := range p.Modules {
|
||||
if m.Module != "" && !placed[node+"."+m.Module] {
|
||||
placed[node+"."+m.Module] = true
|
||||
s.Assignments = append(s.Assignments, Assignment{Node: node, Module: m.Module})
|
||||
}
|
||||
}
|
||||
keys := map[string][]byte{}
|
||||
if err := c.each(PlacementRead, func(key string, raw []byte) error {
|
||||
keys[key] = raw
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
placements, err := delivery.PlacementsOf(keys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("the placement is not read whole: %w", err)
|
||||
}
|
||||
nodes := make([]string, 0, len(placements))
|
||||
for node := range placements {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
sort.Strings(nodes)
|
||||
for _, node := range nodes {
|
||||
for _, module := range placements[node].Assigned() {
|
||||
s.Assignments = append(s.Assignments, Assignment{Node: node, Module: module})
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readDeclarations reads each placed module's declarations from its manifests as the delivery holds them: the trunk's
|
||||
|
||||
@@ -2,7 +2,7 @@ module mesh-config
|
||||
|
||||
go 1.26.0
|
||||
|
||||
require git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030174137-a37181261c24
|
||||
require git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77
|
||||
|
||||
require (
|
||||
github.com/klauspost/compress v1.20.0 // indirect
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030174137-a37181261c24 h1:s0XXZtR7CFPBbnaDygWnE4/Q827iEFt0YfEzujk4Q9g=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030174137-a37181261c24/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77 h1:vMZJm3lVjq7V4SqlSMzteUokziozuoUxws8DakfbgNA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -903,9 +903,9 @@ func (h *Holder) put(key string, p provisions.Provision) {
|
||||
|
||||
// ---- what a change touches --------------------------------------------------------------------------------------
|
||||
|
||||
// NodesOfPlacement is the node a placement key names.
|
||||
// NodesOfPlacement is the node a placement key names, in either form (research 072 row 37).
|
||||
func NodesOfPlacement(key string) []string {
|
||||
if n, err := delivery.ParsePlacementKey(key); err == nil {
|
||||
if n, _, _, err := delivery.ParsePlacementKey(key); err == nil {
|
||||
return []string{n}
|
||||
}
|
||||
return nil
|
||||
@@ -938,25 +938,23 @@ func (h *Holder) NodesOfModule(module string) []string {
|
||||
return sortedKeys(nodes)
|
||||
}
|
||||
|
||||
// placedOn is every node a module is placed on, sorted.
|
||||
// placedOn is every node a module is placed on, sorted, from the placement's keys in either form
|
||||
// (delivery.PlacementsOf; research 072 row 37). A node whose keys do not read whole is read as they stand.
|
||||
func (h *Holder) placedOn(module string) []string {
|
||||
nodes := map[string]bool{}
|
||||
raw := map[string][]byte{}
|
||||
if keys, err := h.Store.Keys(PlacementRead); err == nil {
|
||||
for _, k := range keys {
|
||||
n, err := delivery.ParsePlacementKey(k)
|
||||
if err != nil {
|
||||
continue
|
||||
if e, err := h.Store.Get(PlacementRead, k); err == nil && e != nil {
|
||||
raw[k] = e.Value
|
||||
}
|
||||
e, err := h.Store.Get(PlacementRead, k)
|
||||
if err != nil || e == nil {
|
||||
continue
|
||||
}
|
||||
if p, err := delivery.DecodePlacement(e.Value); err == nil {
|
||||
for _, m := range p.Modules {
|
||||
if m.Module == module {
|
||||
nodes[n] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
placements, _ := delivery.PlacementsOf(raw)
|
||||
for n, p := range placements {
|
||||
for _, m := range p.Modules {
|
||||
if m.Module == module {
|
||||
nodes[n] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,17 @@ func TestAKeysStateFollowsItsProvidersOutcome(t *testing.T) {
|
||||
// A provision's credential is the vault's own provision, on the consumer's node for a login of its own, and the
|
||||
// provision depends on it (clauses 3, 6).
|
||||
c := newMesh()
|
||||
c.s.write(t, PlacementRead, "placement.novox", `{"v":1,"node":"novox","decided":{},"modules":[{"module":"mesh-vault"}]}`)
|
||||
// The placement in its keys per module and node (research 072 row 37).
|
||||
novox, err := delivery.PlacementValues(delivery.Placement{Node: "novox", Modules: []delivery.PlacedModule{{Module: "mesh-vault"}}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for k, v := range novox {
|
||||
c.s.write(t, PlacementRead, k, string(v))
|
||||
if n := NodesOfPlacement(k); !slices.Equal(n, []string{"novox"}) {
|
||||
t.Errorf("NodesOfPlacement(%q) = %v", k, n)
|
||||
}
|
||||
}
|
||||
pair := pgDB
|
||||
pair.CredentialForm = "pair"
|
||||
c.atWant["g14"] = map[string]catalogue.Plan{"gitea": planOf(pair)}
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-provisioner
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030212912-6c5a8ef893b4
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030182415-754edfae6924 h1:aIiKj066gYFEDokUOq0i2n4vsygu5g0XMKJRRaMI4fM=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030182415-754edfae6924/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030212912-6c5a8ef893b4 h1:uzXzKfjoWB8wCbAPgxUAWSArr+3DKwi8qrB3BUEOVOE=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030212912-6c5a8ef893b4/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77 h1:vMZJm3lVjq7V4SqlSMzteUokziozuoUxws8DakfbgNA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -31,29 +31,26 @@ const (
|
||||
ScopeMachine = health.ScopeMachine
|
||||
)
|
||||
|
||||
// placements is every node's placement, by node.
|
||||
// placements is every node's placement, by node, from the state's keys in either form: a node key and its module keys,
|
||||
// or the form before, `placement.<node>` (delivery.PlacementsOf; research 072 row 37).
|
||||
func (c *Checker) placements() (map[string]delivery.Placement, error) {
|
||||
keys, err := c.Store.Keys(PlacementRead)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the placement cannot be read: %w", err)
|
||||
}
|
||||
out := map[string]delivery.Placement{}
|
||||
values := map[string][]byte{}
|
||||
for _, k := range keys {
|
||||
raw, ok, err := c.Store.Get(PlacementRead, k)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the placement of %s cannot be read: %w", k, err)
|
||||
return nil, fmt.Errorf("the placement's key %s cannot be read: %w", k, err)
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
if ok {
|
||||
values[k] = raw
|
||||
}
|
||||
var p delivery.Placement
|
||||
if err := json.Unmarshal(raw, &p); err != nil {
|
||||
return nil, fmt.Errorf("the placement of %s is not readable: %w", k, err)
|
||||
}
|
||||
if p.Node == "" {
|
||||
p.Node = k
|
||||
}
|
||||
out[p.Node] = p
|
||||
}
|
||||
out, err := delivery.PlacementsOf(values)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the placement is not readable: %w", err)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -260,8 +260,12 @@ func machines() *memStore {
|
||||
node, address, endpoint string
|
||||
online bool
|
||||
}{{"novox", "10.10.0.1/16", "203.0.113.5:51820", true}, {"ace", "10.10.0.2/16", "", true}, {"g14", "10.10.0.3/16", "", false}} {
|
||||
_ = s.Put(PlacementRead, p.node, delivery.Placement{V: 1, Node: p.node,
|
||||
Decided: delivery.NodeDecided{Address: p.address, Endpoint: p.endpoint, Hub: p.endpoint != ""}})
|
||||
pl := delivery.Placement{V: 1, Node: p.node,
|
||||
Decided: delivery.NodeDecided{Address: p.address, Endpoint: p.endpoint, Hub: p.endpoint != ""}}
|
||||
if p.node == "ace" {
|
||||
pl.Modules = []delivery.PlacedModule{{Module: "sshd"}} // a module key beside the node key
|
||||
}
|
||||
place(s, pl)
|
||||
_ = s.Put(PresenceRead, p.node, delivery.Presence{V: 1, Online: p.online})
|
||||
key, _ := delivery.SeatHoldersKey(BannedSeat, p.node)
|
||||
_ = s.Put(SeatHoldersRead, key, delivery.SeatHolders{V: 1, Seat: BannedSeat, Scope: "node", Node: p.node,
|
||||
@@ -270,6 +274,31 @@ func machines() *memStore {
|
||||
return s
|
||||
}
|
||||
|
||||
// place writes a node's placement as the seat does, its node key and a key per module (research 072 row 37); g14's in
|
||||
// the form before, `placement.g14`, which the probes still read while the change is delivered.
|
||||
func place(s *memStore, p delivery.Placement) {
|
||||
if p.Node == "g14" {
|
||||
raw, _ := delivery.EncodePlacement(p)
|
||||
_ = s.Put(PlacementRead, "placement.g14", json.RawMessage(raw))
|
||||
return
|
||||
}
|
||||
values, _ := delivery.PlacementValues(p)
|
||||
for k, raw := range values {
|
||||
_ = s.Put(PlacementRead, k, json.RawMessage(raw))
|
||||
}
|
||||
}
|
||||
|
||||
// placed is every node's placement the store holds.
|
||||
func placed(s *memStore) map[string]delivery.Placement {
|
||||
keys, _ := s.Keys(PlacementRead)
|
||||
values := map[string][]byte{}
|
||||
for _, k := range keys {
|
||||
values[k], _, _ = s.Get(PlacementRead, k)
|
||||
}
|
||||
out, _ := delivery.PlacementsOf(values)
|
||||
return out
|
||||
}
|
||||
|
||||
// filling is a store holding the self-check's written fill finding of a stream: the condition open.
|
||||
func filling(stream string) *memStore {
|
||||
s := newStore()
|
||||
@@ -285,11 +314,9 @@ func filling(stream string) *memStore {
|
||||
func agents(verdicts map[string]string) *memStore {
|
||||
s := machines()
|
||||
for node, v := range verdicts {
|
||||
raw, _, _ := s.Get(PlacementRead, node)
|
||||
var p delivery.Placement
|
||||
_ = json.Unmarshal(raw, &p)
|
||||
p := placed(s)[node]
|
||||
p.Decided.AgentAccount = "agent"
|
||||
_ = s.Put(PlacementRead, node, p)
|
||||
place(s, p)
|
||||
h := delivery.NodeHealth{V: 1, Node: node, Contract: 13}
|
||||
switch v {
|
||||
case "":
|
||||
@@ -303,7 +330,7 @@ func agents(verdicts map[string]string) *memStore {
|
||||
h.Root = []delivery.RootVerdict{{Account: "agent", Module: "claude-code", Resource: "claude-code.agent", State: v,
|
||||
Reason: "can become root without a person: a sudo rule"}}
|
||||
}
|
||||
raw, _ = delivery.EncodeNodeHealth(h)
|
||||
raw, _ := delivery.EncodeNodeHealth(h)
|
||||
_ = s.Put(HealthRead, node, json.RawMessage(raw))
|
||||
}
|
||||
return s
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-self-check
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030001116-2da0de75c3f0
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030001116-2da0de75c3f0 h1:lKU3HjNXGiVbLW2hUgFjU/TMTUYMlNnnmZxG5T7biQA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030001116-2da0de75c3f0/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77 h1:vMZJm3lVjq7V4SqlSMzteUokziozuoUxws8DakfbgNA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -25,7 +25,8 @@ type PlacementReader struct {
|
||||
Read func(key string) ([]byte, error)
|
||||
}
|
||||
|
||||
// placements is every node's placement, by node; none when the vault reads no placement.
|
||||
// placements is every node's placement, by node, from the state's keys in either form (delivery.PlacementsOf; research
|
||||
// 072 row 37); none when the vault reads no placement. A node whose keys do not read whole is read as they stand.
|
||||
func (v *Vault) placements() (map[string]delivery.Placement, error) {
|
||||
out := map[string]delivery.Placement{}
|
||||
if v.Placement.Keys == nil || v.Placement.Read == nil {
|
||||
@@ -35,52 +36,73 @@ func (v *Vault) placements() (map[string]delivery.Placement, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the placement's keys could not be read: %w", err)
|
||||
}
|
||||
values := map[string][]byte{}
|
||||
for _, k := range keys {
|
||||
node, err := delivery.ParsePlacementKey(k)
|
||||
if err != nil {
|
||||
if _, _, _, err := delivery.ParsePlacementKey(k); err != nil {
|
||||
continue
|
||||
}
|
||||
raw, err := v.Placement.Read(k)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the placement of %s could not be read: %w", node, err)
|
||||
return nil, fmt.Errorf("the placement's key %s could not be read: %w", k, err)
|
||||
}
|
||||
if raw == nil {
|
||||
continue
|
||||
if raw != nil {
|
||||
values[k] = raw
|
||||
}
|
||||
p, err := delivery.DecodePlacement(raw)
|
||||
if err != nil || p.Node != node {
|
||||
continue
|
||||
}
|
||||
out[node] = p
|
||||
}
|
||||
out, _ = delivery.PlacementsOf(values)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// nodePlaced is what node's own key of the placement says: the modules placed there and what a person decided of it,
|
||||
// read from its node key `<node>.node` alone (which names every module placed, research 072 row 37), or, for a node not
|
||||
// converted yet, from its key in the form before, `placement.<node>`. found is false when it has neither.
|
||||
func (v *Vault) nodePlaced(node string) (modules []string, decided delivery.NodeDecided, found bool, err error) {
|
||||
key, err := delivery.PlacementNodeKey(node)
|
||||
if err != nil {
|
||||
return nil, decided, false, err
|
||||
}
|
||||
raw, err := v.Placement.Read(key)
|
||||
if err != nil {
|
||||
return nil, decided, false, err
|
||||
}
|
||||
if raw != nil {
|
||||
n, err := delivery.DecodePlacementNode(raw)
|
||||
if err != nil {
|
||||
return nil, decided, false, fmt.Errorf("the placement of %s is not readable: %w", node, err)
|
||||
}
|
||||
for _, r := range n.Modules {
|
||||
modules = append(modules, r.Module)
|
||||
}
|
||||
return modules, n.Decided, true, nil
|
||||
}
|
||||
legacy, err := delivery.LegacyPlacementKey(node)
|
||||
if err != nil {
|
||||
return nil, decided, false, err
|
||||
}
|
||||
if raw, err = v.Placement.Read(legacy); err != nil || raw == nil {
|
||||
return nil, decided, false, err
|
||||
}
|
||||
p, err := delivery.DecodePlacement(raw)
|
||||
if err != nil {
|
||||
return nil, decided, false, fmt.Errorf("the placement of %s is not readable: %w", node, err)
|
||||
}
|
||||
return p.Assigned(), p.Decided, true, nil
|
||||
}
|
||||
|
||||
// placedOn says module is placed on node by the catalogue.
|
||||
func (v *Vault) placedOn(node, module string) (bool, error) {
|
||||
placed, err := v.placedModules(node)
|
||||
return slices.Contains(placed, module), err
|
||||
}
|
||||
|
||||
// placedModules is every module the catalogue places on node, read from the node's one key of the placement; none when
|
||||
// the vault reads no placement or the node has no key.
|
||||
// placedModules is every module the catalogue places on node, read from the node's own key of the placement
|
||||
// (nodePlaced); none when the vault reads no placement or the node has no key.
|
||||
func (v *Vault) placedModules(node string) ([]string, error) {
|
||||
if v.Placement.Read == nil {
|
||||
return nil, nil
|
||||
}
|
||||
key, err := delivery.PlacementKey(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
raw, err := v.Placement.Read(key)
|
||||
if err != nil || raw == nil {
|
||||
return nil, err
|
||||
}
|
||||
p, err := delivery.DecodePlacement(raw)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("the placement of %s is not readable: %w", node, err)
|
||||
}
|
||||
return p.Assigned(), nil
|
||||
modules, _, _, err := v.nodePlaced(node)
|
||||
return modules, err
|
||||
}
|
||||
|
||||
// standsOn says module stands on node: placed there, or assigned there while the assignments stand. A read that fails is
|
||||
|
||||
@@ -16,12 +16,14 @@ func placementsOf(t *testing.T, nodes map[string][]string) PlacementReader {
|
||||
for _, m := range modules {
|
||||
p.Modules = append(p.Modules, delivery.PlacedModule{Module: m})
|
||||
}
|
||||
raw, err := delivery.EncodePlacement(p)
|
||||
// Research 072 row 37: the node key and a key per module.
|
||||
kv, err := delivery.PlacementValues(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
key, _ := delivery.PlacementKey(node)
|
||||
values[key] = raw
|
||||
for k, raw := range kv {
|
||||
values[k] = raw
|
||||
}
|
||||
}
|
||||
return PlacementReader{
|
||||
Keys: func() ([]string, error) {
|
||||
|
||||
@@ -303,22 +303,14 @@ func (v *Vault) internalName(node string) (string, error) {
|
||||
if v.Placement.Read == nil {
|
||||
return "", errors.New("the vault reads no placement, so it cannot tell a node's internal name")
|
||||
}
|
||||
key, err := delivery.PlacementKey(node)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
raw, err := v.Placement.Read(key)
|
||||
_, decided, found, err := v.nodePlaced(node)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf(notYetPrefix+"the placement of %s could not be read: %w", node, err)
|
||||
}
|
||||
if raw == nil {
|
||||
if !found {
|
||||
return "", fmt.Errorf("%s has no placement of the seat mesh-placement, so it has no name inside the mesh", node)
|
||||
}
|
||||
p, err := delivery.DecodePlacement(raw)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("the placement of %s is not readable: %w", node, err)
|
||||
}
|
||||
if p.Decided.Address == "" {
|
||||
if decided.Address == "" {
|
||||
return "", fmt.Errorf("%s is not on the private network (its placement names no address), so it has no name inside the mesh to be certified for", node)
|
||||
}
|
||||
return overlay.InternalName(node), nil
|
||||
|
||||
@@ -40,16 +40,21 @@ func TestTheVaultSigns(t *testing.T) {
|
||||
"g14": {Node: "g14", Decided: delivery.NodeDecided{Address: "10.77.0.4"}},
|
||||
"plain": {Node: "plain"},
|
||||
}
|
||||
// Research 072 row 37: ace and plain in their keys per module and node, g14 still in the form before.
|
||||
v.Placement = PlacementReader{Read: func(key string) ([]byte, error) {
|
||||
node, err := delivery.ParsePlacementKey(key)
|
||||
node, _, kind, err := delivery.ParsePlacementKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, ok := placements[node]
|
||||
if !ok {
|
||||
if !ok || (node == "g14") != (kind == delivery.PlacementLegacyKind) {
|
||||
return nil, nil
|
||||
}
|
||||
return delivery.EncodePlacement(p)
|
||||
if kind == delivery.PlacementLegacyKind {
|
||||
return delivery.EncodePlacement(p)
|
||||
}
|
||||
values, err := delivery.PlacementValues(p)
|
||||
return values[key], err
|
||||
}}
|
||||
records := map[string]string{"ace": base64.StdEncoding.EncodeToString(servingPub), "plain": base64.StdEncoding.EncodeToString(servingPub)}
|
||||
v.Haves = func(key string) ([]byte, error) {
|
||||
|
||||
@@ -3,7 +3,7 @@ module mesh-vault
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030225009-17fc9b9b8115
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77
|
||||
github.com/nats-io/nats-server/v2 v2.11.17
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
golang.org/x/crypto v0.57.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030225009-17fc9b9b8115 h1:ezKg8aAKQoZ5XEAWQQVk4y/x0h2qC73GcUKBmbqY5jw=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261030225009-17fc9b9b8115/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77 h1:vMZJm3lVjq7V4SqlSMzteUokziozuoUxws8DakfbgNA=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031082617-a320f8e2cd77/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
Reference in New Issue
Block a user