Skip to content

Commit 966c392

Browse files
fjlatif-konasl
authored andcommitted
cmd/devp2p: add dns nuke-route53 command (ethereum#22695)
1 parent 72e7d5c commit 966c392

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

cmd/devp2p/dns_route53.go

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,22 +107,48 @@ func (c *route53Client) deploy(name string, t *dnsdisc.Tree) error {
107107
return err
108108
}
109109
log.Info(fmt.Sprintf("Found %d TXT records", len(existing)))
110-
111110
records := t.ToTXT(name)
112111
changes := c.computeChanges(name, records, existing)
112+
113+
// Submit to API.
114+
comment := fmt.Sprintf("enrtree update of %s at seq %d", name, t.Seq())
115+
return c.submitChanges(changes, comment)
116+
}
117+
118+
// deleteDomain removes all TXT records of the given domain.
119+
func (c *route53Client) deleteDomain(name string) error {
120+
if err := c.checkZone(name); err != nil {
121+
return err
122+
}
123+
124+
// Compute DNS changes.
125+
existing, err := c.collectRecords(name)
126+
if err != nil {
127+
return err
128+
}
129+
log.Info(fmt.Sprintf("Found %d TXT records", len(existing)))
130+
changes := makeDeletionChanges(existing, nil)
131+
132+
// Submit to API.
133+
comment := "enrtree delete of " + name
134+
return c.submitChanges(changes, comment)
135+
}
136+
137+
// submitChanges submits the given DNS changes to Route53.
138+
func (c *route53Client) submitChanges(changes []types.Change, comment string) error {
113139
if len(changes) == 0 {
114140
log.Info("No DNS changes needed")
115141
return nil
116142
}
117143

118-
// Submit all change batches.
144+
var err error
119145
batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit)
120146
changesToCheck := make([]*route53.ChangeResourceRecordSetsOutput, len(batches))
121147
for i, changes := range batches {
122148
log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes)))
123149
batch := &types.ChangeBatch{
124150
Changes: changes,
125-
Comment: aws.String(fmt.Sprintf("enrtree update %d/%d of %s at seq %d", i+1, len(batches), name, t.Seq())),
151+
Comment: aws.String(fmt.Sprintf("%s (%d/%d)", comment, i+1, len(batches))),
126152
}
127153
req := &route53.ChangeResourceRecordSetsInput{HostedZoneId: &c.zoneID, ChangeBatch: batch}
128154
changesToCheck[i], err = c.api.ChangeResourceRecordSets(context.TODO(), req)
@@ -151,7 +177,6 @@ func (c *route53Client) deploy(name string, t *dnsdisc.Tree) error {
151177
time.Sleep(30 * time.Second)
152178
}
153179
}
154-
155180
return nil
156181
}
157182

@@ -186,7 +211,8 @@ func (c *route53Client) findZoneID(name string) (string, error) {
186211
return "", errors.New("can't find zone ID for " + name)
187212
}
188213

189-
// computeChanges creates DNS changes for the given record.
214+
// computeChanges creates DNS changes for the given set of DNS discovery records.
215+
// The 'existing' arg is the set of records that already exist on Route53.
190216
func (c *route53Client) computeChanges(name string, records map[string]string, existing map[string]recordSet) []types.Change {
191217
// Convert all names to lowercase.
192218
lrecords := make(map[string]string, len(records))
@@ -223,16 +249,23 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
223249
}
224250

