package events import ( "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/runtime" kuberecorder "k8s.io/client-go/tools/record" "k8s.io/client-go/tools/reference" ctrl "sigs.k8s.io/controller-runtime" ) // Recorder posts events to the Kubernetes API. // // Use it by embedding EventRecorder in reconciler struct: // // import ( // ... // kuberecorder "k8s.io/client-go/tools/record" // ... // ) // // type MyTypeReconciler { // client.Client // // ... etc. // kuberecorder.EventRecorder // } // // Use [NewRecorder] to create a working Recorder. // // TODO: add a retryable HTTP client & webhook and update // [NewRecorder] to configure them type Recorder struct { // Name of the controller that emits events. ReportingController string // EventRecorder is the Kubernetes event recorder. EventRecorder kuberecorder.EventRecorder // Scheme to look up the recorded objects. Scheme *runtime.Scheme // Log is the recorder logger. Log logr.Logger } var _ kuberecorder.EventRecorder = &Recorder{} // NewRecorder creates an event Recorder with a Kubernetes event recorder. func NewRecorder(mgr ctrl.Manager, log logr.Logger, reportingController string) *Recorder { return &Recorder{ Scheme: mgr.GetScheme(), ReportingController: reportingController, EventRecorder: mgr.GetEventRecorderFor(reportingController), Log: log, } } // Event constructs an event from the given information and puts it in the queue for sending. // 'object' is the object this event is about. // 'eventtype' of this event, and can be one of Normal, Warning. New types could be added in future // 'reason' is the reason this event is generated. 'reason' should be short and unique; it // should be in UpperCamelCase format (starting with a capital letter). "reason" will be used // to automate handling of events. // 'message' is intended to be human readable. // // The resulting event will be created in the same namespace as the reference object. func (r *Recorder) Event(object runtime.Object, eventtype, reason, message string) { r.AnnotatedEventf(object, nil, eventtype, reason, message) } // Eventf is just like [Event], but with a formatted message. func (r *Recorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) { r.AnnotatedEventf(object, nil, eventtype, reason, messageFmt, args...) } // AnnotatedEventf is just like [Event], but with a formatted message and annotations attached. func (r *Recorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { ref, err := reference.GetReference(r.Scheme, object) if err != nil { r.Log.Error(err, "failed to get object reference") } // Add object info in the logger. _ = r.Log.WithValues("name", ref.Name, "namespace", ref.Namespace, "reconciler kind", ref.Kind) // Forward the event to the Kubernetes recorder. r.EventRecorder.AnnotatedEventf(object, annotations, eventtype, reason, messageFmt, args...) // TODO: update this function to use retryable HTTP client and webhook when available/provided. // See [AnnotatedEventf] in https://github.com/fluxcd/pkg/blob/main/runtime/events/recorder.go // for an implementation example. }