@@ -22,7 +22,10 @@ import (
22
22
"testing"
23
23
24
24
"k8s.io/api/admissionregistration/v1"
25
+ corev1 "k8s.io/api/core/v1"
26
+ "k8s.io/apimachinery/pkg/api/errors"
25
27
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
+ "k8s.io/apimachinery/pkg/labels"
26
29
"k8s.io/apimachinery/pkg/runtime"
27
30
"k8s.io/apimachinery/pkg/runtime/schema"
28
31
"k8s.io/apiserver/pkg/admission"
@@ -75,7 +78,7 @@ func TestShouldCallHook(t *testing.T) {
75
78
}{
76
79
{
77
80
name : "no rules (just write)" ,
78
- webhook : & v1.ValidatingWebhook {Rules : []v1.RuleWithOperations {}},
81
+ webhook : & v1.ValidatingWebhook {NamespaceSelector : & metav1. LabelSelector {}, Rules : []v1.RuleWithOperations {}},
79
82
attrs : admission .NewAttributesRecord (nil , nil , schema.GroupVersionKind {"apps" , "v1" , "Deployment" }, "ns" , "name" , schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "" , admission .Create , & metav1.CreateOptions {}, false , nil ),
80
83
expectCall : false ,
81
84
},
@@ -329,3 +332,228 @@ func TestShouldCallHook(t *testing.T) {
329
332
})
330
333
}
331
334
}
335
+
336
+ type fakeNamespaceLister struct {
337
+ namespaces map [string ]* corev1.Namespace
338
+ }
339
+
340
+ func (f fakeNamespaceLister ) List (selector labels.Selector ) (ret []* corev1.Namespace , err error ) {
341
+ return nil , nil
342
+ }
343
+ func (f fakeNamespaceLister ) Get (name string ) (* corev1.Namespace , error ) {
344
+ ns , ok := f .namespaces [name ]
345
+ if ok {
346
+ return ns , nil
347
+ }
348
+ return nil , errors .NewNotFound (corev1 .Resource ("namespaces" ), name )
349
+ }
350
+
351
+ func BenchmarkShouldCallHookWithComplexSelector (b * testing.B ) {
352
+ allScopes := v1 .AllScopes
353
+ equivalentMatch := v1 .Equivalent
354
+
355
+ namespace1Labels := map [string ]string {"ns" : "ns1" }
356
+ namespace1 := corev1.Namespace {
357
+ ObjectMeta : metav1.ObjectMeta {
358
+ Name : "ns1" ,
359
+ Labels : namespace1Labels ,
360
+ },
361
+ }
362
+ namespaceLister := fakeNamespaceLister {map [string ]* corev1.Namespace {"ns" : & namespace1 }}
363
+
364
+ mapper := runtime .NewEquivalentResourceRegistryWithIdentity (func (resource schema.GroupResource ) string {
365
+ if resource .Resource == "deployments" {
366
+ // co-locate deployments in all API groups
367
+ return "/deployments"
368
+ }
369
+ return ""
370
+ })
371
+ mapper .RegisterKindFor (schema.GroupVersionResource {"extensions" , "v1beta1" , "deployments" }, "" , schema.GroupVersionKind {"extensions" , "v1beta1" , "Deployment" })
372
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1" , "Deployment" })
373
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1beta1" , "Deployment" })
374
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1alpha1" , "Deployment" })
375
+
376
+ mapper .RegisterKindFor (schema.GroupVersionResource {"extensions" , "v1beta1" , "deployments" }, "scale" , schema.GroupVersionKind {"extensions" , "v1beta1" , "Scale" })
377
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "scale" , schema.GroupVersionKind {"autoscaling" , "v1" , "Scale" })
378
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "deployments" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta1" , "Scale" })
379
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha1" , "deployments" }, "scale" , schema.GroupVersionKind {"apps" , "v1alpha1" , "Scale" })
380
+
381
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1" , "StatefulSet" })
382
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1beta1" , "StatefulSet" })
383
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta2" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1beta2" , "StatefulSet" })
384
+
385
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1" , "Scale" })
386
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta1" , "Scale" })
387
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha2" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta2" , "Scale" })
388
+
389
+ nsSelector := make (map [string ]string )
390
+ for i := 0 ; i < 100 ; i ++ {
391
+ nsSelector [fmt .Sprintf ("key-%d" , i )] = fmt .Sprintf ("val-%d" , i )
392
+ }
393
+
394
+ wb := & v1.ValidatingWebhook {
395
+ MatchPolicy : & equivalentMatch ,
396
+ NamespaceSelector : & metav1.LabelSelector {MatchLabels : nsSelector },
397
+ ObjectSelector : & metav1.LabelSelector {},
398
+ Rules : []v1.RuleWithOperations {
399
+ {
400
+ Operations : []v1.OperationType {"*" },
401
+ Rule : v1.Rule {APIGroups : []string {"apps" }, APIVersions : []string {"v1beta1" }, Resources : []string {"deployments" , "deployments/scale" }, Scope : & allScopes },
402
+ },
403
+ {
404
+ Operations : []v1.OperationType {"*" },
405
+ Rule : v1.Rule {APIGroups : []string {"extensions" }, APIVersions : []string {"v1beta1" }, Resources : []string {"deployments" , "deployments/scale" }, Scope : & allScopes },
406
+ },
407
+ },
408
+ }
409
+
410
+ wbAccessor := webhook .NewValidatingWebhookAccessor ("webhook" , "webhook-cfg" , wb )
411
+ attrs := admission .NewAttributesRecord (nil , nil , schema.GroupVersionKind {"autoscaling" , "v1" , "Scale" }, "ns" , "name" , schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "scale" , admission .Create , & metav1.CreateOptions {}, false , nil )
412
+ interfaces := & admission.RuntimeObjectInterfaces {EquivalentResourceMapper : mapper }
413
+ a := & Webhook {namespaceMatcher : & namespace.Matcher {NamespaceLister : namespaceLister }, objectMatcher : & object.Matcher {}}
414
+
415
+ for i := 0 ; i < b .N ; i ++ {
416
+ a .ShouldCallHook (wbAccessor , attrs , interfaces )
417
+ }
418
+ }
419
+
420
+ func BenchmarkShouldCallHookWithComplexRule (b * testing.B ) {
421
+ allScopes := v1 .AllScopes
422
+ equivalentMatch := v1 .Equivalent
423
+
424
+ namespace1Labels := map [string ]string {"ns" : "ns1" }
425
+ namespace1 := corev1.Namespace {
426
+ ObjectMeta : metav1.ObjectMeta {
427
+ Name : "ns1" ,
428
+ Labels : namespace1Labels ,
429
+ },
430
+ }
431
+ namespaceLister := fakeNamespaceLister {map [string ]* corev1.Namespace {"ns" : & namespace1 }}
432
+
433
+ mapper := runtime .NewEquivalentResourceRegistryWithIdentity (func (resource schema.GroupResource ) string {
434
+ if resource .Resource == "deployments" {
435
+ // co-locate deployments in all API groups
436
+ return "/deployments"
437
+ }
438
+ return ""
439
+ })
440
+ mapper .RegisterKindFor (schema.GroupVersionResource {"extensions" , "v1beta1" , "deployments" }, "" , schema.GroupVersionKind {"extensions" , "v1beta1" , "Deployment" })
441
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1" , "Deployment" })
442
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1beta1" , "Deployment" })
443
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1alpha1" , "Deployment" })
444
+
445
+ mapper .RegisterKindFor (schema.GroupVersionResource {"extensions" , "v1beta1" , "deployments" }, "scale" , schema.GroupVersionKind {"extensions" , "v1beta1" , "Scale" })
446
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "scale" , schema.GroupVersionKind {"autoscaling" , "v1" , "Scale" })
447
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "deployments" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta1" , "Scale" })
448
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha1" , "deployments" }, "scale" , schema.GroupVersionKind {"apps" , "v1alpha1" , "Scale" })
449
+
450
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1" , "StatefulSet" })
451
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1beta1" , "StatefulSet" })
452
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta2" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1beta2" , "StatefulSet" })
453
+
454
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1" , "Scale" })
455
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta1" , "Scale" })
456
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha2" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta2" , "Scale" })
457
+
458
+ wb := & v1.ValidatingWebhook {
459
+ MatchPolicy : & equivalentMatch ,
460
+ NamespaceSelector : & metav1.LabelSelector {MatchLabels : map [string ]string {"a" : "b" }},
461
+ ObjectSelector : & metav1.LabelSelector {},
462
+ Rules : []v1.RuleWithOperations {},
463
+ }
464
+
465
+ for i := 0 ; i < 100 ; i ++ {
466
+ rule := v1.RuleWithOperations {
467
+ Operations : []v1.OperationType {"*" },
468
+ Rule : v1.Rule {
469
+ APIGroups : []string {fmt .Sprintf ("app-%d" , i )},
470
+ APIVersions : []string {fmt .Sprintf ("v%d" , i )},
471
+ Resources : []string {fmt .Sprintf ("resource%d" , i ), fmt .Sprintf ("resource%d/scale" , i )},
472
+ Scope : & allScopes ,
473
+ },
474
+ }
475
+ wb .Rules = append (wb .Rules , rule )
476
+ }
477
+
478
+ wbAccessor := webhook .NewValidatingWebhookAccessor ("webhook" , "webhook-cfg" , wb )
479
+ attrs := admission .NewAttributesRecord (nil , nil , schema.GroupVersionKind {"autoscaling" , "v1" , "Scale" }, "ns" , "name" , schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "scale" , admission .Create , & metav1.CreateOptions {}, false , nil )
480
+ interfaces := & admission.RuntimeObjectInterfaces {EquivalentResourceMapper : mapper }
481
+ a := & Webhook {namespaceMatcher : & namespace.Matcher {NamespaceLister : namespaceLister }, objectMatcher : & object.Matcher {}}
482
+
483
+ for i := 0 ; i < b .N ; i ++ {
484
+ a .ShouldCallHook (wbAccessor , attrs , interfaces )
485
+ }
486
+ }
487
+
488
+ func BenchmarkShouldCallHookWithComplexSelectorAndRule (b * testing.B ) {
489
+ allScopes := v1 .AllScopes
490
+ equivalentMatch := v1 .Equivalent
491
+
492
+ namespace1Labels := map [string ]string {"ns" : "ns1" }
493
+ namespace1 := corev1.Namespace {
494
+ ObjectMeta : metav1.ObjectMeta {
495
+ Name : "ns1" ,
496
+ Labels : namespace1Labels ,
497
+ },
498
+ }
499
+ namespaceLister := fakeNamespaceLister {map [string ]* corev1.Namespace {"ns" : & namespace1 }}
500
+
501
+ mapper := runtime .NewEquivalentResourceRegistryWithIdentity (func (resource schema.GroupResource ) string {
502
+ if resource .Resource == "deployments" {
503
+ // co-locate deployments in all API groups
504
+ return "/deployments"
505
+ }
506
+ return ""
507
+ })
508
+ mapper .RegisterKindFor (schema.GroupVersionResource {"extensions" , "v1beta1" , "deployments" }, "" , schema.GroupVersionKind {"extensions" , "v1beta1" , "Deployment" })
509
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1" , "Deployment" })
510
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1beta1" , "Deployment" })
511
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha1" , "deployments" }, "" , schema.GroupVersionKind {"apps" , "v1alpha1" , "Deployment" })
512
+
513
+ mapper .RegisterKindFor (schema.GroupVersionResource {"extensions" , "v1beta1" , "deployments" }, "scale" , schema.GroupVersionKind {"extensions" , "v1beta1" , "Scale" })
514
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "scale" , schema.GroupVersionKind {"autoscaling" , "v1" , "Scale" })
515
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "deployments" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta1" , "Scale" })
516
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha1" , "deployments" }, "scale" , schema.GroupVersionKind {"apps" , "v1alpha1" , "Scale" })
517
+
518
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1" , "StatefulSet" })
519
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1beta1" , "StatefulSet" })
520
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta2" , "statefulset" }, "" , schema.GroupVersionKind {"apps" , "v1beta2" , "StatefulSet" })
521
+
522
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1" , "Scale" })
523
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1beta1" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta1" , "Scale" })
524
+ mapper .RegisterKindFor (schema.GroupVersionResource {"apps" , "v1alpha2" , "statefulset" }, "scale" , schema.GroupVersionKind {"apps" , "v1beta2" , "Scale" })
525
+
526
+ nsSelector := make (map [string ]string )
527
+ for i := 0 ; i < 100 ; i ++ {
528
+ nsSelector [fmt .Sprintf ("key-%d" , i )] = fmt .Sprintf ("val-%d" , i )
529
+ }
530
+
531
+ wb := & v1.ValidatingWebhook {
532
+ MatchPolicy : & equivalentMatch ,
533
+ NamespaceSelector : & metav1.LabelSelector {MatchLabels : nsSelector },
534
+ ObjectSelector : & metav1.LabelSelector {},
535
+ Rules : []v1.RuleWithOperations {},
536
+ }
537
+
538
+ for i := 0 ; i < 100 ; i ++ {
539
+ rule := v1.RuleWithOperations {
540
+ Operations : []v1.OperationType {"*" },
541
+ Rule : v1.Rule {
542
+ APIGroups : []string {fmt .Sprintf ("app-%d" , i )},
543
+ APIVersions : []string {fmt .Sprintf ("v%d" , i )},
544
+ Resources : []string {fmt .Sprintf ("resource%d" , i ), fmt .Sprintf ("resource%d/scale" , i )},
545
+ Scope : & allScopes ,
546
+ },
547
+ }
548
+ wb .Rules = append (wb .Rules , rule )
549
+ }
550
+
551
+ wbAccessor := webhook .NewValidatingWebhookAccessor ("webhook" , "webhook-cfg" , wb )
552
+ attrs := admission .NewAttributesRecord (nil , nil , schema.GroupVersionKind {"autoscaling" , "v1" , "Scale" }, "ns" , "name" , schema.GroupVersionResource {"apps" , "v1" , "deployments" }, "scale" , admission .Create , & metav1.CreateOptions {}, false , nil )
553
+ interfaces := & admission.RuntimeObjectInterfaces {EquivalentResourceMapper : mapper }
554
+ a := & Webhook {namespaceMatcher : & namespace.Matcher {NamespaceLister : namespaceLister }, objectMatcher : & object.Matcher {}}
555
+
556
+ for i := 0 ; i < b .N ; i ++ {
557
+ a .ShouldCallHook (wbAccessor , attrs , interfaces )
558
+ }
559
+ }
0 commit comments