The mesh runs on the seat's bus alone (novox/hq ADR 0131, design 28 task 5.5). The old transport's consume loop, build request, tool ask, management API and account scoping are deleted, and the bus switch with them; the controller connects to the broker seat and to nothing else. The store-window tests keep their assertions on a bus-less fake, and the tests that only made sense for the old transport's in-memory holding go with it.
84 lines
2.9 KiB
Go
84 lines
2.9 KiB
Go
package broker
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/novox/mesh-controller/internal/envfile"
|
|
)
|
|
|
|
// Whether this mesh's own traffic is on the bus being built.
|
|
//
|
|
// **One switch, read in one place** (novox/hq ADR 0116 step 5). Every seam the bus change went
|
|
// behind ships both implementations, and until the rollout every one of them chooses the bus the
|
|
// mesh runs on today. This is what the rollout flips, and it is deliberately a single fact rather
|
|
// than a fact per component: a controller whose outbound is on one bus and whose inbound is on the
|
|
// other is a mesh that hears nothing, and no test of either half would catch it.
|
|
|
|
// NATSVar is where the controller finds the bus being built. Unset is the ordinary case and means
|
|
// the mesh runs on the bus it has always run on.
|
|
const NATSVar = "MESH_BUS_NATS"
|
|
|
|
// OnNATS is the address of the bus being built, and whether the mesh is on it.
|
|
//
|
|
// Read from the node's own settings rather than baked in, for the reason the broker's address is
|
|
// (novox/hq 04-ISSUES/102): an address recorded once does not follow a node's ports.
|
|
func OnNATS() (address string, on bool, err error) {
|
|
address, err = envfile.Placed(NATSVar)
|
|
if err != nil {
|
|
return "", false, err
|
|
}
|
|
address = strings.TrimSpace(address)
|
|
if address == "" {
|
|
return "", false, nil
|
|
}
|
|
return address, true, nil
|
|
}
|
|
|
|
// CredentialIn reads the user and password out of a bus address, and the address without them.
|
|
//
|
|
// The controller's own credential arrives in its address, the way the old bus's does. Split out so the
|
|
// controller can record a hash of what it is actually using: its user is created by the installer at a
|
|
// bootstrap password, before the controller exists to mint one, and a composition that left itself out
|
|
// would produce a bus the writer cannot connect to.
|
|
func CredentialIn(address string) (user, password, bare string) {
|
|
at := strings.LastIndex(address, "@")
|
|
if at < 0 {
|
|
return "", "", address
|
|
}
|
|
scheme := ""
|
|
rest := address[:at]
|
|
if i := strings.Index(rest, "://"); i >= 0 {
|
|
scheme, rest = rest[:i+3], rest[i+3:]
|
|
}
|
|
user, password, _ = strings.Cut(rest, ":")
|
|
return user, password, scheme + address[at+1:]
|
|
}
|
|
|
|
// BareAddress is a bus address with any credential stripped, for something that only needs to know
|
|
// whether a server is answering there.
|
|
func BareAddress(address string) string {
|
|
_, _, bare := CredentialIn(address)
|
|
if bare == "" {
|
|
return address
|
|
}
|
|
if strings.Contains(bare, "://") {
|
|
return bare
|
|
}
|
|
return "nats://" + bare
|
|
}
|
|
|
|
// BusAddress is where the mesh's bus is, with this process's credential, and refuses to be empty:
|
|
// there is one bus, and a control plane without it can hold records and answer nothing (novox/hq
|
|
// ADR 0131, design 28 task 5.5).
|
|
func BusAddress() (string, error) {
|
|
address, _, err := OnNATS()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if address == "" {
|
|
return "", fmt.Errorf("this control plane has no %s, so it cannot reach the mesh's bus", NATSVar)
|
|
}
|
|
return address, nil
|
|
}
|