github.com/cilium/cilium@v1.16.2/operator/pkg/model/ingestion/gateway_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package ingestion 5 6 import ( 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 corev1 "k8s.io/api/core/v1" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" 13 gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" 14 mcsapiv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" 15 mcsapicontrollers "sigs.k8s.io/mcs-api/pkg/controllers" 16 17 "github.com/cilium/cilium/operator/pkg/model" 18 ) 19 20 func GroupPtr(name string) *gatewayv1.Group { 21 group := gatewayv1.Group(name) 22 return &group 23 } 24 25 func KindPtr(name string) *gatewayv1.Kind { 26 kind := gatewayv1.Kind(name) 27 return &kind 28 } 29 30 var basicHTTP = Input{ 31 GatewayClass: gatewayv1.GatewayClass{}, 32 Gateway: gatewayv1.Gateway{ 33 TypeMeta: metav1.TypeMeta{ 34 Kind: "Gateway", 35 APIVersion: "gateway.networking.k8s.io/v1", 36 }, 37 ObjectMeta: metav1.ObjectMeta{ 38 Name: "my-gateway", 39 Namespace: "default", 40 }, 41 Spec: gatewayv1.GatewaySpec{ 42 Listeners: []gatewayv1.Listener{ 43 { 44 Name: "prod-web-gw", 45 Port: 80, 46 Protocol: "HTTP", 47 }, 48 }, 49 Infrastructure: &gatewayv1.GatewayInfrastructure{ 50 Labels: map[gatewayv1.AnnotationKey]gatewayv1.AnnotationValue{ 51 "internal-loadbalancer-label": "true", 52 }, 53 Annotations: map[gatewayv1.AnnotationKey]gatewayv1.AnnotationValue{ 54 "internal-loadbalancer-annotation": "true", 55 }, 56 }, 57 }, 58 }, 59 HTTPRoutes: []gatewayv1.HTTPRoute{ 60 { 61 ObjectMeta: metav1.ObjectMeta{ 62 Name: "http-app-1", 63 Namespace: "default", 64 }, 65 Spec: gatewayv1.HTTPRouteSpec{ 66 CommonRouteSpec: gatewayv1.CommonRouteSpec{ 67 ParentRefs: []gatewayv1.ParentReference{ 68 { 69 Name: "my-gateway", 70 }, 71 }, 72 }, 73 Rules: []gatewayv1.HTTPRouteRule{ 74 { 75 Matches: []gatewayv1.HTTPRouteMatch{ 76 { 77 Path: &gatewayv1.HTTPPathMatch{ 78 Type: model.AddressOf[gatewayv1.PathMatchType]("PathPrefix"), 79 Value: model.AddressOf("/bar"), 80 }, 81 }, 82 }, 83 BackendRefs: []gatewayv1.HTTPBackendRef{ 84 { 85 BackendRef: gatewayv1.BackendRef{ 86 BackendObjectReference: gatewayv1.BackendObjectReference{ 87 Name: "my-service", 88 Port: model.AddressOf[gatewayv1.PortNumber](8080), 89 }, 90 }, 91 }, 92 { 93 BackendRef: gatewayv1.BackendRef{ 94 BackendObjectReference: gatewayv1.BackendObjectReference{ 95 Group: GroupPtr(mcsapiv1alpha1.GroupName), 96 Kind: KindPtr("ServiceImport"), 97 Name: "my-service", 98 Port: model.AddressOf[gatewayv1.PortNumber](8080), 99 }, 100 }, 101 }, 102 }, 103 }, 104 }, 105 }, 106 }, 107 }, 108 Services: []corev1.Service{ 109 { 110 ObjectMeta: metav1.ObjectMeta{ 111 Name: "my-service", 112 Namespace: "default", 113 }, 114 }, 115 }, 116 ServiceImports: []mcsapiv1alpha1.ServiceImport{ 117 { 118 ObjectMeta: metav1.ObjectMeta{ 119 Name: "my-service", 120 Namespace: "default", 121 Annotations: map[string]string{ 122 mcsapicontrollers.DerivedServiceAnnotation: "my-service", 123 }, 124 }, 125 }, 126 }, 127 } 128 129 var basicHTTPListeners = []model.HTTPListener{ 130 { 131 Name: "prod-web-gw", 132 Sources: []model.FullyQualifiedResource{ 133 { 134 Name: "my-gateway", 135 Namespace: "default", 136 Group: "gateway.networking.k8s.io", 137 Version: "v1", 138 Kind: "Gateway", 139 }, 140 }, 141 Address: "", 142 Port: 80, 143 Hostname: "*", 144 Routes: []model.HTTPRoute{ 145 { 146 PathMatch: model.StringMatch{ 147 Prefix: "/bar", 148 }, 149 Backends: []model.Backend{ 150 { 151 Name: "my-service", 152 Namespace: "default", 153 Port: &model.BackendPort{ 154 Port: 8080, 155 }, 156 }, 157 { 158 Name: "my-service", 159 Namespace: "default", 160 Port: &model.BackendPort{ 161 Port: 8080, 162 }, 163 }, 164 }, 165 }, 166 }, 167 Infrastructure: &model.Infrastructure{ 168 Labels: map[string]string{ 169 "internal-loadbalancer-label": "true", 170 }, 171 Annotations: map[string]string{ 172 "internal-loadbalancer-annotation": "true", 173 }, 174 }, 175 }, 176 } 177 178 var basicTLS = Input{ 179 GatewayClass: gatewayv1.GatewayClass{}, 180 Gateway: gatewayv1.Gateway{ 181 TypeMeta: metav1.TypeMeta{ 182 Kind: "Gateway", 183 APIVersion: "gateway.networking.k8s.io/v1", 184 }, 185 ObjectMeta: metav1.ObjectMeta{ 186 Name: "my-gateway", 187 Namespace: "default", 188 }, 189 Spec: gatewayv1.GatewaySpec{ 190 Listeners: []gatewayv1.Listener{ 191 { 192 Name: "prod-web-gw", 193 Port: 443, 194 Protocol: "TLS", 195 }, 196 }, 197 }, 198 }, 199 TLSRoutes: []gatewayv1alpha2.TLSRoute{ 200 { 201 ObjectMeta: metav1.ObjectMeta{ 202 Name: "tls-app-1", 203 Namespace: "default", 204 }, 205 Spec: gatewayv1alpha2.TLSRouteSpec{ 206 CommonRouteSpec: gatewayv1.CommonRouteSpec{ 207 ParentRefs: []gatewayv1.ParentReference{ 208 { 209 Name: "my-gateway", 210 }, 211 }, 212 }, 213 Hostnames: []gatewayv1alpha2.Hostname{ 214 "example.com", 215 }, 216 Rules: []gatewayv1alpha2.TLSRouteRule{ 217 { 218 BackendRefs: []gatewayv1.BackendRef{ 219 { 220 BackendObjectReference: gatewayv1alpha2.BackendObjectReference{ 221 Name: "my-service", 222 Port: model.AddressOf[gatewayv1.PortNumber](443), 223 }, 224 }, 225 { 226 BackendObjectReference: gatewayv1.BackendObjectReference{ 227 Group: GroupPtr(mcsapiv1alpha1.GroupName), 228 Kind: KindPtr("ServiceImport"), 229 Name: "my-service", 230 Port: model.AddressOf[gatewayv1.PortNumber](443), 231 }, 232 }, 233 }, 234 }, 235 }, 236 }, 237 }, 238 }, 239 Services: []corev1.Service{ 240 { 241 ObjectMeta: metav1.ObjectMeta{ 242 Name: "my-service", 243 Namespace: "default", 244 }, 245 }, 246 }, 247 ServiceImports: []mcsapiv1alpha1.ServiceImport{ 248 { 249 ObjectMeta: metav1.ObjectMeta{ 250 Name: "my-service", 251 Namespace: "default", 252 Annotations: map[string]string{ 253 mcsapicontrollers.DerivedServiceAnnotation: "my-service", 254 }, 255 }, 256 }, 257 }, 258 } 259 260 var simpleSameNamespaceTLSListeners = []model.TLSPassthroughListener{ 261 { 262 Name: "https", 263 Sources: []model.FullyQualifiedResource{ 264 { 265 Name: "gateway-tlsroute", 266 Namespace: "gateway-conformance-infra", 267 Group: "gateway.networking.k8s.io", 268 Version: "v1", 269 Kind: "Gateway", 270 }, 271 }, 272 Address: "", 273 Port: 443, 274 Hostname: "*", 275 Routes: []model.TLSPassthroughRoute{ 276 { 277 Hostnames: []string{ 278 "abc.example.com", 279 }, 280 Backends: []model.Backend{ 281 { 282 Name: "tls-backend", 283 Namespace: "gateway-conformance-infra", 284 Port: &model.BackendPort{ 285 Port: 443, 286 }, 287 }, 288 }, 289 }, 290 }, 291 }, 292 } 293 294 var basicTLSListeners = []model.TLSPassthroughListener{ 295 { 296 Name: "prod-web-gw", 297 Sources: []model.FullyQualifiedResource{ 298 { 299 Name: "my-gateway", 300 Namespace: "default", 301 Group: "gateway.networking.k8s.io", 302 Version: "v1", 303 Kind: "Gateway", 304 }, 305 }, 306 Address: "", 307 Port: 443, 308 Hostname: "*", 309 Routes: []model.TLSPassthroughRoute{ 310 { 311 Hostnames: []string{ 312 "example.com", 313 }, 314 Backends: []model.Backend{ 315 { 316 Name: "my-service", 317 Namespace: "default", 318 Port: &model.BackendPort{ 319 Port: 443, 320 }, 321 }, 322 { 323 Name: "my-service", 324 Namespace: "default", 325 Port: &model.BackendPort{ 326 Port: 443, 327 }, 328 }, 329 }, 330 }, 331 }, 332 }, 333 } 334 335 var simpleSameNamespaceTLS = Input{ 336 GatewayClass: gatewayv1.GatewayClass{}, 337 Gateway: sameNamespaceTLSGateway, 338 TLSRoutes: []gatewayv1alpha2.TLSRoute{ 339 sameNamespaceTLSRoute, 340 }, 341 Services: allServices, 342 } 343 344 var crossNamespaceHTTPInput = Input{ 345 GatewayClass: gatewayv1.GatewayClass{}, 346 Gateway: backendNamespaceGateway, 347 HTTPRoutes: []gatewayv1.HTTPRoute{ 348 crossNamespaceHTTPRoute, 349 }, 350 Services: allServices, 351 } 352 353 var crossNamespaceHTTPListeners = []model.HTTPListener{ 354 { 355 Name: "http", 356 Sources: []model.FullyQualifiedResource{ 357 { 358 Name: "backend-namespaces", 359 Namespace: "gateway-conformance-infra", 360 }, 361 }, 362 Port: 80, 363 Hostname: "*", 364 Routes: []model.HTTPRoute{ 365 { 366 Backends: []model.Backend{ 367 { 368 Name: "web-backend", 369 Namespace: "gateway-conformance-web-backend", 370 Port: &model.BackendPort{ 371 Port: 8080, 372 }, 373 }, 374 }, 375 }, 376 }, 377 }, 378 } 379 380 var exactPathMatchingHTTPInput = Input{ 381 GatewayClass: gatewayv1.GatewayClass{}, 382 Gateway: sameNamespaceGateway, 383 HTTPRoutes: []gatewayv1.HTTPRoute{ 384 exactPathMatchingHTTPRoute, 385 }, 386 Services: allServices, 387 } 388 389 var exactPathMatchingHTTPListeners = []model.HTTPListener{ 390 { 391 Name: "http", 392 Sources: []model.FullyQualifiedResource{ 393 { 394 Name: "same-namespace", 395 Namespace: "gateway-conformance-infra", 396 }, 397 }, 398 Port: 80, 399 Hostname: "*", 400 Routes: []model.HTTPRoute{ 401 { 402 PathMatch: model.StringMatch{Exact: "/one"}, 403 Backends: []model.Backend{ 404 { 405 Name: "infra-backend-v1", 406 Namespace: "gateway-conformance-infra", 407 Port: &model.BackendPort{ 408 Port: 8080, 409 }, 410 }, 411 }, 412 }, 413 { 414 PathMatch: model.StringMatch{Exact: "/two"}, 415 Backends: []model.Backend{ 416 { 417 Name: "infra-backend-v2", 418 Namespace: "gateway-conformance-infra", 419 Port: &model.BackendPort{ 420 Port: 8080, 421 }, 422 }, 423 }, 424 }, 425 }, 426 }, 427 } 428 429 var headerMatchingHTTPInput = Input{ 430 GatewayClass: gatewayv1.GatewayClass{}, 431 Gateway: sameNamespaceGateway, 432 HTTPRoutes: []gatewayv1.HTTPRoute{ 433 headerMatchingHTTPRoute, 434 }, 435 Services: allServices, 436 } 437 438 var headerMatchingHTTPListeners = []model.HTTPListener{ 439 { 440 Name: "http", 441 Sources: []model.FullyQualifiedResource{ 442 { 443 Name: "same-namespace", 444 Namespace: "gateway-conformance-infra", 445 }, 446 }, 447 Port: 80, 448 Hostname: "*", 449 Routes: []model.HTTPRoute{ 450 { 451 HeadersMatch: []model.KeyValueMatch{ 452 { 453 Key: "version", 454 Match: model.StringMatch{Exact: "one"}, 455 }, 456 }, 457 Backends: []model.Backend{ 458 { 459 Name: "infra-backend-v1", 460 Namespace: "gateway-conformance-infra", 461 Port: &model.BackendPort{ 462 Port: 8080, 463 }, 464 }, 465 }, 466 }, 467 { 468 HeadersMatch: []model.KeyValueMatch{ 469 { 470 Key: "version", 471 Match: model.StringMatch{Exact: "two"}, 472 }, 473 }, 474 Backends: []model.Backend{ 475 { 476 Name: "infra-backend-v2", 477 Namespace: "gateway-conformance-infra", 478 Port: &model.BackendPort{ 479 Port: 8080, 480 }, 481 }, 482 }, 483 }, 484 { 485 HeadersMatch: []model.KeyValueMatch{ 486 { 487 Key: "version", 488 Match: model.StringMatch{Exact: "two"}, 489 }, 490 { 491 Key: "color", 492 Match: model.StringMatch{Exact: "orange"}, 493 }, 494 }, 495 Backends: []model.Backend{ 496 { 497 Name: "infra-backend-v1", 498 Namespace: "gateway-conformance-infra", 499 Port: &model.BackendPort{ 500 Port: 8080, 501 }, 502 }, 503 }, 504 }, 505 { 506 HeadersMatch: []model.KeyValueMatch{ 507 { 508 Key: "color", 509 Match: model.StringMatch{Prefix: "", Exact: "blue", Regex: ""}, 510 }, 511 }, 512 Backends: []model.Backend{ 513 { 514 Name: "infra-backend-v1", 515 Namespace: "gateway-conformance-infra", 516 Port: &model.BackendPort{ 517 Port: 8080, 518 }, 519 }, 520 }, 521 }, 522 { 523 HeadersMatch: []model.KeyValueMatch{ 524 { 525 Key: "color", 526 Match: model.StringMatch{Exact: "blue"}, 527 }, 528 }, 529 Backends: []model.Backend{ 530 { 531 Name: "infra-backend-v1", 532 Namespace: "gateway-conformance-infra", 533 Port: &model.BackendPort{ 534 Port: 8080, 535 }, 536 }, 537 }, 538 }, 539 { 540 HeadersMatch: []model.KeyValueMatch{ 541 { 542 Key: "color", 543 Match: model.StringMatch{Exact: "red"}, 544 }, 545 }, 546 Backends: []model.Backend{ 547 { 548 Name: "infra-backend-v2", 549 Namespace: "gateway-conformance-infra", 550 Port: &model.BackendPort{ 551 Port: 8080, 552 }, 553 }, 554 }, 555 }, 556 { 557 HeadersMatch: []model.KeyValueMatch{ 558 { 559 Key: "color", 560 Match: model.StringMatch{Exact: "yellow"}, 561 }, 562 }, 563 Backends: []model.Backend{ 564 { 565 Name: "infra-backend-v2", 566 Namespace: "gateway-conformance-infra", Port: &model.BackendPort{ 567 Port: 8080, 568 }, 569 }, 570 }, 571 }, 572 }, 573 }, 574 } 575 576 var hostnameIntersectionHTTPInput = Input{ 577 GatewayClass: gatewayv1.GatewayClass{}, 578 Gateway: *hostnameIntersectionGateway, 579 HTTPRoutes: hostnameIntersectionHTTPRoutes, 580 Services: allServices, 581 } 582 583 var hostnameIntersectionHTTPListeners = []model.HTTPListener{ 584 { 585 Name: "listener-1", 586 Sources: []model.FullyQualifiedResource{{Name: "httproute-hostname-intersection", Namespace: "gateway-conformance-infra"}}, 587 Port: 80, 588 Hostname: "very.specific.com", 589 Routes: []model.HTTPRoute{ 590 { 591 Hostnames: []string{"very.specific.com"}, 592 PathMatch: model.StringMatch{Prefix: "/s1"}, 593 Backends: []model.Backend{ 594 { 595 Name: "infra-backend-v1", 596 Namespace: "gateway-conformance-infra", 597 Port: &model.BackendPort{ 598 Port: 8080, 599 }, 600 }, 601 }, 602 }, 603 { 604 Hostnames: []string{"very.specific.com"}, 605 PathMatch: model.StringMatch{Prefix: "/s3"}, 606 Backends: []model.Backend{ 607 { 608 Name: "infra-backend-v3", 609 Namespace: "gateway-conformance-infra", 610 Port: &model.BackendPort{ 611 Port: 8080, 612 }, 613 }, 614 }, 615 }, 616 }, 617 }, 618 { 619 Name: "listener-2", 620 Sources: []model.FullyQualifiedResource{ 621 { 622 Name: "httproute-hostname-intersection", 623 Namespace: "gateway-conformance-infra", 624 }, 625 }, 626 Port: 80, 627 Hostname: "*.wildcard.io", 628 Routes: []model.HTTPRoute{ 629 { 630 Hostnames: []string{"bar.wildcard.io", "foo.bar.wildcard.io", "foo.wildcard.io"}, 631 PathMatch: model.StringMatch{Prefix: "/s2"}, 632 Backends: []model.Backend{ 633 { 634 Name: "infra-backend-v2", 635 Namespace: "gateway-conformance-infra", 636 Port: &model.BackendPort{ 637 Port: 8080, 638 }, 639 }, 640 }, 641 }, 642 }, 643 }, 644 { 645 Name: "listener-3", 646 Sources: []model.FullyQualifiedResource{ 647 { 648 Name: "httproute-hostname-intersection", 649 Namespace: "gateway-conformance-infra", 650 }, 651 }, 652 Port: 80, 653 Hostname: "*.anotherwildcard.io", 654 Routes: []model.HTTPRoute{ 655 { 656 Hostnames: []string{"*.anotherwildcard.io"}, 657 PathMatch: model.StringMatch{Prefix: "/s4"}, 658 Backends: []model.Backend{ 659 { 660 Name: "infra-backend-v1", 661 Namespace: "gateway-conformance-infra", 662 Port: &model.BackendPort{ 663 Port: 8080, 664 }, 665 }, 666 }, 667 }, 668 }, 669 }, 670 } 671 672 var listenerHostnameMatchingHTTPInput = Input{ 673 GatewayClass: gatewayv1.GatewayClass{}, 674 Gateway: *listenerHostnameMatchingGateway, 675 HTTPRoutes: listenerHostnameMatchingHTTPRoutes, 676 Services: allServices, 677 } 678 679 var listenerHostnameMatchingHTTPListeners = []model.HTTPListener{ 680 { 681 Name: "listener-1", 682 Sources: []model.FullyQualifiedResource{ 683 { 684 Name: "httproute-listener-hostname-matching", 685 Namespace: "gateway-conformance-infra", 686 }, 687 }, 688 Port: 80, 689 Hostname: "bar.com", 690 Routes: []model.HTTPRoute{ 691 { 692 Hostnames: []string{"bar.com"}, 693 Backends: []model.Backend{ 694 { 695 Name: "infra-backend-v1", 696 Namespace: "gateway-conformance-infra", 697 Port: &model.BackendPort{ 698 Port: 8080, 699 }, 700 }, 701 }, 702 }, 703 }, 704 }, 705 { 706 Name: "listener-2", 707 Sources: []model.FullyQualifiedResource{ 708 { 709 Name: "httproute-listener-hostname-matching", 710 Namespace: "gateway-conformance-infra", 711 }, 712 }, 713 Port: 80, 714 Hostname: "foo.bar.com", 715 Routes: []model.HTTPRoute{ 716 { 717 Hostnames: []string{"foo.bar.com"}, 718 Backends: []model.Backend{ 719 { 720 Name: "infra-backend-v2", 721 Namespace: "gateway-conformance-infra", 722 Port: &model.BackendPort{ 723 Port: 8080, 724 }, 725 }, 726 }, 727 }, 728 }, 729 }, 730 { 731 Name: "listener-3", 732 Sources: []model.FullyQualifiedResource{ 733 { 734 Name: "httproute-listener-hostname-matching", 735 Namespace: "gateway-conformance-infra", 736 }, 737 }, 738 Port: 80, 739 Hostname: "*.bar.com", 740 Routes: []model.HTTPRoute{ 741 { 742 Hostnames: []string{"*.bar.com"}, 743 Backends: []model.Backend{ 744 { 745 Name: "infra-backend-v3", 746 Namespace: "gateway-conformance-infra", 747 Port: &model.BackendPort{ 748 Port: 8080, 749 }, 750 }, 751 }, 752 }, 753 }, 754 }, 755 { 756 Name: "listener-4", 757 Sources: []model.FullyQualifiedResource{ 758 { 759 Name: "httproute-listener-hostname-matching", 760 Namespace: "gateway-conformance-infra", 761 }, 762 }, 763 Port: 80, 764 Hostname: "*.foo.com", 765 Routes: []model.HTTPRoute{ 766 { 767 Hostnames: []string{"*.foo.com"}, 768 Backends: []model.Backend{ 769 { 770 Name: "infra-backend-v3", 771 Namespace: "gateway-conformance-infra", 772 Port: &model.BackendPort{ 773 Port: 8080, 774 }, 775 }, 776 }, 777 }, 778 }, 779 }, 780 } 781 782 var matchingAcrossHTTPInput = Input{ 783 GatewayClass: gatewayv1.GatewayClass{}, 784 Gateway: sameNamespaceGateway, 785 HTTPRoutes: matchingAcrossHTTPRoutes, 786 Services: allServices, 787 } 788 789 var matchingAcrossHTTPListeners = []model.HTTPListener{ 790 { 791 Name: "http", 792 Sources: []model.FullyQualifiedResource{ 793 { 794 Name: "same-namespace", 795 Namespace: "gateway-conformance-infra", 796 }, 797 }, 798 Port: 80, 799 Hostname: "*", 800 Routes: []model.HTTPRoute{ 801 { 802 Hostnames: []string{"example.com", "example.net"}, 803 PathMatch: model.StringMatch{Exact: "/"}, 804 HeadersMatch: []model.KeyValueMatch{ 805 { 806 Key: "version", 807 Match: model.StringMatch{Exact: "one"}, 808 }, 809 }, 810 Backends: []model.Backend{ 811 { 812 Name: "infra-backend-v1", 813 Namespace: "gateway-conformance-infra", 814 Port: &model.BackendPort{ 815 Port: 8080, 816 }, 817 }, 818 }, 819 }, 820 { 821 Hostnames: []string{"example.com"}, 822 PathMatch: model.StringMatch{Exact: "/v2"}, 823 HeadersMatch: []model.KeyValueMatch{{Key: "version", Match: model.StringMatch{Exact: "two"}}}, 824 Backends: []model.Backend{ 825 { 826 Name: "infra-backend-v2", 827 Namespace: "gateway-conformance-infra", 828 Port: &model.BackendPort{ 829 Port: 8080, 830 }, 831 }, 832 }, 833 }, 834 }, 835 }, 836 } 837 838 var matchingHTTPInput = Input{ 839 GatewayClass: gatewayv1.GatewayClass{}, 840 Gateway: sameNamespaceGateway, 841 HTTPRoutes: matchingHTTPRoutes, 842 Services: allServices, 843 } 844 845 var matchingHTTPListeners = []model.HTTPListener{ 846 { 847 Name: "http", 848 Sources: []model.FullyQualifiedResource{ 849 { 850 Name: "same-namespace", 851 Namespace: "gateway-conformance-infra", 852 }, 853 }, 854 Port: 80, Hostname: "*", 855 Routes: []model.HTTPRoute{ 856 { 857 PathMatch: model.StringMatch{Exact: "/"}, 858 HeadersMatch: []model.KeyValueMatch{ 859 { 860 Key: "version", 861 Match: model.StringMatch{Exact: "one"}, 862 }, 863 }, 864 Backends: []model.Backend{ 865 { 866 Name: "infra-backend-v1", 867 Namespace: "gateway-conformance-infra", 868 Port: &model.BackendPort{ 869 Port: 8080, 870 }, 871 }, 872 }, 873 }, 874 { 875 PathMatch: model.StringMatch{Exact: "/v2"}, 876 HeadersMatch: []model.KeyValueMatch{ 877 { 878 Key: "version", 879 Match: model.StringMatch{Exact: "two"}, 880 }, 881 }, 882 Backends: []model.Backend{ 883 { 884 Name: "infra-backend-v2", 885 Namespace: "gateway-conformance-infra", 886 Port: &model.BackendPort{ 887 Port: 8080, 888 }, 889 }, 890 }, 891 }, 892 }, 893 }, 894 } 895 896 var queryParamMatchingHTTPInput = Input{ 897 GatewayClass: gatewayv1.GatewayClass{}, 898 Gateway: sameNamespaceGateway, 899 HTTPRoutes: queryParamMatchingHTTPRoutes, 900 Services: allServices, 901 } 902 903 var queryParamMatchingHTTPListeners = []model.HTTPListener{ 904 { 905 Name: "http", 906 Sources: []model.FullyQualifiedResource{ 907 { 908 Name: "same-namespace", 909 Namespace: "gateway-conformance-infra", 910 }, 911 }, 912 Port: 80, 913 Hostname: "*", 914 Routes: []model.HTTPRoute{ 915 { 916 QueryParamsMatch: []model.KeyValueMatch{ 917 { 918 Key: "animal", 919 Match: model.StringMatch{Exact: "whale"}, 920 }, 921 }, 922 Backends: []model.Backend{ 923 { 924 Name: "infra-backend-v1", 925 Namespace: "gateway-conformance-infra", 926 Port: &model.BackendPort{ 927 Port: 8080, 928 }, 929 }, 930 }, 931 }, 932 { 933 QueryParamsMatch: []model.KeyValueMatch{ 934 { 935 Key: "animal", 936 Match: model.StringMatch{Exact: "dolphin"}, 937 }, 938 }, 939 Backends: []model.Backend{ 940 { 941 Name: "infra-backend-v2", 942 Namespace: "gateway-conformance-infra", 943 Port: &model.BackendPort{ 944 Port: 8080, 945 }, 946 }, 947 }, 948 }, 949 { 950 QueryParamsMatch: []model.KeyValueMatch{ 951 { 952 Key: "animal", 953 Match: model.StringMatch{Exact: "dolphin"}, 954 }, 955 { 956 Key: "color", 957 Match: model.StringMatch{Exact: "blue"}, 958 }, 959 }, 960 Backends: []model.Backend{ 961 { 962 Name: "infra-backend-v3", 963 Namespace: "gateway-conformance-infra", 964 Port: &model.BackendPort{ 965 Port: 8080, 966 }, 967 }, 968 }, 969 }, 970 { 971 QueryParamsMatch: []model.KeyValueMatch{ 972 { 973 Key: "ANIMAL", 974 Match: model.StringMatch{Exact: "Whale"}, 975 }, 976 }, 977 Backends: []model.Backend{ 978 { 979 Name: "infra-backend-v3", 980 Namespace: "gateway-conformance-infra", 981 Port: &model.BackendPort{ 982 Port: 8080, 983 }, 984 }, 985 }, 986 }, 987 }, 988 }, 989 } 990 991 var requestHeaderModifierHTTPInput = Input{ 992 GatewayClass: gatewayv1.GatewayClass{}, 993 Gateway: sameNamespaceGateway, 994 HTTPRoutes: requestHeaderModifierHTTPRoutes, 995 Services: allServices, 996 } 997 998 var backendRefsRequestHeaderModifierHTTPInput = Input{ 999 GatewayClass: gatewayv1.GatewayClass{}, 1000 Gateway: sameNamespaceGateway, 1001 HTTPRoutes: backendRefsRequestHeaderModifierHTTPRoutes, 1002 Services: allServices, 1003 } 1004 1005 var requestHeaderModifierHTTPListeners = []model.HTTPListener{ 1006 { 1007 Name: "http", 1008 Sources: []model.FullyQualifiedResource{ 1009 { 1010 Name: "same-namespace", 1011 Namespace: "gateway-conformance-infra", 1012 }, 1013 }, 1014 Port: 80, Hostname: "*", 1015 Routes: []model.HTTPRoute{ 1016 { 1017 PathMatch: model.StringMatch{Exact: "/set"}, 1018 Backends: []model.Backend{ 1019 { 1020 Name: "infra-backend-v1", 1021 Namespace: "gateway-conformance-infra", 1022 Port: &model.BackendPort{ 1023 Port: 8080, 1024 }, 1025 }, 1026 }, 1027 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1028 HeadersToSet: []model.Header{ 1029 { 1030 Name: "X-Header-Set", 1031 Value: "set-overwrites-values", 1032 }, 1033 }, 1034 }, 1035 }, 1036 { 1037 PathMatch: model.StringMatch{Exact: "/add"}, 1038 Backends: []model.Backend{ 1039 { 1040 Name: "infra-backend-v1", 1041 Namespace: "gateway-conformance-infra", 1042 Port: &model.BackendPort{ 1043 Port: 8080, 1044 }, 1045 }, 1046 }, 1047 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1048 HeadersToAdd: []model.Header{ 1049 { 1050 Name: "X-Header-Add", 1051 Value: "add-appends-values", 1052 }, 1053 }, 1054 }, 1055 }, 1056 { 1057 PathMatch: model.StringMatch{Exact: "/remove"}, 1058 Backends: []model.Backend{ 1059 { 1060 Name: "infra-backend-v1", 1061 Namespace: "gateway-conformance-infra", 1062 Port: &model.BackendPort{ 1063 Port: 8080, 1064 }, 1065 }, 1066 }, 1067 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1068 HeadersToRemove: []string{"X-Header-Remove"}, 1069 }, 1070 }, 1071 { 1072 PathMatch: model.StringMatch{Exact: "/multiple"}, 1073 Backends: []model.Backend{ 1074 { 1075 Name: "infra-backend-v1", 1076 Namespace: "gateway-conformance-infra", 1077 Port: &model.BackendPort{ 1078 Port: 8080, 1079 }, 1080 }, 1081 }, 1082 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1083 HeadersToAdd: []model.Header{ 1084 { 1085 Name: "X-Header-Add-1", 1086 Value: "header-add-1", 1087 }, 1088 { 1089 Name: "X-Header-Add-2", 1090 Value: "header-add-2", 1091 }, 1092 { 1093 Name: "X-Header-Add-3", 1094 Value: "header-add-3", 1095 }, 1096 }, 1097 HeadersToSet: []model.Header{ 1098 { 1099 Name: "X-Header-Set-1", 1100 Value: "header-set-1", 1101 }, 1102 { 1103 Name: "X-Header-Set-2", 1104 Value: "header-set-2", 1105 }, 1106 }, 1107 HeadersToRemove: []string{ 1108 "X-Header-Remove-1", 1109 "X-Header-Remove-2", 1110 }, 1111 }, 1112 }, 1113 { 1114 PathMatch: model.StringMatch{Exact: "/case-insensitivity"}, 1115 Backends: []model.Backend{ 1116 { 1117 Name: "infra-backend-v1", 1118 Namespace: "gateway-conformance-infra", 1119 Port: &model.BackendPort{ 1120 Port: 8080, 1121 }, 1122 }, 1123 }, 1124 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1125 HeadersToAdd: []model.Header{ 1126 { 1127 Name: "X-Header-Add", 1128 Value: "header-add", 1129 }, 1130 }, 1131 HeadersToSet: []model.Header{ 1132 { 1133 Name: "X-Header-Set", 1134 Value: "header-set", 1135 }, 1136 }, 1137 HeadersToRemove: []string{ 1138 "X-Header-Remove", 1139 }, 1140 }, 1141 }, 1142 }, 1143 }, 1144 } 1145 1146 var backendRefsRequestHeaderModifierHTTPListeners = []model.HTTPListener{ 1147 { 1148 Name: "http", 1149 Sources: []model.FullyQualifiedResource{ 1150 { 1151 Name: "same-namespace", 1152 Namespace: "gateway-conformance-infra", 1153 }, 1154 }, 1155 Port: 80, Hostname: "*", 1156 Routes: []model.HTTPRoute{ 1157 { 1158 PathMatch: model.StringMatch{Exact: "/set"}, 1159 Backends: []model.Backend{ 1160 { 1161 Name: "infra-backend-v1", 1162 Namespace: "gateway-conformance-infra", 1163 Port: &model.BackendPort{ 1164 Port: 8080, 1165 }, 1166 }, 1167 }, 1168 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1169 { 1170 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1171 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1172 HeadersToSet: []model.Header{ 1173 { 1174 Name: "X-Header-Set", 1175 Value: "set-overwrites-values", 1176 }, 1177 }, 1178 }, 1179 }, 1180 }, 1181 }, 1182 { 1183 PathMatch: model.StringMatch{Exact: "/add"}, 1184 Backends: []model.Backend{ 1185 { 1186 Name: "infra-backend-v1", 1187 Namespace: "gateway-conformance-infra", 1188 Port: &model.BackendPort{ 1189 Port: 8080, 1190 }, 1191 }, 1192 }, 1193 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1194 { 1195 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1196 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1197 HeadersToAdd: []model.Header{ 1198 { 1199 Name: "X-Header-Add", 1200 Value: "add-appends-values", 1201 }, 1202 }, 1203 }, 1204 }, 1205 }, 1206 }, 1207 { 1208 PathMatch: model.StringMatch{Exact: "/remove"}, 1209 Backends: []model.Backend{ 1210 { 1211 Name: "infra-backend-v1", 1212 Namespace: "gateway-conformance-infra", 1213 Port: &model.BackendPort{ 1214 Port: 8080, 1215 }, 1216 }, 1217 }, 1218 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1219 { 1220 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1221 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1222 HeadersToRemove: []string{"X-Header-Remove"}, 1223 }, 1224 }, 1225 }, 1226 }, 1227 { 1228 PathMatch: model.StringMatch{Exact: "/multiple-backends"}, 1229 Backends: []model.Backend{ 1230 { 1231 Name: "infra-backend-v1", 1232 Namespace: "gateway-conformance-infra", 1233 Port: &model.BackendPort{ 1234 Port: 8080, 1235 }, 1236 }, 1237 { 1238 Name: "infra-backend-v2", 1239 Namespace: "gateway-conformance-infra", 1240 Port: &model.BackendPort{ 1241 Port: 8080, 1242 }, 1243 }, 1244 }, 1245 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1246 { 1247 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1248 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1249 HeadersToAdd: []model.Header{ 1250 { 1251 Name: "X-Header-Add-1", 1252 Value: "header-add-1", 1253 }, 1254 { 1255 Name: "X-Header-Add-2", 1256 Value: "header-add-2", 1257 }, 1258 }, 1259 }, 1260 }, 1261 { 1262 Name: "gateway-conformance-infra:infra-backend-v2:8080", 1263 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1264 HeadersToAdd: []model.Header{ 1265 { 1266 Name: "X-Header-Add-3", 1267 Value: "header-add-3", 1268 }, 1269 }, 1270 }, 1271 }, 1272 }, 1273 }, 1274 { 1275 PathMatch: model.StringMatch{Exact: "/multiple-backends-with-some-not"}, 1276 Backends: []model.Backend{ 1277 { 1278 Name: "infra-backend-v1", 1279 Namespace: "gateway-conformance-infra", 1280 Port: &model.BackendPort{ 1281 Port: 8080, 1282 }, 1283 }, 1284 { 1285 Name: "infra-backend-v2", 1286 Namespace: "gateway-conformance-infra", 1287 Port: &model.BackendPort{ 1288 Port: 8080, 1289 }, 1290 }, 1291 }, 1292 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1293 { 1294 Name: "gateway-conformance-infra:infra-backend-v2:8080", 1295 RequestHeaderFilter: &model.HTTPHeaderFilter{ 1296 HeadersToAdd: []model.Header{ 1297 { 1298 Name: "X-Header-Add", 1299 Value: "header-add", 1300 }, 1301 }, 1302 HeadersToSet: []model.Header{ 1303 { 1304 Name: "X-Header-Set", 1305 Value: "header-set", 1306 }, 1307 }, 1308 HeadersToRemove: []string{ 1309 "X-Header-Remove", 1310 }, 1311 }, 1312 }, 1313 }, 1314 }, 1315 }, 1316 }, 1317 } 1318 1319 var simpleSameNamespaceHTTPInput = Input{ 1320 GatewayClass: gatewayv1.GatewayClass{}, 1321 Gateway: sameNamespaceGateway, 1322 HTTPRoutes: simpleSameNamespaceHTTPRoutes, 1323 Services: allServices, 1324 } 1325 1326 var simpleSameNamespaceHTTPListeners = []model.HTTPListener{ 1327 { 1328 Name: "http", 1329 Sources: []model.FullyQualifiedResource{ 1330 { 1331 Name: "same-namespace", 1332 Namespace: "gateway-conformance-infra", 1333 }, 1334 }, 1335 Port: 80, 1336 Hostname: "*", 1337 Routes: []model.HTTPRoute{ 1338 { 1339 Backends: []model.Backend{ 1340 { 1341 Name: "infra-backend-v1", 1342 Namespace: "gateway-conformance-infra", 1343 Port: &model.BackendPort{ 1344 Port: 8080, 1345 }, 1346 }, 1347 }, 1348 }, 1349 }, 1350 }, 1351 } 1352 1353 var methodMatchingHTTPInput = Input{ 1354 GatewayClass: gatewayv1.GatewayClass{}, 1355 Gateway: sameNamespaceGateway, 1356 HTTPRoutes: methodMatchingHTTPRoutes, 1357 Services: allServices, 1358 } 1359 1360 var methodMatchingHTTPListeners = []model.HTTPListener{ 1361 { 1362 Name: "http", 1363 Sources: []model.FullyQualifiedResource{ 1364 { 1365 Name: "same-namespace", 1366 Namespace: "gateway-conformance-infra", 1367 }, 1368 }, 1369 Port: 80, 1370 Hostname: "*", 1371 Routes: []model.HTTPRoute{ 1372 { 1373 Method: model.AddressOf("POST"), 1374 Backends: []model.Backend{ 1375 { 1376 Name: "infra-backend-v1", 1377 Namespace: "gateway-conformance-infra", 1378 Port: &model.BackendPort{ 1379 Port: 8080, 1380 }, 1381 }, 1382 }, 1383 }, 1384 { 1385 Method: model.AddressOf("GET"), 1386 Backends: []model.Backend{ 1387 { 1388 Name: "infra-backend-v2", 1389 Namespace: "gateway-conformance-infra", 1390 Port: &model.BackendPort{ 1391 Port: 8080, 1392 }, 1393 }, 1394 }, 1395 }, 1396 }, 1397 }, 1398 } 1399 1400 var requestRedirectHTTPInput = Input{ 1401 GatewayClass: gatewayv1.GatewayClass{}, 1402 Gateway: sameNamespaceGateway, 1403 HTTPRoutes: requestRedirectHTTPRoutes, 1404 Services: allServices, 1405 } 1406 1407 var requestRedirectHTTPListeners = []model.HTTPListener{ 1408 { 1409 Name: "http", 1410 Sources: []model.FullyQualifiedResource{ 1411 { 1412 Name: "same-namespace", 1413 Namespace: "gateway-conformance-infra", 1414 }, 1415 }, 1416 Port: 80, 1417 Hostname: "*", 1418 Routes: []model.HTTPRoute{ 1419 { 1420 PathMatch: model.StringMatch{Prefix: "/hostname-redirect"}, 1421 Backends: []model.Backend{ 1422 { 1423 Name: "infra-backend-v1", 1424 Namespace: "gateway-conformance-infra", 1425 Port: &model.BackendPort{ 1426 Port: 8080, 1427 }, 1428 }, 1429 }, 1430 RequestRedirect: &model.HTTPRequestRedirectFilter{ 1431 Hostname: model.AddressOf("example.com"), 1432 Port: model.AddressOf(int32(80)), 1433 }, 1434 }, 1435 { 1436 PathMatch: model.StringMatch{Prefix: "/status-code-301"}, 1437 Backends: []model.Backend{}, 1438 DirectResponse: &model.DirectResponse{ 1439 StatusCode: 500, 1440 }, 1441 RequestRedirect: &model.HTTPRequestRedirectFilter{ 1442 StatusCode: model.AddressOf(301), 1443 Port: model.AddressOf(int32(80)), 1444 }, 1445 }, 1446 { 1447 PathMatch: model.StringMatch{Prefix: "/host-and-status"}, 1448 Backends: []model.Backend{ 1449 { 1450 Name: "infra-backend-v1", 1451 Namespace: "gateway-conformance-infra", 1452 Port: &model.BackendPort{ 1453 Port: 8080, 1454 }, 1455 }, 1456 }, 1457 RequestRedirect: &model.HTTPRequestRedirectFilter{ 1458 Hostname: model.AddressOf("example.com"), 1459 StatusCode: model.AddressOf(301), 1460 Port: model.AddressOf(int32(80)), 1461 }, 1462 }, 1463 }, 1464 }, 1465 } 1466 1467 var responseHeaderModifierHTTPInput = Input{ 1468 GatewayClass: gatewayv1.GatewayClass{}, 1469 Gateway: sameNamespaceGateway, 1470 HTTPRoutes: responseHeaderModifierHTTPRoutes, 1471 Services: allServices, 1472 } 1473 1474 var responseHeaderModifierHTTPListeners = []model.HTTPListener{ 1475 { 1476 Name: "http", 1477 Sources: []model.FullyQualifiedResource{ 1478 { 1479 Name: "same-namespace", 1480 Namespace: "gateway-conformance-infra", 1481 }, 1482 }, 1483 Port: 80, Hostname: "*", 1484 Routes: []model.HTTPRoute{ 1485 { 1486 PathMatch: model.StringMatch{Prefix: "/set"}, 1487 Backends: []model.Backend{ 1488 { 1489 Name: "infra-backend-v1", 1490 Namespace: "gateway-conformance-infra", 1491 Port: &model.BackendPort{ 1492 Port: 8080, 1493 }, 1494 }, 1495 }, 1496 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1497 HeadersToSet: []model.Header{ 1498 { 1499 Name: "X-Header-Set", 1500 Value: "set-overwrites-values", 1501 }, 1502 }, 1503 }, 1504 }, 1505 { 1506 PathMatch: model.StringMatch{Prefix: "/add"}, 1507 Backends: []model.Backend{ 1508 { 1509 Name: "infra-backend-v1", 1510 Namespace: "gateway-conformance-infra", 1511 Port: &model.BackendPort{ 1512 Port: 8080, 1513 }, 1514 }, 1515 }, 1516 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1517 HeadersToAdd: []model.Header{ 1518 { 1519 Name: "X-Header-Add", 1520 Value: "add-appends-values", 1521 }, 1522 }, 1523 }, 1524 }, 1525 { 1526 PathMatch: model.StringMatch{Prefix: "/remove"}, 1527 Backends: []model.Backend{ 1528 { 1529 Name: "infra-backend-v1", 1530 Namespace: "gateway-conformance-infra", 1531 Port: &model.BackendPort{ 1532 Port: 8080, 1533 }, 1534 }, 1535 }, 1536 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1537 HeadersToRemove: []string{"X-Header-Remove"}, 1538 }, 1539 }, 1540 { 1541 PathMatch: model.StringMatch{Prefix: "/multiple"}, 1542 Backends: []model.Backend{ 1543 { 1544 Name: "infra-backend-v1", 1545 Namespace: "gateway-conformance-infra", 1546 Port: &model.BackendPort{ 1547 Port: 8080, 1548 }, 1549 }, 1550 }, 1551 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1552 HeadersToAdd: []model.Header{ 1553 { 1554 Name: "X-Header-Add-1", 1555 Value: "header-add-1", 1556 }, 1557 { 1558 Name: "X-Header-Add-2", 1559 Value: "header-add-2", 1560 }, 1561 { 1562 Name: "X-Header-Add-3", 1563 Value: "header-add-3", 1564 }, 1565 }, 1566 HeadersToSet: []model.Header{ 1567 { 1568 Name: "X-Header-Set-1", 1569 Value: "header-set-1", 1570 }, 1571 { 1572 Name: "X-Header-Set-2", 1573 Value: "header-set-2", 1574 }, 1575 }, 1576 HeadersToRemove: []string{ 1577 "X-Header-Remove-1", 1578 "X-Header-Remove-2", 1579 }, 1580 }, 1581 }, 1582 { 1583 PathMatch: model.StringMatch{Prefix: "/case-insensitivity"}, 1584 Backends: []model.Backend{ 1585 { 1586 Name: "infra-backend-v1", 1587 Namespace: "gateway-conformance-infra", 1588 Port: &model.BackendPort{ 1589 Port: 8080, 1590 }, 1591 }, 1592 }, 1593 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1594 HeadersToAdd: []model.Header{ 1595 { 1596 Name: "X-Header-Add", 1597 Value: "header-add", 1598 }, 1599 { 1600 Name: "x-lowercase-add", 1601 Value: "lowercase-add", 1602 }, 1603 { 1604 Name: "x-Mixedcase-ADD-1", 1605 Value: "mixedcase-add-1", 1606 }, 1607 { 1608 Name: "X-mixeDcase-add-2", 1609 Value: "mixedcase-add-2", 1610 }, 1611 { 1612 Name: "X-UPPERCASE-ADD", 1613 Value: "uppercase-add", 1614 }, 1615 }, 1616 HeadersToSet: []model.Header{ 1617 { 1618 Name: "X-Header-Set", 1619 Value: "header-set", 1620 }, 1621 }, 1622 HeadersToRemove: []string{ 1623 "X-Header-Remove", 1624 }, 1625 }, 1626 }, 1627 }, 1628 }, 1629 } 1630 1631 var backendRefsResponseHeaderModifierHTTPInput = Input{ 1632 GatewayClass: gatewayv1.GatewayClass{}, 1633 Gateway: sameNamespaceGateway, 1634 HTTPRoutes: backendRefsResponseHeaderModifierHTTPRoutes, 1635 Services: allServices, 1636 } 1637 1638 var backendRefsResponseHeaderModifierHTTPListeners = []model.HTTPListener{ 1639 { 1640 Name: "http", 1641 Sources: []model.FullyQualifiedResource{ 1642 { 1643 Name: "same-namespace", 1644 Namespace: "gateway-conformance-infra", 1645 }, 1646 }, 1647 Port: 80, Hostname: "*", 1648 Routes: []model.HTTPRoute{ 1649 { 1650 PathMatch: model.StringMatch{Prefix: "/set"}, 1651 Backends: []model.Backend{ 1652 { 1653 Name: "infra-backend-v1", 1654 Namespace: "gateway-conformance-infra", 1655 Port: &model.BackendPort{ 1656 Port: 8080, 1657 }, 1658 }, 1659 }, 1660 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1661 { 1662 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1663 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1664 HeadersToSet: []model.Header{ 1665 { 1666 Name: "X-Header-Set", 1667 Value: "set-overwrites-values", 1668 }, 1669 }, 1670 }, 1671 }, 1672 }, 1673 }, 1674 { 1675 PathMatch: model.StringMatch{Prefix: "/add"}, 1676 Backends: []model.Backend{ 1677 { 1678 Name: "infra-backend-v1", 1679 Namespace: "gateway-conformance-infra", 1680 Port: &model.BackendPort{ 1681 Port: 8080, 1682 }, 1683 }, 1684 }, 1685 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1686 { 1687 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1688 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1689 HeadersToAdd: []model.Header{ 1690 { 1691 Name: "X-Header-Add", 1692 Value: "add-appends-values", 1693 }, 1694 }, 1695 }, 1696 }, 1697 }, 1698 }, 1699 { 1700 PathMatch: model.StringMatch{Prefix: "/remove"}, 1701 Backends: []model.Backend{ 1702 { 1703 Name: "infra-backend-v1", 1704 Namespace: "gateway-conformance-infra", 1705 Port: &model.BackendPort{ 1706 Port: 8080, 1707 }, 1708 }, 1709 }, 1710 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1711 { 1712 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1713 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1714 HeadersToRemove: []string{"X-Header-Remove"}, 1715 }, 1716 }, 1717 }, 1718 }, 1719 { 1720 PathMatch: model.StringMatch{Prefix: "/multiple"}, 1721 Backends: []model.Backend{ 1722 { 1723 Name: "infra-backend-v1", 1724 Namespace: "gateway-conformance-infra", 1725 Port: &model.BackendPort{ 1726 Port: 8080, 1727 }, 1728 }, 1729 }, 1730 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1731 { 1732 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1733 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1734 HeadersToAdd: []model.Header{ 1735 { 1736 Name: "X-Header-Add-1", 1737 Value: "header-add-1", 1738 }, 1739 { 1740 Name: "X-Header-Add-2", 1741 Value: "header-add-2", 1742 }, 1743 { 1744 Name: "X-Header-Add-3", 1745 Value: "header-add-3", 1746 }, 1747 }, 1748 HeadersToSet: []model.Header{ 1749 { 1750 Name: "X-Header-Set-1", 1751 Value: "header-set-1", 1752 }, 1753 { 1754 Name: "X-Header-Set-2", 1755 Value: "header-set-2", 1756 }, 1757 }, 1758 HeadersToRemove: []string{ 1759 "X-Header-Remove-1", 1760 "X-Header-Remove-2", 1761 }, 1762 }, 1763 }, 1764 }, 1765 }, 1766 { 1767 PathMatch: model.StringMatch{Prefix: "/multiple-backends"}, 1768 Backends: []model.Backend{ 1769 { 1770 Name: "infra-backend-v1", 1771 Namespace: "gateway-conformance-infra", 1772 Port: &model.BackendPort{ 1773 Port: 8080, 1774 }, 1775 }, 1776 { 1777 Name: "infra-backend-v2", 1778 Namespace: "gateway-conformance-infra", 1779 Port: &model.BackendPort{ 1780 Port: 8080, 1781 }, 1782 }, 1783 { 1784 Name: "infra-backend-v3", 1785 Namespace: "gateway-conformance-infra", 1786 Port: &model.BackendPort{ 1787 Port: 8080, 1788 }, 1789 }, 1790 }, 1791 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1792 { 1793 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1794 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1795 HeadersToAdd: []model.Header{ 1796 { 1797 Name: "X-Header-Add-1", 1798 Value: "header-add-1", 1799 }, 1800 }, 1801 HeadersToSet: []model.Header{ 1802 { 1803 Name: "X-Header-Set-1", 1804 Value: "header-set-1", 1805 }, 1806 }, 1807 HeadersToRemove: []string{ 1808 "X-Header-Remove-1", 1809 }, 1810 }, 1811 }, 1812 { 1813 Name: "gateway-conformance-infra:infra-backend-v2:8080", 1814 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1815 HeadersToAdd: []model.Header{ 1816 { 1817 Name: "X-Header-Add-2", 1818 Value: "header-add-2", 1819 }, 1820 }, 1821 HeadersToSet: []model.Header{ 1822 { 1823 Name: "X-Header-Set-2", 1824 Value: "header-set-2", 1825 }, 1826 }, 1827 HeadersToRemove: []string{ 1828 "X-Header-Remove-2", 1829 }, 1830 }, 1831 }, 1832 { 1833 Name: "gateway-conformance-infra:infra-backend-v3:8080", 1834 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1835 HeadersToAdd: []model.Header{ 1836 { 1837 Name: "X-Header-Add-3", 1838 Value: "header-add-3", 1839 }, 1840 }, 1841 HeadersToSet: []model.Header{ 1842 { 1843 Name: "X-Header-Set-3", 1844 Value: "header-set-3", 1845 }, 1846 }, 1847 HeadersToRemove: []string{ 1848 "X-Header-Remove-3", 1849 }, 1850 }, 1851 }, 1852 }, 1853 }, 1854 { 1855 PathMatch: model.StringMatch{Prefix: "/case-insensitivity"}, 1856 Backends: []model.Backend{ 1857 { 1858 Name: "infra-backend-v1", 1859 Namespace: "gateway-conformance-infra", 1860 Port: &model.BackendPort{ 1861 Port: 8080, 1862 }, 1863 }, 1864 }, 1865 BackendHTTPFilters: []*model.BackendHTTPFilter{ 1866 { 1867 Name: "gateway-conformance-infra:infra-backend-v1:8080", 1868 ResponseHeaderModifier: &model.HTTPHeaderFilter{ 1869 HeadersToAdd: []model.Header{ 1870 { 1871 Name: "X-Header-Add", 1872 Value: "header-add", 1873 }, 1874 { 1875 Name: "x-lowercase-add", 1876 Value: "lowercase-add", 1877 }, 1878 { 1879 Name: "x-Mixedcase-ADD-1", 1880 Value: "mixedcase-add-1", 1881 }, 1882 { 1883 Name: "X-mixeDcase-add-2", 1884 Value: "mixedcase-add-2", 1885 }, 1886 { 1887 Name: "X-UPPERCASE-ADD", 1888 Value: "uppercase-add", 1889 }, 1890 }, 1891 HeadersToSet: []model.Header{ 1892 { 1893 Name: "X-Header-Set", 1894 Value: "header-set", 1895 }, 1896 }, 1897 HeadersToRemove: []string{ 1898 "X-Header-Remove", 1899 }, 1900 }, 1901 }, 1902 }, 1903 }, 1904 }, 1905 }, 1906 } 1907 1908 var rewriteHostHTTPInput = Input{ 1909 GatewayClass: gatewayv1.GatewayClass{}, 1910 Gateway: sameNamespaceGateway, 1911 HTTPRoutes: rewriteHostHTTPRoutes, 1912 Services: allServices, 1913 } 1914 1915 var rewriteHostHTTPListeners = []model.HTTPListener{ 1916 { 1917 Name: "http", 1918 Sources: []model.FullyQualifiedResource{ 1919 { 1920 Name: "same-namespace", 1921 Namespace: "gateway-conformance-infra", 1922 }, 1923 }, 1924 Port: 80, 1925 Hostname: "*", 1926 Routes: []model.HTTPRoute{ 1927 { 1928 Hostnames: []string{"rewrite.example"}, 1929 PathMatch: model.StringMatch{Prefix: "/one"}, 1930 Backends: []model.Backend{ 1931 { 1932 Name: "infra-backend-v1", 1933 Namespace: "gateway-conformance-infra", 1934 Port: &model.BackendPort{ 1935 Port: 8080, 1936 }, 1937 }, 1938 }, 1939 Rewrite: &model.HTTPURLRewriteFilter{ 1940 HostName: model.AddressOf("one.example.org"), 1941 }, 1942 }, 1943 { 1944 Hostnames: []string{"rewrite.example"}, 1945 Backends: []model.Backend{ 1946 { 1947 Name: "infra-backend-v2", 1948 Namespace: "gateway-conformance-infra", 1949 Port: &model.BackendPort{ 1950 Port: 8080, 1951 }, 1952 }, 1953 }, 1954 Rewrite: &model.HTTPURLRewriteFilter{ 1955 HostName: model.AddressOf("example.org"), 1956 }, 1957 }, 1958 }, 1959 }, 1960 } 1961 1962 var rewritePathHTTPInput = Input{ 1963 GatewayClass: gatewayv1.GatewayClass{}, 1964 Gateway: sameNamespaceGateway, 1965 HTTPRoutes: rewritePathHTTPRoutes, 1966 Services: allServices, 1967 } 1968 1969 var rewritePathHTTPListeners = []model.HTTPListener{ 1970 { 1971 Name: "http", 1972 Sources: []model.FullyQualifiedResource{ 1973 { 1974 Name: "same-namespace", 1975 Namespace: "gateway-conformance-infra", 1976 }, 1977 }, 1978 Port: 80, 1979 Hostname: "*", 1980 Routes: []model.HTTPRoute{ 1981 { 1982 PathMatch: model.StringMatch{Prefix: "/prefix/one"}, 1983 Backends: []model.Backend{ 1984 { 1985 Name: "infra-backend-v1", 1986 Namespace: "gateway-conformance-infra", 1987 Port: &model.BackendPort{ 1988 Port: 8080, 1989 }, 1990 }, 1991 }, 1992 Rewrite: &model.HTTPURLRewriteFilter{ 1993 Path: &model.StringMatch{ 1994 Prefix: "/one", 1995 }, 1996 }, 1997 }, 1998 { 1999 PathMatch: model.StringMatch{Prefix: "/full/one"}, 2000 Backends: []model.Backend{ 2001 { 2002 Name: "infra-backend-v1", 2003 Namespace: "gateway-conformance-infra", 2004 Port: &model.BackendPort{ 2005 Port: 8080, 2006 }, 2007 }, 2008 }, 2009 Rewrite: &model.HTTPURLRewriteFilter{ 2010 Path: &model.StringMatch{ 2011 Exact: "/one", 2012 }, 2013 }, 2014 }, 2015 { 2016 PathMatch: model.StringMatch{Prefix: "/full/rewrite-path-and-modify-headers"}, 2017 Backends: []model.Backend{ 2018 { 2019 Name: "infra-backend-v1", 2020 Namespace: "gateway-conformance-infra", 2021 Port: &model.BackendPort{ 2022 Port: 8080, 2023 }, 2024 }, 2025 }, 2026 Rewrite: &model.HTTPURLRewriteFilter{ 2027 Path: &model.StringMatch{ 2028 Exact: "/test", 2029 }, 2030 }, 2031 RequestHeaderFilter: &model.HTTPHeaderFilter{ 2032 HeadersToAdd: []model.Header{ 2033 { 2034 Name: "X-Header-Add", 2035 Value: "header-val-1", 2036 }, 2037 { 2038 Name: "X-Header-Add-Append", 2039 Value: "header-val-2", 2040 }, 2041 }, 2042 HeadersToSet: []model.Header{ 2043 { 2044 Name: "X-Header-Set", 2045 Value: "set-overwrites-values", 2046 }, 2047 }, 2048 HeadersToRemove: []string{"X-Header-Remove"}, 2049 }, 2050 }, 2051 { 2052 PathMatch: model.StringMatch{Prefix: "/prefix/rewrite-path-and-modify-headers"}, 2053 Backends: []model.Backend{ 2054 { 2055 Name: "infra-backend-v1", 2056 Namespace: "gateway-conformance-infra", 2057 Port: &model.BackendPort{ 2058 Port: 8080, 2059 }, 2060 }, 2061 }, 2062 Rewrite: &model.HTTPURLRewriteFilter{ 2063 Path: &model.StringMatch{ 2064 Prefix: "/prefix", 2065 }, 2066 }, 2067 RequestHeaderFilter: &model.HTTPHeaderFilter{ 2068 HeadersToAdd: []model.Header{ 2069 { 2070 Name: "X-Header-Add", 2071 Value: "header-val-1", 2072 }, 2073 { 2074 Name: "X-Header-Add-Append", 2075 Value: "header-val-2", 2076 }, 2077 }, 2078 HeadersToSet: []model.Header{ 2079 { 2080 Name: "X-Header-Set", 2081 Value: "set-overwrites-values", 2082 }, 2083 }, 2084 HeadersToRemove: []string{"X-Header-Remove"}, 2085 }, 2086 }, 2087 }, 2088 }, 2089 } 2090 2091 var mirrorHTTPInput = Input{ 2092 GatewayClass: gatewayv1.GatewayClass{}, 2093 Gateway: sameNamespaceGateway, 2094 HTTPRoutes: mirrorPathHTTPRoutes, 2095 Services: allServices, 2096 } 2097 2098 var mirrorHTTPListeners = []model.HTTPListener{ 2099 { 2100 Name: "http", 2101 Sources: []model.FullyQualifiedResource{ 2102 { 2103 Name: "same-namespace", 2104 Namespace: "gateway-conformance-infra", 2105 }, 2106 }, 2107 Port: 80, 2108 Hostname: "*", 2109 Routes: []model.HTTPRoute{ 2110 { 2111 PathMatch: model.StringMatch{Prefix: "/mirror"}, 2112 Backends: []model.Backend{ 2113 { 2114 Name: "infra-backend-v1", 2115 Namespace: "gateway-conformance-infra", 2116 Port: &model.BackendPort{ 2117 Port: 8080, 2118 }, 2119 }, 2120 }, 2121 RequestMirrors: []*model.HTTPRequestMirror{ 2122 { 2123 Backend: &model.Backend{ 2124 Name: "infra-backend-v2", 2125 Namespace: "gateway-conformance-infra", 2126 Port: &model.BackendPort{ 2127 Port: 8080, 2128 }, 2129 }, 2130 }, 2131 }, 2132 }, 2133 }, 2134 }, 2135 } 2136 2137 var ( 2138 basicGRPC = Input{ 2139 GatewayClass: gatewayv1.GatewayClass{}, 2140 Gateway: gatewayv1.Gateway{ 2141 TypeMeta: metav1.TypeMeta{ 2142 Kind: "Gateway", 2143 APIVersion: "gateway.networking.k8s.io/v1beta1", 2144 }, 2145 ObjectMeta: metav1.ObjectMeta{ 2146 Name: "my-gateway", 2147 Namespace: "default", 2148 }, 2149 Spec: gatewayv1.GatewaySpec{ 2150 Listeners: []gatewayv1.Listener{ 2151 { 2152 Name: "prod-web-gw", 2153 Port: 80, 2154 Protocol: gatewayv1.HTTPProtocolType, 2155 }, 2156 }, 2157 }, 2158 }, 2159 GRPCRoutes: []gatewayv1.GRPCRoute{ 2160 { 2161 ObjectMeta: metav1.ObjectMeta{ 2162 Name: "grpc-route", 2163 Namespace: "default", 2164 }, 2165 Spec: gatewayv1.GRPCRouteSpec{ 2166 CommonRouteSpec: gatewayv1.CommonRouteSpec{ 2167 ParentRefs: []gatewayv1.ParentReference{ 2168 { 2169 Name: "my-gateway", 2170 }, 2171 }, 2172 }, 2173 Hostnames: []gatewayv1.Hostname{ 2174 "example.com", 2175 }, 2176 Rules: []gatewayv1.GRPCRouteRule{ 2177 { 2178 Matches: []gatewayv1.GRPCRouteMatch{ 2179 { 2180 Method: &gatewayv1.GRPCMethodMatch{ 2181 Type: model.AddressOf[gatewayv1.GRPCMethodMatchType](gatewayv1.GRPCMethodMatchExact), 2182 Service: model.AddressOf("service.Echo"), 2183 Method: model.AddressOf("Ping"), 2184 }, 2185 }, 2186 }, 2187 BackendRefs: []gatewayv1.GRPCBackendRef{ 2188 { 2189 BackendRef: gatewayv1.BackendRef{ 2190 BackendObjectReference: gatewayv1.BackendObjectReference{ 2191 Name: "grp-service", 2192 Port: model.AddressOf[gatewayv1.PortNumber](8080), 2193 }, 2194 }, 2195 }, 2196 }, 2197 }, 2198 }, 2199 }, 2200 }, 2201 }, 2202 Services: []corev1.Service{ 2203 { 2204 ObjectMeta: metav1.ObjectMeta{ 2205 Name: "grp-service", 2206 Namespace: "default", 2207 }, 2208 }, 2209 }, 2210 } 2211 2212 basicGRPCListeners = []model.HTTPListener{ 2213 { 2214 Name: "prod-web-gw", 2215 Sources: []model.FullyQualifiedResource{ 2216 { 2217 Name: "my-gateway", 2218 Namespace: "default", 2219 Group: "gateway.networking.k8s.io", 2220 Version: "v1beta1", 2221 Kind: "Gateway", 2222 }, 2223 }, 2224 Address: "", 2225 Port: 80, 2226 Hostname: "*", 2227 Routes: []model.HTTPRoute{ 2228 { 2229 Hostnames: []string{"example.com"}, 2230 PathMatch: model.StringMatch{ 2231 Exact: "/service.Echo/Ping", 2232 }, 2233 Backends: []model.Backend{ 2234 { 2235 Name: "grp-service", 2236 Namespace: "default", 2237 Port: &model.BackendPort{ 2238 Port: 8080, 2239 }, 2240 }, 2241 }, 2242 IsGRPC: true, 2243 }, 2244 }, 2245 }, 2246 } 2247 ) 2248 2249 func TestHTTPGatewayAPI(t *testing.T) { 2250 tests := map[string]struct { 2251 input Input 2252 want []model.HTTPListener 2253 }{ 2254 "basic http": { 2255 input: basicHTTP, 2256 want: basicHTTPListeners, 2257 }, 2258 "Conformance/HTTPRouteSimpleSameNamespace": { 2259 input: simpleSameNamespaceHTTPInput, 2260 want: simpleSameNamespaceHTTPListeners, 2261 }, 2262 "Conformance/HTTPRouteCrossNamespace": { 2263 input: crossNamespaceHTTPInput, 2264 want: crossNamespaceHTTPListeners, 2265 }, 2266 "Conformance/HTTPExactPathMatching": { 2267 input: exactPathMatchingHTTPInput, 2268 want: exactPathMatchingHTTPListeners, 2269 }, 2270 "Conformance/HTTPRouteHeaderMatching": { 2271 input: headerMatchingHTTPInput, 2272 want: headerMatchingHTTPListeners, 2273 }, 2274 "Conformance/HTTPRouteHostnameIntersection": { 2275 input: hostnameIntersectionHTTPInput, 2276 want: hostnameIntersectionHTTPListeners, 2277 }, 2278 "Conformance/HTTPRouteListenerHostnameMatching": { 2279 input: listenerHostnameMatchingHTTPInput, 2280 want: listenerHostnameMatchingHTTPListeners, 2281 }, 2282 "Conformance/HTTPRouteMatchingAcrossRoutes": { 2283 input: matchingAcrossHTTPInput, 2284 want: matchingAcrossHTTPListeners, 2285 }, 2286 "Conformance/HTTPRouteMatching": { 2287 input: matchingHTTPInput, 2288 want: matchingHTTPListeners, 2289 }, 2290 "Conformance/HTTPRouteMethodMatching": { 2291 input: methodMatchingHTTPInput, 2292 want: methodMatchingHTTPListeners, 2293 }, 2294 "Conformance/HTTPRouteQueryParamMatching": { 2295 input: queryParamMatchingHTTPInput, 2296 want: queryParamMatchingHTTPListeners, 2297 }, 2298 "Conformance/HTTPRouteRequestHeaderModifier": { 2299 input: requestHeaderModifierHTTPInput, 2300 want: requestHeaderModifierHTTPListeners, 2301 }, 2302 "Conformance/HTTPRouteBackendRefsRequestHeaderModifier": { 2303 input: backendRefsRequestHeaderModifierHTTPInput, 2304 want: backendRefsRequestHeaderModifierHTTPListeners, 2305 }, 2306 "Conformance/HTTPRouteRequestRedirect": { 2307 input: requestRedirectHTTPInput, 2308 want: requestRedirectHTTPListeners, 2309 }, 2310 "Conformance/HTTPRouteResponseHeaderModifier": { 2311 input: responseHeaderModifierHTTPInput, 2312 want: responseHeaderModifierHTTPListeners, 2313 }, 2314 "Conformance/HTTPRouteBackendRefsResponseHeaderModifier": { 2315 input: backendRefsResponseHeaderModifierHTTPInput, 2316 want: backendRefsResponseHeaderModifierHTTPListeners, 2317 }, 2318 "Conformance/HTTPRouteRewriteHost": { 2319 input: rewriteHostHTTPInput, 2320 want: rewriteHostHTTPListeners, 2321 }, 2322 "Conformance/HTTPRouteRewritePath": { 2323 input: rewritePathHTTPInput, 2324 want: rewritePathHTTPListeners, 2325 }, 2326 "Conformance/HTTPRouteRequestMirror": { 2327 input: mirrorHTTPInput, 2328 want: mirrorHTTPListeners, 2329 }, 2330 } 2331 2332 for name, tc := range tests { 2333 t.Run(name, func(t *testing.T) { 2334 listeners, _ := GatewayAPI(tc.input) 2335 assert.Equal(t, tc.want, listeners, "Listeners did not match") 2336 }) 2337 } 2338 } 2339 2340 func TestTLSGatewayAPI(t *testing.T) { 2341 tests := map[string]struct { 2342 input Input 2343 want []model.TLSPassthroughListener 2344 }{ 2345 "basic http": { 2346 input: basicTLS, 2347 want: basicTLSListeners, 2348 }, 2349 "Conformance/TLSRouteSimpleSameNamespace": { 2350 input: simpleSameNamespaceTLS, 2351 want: simpleSameNamespaceTLSListeners, 2352 }, 2353 } 2354 2355 for name, tc := range tests { 2356 t.Run(name, func(t *testing.T) { 2357 _, listeners := GatewayAPI(tc.input) 2358 assert.Equal(t, tc.want, listeners, "Listeners did not match") 2359 }) 2360 } 2361 } 2362 2363 func TestGRPCGatewayAPI(t *testing.T) { 2364 tests := map[string]struct { 2365 input Input 2366 want []model.HTTPListener 2367 }{ 2368 "basic grpc": { 2369 input: basicGRPC, 2370 want: basicGRPCListeners, 2371 }, 2372 } 2373 2374 for name, tc := range tests { 2375 t.Run(name, func(t *testing.T) { 2376 listeners, _ := GatewayAPI(tc.input) 2377 assert.Equal(t, tc.want, listeners, "Listeners did not match") 2378 }) 2379 } 2380 }