Skip to content

Commit 32380fb

Browse files
authored
Merge pull request #60 from fluxcd/metricals-probes
Metrics and notifications
2 parents 027370a + 64177cc commit 32380fb

File tree

4 files changed

+95
-23
lines changed

4 files changed

+95
-23
lines changed

controllers/imageupdateautomation_controller.go

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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
6972
type 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

364382
func (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

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/fluxcd/image-reflector-controller v0.0.0-20200810165546-c2265d9b49b9
1010
github.com/fluxcd/pkg/apis/meta v0.4.0
1111
github.com/fluxcd/pkg/gittestserver v0.0.2
12-
github.com/fluxcd/pkg/runtime v0.3.0
12+
github.com/fluxcd/pkg/runtime v0.3.1
1313
github.com/fluxcd/source-controller v0.3.0
1414
// If you bump this, change TOOLKIT_VERSION in the Makefile to match
1515
github.com/fluxcd/source-controller/api v0.3.0

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
290290
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
291291
github.com/fluxcd/image-reflector-controller v0.0.0-20200810165546-c2265d9b49b9 h1:puMXg9dmh/i3rpAuzVq5R5L84pZMA/KUNZbPxi0JdWw=
292292
github.com/fluxcd/image-reflector-controller v0.0.0-20200810165546-c2265d9b49b9/go.mod h1:v2cJ+q7zRlj1VhYjtE1i3cGAFkSTz21/tKidWIIGUtU=
293+
github.com/fluxcd/pkg v0.0.4 h1:fMA6GG3FTSBFDrlB026gQJhxj4xVuvcvwP3rhX/Yqrw=
293294
github.com/fluxcd/pkg/apis/meta v0.2.0 h1:bxoFQtZM6OLLj0+n3h6ga7IEWUtGEDJPc65OWiXSMvY=
294295
github.com/fluxcd/pkg/apis/meta v0.2.0/go.mod h1:50RLLSfqM4LlQrh/+5LiJVf7Hjdthee8WDdXBvpjBdA=
295296
github.com/fluxcd/pkg/apis/meta v0.3.0/go.mod h1:wOzQQx8CdtUQCGaLzqGu4QgnNxYkI6/wvdvlovxWhF0=
@@ -303,6 +304,8 @@ github.com/fluxcd/pkg/runtime v0.2.0 h1:aZmSLuyA9pF/KANf4wi7pZIICE19BKTYFSPRbl6W
303304
github.com/fluxcd/pkg/runtime v0.2.0/go.mod h1:P1/S8TOSuJgVPU0SRahWzbNxLWYoUwvBcPCNGc+dWWg=
304305
github.com/fluxcd/pkg/runtime v0.3.0 h1:WpeTmDT2meIe4NsU081I8zmUGgTYs3bIMRgs9F3Lj90=
305306
github.com/fluxcd/pkg/runtime v0.3.0/go.mod h1:gPe6JgfPB4EDh5gaVkuI0SPuATk3PmclbFa1kPcZrKE=
307+
github.com/fluxcd/pkg/runtime v0.3.1 h1:UI+FQd1OgipZ6N8YxXHtKYMAu1NRFWaR/Gp1M3T6RZA=
308+
github.com/fluxcd/pkg/runtime v0.3.1/go.mod h1:wg33L6k5FkGEYoZta7hbUlBIscM5VZd/PfCbaEi+wK4=
306309
github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
307310
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
308311
github.com/fluxcd/pkg/testserver v0.0.2/go.mod h1:pgUZTh9aQ44FSTQo+5NFlh7YMbUfdz1B80DalW7k96Y=

main.go

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@ import (
2424
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
2525
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
2626
ctrl "sigs.k8s.io/controller-runtime"
27-
"sigs.k8s.io/controller-runtime/pkg/healthz"
27+
ctrlmetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
2828

2929
imagev1alpha1_reflect "github.com/fluxcd/image-reflector-controller/api/v1alpha1"
30+
"github.com/fluxcd/pkg/runtime/events"
3031
"github.com/fluxcd/pkg/runtime/logger"
32+
"github.com/fluxcd/pkg/runtime/metrics"
33+
"github.com/fluxcd/pkg/runtime/probes"
3134
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
3235

3336
imagev1alpha1_auto "github.com/fluxcd/image-automation-controller/api/v1alpha1"
3437
"github.com/fluxcd/image-automation-controller/controllers"
3538
// +kubebuilder:scaffold:imports
3639
)
3740

41+
const controllerName = "image-automation-controller"
42+
3843
var (
3944
scheme = runtime.NewScheme()
4045
setupLog = ctrl.Log.WithName("setup")
@@ -52,6 +57,7 @@ func init() {
5257
func main() {
5358
var (
5459
metricsAddr string
60+
eventsAddr string
5561
healthAddr string
5662
enableLeaderElection bool
5763
logLevel string
@@ -60,6 +66,7 @@ func main() {
6066
)
6167

6268
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
69+
flag.StringVar(&eventsAddr, "events-addr", "", "The address of the events receiver.")
6370
flag.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.")
6471
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
6572
"Enable leader election for controller manager. "+
@@ -72,6 +79,19 @@ func main() {
7279

7380
ctrl.SetLogger(logger.NewLogger(logLevel, logJSON))
7481

82+
var eventRecorder *events.Recorder
83+
if eventsAddr != "" {
84+
if er, err := events.NewRecorder(eventsAddr, controllerName); err != nil {
85+
setupLog.Error(err, "unable to create event recorder")
86+
os.Exit(1)
87+
} else {
88+
eventRecorder = er
89+
}
90+
}
91+
92+
metricsRecorder := metrics.NewRecorder()
93+
ctrlmetrics.Registry.MustRegister(metricsRecorder.Collectors()...)
94+
7595
watchNamespace := ""
7696
if !watchAllNamespaces {
7797
watchNamespace = os.Getenv("RUNTIME_NAMESPACE")
@@ -91,13 +111,15 @@ func main() {
91111
os.Exit(1)
92112
}
93113

94-
setupChecks(mgr)
114+
probes.SetupChecks(mgr, setupLog)
95115

96116
if err = (&controllers.ImageUpdateAutomationReconciler{
97-
Client: mgr.GetClient(),
98-
Log: ctrl.Log.WithName("controllers").WithName("ImageUpdateAutomation"),
99-
Scheme: mgr.GetScheme(),
100-
EventRecorder: mgr.GetEventRecorderFor("image-automation-controller"),
117+
Client: mgr.GetClient(),
118+
Log: ctrl.Log.WithName("controllers").WithName("ImageUpdateAutomation"),
119+
Scheme: mgr.GetScheme(),
120+
EventRecorder: mgr.GetEventRecorderFor(controllerName),
121+
ExternalEventRecorder: eventRecorder,
122+
MetricsRecorder: metricsRecorder,
101123
}).SetupWithManager(mgr); err != nil {
102124
setupLog.Error(err, "unable to create controller", "controller", "ImageUpdateAutomation")
103125
os.Exit(1)
@@ -110,15 +132,3 @@ func main() {
110132
os.Exit(1)
111133
}
112134
}
113-
114-
func setupChecks(mgr ctrl.Manager) {
115-
if err := mgr.AddReadyzCheck("ping", healthz.Ping); err != nil {
116-
setupLog.Error(err, "unable to create ready check")
117-
os.Exit(1)
118-
}
119-
120-
if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil {
121-
setupLog.Error(err, "unable to create health check")
122-
os.Exit(1)
123-
}
124-
}

0 commit comments

Comments
 (0)