Read the foundation's ports from each node's settings, wherever a port is used (hq ADR 0100)

This commit is contained in:
2026-09-22 17:31:07 +02:00
parent 1ea84f8b8f
commit dbf62b5212
9 changed files with 352 additions and 6 deletions
+33 -4
View File
@@ -233,12 +233,19 @@ func theRestOfTheMesh(ctx context.Context, inv *inventory.Inventory,
if err != nil {
return catalogue.World{}, err
}
layers, err := inv.SettingsFor(ctx, o.node.Name, m.Module)
if err != nil {
return catalogue.World{}, err
}
// A port that node was given is where its consumers reach it (novox/hq ADR
// 0100). Unreadable given ports are that node's refusal to report, not this one's.
if given, err := catalogue.GivenPorts(m, layers); err == nil {
for wanted, at := range given {
assigned[wanted] = at
}
}
serves := catalogue.ServedOn(m, name, assigned)
if len(serves) > 0 {
layers, err := inv.SettingsFor(ctx, o.node.Name, m.Module)
if err != nil {
return catalogue.World{}, err
}
serves, err = catalogue.Settle(serves, layers)
if err != nil {
return catalogue.World{}, err
@@ -364,9 +371,30 @@ func renderingFor(ctx context.Context, open *stores, node string,
}
}
// The machine ports this node was given for its modules (novox/hq ADR 0100): the foundation's
// ports, as genesis chose them. A given port wins over anything assigned and over a manifest's
// own long-form mapping.
given := map[string]map[int]int{}
for _, m := range plan.Modules {
g, err := catalogue.GivenPorts(m, settings[m.Module])
if err != nil {
return catalogue.Rendering{}, inventory.Node{}, err
}
if g != nil {
given[m.Module] = g
}
}
ports := map[string]map[int]int{}
for _, m := range plan.Modules {
for _, l := range m.Listens {
if at, isGiven := given[m.Module][l.Port]; isGiven {
if ports[m.Module] == nil {
ports[m.Module] = map[int]int{}
}
ports[m.Module][l.Port] = at
continue
}
// **Only a port the module actually publishes is the mesh's to move.** A container's
// mapping is the thing that translates; without one the software binds what it binds,
// and an assignment would not move the service — it would open the wrong number in the
@@ -515,6 +543,7 @@ func renderingFor(ctx context.Context, open *stores, node string,
Settings: settings, Generators: gens, Grants: grants, Needed: needed, Ports: ports,
Certificate: certificate, Authority: authority, Mesh: private, Names: names,
Suffix: overlay.Suffix(), Foundation: foundation, Kept: kept, Adopted: record.Adopted,
Given: given,
}, record, nil
}
+57
View File
@@ -168,3 +168,60 @@ func stdoutOf(t *testing.T, run func() error) string {
}
return out
}
// novox/hq ADR 0100: a port a node was given for the store is where its consumers on other
// machines are told to reach it, and a port given for the whole mesh is refused.
func TestConsumersAreToldTheGivenPort(t *testing.T) {
open := aMesh(t)
ctx := t.Context()
register(t, open, catalogue.Manifest{Module: "store", Version: "1",
Provides: []catalogue.Offer{{Name: "database", Scope: catalogue.ScopeMesh}},
Listens: []catalogue.Listening{{Port: 5432, From: catalogue.FromMesh}},
Guards: []int{5432},
Resources: []map[string]any{{"id": "server", "type": "container", "name": "mesh-store",
"ports": []any{"5432:5432"},
"image": "registry.example/pg@sha256:" + strings.Repeat("b", 64)}}})
register(t, open, catalogue.Manifest{Module: "app", Version: "1", Requires: []string{"database"}})
if _, err := assign(ctx, open, "anchor", "store"); err != nil {
t.Fatal(err)
}
if _, err := assign(ctx, open, "laptop", "app"); err != nil {
t.Fatal(err)
}
if err := open.inventory.SetSettings(ctx, "anchor", "store",
map[string]any{catalogue.PortsSetting: map[string]any{"5432": 5433}}); err != nil {
t.Fatal(err)
}
plan, _, err := planFor(ctx, open, "laptop")
if err != nil {
t.Fatal(err)
}
var told any
for _, n := range plan.Needs {
if n.Name == "database" {
told = n.Serves["port"]
}
}
if told != 5433 {
t.Fatalf("the consumer is told the store is on %v", told)
}
for _, r := range composed(t, open, "anchor").Resources {
if r["id"] == "store.server" && !reflect.DeepEqual(r["ports"], []any{"5433:5432"}) {
t.Fatalf("the store publishes %v", r["ports"])
}
}
if err := open.inventory.SetSettings(ctx, "", "store",
map[string]any{catalogue.PortsSetting: map[string]any{"5432": 5434}}); err != nil {
t.Fatal(err)
}
plan, settings, err := planFor(ctx, open, "anchor")
if err != nil {
t.Fatal(err)
}
if _, err := declarationFor(ctx, open, "anchor", plan, settings); err == nil ||
!strings.Contains(err.Error(), "per node") {
t.Fatalf("a port given for the whole mesh was not refused: %v", err)
}
}