Add support for multiple Istio Ingress Gateways

The --istio-ingress-gateway flag may now be specified multiple times.
This commit is contained in:
Christian Glombek 2019-03-18 22:13:44 +01:00
parent c3702c9130
commit 0076e4156c
8 changed files with 615 additions and 425 deletions

View File

@ -25,7 +25,7 @@ spec:
- --source=service - --source=service
- --source=ingress - --source=ingress
- --source=istio-gateway - --source=istio-gateway
- --istio-ingress-gateway=custom-istio-namespace/custom-istio-ingressgateway # omit to use the default (istio-system/istio-ingressgateway) - --istio-ingress-gateway=custom-istio-namespace/custom-istio-ingressgateway # load balancer service to be used; can be specified multiple times. Omit to use the default (istio-system/istio-ingressgateway)
- --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws - --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
@ -95,7 +95,7 @@ spec:
- --source=service - --source=service
- --source=ingress - --source=ingress
- --source=istio-gateway - --source=istio-gateway
- --istio-ingress-gateway=custom-istio-namespace/custom-istio-ingressgateway # omit to use the default (istio-system/istio-ingressgateway) - --istio-ingress-gateway=custom-istio-namespace/custom-istio-ingressgateway # load balancer service to be used; can be specified multiple times. Omit to use the default (istio-system/istio-ingressgateway)
- --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --domain-filter=external-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws - --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization

View File

@ -81,7 +81,7 @@ func main() {
KubeConfig: cfg.KubeConfig, KubeConfig: cfg.KubeConfig,
KubeMaster: cfg.Master, KubeMaster: cfg.Master,
ServiceTypeFilter: cfg.ServiceTypeFilter, ServiceTypeFilter: cfg.ServiceTypeFilter,
IstioIngressGateway: cfg.IstioIngressGateway, IstioIngressGatewayServices: cfg.IstioIngressGatewayServices,
} }
// Lookup all the selected sources by names and pass them the desired configuration. // Lookup all the selected sources by names and pass them the desired configuration.

View File

