From 8cf7b6d1fb2056299784c4089b2a8001dd55ebc8 Mon Sep 17 00:00:00 2001 From: Joe Riddle Date: Mon, 23 Mar 2026 16:57:39 -0600 Subject: [PATCH] feat: add Cluster to monitoring LeafInfo Signed-off-by: Joe Riddle --- server/monitor.go | 2 ++ server/monitor_test.go | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/server/monitor.go b/server/monitor.go index c6a932be73b..75e85aea325 100644 --- a/server/monitor.go +++ b/server/monitor.go @@ -2364,6 +2364,7 @@ type LeafzOptions struct { type LeafInfo struct { ID uint64 `json:"id"` Name string `json:"name"` + Cluster string `json:"cluster,omitempty"` IsSpoke bool `json:"is_spoke"` IsIsolated bool `json:"is_isolated,omitempty"` Account string `json:"account"` @@ -2409,6 +2410,7 @@ func (s *Server) Leafz(opts *LeafzOptions) (*Leafz, error) { lni := &LeafInfo{ ID: ln.cid, Name: ln.leaf.remoteServer, + Cluster: ln.leaf.remoteCluster, IsSpoke: ln.isSpokeLeafNode(), IsIsolated: ln.leaf.isolated, Account: ln.acc.Name, diff --git a/server/monitor_test.go b/server/monitor_test.go index 9110c686b9d..125fd366e27 100644 --- a/server/monitor_test.go +++ b/server/monitor_test.go @@ -4263,6 +4263,57 @@ func TestMonitorLeafz(t *testing.T) { } } +func TestMonitorLeafzCluster(t *testing.T) { + hubConf := createConfFile(t, []byte(` + server_name: "hub" + listen: "127.0.0.1:-1" + http: "127.0.0.1:-1" + leafnodes { + listen: "127.0.0.1:-1" + } + `)) + hub, hubOpts := RunServerWithConfig(hubConf) + defer hub.Shutdown() + + leafConf := createConfFile(t, []byte(fmt.Sprintf(` + server_name: "leaf1" + listen: "127.0.0.1:-1" + cluster { + name: "leaf-cluster" + listen: "127.0.0.1:-1" + } + leafnodes { + remotes = [{ + url: "nats-leaf://127.0.0.1:%d" + }] + } + `, hubOpts.LeafNode.Port))) + leaf, _ := RunServerWithConfig(leafConf) + defer leaf.Shutdown() + + checkLeafNodeConnected(t, leaf) + + // Make sure the hub sees the remote cluster name of the leaf node. + l, err := hub.Leafz(nil) + require_NoError(t, err) + require_Equal(t, l.NumLeafs, 1) + require_Equal(t, len(l.Leafs), 1) + require_Equal(t, l.Leafs[0].Cluster, "leaf-cluster") + require_Equal(t, l.Leafs[0].Name, "leaf1") + + // Make sure from the leaf's perspective, the hub has no cluster. + l, err = leaf.Leafz(nil) + require_NoError(t, err) + require_Equal(t, l.NumLeafs, 1) + require_Equal(t, len(l.Leafs), 1) + require_Equal(t, l.Leafs[0].Cluster, "") + require_Equal(t, l.Leafs[0].Name, "hub") + + // Make sure that cluster is present in the HTTP response as well. + body := readBody(t, fmt.Sprintf("http://127.0.0.1:%d/leafz", hub.MonitorAddr().Port)) + require_True(t, strings.Contains(string(body), `"cluster": "leaf-cluster"`)) +} + func pollAccountz(t *testing.T, s *Server, mode int, url string, opts *AccountzOptions) *Accountz { t.Helper() if mode == 0 {