Read the foundation's ports from each node's settings, wherever a port is used (hq ADR 0100)
This commit is contained in:
@@ -654,7 +654,7 @@ func (i *Inventory) SettingsFor(ctx context.Context, nodeName, module string) ([
|
||||
}
|
||||
from := nodeName
|
||||
if meshWide {
|
||||
from = "the mesh"
|
||||
from = catalogue.MeshWideLayer
|
||||
}
|
||||
layers = append(layers, catalogue.Layer{From: from, Values: values})
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package inventory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
@@ -132,6 +133,17 @@ func (i *Inventory) assignPort(
|
||||
taken[port] = "something this machine already runs"
|
||||
}
|
||||
}
|
||||
// And every port this machine was given for a module (novox/hq ADR 0100): the foundation's
|
||||
// ports, as genesis chose them, are the node's settings and never the mesh's to hand out.
|
||||
given, err := i.givenOn(ctx, nodeID)
|
||||
if err != nil {
|
||||
return Assigned{}, err
|
||||
}
|
||||
for port, by := range given {
|
||||
if _, mine := taken[port]; !mine {
|
||||
taken[port] = by
|
||||
}
|
||||
}
|
||||
|
||||
machine := wanted
|
||||
if !fixed {
|
||||
@@ -258,3 +270,33 @@ func (i *Inventory) ReleasePorts(ctx context.Context, node, module string) error
|
||||
`delete from port_assignment where node = $1 and module = $2`, record.ID, module)
|
||||
return err
|
||||
}
|
||||
|
||||
// givenOn is every machine port a module was given on this node by its `ports` setting, and which
|
||||
// module it was given to.
|
||||
func (i *Inventory) givenOn(ctx context.Context, nodeID any) (map[int]string, error) {
|
||||
rows, err := i.store.Pool().Query(ctx,
|
||||
`select module, values->'ports' from settings
|
||||
where node = $1 and jsonb_typeof(values->'ports') = 'object'`, nodeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
out := map[int]string{}
|
||||
for rows.Next() {
|
||||
var module string
|
||||
var raw []byte
|
||||
if err := rows.Scan(&module, &raw); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var given map[string]any
|
||||
if err := json.Unmarshal(raw, &given); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range given {
|
||||
if at, ok := v.(float64); ok {
|
||||
out[int(at)] = module
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
@@ -236,3 +236,24 @@ func TestUnassigningReleasesTheModulesPorts(t *testing.T) {
|
||||
t.Fatalf("port 25 is still held in the name of a module that was unassigned: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// novox/hq ADR 0100: a port a node was given for a module is the node's, and the mesh never hands
|
||||
// it to another.
|
||||
func TestAGivenPortIsNeverAssigned(t *testing.T) {
|
||||
inv, node := aNodeWithModules(t, "postgres", "web")
|
||||
ctx := t.Context()
|
||||
if err := inv.SetSettings(ctx, node, "postgres",
|
||||
map[string]any{catalogue.PortsSetting: map[string]any{"5432": 20000}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := inv.PortFor(ctx, node, "web", 8080, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.Machine == 20000 {
|
||||
t.Fatal("a port given to postgres was assigned to web")
|
||||
}
|
||||
if _, err := inv.PortFor(ctx, node, "web", 20000, true); !errors.Is(err, ErrPortTaken) {
|
||||
t.Fatalf("a fixed port given to another module was handed over: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user