diff options
Diffstat (limited to 'plugin/route53/route53.go')
-rw-r--r-- | plugin/route53/route53.go | 97 |
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 |