瀏覽代碼

cmd/devp2p: use AWS-SDK v2 (#22360)

This updates the DNS deployer to use AWS SDK v2. Migration is relatively
seamless, although there were two locations that required a slightly
different approach to achieve the same results. In particular, waiting for
DNS change propagation is very different with SDK v2. 

This change also optimizes DNS updates by publishing all changes before
waiting for propagation.
Quest Henkart 4 年之前
父節點
當前提交
e3a3f7cd64
共有 4 個文件被更改,包括 153 次插入87 次删除
  1. 87 49
      cmd/devp2p/dns_route53.go
  2. 36 36
      cmd/devp2p/dns_route53_test.go
  3. 5 2
      go.mod
  4. 25 0
      go.sum

+ 87 - 49
cmd/devp2p/dns_route53.go

@@ -17,16 +17,19 @@
 package main
 package main
 
 
 import (
 import (
+	"context"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
 	"sort"
 	"sort"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
+	"time"
 
 
-	"github.com/aws/aws-sdk-go/aws"
-	"github.com/aws/aws-sdk-go/aws/credentials"
-	"github.com/aws/aws-sdk-go/aws/session"
-	"github.com/aws/aws-sdk-go/service/route53"
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/config"
+	"github.com/aws/aws-sdk-go-v2/credentials"
+	"github.com/aws/aws-sdk-go-v2/service/route53"
+	"github.com/aws/aws-sdk-go-v2/service/route53/types"
 	"github.com/ethereum/go-ethereum/log"
 	"github.com/ethereum/go-ethereum/log"
 	"github.com/ethereum/go-ethereum/p2p/dnsdisc"
 	"github.com/ethereum/go-ethereum/p2p/dnsdisc"
 	"gopkg.in/urfave/cli.v1"
 	"gopkg.in/urfave/cli.v1"
@@ -38,6 +41,7 @@ const (
 	// https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets
 	// https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets
 	route53ChangeSizeLimit  = 32000
 	route53ChangeSizeLimit  = 32000
 	route53ChangeCountLimit = 1000
 	route53ChangeCountLimit = 1000
+	maxRetryLimit           = 60
 )
 )
 
 
 var (
 var (
@@ -58,7 +62,7 @@ var (
 )
 )
 
 
 type route53Client struct {
 type route53Client struct {
-	api    *route53.Route53
+	api    *route53.Client
 	zoneID string
 	zoneID string
 }
 }
 
 
@@ -74,13 +78,13 @@ func newRoute53Client(ctx *cli.Context) *route53Client {
 	if akey == "" || asec == "" {
 	if akey == "" || asec == "" {
 		exit(fmt.Errorf("need Route53 Access Key ID and secret proceed"))
 		exit(fmt.Errorf("need Route53 Access Key ID and secret proceed"))
 	}
 	}
-	config := &aws.Config{Credentials: credentials.NewStaticCredentials(akey, asec, "")}
-	session, err := session.NewSession(config)
+	creds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(akey, asec, ""))
+	cfg, err := config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(creds))
 	if err != nil {
 	if err != nil {
-		exit(fmt.Errorf("can't create AWS session: %v", err))
+		exit(fmt.Errorf("can't initialize AWS configuration: %v", err))
 	}
 	}
 	return &route53Client{
 	return &route53Client{
-		api:    route53.New(session),
+		api:    route53.NewFromConfig(cfg),
 		zoneID: ctx.String(route53ZoneIDFlag.Name),
 		zoneID: ctx.String(route53ZoneIDFlag.Name),
 	}
 	}
 }
 }
@@ -105,25 +109,43 @@ func (c *route53Client) deploy(name string, t *dnsdisc.Tree) error {
 		return nil
 		return nil
 	}
 	}
 
 
-	// Submit change batches.
+	// Submit all change batches.
 	batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit)
 	batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit)
+	changesToCheck := make([]*route53.ChangeResourceRecordSetsOutput, len(batches))
 	for i, changes := range batches {
 	for i, changes := range batches {
 		log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes)))
 		log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes)))
-		batch := new(route53.ChangeBatch)
-		batch.SetChanges(changes)
-		batch.SetComment(fmt.Sprintf("enrtree update %d/%d of %s at seq %d", i+1, len(batches), name, t.Seq()))
+		batch := &types.ChangeBatch{
+			Changes: changes,
+			Comment: aws.String(fmt.Sprintf("enrtree update %d/%d of %s at seq %d", i+1, len(batches), name, t.Seq())),
+		}
 		req := &route53.ChangeResourceRecordSetsInput{HostedZoneId: &c.zoneID, ChangeBatch: batch}
 		req := &route53.ChangeResourceRecordSetsInput{HostedZoneId: &c.zoneID, ChangeBatch: batch}
