Test route-proxy without composing: its manifest's own facts and a plan entry's port, since the composition left mesh-sdk
The composer's proof that the manifest composes, and that a port is the placement's, is the node-engine's now (ADR 0593 §7). Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -54,40 +54,16 @@ func TestRouteProxyKeepsItsPublicAccountDirectory(t *testing.T) {
|
||||
if slices.Contains(m.Requires, "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 := catalogue.Resolution{
|
||||
Node: "anchor",
|
||||
Modules: []catalogue.Manifest{m},
|
||||
Needs: []catalogue.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(catalogue.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 := resourceNamed(out, "route-proxy.acme-env")
|
||||
// The tree read inlines the template the manifest names, a literal with nothing to fill, so this is what it writes.
|
||||
env := resourceNamed(m.Resources, "acme-env")
|
||||
if env == nil {
|
||||
t.Fatalf("nothing writes the public issuer's environment: %v", out)
|
||||
t.Fatalf("nothing writes the public issuer's environment: %v", m.Resources)
|
||||
}
|
||||
if got, _ := env["content"].(string); got != renderedBeforeTheFold {
|
||||
t.Fatalf("acme.env changed, which moves the proxy's account and reorders every certificate:\ngot %q\nwant %q",
|
||||
got, renderedBeforeTheFold)
|
||||
}
|
||||
if resourceNamed(out, "route-proxy.bound-acme-ca") != nil {
|
||||
if resourceNamed(m.Resources, "bound-acme-ca") != nil {
|
||||
t.Error("a binding to acme-ca is still written")
|
||||
}
|
||||
var trust string
|
||||
|
||||
@@ -154,70 +154,32 @@ func TestARouteWithNoInternalNameGetsNoAlias(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A route is dialled where the machine publishes its module's endpoint, as the module's declaration publishes it (issue
|
||||
// 774, research 072 row 34; 2026-10-31: gitea's 3000, published at 20000, and grafana's 3000 on another machine,
|
||||
// published at 20012, answered 502): over loopback beside the proxy, which is the only thing that works without a
|
||||
// private network, and at its machine's address otherwise. Each plan is composed by the SDK as the seat
|
||||
// mesh-provisioner composes it, its ports as compose's portsFor gives them (the placement's for a port the mesh may
|
||||
// move, the manifest's own otherwise), and read as this proxy reads it: the live shapes the old proxy served alike.
|
||||
func TestAComposedPlanIsDialledWhereTheMachinePublishesIt(t *testing.T) {
|
||||
proxy := catalogue.Manifest{Module: "route-proxy", Version: "1",
|
||||
Provides: []catalogue.Offer{{Name: "route", Scope: catalogue.ScopeMesh, AnsweredBy: catalogue.AnsweredByHelper}}}
|
||||
world := catalogue.World{Offered: map[string][]catalogue.Provider{
|
||||
"route": {{Node: "anchor", At: "anchor.internal", Module: "route-proxy"}}}}
|
||||
// A route is dialled at the machine port its plan entry carries (issue 774, research 072 row 34; 2026-10-31: gitea's
|
||||
// 3000, published at 20000, and grafana's 3000 on another machine, published at 20012, answered 502): over loopback
|
||||
// when the plan is the one of this proxy's own node, which is the only thing that works without a private network, and
|
||||
// at the address the entry gives for its machine otherwise. The plans here are written as the seat mesh-provisioner
|
||||
// carries them; that the port is the placement's and not the software's own is the composition's, proved by the
|
||||
// node-engine's composer, not here.
|
||||
func TestAPlanEntryIsDialledAtTheMachinePortItCarries(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
name, node, module string
|
||||
port int // the endpoint's port, as listens says it
|
||||
published []any // the container's ports; nil for the host's network
|
||||
placed map[int]int // what mesh-placement holds for the module
|
||||
target string
|
||||
name, node, module, at string
|
||||
port int
|
||||
target string
|
||||
}{
|
||||
{"beside the proxy, moved by the placement (gitea)", "anchor", "gitea", 3000, []any{"3000"}, map[int]int{3000: 20000},
|
||||
"http://127.0.0.1:20000"},
|
||||
{"on another machine, moved by the placement (grafana)", "home", "grafana", 3000, []any{"3000"},
|
||||
map[int]int{3000: 20012}, "http://home.internal:20012"},
|
||||
{"a bare port the placement holds none for (influxdb)", "home", "influxdb", 8086, []any{"8086"}, nil,
|
||||
"http://home.internal:8086"},
|
||||
{"a fixed mapping (mailu 7080:80)", "anchor", "mailu", 7080, []any{"25", "7080:80"}, nil, "http://127.0.0.1:7080"},
|
||||
{"a fixed mapping the placement names another port of (photos 9102:9000)", "anchor", "photos", 9102,
|
||||
[]any{"9102:9000"}, map[int]int{9000: 20011}, "http://127.0.0.1:9102"},
|
||||
{"the host's network (home-assistant)", "anchor", "home-assistant", 8123, nil, nil, "http://127.0.0.1:8123"},
|
||||
{"beside the proxy (gitea)", "anchor", "gitea", "", 20000, "http://127.0.0.1:20000"},
|
||||
{"beside the proxy, though the entry says an address (mailu)", "anchor", "mailu", "anchor.internal", 7080, "http://127.0.0.1:7080"},
|
||||
{"on another machine (grafana)", "home", "grafana", "home.internal", 20012, "http://home.internal:20012"},
|
||||
{"on another machine, a bare port (influxdb)", "home", "influxdb", "home.internal", 8086, "http://home.internal:8086"},
|
||||
} {
|
||||
container := map[string]any{"type": "container", "name": c.module, "image": "x"}
|
||||
if c.published != nil {
|
||||
container["ports"] = c.published
|
||||
} else {
|
||||
container["network"] = "host"
|
||||
}
|
||||
module := catalogue.Manifest{Module: c.module, Version: "1", Requires: []string{"route"},
|
||||
Listens: []catalogue.Listening{{Name: "web", Port: c.port, Protocol: "tcp", From: "mesh"}},
|
||||
Contributes: map[string]map[string]any{"route": {"label": c.module, "endpoint": "web"}},
|
||||
Resources: []map[string]any{container}}
|
||||
node := catalogue.Node{Name: c.node, At: c.node + ".internal", PublicDomain: "example.org",
|
||||
Capabilities: map[string]bool{"container-runtime": true}}
|
||||
r, err := catalogue.Resolve(map[string]catalogue.Manifest{module.Module: module, proxy.Module: proxy},
|
||||
[]string{module.Module}, node, world)
|
||||
values, _ := json.Marshal(map[string]any{"name": c.module + ".example.org", "port": c.port})
|
||||
contributed, err := catalogue.EncodeContributed(catalogue.ContributedForm{At: c.at,
|
||||
Each: []catalogue.ContributedOne{{Values: values}}})
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v", c.name, err)
|
||||
}
|
||||
r.Account = "op"
|
||||
for i, n := range r.Needs {
|
||||
r.Needs[i].AnsweredByHelper = n.Name == "route" // as the plan sets it (compose's answeredByHelper)
|
||||
}
|
||||
ports := map[int]int{}
|
||||
for _, l := range module.Listens { // compose's portsFor
|
||||
where, mayAssign := module.MachineSide(l.Port)
|
||||
if at, known := c.placed[l.Port]; mayAssign && known {
|
||||
where = at
|
||||
}
|
||||
ports[l.Port] = where
|
||||
}
|
||||
composed, err := r.Compose(catalogue.Rendering{Hands: true, Provisioner: "mesh-provisioner-client",
|
||||
ArtifactStore: "store:5000", Planned: true, Ports: map[string]map[int]int{c.module: ports}})
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v", c.name, err)
|
||||
}
|
||||
value, err := provisions.EncodePlan(provisions.Plan{Node: c.node, Module: c.module, Plan: composed.Plans[c.module]})
|
||||
value, err := provisions.EncodePlan(provisions.Plan{Node: c.node, Module: c.module, Plan: catalogue.Plan{
|
||||
Provisions: []catalogue.PlanProvision{{Provision: contract.Provision, Provider: "anchor",
|
||||
ProviderModule: contract.Module, Contributed: contributed}}}})
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v", c.name, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user