diff --git a/source/istio_gateway.go b/source/istio_gateway.go index 1c780c31c9..d158b30a7f 100644 --- a/source/istio_gateway.go +++ b/source/istio_gateway.go @@ -289,6 +289,11 @@ func (sc *gatewaySource) targetsFromGateway(ctx context.Context, gateway *networ continue } + if len(service.Spec.ExternalIPs) > 0 { + targets = append(targets, service.Spec.ExternalIPs...) + continue + } + for _, lb := range service.Status.LoadBalancer.Ingress { if lb.IP != "" { targets = append(targets, lb.IP) diff --git a/source/istio_gateway_test.go b/source/istio_gateway_test.go index f8450c5e51..9c74d7a7fb 100644 --- a/source/istio_gateway_test.go +++ b/source/istio_gateway_test.go @@ -337,8 +337,9 @@ func testEndpointsFromGatewayConfig(t *testing.T) { title: "no rule.host", lbServices: []fakeIngressGatewayService{ { - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, }, }, config: fakeGatewayConfig{ @@ -350,8 +351,9 @@ func testEndpointsFromGatewayConfig(t *testing.T) { title: "one empty rule.host", lbServices: []fakeIngressGatewayService{ { - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, }, }, config: fakeGatewayConfig{ @@ -447,6 +449,48 @@ func testEndpointsFromGatewayConfig(t *testing.T) { }, }, }, + { + title: "one rule.host one lb.externalIP", + lbServices: []fakeIngressGatewayService{ + { + externalIPs: []string{"8.8.8.8"}, + }, + }, + config: fakeGatewayConfig{ + dnsnames: [][]string{ + {"foo.bar"}, + }, + }, + expected: []*endpoint.Endpoint{ + { + DNSName: "foo.bar", + RecordType: endpoint.RecordTypeA, + Targets: endpoint.Targets{"8.8.8.8"}, + }, + }, + }, + { + title: "one rule.host two lb.IP, two lb.Hostname and two lb.externalIP", + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, + }, + }, + config: fakeGatewayConfig{ + dnsnames: [][]string{ + {"foo.bar"}, + }, + }, + expected: []*endpoint.Endpoint{ + { + DNSName: "foo.bar", + RecordType: endpoint.RecordTypeA, + Targets: endpoint.Targets{"1.1.1.1", "2.2.2.2"}, + }, + }, + }, } { ti := ti t.Run(ti.title, func(t *testing.T) { @@ -1521,11 +1565,12 @@ func newTestGatewaySource(loadBalancerList []fakeIngressGatewayService, ingressL } type fakeIngressGatewayService struct { - ips []string - hostnames []string - namespace string - name string - selector map[string]string + ips []string + hostnames []string + namespace string + name string + selector map[string]string + externalIPs []string } func (ig fakeIngressGatewayService) Service() *v1.Service { @@ -1540,7 +1585,8 @@ func (ig fakeIngressGatewayService) Service() *v1.Service { }, }, Spec: v1.ServiceSpec{ - Selector: ig.selector, + Selector: ig.selector, + ExternalIPs: ig.externalIPs, }, } diff --git a/source/istio_virtualservice.go b/source/istio_virtualservice.go index 1eed91d1a8..992e1ef1d6 100644 --- a/source/istio_virtualservice.go +++ b/source/istio_virtualservice.go @@ -470,6 +470,11 @@ func (sc *virtualServiceSource) targetsFromGateway(ctx context.Context, gateway continue } + if len(service.Spec.ExternalIPs) > 0 { + targets = append(targets, service.Spec.ExternalIPs...) + continue + } + for _, lb := range service.Status.LoadBalancer.Ingress { if lb.IP != "" { targets = append(targets, lb.IP) diff --git a/source/istio_virtualservice_test.go b/source/istio_virtualservice_test.go index d907da2eb5..b5bfe3c987 100644 --- a/source/istio_virtualservice_test.go +++ b/source/istio_virtualservice_test.go @@ -450,6 +450,29 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) { }, }, }, + { + title: "one rule.host one lb.externalIPs", + lbServices: []fakeIngressGatewayService{ + { + externalIPs: []string{"8.8.8.8"}, + }, + }, + gwconfig: fakeGatewayConfig{ + name: "mygw", + dnsnames: [][]string{{"*"}}, + }, + vsconfig: fakeVirtualServiceConfig{ + gateways: []string{"mygw"}, + dnsnames: []string{"foo.bar"}, + }, + expected: []*endpoint.Endpoint{ + { + DNSName: "foo.bar", + RecordType: endpoint.RecordTypeA, + Targets: endpoint.Targets{"8.8.8.8"}, + }, + }, + }, { title: "one rule.host two lb.IP and two lb.Hostname", lbServices: []fakeIngressGatewayService{ @@ -479,12 +502,38 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) { }, }, }, + { + title: "one rule.host two lb.IP and two lb.Hostname and two lb.externalIPs", + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, + }, + }, + gwconfig: fakeGatewayConfig{ + name: "mygw", + dnsnames: [][]string{{"*"}}, + }, + vsconfig: fakeVirtualServiceConfig{ + gateways: []string{"mygw"}, + dnsnames: []string{"foo.bar"}, + }, + expected: []*endpoint.Endpoint{ + { + DNSName: "foo.bar", + RecordType: endpoint.RecordTypeA, + Targets: endpoint.Targets{"1.1.1.1", "2.2.2.2"}, + }, + }, + }, { title: "no rule.host", lbServices: []fakeIngressGatewayService{ { - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, }, }, gwconfig: fakeGatewayConfig{ @@ -501,8 +550,9 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) { title: "no rule.gateway", lbServices: []fakeIngressGatewayService{ { - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, }, }, gwconfig: fakeGatewayConfig{ @@ -519,8 +569,9 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) { title: "one empty rule.host", lbServices: []fakeIngressGatewayService{ { - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + externalIPs: []string{"1.1.1.1", "2.2.2.2"}, }, }, gwconfig: fakeGatewayConfig{ @@ -844,6 +895,42 @@ func testVirtualServiceEndpoints(t *testing.T) { }, }, }, + { + title: "one virtualservice with two gateways, one ingressgateway loadbalancer service with externalIPs", + lbServices: []fakeIngressGatewayService{ + { + namespace: namespace, + externalIPs: []string{"8.8.8.8"}, + }, + }, + gwConfigs: []fakeGatewayConfig{ + { + name: "gw1", + namespace: namespace, + dnsnames: [][]string{{"*"}}, + }, + { + name: "gw2", + namespace: namespace, + dnsnames: [][]string{{"*"}}, + }, + }, + vsConfigs: []fakeVirtualServiceConfig{ + { + name: "vs", + namespace: namespace, + gateways: []string{"gw1", "gw2"}, + dnsnames: []string{"example.org"}, + }, + }, + expected: []*endpoint.Endpoint{ + { + DNSName: "example.org", + RecordType: endpoint.RecordTypeA, + Targets: endpoint.Targets{"8.8.8.8"}, + }, + }, + }, { title: "two simple virtualservices on different namespaces with the same target gateway, one ingressgateway loadbalancer service", lbServices: []fakeIngressGatewayService{ @@ -941,6 +1028,44 @@ func testVirtualServiceEndpoints(t *testing.T) { }, }, }, + { + title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingressgateway loadbalancer service with externalIPs", + targetNamespace: "testing1", + lbServices: []fakeIngressGatewayService{ + { + externalIPs: []string{"8.8.8.8"}, + namespace: "testing1", + }, + }, + gwConfigs: []fakeGatewayConfig{ + { + name: "fake1", + namespace: "testing1", + dnsnames: [][]string{{"*"}}, + }, + }, + vsConfigs: []fakeVirtualServiceConfig{ + { + name: "vs1", + namespace: "testing1", + gateways: []string{"testing1/fake1"}, + dnsnames: []string{"example.org"}, + }, + { + name: "vs2", + namespace: "testing2", + gateways: []string{"testing1/fake1"}, + dnsnames: []string{"new.org"}, + }, + }, + expected: []*endpoint.Endpoint{ + { + DNSName: "example.org", + RecordType: endpoint.RecordTypeA, + Targets: endpoint.Targets{"8.8.8.8"}, + }, + }, + }, { title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingress", targetNamespace: "testing1",