@ -39,7 +39,7 @@ type Config struct {
Master string Master string
KubeConfig string KubeConfig string
RequestTimeout time.Duration RequestTimeout time.Duration
IstioIngressGateway string IstioIngressGatewayServices []string
Sources []string Sources []string
Namespace string Namespace string
AnnotationFilter string AnnotationFilter string
@ -118,7 +118,7 @@ var defaultConfig = &Config{
Master: "", Master: "",
KubeConfig: "", KubeConfig: "",
RequestTimeout: time.Second * 30, RequestTimeout: time.Second * 30,
IstioIngressGateway: "istio-system/istio-ingressgateway", IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway"},
Sources: nil, Sources: nil,
Namespace: "", Namespace: "",
AnnotationFilter: "", AnnotationFilter: "",
@ -229,7 +229,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("request-timeout", "Request timeout when calling Kubernetes APIs. 0s means no timeout").Default(defaultConfig.RequestTimeout.String()).DurationVar(&cfg.RequestTimeout) app.Flag("request-timeout", "Request timeout when calling Kubernetes APIs. 0s means no timeout").Default(defaultConfig.RequestTimeout.String()).DurationVar(&cfg.RequestTimeout)
// Flags related to Istio // Flags related to Istio
app.Flag("istio-ingress-gateway", "The fully-qualified name of the Istio ingress gateway service (default: istio-system/istio-ingressgateway)").Default(defaultConfig.IstioIngressGateway).StringVar(&cfg.IstioIngressGateway) app.Flag("istio-ingress-gateway", "The fully-qualified name of the Istio ingress gateway service. Flag can be specified multiple times (default: istio-system/istio-ingressgateway)").Default("istio-system/istio-ingressgateway").StringsVar(&cfg.IstioIngressGatewayServices)
// Flags related to processing sources // Flags related to processing sources
app.Flag("source", "The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, fake, connector, istio-gateway, crd").Required().PlaceHolder("source").EnumsVar(&cfg.Sources, "service", "ingress", "istio-gateway", "fake", "connector", "crd") app.Flag("source", "The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, fake, connector, istio-gateway, crd").Required().PlaceHolder("source").EnumsVar(&cfg.Sources, "service", "ingress", "istio-gateway", "fake", "connector", "crd")

View File

@ -32,7 +32,7 @@ var (
Master: "", Master: "",
KubeConfig: "", KubeConfig: "",
RequestTimeout: time.Second * 30, RequestTimeout: time.Second * 30,
IstioIngressGateway: "istio-system/istio-ingressgateway", IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway"},
Sources: []string{"service"}, Sources: []string{"service"},
Namespace: "", Namespace: "",
FQDNTemplate: "", FQDNTemplate: "",
@ -88,7 +88,7 @@ var (
Master: "http://127.0.0.1:8080", Master: "http://127.0.0.1:8080",
KubeConfig: "/some/path", KubeConfig: "/some/path",
RequestTimeout: time.Second * 77, RequestTimeout: time.Second * 77,
IstioIngressGateway: "istio-other/istio-otheringressgateway", IstioIngressGatewayServices: []string{"istio-other/istio-otheringressgateway"},
Sources: []string{"service", "ingress", "connector"}, Sources: []string{"service", "ingress", "connector"},
Namespace: "namespace", Namespace: "namespace",
IgnoreHostnameAnnotation: true, IgnoreHostnameAnnotation: true,
@ -144,6 +144,63 @@ var (
CRDSourceKind: "Endpoint", CRDSourceKind: "Endpoint",
RcodezeroTXTEncrypt: true, RcodezeroTXTEncrypt: true,
} }
// minimal config with istio gateway source and multiple ingressgateway load balancer services
multipleIstioIngressGatewaysConfig = &Config{
Master: "",
KubeConfig: "",
RequestTimeout: time.Second * 30,
IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway", "istio-other/istio-otheringressgateway"},
Sources: []string{"istio-gateway"},
Namespace: "",
FQDNTemplate: "",
Compatibility: "",
Provider: "google",
GoogleProject: "",
DomainFilter: []string{""},
ZoneIDFilter: []string{""},
AlibabaCloudConfigFile: "/etc/kubernetes/alibaba-cloud.json",
AWSZoneType: "",
AWSZoneTagFilter: []string{""},
AWSAssumeRole: "",
AWSBatchChangeSize: 1000,
AWSBatchChangeInterval: time.Second,
AWSEvaluateTargetHealth: true,
AWSAPIRetries: 3,
AzureConfigFile: "/etc/kubernetes/azure.json",
AzureResourceGroup: "",
CloudflareProxied: false,
CloudflareZonesPerPage: 50,
InfobloxGridHost: "",
InfobloxWapiPort: 443,
InfobloxWapiUsername: "admin",
InfobloxWapiPassword: "",
InfobloxWapiVersion: "2.3.1",
InfobloxView: "",
InfobloxSSLVerify: true,
OCIConfigFile: "/etc/kubernetes/oci.yaml",
InMemoryZones: []string{""},
PDNSServer: "http://localhost:8081",
PDNSAPIKey: "",
Policy: "sync",
Registry: "txt",
TXTOwnerID: "default",
TXTPrefix: "",
TXTCacheInterval: 0,
Interval: time.Minute,
Once: false,
DryRun: false,
LogFormat: "text",
MetricsAddress: ":7979",
LogLevel: logrus.InfoLevel.String(),
ConnectorSourceServer: "localhost:8080",
ExoscaleEndpoint: "https://api.exoscale.ch/dns",
ExoscaleAPIKey: "",
ExoscaleAPISecret: "",
CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1",
CRDSourceKind: "DNSEndpoint",
RcodezeroTXTEncrypt: false,
}
) )
func TestParseFlags(t *testing.T) { func TestParseFlags(t *testing.T) {
@ -295,6 +352,27 @@ func TestParseFlags(t *testing.T) {
}, },
expected: overriddenConfig, expected: overriddenConfig,
}, },
{
title: "istio config with 2 ingressgateways",
args: []string{
"--provider=google",
"--source=istio-gateway",
"--istio-ingress-gateway=istio-system/istio-ingressgateway",
"--istio-ingress-gateway=istio-other/istio-otheringressgateway",
},
envVars: map[string]string{},
expected: multipleIstioIngressGatewaysConfig,
},
{
title: "override everything via environment variables with multiple istio ingress gateway load balancer services",
args: []string{},
envVars: map[string]string{
"EXTERNAL_DNS_PROVIDER": "google",
"EXTERNAL_DNS_SOURCE": "istio-gateway",
"EXTERNAL_DNS_ISTIO_INGRESS_GATEWAY": "istio-system/istio-ingressgateway\nistio-other/istio-otheringressgateway",
},
expected: multipleIstioIngressGatewaysConfig,
},
} { } {
t.Run(ti.title, func(t *testing.T) { t.Run(ti.title, func(t *testing.T) {
originalEnv := setEnv(t, ti.envVars) originalEnv := setEnv(t, ti.envVars)

View File

@ -40,8 +40,7 @@ import (
type gatewaySource struct { type gatewaySource struct {
kubeClient kubernetes.Interface kubeClient kubernetes.Interface
istioClient istiomodel.ConfigStore istioClient istiomodel.ConfigStore
istioNamespace string istioIngressGatewayServices []string
istioIngressGatewayName string
namespace string namespace string
annotationFilter string annotationFilter string
fqdnTemplate *template.Template fqdnTemplate *template.Template
@ -53,7 +52,7 @@ type gatewaySource struct {
func NewIstioGatewaySource( func NewIstioGatewaySource(
kubeClient kubernetes.Interface, kubeClient kubernetes.Interface,
istioClient istiomodel.ConfigStore, istioClient istiomodel.ConfigStore,
istioIngressGateway string, istioIngressGatewayServices []string,
namespace string, namespace string,
annotationFilter string, annotationFilter string,
fqdnTemplate string, fqdnTemplate string,
@ -64,10 +63,11 @@ func NewIstioGatewaySource(
tmpl *template.Template tmpl *template.Template
err error err error
) )
istioNamespace, istioIngressGatewayName, err := parseIngressGateway(istioIngressGateway) for _, lbService := range istioIngressGatewayServices {
if err != nil { if _, _, err = parseIngressGateway(lbService); err != nil {
return nil, err return nil, err
} }
}
if fqdnTemplate != "" { if fqdnTemplate != "" {
tmpl, err = template.New("endpoint").Funcs(template.FuncMap{ tmpl, err = template.New("endpoint").Funcs(template.FuncMap{
@ -81,8 +81,7 @@ func NewIstioGatewaySource(
return &gatewaySource{ return &gatewaySource{
kubeClient: kubeClient, kubeClient: kubeClient,
istioClient: istioClient, istioClient: istioClient,
istioNamespace: istioNamespace, istioIngressGatewayServices: istioIngressGatewayServices,
istioIngressGatewayName: istioIngressGatewayName,
namespace: namespace, namespace: namespace,
annotationFilter: annotationFilter, annotationFilter: annotationFilter,
fqdnTemplate: tmpl, fqdnTemplate: tmpl,
@ -169,7 +168,7 @@ func (sc *gatewaySource) endpointsFromTemplate(config *istiomodel.Config) ([]*en
targets := getTargetsFromTargetAnnotation(config.Annotations) targets := getTargetsFromTargetAnnotation(config.Annotations)
if len(targets) == 0 { if len(targets) == 0 {
targets, err = sc.targetsFromIstioIngressStatus() targets, err = sc.targetsFromIstioIngressGatewayServices()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -224,9 +223,14 @@ func (sc *gatewaySource) setResourceLabel(config istiomodel.Config, endpoints []
} }
} }
func (sc *gatewaySource) targetsFromIstioIngressStatus() (targets endpoint.Targets, err error) { func (sc *gatewaySource) targetsFromIstioIngressGatewayServices() (targets endpoint.Targets, err error) {
if svc, e := sc.kubeClient.CoreV1().Services(sc.istioNamespace).Get(sc.istioIngressGatewayName, metav1.GetOptions{}); e != nil { for _, lbService := range sc.istioIngressGatewayServices {
err = e lbNamespace, lbName, err := parseIngressGateway(lbService)
if err != nil {
return nil, err
}
if svc, err := sc.kubeClient.CoreV1().Services(lbNamespace).Get(lbName, metav1.GetOptions{}); err != nil {
log.Warn(err)
} else { } else {
for _, lb := range svc.Status.LoadBalancer.Ingress { for _, lb := range svc.Status.LoadBalancer.Ingress {
if lb.IP != "" { if lb.IP != "" {
@ -237,6 +241,7 @@ func (sc *gatewaySource) targetsFromIstioIngressStatus() (targets endpoint.Targe
} }
} }
} }
}
return return
} }
@ -253,7 +258,7 @@ func (sc *gatewaySource) endpointsFromGatewayConfig(config istiomodel.Config) ([
targets := getTargetsFromTargetAnnotation(config.Annotations) targets := getTargetsFromTargetAnnotation(config.Annotations)
if len(targets) == 0 { if len(targets) == 0 {
targets, err = sc.targetsFromIstioIngressStatus() targets, err = sc.targetsFromIstioIngressGatewayServices()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -44,7 +44,7 @@ var gatewayType = istiomodel.Gateway.Type
type GatewaySuite struct { type GatewaySuite struct {
suite.Suite suite.Suite
source Source source Source
ingress *v1.Service lbServices []*v1.Service
config istiomodel.Config config istiomodel.Config
} }
@ -53,17 +53,30 @@ func (suite *GatewaySuite) SetupTest() {
fakeIstioClient := NewFakeConfigStore() fakeIstioClient := NewFakeConfigStore()
var err error var err error
suite.ingress = (fakeIngressGateway{ suite.lbServices = []*v1.Service{
(fakeIngressGatewayService{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
hostnames: []string{"v1"}, hostnames: []string{"v1"},
}).Service() namespace: "istio-system",
_, err = fakeKubernetesClient.CoreV1().Services(suite.ingress.Namespace).Create(suite.ingress) name: "istio-gateway1",
}).Service(),
(fakeIngressGatewayService{
ips: []string{"1.1.1.1"},
hostnames: []string{"v42"},
namespace: "istio-other",
name: "istio-gateway2",
}).Service(),
}
for _, loadBalancer := range suite.lbServices {
_, err = fakeKubernetesClient.CoreV1().Services(loadBalancer.Namespace).Create(loadBalancer)
suite.NoError(err, "should succeed") suite.NoError(err, "should succeed")
}
suite.source, err = NewIstioGatewaySource( suite.source, err = NewIstioGatewaySource(
fakeKubernetesClient, fakeKubernetesClient,
fakeIstioClient, fakeIstioClient,
"istio-system/istio-ingressgateway", []string{"istio-system/istio-ingressgateway"},
"default", "default",
"", "",
"{{.Name}}", "{{.Name}}",
@ -137,7 +150,7 @@ func TestNewIstioGatewaySource(t *testing.T) {
_, err := NewIstioGatewaySource( _, err := NewIstioGatewaySource(
fake.NewSimpleClientset(), fake.NewSimpleClientset(),
NewFakeConfigStore(), NewFakeConfigStore(),
"istio-system/istio-ingressgateway", []string{"istio-system/istio-ingressgateway"},
"", "",
ti.annotationFilter, ti.annotationFilter,
ti.fqdnTemplate, ti.fqdnTemplate,
@ -156,15 +169,17 @@ func TestNewIstioGatewaySource(t *testing.T) {
func testEndpointsFromGatewayConfig(t *testing.T) { func testEndpointsFromGatewayConfig(t *testing.T) {
for _, ti := range []struct { for _, ti := range []struct {
title string title string
ingress fakeIngressGateway lbServices []fakeIngressGatewayService
config fakeGatewayConfig config fakeGatewayConfig
expected []*endpoint.Endpoint expected []*endpoint.Endpoint
}{ }{
{ {
title: "one rule.host one lb.hostname", title: "one rule.host one lb.hostname",
ingress: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
hostnames: []string{"lb.com"}, // Kubernetes omits the trailing dot hostnames: []string{"lb.com"}, // Kubernetes omits the trailing dot
}, },
},
config: fakeGatewayConfig{ config: fakeGatewayConfig{
dnsnames: [][]string{ dnsnames: [][]string{
{"foo.bar"}, // Kubernetes requires removal of trailing dot {"foo.bar"}, // Kubernetes requires removal of trailing dot
@ -179,9 +194,11 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
}, },
{ {
title: "one rule.host one lb.IP", title: "one rule.host one lb.IP",
ingress: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
config: fakeGatewayConfig{ config: fakeGatewayConfig{
dnsnames: [][]string{ dnsnames: [][]string{
{"foo.bar"}, {"foo.bar"},
@ -196,10 +213,12 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
}, },
{ {
title: "one rule.host two lb.IP and two lb.Hostname", title: "one rule.host two lb.IP and two lb.Hostname",
ingress: fakeIngressGateway{ 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"},
}, },
},
config: fakeGatewayConfig{ config: fakeGatewayConfig{
dnsnames: [][]string{ dnsnames: [][]string{
{"foo.bar"}, {"foo.bar"},
@ -218,10 +237,12 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
}, },
{ {
title: "no rule.host", title: "no rule.host",
ingress: fakeIngressGateway{ 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"},
}, },
},
config: fakeGatewayConfig{ config: fakeGatewayConfig{
dnsnames: [][]string{}, dnsnames: [][]string{},
}, },
@ -229,10 +250,12 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
}, },
{ {
title: "one empty rule.host", title: "one empty rule.host",
ingress: fakeIngressGateway{ 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"},
}, },
},
config: fakeGatewayConfig{ config: fakeGatewayConfig{
dnsnames: [][]string{ dnsnames: [][]string{
{""}, {""},
@ -242,7 +265,7 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
}, },
{ {
title: "no targets", title: "no targets",
ingress: fakeIngressGateway{}, lbServices: []fakeIngressGatewayService{{}},
config: fakeGatewayConfig{ config: fakeGatewayConfig{
dnsnames: [][]string{ dnsnames: [][]string{
{""}, {""},
@ -250,9 +273,35 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
}, },
expected: []*endpoint.Endpoint{}, expected: []*endpoint.Endpoint{},
}, },
{
title: "one gateway, two ingressgateway loadbalancer hostnames",
lbServices: []fakeIngressGatewayService{
{
hostnames: []string{"lb.com"},
namespace: "istio-other",
name: "gateway1",
},
{
hostnames: []string{"lb2.com"},
namespace: "istio-other",
name: "gateway2",
},
},
config: fakeGatewayConfig{
dnsnames: [][]string{
{"foo.bar"}, // Kubernetes requires removal of trailing dot
},
},
expected: []*endpoint.Endpoint{
{
DNSName: "foo.bar",
Targets: endpoint.Targets{"lb.com", "lb2.com"},
},
},
},
} { } {
t.Run(ti.title, func(t *testing.T) { t.Run(ti.title, func(t *testing.T) {
if source, err := newTestGatewaySource(ti.ingress.Service()); err != nil { if source, err := newTestGatewaySource(ti.lbServices); err != nil {
require.NoError(t, err) require.NoError(t, err)
} else if endpoints, err := source.endpointsFromGatewayConfig(ti.config.Config()); err != nil { } else if endpoints, err := source.endpointsFromGatewayConfig(ti.config.Config()); err != nil {
require.NoError(t, err) require.NoError(t, err)
@ -269,7 +318,7 @@ func testGatewayEndpoints(t *testing.T) {
title string title string
targetNamespace string targetNamespace string
annotationFilter string annotationFilter string
ingressGateway fakeIngressGateway lbServices []fakeIngressGatewayService
configItems []fakeGatewayConfig configItems []fakeGatewayConfig
expected []*endpoint.Endpoint expected []*endpoint.Endpoint
expectError bool expectError bool
@ -282,12 +331,14 @@ func testGatewayEndpoints(t *testing.T) {
targetNamespace: "", targetNamespace: "",
}, },
{ {
title: "two simple gateways", title: "two simple gateways, one ingressgateway loadbalancer service",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
hostnames: []string{"lb.com"}, hostnames: []string{"lb.com"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -320,12 +371,14 @@ func testGatewayEndpoints(t *testing.T) {
}, },
}, },
{ {
title: "two simple gateways on different namespaces", title: "two simple gateways on different namespaces, one ingressgateway loadbalancer service",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
hostnames: []string{"lb.com"}, hostnames: []string{"lb.com"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -358,12 +411,14 @@ func testGatewayEndpoints(t *testing.T) {
}, },
}, },
{ {
title: "two simple gateways on different namespaces with target namespace", title: "two simple gateways on different namespaces and a target namespace, one ingressgateway loadbalancer service",
targetNamespace: "testing1", targetNamespace: "testing1",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
hostnames: []string{"lb.com"}, hostnames: []string{"lb.com"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -391,9 +446,11 @@ func testGatewayEndpoints(t *testing.T) {
title: "valid matching annotation filter expression", title: "valid matching annotation filter expression",
targetNamespace: "", targetNamespace: "",
annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)", annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -415,9 +472,11 @@ func testGatewayEndpoints(t *testing.T) {
title: "valid non-matching annotation filter expression", title: "valid non-matching annotation filter expression",
targetNamespace: "", targetNamespace: "",
annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)", annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -434,9 +493,11 @@ func testGatewayEndpoints(t *testing.T) {
title: "invalid annotation filter expression", title: "invalid annotation filter expression",
targetNamespace: "", targetNamespace: "",
annotationFilter: "kubernetes.io/gateway.name in (a b)", annotationFilter: "kubernetes.io/gateway.name in (a b)",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -454,9 +515,11 @@ func testGatewayEndpoints(t *testing.T) {
title: "valid matching annotation filter label", title: "valid matching annotation filter label",
targetNamespace: "", targetNamespace: "",
annotationFilter: "kubernetes.io/gateway.class=nginx", annotationFilter: "kubernetes.io/gateway.class=nginx",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -478,9 +541,11 @@ func testGatewayEndpoints(t *testing.T) {
title: "valid non-matching annotation filter label", title: "valid non-matching annotation filter label",
targetNamespace: "", targetNamespace: "",
annotationFilter: "kubernetes.io/gateway.class=nginx", annotationFilter: "kubernetes.io/gateway.class=nginx",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -496,9 +561,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "our controller type is dns-controller", title: "our controller type is dns-controller",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -519,9 +586,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "different controller types are ignored", title: "different controller types are ignored",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -537,10 +606,12 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "template for gateway if host is missing", title: "template for gateway if host is missing",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
hostnames: []string{"elb.com"}, hostnames: []string{"elb.com"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -566,9 +637,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "another controller annotation skipped even with template", title: "another controller annotation skipped even with template",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -585,9 +658,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "multiple FQDN template hostnames", title: "multiple FQDN template hostnames",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -613,9 +688,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "multiple FQDN template hostnames", title: "multiple FQDN template hostnames",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -665,9 +742,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "gateway rules with annotation", title: "gateway rules with annotation",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -715,9 +794,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "gateway rules with hostname annotation", title: "gateway rules with hostname annotation",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"1.2.3.4"}, ips: []string{"1.2.3.4"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -744,9 +825,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "gateway rules with hostname annotation having multiple hostnames", title: "gateway rules with hostname annotation having multiple hostnames",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"1.2.3.4"}, ips: []string{"1.2.3.4"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -778,9 +861,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "gateway rules with hostname and target annotation", title: "gateway rules with hostname and target annotation",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{}, ips: []string{},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -808,9 +893,11 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "gateway rules with annotation and custom TTL", title: "gateway rules with annotation and custom TTL",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -847,10 +934,12 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "template for gateway with annotation", title: "template for gateway with annotation",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{}, ips: []string{},
hostnames: []string{}, hostnames: []string{},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -899,10 +988,12 @@ func testGatewayEndpoints(t *testing.T) {
{ {
title: "Ingress with empty annotation", title: "Ingress with empty annotation",
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{}, ips: []string{},
hostnames: []string{}, hostnames: []string{},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -920,10 +1011,12 @@ func testGatewayEndpoints(t *testing.T) {
title: "ignore hostname annotations", title: "ignore hostname annotations",
ignoreHostnameAnnotation: true, ignoreHostnameAnnotation: true,
targetNamespace: "", targetNamespace: "",
ingressGateway: fakeIngressGateway{ lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8"}, ips: []string{"8.8.8.8"},
hostnames: []string{"lb.com"}, hostnames: []string{"lb.com"},
}, },
},
configItems: []fakeGatewayConfig{ configItems: []fakeGatewayConfig{
{ {
name: "fake1", name: "fake1",
@ -969,10 +1062,17 @@ func testGatewayEndpoints(t *testing.T) {
} }
fakeKubernetesClient := fake.NewSimpleClientset() fakeKubernetesClient := fake.NewSimpleClientset()
ingressGatewayService := ti.ingressGateway.Service()
if _, err := fakeKubernetesClient.CoreV1().Services(ingressGatewayService.Namespace).Create(ingressGatewayService); err != nil { var fakeLoadBalancerList []string
for _, lb := range ti.lbServices {
lbService := lb.Service()
_, err := fakeKubernetesClient.CoreV1().Services(lbService.Namespace).Create(lbService)
if err != nil {
require.NoError(t, err) require.NoError(t, err)
} }
fakeLoadBalancerList = append(fakeLoadBalancerList, lbService.Namespace+"/"+lbService.Name)
}
fakeIstioClient := NewFakeConfigStore() fakeIstioClient := NewFakeConfigStore()
for _, config := range configs { for _, config := range configs {
_, err := fakeIstioClient.Create(config) _, err := fakeIstioClient.Create(config)
@ -982,7 +1082,7 @@ func testGatewayEndpoints(t *testing.T) {
gatewaySource, err := NewIstioGatewaySource( gatewaySource, err := NewIstioGatewaySource(
fakeKubernetesClient, fakeKubernetesClient,
fakeIstioClient, fakeIstioClient,
ingressGatewayService.Namespace+"/"+ingressGatewayService.Name, fakeLoadBalancerList,
ti.targetNamespace, ti.targetNamespace,
ti.annotationFilter, ti.annotationFilter,
ti.fqdnTemplate, ti.fqdnTemplate,
@ -1004,19 +1104,24 @@ func testGatewayEndpoints(t *testing.T) {
} }
// gateway specific helper functions // gateway specific helper functions
func newTestGatewaySource(ingress *v1.Service) (*gatewaySource, error) { func newTestGatewaySource(loadBalancerList []fakeIngressGatewayService) (*gatewaySource, error) {
fakeKubernetesClient := fake.NewSimpleClientset() fakeKubernetesClient := fake.NewSimpleClientset()
fakeIstioClient := NewFakeConfigStore() fakeIstioClient := NewFakeConfigStore()
_, err := fakeKubernetesClient.CoreV1().Services(ingress.Namespace).Create(ingress) var lbList []string
for _, lb := range loadBalancerList {
lbService := lb.Service()
_, err := fakeKubernetesClient.CoreV1().Services(lbService.Namespace).Create(lbService)
if err != nil { if err != nil {
return nil, err return nil, err
} }
lbList = append(lbList, lbService.Namespace+"/"+lbService.Name)
}
src, err := NewIstioGatewaySource( src, err := NewIstioGatewaySource(
fakeKubernetesClient, fakeKubernetesClient,
fakeIstioClient, fakeIstioClient,
"istio-system/istio-ingressgateway", lbList,
"default", "default",
"", "",
"{{.Name}}", "{{.Name}}",
@ -1035,16 +1140,18 @@ func newTestGatewaySource(ingress *v1.Service) (*gatewaySource, error) {
return gwsrc, nil return gwsrc, nil
} }
type fakeIngressGateway struct { type fakeIngressGatewayService struct {
ips []string ips []string
hostnames []string hostnames []string
namespace string
name string
} }
func (ig fakeIngressGateway) Service() *v1.Service { func (ig fakeIngressGatewayService) Service() *v1.Service {
svc := &v1.Service{ svc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Namespace: "istio-system", Namespace: ig.namespace,
Name: "istio-ingressgateway", Name: ig.name,
}, },
Status: v1.ServiceStatus{ Status: v1.ServiceStatus{
LoadBalancer: v1.LoadBalancerStatus{ LoadBalancer: v1.LoadBalancerStatus{

View File

@ -52,7 +52,7 @@ type Config struct {
KubeConfig string KubeConfig string
KubeMaster string KubeMaster string
ServiceTypeFilter []string ServiceTypeFilter []string
IstioIngressGateway string IstioIngressGatewayServices []string
} }
// ClientGenerator provides clients // ClientGenerator provides clients
@ -129,7 +129,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewIstioGatewaySource(kubernetesClient, istioClient, cfg.IstioIngressGateway, cfg.Namespace, cfg.AnnotationFilter, cfg.FQDNTemplate, cfg.CombineFQDNAndAnnotation, cfg.IgnoreHostnameAnnotation) return NewIstioGatewaySource(kubernetesClient, istioClient, cfg.IstioIngressGatewayServices, cfg.Namespace, cfg.AnnotationFilter, cfg.FQDNTemplate, cfg.CombineFQDNAndAnnotation, cfg.IgnoreHostnameAnnotation)
case "fake": case "fake":
return NewFakeSource(cfg.FQDNTemplate) return NewFakeSource(cfg.FQDNTemplate)
case "connector": case "connector":

View File

@ -113,5 +113,5 @@ func TestByNames(t *testing.T) {
} }
var minimalConfig = &Config{ var minimalConfig = &Config{
IstioIngressGateway: "istio-system/istio-ingressgateway", IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway"},
} }