From 39d1c2ccb9ea1b21a3aa2d6bf7577864b990ada5 Mon Sep 17 00:00:00 2001 From: Tamal Saha Date: Thu, 25 Jun 2026 19:32:06 +0600 Subject: [PATCH] projectquota: return errors from StartWatcher instead of klog.Fatalln ProjectQuotaReconciler.StartWatcher called klog.Fatalln on a nil reconciler, an unknown resource Kind, or a failed Watch. Because StartWatcher runs from the resource-discovery poller (graph.PollNewResourceTypes), any of these conditions terminated the whole kube-ui-server process rather than failing the single watch. Make StartWatcher return an error and have the poller log it and continue, consistent with the rest of the resilient discovery loop. No condition in this path should bring down the aggregated apiserver. Signed-off-by: Tamal Saha --- .../projectquota/projectquota_controller.go | 10 ++++++---- pkg/graph/setup.go | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/controllers/projectquota/projectquota_controller.go b/pkg/controllers/projectquota/projectquota_controller.go index 791d86bef7..5ee87ed437 100644 --- a/pkg/controllers/projectquota/projectquota_controller.go +++ b/pkg/controllers/projectquota/projectquota_controller.go @@ -18,6 +18,7 @@ package projectquota import ( "context" + "errors" "fmt" "sort" "strings" @@ -373,17 +374,17 @@ func (r *ProjectQuotaReconciler) SetupWithManager(mgr ctrl.Manager) (*ProjectQuo return r, nil } -func (r *ProjectQuotaReconciler) StartWatcher(rid kmapi.ResourceID) { +func (r *ProjectQuotaReconciler) StartWatcher(rid kmapi.ResourceID) error { r.mu.Lock() defer r.mu.Unlock() if r.ctrl == nil { - klog.Fatalln("ProjectQuota reconciler is not setup yet!") + return errors.New("ProjectQuota reconciler is not setup yet") } gvk := rid.GroupVersionKind() if gvk.Kind == "" { - klog.Fatalln("can't start ProjectQuota reconciler for unknown Kind!") + return fmt.Errorf("can't start ProjectQuota reconciler for unknown Kind of resource %s", rid.GroupResource()) } if api.IsRegistered(gvk) && !r.regTypes[gvk] { @@ -396,10 +397,11 @@ func (r *ProjectQuotaReconciler) StartWatcher(rid kmapi.ResourceID) { handler.EnqueueRequestsFromMapFunc(ProjectQuotaForObjects(r.Client))), ) if err != nil { - klog.Fatalln(err) + return fmt.Errorf("failed to start ProjectQuota watcher for %s: %w", gvk, err) } r.regTypes[gvk] = true } + return nil } // Obj -> ProjectQuota diff --git a/pkg/graph/setup.go b/pkg/graph/setup.go index 21ebc99748..8da6f39acf 100644 --- a/pkg/graph/setup.go +++ b/pkg/graph/setup.go @@ -103,7 +103,9 @@ func PollNewResourceTypes(cfg *restclient.Config, pqr *projectquotacontroller.Pr resourceTracker[gvk] = rid resourceChannel <- rid if pqr != nil { - pqr.StartWatcher(rid) + if err := pqr.StartWatcher(rid); err != nil { + klog.ErrorS(err, "failed to start ProjectQuota watcher", "gvk", gvk) + } } } }