From 1a1a35085f9fd073257d77432d33d637292a5a56 Mon Sep 17 00:00:00 2001 From: Philipp Matthes Date: Fri, 4 Sep 2026 11:19:03 +0200 Subject: [PATCH] Fix multicluster recorder for controller-runtime v0.25.0 EventRecorder change Signed-off-by: Philipp Matthes --- pkg/multicluster/client_test.go | 6 +++--- pkg/multicluster/recorder.go | 25 ++++++++++++++++--------- pkg/multicluster/recorder_test.go | 12 ++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/pkg/multicluster/client_test.go b/pkg/multicluster/client_test.go index 29ea8e0ca..e208394de 100644 --- a/pkg/multicluster/client_test.go +++ b/pkg/multicluster/client_test.go @@ -16,7 +16,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/tools/events" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" @@ -24,6 +23,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/cluster" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/recorder" "github.com/cobaltcore-dev/cortex/api/v1alpha1" ) @@ -81,7 +81,7 @@ type fakeCluster struct { cluster.Cluster fakeClient client.Client fakeCache *fakeCache - fakeRecorder events.EventRecorder + fakeRecorder recorder.EventRecorder scheme *runtime.Scheme } @@ -104,7 +104,7 @@ func (f *fakeCluster) GetFieldIndexer() client.FieldIndexer { return f.fakeCache } -func (f *fakeCluster) GetEventRecorder(_ string) events.EventRecorder { +func (f *fakeCluster) GetEventRecorder(_ string) recorder.EventRecorder { if f.fakeRecorder != nil { return f.fakeRecorder } diff --git a/pkg/multicluster/recorder.go b/pkg/multicluster/recorder.go index 8c7c78d3d..f7099dcd3 100644 --- a/pkg/multicluster/recorder.go +++ b/pkg/multicluster/recorder.go @@ -5,18 +5,18 @@ package multicluster import ( "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/tools/events" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cluster" + "sigs.k8s.io/controller-runtime/pkg/recorder" ) -// MultiClusterRecorder implements events.EventRecorder and routes events to the -// correct cluster based on the GVK of the "regarding" object. It uses the same -// routing logic as the multicluster Client's write path. +// MultiClusterRecorder implements recorder.EventRecorder and routes events to +// the correct cluster based on the GVK of the "regarding" object. It uses the +// same routing logic as the multicluster Client's write path. type MultiClusterRecorder struct { client *Client - homeRecorder events.EventRecorder - recorders map[cluster.Cluster]events.EventRecorder + homeRecorder recorder.EventRecorder + recorders map[cluster.Cluster]recorder.EventRecorder } // GetEventRecorder creates a multi-cluster-aware EventRecorder. It pre-creates @@ -24,10 +24,10 @@ type MultiClusterRecorder struct { // registered in the client. The name parameter is passed through to each // cluster's GetEventRecorder method (it becomes the reportingController in the // Kubernetes Event). -func (c *Client) GetEventRecorder(name string) events.EventRecorder { +func (c *Client) GetEventRecorder(name string) recorder.EventRecorder { homeRecorder := c.HomeCluster.GetEventRecorder(name) - recorders := make(map[cluster.Cluster]events.EventRecorder) + recorders := make(map[cluster.Cluster]recorder.EventRecorder) recorders[c.HomeCluster] = homeRecorder c.remoteClustersMu.RLock() @@ -55,8 +55,15 @@ func (r *MultiClusterRecorder) Eventf(regarding, related runtime.Object, eventty recorder.Eventf(regarding, related, eventtype, reason, action, note, args...) } +// AnnotatedEventf routes the annotated event to the cluster that owns the +// "regarding" object. Falls back to the home cluster recorder if routing fails. +func (r *MultiClusterRecorder) AnnotatedEventf(regarding, related runtime.Object, annotations map[string]string, eventtype, reason, action, note string, args ...any) { + recorder := r.recorderFor(regarding) + recorder.AnnotatedEventf(regarding, related, annotations, eventtype, reason, action, note, args...) +} + // recorderFor resolves which per-cluster recorder to use for the given object. -func (r *MultiClusterRecorder) recorderFor(obj runtime.Object) events.EventRecorder { +func (r *MultiClusterRecorder) recorderFor(obj runtime.Object) recorder.EventRecorder { if obj == nil { return r.homeRecorder } diff --git a/pkg/multicluster/recorder_test.go b/pkg/multicluster/recorder_test.go index 90bdd71dc..16318747c 100644 --- a/pkg/multicluster/recorder_test.go +++ b/pkg/multicluster/recorder_test.go @@ -41,6 +41,18 @@ func (f *fakeEventRecorder) Eventf(regarding, _ runtime.Object, eventtype, reaso }) } +func (f *fakeEventRecorder) AnnotatedEventf(regarding, _ runtime.Object, _ map[string]string, eventtype, reason, action, note string, args ...any) { + f.mu.Lock() + defer f.mu.Unlock() + f.calls = append(f.calls, eventfCall{ + regarding: regarding, + eventtype: eventtype, + reason: reason, + action: action, + note: fmt.Sprintf(note, args...), + }) +} + func (f *fakeEventRecorder) getCalls() []eventfCall { f.mu.Lock() defer f.mu.Unlock()