@@ -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