@@ -33,10 +33,12 @@ import (
3333 "github.com/go-git/go-git/v5/plumbing/transport"
3434 "github.com/go-logr/logr"
3535 corev1 "k8s.io/api/core/v1"
36+ apimeta "k8s.io/apimachinery/pkg/api/meta"
3637 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3738 "k8s.io/apimachinery/pkg/runtime"
3839 "k8s.io/apimachinery/pkg/types"
3940 kuberecorder "k8s.io/client-go/tools/record"
41+ "k8s.io/client-go/tools/reference"
4042 ctrl "sigs.k8s.io/controller-runtime"
4143 "sigs.k8s.io/controller-runtime/pkg/client"
4244 "sigs.k8s.io/controller-runtime/pkg/handler"
@@ -46,6 +48,7 @@ import (
4648 imagev1_reflect "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
4749 "github.com/fluxcd/pkg/apis/meta"
4850 "github.com/fluxcd/pkg/runtime/events"
51+ "github.com/fluxcd/pkg/runtime/metrics"
4952 "github.com/fluxcd/pkg/runtime/predicates"
5053 sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
5154 "github.com/fluxcd/source-controller/pkg/git"
@@ -68,9 +71,11 @@ const imagePolicyKey = ".spec.update.imagePolicy"
6871// ImageUpdateAutomationReconciler reconciles a ImageUpdateAutomation object
6972type ImageUpdateAutomationReconciler struct {
7073 client.Client
71- Log logr.Logger
72- Scheme * runtime.Scheme
73- EventRecorder kuberecorder.EventRecorder
74+ Log logr.Logger
75+ Scheme * runtime.Scheme
76+ EventRecorder kuberecorder.EventRecorder
77+ ExternalEventRecorder * events.Recorder
78+ MetricsRecorder * metrics.Recorder
7479}
7580
7681// +kubebuilder:rbac:groups=image.toolkit.fluxcd.io,resources=imageupdateautomations,verbs=get;list;watch;create;update;patch;delete
@@ -92,6 +97,19 @@ func (r *ImageUpdateAutomationReconciler) Reconcile(req ctrl.Request) (ctrl.Resu
9297 return ctrl.Result {}, nil
9398 }
9499
100+ // Record readiness metric when exiting; if there's any points at
101+ // which the readiness is updated _without also exiting_, they
102+ // should also record the readiness.
103+ defer r .recordReadinessMetric (& auto )
104+ // Record reconciliation duration when exiting
105+ if r .MetricsRecorder != nil {
106+ objRef , err := reference .GetReference (r .Scheme , & auto )
107+ if err != nil {
108+ return ctrl.Result {}, err
109+ }
110+ defer r .MetricsRecorder .RecordDuration (* objRef , now )
111+ }
112+
95113 // whatever else happens, we've now "seen" the reconcile
96114 // annotation if it's there
97115 if token , ok := meta .ReconcileAnnotationValue (auto .GetAnnotations ()); ok {
@@ -359,12 +377,53 @@ func commitAllAndPush(ctx context.Context, repo *gogit.Repository, access repoAc
359377 })
360378}
361379
362- // --- events
380+ // --- events, metrics
363381
364382func (r * ImageUpdateAutomationReconciler ) event (auto imagev1.ImageUpdateAutomation , severity , msg string ) {
365383 if r .EventRecorder != nil {
366384 r .EventRecorder .Event (& auto , "Normal" , severity , msg )
367385 }
386+ if r .ExternalEventRecorder != nil {
387+ objRef , err := reference .GetReference (r .Scheme , & auto )
388+ if err != nil {
389+ r .Log .WithValues (
390+ "request" ,
391+ fmt .Sprintf ("%s/%s" , auto .GetNamespace (), auto .GetName ()),
392+ ).Error (err , "unable to send event" )
393+ return
394+ }
395+
396+ if err := r .ExternalEventRecorder .Eventf (* objRef , nil , severity , severity , msg ); err != nil {
397+ r .Log .WithValues (
398+ "request" ,
399+ fmt .Sprintf ("%s/%s" , auto .GetNamespace (), auto .GetName ()),
400+ ).Error (err , "unable to send event" )
401+ return
402+ }
403+ }
404+ }
405+
406+ func (r * ImageUpdateAutomationReconciler ) recordReadinessMetric (auto * imagev1.ImageUpdateAutomation ) {
407+ if r .MetricsRecorder == nil {
408+ return
409+ }
410+
411+ objRef , err := reference .GetReference (r .Scheme , auto )
412+ if err != nil {
413+ r .Log .WithValues (
414+ strings .ToLower (auto .Kind ),
415+ fmt .Sprintf ("%s/%s" , auto .GetNamespace (), auto .GetName ()),
416+ ).Error (err , "unable to record readiness metric" )
417+ return
418+ }
419+ if rc := apimeta .FindStatusCondition (auto .Status .Conditions , meta .ReadyCondition ); rc != nil {
420+ r .MetricsRecorder .RecordCondition (* objRef , * rc , ! auto .DeletionTimestamp .IsZero ())
421+ } else {
422+ r .MetricsRecorder .RecordCondition (* objRef , metav1.Condition {
423+ Type : meta .ReadyCondition ,
424+ Status : metav1 .ConditionUnknown ,
425+ }, ! auto .DeletionTimestamp .IsZero ())
426+ }
368427}
369428
370429// --- updates
0 commit comments