From 84a7639042a74d7cbc9085f6f6515896b538c506 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 15:52:59 +0100 Subject: [PATCH] =?UTF-8?q?mesh-config=20reads=20the=20placement,=20wants,?= =?UTF-8?q?=20haves,=20modules,=20manifests,=20predefined=20list=20and=20c?= =?UTF-8?q?onfig=20candidates=20through=20the=20seats'=20types=20and=20cli?= =?UTF-8?q?ents,=20the=20builder's=20builds=20through=20its=20published=20?= =?UTF-8?q?package;=20the=20kept=20value=20is=20its=20own=20layout=20(B5f;?= =?UTF-8?q?=20ADR=200634=20=C2=A71,=20=C2=A74;=20issue=201966)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i --- .../cmd/mesh-config/config_test.go | 25 ++++++++------ .../mesh-config/cmd/mesh-config/delivery.go | 10 +++--- .../cmd/mesh-config/manifest_test.go | 15 +++++--- .../mesh-config/cmd/mesh-config/ownerviews.go | 14 ++++---- modules/mesh-config/cmd/mesh-config/pulls.go | 31 +++++++++++------ .../mesh-config/cmd/mesh-config/readers.go | 23 +++++++++++++ .../mesh-config/cmd/mesh-config/resolve.go | 15 ++++---- .../mesh-config/cmd/mesh-config/sources.go | 19 ++++++----- .../mesh-config/cmd/mesh-config/takeover.go | 33 ++++++++++++------ .../cmd/mesh-config/takeover_test.go | 9 +++-- .../cmd/mesh-config/whole_integration_test.go | 34 ++++++++++++------- modules/mesh-config/go.mod | 7 ++++ modules/mesh-config/module.json | 3 ++ 13 files changed, 156 insertions(+), 82 deletions(-) create mode 100644 modules/mesh-config/cmd/mesh-config/readers.go diff --git a/modules/mesh-config/cmd/mesh-config/config_test.go b/modules/mesh-config/cmd/mesh-config/config_test.go index 9888a750c..12e0a438f 100644 --- a/modules/mesh-config/cmd/mesh-config/config_test.go +++ b/modules/mesh-config/cmd/mesh-config/config_test.go @@ -4,13 +4,16 @@ import ( "encoding/json" "errors" "fmt" + assignerclient "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" + meshseat "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" + catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" + builds "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "sort" "strings" "sync" "testing" "time" - - "git.novox.be/novox/mesh-sdk/go/delivery" ) // memStore is the bus as mesh-config reaches it, in memory: its states and the mirrors it reads, its history log, @@ -167,36 +170,36 @@ func (m *memStore) place(t *testing.T, node, module string, on bool) { e, _ := m.Get(PlacementRead, k) keys[k] = e.Value } - all, err := delivery.PlacementsOf(keys) + all, err := assignerclient.PlacementsOf(keys) if err != nil { t.Fatal(err) } p := all[node] p.Node = node - var kept []delivery.PlacedModule + var kept []meshseat.PlacedModule for _, x := range p.Modules { if x.Module != module { kept = append(kept, x) } } if on { - kept = append(kept, delivery.PlacedModule{Module: module}) + kept = append(kept, meshseat.PlacedModule{Module: module}) } p.Modules = kept for _, k := range m.keysOf(PlacementRead) { - if n, _, _, err := delivery.ParsePlacementKey(k); err == nil && n == node { + if n, _, _, err := assignerclient.ParseKey(k); err == nil && n == node { _ = m.Delete(PlacementRead, k) } } if node == "ace" { - raw, err := delivery.EncodePlacement(p) + raw, err := assignerclient.EncodePlacement(p) if err != nil { t.Fatal(err) } _ = m.Put(PlacementRead, "placement.ace", json.RawMessage(raw)) return } - values, err := delivery.PlacementValues(p) + values, err := assignerclient.PlacementValues(p) if err != nil { t.Fatal(err) } @@ -218,8 +221,8 @@ func (m *memStore) manifest(t *testing.T, module, raw string) string { if !json.Valid([]byte(raw)) { t.Fatalf("not JSON: %s", raw) } - digest := delivery.ManifestDigest([]byte(raw)) - value, err := delivery.EncodeManifest(delivery.Manifest{Module: module, JSON: raw}) + digest := catalogclient.ManifestDigest([]byte(raw)) + value, err := catalogclient.EncodeManifest(catalog.ManifestsByDigestValue{Module: module, Manifest: raw}) if err != nil { t.Fatal(err) } @@ -239,7 +242,7 @@ func (m *memStore) declare(t *testing.T, module, raw string) { func (m *memStore) want(t *testing.T, node, module, fp, raw string) { t.Helper() digest := m.manifest(t, module, raw) - key, err := delivery.BuilderBuildKey(module, fp) + key, err := builds.BuilderBuildKey(module, fp) if err != nil { t.Fatal(err) } diff --git a/modules/mesh-config/cmd/mesh-config/delivery.go b/modules/mesh-config/cmd/mesh-config/delivery.go index 8da6f8b7e..9aa2b9bc0 100644 --- a/modules/mesh-config/cmd/mesh-config/delivery.go +++ b/modules/mesh-config/cmd/mesh-config/delivery.go @@ -6,10 +6,10 @@ package main import ( "encoding/json" "fmt" + engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient" "strings" "git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient" - "git.novox.be/novox/mesh-sdk/go/delivery" ) // The addresses asked. @@ -46,7 +46,7 @@ func (d toolDelivery) Have(node, module string) (string, bool, error) { if err := json.Unmarshal(answer, &kept); err != nil { return "", false, fmt.Errorf("node_haves answered what is not its listing: %s", output) } - key, err := delivery.HaveKey(node, module) + key, err := engineclient.HaveKey(node, module) if err != nil { return "", false, err } @@ -54,11 +54,11 @@ func (d toolDelivery) Have(node, module string) (string, bool, error) { if !ok { return "", false, nil } - var h delivery.Have - if err := json.Unmarshal(have, &h); err != nil { + h, err := engineclient.DecodeHave(have) + if err != nil { return "", false, fmt.Errorf("the have of %s on %s is not readable: %w", module, node, err) } - return h.FP, true, nil + return h.Fp, true, nil } // Reads asks a node's node-engine what it reads; an answer means it states it. diff --git a/modules/mesh-config/cmd/mesh-config/manifest_test.go b/modules/mesh-config/cmd/mesh-config/manifest_test.go index 0c14a2267..0950206f0 100644 --- a/modules/mesh-config/cmd/mesh-config/manifest_test.go +++ b/modules/mesh-config/cmd/mesh-config/manifest_test.go @@ -19,11 +19,12 @@ func TestEveryStateAndActHasItsTool(t *testing.T) { t.Fatal(err) } var m struct { - State []string `json:"state"` - Logs []string `json:"logs"` - Reads []string `json:"reads"` - Tools []string `json:"tools"` - Claims []struct { + State []string `json:"state"` + Packages map[string]string `json:"packages"` + Logs []string `json:"logs"` + Reads []string `json:"reads"` + Tools []string `json:"tools"` + Claims []struct { Name string `json:"name"` Serves []string `json:"serves"` } `json:"claims"` @@ -31,6 +32,10 @@ func TestEveryStateAndActHasItsTool(t *testing.T) { if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } + // The builder's keys are read through its published package, taken by its series (ADR 0634 §1). + if m.Packages["builds"] != "0.1" { + t.Errorf("packages %v: want builds of series 0.1", m.Packages) + } via := map[string]string{ ValuesState: "config list", ResolvedState: "config list", PredefinedState: "config list", ProposalsState: "config proposals", PullsState: "config list", KeptState: "config list", HistoryLog: "config history", diff --git a/modules/mesh-config/cmd/mesh-config/ownerviews.go b/modules/mesh-config/cmd/mesh-config/ownerviews.go index f220d52a9..1c1988279 100644 --- a/modules/mesh-config/cmd/mesh-config/ownerviews.go +++ b/modules/mesh-config/cmd/mesh-config/ownerviews.go @@ -15,12 +15,12 @@ import ( "encoding/json" "errors" "fmt" + catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" "sort" "strings" "time" stdio "git.novox.be/novox/mesh-sdk/go" - "git.novox.be/novox/mesh-sdk/go/delivery" "git.novox.be/novox/mesh-sdk/go/views" ) @@ -41,12 +41,12 @@ const ( // followed is each state read through its owner: the `.` name this module's code uses, the owner, its // state and its tool. var followed = []struct{ Read, Owner, State, Tool string }{ - {ModulesRead, delivery.IndexerModule, "modules", IndexerModulesTool}, - {ManifestsRead, delivery.IndexerModule, "manifests", IndexerManifestsTool}, - {IndexerPredefinedRead, delivery.IndexerModule, delivery.IndexerPredefinedState, IndexerPredefTool}, - {CandidatesRead, delivery.IndexerModule, delivery.IndexerConfigCandidatesState, IndexerCandidatesTool}, - {PlacementRead, delivery.AssignerModule, "placement", AssignerPlacementTool}, - {WantsRead, delivery.AssignerModule, "wants", AssignerWantsTool}, + {ModulesRead, indexerModule, "modules", IndexerModulesTool}, + {ManifestsRead, indexerModule, "manifests", IndexerManifestsTool}, + {IndexerPredefinedRead, indexerModule, catalog.StatePredefined, IndexerPredefTool}, + {CandidatesRead, indexerModule, catalog.StateConfigCandidates, IndexerCandidatesTool}, + {PlacementRead, assignerModule, "placement", AssignerPlacementTool}, + {WantsRead, assignerModule, "wants", AssignerWantsTool}, } // ownerViews are the pictures, by the read name. diff --git a/modules/mesh-config/cmd/mesh-config/pulls.go b/modules/mesh-config/cmd/mesh-config/pulls.go index 22849bd89..283d99270 100644 --- a/modules/mesh-config/cmd/mesh-config/pulls.go +++ b/modules/mesh-config/cmd/mesh-config/pulls.go @@ -10,8 +10,6 @@ import ( "strconv" "strings" "time" - - "git.novox.be/novox/mesh-sdk/go/delivery" ) // A config value held for the open pull request that introduces its key (novox/hq ADR 0502, issue 1826). @@ -63,16 +61,29 @@ type PullDecl struct { At time.Time `json:"at"` } -// KeptValue is an approved held value, kept apart from the values mesh-config resolves: mesh-sdk's layout, which the -// checker and the assigner's composition check read (novox/hq ADR 0565 §5). -type KeptValue = delivery.KeptValue +// KeptValue is an approved held value, kept apart from the values mesh-config resolves, in this module's own layout +// (the owner's: its state `kept`), which the checker and the assigner's composition check read (novox/hq ADR 0565 §5). +type KeptValue struct { + Pull string `json:"pull"` + Head string `json:"head"` + Digest string `json:"declaration"` + Node string `json:"node"` + Module string `json:"module"` + Key string `json:"key"` + // Value is the value held, as the operator approved it. + Value json.RawMessage `json:"value"` + By string `json:"by"` + Via string `json:"via"` + Why string `json:"why"` + // Approved is who approved it, as the proposal kept it. + Approved string `json:"approved"` + Proposal string `json:"proposal"` + At time.Time `json:"at"` +} -// keptKey is a held value's key in `kept` (delivery.HeldValueKey), the pull request's key form kept for one that is -// not one. +// keptKey is a held value's key in `kept`: the pull request's key form (pullKey), the node, the module and the config +// key, joined by dots. func keptKey(pull, node, module, key string) string { - if k, err := delivery.HeldValueKey(pull, node, module, key); err == nil { - return k - } return pullKey(pull) + "." + node + "." + module + "." + key } diff --git a/modules/mesh-config/cmd/mesh-config/readers.go b/modules/mesh-config/cmd/mesh-config/readers.go new file mode 100644 index 000000000..328303a45 --- /dev/null +++ b/modules/mesh-config/cmd/mesh-config/readers.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + meshwants "git.novox.be/novox/mesh-contracts/placement/go/seats/meshwants" +) + +// The holders whose states this module reads, one constant each (a reader names its holder once; ADR 0634 §4). +const ( + assignerModule = "mesh-delivery-assigner" + indexerModule = "mesh-delivery-indexer" +) + +// parseWantKey reads a want's key, `want..`; the want of a node's own and a held fingerprint's key are +// not one. +func parseWantKey(key string) (node, module string, err error) { + node, module, ok := meshwants.ParseWantsByWantNodeModuleKey(key) + if !ok { + return "", "", fmt.Errorf("%q is not the key of a module's want on a node", key) + } + return node, module, nil +} diff --git a/modules/mesh-config/cmd/mesh-config/resolve.go b/modules/mesh-config/cmd/mesh-config/resolve.go index bc00f098c..8d9ef1e60 100644 --- a/modules/mesh-config/cmd/mesh-config/resolve.go +++ b/modules/mesh-config/cmd/mesh-config/resolve.go @@ -3,11 +3,12 @@ package main import ( "encoding/json" "fmt" + meshseat "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" + builds "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "sort" "strings" "time" - - "git.novox.be/novox/mesh-sdk/go/delivery" ) // The four sources (novox/hq ADR 0348 §2, §3, §9): a module's value on a node resolves, the most specific winning, @@ -25,15 +26,15 @@ const ( // PlacementRead is the seat mesh-module-assigner's state, held by the assigner (novox/hq ADR 0567 §1, §8): each // node's key `placement.` with the modules placed there. It is the one source of which module runs where // (issue 1953): the controller's assignments are no longer read. - PlacementRead = delivery.PlacementRead + PlacementRead = (assignerModule + "." + meshseat.StatePlacement) // WantsRead is the assigner's wants, `want..`: the build each node is to run (ADR 0539 §1). - WantsRead = delivery.AssignerModule + ".wants" + WantsRead = assignerModule + ".wants" // BuildsRead is the builder's builds, `.`: each build's manifest digest (ADR 0525). - BuildsRead = delivery.BuilderModule + ".builds" + BuildsRead = builds.BuilderModule + ".builds" // ModulesRead is the indexer's modules, ``: the trunk's manifest digest of each module, from whichever // repository holds it (ADR 0437 §5, ADR 0478 §9); ManifestsRead its manifests by digest (ADR 0429 §16). - ModulesRead = delivery.IndexerModule + ".modules" - ManifestsRead = delivery.IndexerModule + ".manifests" + ModulesRead = indexerModule + "." + catalog.StateModules + ManifestsRead = indexerModule + "." + catalog.StateManifests // HistoryLog is the log of every set and clear, with the proven caller and why (ADR 0348 §9). HistoryLog = "history" diff --git a/modules/mesh-config/cmd/mesh-config/sources.go b/modules/mesh-config/cmd/mesh-config/sources.go index c70c04001..a7feae520 100644 --- a/modules/mesh-config/cmd/mesh-config/sources.go +++ b/modules/mesh-config/cmd/mesh-config/sources.go @@ -4,10 +4,11 @@ import ( "encoding/json" "errors" "fmt" + assignerclient "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" + catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" + builds "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "sort" "strings" - - "git.novox.be/novox/mesh-sdk/go/delivery" ) // Reading the sources, writing the resolved values, and publishing the list of predefined keys. @@ -64,7 +65,7 @@ func (c *Config) sources() (Sources, error) { } // readPlacement is every module the seat mesh-module-assigner 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.` (delivery.PlacementsOf; +// either form: a node key and its module keys, or the form before, `placement.` (assignerclient.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 { keys := map[string][]byte{} @@ -74,7 +75,7 @@ func (c *Config) readPlacement(s *Sources) error { }); err != nil { return err } - placements, err := delivery.PlacementsOf(keys) + placements, err := assignerclient.PlacementsOf(keys) if err != nil { return fmt.Errorf("the placement is not read whole: %w", err) } @@ -84,7 +85,7 @@ func (c *Config) readPlacement(s *Sources) error { } sort.Strings(nodes) for _, node := range nodes { - for _, module := range placements[node].Assigned() { + for _, module := range assignerclient.Assigned(placements[node]) { s.Assignments = append(s.Assignments, Assignment{Node: node, Module: module}) } } @@ -100,7 +101,7 @@ func (c *Config) readPlacement(s *Sources) error { func (c *Config) readDeclarations(s *Sources) error { wanted := map[string]string{} // . → the fingerprint its want names if err := c.each(WantsRead, func(key string, raw []byte) error { - node, module, err := delivery.ParseWantKey(key) + node, module, err := parseWantKey(key) if err != nil { return nil // a held key or a node's own want } @@ -188,7 +189,7 @@ func modulesOf(as []Assignment) []string { // trunkDeclarations is a module's declarations at the trunk: the manifest the indexer's `modules.` names. func (c *Config) trunkDeclarations(module string) (ModuleDeclarations, error) { - key, err := delivery.ModulesKey(module) + key, err := catalogclient.ModulesKey(module) if err != nil { return ModuleDeclarations{}, err } @@ -210,7 +211,7 @@ func (c *Config) trunkDeclarations(module string) (ModuleDeclarations, error) { // builtDeclarations is a module's declarations at a build: the manifest the builder's done key names. func (c *Config) builtDeclarations(module, fp string) (ModuleDeclarations, error) { - key, err := delivery.BuilderBuildKey(module, fp) + key, err := builds.BuilderBuildKey(module, fp) if err != nil { return ModuleDeclarations{}, err } @@ -239,7 +240,7 @@ func (c *Config) manifestDeclarations(module, digest string) (ModuleDeclarations if ok { return d, nil } - key, err := delivery.ManifestsKey(digest) + key, err := catalogclient.ManifestsKey(digest) if err != nil { return ModuleDeclarations{}, err } diff --git a/modules/mesh-config/cmd/mesh-config/takeover.go b/modules/mesh-config/cmd/mesh-config/takeover.go index 26ca344bb..c616b929b 100644 --- a/modules/mesh-config/cmd/mesh-config/takeover.go +++ b/modules/mesh-config/cmd/mesh-config/takeover.go @@ -13,8 +13,9 @@ import ( "encoding/json" "errors" "fmt" - - "git.novox.be/novox/mesh-sdk/go/delivery" + catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" + catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" + "time" ) // The states and reads. @@ -23,8 +24,8 @@ const ( DeclaredState = "declared" // IndexerPredefinedRead and CandidatesRead are the indexer's states (ADR 0565 §2). - IndexerPredefinedRead = delivery.IndexerModule + "." + delivery.IndexerPredefinedState - CandidatesRead = delivery.IndexerModule + "." + delivery.IndexerConfigCandidatesState + IndexerPredefinedRead = indexerModule + "." + catalog.StatePredefined + CandidatesRead = indexerModule + "." + catalog.StateConfigCandidates ) // SourceIndexer is the one source of a pull request's config and of the predefined list: the indexer's. @@ -54,7 +55,7 @@ type DeclaredKept struct { // trunkKept is a module's declarations at the trunk with the manifest they come from. func (c *Config) trunkKept(module string) (DeclaredKept, error) { - key, err := delivery.ModulesKey(module) + key, err := catalogclient.ModulesKey(module) if err != nil { return DeclaredKept{}, err } @@ -119,16 +120,20 @@ func (c *Config) writeDeclared(s Sources) ([]string, error) { // indexerList is the indexer's predefined list as the mirror's list holds one: the keys, and the commit. func (c *Config) indexerList() (PredefinedList, bool, error) { - e, err := c.Store.Get(IndexerPredefinedRead, delivery.PredefinedListKey) + e, err := c.Store.Get(IndexerPredefinedRead, catalog.PredefinedByListKey()) if err != nil || e == nil { return PredefinedList{}, false, err } - var kept delivery.PredefinedKept + var kept catalog.PredefinedByListValue if err := json.Unmarshal(e.Value, &kept); err != nil { return PredefinedList{}, false, fmt.Errorf("the indexer's predefined list is not one: %w", err) } list := PredefinedList{Keys: map[string]PredefinedKey{}, Commit: kept.Commit} - if err := json.Unmarshal(kept.List, &list.Keys); err != nil { + listed, err := json.Marshal(kept.List) + if err == nil { + err = json.Unmarshal(listed, &list.Keys) + } + if err != nil { return PredefinedList{}, false, fmt.Errorf("the indexer's predefined list is not predefined.json: %w", err) } return list, true, nil @@ -138,11 +143,11 @@ func (c *Config) indexerList() (PredefinedList, bool, error) { func (c *Config) candidates() (map[string]PullDecl, error) { out := map[string]PullDecl{} err := c.each(CandidatesRead, func(key string, raw []byte) error { - var cand delivery.ConfigCandidate + var cand catalog.ConfigCandidatesByPullValue if err := json.Unmarshal(raw, &cand); err != nil || cand.Pull == "" { return fmt.Errorf("the indexer's config candidate %s is not one", key) } - p := PullDecl{Pull: cand.Pull, Head: cand.Head, Declares: map[string]map[string]Declaration{}, At: cand.At} + p := PullDecl{Pull: cand.Pull, Head: cand.Head, Declares: map[string]map[string]Declaration{}, At: timeOf(cand.At)} for module, keys := range cand.Declares { raw, _ := json.Marshal(keys) var d map[string]Declaration @@ -242,3 +247,11 @@ func (c *Config) Resync() (any, error) { } return out, nil } + +// timeOf is an optional time of a seat's value as a time, the zero time when it is absent. +func timeOf(t *time.Time) time.Time { + if t == nil { + return time.Time{} + } + return *t +} diff --git a/modules/mesh-config/cmd/mesh-config/takeover_test.go b/modules/mesh-config/cmd/mesh-config/takeover_test.go index f0c0bbad0..223488219 100644 --- a/modules/mesh-config/cmd/mesh-config/takeover_test.go +++ b/modules/mesh-config/cmd/mesh-config/takeover_test.go @@ -2,10 +2,9 @@ package main import ( "encoding/json" + catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" "strings" "testing" - - "git.novox.be/novox/mesh-sdk/go/delivery" ) // The trunk's manifests aMesh declares. @@ -30,14 +29,14 @@ func anAgreeingMesh(t *testing.T) (*Config, *memStore, *standIn) { // indexerList is the indexer's `predefined.list` at a commit. func indexerList(t *testing.T, m *memStore, commit, list string) { t.Helper() - raw, _ := json.Marshal(delivery.PredefinedKept{V: 1, Commit: commit, List: json.RawMessage(list)}) - m.mirror(t, IndexerPredefinedRead, delivery.PredefinedListKey, string(raw)) + raw, _ := json.Marshal(catalog.PredefinedByListValue{V: 1, Commit: commit, List: json.RawMessage(list)}) + m.mirror(t, IndexerPredefinedRead, catalog.PredefinedByListKey(), string(raw)) } // candidate is the indexer's config candidate of a pull request. func candidate(t *testing.T, m *memStore, pull, head, declares string) { t.Helper() - key, err := delivery.ConfigCandidateKey(pull) + key, err := catalog.ConfigCandidatesByPullKey(pullKey(pull)), error(nil) if err != nil { t.Fatal(err) } diff --git a/modules/mesh-config/cmd/mesh-config/whole_integration_test.go b/modules/mesh-config/cmd/mesh-config/whole_integration_test.go index 9b29419bf..c7ebe4c72 100644 --- a/modules/mesh-config/cmd/mesh-config/whole_integration_test.go +++ b/modules/mesh-config/cmd/mesh-config/whole_integration_test.go @@ -18,6 +18,13 @@ import ( "encoding/json" "errors" "fmt" + engineclient "git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient" + nodeengine "git.novox.be/novox/mesh-contracts/go/seats/nodeengine" + assignerclient "git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient" + meshseat "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner" + catalogclient "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient" + catalog "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog" + builds "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds" "io" "os" "os/exec" @@ -35,7 +42,6 @@ import ( meshconditions "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions" oc "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel" "git.novox.be/novox/mesh-sdk/go/catalogue" - "git.novox.be/novox/mesh-sdk/go/delivery" "git.novox.be/novox/mesh-sdk/go/process" "git.novox.be/novox/mesh-sdk/go/testbus" "git.novox.be/novox/mesh-sdk/go/views" @@ -361,10 +367,10 @@ func (p *player) asked(key string, body json.RawMessage) any { case key == HavesAsk: var q struct{ Node, Module string } _ = json.Unmarshal(body, &q) - hk, _ := delivery.HaveKey(q.Node, q.Module) + hk, _ := engineclient.HaveKey(q.Node, q.Module) keys := map[string]any{} if fp, ok := p.haves[q.Node+"."+q.Module]; ok { - keys[hk] = delivery.Have{V: delivery.Version, FP: fp, Phase: "applied", Health: "healthy"} + keys[hk] = nodeengine.HaveByNodeModuleValue{V: 1, Fp: fp, Phase: "running", Health: "ok"} } return map[string]any{"keys": keys} case strings.HasPrefix(key, ManifestReadsAsk): @@ -562,8 +568,8 @@ func eventually(t *testing.T, what string, ok func() bool) { // manifestIn writes a module's manifest into the indexer's buckets as the indexer writes it, and names it as the trunk's. func (p *player) manifestIn(module, raw string) string { p.t.Helper() - digest := delivery.ManifestDigest([]byte(raw)) - value, err := delivery.EncodeManifest(delivery.Manifest{Module: module, JSON: raw}) + digest := catalogclient.ManifestDigest([]byte(raw)) + value, err := catalogclient.EncodeManifest(catalog.ManifestsByDigestValue{Module: module, Manifest: raw}) if err != nil { p.t.Fatal(err) } @@ -575,26 +581,28 @@ func (p *player) manifestIn(module, raw string) string { // buildIn writes a build of a module with a manifest, and the want that names it on a node. func (p *player) buildIn(node, module, fp, raw string) { p.t.Helper() - digest := delivery.ManifestDigest([]byte(raw)) - value, _ := delivery.EncodeManifest(delivery.Manifest{Module: module, JSON: raw}) + digest := catalogclient.ManifestDigest([]byte(raw)) + value, _ := catalogclient.EncodeManifest(catalog.ManifestsByDigestValue{Module: module, Manifest: raw}) p.put("mesh-delivery-indexer.manifests", digest, json.RawMessage(value)) - bk, _ := delivery.BuilderBuildKey(module, fp) + bk, _ := builds.BuilderBuildKey(module, fp) p.put("mesh-delivery-builder.builds", bk, map[string]any{"v": 1, "state": "done", "manifest": digest}) p.put("mesh-delivery-assigner.wants", "want."+node+"."+module, map[string]any{"v": 1, "fp": fp, "self": true}) } func (p *player) placed(node string, modules ...string) { p.t.Helper() - pl := delivery.Placement{V: delivery.Version, Node: node} + pl := meshseat.Placement{V: 1, Node: node} for _, m := range modules { - pl.Modules = append(pl.Modules, delivery.PlacedModule{Module: m}) + pl.Modules = append(pl.Modules, meshseat.PlacedModule{Module: m}) } - values, err := delivery.PlacementValues(pl) + // In the order the seat's holder writes them (module keys before the node key that names their digests), so a reader + // never holds a node key whose module keys have not arrived. + writes, err := assignerclient.NewKeys().Writes(pl.Node, &pl) if err != nil { p.t.Fatal(err) } - for k, raw := range values { - p.put("mesh-delivery-assigner.placement", k, json.RawMessage(raw)) + for _, w := range writes { + p.put("mesh-delivery-assigner.placement", w.Key, json.RawMessage(w.Value)) } } diff --git a/modules/mesh-config/go.mod b/modules/mesh-config/go.mod index f27f531c8..cb405a36a 100644 --- a/modules/mesh-config/go.mod +++ b/modules/mesh-config/go.mod @@ -3,6 +3,13 @@ module mesh-config go 1.26.0 require ( + git.novox.be/novox/mesh-contracts/placement/go/seats/meshwants v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-contracts/go/clients/nodeengineclient v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-delivery/contracts/go/clients/meshcatalogclient v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds v0.0.0-00010101000000-000000000000 + git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient 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/health-and-repair/go/seats/meshconditions v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient v0.0.0-00010101000000-000000000000 git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient v0.0.0-00010101000000-000000000000 diff --git a/modules/mesh-config/module.json b/modules/mesh-config/module.json index 71f027224..c92985611 100644 --- a/modules/mesh-config/module.json +++ b/modules/mesh-config/module.json @@ -1,6 +1,9 @@ { "module": "mesh-config", "version": "1", + "packages": { + "builds": "0.1" + }, "runs-as": "mesh-config", "claims": [ {