github.com/cilium/cilium@v1.16.2/operator/pkg/gateway-api/controller_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package gateway_api 5 6 import ( 7 "context" 8 "errors" 9 "fmt" 10 "testing" 11 "time" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 corev1 "k8s.io/api/core/v1" 16 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 17 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 18 "k8s.io/apimachinery/pkg/runtime" 19 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 20 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 21 ctrl "sigs.k8s.io/controller-runtime" 22 "sigs.k8s.io/controller-runtime/pkg/client" 23 "sigs.k8s.io/controller-runtime/pkg/client/fake" 24 "sigs.k8s.io/controller-runtime/pkg/event" 25 "sigs.k8s.io/controller-runtime/pkg/predicate" 26 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" 27 gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" 28 29 controllerruntime "github.com/cilium/cilium/operator/pkg/controller-runtime" 30 "github.com/cilium/cilium/operator/pkg/model" 31 ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 32 ) 33 34 func testScheme() *runtime.Scheme { 35 scheme := runtime.NewScheme() 36 37 utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 38 utilruntime.Must(ciliumv2.AddToScheme(scheme)) 39 utilruntime.Must(apiextensionsv1.AddToScheme(scheme)) 40 41 registerGatewayAPITypesToScheme(scheme) 42 43 return scheme 44 } 45 46 var controllerTestFixture = []client.Object{ 47 // Cilium Gateway Class 48 &gatewayv1.GatewayClass{ 49 ObjectMeta: metav1.ObjectMeta{ 50 Name: "cilium", 51 }, 52 Spec: gatewayv1.GatewayClassSpec{ 53 ControllerName: "io.cilium/gateway-controller", 54 }, 55 }, 56 57 // Secret used in Gateway 58 &corev1.Secret{ 59 ObjectMeta: metav1.ObjectMeta{ 60 Name: "tls-secret", 61 Namespace: "default", 62 }, 63 StringData: map[string]string{ 64 "tls.crt": "cert", 65 "tls.key": "key", 66 }, 67 Type: corev1.SecretTypeTLS, 68 }, 69 70 // Gateway with valid TLS secret 71 &gatewayv1.Gateway{ 72 ObjectMeta: metav1.ObjectMeta{ 73 Name: "valid-gateway", 74 Namespace: "default", 75 }, 76 Spec: gatewayv1.GatewaySpec{ 77 GatewayClassName: "cilium", 78 Listeners: []gatewayv1.Listener{ 79 { 80 Name: "https", 81 Hostname: model.AddressOf[gatewayv1.Hostname]("example.com"), 82 Port: 443, 83 TLS: &gatewayv1.GatewayTLSConfig{ 84 CertificateRefs: []gatewayv1.SecretObjectReference{ 85 { 86 Name: "tls-secret", 87 }, 88 }, 89 }, 90 }, 91 }, 92 }, 93 }, 94 95 &gatewayv1.Gateway{ 96 ObjectMeta: metav1.ObjectMeta{ 97 Name: "valid-gateway-2", 98 Namespace: "default", 99 }, 100 Spec: gatewayv1.GatewaySpec{ 101 GatewayClassName: "cilium", 102 Listeners: []gatewayv1.Listener{ 103 { 104 Name: "https", 105 Hostname: model.AddressOf[gatewayv1.Hostname]("example2.com"), 106 Port: 443, 107 TLS: &gatewayv1.GatewayTLSConfig{ 108 CertificateRefs: []gatewayv1.SecretObjectReference{}, 109 }, 110 }, 111 }, 112 }, 113 }, 114 115 // Gateway with no TLS listener 116 &gatewayv1.Gateway{ 117 ObjectMeta: metav1.ObjectMeta{ 118 Name: "gateway-with-no-tls", 119 Namespace: "default", 120 }, 121 Spec: gatewayv1.GatewaySpec{ 122 GatewayClassName: "cilium", 123 Listeners: []gatewayv1.Listener{ 124 { 125 Name: "https", 126 Port: 80, 127 }, 128 }, 129 }, 130 }, 131 132 // Gateway for TLSRoute 133 &gatewayv1.Gateway{ 134 ObjectMeta: metav1.ObjectMeta{ 135 Name: "gateway-tlsroute", 136 Namespace: "default", 137 }, 138 Spec: gatewayv1.GatewaySpec{ 139 GatewayClassName: "cilium", 140 Listeners: []gatewayv1.Listener{ 141 { 142 Name: "tls", 143 Protocol: gatewayv1.TLSProtocolType, 144 Port: 443, 145 }, 146 }, 147 }, 148 }, 149 150 // Gateway with allowed route in same namespace only 151 &gatewayv1.Gateway{ 152 ObjectMeta: metav1.ObjectMeta{ 153 Name: "gateway-from-same-namespace", 154 Namespace: "default", 155 }, 156 Spec: gatewayv1.GatewaySpec{ 157 GatewayClassName: "cilium", 158 Listeners: []gatewayv1.Listener{ 159 { 160 Name: "https", 161 Port: 80, 162 AllowedRoutes: &gatewayv1.AllowedRoutes{ 163 Namespaces: &gatewayv1.RouteNamespaces{ 164 From: model.AddressOf(gatewayv1.NamespacesFromSame), 165 }, 166 }, 167 }, 168 }, 169 }, 170 }, 171 172 // Gateway with allowed routes from ALL namespace 173 &gatewayv1.Gateway{ 174 ObjectMeta: metav1.ObjectMeta{ 175 Name: "gateway-from-all-namespaces", 176 Namespace: "default", 177 }, 178 Spec: gatewayv1.GatewaySpec{ 179 GatewayClassName: "cilium", 180 Listeners: []gatewayv1.Listener{ 181 { 182 Name: "https", 183 Port: 80, 184 AllowedRoutes: &gatewayv1.AllowedRoutes{ 185 Namespaces: &gatewayv1.RouteNamespaces{ 186 From: model.AddressOf(gatewayv1.NamespacesFromAll), 187 }, 188 }, 189 }, 190 }, 191 }, 192 }, 193 194 // Gateway with allowed routes with selector 195 &gatewayv1.Gateway{ 196 ObjectMeta: metav1.ObjectMeta{ 197 Name: "gateway-with-namespaces-selector", 198 Namespace: "default", 199 }, 200 Spec: gatewayv1.GatewaySpec{ 201 GatewayClassName: "cilium", 202 Listeners: []gatewayv1.Listener{ 203 { 204 Name: "https", 205 Port: 80, 206 AllowedRoutes: &gatewayv1.AllowedRoutes{ 207 Namespaces: &gatewayv1.RouteNamespaces{ 208 From: model.AddressOf(gatewayv1.NamespacesFromSelector), 209 Selector: &metav1.LabelSelector{ 210 MatchLabels: map[string]string{ 211 "gateway": "allowed", 212 }, 213 }, 214 }, 215 }, 216 }, 217 }, 218 }, 219 }, 220 } 221 222 var namespaceFixtures = []client.Object{ 223 &corev1.Namespace{ 224 ObjectMeta: metav1.ObjectMeta{ 225 Name: "default", 226 }, 227 }, 228 &corev1.Namespace{ 229 ObjectMeta: metav1.ObjectMeta{ 230 Name: "another-namespace", 231 }, 232 }, 233 &corev1.Namespace{ 234 ObjectMeta: metav1.ObjectMeta{ 235 Name: "namespace-with-allowed-gateway-selector", 236 Labels: map[string]string{ 237 "gateway": "allowed", 238 }, 239 }, 240 }, 241 &corev1.Namespace{ 242 ObjectMeta: metav1.ObjectMeta{ 243 Name: "namespace-with-disallowed-gateway-selector", 244 Labels: map[string]string{ 245 "gateway": "disallowed", 246 }, 247 }, 248 }, 249 } 250 251 func Test_hasMatchingController(t *testing.T) { 252 c := fake.NewClientBuilder().WithScheme(testScheme()).WithObjects(controllerTestFixture...).Build() 253 fn := hasMatchingController(context.Background(), c, "io.cilium/gateway-controller") 254 255 t.Run("invalid object", func(t *testing.T) { 256 res := fn(&corev1.Pod{}) 257 require.False(t, res) 258 }) 259 260 t.Run("gateway is matched by controller", func(t *testing.T) { 261 res := fn(&gatewayv1.Gateway{ 262 Spec: gatewayv1.GatewaySpec{ 263 GatewayClassName: "cilium", 264 }, 265 }) 266 require.True(t, res) 267 }) 268 269 t.Run("gateway is linked to non-existent class", func(t *testing.T) { 270 res := fn(&gatewayv1.Gateway{ 271 Spec: gatewayv1.GatewaySpec{ 272 GatewayClassName: "non-existent", 273 }, 274 }) 275 require.False(t, res) 276 }) 277 } 278 279 func Test_getGatewaysForSecret(t *testing.T) { 280 c := fake.NewClientBuilder().WithScheme(testScheme()).WithObjects(controllerTestFixture...).Build() 281 282 t.Run("secret is used in gateway", func(t *testing.T) { 283 gwList := getGatewaysForSecret(context.Background(), c, &corev1.Secret{ 284 ObjectMeta: metav1.ObjectMeta{ 285 Name: "tls-secret", 286 Namespace: "default", 287 }, 288 }) 289 290 require.Len(t, gwList, 1) 291 require.Equal(t, "valid-gateway", gwList[0].Name) 292 }) 293 294 t.Run("secret is not used in gateway", func(t *testing.T) { 295 gwList := getGatewaysForSecret(context.Background(), c, &corev1.Secret{ 296 ObjectMeta: metav1.ObjectMeta{ 297 Name: "tls-secret-not-used", 298 Namespace: "default", 299 }, 300 }) 301 302 require.Len(t, gwList, 0) 303 }) 304 } 305 306 func Test_getGatewaysForNamespace(t *testing.T) { 307 c := fake.NewClientBuilder(). 308 WithScheme(testScheme()). 309 WithObjects(namespaceFixtures...). 310 WithObjects(controllerTestFixture...). 311 Build() 312 313 type args struct { 314 namespace string 315 } 316 317 tests := []struct { 318 name string 319 args args 320 want []string 321 }{ 322 { 323 name: "with default namespace", 324 args: args{namespace: "default"}, 325 want: []string{"gateway-from-all-namespaces", "gateway-from-same-namespace"}, 326 }, 327 { 328 name: "with another namespace", 329 args: args{namespace: "another-namespace"}, 330 want: []string{"gateway-from-all-namespaces"}, 331 }, 332 { 333 name: "with namespace-with-allowed-gateway-selector", 334 args: args{namespace: "namespace-with-allowed-gateway-selector"}, 335 want: []string{"gateway-from-all-namespaces", "gateway-with-namespaces-selector"}, 336 }, 337 { 338 name: "with namespace-with-disallowed-gateway-selector", 339 args: args{namespace: "namespace-with-disallowed-gateway-selector"}, 340 want: []string{"gateway-from-all-namespaces"}, 341 }, 342 } 343 for _, tt := range tests { 344 t.Run(tt.name, func(t *testing.T) { 345 gwList := getGatewaysForNamespace(context.Background(), c, &corev1.Namespace{ 346 ObjectMeta: metav1.ObjectMeta{ 347 Name: tt.args.namespace, 348 }, 349 }) 350 names := make([]string, 0, len(gwList)) 351 for _, gw := range gwList { 352 names = append(names, gw.Name) 353 } 354 require.ElementsMatch(t, tt.want, names) 355 }) 356 } 357 } 358 359 func Test_success(t *testing.T) { 360 tests := []struct { 361 name string 362 want ctrl.Result 363 wantErr assert.ErrorAssertionFunc 364 }{ 365 { 366 name: "success", 367 want: ctrl.Result{}, 368 wantErr: assert.NoError, 369 }, 370 } 371 for _, tt := range tests { 372 t.Run(tt.name, func(t *testing.T) { 373 got, err := controllerruntime.Success() 374 if !tt.wantErr(t, err, "success()") { 375 return 376 } 377 assert.Equalf(t, tt.want, got, "success()") 378 }) 379 } 380 } 381 382 func Test_fail(t *testing.T) { 383 type args struct { 384 e error 385 } 386 tests := []struct { 387 name string 388 args args 389 want ctrl.Result 390 wantErr assert.ErrorAssertionFunc 391 }{ 392 { 393 name: "fail", 394 args: args{ 395 e: errors.New("fail"), 396 }, 397 want: ctrl.Result{}, 398 wantErr: assert.Error, 399 }, 400 } 401 for _, tt := range tests { 402 t.Run(tt.name, func(t *testing.T) { 403 got, err := controllerruntime.Fail(tt.args.e) 404 if !tt.wantErr(t, err, fmt.Sprintf("fail(%v)", tt.args.e)) { 405 return 406 } 407 assert.Equalf(t, tt.want, got, "fail(%v)", tt.args.e) 408 }) 409 } 410 } 411 412 func Test_onlyStatusChanged(t *testing.T) { 413 failingFuncs := predicate.Funcs{ 414 CreateFunc: func(event.CreateEvent) bool { 415 t.Fail() 416 return false 417 }, 418 DeleteFunc: func(event.DeleteEvent) bool { 419 t.Fail() 420 return false 421 }, 422 UpdateFunc: func(event.UpdateEvent) bool { 423 t.Fail() 424 return false 425 }, 426 GenericFunc: func(event.GenericEvent) bool { 427 t.Fail() 428 return false 429 }, 430 } 431 f := failingFuncs 432 f.UpdateFunc = onlyStatusChanged().Update 433 434 type args struct { 435 evt event.UpdateEvent 436 } 437 tests := []struct { 438 name string 439 args args 440 expected bool 441 }{ 442 { 443 name: "unsupported kind", 444 args: args{ 445 evt: event.UpdateEvent{ 446 ObjectOld: &corev1.Pod{}, 447 ObjectNew: &corev1.Pod{}, 448 }, 449 }, 450 expected: false, 451 }, 452 { 453 name: "mismatch kind for GatewayClass", 454 args: args{ 455 evt: event.UpdateEvent{ 456 ObjectOld: &gatewayv1.GatewayClass{}, 457 ObjectNew: &gatewayv1.Gateway{}, 458 }, 459 }, 460 expected: false, 461 }, 462 { 463 name: "mismatch kind for Gateway", 464 args: args{ 465 evt: event.UpdateEvent{ 466 ObjectOld: &gatewayv1.Gateway{}, 467 ObjectNew: &gatewayv1.GatewayClass{}, 468 }, 469 }, 470 expected: false, 471 }, 472 { 473 name: "mismatch kind for HTTPRoute", 474 args: args{ 475 evt: event.UpdateEvent{ 476 ObjectOld: &gatewayv1.HTTPRoute{}, 477 ObjectNew: &gatewayv1.GatewayClass{}, 478 }, 479 }, 480 expected: false, 481 }, 482 { 483 name: "no change in GatewayClass status", 484 args: args{ 485 evt: event.UpdateEvent{ 486 ObjectOld: &gatewayv1.GatewayClass{}, 487 ObjectNew: &gatewayv1.GatewayClass{}, 488 }, 489 }, 490 expected: false, 491 }, 492 { 493 name: "change in GatewayClass status", 494 args: args{ 495 evt: event.UpdateEvent{ 496 ObjectOld: &gatewayv1.GatewayClass{}, 497 ObjectNew: &gatewayv1.GatewayClass{ 498 Status: gatewayv1.GatewayClassStatus{ 499 Conditions: []metav1.Condition{ 500 { 501 Type: string(gatewayv1.GatewayConditionAccepted), 502 Status: metav1.ConditionTrue, 503 Reason: string(gatewayv1.GatewayReasonAccepted), 504 LastTransitionTime: metav1.NewTime(time.Now()), 505 }, 506 }, 507 }, 508 }, 509 }, 510 }, 511 expected: true, 512 }, 513 { 514 name: "only change LastTransitionTime in GatewayClass status", 515 args: args{ 516 evt: event.UpdateEvent{ 517 ObjectOld: &gatewayv1.Gateway{ 518 Status: gatewayv1.GatewayStatus{ 519 Conditions: []metav1.Condition{ 520 { 521 Type: string(gatewayv1.GatewayConditionAccepted), 522 Status: metav1.ConditionTrue, 523 Reason: string(gatewayv1.GatewayReasonAccepted), 524 LastTransitionTime: metav1.NewTime(time.Now()), 525 }, 526 }, 527 }, 528 }, 529 ObjectNew: &gatewayv1.Gateway{ 530 Status: gatewayv1.GatewayStatus{ 531 Conditions: []metav1.Condition{ 532 { 533 Type: string(gatewayv1.GatewayConditionAccepted), 534 Status: metav1.ConditionTrue, 535 Reason: string(gatewayv1.GatewayReasonAccepted), 536 LastTransitionTime: metav1.NewTime(time.Now()), 537 }, 538 }, 539 }, 540 }, 541 }, 542 }, 543 expected: false, 544 }, 545 546 { 547 name: "no change in gateway status", 548 args: args{ 549 evt: event.UpdateEvent{ 550 ObjectOld: &gatewayv1.Gateway{}, 551 ObjectNew: &gatewayv1.Gateway{}, 552 }, 553 }, 554 expected: false, 555 }, 556 { 557 name: "change in gateway status", 558 args: args{ 559 evt: event.UpdateEvent{ 560 ObjectOld: &gatewayv1.Gateway{}, 561 ObjectNew: &gatewayv1.Gateway{ 562 Status: gatewayv1.GatewayStatus{ 563 Conditions: []metav1.Condition{ 564 { 565 Type: string(gatewayv1.GatewayConditionAccepted), 566 Status: metav1.ConditionTrue, 567 Reason: string(gatewayv1.GatewayReasonAccepted), 568 LastTransitionTime: metav1.NewTime(time.Now()), 569 }, 570 }, 571 }, 572 }, 573 }, 574 }, 575 expected: true, 576 }, 577 { 578 name: "only change LastTransitionTime in gateway status", 579 args: args{ 580 evt: event.UpdateEvent{ 581 ObjectOld: &gatewayv1.Gateway{ 582 Status: gatewayv1.GatewayStatus{ 583 Conditions: []metav1.Condition{ 584 { 585 Type: string(gatewayv1.GatewayConditionAccepted), 586 Status: metav1.ConditionTrue, 587 Reason: string(gatewayv1.GatewayReasonAccepted), 588 LastTransitionTime: metav1.NewTime(time.Now()), 589 }, 590 }, 591 }, 592 }, 593 ObjectNew: &gatewayv1.Gateway{ 594 Status: gatewayv1.GatewayStatus{ 595 Conditions: []metav1.Condition{ 596 { 597 Type: string(gatewayv1.GatewayConditionAccepted), 598 Status: metav1.ConditionTrue, 599 Reason: string(gatewayv1.GatewayReasonAccepted), 600 LastTransitionTime: metav1.NewTime(time.Now()), 601 }, 602 }, 603 }, 604 }, 605 }, 606 }, 607 expected: false, 608 }, 609 { 610 name: "no change in HTTPRoute status", 611 args: args{ 612 evt: event.UpdateEvent{ 613 ObjectOld: &gatewayv1.HTTPRoute{}, 614 ObjectNew: &gatewayv1.HTTPRoute{}, 615 }, 616 }, 617 expected: false, 618 }, 619 { 620 name: "change in HTTP route status", 621 args: args{ 622 evt: event.UpdateEvent{ 623 ObjectOld: &gatewayv1.HTTPRoute{}, 624 ObjectNew: &gatewayv1.HTTPRoute{ 625 Status: gatewayv1.HTTPRouteStatus{ 626 RouteStatus: gatewayv1.RouteStatus{ 627 Parents: []gatewayv1.RouteParentStatus{ 628 { 629 ParentRef: gatewayv1.ParentReference{ 630 Name: "test-gateway", 631 }, 632 ControllerName: "io.cilium/gateway-controller", 633 Conditions: []metav1.Condition{ 634 { 635 Type: "Accepted", 636 Status: "True", 637 ObservedGeneration: 100, 638 Reason: "Accepted", 639 Message: "Valid HTTPRoute", 640 }, 641 }, 642 }, 643 }, 644 }, 645 }, 646 }, 647 }, 648 }, 649 expected: true, 650 }, 651 { 652 name: "only change LastTransitionTime in HTTPRoute status", 653 args: args{ 654 evt: event.UpdateEvent{ 655 ObjectOld: &gatewayv1.HTTPRoute{ 656 Status: gatewayv1.HTTPRouteStatus{ 657 RouteStatus: gatewayv1.RouteStatus{ 658 Parents: []gatewayv1.RouteParentStatus{ 659 { 660 ParentRef: gatewayv1.ParentReference{ 661 Name: "test-gateway", 662 }, 663 ControllerName: "io.cilium/gateway-controller", 664 Conditions: []metav1.Condition{ 665 { 666 Type: "Accepted", 667 Status: "True", 668 ObservedGeneration: 100, 669 Reason: "Accepted", 670 Message: "Valid HTTPRoute", 671 }, 672 }, 673 }, 674 }, 675 }, 676 }, 677 }, 678 ObjectNew: &gatewayv1.HTTPRoute{ 679 Status: gatewayv1.HTTPRouteStatus{ 680 RouteStatus: gatewayv1.RouteStatus{ 681 Parents: []gatewayv1.RouteParentStatus{ 682 { 683 ParentRef: gatewayv1.ParentReference{ 684 Name: "test-gateway", 685 }, 686 ControllerName: "io.cilium/gateway-controller", 687 Conditions: []metav1.Condition{ 688 { 689 Type: "Accepted", 690 Status: "True", 691 ObservedGeneration: 100, 692 Reason: "Accepted", 693 Message: "Valid HTTPRoute", 694 }, 695 }, 696 }, 697 }, 698 }, 699 }, 700 }, 701 }, 702 }, 703 expected: false, 704 }, 705 { 706 name: "no change in TLSRoute status", 707 args: args{ 708 evt: event.UpdateEvent{ 709 ObjectOld: &gatewayv1alpha2.TLSRoute{}, 710 ObjectNew: &gatewayv1alpha2.TLSRoute{}, 711 }, 712 }, 713 expected: false, 714 }, 715 { 716 name: "change in TLSRoute status", 717 args: args{ 718 evt: event.UpdateEvent{ 719 ObjectOld: &gatewayv1alpha2.TLSRoute{}, 720 ObjectNew: &gatewayv1alpha2.TLSRoute{ 721 Status: gatewayv1alpha2.TLSRouteStatus{ 722 RouteStatus: gatewayv1.RouteStatus{ 723 Parents: []gatewayv1.RouteParentStatus{ 724 { 725 ParentRef: gatewayv1.ParentReference{ 726 Name: "test-gateway", 727 }, 728 ControllerName: "io.cilium/gateway-controller", 729 Conditions: []metav1.Condition{ 730 { 731 Type: "Accepted", 732 Status: "True", 733 ObservedGeneration: 100, 734 Reason: "Accepted", 735 Message: "Valid TLSRoute", 736 }, 737 }, 738 }, 739 }, 740 }, 741 }, 742 }, 743 }, 744 }, 745 expected: true, 746 }, 747 { 748 name: "only change LastTransitionTime in TLSRoute status", 749 args: args{ 750 evt: event.UpdateEvent{ 751 ObjectOld: &gatewayv1alpha2.TLSRoute{ 752 Status: gatewayv1alpha2.TLSRouteStatus{ 753 RouteStatus: gatewayv1.RouteStatus{ 754 Parents: []gatewayv1.RouteParentStatus{ 755 { 756 ParentRef: gatewayv1.ParentReference{ 757 Name: "test-gateway", 758 }, 759 ControllerName: "io.cilium/gateway-controller", 760 Conditions: []metav1.Condition{ 761 { 762 Type: "Accepted", 763 Status: "True", 764 ObservedGeneration: 100, 765 Reason: "Accepted", 766 Message: "Valid TLSRoute", 767 }, 768 }, 769 }, 770 }, 771 }, 772 }, 773 }, 774 ObjectNew: &gatewayv1alpha2.TLSRoute{ 775 Status: gatewayv1alpha2.TLSRouteStatus{ 776 RouteStatus: gatewayv1.RouteStatus{ 777 Parents: []gatewayv1.RouteParentStatus{ 778 { 779 ParentRef: gatewayv1.ParentReference{ 780 Name: "test-gateway", 781 }, 782 ControllerName: "io.cilium/gateway-controller", 783 Conditions: []metav1.Condition{ 784 { 785 Type: "Accepted", 786 Status: "True", 787 ObservedGeneration: 100, 788 Reason: "Accepted", 789 Message: "Valid TLSRoute", 790 }, 791 }, 792 }, 793 }, 794 }, 795 }, 796 }, 797 }, 798 }, 799 expected: false, 800 }, 801 } 802 for _, tt := range tests { 803 t.Run(tt.name, func(t *testing.T) { 804 res := f.Update(tt.args.evt) 805 assert.Equal(t, tt.expected, res) 806 }) 807 } 808 }