mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 09:36:58 +02:00
Merge pull request #1005 from devkid/feature/headless-services-publishnotreadyaddresses
Headless service: retrieve endpoints via Endpoints resource; evaluate spec.publishNotReadyAddresses
This commit is contained in:
commit
a563022e8a
@ -95,10 +95,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
@ -192,4 +189,4 @@ spec:
|
|||||||
|
|
||||||
|
|
||||||
**Important!**: Don't run dig, nslookup or similar immediately. You'll get hit by [negative DNS caching](https://tools.ietf.org/html/rfc2308), which is hard to flush.
|
**Important!**: Don't run dig, nslookup or similar immediately. You'll get hit by [negative DNS caching](https://tools.ietf.org/html/rfc2308), which is hard to flush.
|
||||||
Wait about 30s-1m (interval for external-dns to kick in)
|
Wait about 30s-1m (interval for external-dns to kick in)
|
||||||
|
@ -147,10 +147,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -108,10 +108,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -172,10 +172,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -194,10 +194,7 @@ metadata:
|
|||||||
name: externaldns
|
name: externaldns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
@ -268,10 +265,7 @@ metadata:
|
|||||||
name: externaldns
|
name: externaldns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
@ -399,4 +393,4 @@ $ az network private-dns record-set a list -g externaldns -z example.com
|
|||||||
|
|
||||||
Substitute the zone for the one created above if a different domain was used.
|
Substitute the zone for the one created above if a different domain was used.
|
||||||
|
|
||||||
This should show the external IP address of the service as the A record for your domain ('@' indicates the record is for the zone itself).
|
This should show the external IP address of the service as the A record for your domain ('@' indicates the record is for the zone itself).
|
||||||
|
@ -221,10 +221,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
@ -298,10 +295,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -75,10 +75,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -48,10 +48,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -128,10 +128,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -93,7 +93,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods"]
|
resources: ["pods"]
|
||||||
|
@ -69,10 +69,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -60,10 +60,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -72,10 +72,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -116,10 +116,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -56,10 +56,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -109,10 +109,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -54,10 +54,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -65,10 +65,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -222,10 +222,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -85,10 +85,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -51,10 +51,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -76,7 +76,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -80,10 +80,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -76,10 +76,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -144,6 +144,8 @@ rules:
|
|||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- services
|
- services
|
||||||
|
- endpoints
|
||||||
|
- pods
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- watch
|
- watch
|
||||||
|
@ -67,10 +67,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
@ -97,10 +97,7 @@ metadata:
|
|||||||
name: external-dns
|
name: external-dns
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services","endpoints","pods"]
|
||||||
verbs: ["get","watch","list"]
|
|
||||||
- apiGroups: [""]
|
|
||||||
resources: ["pods"]
|
|
||||||
verbs: ["get","watch","list"]
|
verbs: ["get","watch","list"]
|
||||||
- apiGroups: ["extensions"]
|
- apiGroups: ["extensions"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
|
39
main.go
39
main.go
@ -71,25 +71,26 @@ func main() {
|
|||||||
|
|
||||||
// Create a source.Config from the flags passed by the user.
|
// Create a source.Config from the flags passed by the user.
|
||||||
sourceCfg := &source.Config{
|
sourceCfg := &source.Config{
|
||||||
Namespace: cfg.Namespace,
|
Namespace: cfg.Namespace,
|
||||||
AnnotationFilter: cfg.AnnotationFilter,
|
AnnotationFilter: cfg.AnnotationFilter,
|
||||||
FQDNTemplate: cfg.FQDNTemplate,
|
FQDNTemplate: cfg.FQDNTemplate,
|
||||||
CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation,
|
CombineFQDNAndAnnotation: cfg.CombineFQDNAndAnnotation,
|
||||||
IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation,
|
IgnoreHostnameAnnotation: cfg.IgnoreHostnameAnnotation,
|
||||||
Compatibility: cfg.Compatibility,
|
Compatibility: cfg.Compatibility,
|
||||||
PublishInternal: cfg.PublishInternal,
|
PublishInternal: cfg.PublishInternal,
|
||||||
PublishHostIP: cfg.PublishHostIP,
|
PublishHostIP: cfg.PublishHostIP,
|
||||||
ConnectorServer: cfg.ConnectorSourceServer,
|
AlwaysPublishNotReadyAddresses: cfg.AlwaysPublishNotReadyAddresses,
|
||||||
CRDSourceAPIVersion: cfg.CRDSourceAPIVersion,
|
ConnectorServer: cfg.ConnectorSourceServer,
|
||||||
CRDSourceKind: cfg.CRDSourceKind,
|
CRDSourceAPIVersion: cfg.CRDSourceAPIVersion,
|
||||||
KubeConfig: cfg.KubeConfig,
|
CRDSourceKind: cfg.CRDSourceKind,
|
||||||
KubeMaster: cfg.Master,
|
KubeConfig: cfg.KubeConfig,
|
||||||
ServiceTypeFilter: cfg.ServiceTypeFilter,
|
KubeMaster: cfg.Master,
|
||||||
IstioIngressGatewayServices: cfg.IstioIngressGatewayServices,
|
ServiceTypeFilter: cfg.ServiceTypeFilter,
|
||||||
CFAPIEndpoint: cfg.CFAPIEndpoint,
|
IstioIngressGatewayServices: cfg.IstioIngressGatewayServices,
|
||||||
CFUsername: cfg.CFUsername,
|
CFAPIEndpoint: cfg.CFAPIEndpoint,
|
||||||
CFPassword: cfg.CFPassword,
|
CFUsername: cfg.CFUsername,
|
||||||
ContourLoadBalancerService: cfg.ContourLoadBalancerService,
|
CFPassword: cfg.CFPassword,
|
||||||
|
ContourLoadBalancerService: cfg.ContourLoadBalancerService,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -51,6 +51,7 @@ type Config struct {
|
|||||||
Compatibility string
|
Compatibility string
|
||||||
PublishInternal bool
|
PublishInternal bool
|
||||||
PublishHostIP bool
|
PublishHostIP bool
|
||||||
|
AlwaysPublishNotReadyAddresses bool
|
||||||
ConnectorSourceServer string
|
ConnectorSourceServer string
|
||||||
Provider string
|
Provider string
|
||||||
GoogleProject string
|
GoogleProject string
|
||||||
@ -295,6 +296,7 @@ func (cfg *Config) ParseFlags(args []string) error {
|
|||||||
app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule")
|
app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule")
|
||||||
app.Flag("publish-internal-services", "Allow external-dns to publish DNS records for ClusterIP services (optional)").BoolVar(&cfg.PublishInternal)
|
app.Flag("publish-internal-services", "Allow external-dns to publish DNS records for ClusterIP services (optional)").BoolVar(&cfg.PublishInternal)
|
||||||
app.Flag("publish-host-ip", "Allow external-dns to publish host-ip for headless services (optional)").BoolVar(&cfg.PublishHostIP)
|
app.Flag("publish-host-ip", "Allow external-dns to publish host-ip for headless services (optional)").BoolVar(&cfg.PublishHostIP)
|
||||||
|
app.Flag("always-publish-not-ready-addresses", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses)
|
||||||
app.Flag("connector-source-server", "The server to connect for connector source, valid only when using connector source").Default(defaultConfig.ConnectorSourceServer).StringVar(&cfg.ConnectorSourceServer)
|
app.Flag("connector-source-server", "The server to connect for connector source, valid only when using connector source").Default(defaultConfig.ConnectorSourceServer).StringVar(&cfg.ConnectorSourceServer)
|
||||||
app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion)
|
app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion)
|
||||||
app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind)
|
app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind)
|
||||||
|
@ -51,22 +51,25 @@ type serviceSource struct {
|
|||||||
client kubernetes.Interface
|
client kubernetes.Interface
|
||||||
namespace string
|
namespace string
|
||||||
annotationFilter string
|
annotationFilter string
|
||||||
|
|
||||||
// process Services with legacy annotations
|
// process Services with legacy annotations
|
||||||
compatibility string
|
compatibility string
|
||||||
fqdnTemplate *template.Template
|
fqdnTemplate *template.Template
|
||||||
combineFQDNAnnotation bool
|
combineFQDNAnnotation bool
|
||||||
ignoreHostnameAnnotation bool
|
ignoreHostnameAnnotation bool
|
||||||
publishInternal bool
|
publishInternal bool
|
||||||
publishHostIP bool
|
publishHostIP bool
|
||||||
serviceInformer coreinformers.ServiceInformer
|
alwaysPublishNotReadyAddresses bool
|
||||||
podInformer coreinformers.PodInformer
|
serviceInformer coreinformers.ServiceInformer
|
||||||
nodeInformer coreinformers.NodeInformer
|
endpointsInformer coreinformers.EndpointsInformer
|
||||||
serviceTypeFilter map[string]struct{}
|
podInformer coreinformers.PodInformer
|
||||||
runner *async.BoundedFrequencyRunner
|
nodeInformer coreinformers.NodeInformer
|
||||||
|
serviceTypeFilter map[string]struct{}
|
||||||
|
runner *async.BoundedFrequencyRunner
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServiceSource creates a new serviceSource with the given config.
|
// NewServiceSource creates a new serviceSource with the given config.
|
||||||
func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilter string, fqdnTemplate string, combineFqdnAnnotation bool, compatibility string, publishInternal bool, publishHostIP bool, serviceTypeFilter []string, ignoreHostnameAnnotation bool) (Source, error) {
|
func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilter string, fqdnTemplate string, combineFqdnAnnotation bool, compatibility string, publishInternal bool, publishHostIP bool, alwaysPublishNotReadyAddresses bool, serviceTypeFilter []string, ignoreHostnameAnnotation bool) (Source, error) {
|
||||||
var (
|
var (
|
||||||
tmpl *template.Template
|
tmpl *template.Template
|
||||||
err error
|
err error
|
||||||
@ -84,6 +87,7 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt
|
|||||||
// Set resync period to 0, to prevent processing when nothing has changed
|
// Set resync period to 0, to prevent processing when nothing has changed
|
||||||
informerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, 0, kubeinformers.WithNamespace(namespace))
|
informerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, 0, kubeinformers.WithNamespace(namespace))
|
||||||
serviceInformer := informerFactory.Core().V1().Services()
|
serviceInformer := informerFactory.Core().V1().Services()
|
||||||
|
endpointsInformer := informerFactory.Core().V1().Endpoints()
|
||||||
podInformer := informerFactory.Core().V1().Pods()
|
podInformer := informerFactory.Core().V1().Pods()
|
||||||
nodeInformer := informerFactory.Core().V1().Nodes()
|
nodeInformer := informerFactory.Core().V1().Nodes()
|
||||||
|
|
||||||
@ -94,6 +98,12 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
endpointsInformer.Informer().AddEventHandler(
|
||||||
|
cache.ResourceEventHandlerFuncs{
|
||||||
|
AddFunc: func(obj interface{}) {
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
podInformer.Informer().AddEventHandler(
|
podInformer.Informer().AddEventHandler(
|
||||||
cache.ResourceEventHandlerFuncs{
|
cache.ResourceEventHandlerFuncs{
|
||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
@ -126,19 +136,21 @@ func NewServiceSource(kubeClient kubernetes.Interface, namespace, annotationFilt
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &serviceSource{
|
return &serviceSource{
|
||||||
client: kubeClient,
|
client: kubeClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
annotationFilter: annotationFilter,
|
annotationFilter: annotationFilter,
|
||||||
compatibility: compatibility,
|
compatibility: compatibility,
|
||||||
fqdnTemplate: tmpl,
|
fqdnTemplate: tmpl,
|
||||||
combineFQDNAnnotation: combineFqdnAnnotation,
|
combineFQDNAnnotation: combineFqdnAnnotation,
|
||||||
ignoreHostnameAnnotation: ignoreHostnameAnnotation,
|
ignoreHostnameAnnotation: ignoreHostnameAnnotation,
|
||||||
publishInternal: publishInternal,
|
publishInternal: publishInternal,
|
||||||
publishHostIP: publishHostIP,
|
publishHostIP: publishHostIP,
|
||||||
serviceInformer: serviceInformer,
|
alwaysPublishNotReadyAddresses: alwaysPublishNotReadyAddresses,
|
||||||
podInformer: podInformer,
|
serviceInformer: serviceInformer,
|
||||||
nodeInformer: nodeInformer,
|
endpointsInformer: endpointsInformer,
|
||||||
serviceTypeFilter: serviceTypes,
|
podInformer: podInformer,
|
||||||
|
nodeInformer: nodeInformer,
|
||||||
|
serviceTypeFilter: serviceTypes,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +219,7 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) {
|
|||||||
return endpoints, nil
|
return endpoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractHeadlessEndpoints extracts endpoints from a headless service using the "Endpoints" Kubernetes API resource
|
||||||
func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname string, ttl endpoint.TTL) []*endpoint.Endpoint {
|
func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname string, ttl endpoint.TTL) []*endpoint.Endpoint {
|
||||||
var endpoints []*endpoint.Endpoint
|
var endpoints []*endpoint.Endpoint
|
||||||
|
|
||||||
@ -219,6 +232,12 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endpointsObject, err := sc.endpointsInformer.Lister().Endpoints(svc.Namespace).Get(svc.GetName())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Get endpoints of service[%s] error:%v", svc.GetName(), err)
|
||||||
|
return endpoints
|
||||||
|
}
|
||||||
|
|
||||||
pods, err := sc.podInformer.Lister().Pods(svc.Namespace).List(selector)
|
pods, err := sc.podInformer.Lister().Pods(svc.Namespace).List(selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("List Pods of service[%s] error:%v", svc.GetName(), err)
|
log.Errorf("List Pods of service[%s] error:%v", svc.GetName(), err)
|
||||||
@ -226,32 +245,47 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetsByHeadlessDomain := make(map[string][]string)
|
targetsByHeadlessDomain := make(map[string][]string)
|
||||||
for _, v := range pods {
|
for _, subset := range endpointsObject.Subsets {
|
||||||
headlessDomains := []string{hostname}
|
addresses := subset.Addresses
|
||||||
|
if svc.Spec.PublishNotReadyAddresses || sc.alwaysPublishNotReadyAddresses {
|
||||||
if v.Spec.Hostname != "" {
|
addresses = append(addresses, subset.NotReadyAddresses...)
|
||||||
headlessDomains = append(headlessDomains, fmt.Sprintf("%s.%s", v.Spec.Hostname, hostname))
|
|
||||||
}
|
}
|
||||||
for _, headlessDomain := range headlessDomains {
|
|
||||||
if sc.publishHostIP {
|
for _, address := range addresses {
|
||||||
log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, v.Status.HostIP)
|
// find pod for this address
|
||||||
// To reduce traffic on the DNS API only add record for running Pods. Good Idea?
|
if address.TargetRef.APIVersion != "" || address.TargetRef.Kind != "Pod" {
|
||||||
if v.Status.Phase == v1.PodRunning {
|
log.Debugf("Skipping address because its target is not a pod: %v", address)
|
||||||
targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], v.Status.HostIP)
|
continue
|
||||||
} else {
|
}
|
||||||
log.Debugf("Pod %s is not in running phase", v.Spec.Hostname)
|
var pod *v1.Pod
|
||||||
}
|
for _, v := range pods {
|
||||||
} else {
|
if v.Name == address.TargetRef.Name {
|
||||||
log.Debugf("Generating matching endpoint %s with PodIP %s", headlessDomain, v.Status.PodIP)
|
pod = v
|
||||||
// To reduce traffice on the DNS API only add record for running Pods. Good Idea?
|
break
|
||||||
if v.Status.Phase == v1.PodRunning {
|
|
||||||
targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], v.Status.PodIP)
|
|
||||||
} else {
|
|
||||||
log.Debugf("Pod %s is not in running phase", v.Spec.Hostname)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if pod == nil {
|
||||||
|
log.Errorf("Pod %s not found for address %v", address.TargetRef.Name, address)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
headlessDomains := []string{hostname}
|
||||||
|
if pod.Spec.Hostname != "" {
|
||||||
|
headlessDomains = append(headlessDomains, fmt.Sprintf("%s.%s", pod.Spec.Hostname, hostname))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, headlessDomain := range headlessDomains {
|
||||||
|
var ep string
|
||||||
|
if sc.publishHostIP {
|
||||||
|
ep = pod.Status.HostIP
|
||||||
|
log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, ep)
|
||||||
|
} else {
|
||||||
|
ep = address.IP
|
||||||
|
log.Debugf("Generating matching endpoint %s with EndpointAddress IP %s", headlessDomain, ep)
|
||||||
|
}
|
||||||
|
targetsByHeadlessDomain[headlessDomain] = append(targetsByHeadlessDomain[headlessDomain], ep)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
headlessDomains := []string{}
|
headlessDomains := []string{}
|
||||||
|
@ -51,6 +51,7 @@ func (suite *ServiceSuite) SetupTest() {
|
|||||||
"",
|
"",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
[]string{},
|
[]string{},
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
@ -143,6 +144,7 @@ func testServiceSourceNewServiceSource(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
ti.serviceTypesFilter,
|
ti.serviceTypesFilter,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
@ -1107,6 +1109,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
|||||||
tc.compatibility,
|
tc.compatibility,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
tc.serviceTypesFilter,
|
tc.serviceTypesFilter,
|
||||||
tc.ignoreHostnameAnnotation,
|
tc.ignoreHostnameAnnotation,
|
||||||
)
|
)
|
||||||
@ -1277,6 +1280,7 @@ func TestClusterIpServices(t *testing.T) {
|
|||||||
tc.compatibility,
|
tc.compatibility,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
[]string{},
|
[]string{},
|
||||||
tc.ignoreHostnameAnnotation,
|
tc.ignoreHostnameAnnotation,
|
||||||
)
|
)
|
||||||
@ -1608,6 +1612,7 @@ func TestNodePortServices(t *testing.T) {
|
|||||||
tc.compatibility,
|
tc.compatibility,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
[]string{},
|
[]string{},
|
||||||
tc.ignoreHostnameAnnotation,
|
tc.ignoreHostnameAnnotation,
|
||||||
)
|
)
|
||||||
@ -1645,7 +1650,8 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
lbs []string
|
lbs []string
|
||||||
podnames []string
|
podnames []string
|
||||||
hostnames []string
|
hostnames []string
|
||||||
phases []v1.PodPhase
|
podsReady []bool
|
||||||
|
publishNotReadyAddresses bool
|
||||||
expected []*endpoint.Endpoint
|
expected []*endpoint.Endpoint
|
||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
@ -1670,7 +1676,8 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}},
|
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}},
|
||||||
@ -1699,7 +1706,8 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{},
|
[]*endpoint.Endpoint{},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@ -1725,7 +1733,8 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)},
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)},
|
||||||
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)},
|
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)},
|
||||||
@ -1754,13 +1763,44 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodFailed},
|
[]bool{true, false},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"annotated Headless services return endpoints for all Pod if publishNotReadyAddresses is set",
|
||||||
|
"",
|
||||||
|
"testing",
|
||||||
|
"foo",
|
||||||
|
v1.ServiceTypeClusterIP,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
map[string]string{"component": "foo"},
|
||||||
|
map[string]string{
|
||||||
|
hostnameAnnotationKey: "service.example.org",
|
||||||
|
},
|
||||||
|
v1.ClusterIPNone,
|
||||||
|
[]string{"1.1.1.1", "1.1.1.2"},
|
||||||
|
map[string]string{
|
||||||
|
"component": "foo",
|
||||||
|
},
|
||||||
|
[]string{},
|
||||||
|
[]string{"foo-0", "foo-1"},
|
||||||
|
[]string{"foo-0", "foo-1"},
|
||||||
|
[]bool{true, false},
|
||||||
|
true,
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
|
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}},
|
||||||
|
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"annotated Headless services return endpoints for pods missing hostname",
|
"annotated Headless services return endpoints for pods missing hostname",
|
||||||
"",
|
"",
|
||||||
@ -1782,7 +1822,8 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"", ""},
|
[]string{"", ""},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}},
|
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}},
|
||||||
},
|
},
|
||||||
@ -1822,9 +1863,10 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
|
|
||||||
service := &v1.Service{
|
service := &v1.Service{
|
||||||
Spec: v1.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
Type: tc.svcType,
|
Type: tc.svcType,
|
||||||
ClusterIP: tc.clusterIP,
|
ClusterIP: tc.clusterIP,
|
||||||
Selector: tc.selector,
|
Selector: tc.selector,
|
||||||
|
PublishNotReadyAddresses: tc.publishNotReadyAddresses,
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: tc.svcNamespace,
|
Namespace: tc.svcNamespace,
|
||||||
@ -1837,6 +1879,7 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
_, err := kubernetes.CoreV1().Services(service.Namespace).Create(service)
|
_, err := kubernetes.CoreV1().Services(service.Namespace).Create(service)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var addresses, notReadyAddresses []v1.EndpointAddress
|
||||||
for i, podname := range tc.podnames {
|
for i, podname := range tc.podnames {
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
Spec: v1.PodSpec{
|
Spec: v1.PodSpec{
|
||||||
@ -1851,13 +1894,41 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Status: v1.PodStatus{
|
Status: v1.PodStatus{
|
||||||
PodIP: tc.podIPs[i],
|
PodIP: tc.podIPs[i],
|
||||||
Phase: tc.phases[i],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = kubernetes.CoreV1().Pods(tc.svcNamespace).Create(pod)
|
_, err = kubernetes.CoreV1().Pods(tc.svcNamespace).Create(pod)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
address := v1.EndpointAddress{
|
||||||
|
IP: tc.podIPs[i],
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
APIVersion: "",
|
||||||
|
Kind: "Pod",
|
||||||
|
Name: podname,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if tc.podsReady[i] {
|
||||||
|
addresses = append(addresses, address)
|
||||||
|
} else {
|
||||||
|
notReadyAddresses = append(notReadyAddresses, address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
endpointsObject := &v1.Endpoints{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: tc.svcNamespace,
|
||||||
|
Name: tc.svcName,
|
||||||
|
Labels: tc.labels,
|
||||||
|
},
|
||||||
|
Subsets: []v1.EndpointSubset{
|
||||||
|
{
|
||||||
|
Addresses: addresses,
|
||||||
|
NotReadyAddresses: notReadyAddresses,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = kubernetes.CoreV1().Endpoints(tc.svcNamespace).Create(endpointsObject)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create our object under test and get the endpoints.
|
// Create our object under test and get the endpoints.
|
||||||
client, _ := NewServiceSource(
|
client, _ := NewServiceSource(
|
||||||
@ -1869,6 +1940,7 @@ func TestHeadlessServices(t *testing.T) {
|
|||||||
tc.compatibility,
|
tc.compatibility,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
[]string{},
|
[]string{},
|
||||||
tc.ignoreHostnameAnnotation,
|
tc.ignoreHostnameAnnotation,
|
||||||
)
|
)
|
||||||
@ -1906,7 +1978,8 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
lbs []string
|
lbs []string
|
||||||
podnames []string
|
podnames []string
|
||||||
hostnames []string
|
hostnames []string
|
||||||
phases []v1.PodPhase
|
podsReady []bool
|
||||||
|
publishNotReadyAddresses bool
|
||||||
expected []*endpoint.Endpoint
|
expected []*endpoint.Endpoint
|
||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
@ -1931,7 +2004,8 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}},
|
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}},
|
||||||
@ -1960,7 +2034,8 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{},
|
[]*endpoint.Endpoint{},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
@ -1986,7 +2061,8 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)},
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}, RecordTTL: endpoint.TTL(1)},
|
||||||
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)},
|
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}, RecordTTL: endpoint.TTL(1)},
|
||||||
@ -2015,13 +2091,44 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodFailed},
|
[]bool{true, false},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"annotated Headless services return endpoints for all Pod if publishNotReadyAddresses is set",
|
||||||
|
"",
|
||||||
|
"testing",
|
||||||
|
"foo",
|
||||||
|
v1.ServiceTypeClusterIP,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
map[string]string{"component": "foo"},
|
||||||
|
map[string]string{
|
||||||
|
hostnameAnnotationKey: "service.example.org",
|
||||||
|
},
|
||||||
|
v1.ClusterIPNone,
|
||||||
|
[]string{"1.1.1.1", "1.1.1.2"},
|
||||||
|
map[string]string{
|
||||||
|
"component": "foo",
|
||||||
|
},
|
||||||
|
[]string{},
|
||||||
|
[]string{"foo-0", "foo-1"},
|
||||||
|
[]string{"foo-0", "foo-1"},
|
||||||
|
[]bool{true, false},
|
||||||
|
true,
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||||
|
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.2"}},
|
||||||
|
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"annotated Headless services return endpoints for pods missing hostname",
|
"annotated Headless services return endpoints for pods missing hostname",
|
||||||
"",
|
"",
|
||||||
@ -2043,7 +2150,8 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
[]string{},
|
[]string{},
|
||||||
[]string{"foo-0", "foo-1"},
|
[]string{"foo-0", "foo-1"},
|
||||||
[]string{"", ""},
|
[]string{"", ""},
|
||||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
[]bool{true, true},
|
||||||
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}},
|
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1", "1.1.1.2"}},
|
||||||
},
|
},
|
||||||
@ -2056,9 +2164,10 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
|
|
||||||
service := &v1.Service{
|
service := &v1.Service{
|
||||||
Spec: v1.ServiceSpec{
|
Spec: v1.ServiceSpec{
|
||||||
Type: tc.svcType,
|
Type: tc.svcType,
|
||||||
ClusterIP: tc.clusterIP,
|
ClusterIP: tc.clusterIP,
|
||||||
Selector: tc.selector,
|
Selector: tc.selector,
|
||||||
|
PublishNotReadyAddresses: tc.publishNotReadyAddresses,
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: tc.svcNamespace,
|
Namespace: tc.svcNamespace,
|
||||||
@ -2071,6 +2180,8 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
_, err := kubernetes.CoreV1().Services(service.Namespace).Create(service)
|
_, err := kubernetes.CoreV1().Services(service.Namespace).Create(service)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var addresses []v1.EndpointAddress
|
||||||
|
var notReadyAddresses []v1.EndpointAddress
|
||||||
for i, podname := range tc.podnames {
|
for i, podname := range tc.podnames {
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
Spec: v1.PodSpec{
|
Spec: v1.PodSpec{
|
||||||
@ -2085,13 +2196,41 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Status: v1.PodStatus{
|
Status: v1.PodStatus{
|
||||||
HostIP: tc.hostIPs[i],
|
HostIP: tc.hostIPs[i],
|
||||||
Phase: tc.phases[i],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = kubernetes.CoreV1().Pods(tc.svcNamespace).Create(pod)
|
_, err = kubernetes.CoreV1().Pods(tc.svcNamespace).Create(pod)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
address := v1.EndpointAddress{
|
||||||
|
IP: "4.3.2.1",
|
||||||
|
TargetRef: &v1.ObjectReference{
|
||||||
|
APIVersion: "",
|
||||||
|
Kind: "Pod",
|
||||||
|
Name: podname,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if tc.podsReady[i] {
|
||||||
|
addresses = append(addresses, address)
|
||||||
|
} else {
|
||||||
|
notReadyAddresses = append(notReadyAddresses, address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
endpointsObject := &v1.Endpoints{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: tc.svcNamespace,
|
||||||
|
Name: tc.svcName,
|
||||||
|
Labels: tc.labels,
|
||||||
|
},
|
||||||
|
Subsets: []v1.EndpointSubset{
|
||||||
|
{
|
||||||
|
Addresses: addresses,
|
||||||
|
NotReadyAddresses: notReadyAddresses,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = kubernetes.CoreV1().Endpoints(tc.svcNamespace).Create(endpointsObject)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Create our object under test and get the endpoints.
|
// Create our object under test and get the endpoints.
|
||||||
client, _ := NewServiceSource(
|
client, _ := NewServiceSource(
|
||||||
@ -2103,6 +2242,7 @@ func TestHeadlessServicesHostIP(t *testing.T) {
|
|||||||
tc.compatibility,
|
tc.compatibility,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
[]string{},
|
[]string{},
|
||||||
tc.ignoreHostnameAnnotation,
|
tc.ignoreHostnameAnnotation,
|
||||||
)
|
)
|
||||||
@ -2207,6 +2347,7 @@ func TestExternalServices(t *testing.T) {
|
|||||||
tc.compatibility,
|
tc.compatibility,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
[]string{},
|
[]string{},
|
||||||
tc.ignoreHostnameAnnotation,
|
tc.ignoreHostnameAnnotation,
|
||||||
)
|
)
|
||||||
@ -2249,7 +2390,7 @@ func BenchmarkServiceEndpoints(b *testing.B) {
|
|||||||
_, err := kubernetes.CoreV1().Services(service.Namespace).Create(service)
|
_, err := kubernetes.CoreV1().Services(service.Namespace).Create(service)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
client, err := NewServiceSource(kubernetes, v1.NamespaceAll, "", "", false, "", false, false, []string{}, false)
|
client, err := NewServiceSource(kubernetes, v1.NamespaceAll, "", "", false, "", false, false, false, []string{}, false)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
@ -40,25 +40,26 @@ var ErrSourceNotFound = errors.New("source not found")
|
|||||||
|
|
||||||
// Config holds shared configuration options for all Sources.
|
// Config holds shared configuration options for all Sources.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Namespace string
|
Namespace string
|
||||||
AnnotationFilter string
|
AnnotationFilter string
|
||||||
FQDNTemplate string
|
FQDNTemplate string
|
||||||
CombineFQDNAndAnnotation bool
|
CombineFQDNAndAnnotation bool
|
||||||
IgnoreHostnameAnnotation bool
|
IgnoreHostnameAnnotation bool
|
||||||
Compatibility string
|
Compatibility string
|
||||||
PublishInternal bool
|
PublishInternal bool
|
||||||
PublishHostIP bool
|
PublishHostIP bool
|
||||||
ConnectorServer string
|
AlwaysPublishNotReadyAddresses bool
|
||||||
CRDSourceAPIVersion string
|
ConnectorServer string
|
||||||
CRDSourceKind string
|
CRDSourceAPIVersion string
|
||||||
KubeConfig string
|
CRDSourceKind string
|
||||||
KubeMaster string
|
KubeConfig string
|
||||||
ServiceTypeFilter []string
|
KubeMaster string
|
||||||
IstioIngressGatewayServices []string
|
ServiceTypeFilter []string
|
||||||
CFAPIEndpoint string
|
IstioIngressGatewayServices []string
|
||||||
CFUsername string
|
CFAPIEndpoint string
|
||||||
CFPassword string
|
CFUsername string
|
||||||
ContourLoadBalancerService string
|
CFPassword string
|
||||||
|
ContourLoadBalancerService string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientGenerator provides clients
|
// ClientGenerator provides clients
|
||||||
@ -164,7 +165,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewServiceSource(client, cfg.Namespace, cfg.AnnotationFilter, cfg.FQDNTemplate, cfg.CombineFQDNAndAnnotation, cfg.Compatibility, cfg.PublishInternal, cfg.PublishHostIP, cfg.ServiceTypeFilter, cfg.IgnoreHostnameAnnotation)
|
return NewServiceSource(client, cfg.Namespace, cfg.AnnotationFilter, cfg.FQDNTemplate, cfg.CombineFQDNAndAnnotation, cfg.Compatibility, cfg.PublishInternal, cfg.PublishHostIP, cfg.AlwaysPublishNotReadyAddresses, cfg.ServiceTypeFilter, cfg.IgnoreHostnameAnnotation)
|
||||||
case "ingress":
|
case "ingress":
|
||||||
client, err := p.KubeClient()
|
client, err := p.KubeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user