-		resp, err := c.api.ChangeResourceRecordSets(req)
+		changesToCheck[i], err = c.api.ChangeResourceRecordSets(context.TODO(), req)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
+	}
 
 
-		log.Info(fmt.Sprintf("Waiting for change request %s", *resp.ChangeInfo.Id))
-		wreq := &route53.GetChangeInput{Id: resp.ChangeInfo.Id}
-		if err := c.api.WaitUntilResourceRecordSetsChanged(wreq); err != nil {
-			return err
+	// wait for all change batches to propagate
+	for _, change := range changesToCheck {
+		log.Info(fmt.Sprintf("Waiting for change request %s", *change.ChangeInfo.Id))
+		wreq := &route53.GetChangeInput{Id: change.ChangeInfo.Id}
+		var count int
+		for {
+			wresp, err := c.api.GetChange(context.TODO(), wreq)
+			if err != nil {
+				return err
+			}
+
+			count++
+
+			if wresp.ChangeInfo.Status == types.ChangeStatusInsync || count >= maxRetryLimit {
+				break
+			}
+
+			time.Sleep(30 * time.Second)
 		}
 		}
 	}
 	}
+
 	return nil
 	return nil
 }
 }
 
 
@@ -140,7 +162,7 @@ func (c *route53Client) findZoneID(name string) (string, error) {
 	log.Info(fmt.Sprintf("Finding Route53 Zone ID for %s", name))
 	log.Info(fmt.Sprintf("Finding Route53 Zone ID for %s", name))
 	var req route53.ListHostedZonesByNameInput
 	var req route53.ListHostedZonesByNameInput
 	for {
 	for {
-		resp, err := c.api.ListHostedZonesByName(&req)
+		resp, err := c.api.ListHostedZonesByName(context.TODO(), &req)
 		if err != nil {
 		if err != nil {
 			return "", err
 			return "", err
 		}
 		}
@@ -149,7 +171,7 @@ func (c *route53Client) findZoneID(name string) (string, error) {
 				return *zone.Id, nil
 				return *zone.Id, nil
 			}
 			}
 		}
 		}
-		if !*resp.IsTruncated {
+		if !resp.IsTruncated {
 			break
 			break
 		}
 		}
 		req.DNSName = resp.NextDNSName
 		req.DNSName = resp.NextDNSName
@@ -159,7 +181,7 @@ func (c *route53Client) findZoneID(name string) (string, error) {
 }
 }
 
 
 // computeChanges creates DNS changes for the given record.
 // computeChanges creates DNS changes for the given record.
