From 23f002632f78522d7cba8dc16b66296cf8e9cb33 Mon Sep 17 00:00:00 2001 From: bakito Date: Fri, 26 Jun 2026 18:35:05 +0200 Subject: [PATCH] feat: define interface for event recorder Signed-off-by: bakito --- cmd/controller/main.go | 2 +- pkg/runtime/events/event_types.go | 78 +++++++++++++++++++++++++------ pkg/runtime/events/recorder.go | 48 ++++++++++--------- 3 files changed, 92 insertions(+), 36 deletions(-) diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 2f9184216..0e19ba9a6 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -694,7 +694,7 @@ func main() { if err = webhook.Register( manager, - *evt.NewEventRecorder( + evt.NewEventRecorder( manager.GetClient(), ctrl.Log.WithName("capsule.ctrl").WithName("events"), manager.GetEventRecorder("tenant-controller"), diff --git a/pkg/runtime/events/event_types.go b/pkg/runtime/events/event_types.go index 368d34b1b..d0c859b6c 100644 --- a/pkg/runtime/events/event_types.go +++ b/pkg/runtime/events/event_types.go @@ -14,8 +14,26 @@ import ( "github.com/projectcapsule/capsule/pkg/api/meta" ) -type LabeledEvent struct { - recorder *EventRecorder +type LabeledEvent interface { + Emit(ctx context.Context) + WithRelated(obj runtime.Object) LabeledEvent + WithLabels(labels map[string]string) LabeledEvent + WithAnnotations(annotations map[string]string) LabeledEvent + WithTenantLabel(tnt *capsulev1beta2.Tenant) LabeledEvent + WithRequestAnnotations(req admission.Request) LabeledEvent + + Reason() string + Action() string + Regarding() runtime.Object + Labels() map[string]string + Annotations() map[string]string + Note() string + EventType() string + Related() runtime.Object +} + +type labeledEvent struct { + emitter eventEmitter regarding runtime.Object related runtime.Object @@ -29,15 +47,47 @@ type LabeledEvent struct { annotations map[string]string } -func (r *EventRecorder) LabeledEvent( +func (e *labeledEvent) Reason() string { + return e.reason +} + +func (e *labeledEvent) Action() string { + return e.action +} + +func (e *labeledEvent) Regarding() runtime.Object { + return e.regarding +} + +func (e *labeledEvent) Labels() map[string]string { + return maps.Clone(e.labels) +} + +func (e *labeledEvent) Annotations() map[string]string { + return maps.Clone(e.annotations) +} + +func (e *labeledEvent) Note() string { + return e.note +} + +func (e *labeledEvent) EventType() string { + return e.eventType +} + +func (e *labeledEvent) Related() runtime.Object { + return e.related +} + +func (r *eventRecorder) LabeledEvent( regarding runtime.Object, eventType string, reason string, action string, note string, -) *LabeledEvent { - return &LabeledEvent{ - recorder: r, +) LabeledEvent { + return &labeledEvent{ + emitter: r, regarding: regarding, eventType: eventType, reason: reason, @@ -48,33 +98,33 @@ func (r *EventRecorder) LabeledEvent( } } -func (e *LabeledEvent) Emit(ctx context.Context) { - if e == nil || e.recorder == nil { +func (e *labeledEvent) Emit(ctx context.Context) { + if e == nil || e.emitter == nil { return } - e.recorder.emitLabeledEvent(ctx, e) + e.emitter.Emit(ctx, e) } -func (e *LabeledEvent) WithRelated(obj runtime.Object) *LabeledEvent { +func (e *labeledEvent) WithRelated(obj runtime.Object) LabeledEvent { e.related = obj return e } -func (e *LabeledEvent) WithLabels(labels map[string]string) *LabeledEvent { +func (e *labeledEvent) WithLabels(labels map[string]string) LabeledEvent { maps.Copy(e.labels, labels) return e } -func (e *LabeledEvent) WithAnnotations(annotations map[string]string) *LabeledEvent { +func (e *labeledEvent) WithAnnotations(annotations map[string]string) LabeledEvent { maps.Copy(e.annotations, annotations) return e } -func (e *LabeledEvent) WithTenantLabel(tnt *capsulev1beta2.Tenant) *LabeledEvent { +func (e *labeledEvent) WithTenantLabel(tnt *capsulev1beta2.Tenant) LabeledEvent { if tnt == nil { return e } @@ -84,7 +134,7 @@ func (e *LabeledEvent) WithTenantLabel(tnt *capsulev1beta2.Tenant) *LabeledEvent return e } -func (e *LabeledEvent) WithRequestAnnotations(req admission.Request) *LabeledEvent { +func (e *labeledEvent) WithRequestAnnotations(req admission.Request) LabeledEvent { if req.UID != "" { e.annotations[meta.AuditRequestUID] = string(req.UID) } diff --git a/pkg/runtime/events/recorder.go b/pkg/runtime/events/recorder.go index 5b9852421..19108332d 100644 --- a/pkg/runtime/events/recorder.go +++ b/pkg/runtime/events/recorder.go @@ -24,7 +24,16 @@ const ( ReportingInstance = "capsule-admission" ) -type EventRecorder struct { +type EventRecorder interface { + k8sevents.EventRecorder + LabeledEvent(regarding runtime.Object, eventType string, reason string, action string, note string) LabeledEvent +} + +type eventEmitter interface { + Emit(ctx context.Context, e LabeledEvent) +} + +type eventRecorder struct { k8sevents.EventRecorder client client.Client @@ -37,8 +46,8 @@ func NewEventRecorder( log logr.Logger, recorder k8sevents.EventRecorder, configuration configuration.Configuration, -) *EventRecorder { - return &EventRecorder{ +) EventRecorder { + return &eventRecorder{ EventRecorder: recorder, client: c, log: log.WithName("event-recorder"), @@ -46,10 +55,7 @@ func NewEventRecorder( } } -func (r *EventRecorder) emitLabeledEvent( - ctx context.Context, - e *LabeledEvent, -) { +func (r *eventRecorder) Emit(ctx context.Context, e LabeledEvent) { if r == nil { return } @@ -66,19 +72,19 @@ func (r *EventRecorder) emitLabeledEvent( return } - if e.reason == "" { + if e.Reason() == "" { r.log.Error(nil, "cannot emit labeled event: reason is empty") return } - if e.action == "" { + if e.Action() == "" { r.log.Error(nil, "cannot emit labeled event: action is empty") return } - regardingRef, metaObj, err := objectReference(e.regarding) + regardingRef, metaObj, err := objectReference(e.Regarding()) if err != nil { r.log.Error(err, "cannot emit labeled event: build regarding reference") @@ -100,21 +106,21 @@ func (r *EventRecorder) emitLabeledEvent( ObjectMeta: metav1.ObjectMeta{ GenerateName: metaObj.GetName(), Namespace: namespace, - Labels: e.labels, - Annotations: e.annotations, + Labels: e.Labels(), + Annotations: e.Annotations(), }, EventTime: metav1.MicroTime{Time: time.Now()}, ReportingController: ReportingController, ReportingInstance: ReportingInstance, - Action: e.action, - Reason: e.reason, + Action: e.Action(), + Reason: e.Reason(), Regarding: regardingRef, - Note: e.note, - Type: e.eventType, + Note: e.Note(), + Type: e.EventType(), } - if e.related != nil { - relatedRef, _, err := objectReference(e.related) + if e.Related() != nil { + relatedRef, _, err := objectReference(e.Related()) if err != nil { r.log.Error(err, "cannot emit labeled event: build related reference") @@ -128,9 +134,9 @@ func (r *EventRecorder) emitLabeledEvent( r.log.Error( err, "cannot emit labeled event", - "reason", e.reason, - "action", e.action, - "type", e.eventType, + "reason", e.Reason(), + "action", e.Action(), + "type", e.EventType(), "regarding", regardingRef.Name, "namespace", namespace, )