Skip to content

Commit 3529fda

Browse files
authored
Merge pull request #7786 from mtougeron/emit-events-on-status-conditions
✨ Emit Kubernetes Events when Cluster Phase, ControlPlaneReady, or InfrastructureReady change
2 parents 7c855f5 + 8aa4797 commit 3529fda

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

internal/controllers/cluster/cluster_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"time"
2525

2626
"github.com/pkg/errors"
27+
corev1 "k8s.io/api/core/v1"
2728
apierrors "k8s.io/apimachinery/pkg/api/errors"
2829
"k8s.io/apimachinery/pkg/api/meta"
2930
"k8s.io/apimachinery/pkg/runtime"
@@ -331,6 +332,7 @@ func (r *Reconciler) reconcileDelete(ctx context.Context, cluster *clusterv1.Clu
331332
}
332333

333334
controllerutil.RemoveFinalizer(cluster, clusterv1.ClusterFinalizer)
335+
r.recorder.Eventf(cluster, corev1.EventTypeNormal, "Deleted", "Cluster %s has been deleted", cluster.Name)
334336
return ctrl.Result{}, nil
335337
}
336338

internal/controllers/cluster/cluster_controller_phases.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import (
4242
)
4343

4444
func (r *Reconciler) reconcilePhase(_ context.Context, cluster *clusterv1.Cluster) {
45+
preReconcilePhase := cluster.Status.GetTypedPhase()
46+
4547
if cluster.Status.Phase == "" {
4648
cluster.Status.SetTypedPhase(clusterv1.ClusterPhasePending)
4749
}
@@ -61,6 +63,16 @@ func (r *Reconciler) reconcilePhase(_ context.Context, cluster *clusterv1.Cluste
6163
if !cluster.DeletionTimestamp.IsZero() {
6264
cluster.Status.SetTypedPhase(clusterv1.ClusterPhaseDeleting)
6365
}
66+
67+
// Only record the event if the status has changed
68+
if preReconcilePhase != cluster.Status.GetTypedPhase() {
69+
// Failed clusters should get a Warning event
70+
if cluster.Status.GetTypedPhase() == clusterv1.ClusterPhaseFailed {
71+
r.recorder.Eventf(cluster, corev1.EventTypeWarning, string(cluster.Status.GetTypedPhase()), "Cluster %s is %s: %s", cluster.Name, string(cluster.Status.GetTypedPhase()), pointer.StringDeref(cluster.Status.FailureMessage, "unknown"))
72+
} else {
73+
r.recorder.Eventf(cluster, corev1.EventTypeNormal, string(cluster.Status.GetTypedPhase()), "Cluster %s is %s", cluster.Name, string(cluster.Status.GetTypedPhase()))
74+
}
75+
}
6476
}
6577

6678
// reconcileExternal handles generic unstructured objects referenced by a Cluster.
@@ -163,11 +175,16 @@ func (r *Reconciler) reconcileInfrastructure(ctx context.Context, cluster *clust
163175
}
164176

165177
// Determine if the infrastructure provider is ready.
178+
preReconcileInfrastructureReady := cluster.Status.InfrastructureReady
166179
ready, err := external.IsReady(infraConfig)
167180
if err != nil {
168181
return ctrl.Result{}, err
169182
}
170183
cluster.Status.InfrastructureReady = ready
184+
// Only record the event if the status has changed
185+
if preReconcileInfrastructureReady != cluster.Status.InfrastructureReady {
186+
r.recorder.Eventf(cluster, corev1.EventTypeNormal, "InfrastructureReady", "Cluster %s InfrastructureReady is now %t", cluster.Name, cluster.Status.InfrastructureReady)
187+
}
171188

172189
// Report a summary of current status of the infrastructure object defined for this cluster.
173190
conditions.SetMirror(cluster, clusterv1.InfrastructureReadyCondition,
@@ -225,12 +242,17 @@ func (r *Reconciler) reconcileControlPlane(ctx context.Context, cluster *cluster
225242
return ctrl.Result{}, nil
226243
}
227244

245+
preReconcileControlPlaneReady := cluster.Status.ControlPlaneReady
228246
// Determine if the control plane provider is ready.
229247
ready, err := external.IsReady(controlPlaneConfig)
230248
if err != nil {
231249
return ctrl.Result{}, err
232250
}
233251
cluster.Status.ControlPlaneReady = ready
252+
// Only record the event if the status has changed
253+
if preReconcileControlPlaneReady != cluster.Status.ControlPlaneReady {
254+
r.recorder.Eventf(cluster, corev1.EventTypeNormal, "ControlPlaneReady", "Cluster %s ControlPlaneReady is now %t", cluster.Name, cluster.Status.ControlPlaneReady)
255+
}
234256

235257
// Report a summary of current status of the control plane object defined for this cluster.
236258
conditions.SetMirror(cluster, clusterv1.ControlPlaneReadyCondition,

internal/controllers/cluster/cluster_controller_phases_test.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
corev1 "k8s.io/api/core/v1"
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27+
"k8s.io/client-go/tools/record"
2728
ctrl "sigs.k8s.io/controller-runtime"
2829
"sigs.k8s.io/controller-runtime/pkg/client"
2930
"sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -136,7 +137,8 @@ func TestClusterReconcilePhases(t *testing.T) {
136137
Build()
137138
}
138139
r := &Reconciler{
139-
Client: c,
140+
Client: c,
141+
recorder: record.NewFakeRecorder(32),
140142
}
141143

142144
res, err := r.reconcileInfrastructure(ctx, tt.cluster)
@@ -215,7 +217,8 @@ func TestClusterReconcilePhases(t *testing.T) {
215217
Build()
216218
}
217219
r := &Reconciler{
218-
Client: c,
220+
Client: c,
221+
recorder: record.NewFakeRecorder(32),
219222
}
220223
res, err := r.reconcileKubeconfig(ctx, tt.cluster)
221224
if tt.wantErr {
@@ -364,7 +367,8 @@ func TestClusterReconciler_reconcilePhase(t *testing.T) {
364367
Build()
365368

366369
r := &Reconciler{
367-
Client: c,
370+
Client: c,
371+
recorder: record.NewFakeRecorder(32),
368372
}
369373
r.reconcilePhase(ctx, tt.cluster)
370374
g.Expect(tt.cluster.Status.GetTypedPhase()).To(Equal(tt.wantPhase))
@@ -479,7 +483,8 @@ func TestClusterReconcilePhases_reconcileFailureDomains(t *testing.T) {
479483
}
480484

481485
r := &Reconciler{
482-
Client: fake.NewClientBuilder().WithObjects(objs...).Build(),
486+
Client: fake.NewClientBuilder().WithObjects(objs...).Build(),
487+
recorder: record.NewFakeRecorder(32),
483488
}
484489

485490
_, err := r.reconcileInfrastructure(ctx, tt.cluster)

0 commit comments

Comments
 (0)