mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 22:46:57 +00:00
159 lines
3.5 KiB
Go
159 lines
3.5 KiB
Go
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/DeBrosOfficial/network/pkg/cli/monitor"
|
|
)
|
|
|
|
// renderNamespacesTab renders per-namespace health across all nodes.
|
|
func renderNamespacesTab(snap *monitor.ClusterSnapshot, width int) string {
|
|
if snap == nil {
|
|
return styleMuted.Render("Collecting cluster data...")
|
|
}
|
|
|
|
reports := snap.Healthy()
|
|
if len(reports) == 0 {
|
|
return styleMuted.Render("No healthy nodes to display.")
|
|
}
|
|
|
|
var b strings.Builder
|
|
|
|
b.WriteString(styleBold.Render("Namespace Health"))
|
|
b.WriteString("\n")
|
|
b.WriteString(separator(width))
|
|
b.WriteString("\n\n")
|
|
|
|
// Collect unique namespace names
|
|
nsSet := make(map[string]bool)
|
|
for _, r := range reports {
|
|
for _, ns := range r.Namespaces {
|
|
nsSet[ns.Name] = true
|
|
}
|
|
}
|
|
|
|
nsNames := make([]string, 0, len(nsSet))
|
|
for name := range nsSet {
|
|
nsNames = append(nsNames, name)
|
|
}
|
|
sort.Strings(nsNames)
|
|
|
|
if len(nsNames) == 0 {
|
|
return styleMuted.Render("No namespaces found on any node.")
|
|
}
|
|
|
|
// Header
|
|
header := fmt.Sprintf(" %-20s", headerStyle.Render("NAMESPACE"))
|
|
for _, r := range reports {
|
|
host := nodeHost(r)
|
|
if len(host) > 15 {
|
|
host = host[:15]
|
|
}
|
|
header += fmt.Sprintf(" %-17s", headerStyle.Render(host))
|
|
}
|
|
b.WriteString(header)
|
|
b.WriteString("\n")
|
|
|
|
// Build lookup: host -> ns name -> NamespaceReport
|
|
type nsKey struct {
|
|
host string
|
|
name string
|
|
}
|
|
nsMap := make(map[nsKey]nsStatus)
|
|
for _, r := range reports {
|
|
host := nodeHost(r)
|
|
for _, ns := range r.Namespaces {
|
|
nsMap[nsKey{host, ns.Name}] = nsStatus{
|
|
gateway: ns.GatewayUp,
|
|
rqlite: ns.RQLiteUp,
|
|
rqliteState: ns.RQLiteState,
|
|
rqliteReady: ns.RQLiteReady,
|
|
olric: ns.OlricUp,
|
|
}
|
|
}
|
|
}
|
|
|
|
// Rows
|
|
for _, nsName := range nsNames {
|
|
row := fmt.Sprintf(" %-20s", nsName)
|
|
for _, r := range reports {
|
|
host := nodeHost(r)
|
|
ns, ok := nsMap[nsKey{host, nsName}]
|
|
if !ok {
|
|
row += fmt.Sprintf(" %-17s", styleMuted.Render("-"))
|
|
continue
|
|
}
|
|
row += fmt.Sprintf(" %-17s", renderNsCell(ns))
|
|
}
|
|
b.WriteString(row)
|
|
b.WriteString("\n")
|
|
}
|
|
|
|
// Detailed per-namespace view
|
|
b.WriteString("\n")
|
|
b.WriteString(styleBold.Render("Namespace Details"))
|
|
b.WriteString("\n")
|
|
b.WriteString(separator(width))
|
|
b.WriteString("\n")
|
|
|
|
for _, nsName := range nsNames {
|
|
b.WriteString(fmt.Sprintf("\n %s\n", styleBold.Render(nsName)))
|
|
for _, r := range reports {
|
|
host := nodeHost(r)
|
|
for _, ns := range r.Namespaces {
|
|
if ns.Name != nsName {
|
|
continue
|
|
}
|
|
b.WriteString(fmt.Sprintf(" %-18s gw=%s rqlite=%s",
|
|
host,
|
|
statusStr(ns.GatewayUp),
|
|
statusStr(ns.RQLiteUp),
|
|
))
|
|
if ns.RQLiteState != "" {
|
|
b.WriteString(fmt.Sprintf("(%s)", ns.RQLiteState))
|
|
}
|
|
b.WriteString(fmt.Sprintf(" olric=%s", statusStr(ns.OlricUp)))
|
|
if ns.PortBase > 0 {
|
|
b.WriteString(fmt.Sprintf(" port=%d", ns.PortBase))
|
|
}
|
|
b.WriteString("\n")
|
|
}
|
|
}
|
|
}
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// nsStatus holds a namespace's health indicators for one node.
|
|
type nsStatus struct {
|
|
gateway bool
|
|
rqlite bool
|
|
rqliteState string
|
|
rqliteReady bool
|
|
olric bool
|
|
}
|
|
|
|
// renderNsCell renders a compact cell for the namespace matrix.
|
|
func renderNsCell(ns nsStatus) string {
|
|
if ns.gateway && ns.rqlite && ns.olric {
|
|
return styleHealthy.Render("OK")
|
|
}
|
|
if !ns.gateway && !ns.rqlite {
|
|
return styleCritical.Render("DOWN")
|
|
}
|
|
// Partial
|
|
parts := []string{}
|
|
if !ns.gateway {
|
|
parts = append(parts, "gw")
|
|
}
|
|
if !ns.rqlite {
|
|
parts = append(parts, "rq")
|
|
}
|
|
if !ns.olric {
|
|
parts = append(parts, "ol")
|
|
}
|
|
return styleWarning.Render("!" + strings.Join(parts, ","))
|
|
}
|