sigs.k8s.io/external-dns@v0.14.1/source/istio_virtualservice_test.go (about) 1 /* 2 Copyright 2020 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 source 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 24 "github.com/pkg/errors" 25 "github.com/stretchr/testify/assert" 26 "github.com/stretchr/testify/require" 27 "github.com/stretchr/testify/suite" 28 "istio.io/api/meta/v1alpha1" 29 istionetworking "istio.io/api/networking/v1alpha3" 30 networkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3" 31 istiofake "istio.io/client-go/pkg/clientset/versioned/fake" 32 fakenetworking3 "istio.io/client-go/pkg/clientset/versioned/typed/networking/v1alpha3/fake" 33 v1 "k8s.io/api/core/v1" 34 networkv1 "k8s.io/api/networking/v1" 35 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 36 "k8s.io/apimachinery/pkg/runtime" 37 "k8s.io/client-go/kubernetes/fake" 38 k8sclienttesting "k8s.io/client-go/testing" 39 40 "sigs.k8s.io/external-dns/endpoint" 41 ) 42 43 // This is a compile-time validation that istioVirtualServiceSource is a Source. 44 var _ Source = &virtualServiceSource{} 45 46 type VirtualServiceSuite struct { 47 suite.Suite 48 source Source 49 lbServices []*v1.Service 50 ingresses []*networkv1.Ingress 51 gwconfig *networkingv1alpha3.Gateway 52 vsconfig *networkingv1alpha3.VirtualService 53 } 54 55 func (suite *VirtualServiceSuite) SetupTest() { 56 fakeKubernetesClient := fake.NewSimpleClientset() 57 fakeIstioClient := istiofake.NewSimpleClientset() 58 var err error 59 60 suite.lbServices = []*v1.Service{ 61 (fakeIngressGatewayService{ 62 ips: []string{"8.8.8.8"}, 63 hostnames: []string{"v1"}, 64 namespace: "istio-system", 65 name: "istio-gateway1", 66 }).Service(), 67 (fakeIngressGatewayService{ 68 ips: []string{"1.1.1.1"}, 69 hostnames: []string{"v42"}, 70 namespace: "istio-system", 71 name: "istio-gateway2", 72 }).Service(), 73 } 74 75 for _, service := range suite.lbServices { 76 _, err = fakeKubernetesClient.CoreV1().Services(service.Namespace).Create(context.Background(), service, metav1.CreateOptions{}) 77 suite.NoError(err, "should succeed") 78 } 79 80 suite.ingresses = []*networkv1.Ingress{ 81 (fakeIngress{ 82 ips: []string{"2.2.2.2"}, 83 hostnames: []string{"v2"}, 84 namespace: "istio-system", 85 name: "istio-ingress", 86 }).Ingress(), 87 (fakeIngress{ 88 ips: []string{"3.3.3.3"}, 89 hostnames: []string{"v62"}, 90 namespace: "istio-system", 91 name: "istio-ingress2", 92 }).Ingress(), 93 } 94 95 for _, ingress := range suite.ingresses { 96 _, err = fakeKubernetesClient.NetworkingV1().Ingresses(ingress.Namespace).Create(context.Background(), ingress, metav1.CreateOptions{}) 97 suite.NoError(err, "should succeed") 98 } 99 100 suite.gwconfig = (fakeGatewayConfig{ 101 name: "foo-gateway-with-targets", 102 namespace: "istio-system", 103 dnsnames: [][]string{{"*"}}, 104 }).Config() 105 _, err = fakeIstioClient.NetworkingV1alpha3().Gateways(suite.gwconfig.Namespace).Create(context.Background(), suite.gwconfig, metav1.CreateOptions{}) 106 suite.NoError(err, "should succeed") 107 108 suite.vsconfig = (fakeVirtualServiceConfig{ 109 name: "foo-virtualservice", 110 namespace: "istio-other", 111 gateways: []string{"istio-system/foo-gateway-with-targets"}, 112 dnsnames: []string{"foo"}, 113 }).Config() 114 _, err = fakeIstioClient.NetworkingV1alpha3().VirtualServices(suite.vsconfig.Namespace).Create(context.Background(), suite.vsconfig, metav1.CreateOptions{}) 115 suite.NoError(err, "should succeed") 116 117 suite.source, err = NewIstioVirtualServiceSource( 118 context.TODO(), 119 fakeKubernetesClient, 120 fakeIstioClient, 121 "", 122 "", 123 "{{.Name}}", 124 false, 125 false, 126 ) 127 suite.NoError(err, "should initialize virtualservice source") 128 } 129 130 func (suite *VirtualServiceSuite) TestResourceLabelIsSet() { 131 endpoints, err := suite.source.Endpoints(context.Background()) 132 suite.NoError(err, "should succeed") 133 suite.Equal(len(endpoints), 2, "should return the correct number of endpoints") 134 for _, ep := range endpoints { 135 suite.Equal("virtualservice/istio-other/foo-virtualservice", ep.Labels[endpoint.ResourceLabelKey], "should set correct resource label") 136 } 137 } 138 139 func TestVirtualService(t *testing.T) { 140 t.Parallel() 141 142 suite.Run(t, new(VirtualServiceSuite)) 143 t.Run("virtualServiceBindsToGateway", testVirtualServiceBindsToGateway) 144 t.Run("endpointsFromVirtualServiceConfig", testEndpointsFromVirtualServiceConfig) 145 t.Run("Endpoints", testVirtualServiceEndpoints) 146 t.Run("gatewaySelectorMatchesService", testGatewaySelectorMatchesService) 147 } 148 149 func TestNewIstioVirtualServiceSource(t *testing.T) { 150 t.Parallel() 151 152 for _, ti := range []struct { 153 title string 154 annotationFilter string 155 fqdnTemplate string 156 combineFQDNAndAnnotation bool 157 expectError bool 158 }{ 159 { 160 title: "invalid template", 161 expectError: true, 162 fqdnTemplate: "{{.Name", 163 }, 164 { 165 title: "valid empty template", 166 expectError: false, 167 }, 168 { 169 title: "valid template", 170 expectError: false, 171 fqdnTemplate: "{{.Name}}-{{.Namespace}}.ext-dns.test.com", 172 }, 173 { 174 title: "valid template", 175 expectError: false, 176 fqdnTemplate: "{{.Name}}-{{.Namespace}}.ext-dns.test.com, {{.Name}}-{{.Namespace}}.ext-dna.test.com", 177 }, 178 { 179 title: "valid template", 180 expectError: false, 181 fqdnTemplate: "{{.Name}}-{{.Namespace}}.ext-dns.test.com, {{.Name}}-{{.Namespace}}.ext-dna.test.com", 182 combineFQDNAndAnnotation: true, 183 }, 184 { 185 title: "non-empty annotation filter label", 186 expectError: false, 187 annotationFilter: "kubernetes.io/gateway.class=nginx", 188 }, 189 } { 190 ti := ti 191 t.Run(ti.title, func(t *testing.T) { 192 t.Parallel() 193 194 _, err := NewIstioVirtualServiceSource( 195 context.TODO(), 196 fake.NewSimpleClientset(), 197 istiofake.NewSimpleClientset(), 198 "", 199 ti.annotationFilter, 200 ti.fqdnTemplate, 201 ti.combineFQDNAndAnnotation, 202 false, 203 ) 204 if ti.expectError { 205 assert.Error(t, err) 206 } else { 207 assert.NoError(t, err) 208 } 209 }) 210 } 211 } 212 213 func testVirtualServiceBindsToGateway(t *testing.T) { 214 for _, ti := range []struct { 215 title string 216 gwconfig fakeGatewayConfig 217 vsconfig fakeVirtualServiceConfig 218 vsHost string 219 expected bool 220 }{ 221 { 222 title: "matching host *", 223 gwconfig: fakeGatewayConfig{ 224 dnsnames: [][]string{{"*"}}, 225 }, 226 vsconfig: fakeVirtualServiceConfig{}, 227 vsHost: "foo.bar", 228 expected: true, 229 }, 230 { 231 title: "matching host *.<domain>", 232 gwconfig: fakeGatewayConfig{ 233 dnsnames: [][]string{{"*.foo.bar"}}, 234 }, 235 vsconfig: fakeVirtualServiceConfig{}, 236 vsHost: "baz.foo.bar", 237 expected: true, 238 }, 239 { 240 title: "not matching host *.<domain>", 241 gwconfig: fakeGatewayConfig{ 242 dnsnames: [][]string{{"*.foo.bar"}}, 243 }, 244 vsconfig: fakeVirtualServiceConfig{}, 245 vsHost: "foo.bar", 246 expected: false, 247 }, 248 { 249 title: "not matching host *.<domain>", 250 gwconfig: fakeGatewayConfig{ 251 dnsnames: [][]string{{"*.foo.bar"}}, 252 }, 253 vsconfig: fakeVirtualServiceConfig{}, 254 vsHost: "bazfoo.bar", 255 expected: false, 256 }, 257 { 258 title: "not matching host *.<domain>", 259 gwconfig: fakeGatewayConfig{ 260 dnsnames: [][]string{{"*.foo.bar"}}, 261 }, 262 vsconfig: fakeVirtualServiceConfig{}, 263 vsHost: "*foo.bar", 264 expected: false, 265 }, 266 { 267 title: "matching host */*", 268 gwconfig: fakeGatewayConfig{ 269 dnsnames: [][]string{{"*/*"}}, 270 }, 271 vsconfig: fakeVirtualServiceConfig{}, 272 vsHost: "foo.bar", 273 expected: true, 274 }, 275 { 276 title: "matching host <namespace>/*", 277 gwconfig: fakeGatewayConfig{ 278 namespace: "istio-system", 279 dnsnames: [][]string{{"myns/*"}}, 280 }, 281 vsconfig: fakeVirtualServiceConfig{ 282 namespace: "myns", 283 }, 284 vsHost: "foo.bar", 285 expected: true, 286 }, 287 { 288 title: "matching host ./*", 289 gwconfig: fakeGatewayConfig{ 290 namespace: "istio-system", 291 dnsnames: [][]string{{"./*"}}, 292 }, 293 vsconfig: fakeVirtualServiceConfig{ 294 namespace: "istio-system", 295 }, 296 vsHost: "foo.bar", 297 expected: true, 298 }, 299 { 300 title: "not matching host ./*", 301 gwconfig: fakeGatewayConfig{ 302 namespace: "istio-system", 303 dnsnames: [][]string{{"./*"}}, 304 }, 305 vsconfig: fakeVirtualServiceConfig{ 306 namespace: "myns", 307 }, 308 vsHost: "foo.bar", 309 expected: false, 310 }, 311 { 312 title: "not matching host <namespace>/*", 313 gwconfig: fakeGatewayConfig{ 314 namespace: "istio-system", 315 dnsnames: [][]string{{"myns/*"}}, 316 }, 317 vsconfig: fakeVirtualServiceConfig{ 318 namespace: "otherns", 319 }, 320 vsHost: "foo.bar", 321 expected: false, 322 }, 323 { 324 title: "not matching host <namespace>/*", 325 gwconfig: fakeGatewayConfig{ 326 namespace: "istio-system", 327 dnsnames: [][]string{{"myns/*"}}, 328 }, 329 vsconfig: fakeVirtualServiceConfig{ 330 namespace: "otherns", 331 }, 332 vsHost: "foo.bar", 333 expected: false, 334 }, 335 { 336 title: "matching exportTo *", 337 gwconfig: fakeGatewayConfig{ 338 namespace: "istio-system", 339 dnsnames: [][]string{{"*"}}, 340 }, 341 vsconfig: fakeVirtualServiceConfig{ 342 namespace: "otherns", 343 exportTo: "*", 344 }, 345 vsHost: "foo.bar", 346 expected: true, 347 }, 348 { 349 title: "matching exportTo <namespace>", 350 gwconfig: fakeGatewayConfig{ 351 namespace: "istio-system", 352 dnsnames: [][]string{{"*"}}, 353 }, 354 vsconfig: fakeVirtualServiceConfig{ 355 namespace: "otherns", 356 exportTo: "istio-system", 357 }, 358 vsHost: "foo.bar", 359 expected: true, 360 }, 361 { 362 title: "not matching exportTo <namespace>", 363 gwconfig: fakeGatewayConfig{ 364 namespace: "istio-system", 365 dnsnames: [][]string{{"*"}}, 366 }, 367 vsconfig: fakeVirtualServiceConfig{ 368 namespace: "otherns", 369 exportTo: "myns", 370 }, 371 vsHost: "foo.bar", 372 expected: false, 373 }, 374 { 375 title: "not matching exportTo .", 376 gwconfig: fakeGatewayConfig{ 377 namespace: "istio-system", 378 dnsnames: [][]string{{"*"}}, 379 }, 380 vsconfig: fakeVirtualServiceConfig{ 381 namespace: "otherns", 382 exportTo: ".", 383 }, 384 vsHost: "foo.bar", 385 expected: false, 386 }, 387 } { 388 t.Run(ti.title, func(t *testing.T) { 389 vsconfig := ti.vsconfig.Config() 390 gwconfig := ti.gwconfig.Config() 391 require.Equal(t, ti.expected, virtualServiceBindsToGateway(vsconfig, gwconfig, ti.vsHost)) 392 }) 393 } 394 } 395 396 func testEndpointsFromVirtualServiceConfig(t *testing.T) { 397 t.Parallel() 398 399 for _, ti := range []struct { 400 title string 401 lbServices []fakeIngressGatewayService 402 ingresses []fakeIngress 403 gwconfig fakeGatewayConfig 404 vsconfig fakeVirtualServiceConfig 405 expected []*endpoint.Endpoint 406 }{ 407 { 408 title: "one rule.host one lb.hostname", 409 lbServices: []fakeIngressGatewayService{ 410 { 411 hostnames: []string{"lb.com"}, // Kubernetes omits the trailing dot 412 }, 413 }, 414 gwconfig: fakeGatewayConfig{ 415 name: "mygw", 416 dnsnames: [][]string{{"*"}}, 417 }, 418 vsconfig: fakeVirtualServiceConfig{ 419 gateways: []string{"mygw"}, 420 dnsnames: []string{"foo.bar"}, 421 }, 422 expected: []*endpoint.Endpoint{ 423 { 424 DNSName: "foo.bar", 425 RecordType: endpoint.RecordTypeCNAME, 426 Targets: endpoint.Targets{"lb.com"}, 427 }, 428 }, 429 }, 430 { 431 title: "one rule.host one lb.IP", 432 lbServices: []fakeIngressGatewayService{ 433 { 434 ips: []string{"8.8.8.8"}, 435 }, 436 }, 437 gwconfig: fakeGatewayConfig{ 438 name: "mygw", 439 dnsnames: [][]string{{"*"}}, 440 }, 441 vsconfig: fakeVirtualServiceConfig{ 442 gateways: []string{"mygw"}, 443 dnsnames: []string{"foo.bar"}, 444 }, 445 expected: []*endpoint.Endpoint{ 446 { 447 DNSName: "foo.bar", 448 RecordType: endpoint.RecordTypeA, 449 Targets: endpoint.Targets{"8.8.8.8"}, 450 }, 451 }, 452 }, 453 { 454 title: "one rule.host one lb.externalIPs", 455 lbServices: []fakeIngressGatewayService{ 456 { 457 externalIPs: []string{"8.8.8.8"}, 458 }, 459 }, 460 gwconfig: fakeGatewayConfig{ 461 name: "mygw", 462 dnsnames: [][]string{{"*"}}, 463 }, 464 vsconfig: fakeVirtualServiceConfig{ 465 gateways: []string{"mygw"}, 466 dnsnames: []string{"foo.bar"}, 467 }, 468 expected: []*endpoint.Endpoint{ 469 { 470 DNSName: "foo.bar", 471 RecordType: endpoint.RecordTypeA, 472 Targets: endpoint.Targets{"8.8.8.8"}, 473 }, 474 }, 475 }, 476 { 477 title: "one rule.host two lb.IP and two lb.Hostname", 478 lbServices: []fakeIngressGatewayService{ 479 { 480 ips: []string{"8.8.8.8", "127.0.0.1"}, 481 hostnames: []string{"elb.com", "alb.com"}, 482 }, 483 }, 484 gwconfig: fakeGatewayConfig{ 485 name: "mygw", 486 dnsnames: [][]string{{"*"}}, 487 }, 488 vsconfig: fakeVirtualServiceConfig{ 489 gateways: []string{"mygw"}, 490 dnsnames: []string{"foo.bar"}, 491 }, 492 expected: []*endpoint.Endpoint{ 493 { 494 DNSName: "foo.bar", 495 RecordType: endpoint.RecordTypeA, 496 Targets: endpoint.Targets{"8.8.8.8", "127.0.0.1"}, 497 }, 498 { 499 DNSName: "foo.bar", 500 RecordType: endpoint.RecordTypeCNAME, 501 Targets: endpoint.Targets{"elb.com", "alb.com"}, 502 }, 503 }, 504 }, 505 { 506 title: "one rule.host two lb.IP and two lb.Hostname and two lb.externalIPs", 507 lbServices: []fakeIngressGatewayService{ 508 { 509 ips: []string{"8.8.8.8", "127.0.0.1"}, 510 hostnames: []string{"elb.com", "alb.com"}, 511 externalIPs: []string{"1.1.1.1", "2.2.2.2"}, 512 }, 513 }, 514 gwconfig: fakeGatewayConfig{ 515 name: "mygw", 516 dnsnames: [][]string{{"*"}}, 517 }, 518 vsconfig: fakeVirtualServiceConfig{ 519 gateways: []string{"mygw"}, 520 dnsnames: []string{"foo.bar"}, 521 }, 522 expected: []*endpoint.Endpoint{ 523 { 524 DNSName: "foo.bar", 525 RecordType: endpoint.RecordTypeA, 526 Targets: endpoint.Targets{"1.1.1.1", "2.2.2.2"}, 527 }, 528 }, 529 }, 530 { 531 title: "no rule.host", 532 lbServices: []fakeIngressGatewayService{ 533 { 534 ips: []string{"8.8.8.8", "127.0.0.1"}, 535 hostnames: []string{"elb.com", "alb.com"}, 536 externalIPs: []string{"1.1.1.1", "2.2.2.2"}, 537 }, 538 }, 539 gwconfig: fakeGatewayConfig{ 540 name: "mygw", 541 dnsnames: [][]string{{"*"}}, 542 }, 543 vsconfig: fakeVirtualServiceConfig{ 544 gateways: []string{"mygw"}, 545 dnsnames: []string{}, 546 }, 547 expected: []*endpoint.Endpoint{}, 548 }, 549 { 550 title: "no rule.gateway", 551 lbServices: []fakeIngressGatewayService{ 552 { 553 ips: []string{"8.8.8.8", "127.0.0.1"}, 554 hostnames: []string{"elb.com", "alb.com"}, 555 externalIPs: []string{"1.1.1.1", "2.2.2.2"}, 556 }, 557 }, 558 gwconfig: fakeGatewayConfig{ 559 name: "mygw", 560 dnsnames: [][]string{{"*"}}, 561 }, 562 vsconfig: fakeVirtualServiceConfig{ 563 gateways: []string{}, 564 dnsnames: []string{"foo.bar"}, 565 }, 566 expected: []*endpoint.Endpoint{}, 567 }, 568 { 569 title: "one empty rule.host", 570 lbServices: []fakeIngressGatewayService{ 571 { 572 ips: []string{"8.8.8.8", "127.0.0.1"}, 573 hostnames: []string{"elb.com", "alb.com"}, 574 externalIPs: []string{"1.1.1.1", "2.2.2.2"}, 575 }, 576 }, 577 gwconfig: fakeGatewayConfig{ 578 dnsnames: [][]string{ 579 {""}, 580 }, 581 }, 582 expected: []*endpoint.Endpoint{}, 583 }, 584 { 585 title: "no targets", 586 lbServices: []fakeIngressGatewayService{{}}, 587 gwconfig: fakeGatewayConfig{ 588 name: "mygw", 589 dnsnames: [][]string{{"*"}}, 590 }, 591 vsconfig: fakeVirtualServiceConfig{ 592 gateways: []string{}, 593 dnsnames: []string{"foo.bar"}, 594 }, 595 expected: []*endpoint.Endpoint{}, 596 }, 597 { 598 title: "matching selectors for service and gateway", 599 lbServices: []fakeIngressGatewayService{ 600 { 601 name: "service1", 602 selector: map[string]string{ 603 "app": "myservice", 604 }, 605 hostnames: []string{"elb.com", "alb.com"}, 606 }, 607 { 608 name: "service2", 609 selector: map[string]string{ 610 "app": "otherservice", 611 }, 612 ips: []string{"8.8.8.8", "127.0.0.1"}, 613 }, 614 }, 615 gwconfig: fakeGatewayConfig{ 616 name: "mygw", 617 dnsnames: [][]string{{"*"}}, 618 selector: map[string]string{ 619 "app": "myservice", 620 }, 621 }, 622 vsconfig: fakeVirtualServiceConfig{ 623 gateways: []string{"mygw"}, 624 dnsnames: []string{"foo.bar"}, 625 }, 626 expected: []*endpoint.Endpoint{ 627 { 628 DNSName: "foo.bar", 629 RecordType: endpoint.RecordTypeCNAME, 630 Targets: endpoint.Targets{"elb.com", "alb.com"}, 631 }, 632 }, 633 }, 634 { 635 title: "ingress gateway annotation same namespace", 636 ingresses: []fakeIngress{ 637 { 638 name: "ingress1", 639 hostnames: []string{"alb.com", "elb.com"}, 640 }, 641 { 642 name: "ingress2", 643 ips: []string{"127.0.0.1", "8.8.8.8"}, 644 }, 645 }, 646 gwconfig: fakeGatewayConfig{ 647 name: "mygw", 648 dnsnames: [][]string{{"*"}}, 649 annotations: map[string]string{ 650 IstioGatewayIngressSource: "ingress1", 651 }, 652 }, 653 vsconfig: fakeVirtualServiceConfig{ 654 gateways: []string{"mygw"}, 655 dnsnames: []string{"foo.bar"}, 656 }, 657 expected: []*endpoint.Endpoint{ 658 { 659 DNSName: "foo.bar", 660 RecordType: endpoint.RecordTypeCNAME, 661 Targets: endpoint.Targets{"alb.com", "elb.com"}, 662 }, 663 }, 664 }, 665 { 666 title: "ingress gateway annotation separate namespace", 667 ingresses: []fakeIngress{ 668 { 669 name: "ingress1", 670 namespace: "ingress", 671 hostnames: []string{"alb.com", "elb.com"}, 672 }, 673 { 674 name: "ingress2", 675 namespace: "ingress", 676 ips: []string{"127.0.0.1", "8.8.8.8"}, 677 }, 678 }, 679 gwconfig: fakeGatewayConfig{ 680 name: "mygw", 681 dnsnames: [][]string{{"*"}}, 682 annotations: map[string]string{ 683 IstioGatewayIngressSource: "ingress/ingress2", 684 }, 685 }, 686 vsconfig: fakeVirtualServiceConfig{ 687 gateways: []string{"mygw"}, 688 dnsnames: []string{"foo.bar"}, 689 }, 690 expected: []*endpoint.Endpoint{ 691 { 692 DNSName: "foo.bar", 693 RecordType: endpoint.RecordTypeA, 694 Targets: endpoint.Targets{"127.0.0.1", "8.8.8.8"}, 695 }, 696 }, 697 }, 698 } { 699 ti := ti 700 t.Run(ti.title, func(t *testing.T) { 701 t.Parallel() 702 703 if source, err := newTestVirtualServiceSource(ti.lbServices, ti.ingresses, []fakeGatewayConfig{ti.gwconfig}); err != nil { 704 require.NoError(t, err) 705 } else if endpoints, err := source.endpointsFromVirtualService(context.Background(), ti.vsconfig.Config()); err != nil { 706 require.NoError(t, err) 707 } else { 708 validateEndpoints(t, endpoints, ti.expected) 709 } 710 }) 711 } 712 } 713 714 func testVirtualServiceEndpoints(t *testing.T) { 715 t.Parallel() 716 717 namespace := "testing" 718 for _, ti := range []struct { 719 title string 720 targetNamespace string 721 annotationFilter string 722 lbServices []fakeIngressGatewayService 723 ingresses []fakeIngress 724 gwConfigs []fakeGatewayConfig 725 vsConfigs []fakeVirtualServiceConfig 726 expected []*endpoint.Endpoint 727 expectError bool 728 fqdnTemplate string 729 combineFQDNAndAnnotation bool 730 ignoreHostnameAnnotation bool 731 }{ 732 { 733 title: "two simple virtualservices with one gateway each, one ingressgateway loadbalancer service", 734 lbServices: []fakeIngressGatewayService{ 735 { 736 namespace: namespace, 737 ips: []string{"8.8.8.8"}, 738 hostnames: []string{"lb.com"}, 739 }, 740 }, 741 gwConfigs: []fakeGatewayConfig{ 742 { 743 name: "fake1", 744 namespace: namespace, 745 dnsnames: [][]string{{"example.org"}}, 746 }, 747 { 748 name: "fake2", 749 namespace: namespace, 750 dnsnames: [][]string{{"new.org"}}, 751 }, 752 }, 753 vsConfigs: []fakeVirtualServiceConfig{ 754 { 755 name: "vs1", 756 namespace: namespace, 757 gateways: []string{"fake1"}, 758 dnsnames: []string{"example.org"}, 759 }, 760 { 761 name: "vs2", 762 namespace: namespace, 763 gateways: []string{"fake2"}, 764 dnsnames: []string{"new.org"}, 765 }, 766 }, 767 expected: []*endpoint.Endpoint{ 768 { 769 DNSName: "example.org", 770 RecordType: endpoint.RecordTypeA, 771 Targets: endpoint.Targets{"8.8.8.8"}, 772 }, 773 { 774 DNSName: "example.org", 775 RecordType: endpoint.RecordTypeCNAME, 776 Targets: endpoint.Targets{"lb.com"}, 777 }, 778 { 779 DNSName: "new.org", 780 RecordType: endpoint.RecordTypeA, 781 Targets: endpoint.Targets{"8.8.8.8"}, 782 }, 783 { 784 DNSName: "new.org", 785 RecordType: endpoint.RecordTypeCNAME, 786 Targets: endpoint.Targets{"lb.com"}, 787 }, 788 }, 789 }, 790 { 791 title: "two simple virtualservices with one gateway each, one ingress", 792 lbServices: []fakeIngressGatewayService{ 793 { 794 namespace: namespace, 795 ips: []string{"8.8.8.8"}, 796 hostnames: []string{"lb.com"}, 797 }, 798 }, 799 ingresses: []fakeIngress{ 800 { 801 name: "ingress1", 802 namespace: namespace, 803 ips: []string{"8.8.8.8"}, 804 hostnames: []string{"lb.com"}, 805 }, 806 }, 807 gwConfigs: []fakeGatewayConfig{ 808 { 809 name: "fake1", 810 namespace: namespace, 811 dnsnames: [][]string{{"example.org"}}, 812 annotations: map[string]string{ 813 IstioGatewayIngressSource: "ingress1", 814 }, 815 }, 816 { 817 name: "fake2", 818 namespace: namespace, 819 dnsnames: [][]string{{"new.org"}}, 820 annotations: map[string]string{ 821 IstioGatewayIngressSource: "ingress1", 822 }, 823 }, 824 }, 825 vsConfigs: []fakeVirtualServiceConfig{ 826 { 827 name: "vs1", 828 namespace: namespace, 829 gateways: []string{"fake1"}, 830 dnsnames: []string{"example.org"}, 831 }, 832 { 833 name: "vs2", 834 namespace: namespace, 835 gateways: []string{"fake2"}, 836 dnsnames: []string{"new.org"}, 837 }, 838 }, 839 expected: []*endpoint.Endpoint{ 840 { 841 DNSName: "example.org", 842 RecordType: endpoint.RecordTypeA, 843 Targets: endpoint.Targets{"8.8.8.8"}, 844 }, 845 { 846 DNSName: "example.org", 847 RecordType: endpoint.RecordTypeCNAME, 848 Targets: endpoint.Targets{"lb.com"}, 849 }, 850 { 851 DNSName: "new.org", 852 RecordType: endpoint.RecordTypeA, 853 Targets: endpoint.Targets{"8.8.8.8"}, 854 }, 855 { 856 DNSName: "new.org", 857 RecordType: endpoint.RecordTypeCNAME, 858 Targets: endpoint.Targets{"lb.com"}, 859 }, 860 }, 861 }, 862 { 863 title: "one virtualservice with two gateways, one ingressgateway loadbalancer service", 864 lbServices: []fakeIngressGatewayService{ 865 { 866 namespace: namespace, 867 ips: []string{"8.8.8.8"}, 868 }, 869 }, 870 gwConfigs: []fakeGatewayConfig{ 871 { 872 name: "gw1", 873 namespace: namespace, 874 dnsnames: [][]string{{"*"}}, 875 }, 876 { 877 name: "gw2", 878 namespace: namespace, 879 dnsnames: [][]string{{"*"}}, 880 }, 881 }, 882 vsConfigs: []fakeVirtualServiceConfig{ 883 { 884 name: "vs", 885 namespace: namespace, 886 gateways: []string{"gw1", "gw2"}, 887 dnsnames: []string{"example.org"}, 888 }, 889 }, 890 expected: []*endpoint.Endpoint{ 891 { 892 DNSName: "example.org", 893 RecordType: endpoint.RecordTypeA, 894 Targets: endpoint.Targets{"8.8.8.8"}, 895 }, 896 }, 897 }, 898 { 899 title: "one virtualservice with two gateways, one ingressgateway loadbalancer service with externalIPs", 900 lbServices: []fakeIngressGatewayService{ 901 { 902 namespace: namespace, 903 externalIPs: []string{"8.8.8.8"}, 904 }, 905 }, 906 gwConfigs: []fakeGatewayConfig{ 907 { 908 name: "gw1", 909 namespace: namespace, 910 dnsnames: [][]string{{"*"}}, 911 }, 912 { 913 name: "gw2", 914 namespace: namespace, 915 dnsnames: [][]string{{"*"}}, 916 }, 917 }, 918 vsConfigs: []fakeVirtualServiceConfig{ 919 { 920 name: "vs", 921 namespace: namespace, 922 gateways: []string{"gw1", "gw2"}, 923 dnsnames: []string{"example.org"}, 924 }, 925 }, 926 expected: []*endpoint.Endpoint{ 927 { 928 DNSName: "example.org", 929 RecordType: endpoint.RecordTypeA, 930 Targets: endpoint.Targets{"8.8.8.8"}, 931 }, 932 }, 933 }, 934 { 935 title: "two simple virtualservices on different namespaces with the same target gateway, one ingressgateway loadbalancer service", 936 lbServices: []fakeIngressGatewayService{ 937 { 938 ips: []string{"8.8.8.8"}, 939 hostnames: []string{"lb.com"}, 940 namespace: "istio-system", 941 }, 942 }, 943 gwConfigs: []fakeGatewayConfig{ 944 { 945 name: "fake1", 946 namespace: "istio-system", 947 dnsnames: [][]string{{"*"}}, 948 }, 949 }, 950 vsConfigs: []fakeVirtualServiceConfig{ 951 { 952 name: "vs1", 953 namespace: "testing1", 954 gateways: []string{"istio-system/fake1"}, 955 dnsnames: []string{"example.org"}, 956 }, 957 { 958 name: "vs2", 959 namespace: "testing2", 960 gateways: []string{"istio-system/fake1"}, 961 dnsnames: []string{"new.org"}, 962 }, 963 }, 964 expected: []*endpoint.Endpoint{ 965 { 966 DNSName: "example.org", 967 RecordType: endpoint.RecordTypeA, 968 Targets: endpoint.Targets{"8.8.8.8"}, 969 }, 970 { 971 DNSName: "example.org", 972 RecordType: endpoint.RecordTypeCNAME, 973 Targets: endpoint.Targets{"lb.com"}, 974 }, 975 { 976 DNSName: "new.org", 977 RecordType: endpoint.RecordTypeA, 978 Targets: endpoint.Targets{"8.8.8.8"}, 979 }, 980 { 981 DNSName: "new.org", 982 RecordType: endpoint.RecordTypeCNAME, 983 Targets: endpoint.Targets{"lb.com"}, 984 }, 985 }, 986 }, 987 { 988 title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingressgateway loadbalancer service", 989 targetNamespace: "testing1", 990 lbServices: []fakeIngressGatewayService{ 991 { 992 ips: []string{"8.8.8.8"}, 993 hostnames: []string{"lb.com"}, 994 namespace: "testing1", 995 }, 996 }, 997 gwConfigs: []fakeGatewayConfig{ 998 { 999 name: "fake1", 1000 namespace: "testing1", 1001 dnsnames: [][]string{{"*"}}, 1002 }, 1003 }, 1004 vsConfigs: []fakeVirtualServiceConfig{ 1005 { 1006 name: "vs1", 1007 namespace: "testing1", 1008 gateways: []string{"testing1/fake1"}, 1009 dnsnames: []string{"example.org"}, 1010 }, 1011 { 1012 name: "vs2", 1013 namespace: "testing2", 1014 gateways: []string{"testing1/fake1"}, 1015 dnsnames: []string{"new.org"}, 1016 }, 1017 }, 1018 expected: []*endpoint.Endpoint{ 1019 { 1020 DNSName: "example.org", 1021 RecordType: endpoint.RecordTypeA, 1022 Targets: endpoint.Targets{"8.8.8.8"}, 1023 }, 1024 { 1025 DNSName: "example.org", 1026 RecordType: endpoint.RecordTypeCNAME, 1027 Targets: endpoint.Targets{"lb.com"}, 1028 }, 1029 }, 1030 }, 1031 { 1032 title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingressgateway loadbalancer service with externalIPs", 1033 targetNamespace: "testing1", 1034 lbServices: []fakeIngressGatewayService{ 1035 { 1036 externalIPs: []string{"8.8.8.8"}, 1037 namespace: "testing1", 1038 }, 1039 }, 1040 gwConfigs: []fakeGatewayConfig{ 1041 { 1042 name: "fake1", 1043 namespace: "testing1", 1044 dnsnames: [][]string{{"*"}}, 1045 }, 1046 }, 1047 vsConfigs: []fakeVirtualServiceConfig{ 1048 { 1049 name: "vs1", 1050 namespace: "testing1", 1051 gateways: []string{"testing1/fake1"}, 1052 dnsnames: []string{"example.org"}, 1053 }, 1054 { 1055 name: "vs2", 1056 namespace: "testing2", 1057 gateways: []string{"testing1/fake1"}, 1058 dnsnames: []string{"new.org"}, 1059 }, 1060 }, 1061 expected: []*endpoint.Endpoint{ 1062 { 1063 DNSName: "example.org", 1064 RecordType: endpoint.RecordTypeA, 1065 Targets: endpoint.Targets{"8.8.8.8"}, 1066 }, 1067 }, 1068 }, 1069 { 1070 title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingress", 1071 targetNamespace: "testing1", 1072 ingresses: []fakeIngress{ 1073 { 1074 name: "ingress1", 1075 ips: []string{"8.8.8.8"}, 1076 hostnames: []string{"lb.com"}, 1077 namespace: "testing1", 1078 }, 1079 }, 1080 gwConfigs: []fakeGatewayConfig{ 1081 { 1082 name: "fake1", 1083 namespace: "testing1", 1084 dnsnames: [][]string{{"*"}}, 1085 annotations: map[string]string{ 1086 IstioGatewayIngressSource: "ingress1", 1087 }, 1088 }, 1089 }, 1090 vsConfigs: []fakeVirtualServiceConfig{ 1091 { 1092 name: "vs1", 1093 namespace: "testing1", 1094 gateways: []string{"testing1/fake1"}, 1095 dnsnames: []string{"example.org"}, 1096 }, 1097 { 1098 name: "vs2", 1099 namespace: "testing2", 1100 gateways: []string{"testing1/fake1"}, 1101 dnsnames: []string{"new.org"}, 1102 }, 1103 }, 1104 expected: []*endpoint.Endpoint{ 1105 { 1106 DNSName: "example.org", 1107 RecordType: endpoint.RecordTypeA, 1108 Targets: endpoint.Targets{"8.8.8.8"}, 1109 }, 1110 { 1111 DNSName: "example.org", 1112 RecordType: endpoint.RecordTypeCNAME, 1113 Targets: endpoint.Targets{"lb.com"}, 1114 }, 1115 }, 1116 }, 1117 { 1118 title: "valid matching annotation filter expression", 1119 annotationFilter: "kubernetes.io/virtualservice.class in (alb, nginx)", 1120 lbServices: []fakeIngressGatewayService{ 1121 { 1122 ips: []string{"8.8.8.8"}, 1123 namespace: namespace, 1124 }, 1125 }, 1126 gwConfigs: []fakeGatewayConfig{ 1127 { 1128 name: "fake1", 1129 namespace: namespace, 1130 dnsnames: [][]string{{"*"}}, 1131 }, 1132 }, 1133 vsConfigs: []fakeVirtualServiceConfig{ 1134 { 1135 name: "vs1", 1136 namespace: namespace, 1137 annotations: map[string]string{ 1138 "kubernetes.io/virtualservice.class": "nginx", 1139 }, 1140 gateways: []string{"fake1"}, 1141 dnsnames: []string{"example.org"}, 1142 }, 1143 }, 1144 expected: []*endpoint.Endpoint{ 1145 { 1146 DNSName: "example.org", 1147 RecordType: endpoint.RecordTypeA, 1148 Targets: endpoint.Targets{"8.8.8.8"}, 1149 }, 1150 }, 1151 }, 1152 { 1153 title: "valid non-matching annotation filter expression", 1154 annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)", 1155 lbServices: []fakeIngressGatewayService{ 1156 { 1157 ips: []string{"8.8.8.8"}, 1158 namespace: namespace, 1159 }, 1160 }, 1161 gwConfigs: []fakeGatewayConfig{ 1162 { 1163 name: "fake1", 1164 namespace: namespace, 1165 dnsnames: [][]string{{"*"}}, 1166 }, 1167 }, 1168 vsConfigs: []fakeVirtualServiceConfig{ 1169 { 1170 name: "vs1", 1171 namespace: namespace, 1172 annotations: map[string]string{ 1173 "kubernetes.io/virtualservice.class": "tectonic", 1174 }, 1175 gateways: []string{"fake1"}, 1176 dnsnames: []string{"example.org"}, 1177 }, 1178 }, 1179 expected: []*endpoint.Endpoint{}, 1180 }, 1181 { 1182 title: "invalid annotation filter expression", 1183 annotationFilter: "kubernetes.io/gateway.name in (a b)", 1184 expected: []*endpoint.Endpoint{}, 1185 expectError: true, 1186 }, 1187 { 1188 title: "gateway ingress annotation; ingress not found", 1189 ingresses: []fakeIngress{ 1190 { 1191 name: "ingress1", 1192 namespace: namespace, 1193 ips: []string{"8.8.8.8"}, 1194 }, 1195 }, 1196 gwConfigs: []fakeGatewayConfig{ 1197 { 1198 name: "fake1", 1199 namespace: namespace, 1200 dnsnames: [][]string{{"*"}}, 1201 annotations: map[string]string{ 1202 IstioGatewayIngressSource: "ingress2", 1203 }, 1204 }, 1205 }, 1206 vsConfigs: []fakeVirtualServiceConfig{ 1207 { 1208 name: "vs1", 1209 namespace: namespace, 1210 gateways: []string{"fake1"}, 1211 dnsnames: []string{"example.org"}, 1212 }, 1213 }, 1214 expected: []*endpoint.Endpoint{}, 1215 expectError: true, 1216 }, 1217 { 1218 title: "our controller type is dns-controller", 1219 lbServices: []fakeIngressGatewayService{ 1220 { 1221 ips: []string{"8.8.8.8"}, 1222 namespace: namespace, 1223 }, 1224 }, 1225 gwConfigs: []fakeGatewayConfig{ 1226 { 1227 name: "fake1", 1228 namespace: namespace, 1229 dnsnames: [][]string{{"*"}}, 1230 }, 1231 }, 1232 vsConfigs: []fakeVirtualServiceConfig{ 1233 { 1234 name: "vs1", 1235 namespace: namespace, 1236 annotations: map[string]string{ 1237 controllerAnnotationKey: controllerAnnotationValue, 1238 }, 1239 gateways: []string{"fake1"}, 1240 dnsnames: []string{"example.org"}, 1241 }, 1242 }, 1243 expected: []*endpoint.Endpoint{ 1244 { 1245 DNSName: "example.org", 1246 RecordType: endpoint.RecordTypeA, 1247 Targets: endpoint.Targets{"8.8.8.8"}, 1248 }, 1249 }, 1250 }, 1251 { 1252 title: "different controller types are ignored", 1253 lbServices: []fakeIngressGatewayService{ 1254 { 1255 ips: []string{"8.8.8.8"}, 1256 namespace: namespace, 1257 }, 1258 }, 1259 gwConfigs: []fakeGatewayConfig{ 1260 { 1261 name: "fake1", 1262 namespace: namespace, 1263 dnsnames: [][]string{{"*"}}, 1264 }, 1265 }, 1266 vsConfigs: []fakeVirtualServiceConfig{ 1267 { 1268 name: "vs1", 1269 namespace: namespace, 1270 annotations: map[string]string{ 1271 controllerAnnotationKey: "some-other-tool", 1272 }, 1273 gateways: []string{"fake1"}, 1274 dnsnames: []string{"example.org"}, 1275 }, 1276 }, 1277 expected: []*endpoint.Endpoint{}, 1278 }, 1279 { 1280 title: "template for virtualservice if host is missing", 1281 lbServices: []fakeIngressGatewayService{ 1282 { 1283 ips: []string{"8.8.8.8"}, 1284 hostnames: []string{"elb.com"}, 1285 namespace: namespace, 1286 }, 1287 }, 1288 gwConfigs: []fakeGatewayConfig{ 1289 { 1290 name: "fake1", 1291 namespace: namespace, 1292 dnsnames: [][]string{{"*"}}, 1293 }, 1294 }, 1295 vsConfigs: []fakeVirtualServiceConfig{ 1296 { 1297 name: "vs1", 1298 namespace: namespace, 1299 gateways: []string{"fake1"}, 1300 dnsnames: []string{""}, 1301 }, 1302 }, 1303 expected: []*endpoint.Endpoint{ 1304 { 1305 DNSName: "vs1.ext-dns.test.com", 1306 RecordType: endpoint.RecordTypeA, 1307 Targets: endpoint.Targets{"8.8.8.8"}, 1308 }, 1309 { 1310 DNSName: "vs1.ext-dns.test.com", 1311 RecordType: endpoint.RecordTypeCNAME, 1312 Targets: endpoint.Targets{"elb.com"}, 1313 }, 1314 }, 1315 fqdnTemplate: "{{.Name}}.ext-dns.test.com", 1316 }, 1317 { 1318 title: "multiple FQDN template hostnames", 1319 lbServices: []fakeIngressGatewayService{ 1320 { 1321 ips: []string{"8.8.8.8"}, 1322 namespace: namespace, 1323 }, 1324 }, 1325 gwConfigs: []fakeGatewayConfig{ 1326 { 1327 name: "fake1", 1328 namespace: namespace, 1329 dnsnames: [][]string{{"*"}}, 1330 }, 1331 }, 1332 vsConfigs: []fakeVirtualServiceConfig{ 1333 { 1334 name: "vs1", 1335 namespace: namespace, 1336 gateways: []string{"fake1"}, 1337 dnsnames: []string{""}, 1338 }, 1339 }, 1340 expected: []*endpoint.Endpoint{ 1341 { 1342 DNSName: "vs1.ext-dns.test.com", 1343 Targets: endpoint.Targets{"8.8.8.8"}, 1344 RecordType: endpoint.RecordTypeA, 1345 }, 1346 { 1347 DNSName: "vs1.ext-dna.test.com", 1348 Targets: endpoint.Targets{"8.8.8.8"}, 1349 RecordType: endpoint.RecordTypeA, 1350 }, 1351 }, 1352 fqdnTemplate: "{{.Name}}.ext-dns.test.com, {{.Name}}.ext-dna.test.com", 1353 }, 1354 { 1355 title: "multiple FQDN template hostnames with restricted gw.hosts", 1356 gwConfigs: []fakeGatewayConfig{ 1357 { 1358 name: "fake1", 1359 namespace: namespace, 1360 annotations: map[string]string{ 1361 targetAnnotationKey: "gateway-target.com", 1362 }, 1363 dnsnames: [][]string{{"*.org", "*.ext-dns.test.com"}}, 1364 }, 1365 }, 1366 vsConfigs: []fakeVirtualServiceConfig{ 1367 { 1368 name: "vs1", 1369 namespace: namespace, 1370 gateways: []string{"fake1"}, 1371 dnsnames: []string{"example.org"}, 1372 }, 1373 { 1374 name: "vs2", 1375 namespace: namespace, 1376 gateways: []string{"fake1"}, 1377 dnsnames: []string{}, 1378 }, 1379 }, 1380 expected: []*endpoint.Endpoint{ 1381 { 1382 DNSName: "vs1.ext-dns.test.com", 1383 Targets: endpoint.Targets{"gateway-target.com"}, 1384 RecordType: endpoint.RecordTypeCNAME, 1385 }, 1386 { 1387 DNSName: "vs2.ext-dns.test.com", 1388 Targets: endpoint.Targets{"gateway-target.com"}, 1389 RecordType: endpoint.RecordTypeCNAME, 1390 }, 1391 { 1392 DNSName: "example.org", 1393 Targets: endpoint.Targets{"gateway-target.com"}, 1394 RecordType: endpoint.RecordTypeCNAME, 1395 }, 1396 }, 1397 fqdnTemplate: "{{.Name}}.ext-dns.test.com, {{.Name}}.ext-dna.test.com", 1398 combineFQDNAndAnnotation: true, 1399 }, 1400 { 1401 title: "virtualservice with target annotation", 1402 lbServices: []fakeIngressGatewayService{ 1403 { 1404 ips: []string{"8.8.8.8"}, 1405 namespace: namespace, 1406 }, 1407 }, 1408 vsConfigs: []fakeVirtualServiceConfig{ 1409 { 1410 name: "vs1", 1411 namespace: namespace, 1412 gateways: []string{"fake1"}, 1413 annotations: map[string]string{ 1414 targetAnnotationKey: "virtualservice-target.com", 1415 }, 1416 dnsnames: []string{"example.org"}, 1417 }, 1418 { 1419 name: "vs2", 1420 namespace: namespace, 1421 gateways: []string{"fake1"}, 1422 annotations: map[string]string{ 1423 targetAnnotationKey: "virtualservice-target.com", 1424 }, 1425 dnsnames: []string{"example2.org"}, 1426 }, 1427 }, 1428 expected: []*endpoint.Endpoint{ 1429 { 1430 DNSName: "example.org", 1431 Targets: endpoint.Targets{"virtualservice-target.com"}, 1432 RecordType: endpoint.RecordTypeCNAME, 1433 }, 1434 { 1435 DNSName: "example2.org", 1436 Targets: endpoint.Targets{"virtualservice-target.com"}, 1437 RecordType: endpoint.RecordTypeCNAME, 1438 }, 1439 }, 1440 }, 1441 { 1442 title: "virtualservice; gateway with target annotation", 1443 lbServices: []fakeIngressGatewayService{ 1444 { 1445 ips: []string{"8.8.8.8"}, 1446 namespace: namespace, 1447 }, 1448 }, 1449 gwConfigs: []fakeGatewayConfig{ 1450 { 1451 name: "fake1", 1452 namespace: namespace, 1453 dnsnames: [][]string{{"*"}}, 1454 annotations: map[string]string{ 1455 targetAnnotationKey: "gateway-target.com", 1456 }, 1457 }, 1458 }, 1459 vsConfigs: []fakeVirtualServiceConfig{ 1460 { 1461 name: "vs1", 1462 namespace: namespace, 1463 gateways: []string{"fake1"}, 1464 dnsnames: []string{"example.org"}, 1465 }, 1466 { 1467 name: "vs2", 1468 namespace: namespace, 1469 gateways: []string{"fake1"}, 1470 dnsnames: []string{"example2.org"}, 1471 }, 1472 }, 1473 expected: []*endpoint.Endpoint{ 1474 { 1475 DNSName: "example.org", 1476 Targets: endpoint.Targets{"gateway-target.com"}, 1477 RecordType: endpoint.RecordTypeCNAME, 1478 }, 1479 { 1480 DNSName: "example2.org", 1481 Targets: endpoint.Targets{"gateway-target.com"}, 1482 RecordType: endpoint.RecordTypeCNAME, 1483 }, 1484 }, 1485 }, 1486 { 1487 title: "virtualservice; gateway with target and ingress annotation", 1488 lbServices: []fakeIngressGatewayService{ 1489 { 1490 ips: []string{"8.8.8.8"}, 1491 namespace: namespace, 1492 }, 1493 }, 1494 ingresses: []fakeIngress{ 1495 { 1496 name: "ingress1", 1497 ips: []string{"1.1.1.1"}, 1498 namespace: namespace, 1499 }, 1500 }, 1501 gwConfigs: []fakeGatewayConfig{ 1502 { 1503 name: "fake1", 1504 namespace: namespace, 1505 dnsnames: [][]string{{"*"}}, 1506 annotations: map[string]string{ 1507 targetAnnotationKey: "gateway-target.com", 1508 IstioGatewayIngressSource: "ingress1", 1509 }, 1510 }, 1511 }, 1512 vsConfigs: []fakeVirtualServiceConfig{ 1513 { 1514 name: "vs1", 1515 namespace: namespace, 1516 gateways: []string{"fake1"}, 1517 dnsnames: []string{"example.org"}, 1518 }, 1519 { 1520 name: "vs2", 1521 namespace: namespace, 1522 gateways: []string{"fake1"}, 1523 dnsnames: []string{"example2.org"}, 1524 }, 1525 }, 1526 expected: []*endpoint.Endpoint{ 1527 { 1528 DNSName: "example.org", 1529 Targets: endpoint.Targets{"gateway-target.com"}, 1530 RecordType: endpoint.RecordTypeCNAME, 1531 }, 1532 { 1533 DNSName: "example2.org", 1534 Targets: endpoint.Targets{"gateway-target.com"}, 1535 RecordType: endpoint.RecordTypeCNAME, 1536 }, 1537 }, 1538 }, 1539 { 1540 title: "virtualservice with hostname annotation", 1541 lbServices: []fakeIngressGatewayService{ 1542 { 1543 ips: []string{"1.2.3.4"}, 1544 namespace: namespace, 1545 }, 1546 }, 1547 gwConfigs: []fakeGatewayConfig{ 1548 { 1549 name: "fake1", 1550 namespace: namespace, 1551 dnsnames: [][]string{{"*"}}, 1552 }, 1553 }, 1554 vsConfigs: []fakeVirtualServiceConfig{ 1555 { 1556 name: "vs1", 1557 namespace: namespace, 1558 gateways: []string{"fake1"}, 1559 annotations: map[string]string{ 1560 hostnameAnnotationKey: "dns-through-hostname.com", 1561 }, 1562 dnsnames: []string{"example.org"}, 1563 }, 1564 }, 1565 expected: []*endpoint.Endpoint{ 1566 { 1567 DNSName: "example.org", 1568 Targets: endpoint.Targets{"1.2.3.4"}, 1569 RecordType: endpoint.RecordTypeA, 1570 }, 1571 { 1572 DNSName: "dns-through-hostname.com", 1573 Targets: endpoint.Targets{"1.2.3.4"}, 1574 RecordType: endpoint.RecordTypeA, 1575 }, 1576 }, 1577 }, 1578 { 1579 title: "virtualservice with hostname annotation having multiple hostnames, restricted by gw.hosts", 1580 lbServices: []fakeIngressGatewayService{ 1581 { 1582 ips: []string{"1.2.3.4"}, 1583 namespace: namespace, 1584 }, 1585 }, 1586 gwConfigs: []fakeGatewayConfig{ 1587 { 1588 name: "fake1", 1589 namespace: namespace, 1590 dnsnames: [][]string{{"*.bar.com"}}, 1591 }, 1592 }, 1593 vsConfigs: []fakeVirtualServiceConfig{ 1594 { 1595 name: "vs1", 1596 namespace: namespace, 1597 gateways: []string{"fake1"}, 1598 annotations: map[string]string{ 1599 hostnameAnnotationKey: "foo.bar.com, another-dns-through-hostname.com", 1600 }, 1601 dnsnames: []string{"baz.bar.org"}, 1602 }, 1603 }, 1604 expected: []*endpoint.Endpoint{ 1605 { 1606 DNSName: "foo.bar.com", 1607 Targets: endpoint.Targets{"1.2.3.4"}, 1608 RecordType: endpoint.RecordTypeA, 1609 }, 1610 }, 1611 }, 1612 { 1613 title: "virtualservices with annotation and custom TTL", 1614 lbServices: []fakeIngressGatewayService{ 1615 { 1616 ips: []string{"8.8.8.8"}, 1617 namespace: namespace, 1618 }, 1619 }, 1620 gwConfigs: []fakeGatewayConfig{ 1621 { 1622 name: "fake1", 1623 namespace: namespace, 1624 dnsnames: [][]string{{"*"}}, 1625 }, 1626 }, 1627 vsConfigs: []fakeVirtualServiceConfig{ 1628 { 1629 name: "vs1", 1630 namespace: namespace, 1631 gateways: []string{"fake1"}, 1632 annotations: map[string]string{ 1633 ttlAnnotationKey: "6", 1634 }, 1635 dnsnames: []string{"example.org"}, 1636 }, 1637 { 1638 name: "vs2", 1639 namespace: namespace, 1640 gateways: []string{"fake1"}, 1641 annotations: map[string]string{ 1642 ttlAnnotationKey: "1", 1643 }, 1644 dnsnames: []string{"example2.org"}, 1645 }, 1646 }, 1647 expected: []*endpoint.Endpoint{ 1648 { 1649 DNSName: "example.org", 1650 RecordType: endpoint.RecordTypeA, 1651 Targets: endpoint.Targets{"8.8.8.8"}, 1652 RecordTTL: endpoint.TTL(6), 1653 }, 1654 { 1655 DNSName: "example2.org", 1656 RecordType: endpoint.RecordTypeA, 1657 Targets: endpoint.Targets{"8.8.8.8"}, 1658 RecordTTL: endpoint.TTL(1), 1659 }, 1660 }, 1661 }, 1662 { 1663 title: "template for virtualservice; gateway with target annotation", 1664 gwConfigs: []fakeGatewayConfig{ 1665 { 1666 name: "fake1", 1667 namespace: namespace, 1668 annotations: map[string]string{ 1669 targetAnnotationKey: "gateway-target.com", 1670 }, 1671 dnsnames: [][]string{{"*"}}, 1672 }, 1673 { 1674 name: "fake2", 1675 namespace: namespace, 1676 annotations: map[string]string{ 1677 targetAnnotationKey: "gateway-target.com", 1678 }, 1679 dnsnames: [][]string{{"*"}}, 1680 }, 1681 { 1682 name: "fake3", 1683 namespace: namespace, 1684 annotations: map[string]string{ 1685 targetAnnotationKey: "1.2.3.4", 1686 }, 1687 dnsnames: [][]string{{"*"}}, 1688 }, 1689 }, 1690 vsConfigs: []fakeVirtualServiceConfig{ 1691 { 1692 name: "vs1", 1693 namespace: namespace, 1694 gateways: []string{"fake1"}, 1695 dnsnames: []string{}, 1696 }, 1697 { 1698 name: "vs2", 1699 namespace: namespace, 1700 gateways: []string{"fake2"}, 1701 dnsnames: []string{}, 1702 }, 1703 { 1704 name: "vs3", 1705 namespace: namespace, 1706 gateways: []string{"fake3"}, 1707 dnsnames: []string{}, 1708 }, 1709 }, 1710 expected: []*endpoint.Endpoint{ 1711 { 1712 DNSName: "vs1.ext-dns.test.com", 1713 Targets: endpoint.Targets{"gateway-target.com"}, 1714 RecordType: endpoint.RecordTypeCNAME, 1715 }, 1716 { 1717 DNSName: "vs2.ext-dns.test.com", 1718 Targets: endpoint.Targets{"gateway-target.com"}, 1719 RecordType: endpoint.RecordTypeCNAME, 1720 }, 1721 { 1722 DNSName: "vs3.ext-dns.test.com", 1723 Targets: endpoint.Targets{"1.2.3.4"}, 1724 RecordType: endpoint.RecordTypeA, 1725 }, 1726 }, 1727 fqdnTemplate: "{{.Name}}.ext-dns.test.com", 1728 }, 1729 { 1730 title: "ignore hostname annotations", 1731 lbServices: []fakeIngressGatewayService{ 1732 { 1733 ips: []string{"8.8.8.8"}, 1734 hostnames: []string{"lb.com"}, 1735 namespace: namespace, 1736 }, 1737 }, 1738 gwConfigs: []fakeGatewayConfig{ 1739 { 1740 name: "fake1", 1741 namespace: namespace, 1742 dnsnames: [][]string{{"*"}}, 1743 }, 1744 }, 1745 vsConfigs: []fakeVirtualServiceConfig{ 1746 { 1747 name: "vs1", 1748 namespace: namespace, 1749 gateways: []string{"fake1"}, 1750 annotations: map[string]string{ 1751 hostnameAnnotationKey: "ignore.me", 1752 }, 1753 dnsnames: []string{"example.org"}, 1754 }, 1755 { 1756 name: "vs2", 1757 namespace: namespace, 1758 gateways: []string{"fake1"}, 1759 annotations: map[string]string{ 1760 hostnameAnnotationKey: "ignore.me.too", 1761 }, 1762 dnsnames: []string{"new.org"}, 1763 }, 1764 }, 1765 expected: []*endpoint.Endpoint{ 1766 { 1767 DNSName: "example.org", 1768 RecordType: endpoint.RecordTypeA, 1769 Targets: endpoint.Targets{"8.8.8.8"}, 1770 }, 1771 { 1772 DNSName: "example.org", 1773 RecordType: endpoint.RecordTypeCNAME, 1774 Targets: endpoint.Targets{"lb.com"}, 1775 }, 1776 { 1777 DNSName: "new.org", 1778 RecordType: endpoint.RecordTypeA, 1779 Targets: endpoint.Targets{"8.8.8.8"}, 1780 }, 1781 { 1782 DNSName: "new.org", 1783 RecordType: endpoint.RecordTypeCNAME, 1784 Targets: endpoint.Targets{"lb.com"}, 1785 }, 1786 }, 1787 ignoreHostnameAnnotation: true, 1788 }, 1789 { 1790 title: "complex setup with multiple gateways and multiple vs.hosts only matching some of the gateway", 1791 lbServices: []fakeIngressGatewayService{ 1792 { 1793 name: "svc1", 1794 selector: map[string]string{ 1795 "app": "igw1", 1796 }, 1797 hostnames: []string{"target1.com"}, 1798 namespace: "istio-system", 1799 }, 1800 { 1801 name: "svc2", 1802 selector: map[string]string{ 1803 "app": "igw2", 1804 }, 1805 hostnames: []string{"target2.com"}, 1806 namespace: "testing1", 1807 }, 1808 { 1809 name: "svc3", 1810 selector: map[string]string{ 1811 "app": "igw3", 1812 }, 1813 hostnames: []string{"target3.com"}, 1814 namespace: "testing2", 1815 }, 1816 }, 1817 ingresses: []fakeIngress{ 1818 { 1819 name: "ingress1", 1820 namespace: "testing1", 1821 hostnames: []string{"target4.com"}, 1822 }, 1823 { 1824 name: "ingress3", 1825 namespace: "testing3", 1826 hostnames: []string{"target5.com"}, 1827 }, 1828 }, 1829 gwConfigs: []fakeGatewayConfig{ 1830 { 1831 name: "fake1", 1832 namespace: "istio-system", 1833 dnsnames: [][]string{{"*"}}, 1834 selector: map[string]string{ 1835 "app": "igw1", 1836 }, 1837 }, 1838 { 1839 name: "fake2", 1840 namespace: "testing1", 1841 dnsnames: [][]string{{"*.baz.com"}, {"*.bar.com"}}, 1842 selector: map[string]string{ 1843 "app": "igw2", 1844 }, 1845 }, 1846 { 1847 name: "fake3", 1848 namespace: "testing2", 1849 dnsnames: [][]string{{"*.bax.com", "*.bar.com"}}, 1850 selector: map[string]string{ 1851 "app": "igw3", 1852 }, 1853 }, 1854 { 1855 name: "fake4", 1856 namespace: "testing3", 1857 dnsnames: [][]string{{"*.bax.com", "*.bar.com"}}, 1858 selector: map[string]string{ 1859 "app": "igw4", 1860 }, 1861 annotations: map[string]string{ 1862 IstioGatewayIngressSource: "testing1/ingress1", 1863 }, 1864 }, 1865 }, 1866 vsConfigs: []fakeVirtualServiceConfig{ 1867 { 1868 name: "vs1", 1869 namespace: "testing3", 1870 gateways: []string{"istio-system/fake1", "testing1/fake2"}, 1871 dnsnames: []string{"somedomain.com", "foo.bar.com"}, 1872 }, 1873 { 1874 name: "vs2", 1875 namespace: "testing2", 1876 gateways: []string{"testing1/fake2", "fake3"}, 1877 dnsnames: []string{"hello.bar.com", "hello.bax.com", "hello.bak.com"}, 1878 }, 1879 { 1880 name: "vs3", 1881 namespace: "testing1", 1882 gateways: []string{"istio-system/fake1", "testing2/fake3"}, 1883 dnsnames: []string{"world.bax.com", "world.bak.com"}, 1884 }, 1885 { 1886 name: "vs4", 1887 namespace: "testing1", 1888 gateways: []string{"istio-system/fake1", "testing3/fake4"}, 1889 dnsnames: []string{"foo.bax.com", "foo.bak.com"}, 1890 }, 1891 }, 1892 expected: []*endpoint.Endpoint{ 1893 { 1894 DNSName: "somedomain.com", 1895 Targets: endpoint.Targets{"target1.com"}, 1896 RecordType: endpoint.RecordTypeCNAME, 1897 }, 1898 { 1899 DNSName: "foo.bar.com", 1900 Targets: endpoint.Targets{"target1.com", "target2.com"}, 1901 RecordType: endpoint.RecordTypeCNAME, 1902 }, 1903 { 1904 DNSName: "hello.bar.com", 1905 Targets: endpoint.Targets{"target2.com", "target3.com"}, 1906 RecordType: endpoint.RecordTypeCNAME, 1907 }, 1908 { 1909 DNSName: "hello.bax.com", 1910 Targets: endpoint.Targets{"target3.com"}, 1911 RecordType: endpoint.RecordTypeCNAME, 1912 }, 1913 { 1914 DNSName: "world.bak.com", 1915 Targets: endpoint.Targets{"target1.com"}, 1916 RecordType: endpoint.RecordTypeCNAME, 1917 }, 1918 { 1919 DNSName: "world.bax.com", 1920 Targets: endpoint.Targets{"target1.com", "target3.com"}, 1921 RecordType: endpoint.RecordTypeCNAME, 1922 }, 1923 { 1924 DNSName: "foo.bak.com", 1925 Targets: endpoint.Targets{"target1.com"}, 1926 RecordType: endpoint.RecordTypeCNAME, 1927 }, 1928 { 1929 DNSName: "foo.bax.com", 1930 Targets: endpoint.Targets{"target1.com", "target4.com"}, 1931 RecordType: endpoint.RecordTypeCNAME, 1932 }, 1933 }, 1934 fqdnTemplate: "{{.Name}}.ext-dns.test.com", 1935 }, 1936 } { 1937 ti := ti 1938 t.Run(ti.title, func(t *testing.T) { 1939 t.Parallel() 1940 1941 var gateways []*networkingv1alpha3.Gateway 1942 var virtualservices []*networkingv1alpha3.VirtualService 1943 1944 for _, gwItem := range ti.gwConfigs { 1945 gateways = append(gateways, gwItem.Config()) 1946 } 1947 for _, vsItem := range ti.vsConfigs { 1948 virtualservices = append(virtualservices, vsItem.Config()) 1949 } 1950 1951 fakeKubernetesClient := fake.NewSimpleClientset() 1952 1953 for _, lb := range ti.lbServices { 1954 service := lb.Service() 1955 _, err := fakeKubernetesClient.CoreV1().Services(service.Namespace).Create(context.Background(), service, metav1.CreateOptions{}) 1956 require.NoError(t, err) 1957 } 1958 1959 for _, ing := range ti.ingresses { 1960 ingress := ing.Ingress() 1961 _, err := fakeKubernetesClient.NetworkingV1().Ingresses(ingress.Namespace).Create(context.Background(), ingress, metav1.CreateOptions{}) 1962 require.NoError(t, err) 1963 } 1964 1965 fakeIstioClient := istiofake.NewSimpleClientset() 1966 1967 for _, gateway := range gateways { 1968 _, err := fakeIstioClient.NetworkingV1alpha3().Gateways(gateway.Namespace).Create(context.Background(), gateway, metav1.CreateOptions{}) 1969 require.NoError(t, err) 1970 } 1971 1972 for _, virtualservice := range virtualservices { 1973 _, err := fakeIstioClient.NetworkingV1alpha3().VirtualServices(virtualservice.Namespace).Create(context.Background(), virtualservice, metav1.CreateOptions{}) 1974 require.NoError(t, err) 1975 } 1976 1977 virtualServiceSource, err := NewIstioVirtualServiceSource( 1978 context.TODO(), 1979 fakeKubernetesClient, 1980 fakeIstioClient, 1981 ti.targetNamespace, 1982 ti.annotationFilter, 1983 ti.fqdnTemplate, 1984 ti.combineFQDNAndAnnotation, 1985 ti.ignoreHostnameAnnotation, 1986 ) 1987 require.NoError(t, err) 1988 1989 res, err := virtualServiceSource.Endpoints(context.Background()) 1990 if ti.expectError { 1991 assert.Error(t, err) 1992 } else { 1993 assert.NoError(t, err) 1994 } 1995 1996 validateEndpoints(t, res, ti.expected) 1997 }) 1998 } 1999 } 2000 2001 func testGatewaySelectorMatchesService(t *testing.T) { 2002 for _, ti := range []struct { 2003 title string 2004 gwSelector map[string]string 2005 lbSelector map[string]string 2006 expected bool 2007 }{ 2008 { 2009 title: "gw selector matches lb selector", 2010 gwSelector: map[string]string{"istio": "ingressgateway"}, 2011 lbSelector: map[string]string{"istio": "ingressgateway"}, 2012 expected: true, 2013 }, 2014 { 2015 title: "gw selector matches lb selector partially", 2016 gwSelector: map[string]string{"istio": "ingressgateway"}, 2017 lbSelector: map[string]string{"release": "istio", "istio": "ingressgateway"}, 2018 expected: true, 2019 }, 2020 { 2021 title: "gw selector does not match lb selector", 2022 gwSelector: map[string]string{"app": "mytest"}, 2023 lbSelector: map[string]string{"istio": "ingressgateway"}, 2024 expected: false, 2025 }, 2026 } { 2027 t.Run(ti.title, func(t *testing.T) { 2028 require.Equal(t, ti.expected, gatewaySelectorMatchesServiceSelector(ti.gwSelector, ti.lbSelector)) 2029 }) 2030 } 2031 } 2032 2033 func newTestVirtualServiceSource(loadBalancerList []fakeIngressGatewayService, ingressList []fakeIngress, gwList []fakeGatewayConfig) (*virtualServiceSource, error) { 2034 fakeKubernetesClient := fake.NewSimpleClientset() 2035 fakeIstioClient := istiofake.NewSimpleClientset() 2036 2037 for _, lb := range loadBalancerList { 2038 service := lb.Service() 2039 _, err := fakeKubernetesClient.CoreV1().Services(service.Namespace).Create(context.Background(), service, metav1.CreateOptions{}) 2040 if err != nil { 2041 return nil, err 2042 } 2043 } 2044 2045 for _, ing := range ingressList { 2046 ingress := ing.Ingress() 2047 _, err := fakeKubernetesClient.NetworkingV1().Ingresses(ingress.Namespace).Create(context.Background(), ingress, metav1.CreateOptions{}) 2048 if err != nil { 2049 return nil, err 2050 } 2051 } 2052 2053 for _, gw := range gwList { 2054 gwObj := gw.Config() 2055 // use create instead of add 2056 // https://github.com/kubernetes/client-go/blob/92512ee2b8cf6696e9909245624175b7f0c971d9/testing/fixture.go#LL336C3-L336C52 2057 _, err := fakeIstioClient.NetworkingV1alpha3().Gateways(gw.namespace).Create(context.Background(), gwObj, metav1.CreateOptions{}) 2058 if err != nil { 2059 return nil, err 2060 } 2061 } 2062 2063 src, err := NewIstioVirtualServiceSource( 2064 context.TODO(), 2065 fakeKubernetesClient, 2066 fakeIstioClient, 2067 "", 2068 "", 2069 "{{.Name}}", 2070 false, 2071 false, 2072 ) 2073 if err != nil { 2074 return nil, err 2075 } 2076 2077 vssrc, ok := src.(*virtualServiceSource) 2078 if !ok { 2079 return nil, errors.New("underlying source type was not virtualservice") 2080 } 2081 2082 return vssrc, nil 2083 } 2084 2085 type fakeVirtualServiceConfig struct { 2086 namespace string 2087 name string 2088 gateways []string 2089 annotations map[string]string 2090 dnsnames []string 2091 exportTo string 2092 } 2093 2094 func (c fakeVirtualServiceConfig) Config() *networkingv1alpha3.VirtualService { 2095 vs := istionetworking.VirtualService{ 2096 Gateways: c.gateways, 2097 Hosts: c.dnsnames, 2098 } 2099 if c.exportTo != "" { 2100 vs.ExportTo = []string{c.exportTo} 2101 } 2102 2103 return &networkingv1alpha3.VirtualService{ 2104 ObjectMeta: metav1.ObjectMeta{ 2105 Name: c.name, 2106 Namespace: c.namespace, 2107 Annotations: c.annotations, 2108 }, 2109 Spec: *vs.DeepCopy(), 2110 } 2111 } 2112 2113 func TestVirtualServiceSourceGetGateway(t *testing.T) { 2114 type fields struct { 2115 virtualServiceSource *virtualServiceSource 2116 } 2117 type args struct { 2118 ctx context.Context 2119 gatewayStr string 2120 virtualService *networkingv1alpha3.VirtualService 2121 } 2122 tests := []struct { 2123 name string 2124 fields fields 2125 args args 2126 want *networkingv1alpha3.Gateway 2127 expectedErrStr string 2128 }{ 2129 {name: "EmptyGateway", fields: fields{ 2130 virtualServiceSource: func() *virtualServiceSource { vs, _ := newTestVirtualServiceSource(nil, nil, nil); return vs }(), 2131 }, args: args{ 2132 ctx: context.TODO(), 2133 gatewayStr: "", 2134 virtualService: nil, 2135 }, want: nil, expectedErrStr: ""}, 2136 {name: "MeshGateway", fields: fields{ 2137 virtualServiceSource: func() *virtualServiceSource { vs, _ := newTestVirtualServiceSource(nil, nil, nil); return vs }(), 2138 }, args: args{ 2139 ctx: context.TODO(), 2140 gatewayStr: IstioMeshGateway, 2141 virtualService: nil, 2142 }, want: nil, expectedErrStr: ""}, 2143 {name: "MissingGateway", fields: fields{ 2144 virtualServiceSource: func() *virtualServiceSource { vs, _ := newTestVirtualServiceSource(nil, nil, nil); return vs }(), 2145 }, args: args{ 2146 ctx: context.TODO(), 2147 gatewayStr: "doesnt/exist", 2148 virtualService: &networkingv1alpha3.VirtualService{ 2149 TypeMeta: metav1.TypeMeta{}, 2150 ObjectMeta: metav1.ObjectMeta{Name: "exist", Namespace: "doesnt"}, 2151 Spec: istionetworking.VirtualService{}, 2152 Status: v1alpha1.IstioStatus{}, 2153 }, 2154 }, want: nil, expectedErrStr: ""}, 2155 {name: "InvalidGatewayStr", fields: fields{ 2156 virtualServiceSource: func() *virtualServiceSource { vs, _ := newTestVirtualServiceSource(nil, nil, nil); return vs }(), 2157 }, args: args{ 2158 ctx: context.TODO(), 2159 gatewayStr: "1/2/3/", 2160 virtualService: &networkingv1alpha3.VirtualService{}, 2161 }, want: nil, expectedErrStr: "invalid gateway name (name or namespace/name) found '1/2/3/'"}, 2162 {name: "ExistingGateway", fields: fields{ 2163 virtualServiceSource: func() *virtualServiceSource { 2164 vs, _ := newTestVirtualServiceSource(nil, nil, []fakeGatewayConfig{{ 2165 namespace: "bar", 2166 name: "foo", 2167 }}) 2168 return vs 2169 }(), 2170 }, args: args{ 2171 ctx: context.TODO(), 2172 gatewayStr: "bar/foo", 2173 virtualService: &networkingv1alpha3.VirtualService{ 2174 TypeMeta: metav1.TypeMeta{}, 2175 ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, 2176 Spec: istionetworking.VirtualService{}, 2177 Status: v1alpha1.IstioStatus{}, 2178 }, 2179 }, want: &networkingv1alpha3.Gateway{ 2180 TypeMeta: metav1.TypeMeta{}, 2181 ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, 2182 Spec: istionetworking.Gateway{}, 2183 Status: v1alpha1.IstioStatus{}, 2184 }, expectedErrStr: ""}, 2185 {name: "ErrorGettingGateway", fields: fields{ 2186 virtualServiceSource: func() *virtualServiceSource { 2187 istioFake := istiofake.NewSimpleClientset() 2188 istioFake.NetworkingV1alpha3().(*fakenetworking3.FakeNetworkingV1alpha3).PrependReactor("get", "gateways", func(action k8sclienttesting.Action) (handled bool, ret runtime.Object, err error) { 2189 return true, &networkingv1alpha3.Gateway{}, fmt.Errorf("error getting gateway") 2190 }) 2191 vs, _ := NewIstioVirtualServiceSource( 2192 context.TODO(), 2193 fake.NewSimpleClientset(), 2194 istioFake, 2195 "", 2196 "", 2197 "{{.Name}}", 2198 false, 2199 false, 2200 ) 2201 return vs.(*virtualServiceSource) 2202 }(), 2203 }, args: args{ 2204 ctx: context.TODO(), 2205 gatewayStr: "foo/bar", 2206 virtualService: &networkingv1alpha3.VirtualService{ 2207 TypeMeta: metav1.TypeMeta{}, 2208 ObjectMeta: metav1.ObjectMeta{Name: "gateway", Namespace: "error"}, 2209 Spec: istionetworking.VirtualService{}, 2210 Status: v1alpha1.IstioStatus{}, 2211 }, 2212 }, want: nil, expectedErrStr: "error getting gateway"}, 2213 } 2214 for _, tt := range tests { 2215 t.Run(tt.name, func(t *testing.T) { 2216 got, err := tt.fields.virtualServiceSource.getGateway(tt.args.ctx, tt.args.gatewayStr, tt.args.virtualService) 2217 if tt.expectedErrStr != "" { 2218 assert.EqualError(t, err, tt.expectedErrStr, fmt.Sprintf("getGateway(%v, %v, %v)", tt.args.ctx, tt.args.gatewayStr, tt.args.virtualService)) 2219 return 2220 } else { 2221 require.NoError(t, err) 2222 } 2223 if tt.want != nil && got != nil { 2224 tt.want.Spec.ProtoReflect() 2225 tt.want.Status.ProtoReflect() 2226 assert.Equalf(t, tt.want, got, "getGateway(%v, %v, %v)", tt.args.ctx, tt.args.gatewayStr, tt.args.virtualService) 2227 } else { 2228 assert.Equalf(t, tt.want, got, "getGateway(%v, %v, %v)", tt.args.ctx, tt.args.gatewayStr, tt.args.virtualService) 2229 } 2230 }) 2231 } 2232 }