@@ -111,6 +111,7 @@ func (sp *Sample) UpdateTutorial() {
111111 sp .updateConversionFiles ()
112112 sp .updateSampleV2 ()
113113 sp .updateMain ()
114+ sp .updateE2EWebhookConversion ()
114115}
115116
116117func (sp * Sample ) updateCronjobV1DueForce () {
@@ -790,3 +791,103 @@ func (sp *Sample) CodeGen() {
790791 err = sp .ctx .EditHelmPlugin ()
791792 hackutils .CheckError ("Failed to enable helm plugin" , err )
792793}
794+
795+ const webhookConversionE2ETest = `
796+ It("should successfully convert between v1 and v2 versions", func() {
797+ By("creating a v1 CronJob with a specific schedule")
798+ cmd := exec.Command("kubectl", "apply", "-f", "config/samples/batch_v1_cronjob.yaml", "-n", namespace)
799+ _, err := utils.Run(cmd)
800+ Expect(err).NotTo(HaveOccurred(), "Failed to create v1 CronJob")
801+
802+ By("waiting for the v1 CronJob to be created")
803+ Eventually(func(g Gomega) {
804+ cmd := exec.Command("kubectl", "get", "cronjob", "cronjob-sample", "-n", namespace)
805+ _, err := utils.Run(cmd)
806+ g.Expect(err).NotTo(HaveOccurred(), "v1 CronJob should exist")
807+ }, time.Minute, time.Second).Should(Succeed())
808+
809+ By("fetching the v1 CronJob and verifying the schedule format")
810+ cmd = exec.Command("kubectl", "get", "cronjob.v1.batch.tutorial.kubebuilder.io", "cronjob-sample",
811+ "-n", namespace, "-o", "jsonpath={.spec.schedule}")
812+ v1Schedule, err := utils.Run(cmd)
813+ Expect(err).NotTo(HaveOccurred(), "Failed to get v1 CronJob schedule")
814+ Expect(strings.TrimSpace(v1Schedule)).To(Equal("*/1 * * * *"),
815+ "v1 schedule should be in cron format")
816+
817+ By("fetching the same CronJob as v2 and verifying the converted schedule")
818+ Eventually(func(g Gomega) {
819+ cmd := exec.Command("kubectl", "get", "cronjob.v2.batch.tutorial.kubebuilder.io", "cronjob-sample",
820+ "-n", namespace, "-o", "jsonpath={.spec.schedule.minute}")
821+ v2Minute, err := utils.Run(cmd)
822+ g.Expect(err).NotTo(HaveOccurred(), "Failed to get v2 CronJob schedule")
823+ g.Expect(strings.TrimSpace(v2Minute)).To(Equal("*/1"),
824+ "v2 schedule.minute should be converted from v1 schedule")
825+ }, time.Minute, time.Second).Should(Succeed())
826+
827+ By("creating a v2 CronJob with structured schedule fields")
828+ cmd = exec.Command("kubectl", "apply", "-f", "config/samples/batch_v2_cronjob.yaml", "-n", namespace)
829+ _, err = utils.Run(cmd)
830+ Expect(err).NotTo(HaveOccurred(), "Failed to create v2 CronJob")
831+
832+ By("verifying the v2 CronJob has the correct structured schedule")
833+ Eventually(func(g Gomega) {
834+ cmd := exec.Command("kubectl", "get", "cronjob.v2.batch.tutorial.kubebuilder.io", "cronjob-sample",
835+ "-n", namespace, "-o", "jsonpath={.spec.schedule.minute}")
836+ v2Minute, err := utils.Run(cmd)
837+ g.Expect(err).NotTo(HaveOccurred(), "Failed to get v2 CronJob schedule")
838+ g.Expect(strings.TrimSpace(v2Minute)).To(Equal("*/1"),
839+ "v2 CronJob should have minute field set")
840+ }, time.Minute, time.Second).Should(Succeed())
841+
842+ By("fetching the v2 CronJob as v1 and verifying schedule conversion")
843+ Eventually(func(g Gomega) {
844+ cmd := exec.Command("kubectl", "get", "cronjob.v1.batch.tutorial.kubebuilder.io", "cronjob-sample",
845+ "-n", namespace, "-o", "jsonpath={.spec.schedule}")
846+ v1Schedule, err := utils.Run(cmd)
847+ g.Expect(err).NotTo(HaveOccurred(), "Failed to get converted v1 schedule")
848+ // When v2 only has minute field set, it converts to "*/1 * * * *"
849+ g.Expect(strings.TrimSpace(v1Schedule)).To(Equal("*/1 * * * *"),
850+ "v1 schedule should be converted from v2 structured schedule")
851+ }, time.Minute, time.Second).Should(Succeed())
852+ })`
853+
854+ func (sp * Sample ) updateE2EWebhookConversion () {
855+ cronjobE2ETest := filepath .Join (sp .ctx .Dir , "test" , "e2e" , "e2e_test.go" )
856+
857+ // Add strings import if not already present
858+ err := pluginutil .InsertCodeIfNotExist (cronjobE2ETest ,
859+ ` "os/exec"
860+ "path/filepath"
861+ "time"` ,
862+ `
863+ "strings"` )
864+ hackutils .CheckError ("adding strings import for e2e test" , err )
865+
866+ // Add CronJob cleanup to the AfterEach block
867+ err = pluginutil .InsertCode (cronjobE2ETest ,
868+ ` // After each test, check for failures and collect logs, events,
869+ // and pod descriptions for debugging.
870+ AfterEach(func() {` ,
871+ `
872+ By("Cleaning up test CronJob resources")
873+ cmd := exec.Command("kubectl", "delete", "-f", "config/samples/batch_v1_cronjob.yaml", "-n", namespace, "--ignore-not-found=true")
874+ _, _ = utils.Run(cmd)
875+ cmd = exec.Command("kubectl", "delete", "-f", "config/samples/batch_v2_cronjob.yaml", "-n", namespace, "--ignore-not-found=true")
876+ _, _ = utils.Run(cmd)
877+ ` )
878+ hackutils .CheckError ("adding CronJob cleanup to AfterEach" , err )
879+
880+ // Add webhook conversion test after the existing TODO comment
881+ err = pluginutil .InsertCode (cronjobE2ETest ,
882+ ` // TODO: Customize the e2e test suite with scenarios specific to your project.
883+ // Consider applying sample/CR(s) and check their status and/or verifying
884+ // the reconciliation by using the metrics, i.e.:
885+ // metricsOutput, err := getMetricsOutput()
886+ // Expect(err).NotTo(HaveOccurred(), "Failed to retrieve logs from curl pod")
887+ // Expect(metricsOutput).To(ContainSubstring(
888+ // fmt.Sprintf(` + "`" + `controller_runtime_reconcile_total{controller="%s",result="success"} 1` + "`" + `,
889+ // strings.ToLower(<Kind>),
890+ // ))` ,
891+ webhookConversionE2ETest )
892+ hackutils .CheckError ("adding webhook conversion e2e test" , err )
893+ }
0 commit comments