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()