Archived
Remove route-proxy from the controller's repository, which it left for mesh-networking
The group's check composed route-proxy twice, here and in mesh-networking; the move is one delivery group (issue 1126), so it leaves here in the same group. The tests that read its directory go with it. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -172,41 +172,6 @@ func TestANarrowedTreeHoldsTheBuildSourceAndNothingElse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// This repository's own programs: the route proxy lives in its module's own Go module, so its build source is
|
||||
// not the controller's, and neither holds the other's command.
|
||||
func TestThisRepositorysProgramsHaveBuildSourcesOfTheirOwn(t *testing.T) {
|
||||
root := filepath.Join("..", "..")
|
||||
proxy, err := GoBuildSource(filepath.Join(root, "modules", "route-proxy"), "cmd/route-proxy")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
controller, err := GoBuildSource(root, "cmd/mesh-controller")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, c := range []struct {
|
||||
entries []string
|
||||
name string
|
||||
file string
|
||||
held bool
|
||||
}{
|
||||
{proxy, "the route proxy", "cmd/route-proxy/main.go", true},
|
||||
{proxy, "the route proxy", "cmd/route-proxy/bus.go", true},
|
||||
{proxy, "the route proxy", "go.mod", true},
|
||||
{proxy, "the route proxy", "cmd/route-provider/main.go", false},
|
||||
{proxy, "the route proxy", "README.md", false},
|
||||
{controller, "the controller", "cmd/mesh-controller/main.go", true},
|
||||
{controller, "the controller", "internal/conditions/condition.go", true},
|
||||
{controller, "the controller", "internal/inventory/migrations/0001-nodes.sql", true},
|
||||
{controller, "the controller", "modules/route-proxy/cmd/route-proxy/main.go", false},
|
||||
{controller, "the controller", "README.md", false},
|
||||
} {
|
||||
if SourceHolds(c.entries, c.file) != c.held {
|
||||
t.Errorf("%s: %s held %v, wanted %v", c.name, c.file, !c.held, c.held)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// C or assembly beside Go holds its package's directory whole — an include may name a file below it — and a
|
||||
// go.mod made between the module's root and a package is a change.
|
||||
func TestNativeSourcesHoldTheirDirectoryWhole(t *testing.T) {
|
||||
|
||||
@@ -43,28 +43,6 @@ func imagesOutOfPlace(t *testing.T, root string, manifests map[string][]byte) []
|
||||
return out
|
||||
}
|
||||
|
||||
// Every image a module of this repository declares is built from a Dockerfile in the module's own directory
|
||||
// (novox/hq ADR 0487 clause 13). The catalogue's own modules are held to the same by checks/imageplace in mesh-catalog.
|
||||
func TestEveryImageArtifactBuildsFromADockerfileInItsOwnModuleDirectory(t *testing.T) {
|
||||
root := filepath.Join("..", "..", "modules")
|
||||
paths, err := filepath.Glob(filepath.Join(root, "*", "module.json"))
|
||||
if err != nil || len(paths) == 0 {
|
||||
t.Fatalf("no module manifests found in this repository's modules: %v", err)
|
||||
}
|
||||
manifests := map[string][]byte{}
|
||||
for _, p := range paths {
|
||||
raw, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
manifests[filepath.Base(filepath.Dir(p))] = raw
|
||||
}
|
||||
if got := imagesOutOfPlace(t, root, manifests); len(got) != 0 {
|
||||
t.Errorf("these image artifacts do not build from a Dockerfile in their own module's directory "+
|
||||
"(ADR 0487 clause 13): %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// The check fails on each bad case and passes on a good one, so it holds something.
|
||||
func TestAnImageWhoseDockerfileIsOutOfPlaceIsFoundAndOneInPlaceIsNot(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
package ownmanifest
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
. "git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
)
|
||||
|
||||
// The public issuer is the proxy's own fact (novox/hq ADR 0226), and the folding of it must not
|
||||
// move the proxy's account.
|
||||
//
|
||||
// route-proxy keeps each ACME authority's account and certificates in a directory named after a
|
||||
// digest of the directory URL and of the root bundle its `trust` container copies in
|
||||
// (modules/route-proxy/cmd/route-proxy, forThisAuthority). Until ADR 0226 the URL was rendered from a binding to
|
||||
// `public-acme`'s `acme-ca`, spelled with the port. A URL spelled any other way — even the same
|
||||
// authority without `:443` — or a root bundle from another image is a new authority to the proxy:
|
||||
// a new account, and every routed name ordered again, on two machines at once, against Let's
|
||||
// Encrypt's rate limits. So what the module now states is held to exactly what the binding rendered.
|
||||
|
||||
// renderedBeforeTheFold is route-proxy's acme.env as the binding to public-acme rendered it on every
|
||||
// machine running the proxy, read from the controller's plan on 2026-10-06.
|
||||
const renderedBeforeTheFold = "ACME_DIRECTORY=https://acme-v02.api.letsencrypt.org:443/directory\n" +
|
||||
"ACME_ROOTS=https://acme-v02.api.letsencrypt.org:443\n" +
|
||||
"ACME_ROOTS_PATH=\n"
|
||||
|
||||
// trustImage is the image whose system bundle becomes the public root the account directory is
|
||||
// named after. Moving it renames that directory.
|
||||
const trustImage = "alpine@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b"
|
||||
|
||||
func TestRouteProxyKeepsItsPublicAccountDirectory(t *testing.T) {
|
||||
m := catalogueManifest(t, "route-proxy")
|
||||
for _, r := range m.Requires {
|
||||
if r == "acme-ca" {
|
||||
t.Fatal("route-proxy still asks for acme-ca; the public issuer is its own fact (ADR 0226)")
|
||||
}
|
||||
}
|
||||
|
||||
// As a build would leave it: each artifact a container names resolved to an image. Which image
|
||||
// does not matter to the file checked here. An archive resource carries no image: it unpacks a bundle.
|
||||
for _, res := range m.Resources {
|
||||
if res["type"] == "archive" {
|
||||
continue
|
||||
}
|
||||
if artifact, ok := res["artifact"].(string); ok {
|
||||
delete(res, "artifact")
|
||||
res["image"] = "registry.invalid/route-proxy/" + artifact +
|
||||
"@sha256:1111111111111111111111111111111111111111111111111111111111111111"
|
||||
}
|
||||
}
|
||||
r := Resolution{
|
||||
Node: "anchor",
|
||||
Modules: []Manifest{m},
|
||||
Needs: []Needed{{
|
||||
Name: "internal-acme-ca", From: "home", At: "home.internal", For: "route-proxy",
|
||||
Serves: map[string]any{
|
||||
"port": float64(9000), "path": "/acme/acme/directory", "roots": "/roots.pem",
|
||||
},
|
||||
}},
|
||||
}
|
||||
// Its own broker credential, sealed as the mesh would; what it is does not matter here.
|
||||
out, err := r.Declaration(Rendering{Needed: map[string]map[string]string{
|
||||
"route-proxy": {"broker": "sealed"}}})
|
||||
if err != nil {
|
||||
t.Fatalf("route-proxy could not be composed for a machine: %v", err)
|
||||
}
|
||||
env := fileNamed(out, "route-proxy.acme-env")
|
||||
if env == nil {
|
||||
t.Fatalf("nothing writes the public issuer's environment: %v", out)
|
||||
}
|
||||
if got, _ := env["content"].(string); got != renderedBeforeTheFold {
|
||||
t.Fatalf("acme.env changed, which moves the proxy's account and reorders every certificate:\n"+
|
||||
"got %q\nwant %q", got, renderedBeforeTheFold)
|
||||
}
|
||||
if fileNamed(out, "route-proxy.bound-acme-ca") != nil {
|
||||
t.Error("a binding to acme-ca is still written")
|
||||
}
|
||||
|
||||
var trust string
|
||||
if m.Build != nil {
|
||||
for _, a := range m.Build.Artifacts {
|
||||
if a.Name == "trust" {
|
||||
trust = a.From
|
||||
}
|
||||
}
|
||||
}
|
||||
if trust != trustImage {
|
||||
t.Errorf("the trust image is %q, not %q: its system bundle is the public root the account "+
|
||||
"directory is named after, so moving it reorders every certificate. Move it only with a "+
|
||||
"plan for the account (ADR 0226)", trust, trustImage)
|
||||
}
|
||||
}
|
||||
|
||||
// The proxy's program is mounted into the pinned trust image, not baked into an image (novox/hq ADR 0480 clauses 1,
|
||||
// 2 and 4): a Go bundle of the module's own Go module stamped for alpine, unpacked by an archive resource, mounted
|
||||
// read-only at /opt/mesh, called through args, and named under restart-on so a new program never leaves the old
|
||||
// one running. The container's name, network and logging are what the jail and the routes rely on.
|
||||
//
|
||||
// And its routes are the seat mesh-provisioner's plans alone (issue 774, research 072 row 34): it reads them, and
|
||||
// receives no file of contributions; no module of this repository does.
|
||||
func TestRouteProxyRunsItsMountedProgramOnTheTrustImage(t *testing.T) {
|
||||
m := catalogueManifest(t, "route-proxy")
|
||||
if !slices.Contains(m.Reads, "mesh-provisioner.plans") {
|
||||
t.Errorf("route-proxy does not read mesh-provisioner.plans, where its routes are: %v", m.Reads)
|
||||
}
|
||||
dirs, _ := filepath.Glob(filepath.Join("..", "..", "modules", "*"))
|
||||
for _, dir := range dirs {
|
||||
if r := catalogueManifest(t, filepath.Base(dir)); len(r.Receives) > 0 {
|
||||
t.Errorf("%s receives %v: a route, like every provision here, is served from the seat's plans, never a "+
|
||||
"received file", r.Module, r.Receives)
|
||||
}
|
||||
}
|
||||
var bundle *Artifact
|
||||
for i, a := range m.Build.Artifacts {
|
||||
if a.Name == "server" {
|
||||
bundle = &m.Build.Artifacts[i]
|
||||
}
|
||||
if a.Kind == "image" {
|
||||
t.Errorf("artifact %s is an image built from a Dockerfile (ADR 0452 §1)", a.Name)
|
||||
}
|
||||
}
|
||||
if bundle == nil || bundle.Kind != "bundle" || bundle.Language != "go" || bundle.System != "alpine" ||
|
||||
bundle.From != "cmd/route-proxy" || bundle.Binary != "route-proxy" {
|
||||
t.Fatalf("the server artifact is not a Go bundle of cmd/route-proxy stamped for alpine: %+v", bundle)
|
||||
}
|
||||
var archive, server map[string]any
|
||||
for _, r := range m.Resources {
|
||||
switch {
|
||||
case r["type"] == "archive" && r["artifact"] == "server":
|
||||
archive = r
|
||||
case r["id"] == "server":
|
||||
server = r
|
||||
}
|
||||
}
|
||||
if archive == nil || server == nil {
|
||||
t.Fatalf("archive %v or server container %v is missing", archive, server)
|
||||
}
|
||||
if server["artifact"] != "trust" || server["name"] != "route-proxy" || server["network"] != "host" || server["logging"] != "journald" {
|
||||
t.Errorf("the server container moved: %v", server)
|
||||
}
|
||||
mount := archive["path"].(string) + ":/opt/mesh:ro"
|
||||
mounted := false
|
||||
for _, v := range server["volumes"].([]any) {
|
||||
mounted = mounted || v == mount
|
||||
}
|
||||
if !mounted {
|
||||
t.Errorf("the archive is not mounted read-only at /opt/mesh (%s): %v", mount, server["volumes"])
|
||||
}
|
||||
if args, _ := server["args"].([]any); len(args) != 1 || args[0] != "/opt/mesh/route-proxy" {
|
||||
t.Errorf("args are %v, want the mounted program", server["args"])
|
||||
}
|
||||
restarts := false
|
||||
for _, v := range server["restart-on"].([]any) {
|
||||
restarts = restarts || v == archive["id"]
|
||||
}
|
||||
if !restarts {
|
||||
t.Errorf("restart-on %v does not name the archive %v", server["restart-on"], archive["id"])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user