Fixes and cleanup

This commit is contained in:
Alfred Krohmer 2019-06-08 21:53:13 +02:00
parent 6681a3a358
commit b2a3e88303
8 changed files with 79 additions and 36 deletions

View File

@ -187,11 +187,34 @@ func shouldUpdateProviderSpecific(desired, current *endpoint.Endpoint) bool {
continue continue
} }
found := false
for _, d := range desired.ProviderSpecific { for _, d := range desired.ProviderSpecific {
if d.Name == c.Name && d.Value != c.Value { if d.Name == c.Name {
return true if d.Value != c.Value {
// provider-specific attribute updated
return true
}
found = true
break
} }
} }
if !found {
// provider-specific attribute deleted
return true
}
}
for _, d := range desired.ProviderSpecific {
found := false
for _, c := range current.ProviderSpecific {
if d.Name == c.Name {
found = true
break
}
}
if !found {
// provider-specific attribute added
return true
}
} }
return false return false

View File

@ -39,11 +39,9 @@ const (
// provider specific key that designates whether an AWS ALIAS record has the EvaluateTargetHealth // provider specific key that designates whether an AWS ALIAS record has the EvaluateTargetHealth
// field set to true. // field set to true.
providerSpecificEvaluateTargetHealth = "aws/evaluate-target-health" providerSpecificEvaluateTargetHealth = "aws/evaluate-target-health"
providerSpecificSetIdentifier = "aws/set-identifier"
providerSpecificWeight = "aws/weight" providerSpecificWeight = "aws/weight"
providerSpecificRegion = "aws/region" providerSpecificRegion = "aws/region"
providerSpecificFailover = "aws/failover" providerSpecificFailover = "aws/failover"
providerSpecificGeolocation = "aws/geolocation"
providerSpecificGeolocationContinentCode = "aws/geolocation-continent-code" providerSpecificGeolocationContinentCode = "aws/geolocation-continent-code"
providerSpecificGeolocationCountryCode = "aws/geolocation-country-code" providerSpecificGeolocationCountryCode = "aws/geolocation-country-code"
providerSpecificGeolocationSubdivisionCode = "aws/geolocation-subdivision-code" providerSpecificGeolocationSubdivisionCode = "aws/geolocation-subdivision-code"

View File

@ -135,6 +135,7 @@ func (im *TXTRegistry) ApplyChanges(ctx context.Context, changes *plan.Changes)
} }
r.Labels[endpoint.OwnerLabelKey] = im.ownerID r.Labels[endpoint.OwnerLabelKey] = im.ownerID
txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier) txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier)
txt.ProviderSpecific = r.ProviderSpecific
filteredChanges.Create = append(filteredChanges.Create, txt) filteredChanges.Create = append(filteredChanges.Create, txt)
if im.cacheInterval > 0 { if im.cacheInterval > 0 {
@ -144,6 +145,7 @@ func (im *TXTRegistry) ApplyChanges(ctx context.Context, changes *plan.Changes)
for _, r := range filteredChanges.Delete { for _, r := range filteredChanges.Delete {
txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier) txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier)
txt.ProviderSpecific = r.ProviderSpecific
// when we delete TXT records for which value has changed (due to new label) this would still work because // when we delete TXT records for which value has changed (due to new label) this would still work because
// !!! TXT record value is uniquely generated from the Labels of the endpoint. Hence old TXT record can be uniquely reconstructed // !!! TXT record value is uniquely generated from the Labels of the endpoint. Hence old TXT record can be uniquely reconstructed
@ -157,6 +159,7 @@ func (im *TXTRegistry) ApplyChanges(ctx context.Context, changes *plan.Changes)
// make sure TXT records are consistently updated as well // make sure TXT records are consistently updated as well
for _, r := range filteredChanges.UpdateOld { for _, r := range filteredChanges.UpdateOld {
txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier) txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier)
txt.ProviderSpecific = r.ProviderSpecific
// when we updateOld TXT records for which value has changed (due to new label) this would still work because // when we updateOld TXT records for which value has changed (due to new label) this would still work because
// !!! TXT record value is uniquely generated from the Labels of the endpoint. Hence old TXT record can be uniquely reconstructed // !!! TXT record value is uniquely generated from the Labels of the endpoint. Hence old TXT record can be uniquely reconstructed
filteredChanges.UpdateOld = append(filteredChanges.UpdateOld, txt) filteredChanges.UpdateOld = append(filteredChanges.UpdateOld, txt)
@ -169,6 +172,7 @@ func (im *TXTRegistry) ApplyChanges(ctx context.Context, changes *plan.Changes)
// make sure TXT records are consistently updated as well // make sure TXT records are consistently updated as well
for _, r := range filteredChanges.UpdateNew { for _, r := range filteredChanges.UpdateNew {
txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier) txt := endpoint.NewEndpoint(im.mapper.toTXTName(r.DNSName), endpoint.RecordTypeTXT, r.Labels.Serialize(true)).WithSetIdentifier(r.SetIdentifier)
txt.ProviderSpecific = r.ProviderSpecific
filteredChanges.UpdateNew = append(filteredChanges.UpdateNew, txt) filteredChanges.UpdateNew = append(filteredChanges.UpdateNew, txt)
// add new version of record to cache // add new version of record to cache
if im.cacheInterval > 0 { if im.cacheInterval > 0 {

View File

@ -43,7 +43,7 @@ func (ms *dedupSource) Endpoints() ([]*endpoint.Endpoint, error) {
} }
for _, ep := range endpoints { for _, ep := range endpoints {
identifier := ep.DNSName + " / " + ep.Targets.String() identifier := ep.DNSName + " / " + ep.SetIdentifier + " / " + ep.Targets.String()
if _, ok := collected[identifier]; ok { if _, ok := collected[identifier]; ok {
log.Debugf("Removing duplicate endpoint %s", ep) log.Debugf("Removing duplicate endpoint %s", ep)

View File

@ -174,14 +174,14 @@ func (sc *gatewaySource) endpointsFromTemplate(config *istiomodel.Config) ([]*en
} }
} }
providerSpecific := getProviderSpecificAnnotations(config.Annotations) providerSpecific, setIdentifier := getProviderSpecificAnnotations(config.Annotations)
var endpoints []*endpoint.Endpoint var endpoints []*endpoint.Endpoint
// splits the FQDN template and removes the trailing periods // splits the FQDN template and removes the trailing periods
hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",") hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",")
for _, hostname := range hostnameList { for _, hostname := range hostnameList {
hostname = strings.TrimSuffix(hostname, ".") hostname = strings.TrimSuffix(hostname, ".")
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
} }
return endpoints, nil return endpoints, nil
} }
@ -266,7 +266,7 @@ func (sc *gatewaySource) endpointsFromGatewayConfig(config istiomodel.Config) ([
gateway := config.Spec.(*istionetworking.Gateway) gateway := config.Spec.(*istionetworking.Gateway)
providerSpecific := getProviderSpecificAnnotations(config.Annotations) providerSpecific, setIdentifier := getProviderSpecificAnnotations(config.Annotations)
for _, server := range gateway.Servers { for _, server := range gateway.Servers {
for _, host := range server.Hosts { for _, host := range server.Hosts {
@ -282,7 +282,7 @@ func (sc *gatewaySource) endpointsFromGatewayConfig(config istiomodel.Config) ([
host = parts[1] host = parts[1]
} }
endpoints = append(endpoints, endpointsForHostname(host, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(host, targets, ttl, providerSpecific, setIdentifier)...)
} }
} }
@ -290,7 +290,7 @@ func (sc *gatewaySource) endpointsFromGatewayConfig(config istiomodel.Config) ([
if !sc.ignoreHostnameAnnotation { if !sc.ignoreHostnameAnnotation {
hostnameList := getHostnamesFromAnnotations(config.Annotations) hostnameList := getHostnamesFromAnnotations(config.Annotations)
for _, hostname := range hostnameList { for _, hostname := range hostnameList {
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
} }
} }

View File

@ -187,14 +187,14 @@ func (sc *ingressSource) endpointsFromTemplate(ing *v1beta1.Ingress) ([]*endpoin
targets = targetsFromIngressStatus(ing.Status) targets = targetsFromIngressStatus(ing.Status)
} }
providerSpecific := getProviderSpecificAnnotations(ing.Annotations) providerSpecific, setIdentifier := getProviderSpecificAnnotations(ing.Annotations)
var endpoints []*endpoint.Endpoint var endpoints []*endpoint.Endpoint
// splits the FQDN template and removes the trailing periods // splits the FQDN template and removes the trailing periods
hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",") hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",")
for _, hostname := range hostnameList { for _, hostname := range hostnameList {
hostname = strings.TrimSuffix(hostname, ".") hostname = strings.TrimSuffix(hostname, ".")
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
} }
return endpoints, nil return endpoints, nil
} }
@ -261,13 +261,13 @@ func endpointsFromIngress(ing *v1beta1.Ingress, ignoreHostnameAnnotation bool) [
targets = targetsFromIngressStatus(ing.Status) targets = targetsFromIngressStatus(ing.Status)
} }
providerSpecific := getProviderSpecificAnnotations(ing.Annotations) providerSpecific, setIdentifier := getProviderSpecificAnnotations(ing.Annotations)
for _, rule := range ing.Spec.Rules { for _, rule := range ing.Spec.Rules {
if rule.Host == "" { if rule.Host == "" {
continue continue
} }
endpoints = append(endpoints, endpointsForHostname(rule.Host, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(rule.Host, targets, ttl, providerSpecific, setIdentifier)...)
} }
for _, tls := range ing.Spec.TLS { for _, tls := range ing.Spec.TLS {
@ -275,7 +275,7 @@ func endpointsFromIngress(ing *v1beta1.Ingress, ignoreHostnameAnnotation bool) [
if host == "" { if host == "" {
continue continue
} }
endpoints = append(endpoints, endpointsForHostname(host, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(host, targets, ttl, providerSpecific, setIdentifier)...)
} }
} }
@ -283,7 +283,7 @@ func endpointsFromIngress(ing *v1beta1.Ingress, ignoreHostnameAnnotation bool) [
if !ignoreHostnameAnnotation { if !ignoreHostnameAnnotation {
hostnameList := getHostnamesFromAnnotations(ing.Annotations) hostnameList := getHostnamesFromAnnotations(ing.Annotations)
for _, hostname := range hostnameList { for _, hostname := range hostnameList {
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific)...) endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
} }
} }
return endpoints return endpoints

