Skip to content

Commit 2441784

Browse files
🐛 Fix e2e test flakes when webhooks are scaffolded
Projects with webhooks may experience flaky e2e tests due to webhook server not being ready when the metrics test creates the curl-metrics pod.
1 parent 9eee7a7 commit 2441784

File tree

8 files changed

+89
-8
lines changed

8 files changed

+89
-8
lines changed

docs/book/src/cronjob-tutorial/testdata/project/test/e2e/e2e_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ var _ = Describe("Manager", Ordered, func() {
216216
}
217217
Eventually(verifyMetricsServerStarted).Should(Succeed())
218218

219+
By("ensuring the controller pod is fully ready before creating test pods")
220+
verifyControllerPodReady := func(g Gomega) {
221+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
222+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
223+
output, err := utils.Run(cmd)
224+
g.Expect(err).NotTo(HaveOccurred())
225+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
226+
}
227+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
228+
219229
By("creating the curl-metrics pod to access the metrics endpoint")
220230
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
221231
"--namespace", namespace,

docs/book/src/getting-started/testdata/project/test/e2e/e2e_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ var _ = Describe("Manager", Ordered, func() {
211211
}
212212
Eventually(verifyMetricsServerStarted).Should(Succeed())
213213

214+
By("ensuring the controller pod is fully ready before creating test pods")
215+
verifyControllerPodReady := func(g Gomega) {
216+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
217+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
218+
output, err := utils.Run(cmd)
219+
g.Expect(err).NotTo(HaveOccurred())
220+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
221+
}
222+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
223+
214224
By("creating the curl-metrics pod to access the metrics endpoint")
215225
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
216226
"--namespace", namespace,

docs/book/src/multiversion-tutorial/testdata/project/test/e2e/e2e_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,16 @@ var _ = Describe("Manager", Ordered, func() {
223223
}
224224
Eventually(verifyMetricsServerStarted).Should(Succeed())
225225

226+
By("ensuring the controller pod is fully ready before creating test pods")
227+
verifyControllerPodReady := func(g Gomega) {
228+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
229+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
230+
output, err := utils.Run(cmd)
231+
g.Expect(err).NotTo(HaveOccurred())
232+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
233+
}
234+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
235+
226236
By("creating the curl-metrics pod to access the metrics endpoint")
227237
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
228238
"--namespace", namespace,

pkg/plugins/golang/v4/scaffolds/internal/templates/test/e2e/test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,16 @@ var _ = Describe("Manager", Ordered, func() {
394394
}
395395
Eventually(verifyMetricsServerStarted).Should(Succeed())
396396
397+
By("ensuring the controller pod is fully ready before creating test pods")
398+
verifyControllerPodReady := func(g Gomega) {
399+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
400+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
401+
output, err := utils.Run(cmd)
402+
g.Expect(err).NotTo(HaveOccurred())
403+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
404+
}
405+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
406+
397407
By("creating the curl-metrics pod to access the metrics endpoint")
398408
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
399409
"--namespace", namespace,

test/e2e/v4/plugin_cluster_test.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ func Run(kbc *utils.TestContext, hasWebhook, isToUseInstaller, isToUseHelmChart,
299299

300300
if hasMetrics {
301301
By("checking the metrics values to validate that the created resource object gets reconciled")
302-
metricsOutput := getMetricsOutput(kbc)
302+
metricsOutput := getMetricsOutput(controllerPodName, kbc)
303303
Expect(metricsOutput).To(ContainSubstring(fmt.Sprintf(
304304
`controller_runtime_reconcile_total{controller="%s",result="success"} 1`,
305305
strings.ToLower(kbc.Kind),
@@ -392,7 +392,7 @@ func Run(kbc *utils.TestContext, hasWebhook, isToUseInstaller, isToUseHelmChart,
392392

393393
if hasMetrics {
394394
By("validating conversion metrics to confirm conversion operations")
395-
metricsOutput := getMetricsOutput(kbc)
395+
metricsOutput := getMetricsOutput(controllerPodName, kbc)
396396
conversionMetric := `controller_runtime_reconcile_total{controller="conversiontest",result="success"} 1`
397397
Expect(metricsOutput).To(ContainSubstring(conversionMetric),
398398
"Expected metric for successful ConversionTest reconciliation")
@@ -438,7 +438,7 @@ func getControllerName(kbc *utils.TestContext) string {
438438
}
439439

440440
// getMetricsOutput return the metrics output from curl pod
441-
func getMetricsOutput(kbc *utils.TestContext) string {
441+
func getMetricsOutput(controllerPodName string, kbc *utils.TestContext) string {
442442
_, err := kbc.Kubectl.Command(
443443
"get", "clusterrolebinding", fmt.Sprintf("metrics-%s", kbc.TestSuffix),
444444
)
@@ -484,11 +484,22 @@ func getMetricsOutput(kbc *utils.TestContext) string {
484484
// when using controller-runtime's WithAuthenticationAndAuthorization() with self-signed certificates.
485485
// This delay appears to stem from Kubernetes itself, potentially due to changes in how it initializes
486486
// service account tokens or handles TLS/service readiness.
487-
//
488-
// Without this delay, tests that curl the /metrics endpoint using a token can fail from k8s 1.33+.
489-
// As a temporary workaround, we wait briefly before attempting to access metrics.
490-
By("waiting briefly to ensure that the certs are provisioned and metrics are available")
491-
time.Sleep(15 * time.Second)
487+
// Instead of using a fixed sleep, we check that the controller pod is fully ready, which ensures
488+
// all containers are running, volumes are mounted, and readiness probes pass. This is especially
489+
// important when webhooks are configured, as the webhook server must be serving before we can
490+
// create the curl-metrics pod (otherwise validating webhooks will reject the pod creation).
491+
By("ensuring the controller pod is fully ready before creating test pods")
492+
verifyControllerPodReady := func(g Gomega) {
493+
var output string
494+
output, err = kbc.Kubectl.Get(
495+
true,
496+
"pod", controllerPodName,
497+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}",
498+
)
499+
g.Expect(err).NotTo(HaveOccurred())
500+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
501+
}
502+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
492503

493504
By("creating a curl pod to access the metrics endpoint")
494505
cmdOpts := cmdOptsToCreateCurlPod(kbc, token)

testdata/project-v4-multigroup/test/e2e/e2e_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ var _ = Describe("Manager", Ordered, func() {
211211
}
212212
Eventually(verifyMetricsServerStarted).Should(Succeed())
213213

214+
By("ensuring the controller pod is fully ready before creating test pods")
215+
verifyControllerPodReady := func(g Gomega) {
216+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
217+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
218+
output, err := utils.Run(cmd)
219+
g.Expect(err).NotTo(HaveOccurred())
220+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
221+
}
222+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
223+
214224
By("creating the curl-metrics pod to access the metrics endpoint")
215225
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
216226
"--namespace", namespace,

testdata/project-v4-with-plugins/test/e2e/e2e_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ var _ = Describe("Manager", Ordered, func() {
211211
}
212212
Eventually(verifyMetricsServerStarted).Should(Succeed())
213213

214+
By("ensuring the controller pod is fully ready before creating test pods")
215+
verifyControllerPodReady := func(g Gomega) {
216+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
217+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
218+
output, err := utils.Run(cmd)
219+
g.Expect(err).NotTo(HaveOccurred())
220+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
221+
}
222+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
223+
214224
By("creating the curl-metrics pod to access the metrics endpoint")
215225
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
216226
"--namespace", namespace,

testdata/project-v4/test/e2e/e2e_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ var _ = Describe("Manager", Ordered, func() {
211211
}
212212
Eventually(verifyMetricsServerStarted).Should(Succeed())
213213

214+
By("ensuring the controller pod is fully ready before creating test pods")
215+
verifyControllerPodReady := func(g Gomega) {
216+
cmd := exec.Command("kubectl", "get", "pod", controllerPodName, "-n", namespace,
217+
"-o", "jsonpath={.status.conditions[?(@.type=='Ready')].status}")
218+
output, err := utils.Run(cmd)
219+
g.Expect(err).NotTo(HaveOccurred())
220+
g.Expect(output).To(Equal("True"), "Controller pod not ready")
221+
}
222+
Eventually(verifyControllerPodReady, 3*time.Minute, time.Second).Should(Succeed())
223+
214224
By("creating the curl-metrics pod to access the metrics endpoint")
215225
cmd = exec.Command("kubectl", "run", "curl-metrics", "--restart=Never",
216226
"--namespace", namespace,

0 commit comments

Comments
 (0)