Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 0 additions & 161 deletions cmd/unbounded-net-controller/cluster_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,6 @@ func fetchClusterStatus(ctx context.Context, health *healthState, pullEnabled bo
}

sort.Slice(status.Peerings, func(i, j int) bool { return status.Peerings[i].Name < status.Peerings[j].Name })
status.ConnectivityMatrix = buildConnectivityMatrix(status.Nodes, status.GatewayPools)
status.Problems = collectClusterProblems(status)

return status
Expand Down Expand Up @@ -1038,163 +1037,3 @@ func latestNodeUpdateTime(node *corev1.Node) time.Time {

return latest
}

// buildConnectivityMatrix builds health check connectivity matrices from node peer data.
func buildConnectivityMatrix(nodes []*NodeStatusResponse, gatewayPools []GatewayPoolStatus) map[string]*SiteMatrix {
siteNodes := make(map[string]map[string]bool)
nodePeers := make(map[string][]WireGuardPeerStatus)
nodeByName := make(map[string]*NodeStatusResponse)

for _, n := range nodes {
name := n.NodeInfo.Name

site := n.NodeInfo.SiteName
if name == "" || site == "" {
continue
}

nodeByName[name] = n

if siteNodes[site] == nil {
siteNodes[site] = make(map[string]bool)
}

siteNodes[site][name] = true

// Keep the immutable snapshot's slice; filter when reading rather
// than copying every peer, including for scopes above the size limit.
nodePeers[name] = n.Peers

for _, p := range n.Peers {
if p.PeerType == "gateway" && p.Name != "" && p.SiteName == site {
siteNodes[site][p.Name] = true
}
}
}

if len(siteNodes) == 0 {
siteNodes = make(map[string]map[string]bool)
}

result := make(map[string]*SiteMatrix)
selfMatrixStatusFromCNI := func(node *NodeStatusResponse) string {
if node.NodeInfo.WireGuard != nil && strings.TrimSpace(node.NodeInfo.WireGuard.Interface) != "" {
return "up"
}

return ""
}

buildScopeMatrix := func(nodeSet map[string]bool) *SiteMatrix {
if len(nodeSet) == 0 || len(nodeSet) > 100 {
return nil
}

nodeNames := make([]string, 0, len(nodeSet))
for name := range nodeSet {
nodeNames = append(nodeNames, name)
}

sort.Strings(nodeNames)

results := make(map[string]map[string]string)
for _, srcNode := range nodeNames {
results[srcNode] = make(map[string]string)
if node, ok := nodeByName[srcNode]; ok {
results[srcNode][srcNode] = selfMatrixStatusFromCNI(node)
}

for _, peer := range nodePeers[srcNode] {
if !isConnectivityMatrixPeer(peer) {
continue
}

tgtNode := peer.Name
if tgtNode == "" || tgtNode == srcNode || !nodeSet[tgtNode] {
continue
}

cellStatus := ""
if peer.HealthCheck != nil {
cellStatus = peer.HealthCheck.Status
} else if peer.PeerType == "gateway" && !peer.Tunnel.LastHandshake.IsZero() {
cellStatus = "up"
}

results[srcNode][tgtNode] = cellStatus
}
}

return &SiteMatrix{Nodes: nodeNames, Results: results}
}

for site, nodeSet := range siteNodes {
scopeMatrix := buildScopeMatrix(nodeSet)
if scopeMatrix != nil {
result[site] = scopeMatrix
}
}

for _, pool := range gatewayPools {
poolName := strings.TrimSpace(pool.Name)
if poolName == "" {
continue
}

poolNodeSet := make(map[string]bool)

for _, gatewayName := range pool.Gateways {
name := strings.TrimSpace(gatewayName)
if name == "" {
continue
}

poolNodeSet[name] = true
for _, peer := range nodePeers[name] {
if !isConnectivityMatrixPeer(peer) {
continue
}

peerName := strings.TrimSpace(peer.Name)
if peerName == "" {
continue
}

if _, ok := nodeByName[peerName]; ok {
poolNodeSet[peerName] = true
}
}

for srcNodeName, peers := range nodePeers {
for _, peer := range peers {
if !isConnectivityMatrixPeer(peer) {
continue
}

if strings.TrimSpace(peer.Name) == name {
if _, ok := nodeByName[srcNodeName]; ok {
poolNodeSet[srcNodeName] = true
}

break
}
}
}
}

scopeMatrix := buildScopeMatrix(poolNodeSet)
if scopeMatrix != nil {
result["pool:"+poolName] = scopeMatrix
}
}

if len(result) == 0 {
return nil
}

return result
}

