@@ -13,7 +13,7 @@ import (
13
13
14
14
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render"
15
15
"github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/render/validators"
16
- . "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util"
16
+ . "github.com/operator-framework/operator-controller/internal/operator-controller/rukpak/util/testing "
17
17
)
18
18
19
19
func Test_BundleValidatorHasAllValidationFns (t * testing.T ) {
@@ -22,6 +22,10 @@ func Test_BundleValidatorHasAllValidationFns(t *testing.T) {
22
22
validators .CheckCRDResourceUniqueness ,
23
23
validators .CheckOwnedCRDExistence ,
24
24
validators .CheckPackageNameNotEmpty ,
25
+ validators .CheckWebhookDeploymentReferentialIntegrity ,
26
+ validators .CheckWebhookNameUniqueness ,
27
+ validators .CheckConversionWebhookCRDReferenceUniqueness ,
28
+ validators .CheckConversionWebhooksReferenceOwnedCRDs ,
25
29
}
26
30
actualValidationFns := validators .RegistryV1BundleValidator
27
31
@@ -216,3 +220,620 @@ func Test_CheckPackageNameNotEmpty(t *testing.T) {
216
220
})
217
221
}
218
222
}
223
+
224
+ func Test_CheckWebhookSupport (t * testing.T ) {
225
+ for _ , tc := range []struct {
226
+ name string
227
+ bundle * render.RegistryV1
228
+ expectedErrs []error
229
+ }{
230
+ {
231
+ name : "accepts bundles with validating webhook definitions when they only support AllNamespaces install mode" ,
232
+ bundle : & render.RegistryV1 {
233
+ CSV : MakeCSV (
234
+ WithInstallModeSupportFor (v1alpha1 .InstallModeTypeAllNamespaces ),
235
+ WithWebhookDefinitions (
236
+ v1alpha1.WebhookDescription {
237
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
238
+ },
239
+ ),
240
+ ),
241
+ },
242
+ },
243
+ {
244
+ name : "accepts bundles with mutating webhook definitions when they only support AllNamespaces install mode" ,
245
+ bundle : & render.RegistryV1 {
246
+ CSV : MakeCSV (
247
+ WithInstallModeSupportFor (v1alpha1 .InstallModeTypeAllNamespaces ),
248
+ WithWebhookDefinitions (
249
+ v1alpha1.WebhookDescription {
250
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
251
+ },
252
+ ),
253
+ ),
254
+ },
255
+ },
256
+ {
257
+ name : "accepts bundles with conversion webhook definitions when they only support AllNamespaces install mode" ,
258
+ bundle : & render.RegistryV1 {
259
+ CSV : MakeCSV (
260
+ WithInstallModeSupportFor (v1alpha1 .InstallModeTypeAllNamespaces ),
261
+ WithWebhookDefinitions (
262
+ v1alpha1.WebhookDescription {
263
+ Type : v1alpha1 .ConversionWebhook ,
264
+ },
265
+ ),
266
+ ),
267
+ },
268
+ },
269
+ {
270
+ name : "rejects bundles with validating webhook definitions when they support more modes than AllNamespaces install mode" ,
271
+ bundle : & render.RegistryV1 {
272
+ CSV : MakeCSV (
273
+ WithInstallModeSupportFor (v1alpha1 .InstallModeTypeAllNamespaces , v1alpha1 .InstallModeTypeSingleNamespace ),
274
+ WithWebhookDefinitions (
275
+ v1alpha1.WebhookDescription {
276
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
277
+ },
278
+ ),
279
+ ),
280
+ },
281
+ expectedErrs : []error {errors .New ("bundle contains webhook definitions but supported install modes beyond AllNamespaces" )},
282
+ },
283
+ {
284
+ name : "accepts bundles with mutating webhook definitions when they support more modes than AllNamespaces install mode" ,
285
+ bundle : & render.RegistryV1 {
286
+ CSV : MakeCSV (
287
+ WithInstallModeSupportFor (v1alpha1 .InstallModeTypeAllNamespaces , v1alpha1 .InstallModeTypeSingleNamespace ),
288
+ WithWebhookDefinitions (
289
+ v1alpha1.WebhookDescription {
290
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
291
+ },
292
+ ),
293
+ ),
294
+ },
295
+ expectedErrs : []error {errors .New ("bundle contains webhook definitions but supported install modes beyond AllNamespaces" )},
296
+ },
297
+ {
298
+ name : "accepts bundles with conversion webhook definitions when they support more modes than AllNamespaces install mode" ,
299
+ bundle : & render.RegistryV1 {
300
+ CSV : MakeCSV (
301
+ WithInstallModeSupportFor (v1alpha1 .InstallModeTypeAllNamespaces , v1alpha1 .InstallModeTypeSingleNamespace ),
302
+ WithWebhookDefinitions (
303
+ v1alpha1.WebhookDescription {
304
+ Type : v1alpha1 .ConversionWebhook ,
305
+ },
306
+ ),
307
+ ),
308
+ },
309
+ expectedErrs : []error {errors .New ("bundle contains webhook definitions but supported install modes beyond AllNamespaces" )},
310
+ },
311
+ } {
312
+ t .Run (tc .name , func (t * testing.T ) {
313
+ errs := validators .CheckWebhookSupport (tc .bundle )
314
+ require .Equal (t , tc .expectedErrs , errs )
315
+ })
316
+ }
317
+ }
318
+
319
+ func Test_CheckWebhookDeploymentReferentialIntegrity (t * testing.T ) {
320
+ for _ , tc := range []struct {
321
+ name string
322
+ bundle * render.RegistryV1
323
+ expectedErrs []error
324
+ }{
325
+ {
326
+ name : "accepts bundles where webhook definitions reference existing strategy deployment specs" ,
327
+ bundle : & render.RegistryV1 {
328
+ CSV : MakeCSV (
329
+ WithStrategyDeploymentSpecs (
330
+ v1alpha1.StrategyDeploymentSpec {Name : "test-deployment-one" },
331
+ v1alpha1.StrategyDeploymentSpec {Name : "test-deployment-two" },
332
+ ),
333
+ WithWebhookDefinitions (
334
+ v1alpha1.WebhookDescription {
335
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
336
+ GenerateName : "test-webhook" ,
337
+ DeploymentName : "test-deployment-one" ,
338
+ },
339
+ ),
340
+ ),
341
+ },
342
+ }, {
343
+ name : "rejects bundles with webhook definitions that reference non-existing strategy deployment specs" ,
344
+ bundle : & render.RegistryV1 {
345
+ CSV : MakeCSV (
346
+ WithStrategyDeploymentSpecs (
347
+ v1alpha1.StrategyDeploymentSpec {Name : "test-deployment-one" },
348
+ ),
349
+ WithWebhookDefinitions (
350
+ v1alpha1.WebhookDescription {
351
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
352
+ GenerateName : "test-webhook" ,
353
+ DeploymentName : "test-deployment-two" ,
354
+ },
355
+ ),
356
+ ),
357
+ },
358
+ expectedErrs : []error {
359
+ errors .New ("webhook 'test-webhook' of type 'ValidatingAdmissionWebhook' references non-existent deployment 'test-deployment-two'" ),
360
+ },
361
+ }, {
362
+ name : "errors are ordered by deployment strategy spec name, webhook type, and webhook name" ,
363
+ bundle : & render.RegistryV1 {
364
+ CSV : MakeCSV (
365
+ WithStrategyDeploymentSpecs (
366
+ v1alpha1.StrategyDeploymentSpec {Name : "test-deployment-one" },
367
+ ),
368
+ WithWebhookDefinitions (
369
+ v1alpha1.WebhookDescription {
370
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
371
+ GenerateName : "test-val-webhook-c" ,
372
+ DeploymentName : "test-deployment-c" ,
373
+ },
374
+ v1alpha1.WebhookDescription {
375
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
376
+ GenerateName : "test-mute-webhook-a" ,
377
+ DeploymentName : "test-deployment-a" ,
378
+ },
379
+ v1alpha1.WebhookDescription {
380
+ Type : v1alpha1 .ConversionWebhook ,
381
+ GenerateName : "test-conv-webhook-b" ,
382
+ DeploymentName : "test-deployment-b" ,
383
+ }, v1alpha1.WebhookDescription {
384
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
385
+ GenerateName : "test-mute-webhook-c" ,
386
+ DeploymentName : "test-deployment-c" ,
387
+ },
388
+ v1alpha1.WebhookDescription {
389
+ Type : v1alpha1 .ConversionWebhook ,
390
+ GenerateName : "test-conv-webhook-c-b" ,
391
+ DeploymentName : "test-deployment-c" ,
392
+ }, v1alpha1.WebhookDescription {
393
+ Type : v1alpha1 .ConversionWebhook ,
394
+ GenerateName : "test-conv-webhook-c-a" ,
395
+ DeploymentName : "test-deployment-c" ,
396
+ },
397
+ ),
398
+ ),
399
+ },
400
+ expectedErrs : []error {
401
+ errors .New ("webhook 'test-mute-webhook-a' of type 'MutatingAdmissionWebhook' references non-existent deployment 'test-deployment-a'" ),
402
+ errors .New ("webhook 'test-conv-webhook-b' of type 'ConversionWebhook' references non-existent deployment 'test-deployment-b'" ),
403
+ errors .New ("webhook 'test-conv-webhook-c-a' of type 'ConversionWebhook' references non-existent deployment 'test-deployment-c'" ),
404
+ errors .New ("webhook 'test-conv-webhook-c-b' of type 'ConversionWebhook' references non-existent deployment 'test-deployment-c'" ),
405
+ errors .New ("webhook 'test-mute-webhook-c' of type 'MutatingAdmissionWebhook' references non-existent deployment 'test-deployment-c'" ),
406
+ errors .New ("webhook 'test-val-webhook-c' of type 'ValidatingAdmissionWebhook' references non-existent deployment 'test-deployment-c'" ),
407
+ },
408
+ },
409
+ } {
410
+ t .Run (tc .name , func (t * testing.T ) {
411
+ errs := validators .CheckWebhookDeploymentReferentialIntegrity (tc .bundle )
412
+ require .Equal (t , tc .expectedErrs , errs )
413
+ })
414
+ }
415
+ }
416
+
417
+ func Test_CheckWebhookNameUniqueness (t * testing.T ) {
418
+ for _ , tc := range []struct {
419
+ name string
420
+ bundle * render.RegistryV1
421
+ expectedErrs []error
422
+ }{
423
+ {
424
+ name : "accepts bundles without webhook definitions" ,
425
+ bundle : & render.RegistryV1 {
426
+ CSV : MakeCSV (),
427
+ },
428
+ }, {
429
+ name : "accepts bundles with unique webhook names" ,
430
+ bundle : & render.RegistryV1 {
431
+ CSV : MakeCSV (
432
+ WithWebhookDefinitions (
433
+ v1alpha1.WebhookDescription {
434
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
435
+ GenerateName : "test-webhook-one" ,
436
+ }, v1alpha1.WebhookDescription {
437
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
438
+ GenerateName : "test-webhook-two" ,
439
+ }, v1alpha1.WebhookDescription {
440
+ Type : v1alpha1 .ConversionWebhook ,
441
+ GenerateName : "test-webhook-three" ,
442
+ }, v1alpha1.WebhookDescription {
443
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
444
+ GenerateName : "test-webhook-four" ,
445
+ }, v1alpha1.WebhookDescription {
446
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
447
+ GenerateName : "test-webhook-five" ,
448
+ }, v1alpha1.WebhookDescription {
449
+ Type : v1alpha1 .ConversionWebhook ,
450
+ GenerateName : "test-webhook-six" ,
451
+ },
452
+ ),
453
+ ),
454
+ },
455
+ }, {
456
+ name : "accepts bundles with webhooks with the same name but different types" ,
457
+ bundle : & render.RegistryV1 {
458
+ CSV : MakeCSV (
459
+ WithWebhookDefinitions (
460
+ v1alpha1.WebhookDescription {
461
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
462
+ GenerateName : "test-webhook" ,
463
+ }, v1alpha1.WebhookDescription {
464
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
465
+ GenerateName : "test-webhook" ,
466
+ }, v1alpha1.WebhookDescription {
467
+ Type : v1alpha1 .ConversionWebhook ,
468
+ GenerateName : "test-webhook" ,
469
+ },
470
+ ),
471
+ ),
472
+ },
473
+ }, {
474
+ name : "rejects bundles with duplicate validating webhook definitions" ,
475
+ bundle : & render.RegistryV1 {
476
+ CSV : MakeCSV (
477
+ WithWebhookDefinitions (
478
+ v1alpha1.WebhookDescription {
479
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
480
+ GenerateName : "test-webhook" ,
481
+ }, v1alpha1.WebhookDescription {
482
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
483
+ GenerateName : "test-webhook" ,
484
+ },
485
+ ),
486
+ ),
487
+ },
488
+ expectedErrs : []error {
489
+ errors .New ("duplicate webhook 'test-webhook' of type 'ValidatingAdmissionWebhook'" ),
490
+ },
491
+ }, {
492
+ name : "rejects bundles with duplicate mutating webhook definitions" ,
493
+ bundle : & render.RegistryV1 {
494
+ CSV : MakeCSV (
495
+ WithWebhookDefinitions (
496
+ v1alpha1.WebhookDescription {
497
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
498
+ GenerateName : "test-webhook" ,
499
+ }, v1alpha1.WebhookDescription {
500
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
501
+ GenerateName : "test-webhook" ,
502
+ },
503
+ ),
504
+ ),
505
+ },
506
+ expectedErrs : []error {
507
+ errors .New ("duplicate webhook 'test-webhook' of type 'MutatingAdmissionWebhook'" ),
508
+ },
509
+ }, {
510
+ name : "rejects bundles with duplicate conversion webhook definitions" ,
511
+ bundle : & render.RegistryV1 {
512
+ CSV : MakeCSV (
513
+ WithWebhookDefinitions (
514
+ v1alpha1.WebhookDescription {
515
+ Type : v1alpha1 .ConversionWebhook ,
516
+ GenerateName : "test-webhook" ,
517
+ }, v1alpha1.WebhookDescription {
518
+ Type : v1alpha1 .ConversionWebhook ,
519
+ GenerateName : "test-webhook" ,
520
+ },
521
+ ),
522
+ ),
523
+ },
524
+ expectedErrs : []error {
525
+ errors .New ("duplicate webhook 'test-webhook' of type 'ConversionWebhook'" ),
526
+ },
527
+ }, {
528
+ name : "orders errors by webhook type and name" ,
529
+ bundle : & render.RegistryV1 {
530
+ CSV : MakeCSV (
531
+ WithWebhookDefinitions (
532
+ v1alpha1.WebhookDescription {
533
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
534
+ GenerateName : "test-val-webhook-b" ,
535
+ }, v1alpha1.WebhookDescription {
536
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
537
+ GenerateName : "test-val-webhook-a" ,
538
+ },
539
+ v1alpha1.WebhookDescription {
540
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
541
+ GenerateName : "test-val-webhook-a" ,
542
+ }, v1alpha1.WebhookDescription {
543
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
544
+ GenerateName : "test-val-webhook-b" ,
545
+ },
546
+ v1alpha1.WebhookDescription {
547
+ Type : v1alpha1 .ConversionWebhook ,
548
+ GenerateName : "test-conv-webhook-b" ,
549
+ }, v1alpha1.WebhookDescription {
550
+ Type : v1alpha1 .ConversionWebhook ,
551
+ GenerateName : "test-conv-webhook-a" ,
552
+ },
553
+ v1alpha1.WebhookDescription {
554
+ Type : v1alpha1 .ConversionWebhook ,
555
+ GenerateName : "test-conv-webhook-a" ,
556
+ }, v1alpha1.WebhookDescription {
557
+ Type : v1alpha1 .ConversionWebhook ,
558
+ GenerateName : "test-conv-webhook-b" ,
559
+ }, v1alpha1.WebhookDescription {
560
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
561
+ GenerateName : "test-mute-webhook-b" ,
562
+ }, v1alpha1.WebhookDescription {
563
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
564
+ GenerateName : "test-mute-webhook-a" ,
565
+ },
566
+ v1alpha1.WebhookDescription {
567
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
568
+ GenerateName : "test-mute-webhook-a" ,
569
+ }, v1alpha1.WebhookDescription {
570
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
571
+ GenerateName : "test-mute-webhook-b" ,
572
+ },
573
+ ),
574
+ ),
575
+ },
576
+ expectedErrs : []error {
577
+ errors .New ("duplicate webhook 'test-conv-webhook-a' of type 'ConversionWebhook'" ),
578
+ errors .New ("duplicate webhook 'test-conv-webhook-b' of type 'ConversionWebhook'" ),
579
+ errors .New ("duplicate webhook 'test-mute-webhook-a' of type 'MutatingAdmissionWebhook'" ),
580
+ errors .New ("duplicate webhook 'test-mute-webhook-b' of type 'MutatingAdmissionWebhook'" ),
581
+ errors .New ("duplicate webhook 'test-val-webhook-a' of type 'ValidatingAdmissionWebhook'" ),
582
+ errors .New ("duplicate webhook 'test-val-webhook-b' of type 'ValidatingAdmissionWebhook'" ),
583
+ },
584
+ },
585
+ } {
586
+ t .Run (tc .name , func (t * testing.T ) {
587
+ errs := validators .CheckWebhookNameUniqueness (tc .bundle )
588
+ require .Equal (t , tc .expectedErrs , errs )
589
+ })
590
+ }
591
+ }
592
+
593
+ func Test_CheckConversionWebhooksReferenceOwnedCRDs (t * testing.T ) {
594
+ for _ , tc := range []struct {
595
+ name string
596
+ bundle * render.RegistryV1
597
+ expectedErrs []error
598
+ }{
599
+ {
600
+ name : "accepts bundles without webhook definitions" ,
601
+ bundle : & render.RegistryV1 {},
602
+ }, {
603
+ name : "accepts bundles without conversion webhook definitions" ,
604
+ bundle : & render.RegistryV1 {
605
+ CSV : MakeCSV (
606
+ WithWebhookDefinitions (
607
+ v1alpha1.WebhookDescription {
608
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
609
+ GenerateName : "test-val-webhook" ,
610
+ },
611
+ v1alpha1.WebhookDescription {
612
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
613
+ GenerateName : "test-mute-webhook" ,
614
+ },
615
+ ),
616
+ ),
617
+ },
618
+ }, {
619
+ name : "accepts bundles with conversion webhooks that reference owned CRDs" ,
620
+ bundle : & render.RegistryV1 {
621
+ CSV : MakeCSV (
622
+ WithOwnedCRDs (
623
+ v1alpha1.CRDDescription {Name : "some.crd.something" },
624
+ v1alpha1.CRDDescription {Name : "another.crd.something" },
625
+ ),
626
+ WithWebhookDefinitions (
627
+ v1alpha1.WebhookDescription {
628
+ Type : v1alpha1 .ConversionWebhook ,
629
+ GenerateName : "test-webhook" ,
630
+ ConversionCRDs : []string {
631
+ "some.crd.something" ,
632
+ "another.crd.something" ,
633
+ },
634
+ },
635
+ ),
636
+ ),
637
+ },
638
+ }, {
639
+ name : "rejects bundles with conversion webhooks that reference existing CRDs that are not owned" ,
640
+ bundle : & render.RegistryV1 {
641
+ CSV : MakeCSV (
642
+ WithOwnedCRDs (
643
+ v1alpha1.CRDDescription {Name : "some.crd.something" },
644
+ ),
645
+ WithWebhookDefinitions (
646
+ v1alpha1.WebhookDescription {
647
+ Type : v1alpha1 .ConversionWebhook ,
648
+ GenerateName : "test-webhook" ,
649
+ ConversionCRDs : []string {
650
+ "some.crd.something" ,
651
+ "another.crd.something" ,
652
+ },
653
+ },
654
+ ),
655
+ ),
656
+ },
657
+ expectedErrs : []error {
658
+ errors .New ("conversion webhook 'test-webhook' references custom resource definition 'another.crd.something' not owned bundle" ),
659
+ },
660
+ }, {
661
+ name : "errors are ordered by webhook name and CRD name" ,
662
+ bundle : & render.RegistryV1 {
663
+ CSV : MakeCSV (
664
+ WithOwnedCRDs (
665
+ v1alpha1.CRDDescription {Name : "b.crd.something" },
666
+ ),
667
+ WithWebhookDefinitions (
668
+ v1alpha1.WebhookDescription {
669
+ Type : v1alpha1 .ConversionWebhook ,
670
+ GenerateName : "test-webhook-b" ,
671
+ ConversionCRDs : []string {
672
+ "b.crd.something" ,
673
+ },
674
+ }, v1alpha1.WebhookDescription {
675
+ Type : v1alpha1 .ConversionWebhook ,
676
+ GenerateName : "test-webhook-a" ,
677
+ ConversionCRDs : []string {
678
+ "c.crd.something" ,
679
+ "a.crd.something" ,
680
+ },
681
+ }, v1alpha1.WebhookDescription {
682
+ Type : v1alpha1 .ConversionWebhook ,
683
+ GenerateName : "test-webhook-c" ,
684
+ ConversionCRDs : []string {
685
+ "a.crd.something" ,
686
+ "d.crd.something" ,
687
+ },
688
+ },
689
+ ),
690
+ ),
691
+ },
692
+ expectedErrs : []error {
693
+ errors .New ("conversion webhook 'test-webhook-a' references custom resource definition 'a.crd.something' not owned bundle" ),
694
+ errors .New ("conversion webhook 'test-webhook-a' references custom resource definition 'c.crd.something' not owned bundle" ),
695
+ errors .New ("conversion webhook 'test-webhook-c' references custom resource definition 'a.crd.something' not owned bundle" ),
696
+ errors .New ("conversion webhook 'test-webhook-c' references custom resource definition 'd.crd.something' not owned bundle" ),
697
+ },
698
+ },
699
+ } {
700
+ t .Run (tc .name , func (t * testing.T ) {
701
+ errs := validators .CheckConversionWebhooksReferenceOwnedCRDs (tc .bundle )
702
+ require .Equal (t , tc .expectedErrs , errs )
703
+ })
704
+ }
705
+ }
706
+
707
+ func Test_CheckConversionWebhookCRDReferenceUniqueness (t * testing.T ) {
708
+ for _ , tc := range []struct {
709
+ name string
710
+ bundle * render.RegistryV1
711
+ expectedErrs []error
712
+ }{
713
+ {
714
+ name : "accepts bundles without webhook definitions" ,
715
+ bundle : & render.RegistryV1 {},
716
+ expectedErrs : []error {},
717
+ },
718
+ {
719
+ name : "accepts bundles without conversion webhook definitions" ,
720
+ bundle : & render.RegistryV1 {
721
+ CSV : MakeCSV (
722
+ WithWebhookDefinitions (
723
+ v1alpha1.WebhookDescription {
724
+ Type : v1alpha1 .ValidatingAdmissionWebhook ,
725
+ GenerateName : "test-val-webhook" ,
726
+ },
727
+ v1alpha1.WebhookDescription {
728
+ Type : v1alpha1 .MutatingAdmissionWebhook ,
729
+ GenerateName : "test-mute-webhook" ,
730
+ },
731
+ ),
732
+ ),
733
+ },
734
+ expectedErrs : []error {},
735
+ },
736
+ {
737
+ name : "accepts bundles with conversion webhooks that reference different CRDs" ,
738
+ bundle : & render.RegistryV1 {
739
+ CSV : MakeCSV (
740
+ WithOwnedCRDs (
741
+ v1alpha1.CRDDescription {Name : "some.crd.something" },
742
+ v1alpha1.CRDDescription {Name : "another.crd.something" },
743
+ ),
744
+ WithWebhookDefinitions (
745
+ v1alpha1.WebhookDescription {
746
+ Type : v1alpha1 .ConversionWebhook ,
747
+ GenerateName : "test-webhook" ,
748
+ ConversionCRDs : []string {
749
+ "some.crd.something" ,
750
+ },
751
+ },
752
+ v1alpha1.WebhookDescription {
753
+ Type : v1alpha1 .ConversionWebhook ,
754
+ GenerateName : "test-webhook-2" ,
755
+ ConversionCRDs : []string {
756
+ "another.crd.something" ,
757
+ },
758
+ },
759
+ ),
760
+ ),
761
+ },
762
+ expectedErrs : []error {},
763
+ },
764
+ {
765
+ name : "rejects bundles with conversion webhooks that reference the same CRD" ,
766
+ bundle : & render.RegistryV1 {
767
+ CSV : MakeCSV (
768
+ WithOwnedCRDs (
769
+ v1alpha1.CRDDescription {Name : "some.crd.something" },
770
+ ),
771
+ WithWebhookDefinitions (
772
+ v1alpha1.WebhookDescription {
773
+ Type : v1alpha1 .ConversionWebhook ,
774
+ GenerateName : "test-webhook" ,
775
+ ConversionCRDs : []string {
776
+ "some.crd.something" ,
777
+ },
778
+ },
779
+ v1alpha1.WebhookDescription {
780
+ Type : v1alpha1 .ConversionWebhook ,
781
+ GenerateName : "test-webhook-two" ,
782
+ ConversionCRDs : []string {
783
+ "some.crd.something" ,
784
+ },
785
+ },
786
+ ),
787
+ ),
788
+ },
789
+ expectedErrs : []error {
790
+ errors .New ("conversion webhooks [test-webhook,test-webhook-two] reference same custom resource definition 'some.crd.something'" ),
791
+ },
792
+ },
793
+ {
794
+ name : "errors are ordered by CRD name and webhook names" ,
795
+ bundle : & render.RegistryV1 {
796
+ CSV : MakeCSV (
797
+ WithOwnedCRDs (
798
+ v1alpha1.CRDDescription {Name : "b.crd.something" },
799
+ ),
800
+ WithWebhookDefinitions (
801
+ v1alpha1.WebhookDescription {
802
+ Type : v1alpha1 .ConversionWebhook ,
803
+ GenerateName : "test-webhook-b" ,
804
+ ConversionCRDs : []string {
805
+ "b.crd.something" ,
806
+ "a.crd.something" ,
807
+ },
808
+ }, v1alpha1.WebhookDescription {
809
+ Type : v1alpha1 .ConversionWebhook ,
810
+ GenerateName : "test-webhook-a" ,
811
+ ConversionCRDs : []string {
812
+ "d.crd.something" ,
813
+ "a.crd.something" ,
814
+ "b.crd.something" ,
815
+ },
816
+ }, v1alpha1.WebhookDescription {
817
+ Type : v1alpha1 .ConversionWebhook ,
818
+ GenerateName : "test-webhook-c" ,
819
+ ConversionCRDs : []string {
820
+ "b.crd.something" ,
821
+ "d.crd.something" ,
822
+ },
823
+ },
824
+ ),
825
+ ),
826
+ },
827
+ expectedErrs : []error {
828
+ errors .New ("conversion webhooks [test-webhook-a,test-webhook-b] reference same custom resource definition 'a.crd.something'" ),
829
+ errors .New ("conversion webhooks [test-webhook-a,test-webhook-b,test-webhook-c] reference same custom resource definition 'b.crd.something'" ),
830
+ errors .New ("conversion webhooks [test-webhook-a,test-webhook-c] reference same custom resource definition 'd.crd.something'" ),
831
+ },
832
+ },
833
+ } {
834
+ t .Run (tc .name , func (t * testing.T ) {
835
+ errs := validators .CheckConversionWebhookCRDReferenceUniqueness (tc .bundle )
836
+ require .Equal (t , tc .expectedErrs , errs )
837
+ })
838
+ }
839
+ }
0 commit comments