@@ -25,6 +25,7 @@ import (
25
25
"os"
26
26
"os/exec"
27
27
"path/filepath"
28
+ "strings"
28
29
"time"
29
30
30
31
. "github.com/onsi/ginkgo/v2"
@@ -178,9 +179,14 @@ var _ = Describe("Manager", Ordered, func() {
178
179
cmd := exec .Command ("kubectl" , "create" , "clusterrolebinding" , metricsRoleBindingName ,
179
180
"--clusterrole=project-metrics-reader" ,
180
181
fmt .Sprintf ("--serviceaccount=%s:%s" , namespace , serviceAccountName ),
181
- )
182
- _ , err := utils .Run (cmd )
183
- Expect (err ).NotTo (HaveOccurred (), "Failed to create ClusterRoleBinding" )
182
+ "--dry-run=client" , "-o" , "yaml" )
183
+ output , err := utils .Run (cmd )
184
+ Expect (err ).NotTo (HaveOccurred (), "Failed to generate ClusterRoleBinding YAML" )
185
+
186
+ cmd = exec .Command ("kubectl" , "apply" , "-f" , "-" )
187
+ cmd .Stdin = strings .NewReader (output )
188
+ _ , err = utils .Run (cmd )
189
+ Expect (err ).NotTo (HaveOccurred (), "Failed to apply ClusterRoleBinding" )
184
190
185
191
By ("validating that the metrics service is available" )
186
192
cmd = exec .Command ("kubectl" , "get" , "service" , metricsServiceName , "-n" , namespace )
@@ -319,7 +325,86 @@ var _ = Describe("Manager", Ordered, func() {
319
325
320
326
// +kubebuilder:scaffold:e2e-webhooks-checks
321
327
322
- // TODO: Customize the e2e test suite with scenarios specific to your project.
328
+ It ("should validate webhook conversion between v1 and v2 CronJob versions" , func () {
329
+ By ("applying the v1 CronJob sample" )
330
+ cmd := exec .Command ("kubectl" , "apply" , "-f" , "config/samples/batch_v1_cronjob.yaml" , "-n" , namespace )
331
+ _ , err := utils .Run (cmd )
332
+ Expect (err ).NotTo (HaveOccurred (), "Failed to apply v1 CronJob sample" )
333
+
334
+ By ("checking what is actually stored for v1 CronJob" )
335
+ Eventually (func (g Gomega ) {
336
+ cmd := exec .Command ("kubectl" , "get" , "cronjob.batch.tutorial.kubebuilder.io" , "cronjob-sample" , "-n" , namespace , "-o" , "json" )
337
+ output , err := utils .Run (cmd )
338
+ g .Expect (err ).NotTo (HaveOccurred ())
339
+
340
+ // Log the full output for debugging
341
+ fmt .Printf ("V1 CronJob JSON: %s\n " , output )
342
+
343
+ var cronJobData map [string ]interface {}
344
+ err = json .Unmarshal ([]byte (output ), & cronJobData )
345
+ g .Expect (err ).NotTo (HaveOccurred ())
346
+
347
+ spec , ok := cronJobData ["spec" ].(map [string ]interface {})
348
+ g .Expect (ok ).To (BeTrue (), "Failed to get spec from CronJob" )
349
+
350
+ scheduleValue := spec ["schedule" ]
351
+ g .Expect (scheduleValue ).NotTo (BeNil (), "Schedule field should exist" )
352
+
353
+ fmt .Printf ("Schedule value: %+v (type: %T)\n " , scheduleValue , scheduleValue )
354
+ }).Should (Succeed ())
355
+
356
+ By ("deleting the v1 CronJob sample" )
357
+ cmd = exec .Command ("kubectl" , "delete" , "-f" , "config/samples/batch_v1_cronjob.yaml" , "-n" , namespace , "--ignore-not-found" )
358
+ _ , _ = utils .Run (cmd )
359
+
360
+ By ("applying the v2 CronJob sample" )
361
+ cmd = exec .Command ("kubectl" , "apply" , "-f" , "config/samples/batch_v2_cronjob.yaml" , "-n" , namespace )
362
+ _ , err = utils .Run (cmd )
363
+ Expect (err ).NotTo (HaveOccurred (), "Failed to apply v2 CronJob sample" )
364
+
365
+ By ("checking what is actually stored for v2 CronJob" )
366
+ Eventually (func (g Gomega ) {
367
+ cmd := exec .Command ("kubectl" , "get" , "cronjob.batch.tutorial.kubebuilder.io" , "cronjob-sample" , "-n" , namespace , "-o" , "json" )
368
+ output , err := utils .Run (cmd )
369
+ g .Expect (err ).NotTo (HaveOccurred ())
370
+
371
+ // Log the full output for debugging
372
+ fmt .Printf ("V2 CronJob JSON: %s\n " , output )
373
+
374
+ var cronJobData map [string ]interface {}
375
+ err = json .Unmarshal ([]byte (output ), & cronJobData )
376
+ g .Expect (err ).NotTo (HaveOccurred ())
377
+
378
+ spec , ok := cronJobData ["spec" ].(map [string ]interface {})
379
+ g .Expect (ok ).To (BeTrue (), "Failed to get spec from CronJob" )
380
+
381
+ scheduleValue := spec ["schedule" ]
382
+ g .Expect (scheduleValue ).NotTo (BeNil (), "Schedule field should exist" )
383
+
384
+ fmt .Printf ("Schedule value: %+v (type: %T)\n " , scheduleValue , scheduleValue )
385
+ }).Should (Succeed ())
386
+
387
+ By ("verifying conversion webhook was called by checking controller logs" )
388
+ Eventually (func (g Gomega ) {
389
+ cmd := exec .Command ("kubectl" , "logs" , controllerPodName , "-n" , namespace )
390
+ logs , err := utils .Run (cmd )
391
+ g .Expect (err ).NotTo (HaveOccurred ())
392
+
393
+ fmt .Printf ("Controller logs:\n %s\n " , logs )
394
+
395
+ // Look for any conversion log messages
396
+ hasConversion := strings .Contains (logs , "ConvertTo" ) || strings .Contains (logs , "ConvertFrom" )
397
+ if hasConversion {
398
+ fmt .Printf ("Found conversion logs!\n " )
399
+ } else {
400
+ fmt .Printf ("No conversion logs found\n " )
401
+ }
402
+ }, 30 * time .Second , 2 * time .Second ).Should (Succeed ())
403
+
404
+ By ("cleaning up the v2 CronJob sample" )
405
+ cmd = exec .Command ("kubectl" , "delete" , "-f" , "config/samples/batch_v2_cronjob.yaml" , "-n" , namespace , "--ignore-not-found" )
406
+ _ , _ = utils .Run (cmd )
407
+ })
323
408
// Consider applying sample/CR(s) and check their status and/or verifying
324
409
// the reconciliation by using the metrics, i.e.:
325
410
// metricsOutput := getMetricsOutput()
0 commit comments