sigs.k8s.io/controller-runtime@v0.18.2/pkg/handler/eventhandler_test.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package handler_test 18 19 import ( 20 "context" 21 22 . "github.com/onsi/ginkgo/v2" 23 . "github.com/onsi/gomega" 24 appsv1 "k8s.io/api/apps/v1" 25 autoscalingv1 "k8s.io/api/autoscaling/v1" 26 corev1 "k8s.io/api/core/v1" 27 "k8s.io/apimachinery/pkg/api/meta" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/apimachinery/pkg/types" 30 "k8s.io/client-go/kubernetes/scheme" 31 "k8s.io/client-go/rest" 32 "k8s.io/client-go/util/workqueue" 33 "k8s.io/utils/ptr" 34 "sigs.k8s.io/controller-runtime/pkg/client" 35 "sigs.k8s.io/controller-runtime/pkg/client/apiutil" 36 "sigs.k8s.io/controller-runtime/pkg/controller/controllertest" 37 "sigs.k8s.io/controller-runtime/pkg/event" 38 "sigs.k8s.io/controller-runtime/pkg/handler" 39 "sigs.k8s.io/controller-runtime/pkg/reconcile" 40 ) 41 42 var _ = Describe("Eventhandler", func() { 43 var ctx = context.Background() 44 var q workqueue.RateLimitingInterface 45 var instance handler.EnqueueRequestForObject 46 var pod *corev1.Pod 47 var mapper meta.RESTMapper 48 BeforeEach(func() { 49 q = &controllertest.Queue{Interface: workqueue.New()} 50 pod = &corev1.Pod{ 51 ObjectMeta: metav1.ObjectMeta{Namespace: "biz", Name: "baz"}, 52 } 53 Expect(cfg).NotTo(BeNil()) 54 55 httpClient, err := rest.HTTPClientFor(cfg) 56 Expect(err).ShouldNot(HaveOccurred()) 57 mapper, err = apiutil.NewDynamicRESTMapper(cfg, httpClient) 58 Expect(err).ShouldNot(HaveOccurred()) 59 }) 60 61 Describe("EnqueueRequestForObject", func() { 62 It("should enqueue a Request with the Name / Namespace of the object in the CreateEvent.", func() { 63 evt := event.CreateEvent{ 64 Object: pod, 65 } 66 instance.Create(ctx, evt, q) 67 Expect(q.Len()).To(Equal(1)) 68 69 i, _ := q.Get() 70 Expect(i).NotTo(BeNil()) 71 req, ok := i.(reconcile.Request) 72 Expect(ok).To(BeTrue()) 73 Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz", Name: "baz"})) 74 }) 75 76 It("should enqueue a Request with the Name / Namespace of the object in the DeleteEvent.", func() { 77 evt := event.DeleteEvent{ 78 Object: pod, 79 } 80 instance.Delete(ctx, evt, q) 81 Expect(q.Len()).To(Equal(1)) 82 83 i, _ := q.Get() 84 Expect(i).NotTo(BeNil()) 85 req, ok := i.(reconcile.Request) 86 Expect(ok).To(BeTrue()) 87 Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz", Name: "baz"})) 88 }) 89 90 It("should enqueue a Request with the Name / Namespace of one object in the UpdateEvent.", 91 func() { 92 newPod := pod.DeepCopy() 93 newPod.Name = "baz2" 94 newPod.Namespace = "biz2" 95 96 evt := event.UpdateEvent{ 97 ObjectOld: pod, 98 ObjectNew: newPod, 99 } 100 instance.Update(ctx, evt, q) 101 Expect(q.Len()).To(Equal(1)) 102 103 i, _ := q.Get() 104 Expect(i).NotTo(BeNil()) 105 req, ok := i.(reconcile.Request) 106 Expect(ok).To(BeTrue()) 107 Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz2", Name: "baz2"})) 108 }) 109 110 It("should enqueue a Request with the Name / Namespace of the object in the GenericEvent.", func() { 111 evt := event.GenericEvent{ 112 Object: pod, 113 } 114 instance.Generic(ctx, evt, q) 115 Expect(q.Len()).To(Equal(1)) 116 i, _ := q.Get() 117 Expect(i).NotTo(BeNil()) 118 req, ok := i.(reconcile.Request) 119 Expect(ok).To(BeTrue()) 120 Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz", Name: "baz"})) 121 }) 122 123 Context("for a runtime.Object without Object", func() { 124 It("should do nothing if the Object is missing for a CreateEvent.", func() { 125 evt := event.CreateEvent{ 126 Object: nil, 127 } 128 instance.Create(ctx, evt, q) 129 Expect(q.Len()).To(Equal(0)) 130 }) 131 132 It("should do nothing if the Object is missing for a UpdateEvent.", func() { 133 newPod := pod.DeepCopy() 134 newPod.Name = "baz2" 135 newPod.Namespace = "biz2" 136 137 evt := event.UpdateEvent{ 138 ObjectNew: newPod, 139 ObjectOld: nil, 140 } 141 instance.Update(ctx, evt, q) 142 Expect(q.Len()).To(Equal(1)) 143 i, _ := q.Get() 144 Expect(i).NotTo(BeNil()) 145 req, ok := i.(reconcile.Request) 146 Expect(ok).To(BeTrue()) 147 Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz2", Name: "baz2"})) 148 149 evt.ObjectNew = nil 150 evt.ObjectOld = pod 151 instance.Update(ctx, evt, q) 152 Expect(q.Len()).To(Equal(1)) 153 i, _ = q.Get() 154 Expect(i).NotTo(BeNil()) 155 req, ok = i.(reconcile.Request) 156 Expect(ok).To(BeTrue()) 157 Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz", Name: "baz"})) 158 }) 159 160 It("should do nothing if the Object is missing for a DeleteEvent.", func() { 161 evt := event.DeleteEvent{ 162 Object: nil, 163 } 164 instance.Delete(ctx, evt, q) 165 Expect(q.Len()).To(Equal(0)) 166 }) 167 168 It("should do nothing if the Object is missing for a GenericEvent.", func() { 169 evt := event.GenericEvent{ 170 Object: nil, 171 } 172 instance.Generic(ctx, evt, q) 173 Expect(q.Len()).To(Equal(0)) 174 }) 175 }) 176 }) 177 178 Describe("EnqueueRequestsFromMapFunc", func() { 179 It("should enqueue a Request with the function applied to the CreateEvent.", func() { 180 req := []reconcile.Request{} 181 instance := handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, a client.Object) []reconcile.Request { 182 defer GinkgoRecover() 183 Expect(a).To(Equal(pod)) 184 req = []reconcile.Request{ 185 { 186 NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}, 187 }, 188 { 189 NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}, 190 }, 191 } 192 return req 193 }) 194 195 evt := event.CreateEvent{ 196 Object: pod, 197 } 198 instance.Create(ctx, evt, q) 199 Expect(q.Len()).To(Equal(2)) 200 201 i1, _ := q.Get() 202 i2, _ := q.Get() 203 Expect([]interface{}{i1, i2}).To(ConsistOf( 204 reconcile.Request{ 205 NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}}, 206 reconcile.Request{ 207 NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}}, 208 )) 209 }) 210 211 It("should enqueue a Request with the function applied to the DeleteEvent.", func() { 212 req := []reconcile.Request{} 213 instance := handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, a client.Object) []reconcile.Request { 214 defer GinkgoRecover() 215 Expect(a).To(Equal(pod)) 216 req = []reconcile.Request{ 217 { 218 NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}, 219 }, 220 { 221 NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}, 222 }, 223 } 224 return req 225 }) 226 227 evt := event.DeleteEvent{ 228 Object: pod, 229 } 230 instance.Delete(ctx, evt, q) 231 Expect(q.Len()).To(Equal(2)) 232 233 i1, _ := q.Get() 234 i2, _ := q.Get() 235 Expect([]interface{}{i1, i2}).To(ConsistOf( 236 reconcile.Request{ 237 NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}}, 238 reconcile.Request{ 239 NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}}, 240 )) 241 }) 242 243 It("should enqueue a Request with the function applied to both objects in the UpdateEvent.", 244 func() { 245 newPod := pod.DeepCopy() 246 247 req := []reconcile.Request{} 248 249 instance := handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, a client.Object) []reconcile.Request { 250 defer GinkgoRecover() 251 req = []reconcile.Request{ 252 { 253 NamespacedName: types.NamespacedName{Namespace: "foo", Name: a.GetName() + "-bar"}, 254 }, 255 { 256 NamespacedName: types.NamespacedName{Namespace: "biz", Name: a.GetName() + "-baz"}, 257 }, 258 } 259 return req 260 }) 261 262 evt := event.UpdateEvent{ 263 ObjectOld: pod, 264 ObjectNew: newPod, 265 } 266 instance.Update(ctx, evt, q) 267 Expect(q.Len()).To(Equal(2)) 268 269 i, _ := q.Get() 270 Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz-bar"}})) 271 272 i, _ = q.Get() 273 Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz-baz"}})) 274 }) 275 276 It("should enqueue a Request with the function applied to the GenericEvent.", func() { 277 req := []reconcile.Request{} 278 instance := handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, a client.Object) []reconcile.Request { 279 defer GinkgoRecover() 280 Expect(a).To(Equal(pod)) 281 req = []reconcile.Request{ 282 { 283 NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}, 284 }, 285 { 286 NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}, 287 }, 288 } 289 return req 290 }) 291 292 evt := event.GenericEvent{ 293 Object: pod, 294 } 295 instance.Generic(ctx, evt, q) 296 Expect(q.Len()).To(Equal(2)) 297 298 i1, _ := q.Get() 299 i2, _ := q.Get() 300 Expect([]interface{}{i1, i2}).To(ConsistOf( 301 reconcile.Request{ 302 NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}}, 303 reconcile.Request{ 304 NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}}, 305 )) 306 }) 307 }) 308 309 Describe("EnqueueRequestForOwner", func() { 310 It("should enqueue a Request with the Owner of the object in the CreateEvent.", func() { 311 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 312 313 pod.OwnerReferences = []metav1.OwnerReference{ 314 { 315 Name: "foo-parent", 316 Kind: "ReplicaSet", 317 APIVersion: "apps/v1", 318 }, 319 } 320 evt := event.CreateEvent{ 321 Object: pod, 322 } 323 instance.Create(ctx, evt, q) 324 Expect(q.Len()).To(Equal(1)) 325 326 i, _ := q.Get() 327 Expect(i).To(Equal(reconcile.Request{ 328 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo-parent"}})) 329 }) 330 331 It("should enqueue a Request with the Owner of the object in the DeleteEvent.", func() { 332 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 333 334 pod.OwnerReferences = []metav1.OwnerReference{ 335 { 336 Name: "foo-parent", 337 Kind: "ReplicaSet", 338 APIVersion: "apps/v1", 339 }, 340 } 341 evt := event.DeleteEvent{ 342 Object: pod, 343 } 344 instance.Delete(ctx, evt, q) 345 Expect(q.Len()).To(Equal(1)) 346 347 i, _ := q.Get() 348 Expect(i).To(Equal(reconcile.Request{ 349 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo-parent"}})) 350 }) 351 352 It("should enqueue a Request with the Owners of both objects in the UpdateEvent.", func() { 353 newPod := pod.DeepCopy() 354 newPod.Name = pod.Name + "2" 355 newPod.Namespace = pod.Namespace + "2" 356 357 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 358 359 pod.OwnerReferences = []metav1.OwnerReference{ 360 { 361 Name: "foo1-parent", 362 Kind: "ReplicaSet", 363 APIVersion: "apps/v1", 364 }, 365 } 366 newPod.OwnerReferences = []metav1.OwnerReference{ 367 { 368 Name: "foo2-parent", 369 Kind: "ReplicaSet", 370 APIVersion: "apps/v1", 371 }, 372 } 373 evt := event.UpdateEvent{ 374 ObjectOld: pod, 375 ObjectNew: newPod, 376 } 377 instance.Update(ctx, evt, q) 378 Expect(q.Len()).To(Equal(2)) 379 380 i1, _ := q.Get() 381 i2, _ := q.Get() 382 Expect([]interface{}{i1, i2}).To(ConsistOf( 383 reconcile.Request{ 384 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo1-parent"}}, 385 reconcile.Request{ 386 NamespacedName: types.NamespacedName{Namespace: newPod.GetNamespace(), Name: "foo2-parent"}}, 387 )) 388 }) 389 390 It("should enqueue a Request with the one duplicate Owner of both objects in the UpdateEvent.", func() { 391 newPod := pod.DeepCopy() 392 newPod.Name = pod.Name + "2" 393 394 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 395 396 pod.OwnerReferences = []metav1.OwnerReference{ 397 { 398 Name: "foo-parent", 399 Kind: "ReplicaSet", 400 APIVersion: "apps/v1", 401 }, 402 } 403 newPod.OwnerReferences = []metav1.OwnerReference{ 404 { 405 Name: "foo-parent", 406 Kind: "ReplicaSet", 407 APIVersion: "apps/v1", 408 }, 409 } 410 evt := event.UpdateEvent{ 411 ObjectOld: pod, 412 ObjectNew: newPod, 413 } 414 instance.Update(ctx, evt, q) 415 Expect(q.Len()).To(Equal(1)) 416 417 i, _ := q.Get() 418 Expect(i).To(Equal(reconcile.Request{ 419 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo-parent"}})) 420 }) 421 422 It("should enqueue a Request with the Owner of the object in the GenericEvent.", func() { 423 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 424 pod.OwnerReferences = []metav1.OwnerReference{ 425 { 426 Name: "foo-parent", 427 Kind: "ReplicaSet", 428 APIVersion: "apps/v1", 429 }, 430 } 431 evt := event.GenericEvent{ 432 Object: pod, 433 } 434 instance.Generic(ctx, evt, q) 435 Expect(q.Len()).To(Equal(1)) 436 437 i, _ := q.Get() 438 Expect(i).To(Equal(reconcile.Request{ 439 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo-parent"}})) 440 }) 441 442 It("should not enqueue a Request if there are no owners matching Group and Kind.", func() { 443 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}, handler.OnlyControllerOwner()) 444 pod.OwnerReferences = []metav1.OwnerReference{ 445 { // Wrong group 446 Name: "foo1-parent", 447 Kind: "ReplicaSet", 448 APIVersion: "extensions/v1", 449 }, 450 { // Wrong kind 451 Name: "foo2-parent", 452 Kind: "Deployment", 453 APIVersion: "apps/v1", 454 }, 455 } 456 evt := event.CreateEvent{ 457 Object: pod, 458 } 459 instance.Create(ctx, evt, q) 460 Expect(q.Len()).To(Equal(0)) 461 }) 462 463 It("should enqueue a Request if there are owners matching Group "+ 464 "and Kind with a different version.", func() { 465 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &autoscalingv1.HorizontalPodAutoscaler{}) 466 pod.OwnerReferences = []metav1.OwnerReference{ 467 { 468 Name: "foo-parent", 469 Kind: "HorizontalPodAutoscaler", 470 APIVersion: "autoscaling/v2", 471 }, 472 } 473 evt := event.CreateEvent{ 474 Object: pod, 475 } 476 instance.Create(ctx, evt, q) 477 Expect(q.Len()).To(Equal(1)) 478 479 i, _ := q.Get() 480 Expect(i).To(Equal(reconcile.Request{ 481 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo-parent"}})) 482 }) 483 484 It("should enqueue a Request for a owner that is cluster scoped", func() { 485 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &corev1.Node{}) 486 pod.OwnerReferences = []metav1.OwnerReference{ 487 { 488 Name: "node-1", 489 Kind: "Node", 490 APIVersion: "v1", 491 }, 492 } 493 evt := event.CreateEvent{ 494 Object: pod, 495 } 496 instance.Create(ctx, evt, q) 497 Expect(q.Len()).To(Equal(1)) 498 499 i, _ := q.Get() 500 Expect(i).To(Equal(reconcile.Request{ 501 NamespacedName: types.NamespacedName{Namespace: "", Name: "node-1"}})) 502 503 }) 504 505 It("should not enqueue a Request if there are no owners.", func() { 506 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 507 evt := event.CreateEvent{ 508 Object: pod, 509 } 510 instance.Create(ctx, evt, q) 511 Expect(q.Len()).To(Equal(0)) 512 }) 513 514 Context("with the Controller field set to true", func() { 515 It("should enqueue reconcile.Requests for only the first the Controller if there are "+ 516 "multiple Controller owners.", func() { 517 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}, handler.OnlyControllerOwner()) 518 pod.OwnerReferences = []metav1.OwnerReference{ 519 { 520 Name: "foo1-parent", 521 Kind: "ReplicaSet", 522 APIVersion: "apps/v1", 523 }, 524 { 525 Name: "foo2-parent", 526 Kind: "ReplicaSet", 527 APIVersion: "apps/v1", 528 Controller: ptr.To(true), 529 }, 530 { 531 Name: "foo3-parent", 532 Kind: "ReplicaSet", 533 APIVersion: "apps/v1", 534 }, 535 { 536 Name: "foo4-parent", 537 Kind: "ReplicaSet", 538 APIVersion: "apps/v1", 539 Controller: ptr.To(true), 540 }, 541 { 542 Name: "foo5-parent", 543 Kind: "ReplicaSet", 544 APIVersion: "apps/v1", 545 }, 546 } 547 evt := event.CreateEvent{ 548 Object: pod, 549 } 550 instance.Create(ctx, evt, q) 551 Expect(q.Len()).To(Equal(1)) 552 i, _ := q.Get() 553 Expect(i).To(Equal(reconcile.Request{ 554 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo2-parent"}})) 555 }) 556 557 It("should not enqueue reconcile.Requests if there are no Controller owners.", func() { 558 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}, handler.OnlyControllerOwner()) 559 pod.OwnerReferences = []metav1.OwnerReference{ 560 { 561 Name: "foo1-parent", 562 Kind: "ReplicaSet", 563 APIVersion: "apps/v1", 564 }, 565 { 566 Name: "foo2-parent", 567 Kind: "ReplicaSet", 568 APIVersion: "apps/v1", 569 }, 570 { 571 Name: "foo3-parent", 572 Kind: "ReplicaSet", 573 APIVersion: "apps/v1", 574 }, 575 } 576 evt := event.CreateEvent{ 577 Object: pod, 578 } 579 instance.Create(ctx, evt, q) 580 Expect(q.Len()).To(Equal(0)) 581 }) 582 583 It("should not enqueue reconcile.Requests if there are no owners.", func() { 584 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}, handler.OnlyControllerOwner()) 585 evt := event.CreateEvent{ 586 Object: pod, 587 } 588 instance.Create(ctx, evt, q) 589 Expect(q.Len()).To(Equal(0)) 590 }) 591 }) 592 593 Context("with the Controller field set to false", func() { 594 It("should enqueue a reconcile.Requests for all owners.", func() { 595 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 596 pod.OwnerReferences = []metav1.OwnerReference{ 597 { 598 Name: "foo1-parent", 599 Kind: "ReplicaSet", 600 APIVersion: "apps/v1", 601 }, 602 { 603 Name: "foo2-parent", 604 Kind: "ReplicaSet", 605 APIVersion: "apps/v1", 606 }, 607 { 608 Name: "foo3-parent", 609 Kind: "ReplicaSet", 610 APIVersion: "apps/v1", 611 }, 612 } 613 evt := event.CreateEvent{ 614 Object: pod, 615 } 616 instance.Create(ctx, evt, q) 617 Expect(q.Len()).To(Equal(3)) 618 619 i1, _ := q.Get() 620 i2, _ := q.Get() 621 i3, _ := q.Get() 622 Expect([]interface{}{i1, i2, i3}).To(ConsistOf( 623 reconcile.Request{ 624 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo1-parent"}}, 625 reconcile.Request{ 626 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo2-parent"}}, 627 reconcile.Request{ 628 NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo3-parent"}}, 629 )) 630 }) 631 }) 632 633 Context("with a nil object", func() { 634 It("should do nothing.", func() { 635 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 636 pod.OwnerReferences = []metav1.OwnerReference{ 637 { 638 Name: "foo1-parent", 639 Kind: "ReplicaSet", 640 APIVersion: "apps/v1", 641 }, 642 } 643 evt := event.CreateEvent{ 644 Object: nil, 645 } 646 instance.Create(ctx, evt, q) 647 Expect(q.Len()).To(Equal(0)) 648 }) 649 }) 650 651 Context("with a nil OwnerType", func() { 652 It("should panic", func() { 653 Expect(func() { 654 handler.EnqueueRequestForOwner(nil, nil, nil) 655 }).To(Panic()) 656 }) 657 }) 658 659 Context("with an invalid APIVersion in the OwnerReference", func() { 660 It("should do nothing.", func() { 661 instance := handler.EnqueueRequestForOwner(scheme.Scheme, mapper, &appsv1.ReplicaSet{}) 662 pod.OwnerReferences = []metav1.OwnerReference{ 663 { 664 Name: "foo1-parent", 665 Kind: "ReplicaSet", 666 APIVersion: "apps/v1/fail", 667 }, 668 } 669 evt := event.CreateEvent{ 670 Object: pod, 671 } 672 instance.Create(ctx, evt, q) 673 Expect(q.Len()).To(Equal(0)) 674 }) 675 }) 676 }) 677 678 Describe("Funcs", func() { 679 failingFuncs := handler.Funcs{ 680 CreateFunc: func(context.Context, event.CreateEvent, workqueue.RateLimitingInterface) { 681 defer GinkgoRecover() 682 Fail("Did not expect CreateEvent to be called.") 683 }, 684 DeleteFunc: func(context.Context, event.DeleteEvent, workqueue.RateLimitingInterface) { 685 defer GinkgoRecover() 686 Fail("Did not expect DeleteEvent to be called.") 687 }, 688 UpdateFunc: func(context.Context, event.UpdateEvent, workqueue.RateLimitingInterface) { 689 defer GinkgoRecover() 690 Fail("Did not expect UpdateEvent to be called.") 691 }, 692 GenericFunc: func(context.Context, event.GenericEvent, workqueue.RateLimitingInterface) { 693 defer GinkgoRecover() 694 Fail("Did not expect GenericEvent to be called.") 695 }, 696 } 697 698 It("should call CreateFunc for a CreateEvent if provided.", func() { 699 instance := failingFuncs 700 evt := event.CreateEvent{ 701 Object: pod, 702 } 703 instance.CreateFunc = func(ctx context.Context, evt2 event.CreateEvent, q2 workqueue.RateLimitingInterface) { 704 defer GinkgoRecover() 705 Expect(q2).To(Equal(q)) 706 Expect(evt2).To(Equal(evt)) 707 } 708 instance.Create(ctx, evt, q) 709 }) 710 711 It("should NOT call CreateFunc for a CreateEvent if NOT provided.", func() { 712 instance := failingFuncs 713 instance.CreateFunc = nil 714 evt := event.CreateEvent{ 715 Object: pod, 716 } 717 instance.Create(ctx, evt, q) 718 }) 719 720 It("should call UpdateFunc for an UpdateEvent if provided.", func() { 721 newPod := pod.DeepCopy() 722 newPod.Name = pod.Name + "2" 723 newPod.Namespace = pod.Namespace + "2" 724 evt := event.UpdateEvent{ 725 ObjectOld: pod, 726 ObjectNew: newPod, 727 } 728 729 instance := failingFuncs 730 instance.UpdateFunc = func(ctx context.Context, evt2 event.UpdateEvent, q2 workqueue.RateLimitingInterface) { 731 defer GinkgoRecover() 732 Expect(q2).To(Equal(q)) 733 Expect(evt2).To(Equal(evt)) 734 } 735 736 instance.Update(ctx, evt, q) 737 }) 738 739 It("should NOT call UpdateFunc for an UpdateEvent if NOT provided.", func() { 740 newPod := pod.DeepCopy() 741 newPod.Name = pod.Name + "2" 742 newPod.Namespace = pod.Namespace + "2" 743 evt := event.UpdateEvent{ 744 ObjectOld: pod, 745 ObjectNew: newPod, 746 } 747 instance.Update(ctx, evt, q) 748 }) 749 750 It("should call DeleteFunc for a DeleteEvent if provided.", func() { 751 instance := failingFuncs 752 evt := event.DeleteEvent{ 753 Object: pod, 754 } 755 instance.DeleteFunc = func(ctx context.Context, evt2 event.DeleteEvent, q2 workqueue.RateLimitingInterface) { 756 defer GinkgoRecover() 757 Expect(q2).To(Equal(q)) 758 Expect(evt2).To(Equal(evt)) 759 } 760 instance.Delete(ctx, evt, q) 761 }) 762 763 It("should NOT call DeleteFunc for a DeleteEvent if NOT provided.", func() { 764 instance := failingFuncs 765 instance.DeleteFunc = nil 766 evt := event.DeleteEvent{ 767 Object: pod, 768 } 769 instance.Delete(ctx, evt, q) 770 }) 771 772 It("should call GenericFunc for a GenericEvent if provided.", func() { 773 instance := failingFuncs 774 evt := event.GenericEvent{ 775 Object: pod, 776 } 777 instance.GenericFunc = func(ctx context.Context, evt2 event.GenericEvent, q2 workqueue.RateLimitingInterface) { 778 defer GinkgoRecover() 779 Expect(q2).To(Equal(q)) 780 Expect(evt2).To(Equal(evt)) 781 } 782 instance.Generic(ctx, evt, q) 783 }) 784 785 It("should NOT call GenericFunc for a GenericEvent if NOT provided.", func() { 786 instance := failingFuncs 787 instance.GenericFunc = nil 788 evt := event.GenericEvent{ 789 Object: pod, 790 } 791 instance.Generic(ctx, evt, q) 792 }) 793 }) 794 })