Skip to content

Commit d65d418

Browse files
committed
feat: add e2e test to validate webhook conversion between versions
1 parent b77b135 commit d65d418

File tree

1 file changed

+80
-1
lines changed
  • docs/book/src/multiversion-tutorial/testdata/project/test/e2e

1 file changed

+80
-1
lines changed

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

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,86 @@ var _ = Describe("Manager", Ordered, func() {
319319

320320
// +kubebuilder:scaffold:e2e-webhooks-checks
321321

322-
// TODO: Customize the e2e test suite with scenarios specific to your project.
322+
It("should validate webhook conversion between v1 and v2 CronJob versions", func() {
323+
By("applying the v1 CronJob sample")
324+
cmd := exec.Command("kubectl", "apply", "-f", "config/samples/batch_v1_cronjob.yaml", "-n", namespace)
325+
_, err := utils.Run(cmd)
326+
Expect(err).NotTo(HaveOccurred(), "Failed to apply v1 CronJob sample")
327+
328+
By("verifying the v1 CronJob was created successfully")
329+
Eventually(func(g Gomega) {
330+
cmd := exec.Command("kubectl", "get", "cronjob.batch.tutorial.kubebuilder.io", "cronjob-sample", "-n", namespace, "-o", "json")
331+
output, err := utils.Run(cmd)
332+
g.Expect(err).NotTo(HaveOccurred())
333+
334+
var cronJobData map[string]interface{}
335+
err = json.Unmarshal([]byte(output), &cronJobData)
336+
g.Expect(err).NotTo(HaveOccurred())
337+
338+
// Verify this is a v1 resource with string schedule
339+
spec, ok := cronJobData["spec"].(map[string]interface{})
340+
g.Expect(ok).To(BeTrue(), "Failed to get spec from CronJob")
341+
342+
schedule, ok := spec["schedule"].(string)
343+
g.Expect(ok).To(BeTrue(), "Schedule should be a string in v1 format")
344+
g.Expect(schedule).To(Equal("*/1 * * * *"), "Schedule should match the v1 sample format")
345+
}).Should(Succeed())
346+
347+
By("deleting the v1 CronJob sample")
348+
cmd = exec.Command("kubectl", "delete", "-f", "config/samples/batch_v1_cronjob.yaml", "-n", namespace, "--ignore-not-found")
349+
_, _ = utils.Run(cmd)
350+
351+
By("applying the v2 CronJob sample")
352+
cmd = exec.Command("kubectl", "apply", "-f", "config/samples/batch_v2_cronjob.yaml", "-n", namespace)
353+
_, err = utils.Run(cmd)
354+
Expect(err).NotTo(HaveOccurred(), "Failed to apply v2 CronJob sample")
355+
356+
By("verifying the v2 CronJob was created and converted to hub version")
357+
Eventually(func(g Gomega) {
358+
cmd := exec.Command("kubectl", "get", "cronjob.batch.tutorial.kubebuilder.io", "cronjob-sample", "-n", namespace, "-o", "json")
359+
output, err := utils.Run(cmd)
360+
g.Expect(err).NotTo(HaveOccurred())
361+
362+
var cronJobData map[string]interface{}
363+
err = json.Unmarshal([]byte(output), &cronJobData)
364+
g.Expect(err).NotTo(HaveOccurred())
365+
366+
spec, ok := cronJobData["spec"].(map[string]interface{})
367+
g.Expect(ok).To(BeTrue(), "Failed to get spec from CronJob")
368+
369+
// The schedule should be stored as string in the hub version (v1) due to conversion
370+
schedule, ok := spec["schedule"].(string)
371+
g.Expect(ok).To(BeTrue(), "Schedule should be stored as string due to hub conversion")
372+
// The v2 sample has minute: "*/1", which should convert to "*/1 * * * *"
373+
g.Expect(schedule).To(Equal("*/1 * * * *"), "Schedule should be converted from v2 structured format to v1 cron format")
374+
}).Should(Succeed())
375+
376+
By("testing conversion by patching the CronJob to trigger webhook conversion")
377+
// Apply a patch to trigger conversion webhook calls
378+
patchData := `{"metadata":{"labels":{"test":"conversion"}}}`
379+
cmd = exec.Command("kubectl", "patch", "cronjob.batch.tutorial.kubebuilder.io", "cronjob-sample", "-n", namespace,
380+
"--type", "merge", "-p", patchData)
381+
_, err = utils.Run(cmd)
382+
Expect(err).NotTo(HaveOccurred(), "Failed to patch CronJob")
383+
384+
By("verifying conversion webhook was called by checking controller logs")
385+
// Check the controller logs for conversion messages
386+
Eventually(func(g Gomega) {
387+
cmd := exec.Command("kubectl", "logs", controllerPodName, "-n", namespace)
388+
logs, err := utils.Run(cmd)
389+
g.Expect(err).NotTo(HaveOccurred())
390+
391+
// Look for conversion log messages that should be present in the conversion functions
392+
g.Expect(logs).To(ContainSubstring("ConvertTo: Converting CronJob from Spoke version v2 to Hub version v1"),
393+
"Should see v2->v1 conversion in logs")
394+
g.Expect(logs).To(ContainSubstring("ConvertFrom: Converting CronJob from Hub version v1 to Spoke version v2"),
395+
"Should see v1->v2 conversion in logs")
396+
}, 30*time.Second, 2*time.Second).Should(Succeed())
397+
398+
By("cleaning up the v2 CronJob sample")
399+
cmd = exec.Command("kubectl", "delete", "-f", "config/samples/batch_v2_cronjob.yaml", "-n", namespace, "--ignore-not-found")
400+
_, _ = utils.Run(cmd) // Use _ for cleanup as it might fail if resources don't exist
401+
})
323402
// Consider applying sample/CR(s) and check their status and/or verifying
324403
// the reconciliation by using the metrics, i.e.:
325404
// metricsOutput := getMetricsOutput()

0 commit comments

Comments
 (0)