@@ -31,6 +31,7 @@ import (
31
31
corev1 "k8s.io/api/core/v1"
32
32
apierrors "k8s.io/apimachinery/pkg/api/errors"
33
33
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
34
+ "k8s.io/apimachinery/pkg/runtime"
34
35
"k8s.io/apimachinery/pkg/types"
35
36
ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
36
37
)
@@ -57,15 +58,39 @@ type objectSyncer struct {
57
58
mutator mutation.Mutator
58
59
// stateStore is capable of remembering the state of a Kubernetes object
59
60
stateStore ObjectStateStore
61
+ // eventObjSide is configuring whether the source or destination object will
62
+ // receive events. Since these objects might be created during the sync,
63
+ // they cannot be specified here directly.
64
+ eventObjSide syncSideType
60
65
}
61
66
67
+ type syncSideType int
68
+
69
+ const (
70
+ syncSideSource syncSideType = iota
71
+ syncSideDestination
72
+ )
73
+
62
74
type syncSide struct {
63
75
clusterName logicalcluster.Name
64
76
workspacePath logicalcluster.Path
65
77
client ctrlruntimeclient.Client
66
78
object * unstructured.Unstructured
67
79
}
68
80
81
+ func (s * objectSyncer ) recordEvent (ctx context.Context , source , dest syncSide , eventtype , reason , msg string , args ... any ) {
82
+ recorder := recorderFromContext (ctx )
83
+
84
+ var obj runtime.Object
85
+ if s .eventObjSide == syncSideDestination {
86
+ obj = dest .object
87
+ } else {
88
+ obj = source .object
89
+ }
90
+
91
+ recorder .Eventf (obj , eventtype , reason , msg , args ... )
92
+ }
93
+
69
94
func (s * objectSyncer ) Sync (ctx context.Context , log * zap.SugaredLogger , source , dest syncSide ) (requeue bool , err error ) {
70
95
// handle deletion: if source object is in deletion, delete the destination object (the clone)
71
96
if source .object .GetDeletionTimestamp () != nil {
@@ -81,6 +106,7 @@ func (s *objectSyncer) Sync(ctx context.Context, log *zap.SugaredLogger, source,
81
106
82
107
// the patch above would trigger a new reconciliation anyway
83
108
if updated {
109
+ s .recordEvent (ctx , source , dest , corev1 .EventTypeNormal , "ObjectAccepted" , "Object has been seen by the service provider." )
84
110
return true , nil
85
111
}
86
112
}
@@ -103,6 +129,7 @@ func (s *objectSyncer) Sync(ctx context.Context, log *zap.SugaredLogger, source,
103
129
104
130
// The function above either created a new destination object or patched-in the missing labels,
105
131
// in both cases do we want to requeue.
132
+ s .recordEvent (ctx , source , dest , corev1 .EventTypeNormal , "ObjectPlaced" , "Object has been placed." )
106
133
return true , nil
107
134
}
108
135
@@ -254,6 +281,8 @@ func (s *objectSyncer) syncObjectSpec(ctx context.Context, log *zap.SugaredLogge
254
281
}
255
282
256
283
if requeue {
284
+ s .recordEvent (ctx , source , dest , corev1 .EventTypeNormal , "ObjectSynced" , "The current desired state of the object has been synchronized." )
285
+
257
286
// remember this object state for the next reconciliation (this will strip any syncer-related
258
287
// metadata the 3-way diff may have added above)
259
288
if err := s .stateStore .Put (ctx , sourceObjCopy , source .clusterName , s .subresources ); err != nil {
@@ -282,6 +311,8 @@ func (s *objectSyncer) syncObjectStatus(ctx context.Context, log *zap.SugaredLog
282
311
if err := source .client .Status ().Update (ctx , source .object ); err != nil {
283
312
return false , fmt .Errorf ("failed to update source object status: %w" , err )
284
313
}
314
+
315
+ s .recordEvent (ctx , source , dest , corev1 .EventTypeNormal , "ObjectStatusSynced" , "The current object status has been updated." )
285
316
}
286
317
287
318
// always return false; there is no need to requeue the source object when we changed its status
@@ -406,6 +437,7 @@ func (s *objectSyncer) handleDeletion(ctx context.Context, log *zap.SugaredLogge
406
437
if dest .object != nil {
407
438
if dest .object .GetDeletionTimestamp () == nil {
408
439
log .Debugw ("Deleting destination object…" , "dest-object" , newObjectKey (dest .object , dest .clusterName , logicalcluster .None ))
440
+ s .recordEvent (ctx , source , dest , corev1 .EventTypeNormal , "ObjectCleanup" , "Object deletion has been started and will progress in the background." )
409
441
if err := dest .client .Delete (ctx , dest .object ); err != nil {
410
442
return false , fmt .Errorf ("failed to delete destination object: %w" , err )
411
443
}
@@ -422,6 +454,7 @@ func (s *objectSyncer) handleDeletion(ctx context.Context, log *zap.SugaredLogge
422
454
423
455
// if we just removed the finalizer, we can requeue the source object
424
456
if updated {
457
+ s .recordEvent (ctx , source , dest , corev1 .EventTypeNormal , "ObjectDeleted" , "Object deletion has been completed, finalizer has been removed." )
425
458
return true , nil
426
459
}
427
460
0 commit comments