From 06c1732891630bce3aeafa33682afd5684b7cd87 Mon Sep 17 00:00:00 2001 From: Saloni Tanmor Date: Tue, 18 Aug 2026 08:37:22 +0530 Subject: [PATCH] fix: consistent dry-run behavior between NodeController and RuleController --- internal/controller/node_controller.go | 35 ++++++++++++++++++++++++-- test/e2e/e2e_test.go | 25 +++++++++++------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/internal/controller/node_controller.go b/internal/controller/node_controller.go index 2d1b1c12..7e0d9294 100644 --- a/internal/controller/node_controller.go +++ b/internal/controller/node_controller.go @@ -140,10 +140,41 @@ func (r *RuleReadinessController) processNodeAgainstAllRules(ctx context.Context continue } - // Skip if dry run + // Handle dry run if rule.Spec.DryRun { - log.Info("Skipping rule - dry run mode", + log.Info("Evaluating rule - dry run mode", "node", node.Name, "rule", rule.Name) + + nodeList := &corev1.NodeList{} + if err := r.List(ctx, nodeList); err != nil { + log.Error(err, "Failed to list nodes for dry run evaluation", "rule", rule.Name) + errs = append(errs, err) + continue + } + + if err := r.processDryRun(ctx, rule, nodeList); err != nil { + log.Error(err, "Failed to process dry run for node", + "node", node.Name, "rule", rule.Name) + errs = append(errs, err) + continue + } + + err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + latestRule := &readinessv1alpha1.NodeReadinessRule{} + if err := r.Get(ctx, client.ObjectKey{Name: rule.Name}, latestRule); err != nil { + return err + } + patch := client.MergeFrom(latestRule.DeepCopy()) + latestRule.Status.DryRunResults = rule.Status.DryRunResults + latestRule.Status.ObservedGeneration = rule.Status.ObservedGeneration + return r.Status().Patch(ctx, latestRule, patch) + }) + + if err != nil { + log.Error(err, "Failed to update rule status after dry run evaluation", + "node", node.Name, "rule", rule.Name) + errs = append(errs, err) + } continue } diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index e6382e09..1801e9b7 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -543,15 +543,22 @@ status: }, 10*time.Second, 2*time.Second).Should(BeTrue()) By("verifying rule has dry-run results showing what would happen") - Eventually(func() bool { - cmd := exec.Command("kubectl", "get", "nodereadinessrule", "dryrun-test-rule", "-o", "jsonpath={.status.dryRunResults}") - output, err := utils.Run(cmd) - if err != nil { - return false - } - // Check that dry run results exist and contain the node - return len(output) > 0 - }, 30*time.Second, 2*time.Second).Should(BeTrue()) + Eventually(func() string { + cmd := exec.Command("kubectl", "get", "nodereadinessrule", "dryrun-test-rule", "-o", "jsonpath={.status.dryRunResults.taintsToAdd}") + output, _ := utils.Run(cmd) + return output + }, 30*time.Second, 2*time.Second).Should(Equal("1")) + + By("updating node condition to True") + err = patchNodeCondition(nodeName, "TestReady", "True") + Expect(err).NotTo(HaveOccurred()) + + By("verifying rule dry-run results update to reflect the change") + Eventually(func() string { + cmd := exec.Command("kubectl", "get", "nodereadinessrule", "dryrun-test-rule", "-o", "jsonpath={.status.dryRunResults.taintsToAdd}") + output, _ := utils.Run(cmd) + return output + }, 30*time.Second, 2*time.Second).Should(BeEmpty()) By("cleaning up test resources") exec.Command("kubectl", "delete", "node", nodeName).Run()