From 3eadff23eb46ef1e94f0781990132aec33dc603e Mon Sep 17 00:00:00 2001 From: mesh-tools Date: Tue, 20 Oct 2026 07:02:58 +0000 Subject: [PATCH] Take the suffix of internal names from the Input and never the environment: Input.InternalSuffix and a local internal-name helper, so the package doc is true (review round 1, finding 5). The test failed first; the suite is 1257 tests in 1.04 s --- go/compose/credentials_test.go | 22 ++++++++++++++++++++++ go/compose/input.go | 4 ++++ go/compose/network.go | 15 ++++++++++++++- go/compose/rendering.go | 14 +++++++------- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/go/compose/credentials_test.go b/go/compose/credentials_test.go index 2974ace..cbf37d4 100644 --- a/go/compose/credentials_test.go +++ b/go/compose/credentials_test.go @@ -447,3 +447,25 @@ func TestAGivenFamilyMemberWithoutItsValueIsAStandInAndNamedForeseen(t *testing. t.Errorf("foreseen %v", got.Foreseen) } } + +// Round 1, finding 5: the suffix internal names end in is a field of the Input, and the environment is never read. +func TestTheInternalSuffixIsTheInputsAndNeverTheEnvironments(t *testing.T) { + t.Setenv(overlay.SuffixVar, "from-the-environment") + in := aGrantMesh(t) + got := rendered(t, in, "anchor", Foreseeing) + if got.Rendering.Suffix != "internal" || got.Rendering.Grants[0].At != "laptop.internal" { + t.Errorf("by default: suffix %q, grant at %q", got.Rendering.Suffix, got.Rendering.Grants[0].At) + } + in.InternalSuffix = ".lan" + got = rendered(t, in, "anchor", Foreseeing) + if got.Rendering.Suffix != "lan" || got.Rendering.Grants[0].At != "laptop.lan" { + t.Errorf("given: suffix %q, grant at %q", got.Rendering.Suffix, got.Rendering.Grants[0].At) + } + where, err := newComposer(in).whereEveryoneIs() + if err != nil || where["anchor"] != "anchor.lan" { + t.Errorf("where everyone is: %v %v", where, err) + } + if names := newComposer(in).namesInTheMesh(); names["anchor.lan"] == "" || names["anchor.internal"] != "" { + t.Errorf("names: %v", names) + } +} diff --git a/go/compose/input.go b/go/compose/input.go index a5d5c7d..a7ffe25 100644 --- a/go/compose/input.go +++ b/go/compose/input.go @@ -12,6 +12,7 @@ // same refusals in the same words, so that a comparison node for node is a fair one. // // It imports the standard library and mesh-sdk's own packages only. +// It reads no environment variable: the range the mesh allocates from and the suffix of its internal names are fields of Input. package compose import ( @@ -42,6 +43,9 @@ type Input struct { // OverlayCIDR is the range the mesh allocates from when no tunnel was adopted, as genesis was told it (the // controller's OverlayCIDRVar); empty means DefaultOverlayCIDR. The package reads no environment. OverlayCIDR string + // InternalSuffix is what the mesh's internal names end in (the controller's MESH_INTERNAL_SUFFIX), with or without a leading + // dot; empty means overlay.DefaultSuffix. A fact of the whole mesh, so it is in the Input and never read from the environment. + InternalSuffix string // Tunnels is, by node name, the found tunnel whose key is the node's overlay key (inv.Tunnels). Tunnels map[string]FoundTunnel // Adopted is the hub's found tunnel and the hub's name, whether or not the hub took it (inv.AdoptedTunnel); nil diff --git a/go/compose/network.go b/go/compose/network.go index ef01f70..de789c6 100644 --- a/go/compose/network.go +++ b/go/compose/network.go @@ -37,6 +37,19 @@ func (c *composer) say(format string, args ...any) { c.said = append(c.said, line) } +// suffix is what the mesh's internal names end in: the Input's, and overlay.DefaultSuffix when it gives none. The package never calls +// overlay.Suffix or overlay.InternalName, which read the environment, so the assigner and the controller compose the same names +// from the same Input. +func (c *composer) suffix() string { + if v := strings.TrimPrefix(strings.TrimSpace(c.in.InternalSuffix), "."); v != "" { + return v + } + return overlay.DefaultSuffix +} + +// internalName is a node's name inside the mesh. +func (c *composer) internalName(node string) string { return node + "." + c.suffix() } + // overlayRange is the range the mesh allocates node addresses from: the adopted tunnel's first (novox/hq ADR 0105), // then the range genesis was told, then the default. func (c *composer) overlayRange() string { @@ -203,7 +216,7 @@ func (c *composer) whereEveryoneIs() (map[string]string, error) { } out := map[string]string{} for _, p := range c.onTheNetwork() { - out[p.Name] = overlay.InternalName(p.Name) + out[p.Name] = c.internalName(p.Name) } return out, nil } diff --git a/go/compose/rendering.go b/go/compose/rendering.go index c54e571..468683d 100644 --- a/go/compose/rendering.go +++ b/go/compose/rendering.go @@ -120,7 +120,7 @@ func (c *composer) places(nodeName string, resolved Resolved) (Placed, error) { // And who holds each replicated seat, where (novox/hq ADR 0223). r.Holders = c.replicatedHolders() - r.Suffix, r.TunnelInterface = overlay.Suffix(), overlay.Interface + r.Suffix, r.TunnelInterface = c.suffix(), overlay.Interface // And, for a module that keeps them, every operator-sealed secret in the mesh (novox/hq ADR 0085, amended). for _, m := range plan.Modules { @@ -272,16 +272,16 @@ func (c *composer) onThePrivateNetwork() []string { func (c *composer) namesInTheMesh() map[string]string { out := map[string]string{} for _, p := range c.onTheNetwork() { - out[overlay.InternalName(p.Name)] = p.Place.Address + out[c.internalName(p.Name)] = p.Place.Address } for _, p := range c.in.CarriedPeers { if p.Named == "" || p.EnrolledAs != "" { continue } - if _, taken := out[overlay.InternalName(p.Named)]; taken { + if _, taken := out[c.internalName(p.Named)]; taken { continue // a node of the mesh owns the name; the stale statement loses } - out[overlay.InternalName(p.Named)] = p.Address + out[c.internalName(p.Named)] = p.Address } return out } @@ -342,7 +342,7 @@ func (c *composer) artifactStoreAddress(forNode string) (string, error) { return "", err } if found { - return overlay.InternalName(node) + ":" + port, nil + return c.internalName(node) + ":" + port, nil } all := map[string]bool{} for _, n := range c.in.Nodes { @@ -399,7 +399,7 @@ func (c *composer) zonesInTheMesh() ([]catalogue.ZoneAt, error) { zones = append(zones, *z) } } - if problems := catalogue.ZonesProblems(zones, overlay.Suffix(), public); len(problems) > 0 { + if problems := catalogue.ZonesProblems(zones, c.suffix(), public); len(problems) > 0 { return nil, fmt.Errorf("the mesh's zones cannot be forwarded:\n - %s", strings.Join(problems, "\n - ")) } return zones, nil @@ -458,7 +458,7 @@ func (c *composer) replicatedHolders() map[string]map[string]string { at := map[string]string{} for _, n := range nodes { if address[n] != "" { - at[overlay.InternalName(n)] = address[n] + at[c.internalName(n)] = address[n] } } out[seat.Name] = at