@@ -319,7 +319,86 @@ var _ = Describe("Manager", Ordered, func() {
319
319
320
320
// +kubebuilder:scaffold:e2e-webhooks-checks
321
321
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
+ })
323
402
// Consider applying sample/CR(s) and check their status and/or verifying
324
403
// the reconciliation by using the metrics, i.e.:
325
404
// metricsOutput := getMetricsOutput()
0 commit comments