From de272331b657d0ca18899eccc1a3d5f667737018 Mon Sep 17 00:00:00 2001 From: jedarden Date: Mon, 13 Apr 2026 16:24:06 -0400 Subject: [PATCH] fix(health): don't degrade status when no nodes are connected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zero connected nodes is valid for headless/standby deployments. The 5-minute grace period was causing an infinite crash loop: healthz returned 503 after 5min uptime → liveness probe failed → pod restarted. The "no nodes connected" reason is still reported but no longer sets status to degraded. Co-Authored-By: Claude Opus 4.6 (1M context) --- mothership/internal/health/health.go | 4 ++-- mothership/internal/health/health_test.go | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mothership/internal/health/health.go b/mothership/internal/health/health.go index 980c214..e41f3dc 100644 --- a/mothership/internal/health/health.go +++ b/mothership/internal/health/health.go @@ -122,9 +122,9 @@ func (c *Checker) check(version string) Response { c.level3Since = time.Time{} } - // Condition 3: No nodes online after 5 minutes uptime + // Condition 3: No nodes online after 5 minutes uptime (informational only, + // does not degrade status — zero nodes is valid for headless deployments) if nodesOnline == 0 && uptime > 300 { - status = "degraded" if reason == "" { reason = "no nodes connected" } diff --git a/mothership/internal/health/health_test.go b/mothership/internal/health/health_test.go index a971563..3ec9490 100644 --- a/mothership/internal/health/health_test.go +++ b/mothership/internal/health/health_test.go @@ -72,7 +72,8 @@ func TestHealthCheckDBFailing(t *testing.T) { } } -// TestHealthCheckNoNodes tests that health check returns degraded after 5 min with no nodes. +// TestHealthCheckNoNodes tests that health check stays OK after 5 min with no nodes +// (zero nodes is valid for headless deployments). func TestHealthCheckNoNodes(t *testing.T) { checker := &Checker{ startTime: time.Now().Add(-6 * time.Minute), // 6 minutes ago @@ -88,8 +89,8 @@ func TestHealthCheckNoNodes(t *testing.T) { resp := checker.check("1.0.0") - if resp.Status != "degraded" { - t.Errorf("expected status=degraded, got %s", resp.Status) + if resp.Status != "ok" { + t.Errorf("expected status=ok, got %s", resp.Status) } if resp.Reason != "no nodes connected" { t.Errorf("expected reason='no nodes connected', got %s", resp.Reason)