mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 16:24:19 -04:00
plugin/route53: add split zone support (#2160)
Automatically submitted.
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user