func isConnectivityMatrixPeer(peer WireGuardPeerStatus) bool {
return peer.PeerType == "site" || peer.PeerType == "gateway"
}
83 changes: 0 additions & 83 deletions cmd/unbounded-net-controller/cluster_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"fmt"
"slices"
"strconv"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -447,88 +446,6 @@ func TestNodeReadinessAndLatestUpdateTime(t *testing.T) {
}
}

// TestBuildConnectivityMatrix tests BuildConnectivityMatrix.
func TestBuildConnectivityMatrix(t *testing.T) {
now := time.Now().Add(-75 * time.Second)

nodes := []*NodeStatusResponse{
{
NodeInfo: NodeInfo{Name: "node-a", SiteName: "site-a", WireGuard: &WireGuardStatusInfo{Interface: "wg51820"}},
Peers: []WireGuardPeerStatus{
{Name: "node-b", PeerType: "site", HealthCheck: &HealthCheckPeerStatus{Status: "up", Uptime: "15s"}},
{Name: "gw-a", PeerType: "gateway", SiteName: "site-a", Tunnel: PeerTunnelStatus{LastHandshake: now}},
{Name: "gw-remote", PeerType: "gateway", SiteName: "site-b", Tunnel: PeerTunnelStatus{LastHandshake: now}},
},
},
{
NodeInfo: NodeInfo{Name: "node-b", SiteName: "site-a"},
Peers: []WireGuardPeerStatus{
{Name: "node-a", PeerType: "site", HealthCheck: &HealthCheckPeerStatus{Status: "down", Uptime: "3s"}},
},
},
}
for i := 0; i < 101; i++ {
nodes = append(nodes, &NodeStatusResponse{NodeInfo: NodeInfo{Name: "big-" + strconv.Itoa(i), SiteName: "site-big"}})
}

gatewayPools := []GatewayPoolStatus{{
Name: "pool-a",
Gateways: []string{"gw-a"},
}}

matrix := buildConnectivityMatrix(nodes, gatewayPools)
if matrix == nil {
t.Fatalf("expected non-nil connectivity matrix")
}

if _, ok := matrix["site-big"]; ok {
t.Fatalf("expected site-big to be skipped when >100 nodes")
}

site := matrix["site-a"]
if site == nil {
t.Fatalf("expected site-a matrix")
}

if !slices.Equal(site.Nodes, []string{"gw-a", "node-a", "node-b"}) {
t.Fatalf("unexpected node list: %#v", site.Nodes)
}

if got := site.Results["node-a"]["node-b"]; got != "up" {
t.Fatalf("unexpected node-a->node-b status: %q", got)
}

gatewayCell := site.Results["node-a"]["gw-a"]
if gatewayCell != "up" {
t.Fatalf("unexpected gateway fallback cell: %q", gatewayCell)
}

if _, ok := site.Results["node-a"]["gw-remote"]; ok {
t.Fatalf("did not expect remote-site gateway in site matrix")
}

if got := site.Results["node-a"]["node-a"]; got != "up" {
t.Fatalf("expected self cell for node-a to be up from CNI health, got %q", got)
}

if got := site.Results["node-b"]["node-b"]; got != "" {
t.Fatalf("expected self cell for node-b to be unknown when CNI health is unavailable, got %q", got)
}

pool := matrix["pool:pool-a"]
if pool == nil {
t.Fatalf("expected pool:pool-a matrix")
}

if !slices.Equal(pool.Nodes, []string{"gw-a", "node-a"}) {
t.Fatalf("unexpected pool node list: %#v", pool.Nodes)
}

if got := pool.Results["node-a"]["gw-a"]; got != "up" {
t.Fatalf("unexpected node-a->gw-a pool status: %q", got)
}
}

// TestCollectClusterProblemsIncludesUnhealthySignals tests CollectClusterProblemsIncludesUnhealthySignals.
func TestCollectClusterProblemsIncludesUnhealthySignals(t *testing.T) {
expectedTrue := true
Expand Down
113 changes: 0 additions & 113 deletions cmd/unbounded-net-controller/matrix_memory_test.go

This file was deleted.

Loading