go.mod and go.sum move to mesh-sdk 14fd5cb68fd1, the commit on its main that holds go/catalogue, go/overlay and go/validate (ADR 0453 clause 2); vendor/modules.txt follows in the last of the six commits.
144 lines
7.4 KiB
Go
144 lines
7.4 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// What the forge's take compares, as a machine would report it.
|
|
func aForgeComparison() comparison {
|
|
return comparison{reported: inventory.Adoption{
|
|
Firewall: "ufw",
|
|
Held: []inventory.Held{
|
|
{ID: "forge.server", Module: "forge", Kind: "container", Target: "forge", Facts: map[string]any{
|
|
"image": "forge:1.27.3", "image_created": "2026-09-17T10:00:00Z",
|
|
"declared_image": "forge:1.22.6", "declared_image_created": "2026-08-20T10:00:00Z", "downgrade": true,
|
|
"networks": map[string]any{"predecessor_default": []any{"office", "db"}},
|
|
"ports": []any{"3000/tcp>0.0.0.0:3000"}, "declared_ports": []any{"3000:3000"},
|
|
}},
|
|
{ID: "forge.config", Module: "forge", Kind: "file", Target: "/etc/forge/app.ini", Kept: "/var/lib/mesh/kept/app.ini",
|
|
Facts: map[string]any{"differs": true, "difference": []any{"- private scope: local", "+ upstream: public"}}},
|
|
{ID: "other.server", Module: "other", Kind: "container", Target: "other"},
|
|
},
|
|
Reachable: []inventory.Reach{
|
|
{Protocol: "tcp", Address: "0.0.0.0", Port: 3000, By: "forge", Published: true, ContainerPort: 3000},
|
|
{Protocol: "tcp", Address: "0.0.0.0", Port: 22, By: "sshd"},
|
|
},
|
|
}}
|
|
}
|
|
|
|
// A take is a comparison (novox/hq ADR 0163): the preview puts what runs beside what the module
|
|
// declares, and an older image or a differing file refuses unless named.
|
|
func TestATakePreviewsTheComparisonAndRefusesWhatIsNotNamed(t *testing.T) {
|
|
c := aForgeComparison()
|
|
preview, refusals, saw := comparisonOf("forge", c, takeOptions{})
|
|
for _, want := range []string{"runs forge:1.27.3 (made 2026-09-17)", "declares forge:1.22.6 (made 2026-08-20)", "DOWNGRADE",
|
|
"on the network predecessor_default with office, db", "will not once it moves to the module's own network",
|
|
"publishes 3000/tcp>0.0.0.0:3000; the module declares 3000:3000",
|
|
// How far the port reaches now, as the machine reported it (rule 1).
|
|
"reachable now at 0.0.0.0:3000 (tcp, container port 3000), behind the found firewall (ufw)",
|
|
"- private scope: local", "original kept at /var/lib/mesh/kept/app.ini"} {
|
|
if !strings.Contains(preview, want) {
|
|
t.Errorf("the preview lacks %q:\n%s", want, preview)
|
|
}
|
|
}
|
|
if strings.Contains(preview, "other") {
|
|
t.Errorf("another module's held things are in the preview:\n%s", preview)
|
|
}
|
|
if len(refusals) != 2 || !strings.Contains(refusals[0], "--downgrade") || !strings.Contains(refusals[1], "--replace /etc/forge/app.ini") {
|
|
t.Fatalf("the downgrade and the differing file refuse, each naming its override: %v", refusals)
|
|
}
|
|
if len(saw) != 12 {
|
|
t.Fatalf("the preview's digest is %q", saw)
|
|
}
|
|
// Named, they pass.
|
|
if _, refusals, _ := comparisonOf("forge", c, takeOptions{Downgrade: true, Replace: map[string]bool{"/etc/forge/app.ini": true}}); len(refusals) != 0 {
|
|
t.Fatalf("named differences still refused: %v", refusals)
|
|
}
|
|
if _, refusals, _ := comparisonOf("forge", c, takeOptions{Downgrade: true, Replace: map[string]bool{"*": true}}); len(refusals) != 0 {
|
|
t.Fatalf("replace * did not cover the file: %v", refusals)
|
|
}
|
|
// A held thing with no facts yet — a host older than this — refuses nothing and says what it can.
|
|
if preview, refusals, _ := comparisonOf("other", c, takeOptions{}); len(refusals) != 0 || !strings.Contains(preview, "container other") {
|
|
t.Fatalf("a factless hold: %q %v", preview, refusals)
|
|
}
|
|
// The digest is of what the preview says: a fact changing changes it.
|
|
c.reported.Held[0].Facts["image"] = "forge:1.27.4"
|
|
if _, _, again := comparisonOf("forge", c, takeOptions{}); again == saw {
|
|
t.Fatal("the found image changed and the digest did not")
|
|
}
|
|
}
|
|
|
|
// A secret the mesh minted for a service whose data was found refuses: the running service already
|
|
// has a value (rule 2). Accepted, it is carried in; `--mint` says the service shall take the new one.
|
|
func TestAMintedSecretForFoundDataRefusesUnlessAcceptedOrMinted(t *testing.T) {
|
|
c := aForgeComparison()
|
|
c.secrets = []inventory.SecretState{
|
|
{Name: "admin", Origin: inventory.OriginMade},
|
|
{Name: "postgres-database", Origin: inventory.OriginMade, Provider: "anchor"},
|
|
{Name: "broker", Origin: inventory.OriginAccepted},
|
|
}
|
|
preview, refusals, _ := comparisonOf("forge", c, takeOptions{Downgrade: true, Replace: map[string]bool{"*": true}})
|
|
for _, want := range []string{
|
|
"own secret admin: MINTED by the mesh and not accepted",
|
|
"secret from anchor postgres-database: MINTED by the mesh and not accepted",
|
|
"own secret broker: accepted from a person, carried in as it is",
|
|
} {
|
|
if !strings.Contains(preview, want) {
|
|
t.Errorf("the preview lacks %q:\n%s", want, preview)
|
|
}
|
|
}
|
|
if len(refusals) != 2 {
|
|
t.Fatalf("two minted secrets refuse: %v", refusals)
|
|
}
|
|
if !strings.Contains(refusals[0], "`secret accept <node> forge admin`") || !strings.Contains(refusals[0], "`--mint admin`") {
|
|
t.Errorf("the own secret's refusal names accepting it and minting it: %s", refusals[0])
|
|
}
|
|
if !strings.Contains(refusals[1], "`secret accept <node> forge postgres-database --provider anchor`") {
|
|
t.Errorf("the required secret's refusal names its provider: %s", refusals[1])
|
|
}
|
|
preview, refusals, _ = comparisonOf("forge", c, takeOptions{Downgrade: true, Replace: map[string]bool{"*": true},
|
|
Mint: map[string]bool{"admin": true, "postgres-database": true}})
|
|
if len(refusals) != 0 || !strings.Contains(preview, "admin: minted by the mesh; the service takes the new value, as --mint said") {
|
|
t.Fatalf("--mint did not pass the minted secrets: %v\n%s", refusals, preview)
|
|
}
|
|
// With no found data — only a file held — the service has no value of its own, and a minted
|
|
// secret is simply said.
|
|
c.reported.Held = c.reported.Held[1:2]
|
|
if _, refusals, _ := comparisonOf("forge", c, takeOptions{Replace: map[string]bool{"*": true}}); len(refusals) != 0 {
|
|
t.Fatalf("a minted secret refused with no data found: %v", refusals)
|
|
}
|
|
}
|
|
|
|
// A found network a per-machine setting keeps is named in the preview (rule 4), and the module's
|
|
// settings are said with where each came from, composed or not (rules 1 and 6).
|
|
func TestTheKeptNetworkAndTheSettingsAreInThePreview(t *testing.T) {
|
|
c := aForgeComparison()
|
|
c.keeps = map[string][]string{"forge.server": {"predecessor_default"}}
|
|
c.layers = []catalogue.Layer{
|
|
{From: catalogue.MeshWideLayer, Values: map[string]any{"site": "x"}},
|
|
{From: "anchor", Values: map[string]any{catalogue.NetworksSetting: map[string]any{"server": []any{"predecessor_default"}}}},
|
|
}
|
|
preview, _, _ := comparisonOf("forge", c, takeOptions{Downgrade: true, Replace: map[string]bool{"*": true}})
|
|
for _, want := range []string{
|
|
"on the network predecessor_default with office, db — kept by this machine's setting, so they still reach it by name once taken",
|
|
"settings from the mesh: site",
|
|
"settings from anchor: networks",
|
|
} {
|
|
if !strings.Contains(preview, want) {
|
|
t.Errorf("the preview lacks %q:\n%s", want, preview)
|
|
}
|
|
}
|
|
if strings.Contains(preview, "will not once it moves") {
|
|
t.Errorf("a kept network is still said to be lost:\n%s", preview)
|
|
}
|
|
c.settingsRefused = "forge: ports is a { port: machine-port } map"
|
|
preview, _, _ = comparisonOf("forge", c, takeOptions{Downgrade: true, Replace: map[string]bool{"*": true}})
|
|
if !strings.Contains(preview, "SETTINGS DO NOT COMPOSE with the module's definition, so the push leaves it out: forge: ports") {
|
|
t.Errorf("settings that cannot compose are not said:\n%s", preview)
|
|
}
|
|
}
|