fix(istio): support for ExternalIPs in Istio resources

 Add support for ExternalIPs in Istio Gateway and VirtualService
ℹ️ This commit extends Istio Gateway and VirtualService resources
to support ExternalIPs. The changes include:
- Checking if service has ExternalIPs defined
- If yes, adding them to the list of targets
- If not, continuing with the existing process

👌 Now you can have your Istio resources use `externalIPs` too! 🎉

Not to be `ip`-percritical, but don't we all love an `ip`grade! 🎈

Signed-off-by: Karsten Siemer <karsten.siemer@sda.se>
This commit is contained in:
Karsten Siemer 2023-12-04 15:15:08 +01:00
parent 832bcb5148
commit 87a53778a8
No known key found for this signature in database
GPG Key ID: 6C4C0E03A7B1E81C
4 changed files with 197 additions and 16 deletions

View File

@ -289,6 +289,11 @@ func (sc *gatewaySource) targetsFromGateway(ctx context.Context, gateway *networ
continue continue
} }
if len(service.Spec.ExternalIPs) > 0 {
targets = append(targets, service.Spec.ExternalIPs...)
continue
}
for _, lb := range service.Status.LoadBalancer.Ingress { for _, lb := range service.Status.LoadBalancer.Ingress {
if lb.IP != "" { if lb.IP != "" {
targets = append(targets, lb.IP) targets = append(targets, lb.IP)

View File

@ -339,6 +339,7 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
{ {
ips: []string{"8.8.8.8", "127.0.0.1"}, ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"}, hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
}, },
}, },
config: fakeGatewayConfig{ config: fakeGatewayConfig{
@ -352,6 +353,7 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
{ {
ips: []string{"8.8.8.8", "127.0.0.1"}, ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"}, hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
}, },
}, },
config: fakeGatewayConfig{ 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 ti := ti
t.Run(ti.title, func(t *testing.T) { t.Run(ti.title, func(t *testing.T) {
@ -1526,6 +1570,7 @@ type fakeIngressGatewayService struct {
namespace string namespace string
name string name string
selector map[string]string selector map[string]string
externalIPs []string
} }
func (ig fakeIngressGatewayService) Service() *v1.Service { func (ig fakeIngressGatewayService) Service() *v1.Service {
@ -1541,6 +1586,7 @@ func (ig fakeIngressGatewayService) Service() *v1.Service {
}, },
Spec: v1.ServiceSpec{ Spec: v1.ServiceSpec{
Selector: ig.selector, Selector: ig.selector,
ExternalIPs: ig.externalIPs,
}, },
} }

View File

@ -470,6 +470,11 @@ func (sc *virtualServiceSource) targetsFromGateway(ctx context.Context, gateway
continue continue
} }
if len(service.Spec.ExternalIPs) > 0 {
targets = append(targets, service.Spec.ExternalIPs...)
continue
}
for _, lb := range service.Status.LoadBalancer.Ingress { for _, lb := range service.Status.LoadBalancer.Ingress {
if lb.IP != "" { if lb.IP != "" {
targets = append(targets, lb.IP) targets = append(targets, lb.IP)

View File

@ -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", title: "one rule.host two lb.IP and two lb.Hostname",
lbServices: []fakeIngressGatewayService{ 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", title: "no rule.host",
lbServices: []fakeIngressGatewayService{ lbServices: []fakeIngressGatewayService{
{ {
ips: []string{"8.8.8.8", "127.0.0.1"}, ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"}, hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
}, },
}, },
gwconfig: fakeGatewayConfig{ gwconfig: fakeGatewayConfig{
@ -503,6 +552,7 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) {
{ {
ips: []string{"8.8.8.8", "127.0.0.1"}, ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"}, hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
}, },
}, },
gwconfig: fakeGatewayConfig{ gwconfig: fakeGatewayConfig{
@ -521,6 +571,7 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) {
{ {
ips: []string{"8.8.8.8", "127.0.0.1"}, ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"}, hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
}, },
}, },
gwconfig: fakeGatewayConfig{ 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", title: "two simple virtualservices on different namespaces with the same target gateway, one ingressgateway loadbalancer service",
lbServices: []fakeIngressGatewayService{ 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", title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingress",
targetNamespace: "testing1", targetNamespace: "testing1",