mesh/delivery closed: a newer head of the same pull request
mesh/check checking 9d8a5a7ede90 on 2ecfbb3a29cb | novox/mesh-controller#474 in group feat/1126-nodes-compose
72 lines
2.9 KiB
Go
72 lines
2.9 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
|
|
sdkdelivery "git.novox.be/novox/mesh-sdk/go/delivery"
|
|
"git.novox.be/novox/mesh-sdk/go/overlay"
|
|
)
|
|
|
|
// Issue 1126 (novox/hq ADR 0555 §6, the operator's one export verb of 2026-10-26 19:06:40): `node placement-export`
|
|
// answers, from the real store, each node's placement as the catalogue's placement file says it: what a person decided
|
|
// of the node (its endpoint, site, hub and address on the private network) and its modules in the order the composition
|
|
// reads them, exactly frombus.Export of the input this controller composes from; one node when named; a node the store
|
|
// lacks is refused. Checked within TestTheControlPlaneIsToldWhereTheNodePutTheStoreAndTheBroker, over the same fresh
|
|
// mesh, so the export adds no integration test of its own (the test budget).
|
|
func placementExportIsEachNodesPlacementFromTheStore(t *testing.T, open *stores) {
|
|
t.Helper()
|
|
ctx := t.Context()
|
|
in, _, err := readMeshAndNodes(ctx, open)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := readSettings(ctx, open, &in); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var all map[string]sdkdelivery.Placement
|
|
if err := json.Unmarshal([]byte(stdoutOf(t, func() error { return placementExport(ctx, open, nil) })), &all); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(all) != 2 {
|
|
t.Fatalf("exported %d nodes, want anchor and laptop", len(all))
|
|
}
|
|
for i, name := range []string{"anchor", "laptop"} {
|
|
got := all[name]
|
|
d := got.Decided
|
|
if d.Endpoint != name+".example:51820" || d.Site != "here" || d.Hub != (name == "anchor") || d.Address != []string{"10.77.0.1", "10.77.0.2"}[i] {
|
|
t.Errorf("%s's decided facts are %+v", name, d)
|
|
}
|
|
if a := got.Assigned(); len(a) == 0 || !strings.Contains(strings.Join(a, ","), overlay.Name) {
|
|
t.Errorf("%s's modules are %v, want the private network among them", name, a)
|
|
}
|
|
// What it prints is the file the seed writes: at the placement file's version, read back by its reader.
|
|
if raw, _ := json.Marshal(got); got.V != sdkdelivery.Version {
|
|
t.Errorf("%s is exported at version %d: %s", name, got.V, raw)
|
|
} else if _, err := sdkdelivery.DecodePlacement(raw); err != nil {
|
|
t.Errorf("%s's export does not read as a placement file: %v", name, err)
|
|
}
|
|
want, err := frombus.Export(in, name)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !sdkdelivery.SamePlacement(got, want) {
|
|
t.Errorf("%s's export differs from frombus.Export of the controller's own input:\n%+v\n%+v", name, got, want)
|
|
}
|
|
}
|
|
var one map[string]sdkdelivery.Placement
|
|
if err := json.Unmarshal([]byte(stdoutOf(t, func() error { return placementExport(ctx, open, []string{"laptop"}) })), &one); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := one["laptop"]; !ok || len(one) != 1 {
|
|
t.Errorf("one node named exported %v", one)
|
|
}
|
|
if err := placementExport(ctx, open, []string{"stranger"}); err == nil {
|
|
t.Error("a node the store lacks was exported")
|
|
}
|
|
}
|