aboutsummaryrefslogtreecommitdiff
path: root/plugin/route53/route53.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/route53/route53.go')
-rw-r--r--plugin/route53/route53.go97
1 files changed, 57 insertions, 40 deletions
diff --git a/plugin/route53/route53.go b/plugin/route53/route53.go
index 3e1a2ddea..7420e2677 100644
--- a/plugin/route53/route53.go
+++ b/plugin/route53/route53.go
@@ -30,28 +30,39 @@ type Route53 struct {
upstream *upstream.Upstream
zMu sync.RWMutex
- zones map[string]*zone
+ zones zones
}
type zone struct {
- id string
- z *file.Zone
+ id string
+ z *file.Zone
+ dns string
}
-// New returns new *Route53.
-func New(ctx context.Context, c route53iface.Route53API, keys map[string]string, up *upstream.Upstream) (*Route53, error) {
- zones := make(map[string]*zone, len(keys))
+type zones map[string][]*zone
+
+// New reads from the keys map which uses domain names as its key and hosted
+// zone id lists as its values, validates that each domain name/zone id pair does
+// exist, and returns a new *Route53. In addition to this, upstream is passed
+// for doing recursive queries against CNAMEs.
+// Returns error if it cannot verify any given domain name/zone id pair.
+func New(ctx context.Context, c route53iface.Route53API, keys map[string][]string, up *upstream.Upstream) (*Route53, error) {
+ zones := make(map[string][]*zone, len(keys))
zoneNames := make([]string, 0, len(keys))
- for dns, id := range keys {
- _, err := c.ListHostedZonesByNameWithContext(ctx, &route53.ListHostedZonesByNameInput{
- DNSName: aws.String(dns),
- HostedZoneId: aws.String(id),
- })
- if err != nil {
- return nil, err
+ for dns, hostedZoneIDs := range keys {
+ for _, hostedZoneID := range hostedZoneIDs {
+ _, err := c.ListHostedZonesByNameWithContext(ctx, &route53.ListHostedZonesByNameInput{
+ DNSName: aws.String(dns),
+ HostedZoneId: aws.String(hostedZoneID),
+ })
+ if err != nil {
+ return nil, err
+ }
+ if _, ok := zones[dns]; !ok {
+ zoneNames = append(zoneNames, dns)
+ }
+ zones[dns] = append(zones[dns], &zone{id: hostedZoneID, dns: dns, z: file.NewZone(dns, "")})
}
- zones[dns] = &zone{id: id, z: file.NewZone(dns, "")}
- zoneNames = append(zoneNames, dns)
}
return &Route53{
client: c,
@@ -101,9 +112,14 @@ func (h *Route53) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
m.SetReply(r)
m.Authoritative, m.RecursionAvailable = true, true
var result file.Result
- h.zMu.RLock()
- m.Answer, m.Ns, m.Extra, result = z.z.Lookup(state, qname)
- h.zMu.RUnlock()
+ for _, hostedZone := range z {
+ h.zMu.RLock()
+ m.Answer, m.Ns, m.Extra, result = hostedZone.z.Lookup(state, qname)
+ h.zMu.RUnlock()
+ if len(m.Answer) != 0 {
+ break
+ }
+ }
if len(m.Answer) == 0 && h.Fall.Through(qname) {
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
@@ -146,36 +162,37 @@ func (h *Route53) updateZones(ctx context.Context) error {
errc := make(chan error)
defer close(errc)
for zName, z := range h.zones {
- go func(zName string, z *zone) {
+ go func(zName string, z []*zone) {
var err error
defer func() {
errc <- err
}()
- newZ := file.NewZone(zName, "")
- newZ.Upstream = *h.upstream
-
- in := &route53.ListResourceRecordSetsInput{
- HostedZoneId: aws.String(z.id),
- }
- err = h.client.ListResourceRecordSetsPagesWithContext(ctx, in,
- func(out *route53.ListResourceRecordSetsOutput, last bool) bool {
- for _, rrs := range out.ResourceRecordSets {
- if err := updateZoneFromRRS(rrs, newZ); err != nil {
- // Maybe unsupported record type. Log and carry on.
- log.Warningf("Failed to process resource record set: %v", err)
+ for i, hostedZone := range z {
+ newZ := file.NewZone(zName, "")
+ newZ.Upstream = *h.upstream
+ in := &route53.ListResourceRecordSetsInput{
+ HostedZoneId: aws.String(hostedZone.id),
+ }
+ err = h.client.ListResourceRecordSetsPagesWithContext(ctx, in,
+ func(out *route53.ListResourceRecordSetsOutput, last bool) bool {
+ for _, rrs := range out.ResourceRecordSets {
+ if err := updateZoneFromRRS(rrs, newZ); err != nil {
+ // Maybe unsupported record type. Log and carry on.
+ log.Warningf("Failed to process resource record set: %v", err)
+ }
}
- }
- return true
- })
- if err != nil {
- err = fmt.Errorf("failed to list resource records for %v:%v from route53: %v", zName, z.id, err)
- return
+ return true
+ })
+ if err != nil {
+ err = fmt.Errorf("failed to list resource records for %v:%v from route53: %v", zName, hostedZone.id, err)
+ return
+ }
+ h.zMu.Lock()
+ (*z[i]).z = newZ
+ h.zMu.Unlock()
}
- h.zMu.Lock()
- z.z = newZ
- h.zMu.Unlock()
}(zName, z)
}
// Collect errors (if any). This will also sync on all zones updates