source: dedupe template execution

This commit is contained in:
Andy Bursavich 2021-07-28 11:32:26 -07:00
parent 638194fccd
commit b032f2864f
9 changed files with 50 additions and 92 deletions

View File

@ -17,11 +17,9 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
"strings"
"text/template"
"time"
@ -189,22 +187,17 @@ func (sc *httpProxySource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint,
}
func (sc *httpProxySource) endpointsFromTemplate(httpProxy *projectcontour.HTTPProxy) ([]*endpoint.Endpoint, error) {
// Process the whole template string
var buf bytes.Buffer
err := sc.fqdnTemplate.Execute(&buf, httpProxy)
hostnames, err := execTemplate(sc.fqdnTemplate, httpProxy)
if err != nil {
return nil, errors.Wrapf(err, "failed to apply template on HTTPProxy %s/%s", httpProxy.Namespace, httpProxy.Name)
return nil, err
}
hostnames := buf.String()
ttl, err := getTTLFromAnnotations(httpProxy.Annotations)
if err != nil {
log.Warn(err)
}
targets := getTargetsFromTargetAnnotation(httpProxy.Annotations)
if len(targets) == 0 {
for _, lb := range httpProxy.Status.LoadBalancer.Ingress {
if lb.IP != "" {
@ -219,10 +212,7 @@ func (sc *httpProxySource) endpointsFromTemplate(httpProxy *projectcontour.HTTPP
providerSpecific, setIdentifier := getProviderSpecificAnnotations(httpProxy.Annotations)
var endpoints []*endpoint.Endpoint
// splits the FQDN template and removes the trailing periods
hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",")
for _, hostname := range hostnameList {
hostname = strings.TrimSuffix(hostname, ".")
for _, hostname := range hostnames {
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
}
return endpoints, nil

View File

@ -17,7 +17,6 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
@ -200,22 +199,17 @@ func (sc *ingressRouteSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoi
}
func (sc *ingressRouteSource) endpointsFromTemplate(ctx context.Context, ingressRoute *contour.IngressRoute) ([]*endpoint.Endpoint, error) {
// Process the whole template string
var buf bytes.Buffer
err := sc.fqdnTemplate.Execute(&buf, ingressRoute)
hostnames, err := execTemplate(sc.fqdnTemplate, ingressRoute)
if err != nil {
return nil, fmt.Errorf("failed to apply template on ingressroute %s/%s: %v", ingressRoute.Namespace, ingressRoute.Name, err)
return nil, err
}
hostnames := buf.String()
ttl, err := getTTLFromAnnotations(ingressRoute.Annotations)
if err != nil {
log.Warn(err)
}
targets := getTargetsFromTargetAnnotation(ingressRoute.Annotations)
if len(targets) == 0 {
targets, err = sc.targetsFromContourLoadBalancer(ctx)
if err != nil {
@ -226,10 +220,7 @@ func (sc *ingressRouteSource) endpointsFromTemplate(ctx context.Context, ingress
providerSpecific, setIdentifier := getProviderSpecificAnnotations(ingressRoute.Annotations)
var endpoints []*endpoint.Endpoint
// splits the FQDN template and removes the trailing periods
hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",")
for _, hostname := range hostnameList {
hostname = strings.TrimSuffix(hostname, ".")
for _, hostname := range hostnames {
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
}
return endpoints, nil

View File

@ -17,7 +17,6 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
@ -167,22 +166,17 @@ func (sc *ingressSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, e
}
func (sc *ingressSource) endpointsFromTemplate(ing *v1beta1.Ingress) ([]*endpoint.Endpoint, error) {
// Process the whole template string
var buf bytes.Buffer
err := sc.fqdnTemplate.Execute(&buf, ing)
hostnames, err := execTemplate(sc.fqdnTemplate, ing)
if err != nil {
return nil, fmt.Errorf("failed to apply template on ingress %s: %v", ing.String(), err)
return nil, err
}
hostnames := buf.String()
ttl, err := getTTLFromAnnotations(ing.Annotations)
if err != nil {
log.Warn(err)
}
targets := getTargetsFromTargetAnnotation(ing.Annotations)
if len(targets) == 0 {
targets = targetsFromIngressStatus(ing.Status)
}
@ -190,10 +184,7 @@ func (sc *ingressSource) endpointsFromTemplate(ing *v1beta1.Ingress) ([]*endpoin
providerSpecific, setIdentifier := getProviderSpecificAnnotations(ing.Annotations)
var endpoints []*endpoint.Endpoint
// splits the FQDN template and removes the trailing periods
hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",")
for _, hostname := range hostnameList {
hostname = strings.TrimSuffix(hostname, ".")
for _, hostname := range hostnames {
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
}
return endpoints, nil

View File

@ -17,7 +17,6 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
@ -160,7 +159,7 @@ func (sc *gatewaySource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, e
// apply template if host is missing on gateway
if (sc.combineFQDNAnnotation || len(gwHostnames) == 0) && sc.fqdnTemplate != nil {
iHostnames, err := sc.hostNamesFromTemplate(gateway)
iHostnames, err := execTemplate(sc.fqdnTemplate, &gateway)
if err != nil {
return nil, err
}
@ -336,18 +335,6 @@ func (sc *gatewaySource) hostNamesFromGateway(gateway networkingv1alpha3.Gateway
return hostnames, nil
}
func (sc *gatewaySource) hostNamesFromTemplate(gateway networkingv1alpha3.Gateway) ([]string, error) {
// Process the whole template string
var buf bytes.Buffer
err := sc.fqdnTemplate.Execute(&buf, gateway)
if err != nil {
return nil, fmt.Errorf("failed to apply template on istio gateway %v: %v", gateway, err)
}
hostnames := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",")
return hostnames, nil
}
func gatewaySelectorMatchesServiceSelector(gwSelector, svcSelector map[string]string) bool {
for k, v := range gwSelector {
if lbl, ok := svcSelector[k]; !ok || lbl != v {

View File

@ -17,7 +17,6 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
@ -240,28 +239,20 @@ func (sc *virtualServiceSource) getGateway(ctx context.Context, gatewayStr strin
}
func (sc *virtualServiceSource) endpointsFromTemplate(ctx context.Context, virtualService networkingv1alpha3.VirtualService) ([]*endpoint.Endpoint, error) {
// Process the whole template string
var buf bytes.Buffer
err := sc.fqdnTemplate.Execute(&buf, virtualService)
hostnames, err := execTemplate(sc.fqdnTemplate, &virtualService)
if err != nil {
return nil, fmt.Errorf("failed to apply template on istio config %v: %v", virtualService, err)
return nil, err
}
hostnamesTemplate := buf.String()
ttl, err := getTTLFromAnnotations(virtualService.Annotations)
if err != nil {
log.Warn(err)
}
var endpoints []*endpoint.Endpoint
providerSpecific, setIdentifier := getProviderSpecificAnnotations(virtualService.Annotations)
// splits the FQDN template and removes the trailing periods
hostnames := strings.Split(strings.Replace(hostnamesTemplate, " ", "", -1), ",")
var endpoints []*endpoint.Endpoint
for _, hostname := range hostnames {
hostname = strings.TrimSuffix(hostname, ".")
targets, err := sc.targetsFromVirtualService(ctx, virtualService, hostname)
if err != nil {
return endpoints, err

View File

@ -17,7 +17,6 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"text/template"
@ -121,14 +120,15 @@ func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, erro
}
if ns.fqdnTemplate != nil {
// Process the whole template string
var buf bytes.Buffer
err := ns.fqdnTemplate.Execute(&buf, node)
hostnames, err := execTemplate(ns.fqdnTemplate, node)
if err != nil {
return nil, fmt.Errorf("failed to apply template on node %s: %v", node.Name, err)
return nil, err
}
ep.DNSName = buf.String()
hostname := ""
if len(hostnames) > 0 {
hostname = hostnames[0]
}
ep.DNSName = hostname
log.Debugf("applied template for %s, converting to %s", node.Name, ep.DNSName)
} else {
ep.DNSName = node.Name

View File

@ -17,11 +17,9 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
"strings"
"text/template"
"time"
@ -165,22 +163,17 @@ func (ors *ocpRouteSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint,
}
func (ors *ocpRouteSource) endpointsFromTemplate(ocpRoute *routev1.Route) ([]*endpoint.Endpoint, error) {
// Process the whole template string
var buf bytes.Buffer
err := ors.fqdnTemplate.Execute(&buf, ocpRoute)
hostnames, err := execTemplate(ors.fqdnTemplate, ocpRoute)
if err != nil {
return nil, fmt.Errorf("failed to apply template on OpenShift Route %s: %s", ocpRoute.Name, err)
return nil, err
}
hostnames := buf.String()
ttl, err := getTTLFromAnnotations(ocpRoute.Annotations)
if err != nil {
log.Warn(err)
}
targets := getTargetsFromTargetAnnotation(ocpRoute.Annotations)
if len(targets) == 0 {
targets = targetsFromOcpRouteStatus(ocpRoute.Status)
}
@ -188,10 +181,7 @@ func (ors *ocpRouteSource) endpointsFromTemplate(ocpRoute *routev1.Route) ([]*en
providerSpecific, setIdentifier := getProviderSpecificAnnotations(ocpRoute.Annotations)
var endpoints []*endpoint.Endpoint
// splits the FQDN template and removes the trailing periods
hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",")
for _, hostname := range hostnameList {
hostname = strings.TrimSuffix(hostname, ".")
for _, hostname := range hostnames {
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier)...)
}
return endpoints, nil

View File

@ -17,7 +17,6 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"sort"
@ -345,18 +344,15 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri
}
func (sc *serviceSource) endpointsFromTemplate(svc *v1.Service) ([]*endpoint.Endpoint, error) {
var endpoints []*endpoint.Endpoint
// Process the whole template string
var buf bytes.Buffer
err := sc.fqdnTemplate.Execute(&buf, svc)
hostnames, err := execTemplate(sc.fqdnTemplate, svc)
if err != nil {
return nil, fmt.Errorf("failed to apply template on service %s: %v", svc.String(), err)
return nil, err
}
providerSpecific, setIdentifier := getProviderSpecificAnnotations(svc.Annotations)
hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",")
for _, hostname := range hostnameList {
var endpoints []*endpoint.Endpoint
for _, hostname := range hostnames {
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname, providerSpecific, setIdentifier, false)...)
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package source
import (
"bytes"
"context"
"fmt"
"math"
@ -25,9 +26,11 @@ import (
"strings"
"text/template"
"time"
"unicode"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/external-dns/endpoint"
@ -107,6 +110,25 @@ func parseTTL(s string) (ttlSeconds int64, err error) {
return int64(ttlDuration.Seconds()), nil
}
type kubeObject interface {
runtime.Object
metav1.Object
}
func execTemplate(tmpl *template.Template, obj kubeObject) (hostnames []string, err error) {
var buf bytes.Buffer
if err := tmpl.Execute(&buf, obj); err != nil {
kind := obj.GetObjectKind().GroupVersionKind().Kind
return nil, fmt.Errorf("failed to apply template on %s %s/%s: %w", kind, obj.GetNamespace(), obj.GetName(), err)
}
for _, name := range strings.Split(buf.String(), ",") {
name = strings.TrimFunc(name, unicode.IsSpace)
name = strings.TrimSuffix(name, ".")
hostnames = append(hostnames, name)
}
return hostnames, nil
}
func parseTemplate(fqdnTemplate string) (tmpl *template.Template, err error) {
if fqdnTemplate == "" {
return nil, nil