View File

@ -285,10 +285,10 @@ func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service) ([]*endpoint.End
return nil, fmt.Errorf("failed to apply template on service %s: %v", svc.String(), err) return nil, fmt.Errorf("failed to apply template on service %s: %v", svc.String(), err)
} }
providerSpecific := getProviderSpecificAnnotations(svc.Annotations) providerSpecific, setIdentifier := getProviderSpecificAnnotations(svc.Annotations)
hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",") hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",")
for _, hostname := range hostnameList { for _, hostname := range hostnameList {
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific)...) endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier)...)
} }
return endpoints, nil return endpoints, nil
@ -299,10 +299,10 @@ func (sc *serviceSource) endpoints(svc *v1.Service) []*endpoint.Endpoint {
var endpoints []*endpoint.Endpoint var endpoints []*endpoint.Endpoint
// Skip endpoints if we do not want entries from annotations // Skip endpoints if we do not want entries from annotations
if !sc.ignoreHostnameAnnotation { if !sc.ignoreHostnameAnnotation {
providerSpecific := getProviderSpecificAnnotations(svc.Annotations) providerSpecific, setIdentifier := getProviderSpecificAnnotations(svc.Annotations)
hostnameList := getHostnamesFromAnnotations(svc.Annotations) hostnameList := getHostnamesFromAnnotations(svc.Annotations)
for _, hostname := range hostnameList { for _, hostname := range hostnameList {
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific)...) endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier)...)
} }
} }
return endpoints return endpoints
@ -358,7 +358,7 @@ func (sc *serviceSource) setResourceLabel(service *v1.Service, endpoints []*endp
} }
} }
func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, providerSpecific endpoint.ProviderSpecific) []*endpoint.Endpoint { func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, providerSpecific endpoint.ProviderSpecific, setIdentifier string) []*endpoint.Endpoint {
hostname = strings.TrimSuffix(hostname, ".") hostname = strings.TrimSuffix(hostname, ".")
ttl, err := getTTLFromAnnotations(svc.Annotations) ttl, err := getTTLFromAnnotations(svc.Annotations)
if err != nil { if err != nil {
@ -366,21 +366,19 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro
} }
epA := &endpoint.Endpoint{ epA := &endpoint.Endpoint{
RecordTTL: ttl, RecordTTL: ttl,
RecordType: endpoint.RecordTypeA, RecordType: endpoint.RecordTypeA,
Labels: endpoint.NewLabels(), Labels: endpoint.NewLabels(),
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity), Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
DNSName: hostname, DNSName: hostname,
ProviderSpecific: providerSpecific,
} }
epCNAME := &endpoint.Endpoint{ epCNAME := &endpoint.Endpoint{
RecordTTL: ttl, RecordTTL: ttl,
RecordType: endpoint.RecordTypeCNAME, RecordType: endpoint.RecordTypeCNAME,
Labels: endpoint.NewLabels(), Labels: endpoint.NewLabels(),
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity), Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
DNSName: hostname, DNSName: hostname,
ProviderSpecific: providerSpecific,
} }
var endpoints []*endpoint.Endpoint var endpoints []*endpoint.Endpoint
@ -423,6 +421,10 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro
if len(epCNAME.Targets) > 0 { if len(epCNAME.Targets) > 0 {
endpoints = append(endpoints, epCNAME) endpoints = append(endpoints, epCNAME)
} }
for _, endpoint := range endpoints {
endpoint.ProviderSpecific = providerSpecific
endpoint.SetIdentifier = setIdentifier
}
return endpoints return endpoints
} }

