Support a comma separated list for the FQDN template (#512)

* Support a comma separated list for the FQDN template

* Add documentation for comma separated FQDN templates

* chore: add multiple fqdn templates to changelog
This commit is contained in:
Helgi Þormar Þorbjörnsson 2018-04-04 02:39:39 -07:00 committed by Martin Linkhorst
parent 3fa55ab682
commit 321d4d463b
7 changed files with 71 additions and 12 deletions

View File

@ -1,3 +1,4 @@
- Support a comma separated list for the FQDN template (#512) @helgi
- Google Provider: Add auto-detection of Google Project when running on GCP (#492) @drzero42
- Add custom TTL support for DNSimple (#477) @jbowes
- Fix docker build and delete vendor files which were not deleted (#473) @njuettner

View File

@ -48,6 +48,10 @@ There are three sources of information for ExternalDNS to decide on DNS name. Ex
3. If `--fqdn-template` flag is specified, e.g. `--fqdn-template={{.Name}}.my-org.com`, ExternalDNS will use service/ingress specifications for the provided template to generate DNS name.
### Can I specify multiple global FQDN templates?
Yes, yes you can. Pass in a comma separated list to `--fqdn-template`. Beaware this will double (triple, etc) the amount of DNS entries based on how many services, ingresses and so on you have and will get you faster towards the API request limit of your DNS provider.
### Which Service and Ingress controllers are supported?
Regarding Services, we'll support the OSI Layer 4 load balancers that Kubernetes creates on AWS and Google Container Engine, and possibly other clusters running on Google Compute Engine.

View File

@ -151,7 +151,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("source", "The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, fake)").Required().PlaceHolder("source").EnumsVar(&cfg.Sources, "service", "ingress", "fake")
app.Flag("namespace", "Limit sources of endpoints to a specific namespace (default: all namespaces)").Default(defaultConfig.Namespace).StringVar(&cfg.Namespace)
app.Flag("annotation-filter", "Filter sources managed by external-dns via annotation using label selector semantics (default: all sources)").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter)
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional)").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN.").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
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)

View File

@ -136,14 +136,14 @@ func getTargetsFromTargetAnnotation(ing *v1beta1.Ingress) endpoint.Targets {
}
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)
if err != nil {
return nil, fmt.Errorf("failed to apply template on ingress %s: %v", ing.String(), err)
}
hostname := buf.String()
hostnames := buf.String()
ttl, err := getTTLFromAnnotations(ing.Annotations)
if err != nil {
@ -156,7 +156,14 @@ func (sc *ingressSource) endpointsFromTemplate(ing *v1beta1.Ingress) ([]*endpoin
targets = targetsFromIngressStatus(ing.Status)
}
return endpointsForHostname(hostname, targets, ttl), nil
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, ".")
endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl)...)
}
return endpoints, nil
}
// filterByAnnotations filters a list of ingresses by a given annotation selector.

View File

@ -473,6 +473,32 @@ func testIngressEndpoints(t *testing.T) {
expected: []*endpoint.Endpoint{},
fqdnTemplate: "{{.Name}}.ext-dns.test.com",
},
{
title: "multiple FQDN template hostnames",
targetNamespace: "",
ingressItems: []fakeIngress{
{
name: "fake1",
namespace: namespace,
annotations: map[string]string{},
dnsnames: []string{},
ips: []string{"8.8.8.8"},
},
},
expected: []*endpoint.Endpoint{
{
DNSName: "fake1.ext-dns.test.com",
Targets: endpoint.Targets{"8.8.8.8"},
RecordType: endpoint.RecordTypeA,
},
{
DNSName: "fake1.ext-dna.test.com",
Targets: endpoint.Targets{"8.8.8.8"},
RecordType: endpoint.RecordTypeA,
},
},
fqdnTemplate: "{{.Name}}.ext-dns.test.com, {{.Name}}.ext-dna.test.com",
},
{
title: "ingress rules with annotation",
targetNamespace: "",

View File

@ -162,15 +162,17 @@ 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)
if err != nil {
return nil, fmt.Errorf("failed to apply template on service %s: %v", svc.String(), err)
}
hostname := buf.String()
endpoints = sc.generateEndpoints(svc, hostname)
hostnameList := strings.Split(strings.Replace(buf.String(), " ", "", -1), ",")
for _, hostname := range hostnameList {
endpoints = append(endpoints, sc.generateEndpoints(svc, hostname)...)
}
return endpoints, nil
}

View File

@ -213,6 +213,25 @@ func testServiceSourceEndpoints(t *testing.T) {
[]*endpoint.Endpoint{},
false,
},
{
"FQDN template with multiple hostnames return an endpoint with target IP",
"",
"",
"testing",
"foo",
v1.ServiceTypeLoadBalancer,
"",
"{{.Name}}.fqdn.org,{{.Name}}.fqdn.com",
map[string]string{},
map[string]string{},
"",
[]string{"1.2.3.4"},
[]*endpoint.Endpoint{
{DNSName: "foo.fqdn.org", Targets: endpoint.Targets{"1.2.3.4"}},
{DNSName: "foo.fqdn.com", Targets: endpoint.Targets{"1.2.3.4"}},
},
false,
},
{
"annotated services with multiple hostnames return an endpoint with target IP",
"",