What remains of names.go is the naming

The hosts-file writing moved to the node-names fact; what stays is the suffix
(configurable, MESH_INTERNAL_SUFFIX, defaulting to .internal which IANA reserved
for exactly this), a node's internal name, and the rule for what a node may be
called. Several things compose an internal name, and one of them writing the
suffix differently would be a name nothing answers to.

First attempt at this rewrote the file from memory and silently dropped the
configurable suffix. Restored from the original instead — deleting most of a
file is git surgery, not paraphrase.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
2026-09-15 21:33:20 +02:00
parent fcdb065660
commit b8cacbaf4d
3 changed files with 12 additions and 177 deletions
+4 -52
View File
@@ -1,10 +1,8 @@
package overlay
import (
"fmt"
"os"
"regexp"
"sort"
"strings"
)
@@ -49,53 +47,7 @@ var nodeName = regexp.MustCompile(`^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$`)
// InternalName is a node's name inside the mesh.
func InternalName(node string) string { return node + "." + Suffix() }
// Hosts writes the name file for one node.
//
// Every node in the mesh, including this one. Including itself because a machine referring to
// itself by its mesh name should get its overlay address rather than a loopback — otherwise a
// service that binds to the name it was given ends up unreachable from everywhere else.
//
// The machine's own loopback lines come first and are not the mesh's to have an opinion about,
// but they have to be here: this file is generated whole, so anything left out is removed.
func Hosts(nodes []Node, self string) (string, error) {
var b strings.Builder
b.WriteString("# Generated by the mesh. Do not edit — this file is replaced whenever a node\n")
b.WriteString("# joins or leaves, and an edit would survive until then and vanish.\n\n")
// The floor every Linux expects, and which removing would break things that have nothing to
// do with the mesh.
b.WriteString("127.0.0.1\tlocalhost\n")
b.WriteString("::1\t\tlocalhost ip6-localhost ip6-loopback\n")
if self != "" {
fmt.Fprintf(&b, "127.0.1.1\t%s\n", self)
}
named := make([]Node, 0, len(nodes))
for _, n := range nodes {
if n.Address == "" {
// A node with no address on the network has no name here. Writing one that resolves
// to nothing is worse than not writing it: a connection to an address that does not
// answer hangs, where a name that does not resolve fails at once and says so.
continue
}
if !nodeName.MatchString(n.Name) {
return "", fmt.Errorf(
"%q cannot be a mesh name: it becomes a hostname, so it is lower-case letters, "+
"digits and dashes", n.Name)
}
named = append(named, n)
}
sort.Slice(named, func(i, j int) bool { return named[i].Name < named[j].Name })
if len(named) > 0 {
fmt.Fprintf(&b, "\n# the mesh, %d node(s)\n", len(named))
}
for _, n := range named {
line := fmt.Sprintf("%s\t%s\t%s", n.Address, InternalName(n.Name), n.Name)
if n.Name == self {
line += "\t# this machine"
}
b.WriteString(line + "\n")
}
return b.String(), nil
}
// **What remains of a larger file.** The rest wrote /etc/hosts — that is the `node-names` fact now
// (catalogue.FactsInto), computed where the graph lives instead of by a module that ran nothing.
// The naming stays here, because several things compose a node's internal name and one of them
// writing the suffix differently would be a name nothing answers to.