From 7bcb1a43265f90b400a909008184ec036061777c Mon Sep 17 00:00:00 2001 From: Niklas Walter Date: Wed, 8 Apr 2026 14:10:18 +0200 Subject: [PATCH] Emit Warning events when scheduling is blocked by missing children When the Wave reconciler detects missing or invalid ConfigMaps/Secrets, it now emits a Kubernetes Warning event with reason 'MissingChildren' and details of what's missing (e.g. 'missing required configmap default/foo'). Also change the webhook-path 'SchedulingDisabled' event from EventTypeNormal to EventTypeWarning, since blocking scheduling is a warning condition. Closes #186 (wave-k8s/wave) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- pkg/core/controller_suite.go | 38 ++++++++++++++++++++++++++++++++++++ pkg/core/handler.go | 3 ++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkg/core/controller_suite.go b/pkg/core/controller_suite.go index d3b0352..08b836a 100644 --- a/pkg/core/controller_suite.go +++ b/pkg/core/controller_suite.go @@ -458,6 +458,25 @@ func ControllerTestSuite[I InstanceType]( Expect(instance.GetAnnotations()[SchedulingDisabledAnnotation]).To(Equal("default-scheduler")) }) + It("Emits a MissingChildren warning event", func() { + eventReason := func(event *corev1.Event) string { + return event.Reason + } + eventType := func(event *corev1.Event) string { + return event.Type + } + Eventually(func() *corev1.EventList { + events := &corev1.EventList{} + Expect(m.Client.List(context.TODO(), events)).To(Succeed()) + return events + }, timeout).Should(utils.WithItems(ContainElement( + SatisfyAll( + WithTransform(eventReason, Equal("MissingChildren")), + WithTransform(eventType, Equal(corev1.EventTypeWarning)), + ), + ))) + }) + Context("And the missing child is created", func() { JustBeforeEach(func() { expectNoReconciles() @@ -559,6 +578,25 @@ func ControllerTestSuite[I InstanceType]( Expect(instance.GetAnnotations()[SchedulingDisabledAnnotation]).To(Equal("default-scheduler")) }) + It("Emits a MissingChildren warning event", func() { + eventReason := func(event *corev1.Event) string { + return event.Reason + } + eventType := func(event *corev1.Event) string { + return event.Type + } + Eventually(func() *corev1.EventList { + events := &corev1.EventList{} + Expect(m.Client.List(context.TODO(), events)).To(Succeed()) + return events + }, timeout).Should(utils.WithItems(ContainElement( + SatisfyAll( + WithTransform(eventReason, Equal("MissingChildren")), + WithTransform(eventType, Equal(corev1.EventTypeWarning)), + ), + ))) + }) + Context("And the missing child is created with a missing field", func() { BeforeEach(func() { expectNoReconciles() diff --git a/pkg/core/handler.go b/pkg/core/handler.go index 02c6dd4..a847e29 100644 --- a/pkg/core/handler.go +++ b/pkg/core/handler.go @@ -112,6 +112,7 @@ func (h *Handler[I]) handlePodController(ctx context.Context, instance I) (recon err = h.checkRequiredChildren(configMaps, secrets, configMapsConfig, secretsConfig) if err != nil { // We are missing children but we added watchers for all children so we are done + h.recorder.Eventf(instance, corev1.EventTypeWarning, "MissingChildren", "Scheduling blocked due to missing children: %s", err) return reconcile.Result{}, nil } @@ -191,7 +192,7 @@ func (h *Handler[I]) updatePodController(instance I, dryRun bool, isCreate bool) if isCreate { if !dryRun { log.V(0).Info("Not all required children found yet. Disabling scheduling!", "err", err) - h.recorder.Eventf(instance, corev1.EventTypeNormal, "SchedulingDisabled", "Disabled scheduling due to missing children: %s", err) + h.recorder.Eventf(instance, corev1.EventTypeWarning, "SchedulingDisabled", "Disabled scheduling due to missing children: %s", err) } disableScheduling(instance) } else {