diff --git a/docs/tutorials/istio.md b/docs/tutorials/istio.md index 4f74908c7..269c10bcb 100644 --- a/docs/tutorials/istio.md +++ b/docs/tutorials/istio.md @@ -25,7 +25,7 @@ spec: - --source=service - --source=ingress - --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 - --provider=aws - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization @@ -95,7 +95,7 @@ spec: - --source=service - --source=ingress - --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 - --provider=aws - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization diff --git a/main.go b/main.go index d5786c25a..5e2354cd4 100644 --- a/main.go +++ b/main.go @@ -67,21 +67,21 @@ func main() { // Create a source.Config from the flags passed by the user. sourceCfg := &source.Config{ - Namespace: cfg.Namespace, - AnnotationFilter: cfg.AnnotationFilter, - FQDNTemplate: cfg.FQDNTemplate, - CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation, - IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation, - Compatibility: cfg.Compatibility, - PublishInternal: cfg.PublishInternal, - PublishHostIP: cfg.PublishHostIP, - ConnectorServer: cfg.ConnectorSourceServer, - CRDSourceAPIVersion: cfg.CRDSourceAPIVersion, - CRDSourceKind: cfg.CRDSourceKind, - KubeConfig: cfg.KubeConfig, - KubeMaster: cfg.Master, - ServiceTypeFilter: cfg.ServiceTypeFilter, - IstioIngressGateway: cfg.IstioIngressGateway, + Namespace: cfg.Namespace, + AnnotationFilter: cfg.AnnotationFilter, + FQDNTemplate: cfg.FQDNTemplate, + CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation, + IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation, + Compatibility: cfg.Compatibility, + PublishInternal: cfg.PublishInternal, + PublishHostIP: cfg.PublishHostIP, + ConnectorServer: cfg.ConnectorSourceServer, + CRDSourceAPIVersion: cfg.CRDSourceAPIVersion, + CRDSourceKind: cfg.CRDSourceKind, + KubeConfig: cfg.KubeConfig, + KubeMaster: cfg.Master, + ServiceTypeFilter: cfg.ServiceTypeFilter, + IstioIngressGatewayServices: cfg.IstioIngressGatewayServices, } // Lookup all the selected sources by names and pass them the desired configuration. diff --git a/pkg/apis/externaldns/types.go b/pkg/apis/externaldns/types.go index 367c512e7..a3257fc1d 100644 --- a/pkg/apis/externaldns/types.go +++ b/pkg/apis/externaldns/types.go @@ -36,155 +36,155 @@ var ( // Config is a project-wide configuration type Config struct { - Master string - KubeConfig string - RequestTimeout time.Duration - IstioIngressGateway string - Sources []string - Namespace string - AnnotationFilter string - FQDNTemplate string - CombineFQDNAndAnnotation bool - IgnoreHostnameAnnotation bool - Compatibility string - PublishInternal bool - PublishHostIP bool - ConnectorSourceServer string - Provider string - GoogleProject string - DomainFilter []string - ZoneIDFilter []string - AlibabaCloudConfigFile string - AlibabaCloudZoneType string - AWSZoneType string - AWSZoneTagFilter []string - AWSAssumeRole string - AWSBatchChangeSize int - AWSBatchChangeInterval time.Duration - AWSEvaluateTargetHealth bool - AWSAPIRetries int - AzureConfigFile string - AzureResourceGroup string - CloudflareProxied bool - CloudflareZonesPerPage int - RcodezeroTXTEncrypt bool - InfobloxGridHost string - InfobloxWapiPort int - InfobloxWapiUsername string - InfobloxWapiPassword string - InfobloxWapiVersion string - InfobloxSSLVerify bool - InfobloxView string - DynCustomerName string - DynUsername string - DynPassword string - DynMinTTLSeconds int - OCIConfigFile string - InMemoryZones []string - PDNSServer string - PDNSAPIKey string - PDNSTLSEnabled bool - TLSCA string - TLSClientCert string - TLSClientCertKey string - Policy string - Registry string - TXTOwnerID string - TXTPrefix string - Interval time.Duration - Once bool - DryRun bool - LogFormat string - MetricsAddress string - LogLevel string - TXTCacheInterval time.Duration - ExoscaleEndpoint string - ExoscaleAPIKey string - ExoscaleAPISecret string - CRDSourceAPIVersion string - CRDSourceKind string - ServiceTypeFilter []string - RFC2136Host string - RFC2136Port int - RFC2136Zone string - RFC2136Insecure bool - RFC2136TSIGKeyName string - RFC2136TSIGSecret string - RFC2136TSIGSecretAlg string - RFC2136TAXFR bool + Master string + KubeConfig string + RequestTimeout time.Duration + IstioIngressGatewayServices []string + Sources []string + Namespace string + AnnotationFilter string + FQDNTemplate string + CombineFQDNAndAnnotation bool + IgnoreHostnameAnnotation bool + Compatibility string + PublishInternal bool + PublishHostIP bool + ConnectorSourceServer string + Provider string + GoogleProject string + DomainFilter []string + ZoneIDFilter []string + AlibabaCloudConfigFile string + AlibabaCloudZoneType string + AWSZoneType string + AWSZoneTagFilter []string + AWSAssumeRole string + AWSBatchChangeSize int + AWSBatchChangeInterval time.Duration + AWSEvaluateTargetHealth bool + AWSAPIRetries int + AzureConfigFile string + AzureResourceGroup string + CloudflareProxied bool + CloudflareZonesPerPage int + RcodezeroTXTEncrypt bool + InfobloxGridHost string + InfobloxWapiPort int + InfobloxWapiUsername string + InfobloxWapiPassword string + InfobloxWapiVersion string + InfobloxSSLVerify bool + InfobloxView string + DynCustomerName string + DynUsername string + DynPassword string + DynMinTTLSeconds int + OCIConfigFile string + InMemoryZones []string + PDNSServer string + PDNSAPIKey string + PDNSTLSEnabled bool + TLSCA string + TLSClientCert string + TLSClientCertKey string + Policy string + Registry string + TXTOwnerID string + TXTPrefix string + Interval time.Duration + Once bool + DryRun bool + LogFormat string + MetricsAddress string + LogLevel string + TXTCacheInterval time.Duration + ExoscaleEndpoint string + ExoscaleAPIKey string + ExoscaleAPISecret string + CRDSourceAPIVersion string + CRDSourceKind string + ServiceTypeFilter []string + RFC2136Host string + RFC2136Port int + RFC2136Zone string + RFC2136Insecure bool + RFC2136TSIGKeyName string + RFC2136TSIGSecret string + RFC2136TSIGSecretAlg string + RFC2136TAXFR bool } var defaultConfig = &Config{ - Master: "", - KubeConfig: "", - RequestTimeout: time.Second * 30, - IstioIngressGateway: "istio-system/istio-ingressgateway", - Sources: nil, - Namespace: "", - AnnotationFilter: "", - FQDNTemplate: "", - CombineFQDNAndAnnotation: false, - IgnoreHostnameAnnotation: false, - Compatibility: "", - PublishInternal: false, - PublishHostIP: false, - ConnectorSourceServer: "localhost:8080", - Provider: "", - GoogleProject: "", - DomainFilter: []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, - RcodezeroTXTEncrypt: false, - InfobloxGridHost: "", - InfobloxWapiPort: 443, - InfobloxWapiUsername: "admin", - InfobloxWapiPassword: "", - InfobloxWapiVersion: "2.3.1", - InfobloxSSLVerify: true, - InfobloxView: "", - OCIConfigFile: "/etc/kubernetes/oci.yaml", - InMemoryZones: []string{}, - PDNSServer: "http://localhost:8081", - PDNSAPIKey: "", - PDNSTLSEnabled: false, - TLSCA: "", - TLSClientCert: "", - TLSClientCertKey: "", - Policy: "sync", - Registry: "txt", - TXTOwnerID: "default", - TXTPrefix: "", - TXTCacheInterval: 0, - Interval: time.Minute, - Once: false, - DryRun: false, - LogFormat: "text", - MetricsAddress: ":7979", - LogLevel: logrus.InfoLevel.String(), - ExoscaleEndpoint: "https://api.exoscale.ch/dns", - ExoscaleAPIKey: "", - ExoscaleAPISecret: "", - CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1", - CRDSourceKind: "DNSEndpoint", - ServiceTypeFilter: []string{}, - RFC2136Host: "", - RFC2136Port: 0, - RFC2136Zone: "", - RFC2136Insecure: false, - RFC2136TSIGKeyName: "", - RFC2136TSIGSecret: "", - RFC2136TSIGSecretAlg: "", - RFC2136TAXFR: true, + Master: "", + KubeConfig: "", + RequestTimeout: time.Second * 30, + IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway"}, + Sources: nil, + Namespace: "", + AnnotationFilter: "", + FQDNTemplate: "", + CombineFQDNAndAnnotation: false, + IgnoreHostnameAnnotation: false, + Compatibility: "", + PublishInternal: false, + PublishHostIP: false, + ConnectorSourceServer: "localhost:8080", + Provider: "", + GoogleProject: "", + DomainFilter: []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, + RcodezeroTXTEncrypt: false, + InfobloxGridHost: "", + InfobloxWapiPort: 443, + InfobloxWapiUsername: "admin", + InfobloxWapiPassword: "", + InfobloxWapiVersion: "2.3.1", + InfobloxSSLVerify: true, + InfobloxView: "", + OCIConfigFile: "/etc/kubernetes/oci.yaml", + InMemoryZones: []string{}, + PDNSServer: "http://localhost:8081", + PDNSAPIKey: "", + PDNSTLSEnabled: false, + TLSCA: "", + TLSClientCert: "", + TLSClientCertKey: "", + Policy: "sync", + Registry: "txt", + TXTOwnerID: "default", + TXTPrefix: "", + TXTCacheInterval: 0, + Interval: time.Minute, + Once: false, + DryRun: false, + LogFormat: "text", + MetricsAddress: ":7979", + LogLevel: logrus.InfoLevel.String(), + ExoscaleEndpoint: "https://api.exoscale.ch/dns", + ExoscaleAPIKey: "", + ExoscaleAPISecret: "", + CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1", + CRDSourceKind: "DNSEndpoint", + ServiceTypeFilter: []string{}, + RFC2136Host: "", + RFC2136Port: 0, + RFC2136Zone: "", + RFC2136Insecure: false, + RFC2136TSIGKeyName: "", + RFC2136TSIGSecret: "", + RFC2136TSIGSecretAlg: "", + RFC2136TAXFR: true, } // NewConfig returns new Config object @@ -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) // 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 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") diff --git a/pkg/apis/externaldns/types_test.go b/pkg/apis/externaldns/types_test.go index b2aacbd09..24b3eddc4 100644 --- a/pkg/apis/externaldns/types_test.go +++ b/pkg/apis/externaldns/types_test.go @@ -29,120 +29,177 @@ import ( var ( minimalConfig = &Config{ - Master: "", - KubeConfig: "", - RequestTimeout: time.Second * 30, - IstioIngressGateway: "istio-system/istio-ingressgateway", - Sources: []string{"service"}, - 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, + Master: "", + KubeConfig: "", + RequestTimeout: time.Second * 30, + IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway"}, + Sources: []string{"service"}, + 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, } overriddenConfig = &Config{ - Master: "http://127.0.0.1:8080", - KubeConfig: "/some/path", - RequestTimeout: time.Second * 77, - IstioIngressGateway: "istio-other/istio-otheringressgateway", - Sources: []string{"service", "ingress", "connector"}, - Namespace: "namespace", - IgnoreHostnameAnnotation: true, - FQDNTemplate: "{{.Name}}.service.example.com", - Compatibility: "mate", - Provider: "google", - GoogleProject: "project", - DomainFilter: []string{"example.org", "company.com"}, - ZoneIDFilter: []string{"/hostedzone/ZTST1", "/hostedzone/ZTST2"}, - AlibabaCloudConfigFile: "/etc/kubernetes/alibaba-cloud.json", - AWSZoneType: "private", - AWSZoneTagFilter: []string{"tag=foo"}, - AWSAssumeRole: "some-other-role", - AWSBatchChangeSize: 100, - AWSBatchChangeInterval: time.Second * 2, - AWSEvaluateTargetHealth: false, - AWSAPIRetries: 13, - AzureConfigFile: "azure.json", - AzureResourceGroup: "arg", - CloudflareProxied: true, - CloudflareZonesPerPage: 20, - InfobloxGridHost: "127.0.0.1", - InfobloxWapiPort: 8443, - InfobloxWapiUsername: "infoblox", - InfobloxWapiPassword: "infoblox", - InfobloxWapiVersion: "2.6.1", - InfobloxView: "internal", - InfobloxSSLVerify: false, - OCIConfigFile: "oci.yaml", - InMemoryZones: []string{"example.org", "company.com"}, - PDNSServer: "http://ns.example.com:8081", - PDNSAPIKey: "some-secret-key", - PDNSTLSEnabled: true, - TLSCA: "/path/to/ca.crt", - TLSClientCert: "/path/to/cert.pem", - TLSClientCertKey: "/path/to/key.pem", - Policy: "upsert-only", - Registry: "noop", - TXTOwnerID: "owner-1", - TXTPrefix: "associated-txt-record", - TXTCacheInterval: 12 * time.Hour, - Interval: 10 * time.Minute, - Once: true, - DryRun: true, - LogFormat: "json", - MetricsAddress: "127.0.0.1:9099", - LogLevel: logrus.DebugLevel.String(), - ConnectorSourceServer: "localhost:8081", - ExoscaleEndpoint: "https://api.foo.ch/dns", - ExoscaleAPIKey: "1", - ExoscaleAPISecret: "2", - CRDSourceAPIVersion: "test.k8s.io/v1alpha1", - CRDSourceKind: "Endpoint", - RcodezeroTXTEncrypt: true, + Master: "http://127.0.0.1:8080", + KubeConfig: "/some/path", + RequestTimeout: time.Second * 77, + IstioIngressGatewayServices: []string{"istio-other/istio-otheringressgateway"}, + Sources: []string{"service", "ingress", "connector"}, + Namespace: "namespace", + IgnoreHostnameAnnotation: true, + FQDNTemplate: "{{.Name}}.service.example.com", + Compatibility: "mate", + Provider: "google", + GoogleProject: "project", + DomainFilter: []string{"example.org", "company.com"}, + ZoneIDFilter: []string{"/hostedzone/ZTST1", "/hostedzone/ZTST2"}, + AlibabaCloudConfigFile: "/etc/kubernetes/alibaba-cloud.json", + AWSZoneType: "private", + AWSZoneTagFilter: []string{"tag=foo"}, + AWSAssumeRole: "some-other-role", + AWSBatchChangeSize: 100, + AWSBatchChangeInterval: time.Second * 2, + AWSEvaluateTargetHealth: false, + AWSAPIRetries: 13, + AzureConfigFile: "azure.json", + AzureResourceGroup: "arg", + CloudflareProxied: true, + CloudflareZonesPerPage: 20, + InfobloxGridHost: "127.0.0.1", + InfobloxWapiPort: 8443, + InfobloxWapiUsername: "infoblox", + InfobloxWapiPassword: "infoblox", + InfobloxWapiVersion: "2.6.1", + InfobloxView: "internal", + InfobloxSSLVerify: false, + OCIConfigFile: "oci.yaml", + InMemoryZones: []string{"example.org", "company.com"}, + PDNSServer: "http://ns.example.com:8081", + PDNSAPIKey: "some-secret-key", + PDNSTLSEnabled: true, + TLSCA: "/path/to/ca.crt", + TLSClientCert: "/path/to/cert.pem", + TLSClientCertKey: "/path/to/key.pem", + Policy: "upsert-only", + Registry: "noop", + TXTOwnerID: "owner-1", + TXTPrefix: "associated-txt-record", + TXTCacheInterval: 12 * time.Hour, + Interval: 10 * time.Minute, + Once: true, + DryRun: true, + LogFormat: "json", + MetricsAddress: "127.0.0.1:9099", + LogLevel: logrus.DebugLevel.String(), + ConnectorSourceServer: "localhost:8081", + ExoscaleEndpoint: "https://api.foo.ch/dns", + ExoscaleAPIKey: "1", + ExoscaleAPISecret: "2", + CRDSourceAPIVersion: "test.k8s.io/v1alpha1", + CRDSourceKind: "Endpoint", + 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, } ) @@ -295,6 +352,27 @@ func TestParseFlags(t *testing.T) { }, 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) { originalEnv := setEnv(t, ti.envVars) diff --git a/source/gateway.go b/source/gateway.go index 9d34c16ca..751698da1 100644 --- a/source/gateway.go +++ b/source/gateway.go @@ -38,22 +38,21 @@ import ( // The gateway implementation uses the spec.servers.hosts values for the hostnames. // Use targetAnnotationKey to explicitly set Endpoint. type gatewaySource struct { - kubeClient kubernetes.Interface - istioClient istiomodel.ConfigStore - istioNamespace string - istioIngressGatewayName string - namespace string - annotationFilter string - fqdnTemplate *template.Template - combineFQDNAnnotation bool - ignoreHostnameAnnotation bool + kubeClient kubernetes.Interface + istioClient istiomodel.ConfigStore + istioIngressGatewayServices []string + namespace string + annotationFilter string + fqdnTemplate *template.Template + combineFQDNAnnotation bool + ignoreHostnameAnnotation bool } // NewIstioGatewaySource creates a new gatewaySource with the given config. func NewIstioGatewaySource( kubeClient kubernetes.Interface, istioClient istiomodel.ConfigStore, - istioIngressGateway string, + istioIngressGatewayServices []string, namespace string, annotationFilter string, fqdnTemplate string, @@ -64,9 +63,10 @@ func NewIstioGatewaySource( tmpl *template.Template err error ) - istioNamespace, istioIngressGatewayName, err := parseIngressGateway(istioIngressGateway) - if err != nil { - return nil, err + for _, lbService := range istioIngressGatewayServices { + if _, _, err = parseIngressGateway(lbService); err != nil { + return nil, err + } } if fqdnTemplate != "" { @@ -79,15 +79,14 @@ func NewIstioGatewaySource( } return &gatewaySource{ - kubeClient: kubeClient, - istioClient: istioClient, - istioNamespace: istioNamespace, - istioIngressGatewayName: istioIngressGatewayName, - namespace: namespace, - annotationFilter: annotationFilter, - fqdnTemplate: tmpl, - combineFQDNAnnotation: combineFqdnAnnotation, - ignoreHostnameAnnotation: ignoreHostnameAnnotation, + kubeClient: kubeClient, + istioClient: istioClient, + istioIngressGatewayServices: istioIngressGatewayServices, + namespace: namespace, + annotationFilter: annotationFilter, + fqdnTemplate: tmpl, + combineFQDNAnnotation: combineFqdnAnnotation, + ignoreHostnameAnnotation: ignoreHostnameAnnotation, }, nil } @@ -169,7 +168,7 @@ func (sc *gatewaySource) endpointsFromTemplate(config *istiomodel.Config) ([]*en targets := getTargetsFromTargetAnnotation(config.Annotations) if len(targets) == 0 { - targets, err = sc.targetsFromIstioIngressStatus() + targets, err = sc.targetsFromIstioIngressGatewayServices() if err != nil { return nil, err } @@ -224,16 +223,22 @@ func (sc *gatewaySource) setResourceLabel(config istiomodel.Config, endpoints [] } } -func (sc *gatewaySource) targetsFromIstioIngressStatus() (targets endpoint.Targets, err error) { - if svc, e := sc.kubeClient.CoreV1().Services(sc.istioNamespace).Get(sc.istioIngressGatewayName, metav1.GetOptions{}); e != nil { - err = e - } else { - for _, lb := range svc.Status.LoadBalancer.Ingress { - if lb.IP != "" { - targets = append(targets, lb.IP) - } - if lb.Hostname != "" { - targets = append(targets, lb.Hostname) +func (sc *gatewaySource) targetsFromIstioIngressGatewayServices() (targets endpoint.Targets, err error) { + for _, lbService := range sc.istioIngressGatewayServices { + 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 { + for _, lb := range svc.Status.LoadBalancer.Ingress { + if lb.IP != "" { + targets = append(targets, lb.IP) + } + if lb.Hostname != "" { + targets = append(targets, lb.Hostname) + } } } } @@ -253,7 +258,7 @@ func (sc *gatewaySource) endpointsFromGatewayConfig(config istiomodel.Config) ([ targets := getTargetsFromTargetAnnotation(config.Annotations) if len(targets) == 0 { - targets, err = sc.targetsFromIstioIngressStatus() + targets, err = sc.targetsFromIstioIngressGatewayServices() if err != nil { return nil, err } diff --git a/source/gateway_test.go b/source/gateway_test.go index c12a8389b..2d702f6eb 100644 --- a/source/gateway_test.go +++ b/source/gateway_test.go @@ -43,9 +43,9 @@ var gatewayType = istiomodel.Gateway.Type type GatewaySuite struct { suite.Suite - source Source - ingress *v1.Service - config istiomodel.Config + source Source + lbServices []*v1.Service + config istiomodel.Config } func (suite *GatewaySuite) SetupTest() { @@ -53,17 +53,30 @@ func (suite *GatewaySuite) SetupTest() { fakeIstioClient := NewFakeConfigStore() var err error - suite.ingress = (fakeIngressGateway{ - ips: []string{"8.8.8.8"}, - hostnames: []string{"v1"}, - }).Service() - _, err = fakeKubernetesClient.CoreV1().Services(suite.ingress.Namespace).Create(suite.ingress) - suite.NoError(err, "should succeed") + suite.lbServices = []*v1.Service{ + (fakeIngressGatewayService{ + ips: []string{"8.8.8.8"}, + hostnames: []string{"v1"}, + namespace: "istio-system", + 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.source, err = NewIstioGatewaySource( fakeKubernetesClient, fakeIstioClient, - "istio-system/istio-ingressgateway", + []string{"istio-system/istio-ingressgateway"}, "default", "", "{{.Name}}", @@ -137,7 +150,7 @@ func TestNewIstioGatewaySource(t *testing.T) { _, err := NewIstioGatewaySource( fake.NewSimpleClientset(), NewFakeConfigStore(), - "istio-system/istio-ingressgateway", + []string{"istio-system/istio-ingressgateway"}, "", ti.annotationFilter, ti.fqdnTemplate, @@ -155,15 +168,17 @@ func TestNewIstioGatewaySource(t *testing.T) { func testEndpointsFromGatewayConfig(t *testing.T) { for _, ti := range []struct { - title string - ingress fakeIngressGateway - config fakeGatewayConfig - expected []*endpoint.Endpoint + title string + lbServices []fakeIngressGatewayService + config fakeGatewayConfig + expected []*endpoint.Endpoint }{ { title: "one rule.host one lb.hostname", - ingress: fakeIngressGateway{ - hostnames: []string{"lb.com"}, // Kubernetes omits the trailing dot + lbServices: []fakeIngressGatewayService{ + { + hostnames: []string{"lb.com"}, // Kubernetes omits the trailing dot + }, }, config: fakeGatewayConfig{ dnsnames: [][]string{ @@ -179,8 +194,10 @@ func testEndpointsFromGatewayConfig(t *testing.T) { }, { title: "one rule.host one lb.IP", - ingress: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, config: fakeGatewayConfig{ dnsnames: [][]string{ @@ -196,9 +213,11 @@ func testEndpointsFromGatewayConfig(t *testing.T) { }, { title: "one rule.host two lb.IP and two lb.Hostname", - ingress: fakeIngressGateway{ - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + }, }, config: fakeGatewayConfig{ dnsnames: [][]string{ @@ -218,9 +237,11 @@ func testEndpointsFromGatewayConfig(t *testing.T) { }, { title: "no rule.host", - ingress: fakeIngressGateway{ - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + }, }, config: fakeGatewayConfig{ dnsnames: [][]string{}, @@ -229,9 +250,11 @@ func testEndpointsFromGatewayConfig(t *testing.T) { }, { title: "one empty rule.host", - ingress: fakeIngressGateway{ - ips: []string{"8.8.8.8", "127.0.0.1"}, - hostnames: []string{"elb.com", "alb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8", "127.0.0.1"}, + hostnames: []string{"elb.com", "alb.com"}, + }, }, config: fakeGatewayConfig{ dnsnames: [][]string{ @@ -241,8 +264,8 @@ func testEndpointsFromGatewayConfig(t *testing.T) { expected: []*endpoint.Endpoint{}, }, { - title: "no targets", - ingress: fakeIngressGateway{}, + title: "no targets", + lbServices: []fakeIngressGatewayService{{}}, config: fakeGatewayConfig{ dnsnames: [][]string{ {""}, @@ -250,9 +273,35 @@ func testEndpointsFromGatewayConfig(t *testing.T) { }, 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) { - if source, err := newTestGatewaySource(ti.ingress.Service()); err != nil { + if source, err := newTestGatewaySource(ti.lbServices); err != nil { require.NoError(t, err) } else if endpoints, err := source.endpointsFromGatewayConfig(ti.config.Config()); err != nil { require.NoError(t, err) @@ -269,7 +318,7 @@ func testGatewayEndpoints(t *testing.T) { title string targetNamespace string annotationFilter string - ingressGateway fakeIngressGateway + lbServices []fakeIngressGatewayService configItems []fakeGatewayConfig expected []*endpoint.Endpoint expectError bool @@ -282,11 +331,13 @@ func testGatewayEndpoints(t *testing.T) { targetNamespace: "", }, { - title: "two simple gateways", + title: "two simple gateways, one ingressgateway loadbalancer service", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, - hostnames: []string{"lb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + hostnames: []string{"lb.com"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -320,11 +371,13 @@ func testGatewayEndpoints(t *testing.T) { }, }, { - title: "two simple gateways on different namespaces", + title: "two simple gateways on different namespaces, one ingressgateway loadbalancer service", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, - hostnames: []string{"lb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + hostnames: []string{"lb.com"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -358,11 +411,13 @@ 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", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, - hostnames: []string{"lb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + hostnames: []string{"lb.com"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -391,8 +446,10 @@ func testGatewayEndpoints(t *testing.T) { title: "valid matching annotation filter expression", targetNamespace: "", annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -415,8 +472,10 @@ func testGatewayEndpoints(t *testing.T) { title: "valid non-matching annotation filter expression", targetNamespace: "", annotationFilter: "kubernetes.io/gateway.class in (alb, nginx)", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -434,8 +493,10 @@ func testGatewayEndpoints(t *testing.T) { title: "invalid annotation filter expression", targetNamespace: "", annotationFilter: "kubernetes.io/gateway.name in (a b)", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -454,8 +515,10 @@ func testGatewayEndpoints(t *testing.T) { title: "valid matching annotation filter label", targetNamespace: "", annotationFilter: "kubernetes.io/gateway.class=nginx", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -478,8 +541,10 @@ func testGatewayEndpoints(t *testing.T) { title: "valid non-matching annotation filter label", targetNamespace: "", annotationFilter: "kubernetes.io/gateway.class=nginx", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -496,8 +561,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "our controller type is dns-controller", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -519,8 +586,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "different controller types are ignored", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -537,9 +606,11 @@ func testGatewayEndpoints(t *testing.T) { { title: "template for gateway if host is missing", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, - hostnames: []string{"elb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + hostnames: []string{"elb.com"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -566,8 +637,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "another controller annotation skipped even with template", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -585,8 +658,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "multiple FQDN template hostnames", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -613,8 +688,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "multiple FQDN template hostnames", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -665,8 +742,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "gateway rules with annotation", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -715,8 +794,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "gateway rules with hostname annotation", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"1.2.3.4"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"1.2.3.4"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -744,8 +825,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "gateway rules with hostname annotation having multiple hostnames", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"1.2.3.4"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"1.2.3.4"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -778,8 +861,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "gateway rules with hostname and target annotation", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{}, + }, }, configItems: []fakeGatewayConfig{ { @@ -808,8 +893,10 @@ func testGatewayEndpoints(t *testing.T) { { title: "gateway rules with annotation and custom TTL", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -847,9 +934,11 @@ func testGatewayEndpoints(t *testing.T) { { title: "template for gateway with annotation", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{}, - hostnames: []string{}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{}, + hostnames: []string{}, + }, }, configItems: []fakeGatewayConfig{ { @@ -899,9 +988,11 @@ func testGatewayEndpoints(t *testing.T) { { title: "Ingress with empty annotation", targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{}, - hostnames: []string{}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{}, + hostnames: []string{}, + }, }, configItems: []fakeGatewayConfig{ { @@ -920,9 +1011,11 @@ func testGatewayEndpoints(t *testing.T) { title: "ignore hostname annotations", ignoreHostnameAnnotation: true, targetNamespace: "", - ingressGateway: fakeIngressGateway{ - ips: []string{"8.8.8.8"}, - hostnames: []string{"lb.com"}, + lbServices: []fakeIngressGatewayService{ + { + ips: []string{"8.8.8.8"}, + hostnames: []string{"lb.com"}, + }, }, configItems: []fakeGatewayConfig{ { @@ -969,10 +1062,17 @@ func testGatewayEndpoints(t *testing.T) { } fakeKubernetesClient := fake.NewSimpleClientset() - ingressGatewayService := ti.ingressGateway.Service() - if _, err := fakeKubernetesClient.CoreV1().Services(ingressGatewayService.Namespace).Create(ingressGatewayService); err != nil { - require.NoError(t, err) + + 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) + } + fakeLoadBalancerList = append(fakeLoadBalancerList, lbService.Namespace+"/"+lbService.Name) } + fakeIstioClient := NewFakeConfigStore() for _, config := range configs { _, err := fakeIstioClient.Create(config) @@ -982,7 +1082,7 @@ func testGatewayEndpoints(t *testing.T) { gatewaySource, err := NewIstioGatewaySource( fakeKubernetesClient, fakeIstioClient, - ingressGatewayService.Namespace+"/"+ingressGatewayService.Name, + fakeLoadBalancerList, ti.targetNamespace, ti.annotationFilter, ti.fqdnTemplate, @@ -1004,19 +1104,24 @@ func testGatewayEndpoints(t *testing.T) { } // gateway specific helper functions -func newTestGatewaySource(ingress *v1.Service) (*gatewaySource, error) { +func newTestGatewaySource(loadBalancerList []fakeIngressGatewayService) (*gatewaySource, error) { fakeKubernetesClient := fake.NewSimpleClientset() fakeIstioClient := NewFakeConfigStore() - _, err := fakeKubernetesClient.CoreV1().Services(ingress.Namespace).Create(ingress) - if err != nil { - return nil, err + var lbList []string + for _, lb := range loadBalancerList { + lbService := lb.Service() + _, err := fakeKubernetesClient.CoreV1().Services(lbService.Namespace).Create(lbService) + if err != nil { + return nil, err + } + lbList = append(lbList, lbService.Namespace+"/"+lbService.Name) } src, err := NewIstioGatewaySource( fakeKubernetesClient, fakeIstioClient, - "istio-system/istio-ingressgateway", + lbList, "default", "", "{{.Name}}", @@ -1035,16 +1140,18 @@ func newTestGatewaySource(ingress *v1.Service) (*gatewaySource, error) { return gwsrc, nil } -type fakeIngressGateway struct { +type fakeIngressGatewayService struct { ips []string hostnames []string + namespace string + name string } -func (ig fakeIngressGateway) Service() *v1.Service { +func (ig fakeIngressGatewayService) Service() *v1.Service { svc := &v1.Service{ ObjectMeta: metav1.ObjectMeta{ - Namespace: "istio-system", - Name: "istio-ingressgateway", + Namespace: ig.namespace, + Name: ig.name, }, Status: v1.ServiceStatus{ LoadBalancer: v1.LoadBalancerStatus{ diff --git a/source/store.go b/source/store.go index 01d3ef76f..4a143e13d 100644 --- a/source/store.go +++ b/source/store.go @@ -38,21 +38,21 @@ var ErrSourceNotFound = errors.New("source not found") // Config holds shared configuration options for all Sources. type Config struct { - Namespace string - AnnotationFilter string - FQDNTemplate string - CombineFQDNAndAnnotation bool - IgnoreHostnameAnnotation bool - Compatibility string - PublishInternal bool - PublishHostIP bool - ConnectorServer string - CRDSourceAPIVersion string - CRDSourceKind string - KubeConfig string - KubeMaster string - ServiceTypeFilter []string - IstioIngressGateway string + Namespace string + AnnotationFilter string + FQDNTemplate string + CombineFQDNAndAnnotation bool + IgnoreHostnameAnnotation bool + Compatibility string + PublishInternal bool + PublishHostIP bool + ConnectorServer string + CRDSourceAPIVersion string + CRDSourceKind string + KubeConfig string + KubeMaster string + ServiceTypeFilter []string + IstioIngressGatewayServices []string } // ClientGenerator provides clients @@ -129,7 +129,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err if err != nil { 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": return NewFakeSource(cfg.FQDNTemplate) case "connector": diff --git a/source/store_test.go b/source/store_test.go index 1ba8ad115..08045a0a8 100644 --- a/source/store_test.go +++ b/source/store_test.go @@ -113,5 +113,5 @@ func TestByNames(t *testing.T) { } var minimalConfig = &Config{ - IstioIngressGateway: "istio-system/istio-ingressgateway", + IstioIngressGatewayServices: []string{"istio-system/istio-ingressgateway"}, }