-func (c *route53Client) computeChanges(name string, records map[string]string, existing map[string]recordSet) []*route53.Change {
+func (c *route53Client) computeChanges(name string, records map[string]string, existing map[string]recordSet) []types.Change {
 	// Convert all names to lowercase.
 	// Convert all names to lowercase.
 	lrecords := make(map[string]string, len(records))
 	lrecords := make(map[string]string, len(records))
 	for name, r := range records {
 	for name, r := range records {
@@ -167,7 +189,7 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
 	}
 	}
 	records = lrecords
 	records = lrecords
 
 
-	var changes []*route53.Change
+	var changes []types.Change
 	for path, val := range records {
 	for path, val := range records {
 		ttl := int64(rootTTL)
 		ttl := int64(rootTTL)
 		if path != name {
 		if path != name {
@@ -204,21 +226,21 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
 }
 }
 
 
 // sortChanges ensures DNS changes are in leaf-added -> root-changed -> leaf-deleted order.
 // sortChanges ensures DNS changes are in leaf-added -> root-changed -> leaf-deleted order.
-func sortChanges(changes []*route53.Change) {
+func sortChanges(changes []types.Change) {
 	score := map[string]int{"CREATE": 1, "UPSERT": 2, "DELETE": 3}
 	score := map[string]int{"CREATE": 1, "UPSERT": 2, "DELETE": 3}
 	sort.Slice(changes, func(i, j int) bool {
 	sort.Slice(changes, func(i, j int) bool {
-		if *changes[i].Action == *changes[j].Action {
+		if changes[i].Action == changes[j].Action {
 			return *changes[i].ResourceRecordSet.Name < *changes[j].ResourceRecordSet.Name
 			return *changes[i].ResourceRecordSet.Name < *changes[j].ResourceRecordSet.Name
 		}
 		}
-		return score[*changes[i].Action] < score[*changes[j].Action]
+		return score[string(changes[i].Action)] < score[string(changes[j].Action)]
 	})
 	})
 }
 }
 
 
 // splitChanges splits up DNS changes such that each change batch
 // splitChanges splits up DNS changes such that each change batch
 // is smaller than the given RDATA limit.
 // is smaller than the given RDATA limit.
-func splitChanges(changes []*route53.Change, sizeLimit, countLimit int) [][]*route53.Change {
+func splitChanges(changes []types.Change, sizeLimit, countLimit int) [][]types.Change {
 	var (
 	var (
-		batches    [][]*route53.Change
+		batches    [][]types.Change
 		batchSize  int
 		batchSize  int
 		batchCount int
 		batchCount int
 	)
 	)
@@ -241,7 +263,7 @@ func splitChanges(changes []*route53.Change, sizeLimit, countLimit int) [][]*rou
 }
 }
 
 
 // changeSize returns the RDATA size of a DNS change.
 // changeSize returns the RDATA size of a DNS change.
-func changeSize(ch *route53.Change) int {
+func changeSize(ch types.Change) int {
 	size := 0
 	size := 0
 	for _, rr := range ch.ResourceRecordSet.ResourceRecords {
 	for _, rr := range ch.ResourceRecordSet.ResourceRecords {
 		if rr.Value != nil {
 		if rr.Value != nil {
@@ -251,8 +273,8 @@ func changeSize(ch *route53.Change) int {
 	return size
 	return size
 }
 }
 
 
-func changeCount(ch *route53.Change) int {
-	if *ch.Action == "UPSERT" {
+func changeCount(ch types.Change) int {
+	if ch.Action == types.ChangeActionUpsert {
 		return 2
 		return 2
 	}
 	}
 	return 1
 	return 1
@@ -262,13 +284,19 @@ func changeCount(ch *route53.Change) int {
 func (c *route53Client) collectRecords(name string) (map[string]recordSet, error) {
 func (c *route53Client) collectRecords(name string) (map[string]recordSet, error) {
 	log.Info(fmt.Sprintf("Retrieving existing TXT records on %s (%s)", name, c.zoneID))
 	log.Info(fmt.Sprintf("Retrieving existing TXT records on %s (%s)", name, c.zoneID))
 	var req route53.ListResourceRecordSetsInput
 	var req route53.ListResourceRecordSetsInput
-	req.SetHostedZoneId(c.zoneID)
+	req.HostedZoneId = &c.zoneID
 	existing := make(map[string]recordSet)
 	existing := make(map[string]recordSet)
-	err := c.api.ListResourceRecordSetsPages(&req, func(resp *route53.ListResourceRecordSetsOutput, last bool) bool {
+	for {
+		resp, err := c.api.ListResourceRecordSets(context.TODO(), &req)
+		if err != nil {
+			return existing, err
+		}
+
 		for _, set := range resp.ResourceRecordSets {
 		for _, set := range resp.ResourceRecordSets {
-			if !isSubdomain(*set.Name, name) || *set.Type != "TXT" {
+			if !isSubdomain(*set.Name, name) || set.Type != types.RRTypeTxt {
 				continue
 				continue
 			}
 			}
+
 			s := recordSet{ttl: *set.TTL}
 			s := recordSet{ttl: *set.TTL}
 			for _, rec := range set.ResourceRecords {
 			for _, rec := range set.ResourceRecords {
 				s.values = append(s.values, *rec.Value)
 				s.values = append(s.values, *rec.Value)
@@ -276,28 +304,38 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error
 			name := strings.TrimSuffix(*set.Name, ".")
 			name := strings.TrimSuffix(*set.Name, ".")
 			existing[name] = s
 			existing[name] = s
 		}
 		}
-		return true
-	})
-	return existing, err
+
+		if !resp.IsTruncated {
+			break
+		}
+
+		// sets the cursor to the next batch
+		req.StartRecordIdentifier = resp.NextRecordIdentifier
+	}
+
+	return existing, nil
 }
 }
 
 
 // newTXTChange creates a change to a TXT record.
 // newTXTChange creates a change to a TXT record.
-func newTXTChange(action, name string, ttl int64, values ...string) *route53.Change {
-	var c route53.Change
-	var r route53.ResourceRecordSet
-	var rrs []*route53.ResourceRecord
+func newTXTChange(action, name string, ttl int64, values ...string) types.Change {
+	r := types.ResourceRecordSet{
+		Type: types.RRTypeTxt,
+		Name: &name,
+		TTL:  &ttl,
+	}
+	var rrs []types.ResourceRecord
 	for _, val := range values {
 	for _, val := range values {
-		rr := new(route53.ResourceRecord)
-		rr.SetValue(val)
+		var rr types.ResourceRecord
+		rr.Value = aws.String(val)
 		rrs = append(rrs, rr)
 		rrs = append(rrs, rr)
 	}
 	}
-	r.SetType("TXT")
-	r.SetName(name)
-	r.SetTTL(ttl)
-	r.SetResourceRecords(rrs)
-	c.SetAction(action)
-	c.SetResourceRecordSet(&r)
-	return &c
+
+	r.ResourceRecords = rrs
+
+	return types.Change{
+		Action:            types.ChangeAction(action),
+		ResourceRecordSet: &r,
+	}
 }
 }
 
 
 // isSubdomain returns true if name is a subdomain of domain.
 // isSubdomain returns true if name is a subdomain of domain.

+ 36 - 36
cmd/devp2p/dns_route53_test.go

@@ -20,7 +20,7 @@ import (
 	"reflect"
 	"reflect"
 	"testing"
 	"testing"
 
 
-	"github.com/aws/aws-sdk-go/service/route53"
+	"github.com/aws/aws-sdk-go-v2/service/route53/types"
 )
 )
 
 
 // This test checks that computeChanges/splitChanges create DNS changes in
 // This test checks that computeChanges/splitChanges create DNS changes in
@@ -43,93 +43,93 @@ func TestRoute53ChangeSort(t *testing.T) {
 		"MHTDO6TMUBRIA2XWG5LUDACK24.n": "enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o",
 		"MHTDO6TMUBRIA2XWG5LUDACK24.n": "enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o",
 	}
 	}
 
 
-	wantChanges := []*route53.Change{
+	wantChanges := []types.Change{
 		{
 		{
-			Action: sp("CREATE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "CREATE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("2xs2367yhaxjfglzhvawlqd4zy.n"),
 				Name: sp("2xs2367yhaxjfglzhvawlqd4zy.n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA"`),
 					Value: sp(`"enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA"`),
 				}},
 				}},
 				TTL:  ip(treeNodeTTL),
 				TTL:  ip(treeNodeTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("CREATE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "CREATE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("c7hrfpf3blgf3yr4dy5kx3smbe.n"),
 				Name: sp("c7hrfpf3blgf3yr4dy5kx3smbe.n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"`),
 					Value: sp(`"enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"`),
 				}},
 				}},
 				TTL:  ip(treeNodeTTL),
 				TTL:  ip(treeNodeTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("CREATE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "CREATE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("h4fht4b454p6uxfd7jcyq5pwdy.n"),
 				Name: sp("h4fht4b454p6uxfd7jcyq5pwdy.n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI"`),
 					Value: sp(`"enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI"`),
 				}},
 				}},
 				TTL:  ip(treeNodeTTL),
 				TTL:  ip(treeNodeTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("CREATE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "CREATE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("jwxydbpxywg6fx3gmdibfa6cj4.n"),
 				Name: sp("jwxydbpxywg6fx3gmdibfa6cj4.n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24"`),
 					Value: sp(`"enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24"`),
 				}},
 				}},
 				TTL:  ip(treeNodeTTL),
 				TTL:  ip(treeNodeTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("CREATE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "CREATE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("mhtdo6tmubria2xwg5ludack24.n"),
 				Name: sp("mhtdo6tmubria2xwg5ludack24.n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o"`),
 					Value: sp(`"enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o"`),
 				}},
 				}},
 				TTL:  ip(treeNodeTTL),
 				TTL:  ip(treeNodeTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("UPSERT"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "UPSERT",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("n"),
 				Name: sp("n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA"`),
 					Value: sp(`"enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA"`),
 				}},
 				}},
 				TTL:  ip(rootTTL),
 				TTL:  ip(rootTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("DELETE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "DELETE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("2kfjogvxdqtxxugbh7gs7naaai.n"),
 				Name: sp("2kfjogvxdqtxxugbh7gs7naaai.n"),
-				ResourceRecords: []*route53.ResourceRecord{
+				ResourceRecords: []types.ResourceRecord{
 					{Value: sp(`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`)},
 					{Value: sp(`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`)},
 				},
 				},
 				TTL:  ip(3333),
 				TTL:  ip(3333),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 		{
 		{
-			Action: sp("DELETE"),
-			ResourceRecordSet: &route53.ResourceRecordSet{
+			Action: "DELETE",
+			ResourceRecordSet: &types.ResourceRecordSet{
 				Name: sp("fdxn3sn67na5dka4j2gok7bvqi.n"),
 				Name: sp("fdxn3sn67na5dka4j2gok7bvqi.n"),
-				ResourceRecords: []*route53.ResourceRecord{{
+				ResourceRecords: []types.ResourceRecord{{
 					Value: sp(`"enrtree-branch:"`),
 					Value: sp(`"enrtree-branch:"`),
 				}},
 				}},
 				TTL:  ip(treeNodeTTL),
 				TTL:  ip(treeNodeTTL),
-				Type: sp("TXT"),
+				Type: "TXT",
 			},
 			},
 		},
 		},
 	}
 	}
@@ -141,7 +141,7 @@ func TestRoute53ChangeSort(t *testing.T) {
 	}
 	}
 
 
 	// Check splitting according to size.
 	// Check splitting according to size.
-	wantSplit := [][]*route53.Change{
+	wantSplit := [][]types.Change{
 		wantChanges[:4],
 		wantChanges[:4],
 		wantChanges[4:6],
 		wantChanges[4:6],
 		wantChanges[6:],
 		wantChanges[6:],
@@ -152,7 +152,7 @@ func TestRoute53ChangeSort(t *testing.T) {
 	}
 	}
 
 
 	// Check splitting according to count.
 	// Check splitting according to count.
-	wantSplit = [][]*route53.Change{
+	wantSplit = [][]types.Change{
 		wantChanges[:5],
 		wantChanges[:5],
 		wantChanges[5:],
 		wantChanges[5:],
 	}
 	}

+ 5 - 2
go.mod

@@ -1,11 +1,14 @@
 module github.com/ethereum/go-ethereum
 module github.com/ethereum/go-ethereum
 
 
-go 1.13
+go 1.15
 
 
 require (
 require (
 	github.com/Azure/azure-storage-blob-go v0.7.0
 	github.com/Azure/azure-storage-blob-go v0.7.0
 	github.com/VictoriaMetrics/fastcache v1.5.7
 	github.com/VictoriaMetrics/fastcache v1.5.7
-	github.com/aws/aws-sdk-go v1.25.48
+	github.com/aws/aws-sdk-go-v2 v1.2.0
+	github.com/aws/aws-sdk-go-v2/config v1.1.1
+	github.com/aws/aws-sdk-go-v2/credentials v1.1.1
+	github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1
 	github.com/btcsuite/btcd v0.20.1-beta
 	github.com/btcsuite/btcd v0.20.1-beta
 	github.com/cespare/cp v0.1.0
 	github.com/cespare/cp v0.1.0
 	github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9
 	github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9

+ 25 - 0
go.sum

@@ -62,6 +62,24 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/aws/aws-sdk-go v1.25.48 h1:J82DYDGZHOKHdhx6hD24Tm30c2C3GchYGfN0mf9iKUk=
 github.com/aws/aws-sdk-go v1.25.48 h1:J82DYDGZHOKHdhx6hD24Tm30c2C3GchYGfN0mf9iKUk=
 github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
 github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go-v2 v1.2.0 h1:BS+UYpbsElC82gB+2E2jiCBg36i8HlubTB/dO/moQ9c=
+github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo=
+github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
+github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y=
+github.com/aws/aws-sdk-go-v2/credentials v1.1.1 h1:NbvWIM1Mx6sNPTxowHgS2ewXCRp+NGTzUYb/96FZJbY=
+github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 h1:EtEU7WRaWliitZh2nmuxEXrN0Cb8EgPUFGIoTMeqbzI=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 h1:4AH9fFjUlVktQMznF+YN33aWNXaR4VgDXyP28qokJC0=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4=
+github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 h1:37QubsarExl5ZuCBlnRP+7l1tNwZPBSTqpTBrPH98RU=
+github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0=
+github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5MwjwYN4iFhuYIhfIY=
+github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
+github.com/aws/smithy-go v1.1.0 h1:D6CSsM3gdxaGaqXnPgOBCeL6Mophqzu7KJOu7zW78sU=
+github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
@@ -193,6 +211,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
+github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@@ -265,6 +286,10 @@ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1C
 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
+github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
+github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
 github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=