One name per thing, per the HQ glossary: the module/container/image/binary/repo becomes mesh-controller, the seat the-controller, and the store+broker pair the foundation (embedded base bundles, default template and example lock renamed with their go:embed directives). No behaviour change — a pure vocabulary rename. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
110 lines
4.4 KiB
Go
110 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// The password comes from a file, because that is how the mesh delivers one.
|
|
//
|
|
// A provisioner told to take a superuser password from an environment variable needs somebody to
|
|
// read the sealed file and pass it in — a person in the middle of the one path that exists so
|
|
// there is not one. It is also the difference between a credential in a file and one in a process
|
|
// listing: `docker inspect` prints environment.
|
|
func TestTheSuperuserPasswordComesFromTheFileTheMeshWrote(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "superuser")
|
|
if err := os.WriteFile(path, []byte("the-sealed-one\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv("MESH_PROVISION_POSTGRES", "postgres://postgres@127.0.0.1:5433/postgres?sslmode=disable")
|
|
t.Setenv("MESH_PROVISION_PASSWORD_FILE", path)
|
|
|
|
where, err := connectionString()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(where, "the-sealed-one") {
|
|
t.Fatalf("the password the mesh wrote is not in the connection: %s", where)
|
|
}
|
|
if !strings.Contains(where, "127.0.0.1:5433") || !strings.Contains(where, "sslmode=disable") {
|
|
t.Fatalf("the rest of the connection was lost: %s", where)
|
|
}
|
|
}
|
|
|
|
// An empty file connects as nobody and is refused by the database three layers away, as an
|
|
// authentication problem with no cause anybody changed.
|
|
func TestAnEmptyPasswordFileIsRefusedHere(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "superuser")
|
|
if err := os.WriteFile(path, []byte("\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv("MESH_PROVISION_POSTGRES", "postgres://postgres@127.0.0.1:5433/postgres")
|
|
t.Setenv("MESH_PROVISION_PASSWORD_FILE", path)
|
|
if _, err := connectionString(); err == nil {
|
|
t.Fatal("a provisioner with no password reported one")
|
|
}
|
|
}
|
|
|
|
// And a provisioner somebody runs by hand still works with the URL alone.
|
|
func TestAConnectionWithNoPasswordFileIsLeftAlone(t *testing.T) {
|
|
t.Setenv("MESH_PROVISION_POSTGRES", "postgres://postgres:typed@127.0.0.1:5433/postgres")
|
|
t.Setenv("MESH_PROVISION_PASSWORD_FILE", "")
|
|
where, err := connectionString()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if where != "postgres://postgres:typed@127.0.0.1:5433/postgres" {
|
|
t.Fatalf("the connection was rewritten when it should have been left alone: %s", where)
|
|
}
|
|
}
|
|
|
|
func TestAProvisionerWithNoDatabaseSaysSo(t *testing.T) {
|
|
t.Setenv("MESH_PROVISION_POSTGRES", "")
|
|
t.Setenv("MESH_PROVISION_PASSWORD_FILE", "")
|
|
if _, err := connectionString(); err == nil {
|
|
t.Fatal("a provisioner that does not know which database it owns reported one")
|
|
}
|
|
}
|
|
|
|
// PostgreSQL cuts an identifier at 63 bytes and says so only as a notice, so two consumers whose
|
|
// role names agree that far would quietly become one login — 022 again, at a length nobody tests.
|
|
func TestARoleNameTooLongToBeDistinctIsRefused(t *testing.T) {
|
|
if err := usableRole("mesh_anchor_gitea"); err != nil {
|
|
t.Fatalf("an ordinary name was refused: %v", err)
|
|
}
|
|
long := "mesh_" + strings.Repeat("n", 40) + "_" + strings.Repeat("m", 40)
|
|
err := usableRole(long)
|
|
if err == nil {
|
|
t.Fatal("a role name PostgreSQL would shorten was accepted")
|
|
}
|
|
if !strings.Contains(err.Error(), "share the login") {
|
|
t.Errorf("the refusal does not say what goes wrong: %v", err)
|
|
}
|
|
}
|
|
|
|
// The prefix this provisioner removes by is the prefix the mesh names by.
|
|
//
|
|
// **Two definitions on purpose.** A provisioner is a separate program and anyone may write one, so
|
|
// the prefix is part of the contract rather than a symbol to import — the same reason the grant
|
|
// file's shape is written down rather than shared. But a contract with two copies and no check is
|
|
// a contract until somebody edits one: if the mesh named `nox_` and this removed `mesh_`, every
|
|
// login it created would be permanent, and nothing would report anything at all.
|
|
func TestTheMarkAgreesWithWhatTheMeshNamesBy(t *testing.T) {
|
|
if mark != catalogue.IdentityPrefix {
|
|
t.Fatalf(
|
|
"this provisioner removes what begins with %q and the mesh names things %q, so it "+
|
|
"would never remove anything it made", mark, catalogue.IdentityPrefix)
|
|
}
|
|
}
|
|
|
|
// And a name the mesh would produce is one this provisioner accepts.
|
|
func TestWhatTheMeshNamesIsUsableAsARole(t *testing.T) {
|
|
if err := usableRole(catalogue.ConsumerIdentity("home-server", "keycloak")); err != nil {
|
|
t.Fatalf("the mesh named a consumer and this cannot make a role for it: %v", err)
|
|
}
|
|
}
|