diff --git a/README.md b/README.md index fc00e2ed..98ff5603 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Proxmox Biggie (Cron every 5min) ### Automation -- Script: `~/scripts/noc_update.py` running on Biggie (`10.10.30.192`) +- Script: `~/scripts/noc_update.py` running on Biggie - Cron: `*/5 * * * *` — every 5 minutes - Log: `/var/log/noc_update.log` - Auth: GitHub Personal Access Token via baked remote URL diff --git a/data/noc-status.json b/data/noc-status.json index 9bab61ff..51e9957f 100644 --- a/data/noc-status.json +++ b/data/noc-status.json @@ -10,198 +10,198 @@ }, "systems": [ { - "name": "Proxmox \u2014 BigWorld", + "name": "Proxmox — BigWorld", "type": "Proxmox VE Hypervisor", "layer": "Infrastructure", "label": "Compute", - "address": "10.10.30.250", + "address": "BigWorld", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "Proxmox \u2014 Biggie", + "name": "Proxmox — Biggie", "type": "Proxmox VE Hypervisor", "layer": "Infrastructure", "label": "Compute", - "address": "10.10.30.192", + "address": "Biggie", "status": "Online", "severity": "Healthy", "latency": "0.1ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "Proxmox \u2014 Snoop", + "name": "Proxmox — Snoop", "type": "Proxmox VE Hypervisor", "layer": "Infrastructure", "label": "Compute", - "address": "10.10.30.153", + "address": "Snoop", "status": "Online", "severity": "Healthy", "latency": "0.7ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "Proxmox \u2014 TooShort", + "name": "Proxmox — TooShort", "type": "Proxmox VE Hypervisor", "layer": "Infrastructure", "label": "Compute", - "address": "10.10.30.120", + "address": "TooShort", "status": "Online", "severity": "Healthy", "latency": "0.4ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "Proxmox \u2014 Tupac", + "name": "Proxmox — Tupac", "type": "Proxmox VE Hypervisor", "layer": "Infrastructure", "label": "Compute", - "address": "10.10.30.74", + "address": "Tupac", "status": "Online", "severity": "Healthy", "latency": "0.5ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "Proxmox \u2014 DrDre", + "name": "Proxmox — DrDre", "type": "Proxmox VE Hypervisor", "layer": "Infrastructure", "label": "Compute", - "address": "10.10.30.227", + "address": "DrDre", "status": "Online", "severity": "Healthy", "latency": "0.5ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Control \u2014 django-1", + "name": "K3s Control — django-1", "type": "K3s Control Plane", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.72", + "address": "k3s-django-1", "status": "Online", "severity": "Healthy", "latency": "0.3ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Control \u2014 django-2", + "name": "K3s Control — django-2", "type": "K3s Control Plane", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.245", + "address": "k3s-django-2", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Control \u2014 django-3", + "name": "K3s Control — django-3", "type": "K3s Control Plane", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.128", + "address": "k3s-django-3", "status": "Online", "severity": "Healthy", "latency": "0.3ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Ingress \u2014 node-1", + "name": "K3s Ingress — node-1", "type": "K3s Worker / Ingress", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.219", + "address": "k3s-node-1", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Ingress \u2014 node-2", + "name": "K3s Ingress — node-2", "type": "K3s Worker / Ingress", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.134", + "address": "k3s-node-2", "status": "Online", "severity": "Healthy", "latency": "0.3ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Ingress \u2014 node-3", + "name": "K3s Ingress — node-3", "type": "K3s Worker / Ingress", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.222", + "address": "k3s-node-3", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Data \u2014 node-4", + "name": "K3s Data — node-4", "type": "K3s Worker / Data", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.126", + "address": "k3s-node-4", "status": "Online", "severity": "Healthy", "latency": "0.3ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Data \u2014 node-5", + "name": "K3s Data — node-5", "type": "K3s Worker / Data", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.239", + "address": "k3s-node-5", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Data \u2014 node-6", + "name": "K3s Data — node-6", "type": "K3s Worker / Data", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.208", + "address": "k3s-node-6", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Monitor \u2014 node-7", + "name": "K3s Monitor — node-7", "type": "K3s Worker / Monitoring", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.198", + "address": "k3s-node-7", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Monitor \u2014 node-8", + "name": "K3s Monitor — node-8", "type": "K3s Worker / Monitoring", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.216", + "address": "k3s-node-8", "status": "Online", "severity": "Healthy", "latency": "0.2ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "K3s Monitor \u2014 node-9", + "name": "K3s Monitor — node-9", "type": "K3s Worker / Monitoring", "layer": "Orchestration", "label": "K3s", - "address": "10.10.30.29", + "address": "k3s-node-9", "status": "Online", "severity": "Healthy", "latency": "0.2ms", @@ -212,7 +212,7 @@ "type": "Network Attached Storage", "layer": "Infrastructure", "label": "Storage", - "address": "10.10.30.143", + "address": "TrueNAS", "status": "Online", "severity": "Healthy", "latency": "0.6ms", @@ -223,7 +223,7 @@ "type": "Reverse Proxy", "layer": "Networking", "label": "Access", - "address": "10.10.30.210", + "address": "NPM", "status": "Online", "severity": "Healthy", "latency": "0.3ms", @@ -234,7 +234,7 @@ "type": "Metrics Collection", "layer": "Monitoring", "label": "Observability", - "address": "10.10.30.140", + "address": "Prometheus", "status": "Online", "severity": "Healthy", "latency": "0.2ms", @@ -245,7 +245,7 @@ "type": "Metrics Dashboard", "layer": "Monitoring", "label": "Observability", - "address": "10.10.30.68", + "address": "Grafana", "status": "Online", "severity": "Healthy", "latency": "0.2ms", @@ -256,7 +256,7 @@ "type": "Service Monitor", "layer": "Monitoring", "label": "Observability", - "address": "10.10.30.14", + "address": "Uptime Kuma", "status": "Online", "severity": "Healthy", "latency": "0.3ms", @@ -267,7 +267,7 @@ "type": "HomeLab Dashboard", "layer": "Services", "label": "Dashboard", - "address": "10.10.30.61", + "address": "Dashy", "status": "Online", "severity": "Healthy", "latency": "0.2ms", @@ -278,7 +278,7 @@ "type": "Home Automation", "layer": "Services", "label": "Automation", - "address": "10.10.30.104", + "address": "Home Assistant", "status": "Offline", "severity": "Critical", "latency": "N/A", @@ -289,29 +289,29 @@ "type": "Media / Game Server", "layer": "Services", "label": "Media", - "address": "10.10.30.233", + "address": "PrimeStation", "status": "Online", "severity": "Healthy", "latency": "0.4ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "APRS iGate \u2014 Home", + "name": "APRS iGate — Home", "type": "RF Edge / APRS-IS Gateway", "layer": "Edge", "label": "RF", - "address": "10.10.30.129", + "address": "KJ5JCO-10 iGate", "status": "Online", "severity": "Healthy", "latency": "160.8ms", "lastCheck": "2026-05-14 23:45 UTC" }, { - "name": "APRS iGate \u2014 Mobile", + "name": "APRS iGate — Mobile", "type": "RF Edge / Mobile Node", "layer": "Edge", "label": "RF", - "address": "10.10.30.35", + "address": "KJ5JCO Mobile", "status": "Online", "severity": "Healthy", "latency": "21.2ms", diff --git a/noc/index.html b/noc/index.html index eb025b18..afc02dec 100644 --- a/noc/index.html +++ b/noc/index.html @@ -16,6 +16,11 @@ + + + + + @@ -193,12 +198,11 @@ @@ -300,7 +304,7 @@
Full observability stack for Proxmox, TrueNAS, K3s, Raspberry Pi, @@ -362,6 +366,7 @@ // ── Layer filter tabs ────────────────────────────────────────── // Populated after NOC data loads. Filters the system grid by layer. let allSystems = []; + let activeLayer = "all"; // Track active filter across refreshes const originalLoad = window.loadNocStatus; @@ -372,7 +377,8 @@ if (cards.length > 0) { buildLayerTabs(); buildUptimePills(); - observer.disconnect(); + // Re-apply active filter after data refresh + reapplyFilter(); } }); @@ -380,6 +386,16 @@ if (grid) observer.observe(grid, { childList: true }); }); + function reapplyFilter() { + if (activeLayer !== "all") { + document.querySelectorAll(".noc-system-card").forEach(card => { + const layerEl = card.querySelector(".noc-system-top span:last-child"); + card.style.display = + layerEl && layerEl.textContent.trim() === activeLayer ? "" : "none"; + }); + } + } + function buildLayerTabs() { const cards = document.querySelectorAll(".noc-system-card"); const layers = new Set(["all"]); @@ -394,7 +410,7 @@ layers.forEach(layer => { const btn = document.createElement("button"); - btn.className = "layer-tab" + (layer === "all" ? " active" : ""); + btn.className = "layer-tab" + (layer === activeLayer ? " active" : ""); btn.dataset.layer = layer; btn.textContent = layer === "all" ? "All Systems" : layer; btn.addEventListener("click", () => filterByLayer(layer, btn)); @@ -403,6 +419,7 @@ } function filterByLayer(layer, activeBtn) { + activeLayer = layer; // Persist across refreshes document.querySelectorAll(".layer-tab").forEach(t => t.classList.remove("active")); activeBtn.classList.add("active"); diff --git a/scripts/generate-noc-status.py b/scripts/generate-noc-status.py index a8d2d7ba..35c0e630 100644 --- a/scripts/generate-noc-status.py +++ b/scripts/generate-noc-status.py @@ -12,7 +12,7 @@ SYSTEMS = [ "type": "Virtualization Platform", "host": "10.10.30.250", "port": 8006, - "address": "10.10.30.250:8006", + "display_name": "BigWorld", "layer": "Core Infrastructure", "label": "Hypervisor" }, @@ -21,7 +21,7 @@ SYSTEMS = [ "type": "Storage Platform", "host": "10.10.30.143", "port": 80, - "address": "10.10.30.143", + "display_name": "TrueNAS", "layer": "Storage", "label": "NAS" }, @@ -30,7 +30,7 @@ SYSTEMS = [ "type": "Reverse Proxy", "host": "10.10.30.210", "port": 81, - "address": "10.10.30.210:81", + "display_name": "NPM", "layer": "Access Layer", "label": "Proxy" }, @@ -39,7 +39,7 @@ SYSTEMS = [ "type": "Service Dashboard", "host": "10.10.30.61", "port": 4000, - "address": "10.10.30.61:4000", + "display_name": "Dashy", "layer": "Dashboard", "label": "Portal" }, @@ -48,7 +48,7 @@ SYSTEMS = [ "type": "Media Service", "host": "10.10.30.143", "port": 30013, - "address": "10.10.30.143:30013", + "display_name": "PrimeStation", "layer": "Application Service", "label": "App" }, @@ -57,7 +57,7 @@ SYSTEMS = [ "type": "Kubernetes API", "host": "10.10.30.72", "port": 6443, - "address": "10.10.30.72:6443", + "display_name": "k3s-django-1", "layer": "Compute Cluster", "label": "Cluster" }, @@ -66,7 +66,7 @@ SYSTEMS = [ "type": "RF Edge Gateway", "host": "10.10.30.129", "port": 8001, - "address": "KJ5JCO-10 / Direwolf KISS 8001", + "display_name": "KJ5JCO-10 iGate", "layer": "Edge / RF", "label": "iGate" }, @@ -75,7 +75,7 @@ SYSTEMS = [ "type": "APRS Internet Service", "host": "noam.aprs2.net", "port": 14580, - "address": "noam.aprs2.net:14580", + "display_name": "noam.aprs2.net", "layer": "Edge / RF", "label": "External" } @@ -141,7 +141,7 @@ def main(): systems.append({ "name": system["name"], "type": system["type"], - "address": system["address"], + "address": system["display_name"], "status": status, "severity": severity_from_status(online, latency), "layer": system["layer"],