View File

@ -45,6 +45,8 @@ const (
const ( const (
// The annotation used for determining if traffic will go through Cloudflare // The annotation used for determining if traffic will go through Cloudflare
CloudflareProxiedKey = "external-dns.alpha.kubernetes.io/cloudflare-proxied" CloudflareProxiedKey = "external-dns.alpha.kubernetes.io/cloudflare-proxied"
SetIdentifierKey = "external-dns.alpha.kubernetes.io/set-identifier"
) )
const ( const (
@ -86,7 +88,7 @@ func getAliasFromAnnotations(annotations map[string]string) bool {
return exists && aliasAnnotation == "true" return exists && aliasAnnotation == "true"
} }
func getProviderSpecificAnnotations(annotations map[string]string) endpoint.ProviderSpecific { func getProviderSpecificAnnotations(annotations map[string]string) (endpoint.ProviderSpecific, string) {
providerSpecificAnnotations := endpoint.ProviderSpecific{} providerSpecificAnnotations := endpoint.ProviderSpecific{}
v, exists := annotations[CloudflareProxiedKey] v, exists := annotations[CloudflareProxiedKey]
@ -102,7 +104,19 @@ func getProviderSpecificAnnotations(annotations map[string]string) endpoint.Prov
Value: "true", Value: "true",
}) })
} }
return providerSpecificAnnotations setIdentifier := ""
for k, v := range annotations {
if k == SetIdentifierKey {
setIdentifier = v
} else if strings.HasPrefix(k, "external-dns.alpha.kubernetes.io/aws-") {
attr := strings.TrimPrefix(k, "external-dns.alpha.kubernetes.io/aws-")
providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{
Name: fmt.Sprintf("aws/%s", attr),
Value: v,
})
}
}
return providerSpecificAnnotations, setIdentifier
} }
// getTargetsFromTargetAnnotation gets endpoints from optional "target" annotation. // getTargetsFromTargetAnnotation gets endpoints from optional "target" annotation.
@ -133,7 +147,7 @@ func suitableType(target string) string {
} }
// endpointsForHostname returns the endpoint objects for each host-target combination. // endpointsForHostname returns the endpoint objects for each host-target combination.
func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoint.TTL, providerSpecific endpoint.ProviderSpecific) []*endpoint.Endpoint { func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoint.TTL, providerSpecific endpoint.ProviderSpecific, setIdentifier string) []*endpoint.Endpoint {
var endpoints []*endpoint.Endpoint var endpoints []*endpoint.Endpoint
var aTargets endpoint.Targets var aTargets endpoint.Targets
@ -156,6 +170,7 @@ func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoin
RecordType: endpoint.RecordTypeA, RecordType: endpoint.RecordTypeA,
Labels: endpoint.NewLabels(), Labels: endpoint.NewLabels(),
ProviderSpecific: providerSpecific, ProviderSpecific: providerSpecific,
SetIdentifier: setIdentifier,
} }
endpoints = append(endpoints, epA) endpoints = append(endpoints, epA)
} }
@ -168,6 +183,7 @@ func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoin
RecordType: endpoint.RecordTypeCNAME, RecordType: endpoint.RecordTypeCNAME,
Labels: endpoint.NewLabels(), Labels: endpoint.NewLabels(),
ProviderSpecific: providerSpecific, ProviderSpecific: providerSpecific,
SetIdentifier: setIdentifier,
} }
endpoints = append(endpoints, epCNAME) endpoints = append(endpoints, epCNAME)
} }