Files
mesh-host/internal/compose/resolution/two_consumers_test.go
T
jschoubben d68e241724 Take the catalogue's composition rules into the node-engine
ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk
carries no composition rule. The catalogue functions only the
node-engine's composition reaches (Resolve, Resolution's Compose,
Declaration, DataItems, LeftOut, Rules and the rest, the settings,
placeholder and template refusals, the rendering helpers) are copied
with their tests into internal/compose/resolution; a method of a
mesh-sdk shape becomes a function taking it first. The composition
calls its own copies, and the captured catalogue its tests read lives
here now, shared by mesh-compose's tests.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 19:15:55 +01:00

129 lines
4.5 KiB
Go

package resolution
import (
"strings"
"testing"
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
)
func threeConsumers() map[string]mcat.Manifest {
return shelf(mcat.Manifest{Module: "postgres", Version: "1", Provides: mcat.FromAnywhere("postgres-database")}, mcat.Manifest{Module: "gitea", Version: "1", Requires: []string{"postgres-database"},
Contributes: map[string]map[string]any{"postgres-database": {"name": "gitea"}},
Secrets: map[string]string{"postgres-database": "/var/lib/gitea/db.secret"}}, mcat.Manifest{Module: "keycloak", Version: "1", Requires: []string{"postgres-database"},
Contributes: map[string]map[string]any{"postgres-database": {"name": "keycloak"}},
Secrets: map[string]string{"postgres-database": "/var/lib/keycloak/db.secret"}}, mcat.Manifest{Module: "umami", Version: "1", Requires: []string{"postgres-database"},
Contributes: map[string]map[string]any{"postgres-database": {"name": "umami"}},
Secrets: map[string]string{"postgres-database": "/var/lib/umami/db.secret"}},
)
}
func TestEveryConsumerOnANodeGetsItsOwnCredential(t *testing.T) {
got, err := Resolve(threeConsumers(), []string{"gitea", "keycloak", "umami"},
reachable(), mcat.World{Offered: onNetwork("anchor")})
if err != nil {
t.Fatal(err)
}
if len(got.Needs) != 3 {
t.Fatalf("three modules want a database and the node has %d need(s): %v",
len(got.Needs), got.Needs)
}
for _, want := range []string{"gitea", "keycloak", "umami"} {
var found bool
for _, n := range got.Needs {
if n.For == want {
found = true
}
}
if !found {
t.Errorf("%s wants a database and no credential is made for it", want)
}
}
}
// Each consumer's own credential reaches its own file. Matching on the provision alone, every
// consumer took whichever need was last — a module handed somebody else's password, which is a
// valid credential and therefore fails in a way that looks like a configuration error.
func TestEachConsumerGetsItsOwnCredentialAndNotAnothersFile(t *testing.T) {
got, err := Resolve(threeConsumers(), []string{"gitea", "keycloak", "umami"},
reachable(), mcat.World{Offered: onNetwork("anchor")})
if err != nil {
t.Fatal(err)
}
for i := range got.Needs {
got.Needs[i].Sealed = "sealed-for-" + got.Needs[i].For
}
out, err := Declaration(got, mcat.Rendering{})
if err != nil {
t.Fatal(err)
}
for _, want := range []string{"gitea", "keycloak", "umami"} {
var seen bool
for _, r := range out {
if r["path"] != "/var/lib/"+want+"/db.secret" {
continue
}
seen = true
if r["sealed"] != "sealed-for-"+want {
t.Errorf("%s was given %v, which belongs to something else", want, r["sealed"])
}
}
if !seen {
t.Errorf("%s resolved and its credential file was never written", want)
}
}
}
// The provider is told about all three, separately, and names each grant after the module.
func TestAProviderIsToldAboutEveryConsumerOnOneMachine(t *testing.T) {
provider, err := Resolve(shelf(mcat.Manifest{
Module: "postgres", Version: "1", Provides: mcat.FromAnywhere("postgres-database"),
Grants: map[string]string{"postgres-database": "/var/lib/postgres/grants"},
Receives: map[string]string{"postgres-database": "/var/lib/postgres/grants/mesh.json"},
}), []string{"postgres"}, reachable(), mcat.World{})
if err != nil {
t.Fatal(err)
}
var grants []mcat.Grant
for _, who := range []string{"gitea", "keycloak", "umami"} {
grants = append(grants, mcat.Grant{
Provision: "postgres-database", Consumer: "anchor", From: who,
Values: map[string]any{"name": who}, Sealed: "sealed-for-" + who})
}
out, err := Declaration(provider, mcat.Rendering{Grants: grants})
if err != nil {
t.Fatal(err)
}
for _, who := range []string{"gitea", "keycloak", "umami"} {
path := "/var/lib/postgres/grants/anchor." + who + ".secret"
var found bool
for _, r := range out {
if r["path"] == path {
found = true
if r["sealed"] != "sealed-for-"+who {
t.Errorf("%s's grant holds %v", who, r["sealed"])
}
}
}
if !found {
t.Errorf("the provider was never told to create a login for %s", who)
}
}
// And all three appear in the readable manifest, so the provisioner sees three consumers
// where there are three. Named after one machine, they were one path and the last won.
for _, r := range out {
if r["path"] != "/var/lib/postgres/grants/mesh.json" {
continue
}
body := r["content"].(string)
for _, who := range []string{"gitea", "keycloak", "umami"} {
if !strings.Contains(body, `"`+who+`"`) {
t.Errorf("the provider's manifest never mentions %s: %s", who, body)
}
}
}
}