225251
// Iterate over the old records and delete anything stale.
226-
for path, set := range existing {
227-
if _, ok := records[path]; ok {
252+
changes = append(changes, makeDeletionChanges(existing, records)...)
253+
254+
// Ensure changes are in the correct order.
255+
sortChanges(changes)
256+
return changes
257+
}
258+
259+
// makeDeletionChanges creates record changes which delete all records not contained in 'keep'.
260+
func makeDeletionChanges(records map[string]recordSet, keep map[string]string) []types.Change {
261+
var changes []types.Change
262+
for path, set := range records {
263+
if _, ok := keep[path]; ok {
228264
continue
229265
}
230-
// Stale entry, nuke it.
231-
log.Info(fmt.Sprintf("Deleting %s = %q", path, strings.Join(set.values, "")))
266+
log.Info(fmt.Sprintf("Deleting %s = %s", path, strings.Join(set.values, "")))
232267
changes = append(changes, newTXTChange("DELETE", path, set.ttl, set.values...))
233268
}
234-
235-
sortChanges(changes)
236269
return changes
237270
}
238271

cmd/devp2p/dnscmd.go

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ var (
4343
dnsTXTCommand,
4444
dnsCloudflareCommand,
4545
dnsRoute53Command,
46+
dnsRoute53NukeCommand,
4647
},
4748
}
4849
dnsSyncCommand = cli.Command{
@@ -84,6 +85,18 @@ var (
8485
route53RegionFlag,
8586
},
8687
}
88+
dnsRoute53NukeCommand = cli.Command{
89+
Name: "nuke-route53",
90+
Usage: "Deletes DNS TXT records of a subdomain on Amazon Route53",
91+
ArgsUsage: "<domain>",
92+
Action: dnsNukeRoute53,
93+
Flags: []cli.Flag{
94+
route53AccessKeyFlag,
95+
route53AccessSecretFlag,
96+
route53ZoneIDFlag,
97+
route53RegionFlag,
98+
},
99+
}
87100
)
88101

89102
var (
@@ -174,6 +187,9 @@ func dnsSign(ctx *cli.Context) error {
174187
return nil
175188
}
176189

190+
// directoryName returns the directory name of the given path.
191+
// For example, when dir is "foo/bar", it returns "bar".
192+
// When dir is ".", and the working directory is "example/foo", it returns "foo".
177193
func directoryName(dir string) string {
178194
abs, err := filepath.Abs(dir)
179195
if err != nil {
@@ -182,7 +198,7 @@ func directoryName(dir string) string {
182198
return filepath.Base(abs)
183199
}
184200

185-
// dnsToTXT peforms dnsTXTCommand.
201+
// dnsToTXT performs dnsTXTCommand.
186202
func dnsToTXT(ctx *cli.Context) error {
187203
if ctx.NArg() < 1 {
188204
return fmt.Errorf("need tree definition directory as argument")
@@ -199,9 +215,9 @@ func dnsToTXT(ctx *cli.Context) error {
199215
return nil
200216
}
201217

202-
// dnsToCloudflare peforms dnsCloudflareCommand.
218+
// dnsToCloudflare performs dnsCloudflareCommand.
203219
func dnsToCloudflare(ctx *cli.Context) error {
204-
if ctx.NArg() < 1 {
220+
if ctx.NArg() != 1 {
205221
return fmt.Errorf("need tree definition directory as argument")
206222
}
207223
domain, t, err := loadTreeDefinitionForExport(ctx.Args().Get(0))
@@ -212,9 +228,9 @@ func dnsToCloudflare(ctx *cli.Context) error {
212228
return client.deploy(domain, t)
213229
}
214230

215-
// dnsToRoute53 peforms dnsRoute53Command.
231+
// dnsToRoute53 performs dnsRoute53Command.
216232
func dnsToRoute53(ctx *cli.Context) error {
217-
if ctx.NArg() < 1 {
233+
if ctx.NArg() != 1 {
218234
return fmt.Errorf("need tree definition directory as argument")
219235
}
220236
domain, t, err := loadTreeDefinitionForExport(ctx.Args().Get(0))
@@ -225,6 +241,15 @@ func dnsToRoute53(ctx *cli.Context) error {
225241
return client.deploy(domain, t)
226242
}
227243

244+
// dnsNukeRoute53 performs dnsRoute53NukeCommand.
245+
func dnsNukeRoute53(ctx *cli.Context) error {
246+
if ctx.NArg() != 1 {
247+
return fmt.Errorf("need domain name as argument")
248+
}
249+
client := newRoute53Client(ctx)
250+
return client.deleteDomain(ctx.Args().First())
251+
}
252+
228253
// loadSigningKey loads a private key in Ethereum keystore format.
229254
func loadSigningKey(keyfile string) *ecdsa.PrivateKey {
230255
keyjson, err := ioutil.ReadFile(keyfile)

0 commit comments

Comments
 (0)