| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | // Package route53 implements a plugin that returns resource records
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | // from AWS route53.
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | package route53
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							| 
									
										
										
										
											2018-04-22 08:34:35 +01:00
										 |  |  | 	"context"
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | 	"errors"
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	"fmt"
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | 	"strconv"
 | 
					
						
							|  |  |  | 	"strings"
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	"sync"
 | 
					
						
							|  |  |  | 	"time"
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin"
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	"github.com/coredns/coredns/plugin/file"
 | 
					
						
							| 
									
										
										
										
											2018-09-25 11:41:05 -07:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/fall"
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/upstream"
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 	"github.com/coredns/coredns/request"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/aws/aws-sdk-go/aws"
 | 
					
						
							|  |  |  | 	"github.com/aws/aws-sdk-go/service/route53"
 | 
					
						
							|  |  |  | 	"github.com/aws/aws-sdk-go/service/route53/route53iface"
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | // Route53 is a plugin that returns RR from AWS route53.
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | type Route53 struct {
 | 
					
						
							|  |  |  | 	Next plugin.Handler
 | 
					
						
							| 
									
										
										
										
											2018-09-25 11:41:05 -07:00
										 |  |  | 	Fall fall.F
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	zoneNames []string
 | 
					
						
							|  |  |  | 	client    route53iface.Route53API
 | 
					
						
							|  |  |  | 	upstream  *upstream.Upstream
 | 
					
						
							| 
									
										
										
										
											2019-08-03 18:07:28 -07:00
										 |  |  | 	refresh   time.Duration
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	zMu   sync.RWMutex
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 	zones zones
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | type zone struct {
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 	id  string
 | 
					
						
							|  |  |  | 	z   *file.Zone
 | 
					
						
							|  |  |  | 	dns string
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | type zones map[string][]*zone
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // New reads from the keys map which uses domain names as its key and hosted
 | 
					
						
							| 
									
										
										
										
											2019-08-13 15:02:29 +00:00
										 |  |  | // 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 use
 | 
					
						
							|  |  |  | // 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, refresh time.Duration) (*Route53, error) {
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 	zones := make(map[string][]*zone, len(keys))
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	zoneNames := make([]string, 0, len(keys))
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 	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, "")})
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 		}
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	return &Route53{
 | 
					
						
							|  |  |  | 		client:    c,
 | 
					
						
							|  |  |  | 		zoneNames: zoneNames,
 | 
					
						
							|  |  |  | 		zones:     zones,
 | 
					
						
							| 
									
										
										
										
											2019-08-13 15:02:29 +00:00
										 |  |  | 		upstream:  upstream.New(),
 | 
					
						
							| 
									
										
										
										
											2019-08-03 18:07:28 -07:00
										 |  |  | 		refresh:   refresh,
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	}, nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | // Run executes first update, spins up an update forever-loop.
 | 
					
						
							|  |  |  | // Returns error if first update fails.
 | 
					
						
							|  |  |  | func (h *Route53) Run(ctx context.Context) error {
 | 
					
						
							|  |  |  | 	if err := h.updateZones(ctx); err != nil {
 | 
					
						
							|  |  |  | 		return err
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	go func() {
 | 
					
						
							| 
									
										
										
										
											2022-03-04 02:36:02 -05:00
										 |  |  | 		timer := time.NewTimer(h.refresh)
 | 
					
						
							|  |  |  | 		defer timer.Stop()
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 		for {
 | 
					
						
							| 
									
										
										
										
											2022-03-04 02:36:02 -05:00
										 |  |  | 			timer.Reset(h.refresh)
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 			select {
 | 
					
						
							|  |  |  | 			case <-ctx.Done():
 | 
					
						
							| 
									
										
										
										
											2020-10-24 05:37:01 -07:00
										 |  |  | 				log.Debugf("Breaking out of Route53 update loop for %v: %v", h.zoneNames, ctx.Err())
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 				return
 | 
					
						
							| 
									
										
										
										
											2022-03-04 02:36:02 -05:00
										 |  |  | 			case <-timer.C:
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 				if err := h.updateZones(ctx); err != nil && ctx.Err() == nil /* Don't log error if ctx expired. */ {
 | 
					
						
							| 
									
										
										
										
											2020-10-24 05:37:01 -07:00
										 |  |  | 					log.Errorf("Failed to update zones %v: %v", h.zoneNames, err)
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 				}
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}()
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | // ServeDNS implements the plugin.Handler.ServeDNS.
 | 
					
						
							|  |  |  | func (h *Route53) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 | 
					
						
							|  |  |  | 	state := request.Request{W: w, Req: r}
 | 
					
						
							|  |  |  | 	qname := state.Name()
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	zName := plugin.Zones(h.zoneNames).Matches(qname)
 | 
					
						
							|  |  |  | 	if zName == "" {
 | 
					
						
							|  |  |  | 		return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	z, ok := h.zones[zName]
 | 
					
						
							|  |  |  | 	if !ok || z == nil {
 | 
					
						
							|  |  |  | 		return dns.RcodeServerFailure, nil
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m := new(dns.Msg)
 | 
					
						
							|  |  |  | 	m.SetReply(r)
 | 
					
						
							| 
									
										
										
										
											2018-12-30 17:05:08 +01:00
										 |  |  | 	m.Authoritative = true
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	var result file.Result
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 	for _, hostedZone := range z {
 | 
					
						
							|  |  |  | 		h.zMu.RLock()
 | 
					
						
							| 
									
										
										
										
											2019-03-26 14:37:30 +00:00
										 |  |  | 		m.Answer, m.Ns, m.Extra, result = hostedZone.z.Lookup(ctx, state, qname)
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 		h.zMu.RUnlock()
 | 
					
						
							| 
									
										
										
										
											2019-03-31 10:12:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Take the answer if it's non-empty OR if there is another
 | 
					
						
							|  |  |  | 		// record type exists for this name (NODATA).
 | 
					
						
							|  |  |  | 		if len(m.Answer) != 0 || result == file.NoData {
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 			break
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 10:12:33 -07:00
										 |  |  | 	if len(m.Answer) == 0 && result != file.NoData && h.Fall.Through(qname) {
 | 
					
						
							| 
									
										
										
										
											2018-09-25 11:41:05 -07:00
										 |  |  | 		return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	switch result {
 | 
					
						
							|  |  |  | 	case file.Success:
 | 
					
						
							|  |  |  | 	case file.NoData:
 | 
					
						
							|  |  |  | 	case file.NameError:
 | 
					
						
							|  |  |  | 		m.Rcode = dns.RcodeNameError
 | 
					
						
							|  |  |  | 	case file.Delegation:
 | 
					
						
							|  |  |  | 		m.Authoritative = false
 | 
					
						
							|  |  |  | 	case file.ServerFailure:
 | 
					
						
							|  |  |  | 		return dns.RcodeServerFailure, nil
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	w.WriteMsg(m)
 | 
					
						
							|  |  |  | 	return dns.RcodeSuccess, nil
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 22:51:14 -07:00
										 |  |  | const escapeSeq = "\\"
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // maybeUnescape parses s and converts escaped ASCII codepoints (in octal) back
 | 
					
						
							|  |  |  | // to its ASCII representation.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // From AWS docs:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // "If the domain name includes any characters other than a to z, 0 to 9, -
 | 
					
						
							|  |  |  | // (hyphen), or _ (underscore), Route 53 API actions return the characters as
 | 
					
						
							|  |  |  | // escape codes."
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // For our purposes (and with respect to RFC 1035), we'll fish for a-z, 0-9,
 | 
					
						
							|  |  |  | // '-', '.' and '*' as the leftmost character (for wildcards) and throw error
 | 
					
						
							|  |  |  | // for everything else.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Example:
 | 
					
						
							| 
									
										
										
										
											2023-06-09 18:08:23 +02:00
										 |  |  | //
 | 
					
						
							|  |  |  | //	`\\052.example.com.` -> `*.example.com`
 | 
					
						
							|  |  |  | //	`\\137.example.com.` -> error ('_' is not valid)
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | func maybeUnescape(s string) (string, error) {
 | 
					
						
							|  |  |  | 	var out string
 | 
					
						
							|  |  |  | 	for {
 | 
					
						
							|  |  |  | 		i := strings.Index(s, escapeSeq)
 | 
					
						
							|  |  |  | 		if i < 0 {
 | 
					
						
							|  |  |  | 			return out + s, nil
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		out += s[:i]
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		li, ri := i+len(escapeSeq), i+len(escapeSeq)+3
 | 
					
						
							|  |  |  | 		if ri > len(s) {
 | 
					
						
							|  |  |  | 			return "", fmt.Errorf("invalid escape sequence: '%s%s'", escapeSeq, s[li:])
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		// Parse `\\xxx` in base 8 (2nd arg) and attempt to fit into
 | 
					
						
							|  |  |  | 		// 8-bit result (3rd arg).
 | 
					
						
							|  |  |  | 		n, err := strconv.ParseInt(s[li:ri], 8, 8)
 | 
					
						
							|  |  |  | 		if err != nil {
 | 
					
						
							|  |  |  | 			return "", fmt.Errorf("invalid escape sequence: '%s%s'", escapeSeq, s[li:ri])
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		r := rune(n)
 | 
					
						
							|  |  |  | 		switch {
 | 
					
						
							|  |  |  | 		case r >= rune('a') && r <= rune('z'): // Route53 converts everything to lowercase.
 | 
					
						
							|  |  |  | 		case r >= rune('0') && r <= rune('9'):
 | 
					
						
							|  |  |  | 		case r == rune('*'):
 | 
					
						
							|  |  |  | 			if out != "" {
 | 
					
						
							| 
									
										
										
										
											2019-10-09 15:24:18 +08:00
										 |  |  | 				return "", errors.New("`*' only supported as wildcard (leftmost label)")
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | 			}
 | 
					
						
							|  |  |  | 		case r == rune('-'):
 | 
					
						
							|  |  |  | 		case r == rune('.'):
 | 
					
						
							|  |  |  | 		default:
 | 
					
						
							|  |  |  | 			return "", fmt.Errorf("invalid character: %s%#03o", escapeSeq, r)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		out += string(r)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		s = s[i+len(escapeSeq)+3:]
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | func updateZoneFromRRS(rrs *route53.ResourceRecordSet, z *file.Zone) error {
 | 
					
						
							|  |  |  | 	for _, rr := range rrs.ResourceRecords {
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | 		n, err := maybeUnescape(aws.StringValue(rrs.Name))
 | 
					
						
							|  |  |  | 		if err != nil {
 | 
					
						
							|  |  |  | 			return fmt.Errorf("failed to unescape `%s' name: %v", aws.StringValue(rrs.Name), err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		v, err := maybeUnescape(aws.StringValue(rr.Value))
 | 
					
						
							|  |  |  | 		if err != nil {
 | 
					
						
							|  |  |  | 			return fmt.Errorf("failed to unescape `%s' value: %v", aws.StringValue(rr.Value), err)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 		// Assemble RFC 1035 conforming record to pass into dns scanner.
 | 
					
						
							| 
									
										
										
										
											2019-03-13 11:46:30 -07:00
										 |  |  | 		rfc1035 := fmt.Sprintf("%s %d IN %s %s", n, aws.Int64Value(rrs.TTL), aws.StringValue(rrs.Type), v)
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 		r, err := dns.NewRR(rfc1035)
 | 
					
						
							|  |  |  | 		if err != nil {
 | 
					
						
							|  |  |  | 			return fmt.Errorf("failed to parse resource record: %v", err)
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 		z.Insert(r)
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	return nil
 | 
					
						
							| 
									
										
										
										
											2018-01-15 09:59:29 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | // updateZones re-queries resource record sets for each zone and updates the
 | 
					
						
							|  |  |  | // zone object.
 | 
					
						
							|  |  |  | // Returns error if any zones error'ed out, but waits for other zones to
 | 
					
						
							|  |  |  | // complete first.
 | 
					
						
							|  |  |  | func (h *Route53) updateZones(ctx context.Context) error {
 | 
					
						
							|  |  |  | 	errc := make(chan error)
 | 
					
						
							|  |  |  | 	defer close(errc)
 | 
					
						
							|  |  |  | 	for zName, z := range h.zones {
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 		go func(zName string, z []*zone) {
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 			var err error
 | 
					
						
							|  |  |  | 			defer func() {
 | 
					
						
							|  |  |  | 				errc <- err
 | 
					
						
							|  |  |  | 			}()
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 			for i, hostedZone := range z {
 | 
					
						
							|  |  |  | 				newZ := file.NewZone(zName, "")
 | 
					
						
							| 
									
										
										
										
											2019-01-13 16:54:49 +00:00
										 |  |  | 				newZ.Upstream = h.upstream
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 				in := &route53.ListResourceRecordSetsInput{
 | 
					
						
							|  |  |  | 					HostedZoneId: aws.String(hostedZone.id),
 | 
					
						
							| 
									
										
										
										
											2019-08-03 18:07:28 -07:00
										 |  |  | 					MaxItems:     aws.String("1000"),
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 				}
 | 
					
						
							|  |  |  | 				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)
 | 
					
						
							|  |  |  | 							}
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 						}
 | 
					
						
							| 
									
										
										
										
											2018-10-10 10:55:54 -07:00
										 |  |  | 						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()
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 			}
 | 
					
						
							| 
									
										
										
										
											2018-09-22 05:26:17 -07:00
										 |  |  | 		}(zName, z)
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 	// Collect errors (if any). This will also sync on all zones updates
 | 
					
						
							|  |  |  | 	// completion.
 | 
					
						
							|  |  |  | 	var errs []string
 | 
					
						
							| 
									
										
										
										
											2025-05-29 03:50:55 +03:00
										 |  |  | 	for range len(h.zones) {
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 		err := <-errc
 | 
					
						
							|  |  |  | 		if err != nil {
 | 
					
						
							|  |  |  | 			errs = append(errs, err.Error())
 | 
					
						
							| 
									
										
										
										
											2018-03-13 15:10:07 -07:00
										 |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | 	if len(errs) != 0 {
 | 
					
						
							|  |  |  | 		return fmt.Errorf("errors updating zones: %v", errs)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return nil
 | 
					
						
							| 
									
										
										
										
											2018-03-13 15:10:07 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 11:19:07 -07:00
										 |  |  | // Name implements plugin.Handler.Name.
 | 
					
						
							|  |  |  | func (h *Route53) Name() string { return "route53" }
 |