Merge pull request 'A cross-node module reaches the broker by the hub's overlay name' (#27) from multi-node/broker-reaches-over-overlay into main

This commit was merged in pull request #27.
This commit is contained in:
2026-09-17 01:44:41 +02:00
2 changed files with 46 additions and 2 deletions
+6 -1
View File
@@ -216,6 +216,11 @@ func builderCommand(ctx context.Context, args []string) error {
}
defer inv.Close()
brokerAddr, err := brokerReachableAt(ctx, inv, known, *forNode)
if err != nil {
return err
}
// The URL and what verifies the broker, together. A mesh's broker presents a certificate
// of the mesh's own, which is in no public trust store — so a URL on its own reaches only
// a broker somebody else vouches for, and the connection fails at TLS with an error about
@@ -228,7 +233,7 @@ func builderCommand(ctx context.Context, args []string) error {
URL string `json:"url"`
Fingerprint string `json:"fingerprint,omitempty"`
}{
URL: fmt.Sprintf("amqps://%s:%s@%s/", name, password, known.Address),
URL: fmt.Sprintf("amqps://%s:%s@%s/", name, password, brokerAddr),
Fingerprint: known.Fingerprint,
})
if err != nil {
+40 -1
View File
@@ -8,6 +8,7 @@ import (
"errors"
"flag"
"fmt"
"net"
"os"
"sort"
"strings"
@@ -283,6 +284,10 @@ func moduleCommand(ctx context.Context, args []string) error {
if err != nil {
return fmt.Errorf("cannot deliver a credential without knowing where the broker is: %w", err)
}
brokerAddr, err := brokerReachableAt(ctx, inv, known, *forNode)
if err != nil {
return err
}
// The URL and what verifies the broker, together — a mesh's broker presents its own
// certificate, in no public trust store, so a URL alone fails at TLS (as `builder issue`).
held, err := json.Marshal(struct {
@@ -291,7 +296,7 @@ func moduleCommand(ctx context.Context, args []string) error {
Node string `json:"node"`
Module string `json:"module"`
}{
URL: fmt.Sprintf("amqps://%s:%s@%s/", account, password, known.Address),
URL: fmt.Sprintf("amqps://%s:%s@%s/", account, password, brokerAddr),
Fingerprint: known.Fingerprint,
// The node and module the account is for, so the runtime names its queue as the mesh
// scoped it (<node>.<module>.events) without a manifest having to interpolate a node.
@@ -461,3 +466,37 @@ func pinCommand(ctx context.Context, args []string, setting bool) error {
fmt.Printf(" run `push %s` to send it\n", args[0])
return nil
}
// brokerReachableAt is the broker's address as the given node can reach it.
//
// The genesis address (MESH_BROKER_ADDRESS) is the broker's public endpoint — reachable from the
// control-node itself, but not routed to another node, whose firewall admits only the overlay
// (from:mesh). The foundation, and so the broker, sits on the control-node, which is the overlay
// hub; a node that is on the overlay reaches the broker by the hub's `.internal` name, which the
// firewall admits and every node resolves. A node not yet on the overlay — at genesis, before any
// `overlay place`, which is when the builder's account is issued — keeps the genesis address it
// was given, so nothing about bring-up changes. This is issue 055.
func brokerReachableAt(ctx context.Context, inv *inventory.Inventory, known broker.Broker, node string) (string, error) {
overlays, err := inv.Overlays(ctx)
if err != nil {
return "", err
}
var hub string
onOverlay := false
for _, o := range overlays {
if o.Hub && o.Address != "" {
hub = o.Name
}
if o.Name == node && o.Address != "" {
onOverlay = true
}
}
if hub == "" || !onOverlay {
return known.Address, nil
}
_, port, err := net.SplitHostPort(known.Address)
if err != nil {
return known.Address, nil
}
return net.JoinHostPort(overlay.InternalName(hub), port), nil
}