From faaedb812d89f78ef3ccde7473fcefaac4bf7c48 Mon Sep 17 00:00:00 2001 From: Andrew Ayer Date: Wed, 7 Oct 2020 14:05:59 -0400 Subject: [PATCH 1/2] Update to latest version of github.com/miekg/dns Closes: #302 --- bind.go | 14 +++++++++----- go.mod | 2 +- go.sum | 9 +++++++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/bind.go b/bind.go index 60e24127..0c897bc8 100644 --- a/bind.go +++ b/bind.go @@ -39,15 +39,19 @@ func parseComment(rr dns.RR, comment string) dns.RR { } func parseBindFile(reader io.Reader, filename, origin string) []dns.RR { - tokensch := dns.ParseZone(reader, origin, filename) + parser := dns.NewZoneParser(reader, origin, filename) records := []dns.RR{} - for token := range tokensch { - if token.Error != nil { - fatalIfErr(token.Error) + for { + rr, ok := parser.Next() + if !ok { + break } - record := parseComment(token.RR, token.Comment) + record := parseComment(rr, parser.Comment()) records = append(records, record) } + if err := parser.Err(); err != nil { + fatalIfErr(err) + } return records } diff --git a/go.mod b/go.mod index 61b15bd2..bf089039 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/aws/aws-sdk-go v1.29.19 github.com/bobisme/gucumber v0.0.0-20181101035029-55b04af03920 // indirect github.com/gucumber/gucumber v0.0.0-20180127021336-7d5c79e832a2 - github.com/miekg/dns v0.0.0-20170818131442-e4205768578d + github.com/miekg/dns v1.1.31 github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect github.com/stretchr/testify v1.4.0 github.com/urfave/cli/v2 v2.2.0 diff --git a/go.sum b/go.sum index 8c5f1e8f..4d340e3b 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5i github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/miekg/dns v0.0.0-20170818131442-e4205768578d h1:M1nGptTlM6l6aT5MUYA5XExwSjnIPHA+xEOWobbMU6g= github.com/miekg/dns v0.0.0-20170818131442-e4205768578d/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -35,21 +37,28 @@ github.com/wadey/gocovmerge v0.0.0-20160331181800-b5bfa59ec0ad/go.mod h1:Hy8o65+ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200809012840-6f4f008689da h1:ml5G98G4/tdKT1XNq+ky5iSRdKKux0TANlLAzmXT/hg= golang.org/x/tools v0.0.0-20200809012840-6f4f008689da/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From ce3fc7b9f3cc125d9cc469f7402ad28203b4cbed Mon Sep 17 00:00:00 2001 From: Nathan Neulinger Date: Sat, 8 Aug 2020 12:22:46 -0500 Subject: [PATCH 2/2] Add upsert mode that can be used with import to only add/replace additional records found in the file --- README.md | 4 ++++ commands.go | 33 +++++++++++++++++++++----------- internal/features/import.feature | 6 ++++++ main.go | 5 +++++ tests/upsert1.txt | 14 ++++++++++++++ tests/upsert2.txt | 5 +++++ tests/upsert3.txt | 15 +++++++++++++++ 7 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 tests/upsert1.txt create mode 100644 tests/upsert2.txt create mode 100644 tests/upsert3.txt diff --git a/README.md b/README.md index f7ab4647..c0655587 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,10 @@ Also you can 'dry-run' import, to check what will happen: $ cli53 import --file zonefile.txt --replace --wait --dry-run example.com +Upsert with an imported zone (replace existing and add new records, without deleting): + + $ cli53 import --file zonefile.txt --upsert example.com + Create an A record pointed to 192.168.0.1 with TTL of 60 seconds: $ cli53 rrcreate example.com 'www 60 A 192.168.0.1' diff --git a/commands.go b/commands.go index 431b27ed..e66621e2 100644 --- a/commands.go +++ b/commands.go @@ -239,6 +239,7 @@ type importArgs struct { wait bool editauth bool replace bool + upsert bool dryrun bool } @@ -279,7 +280,7 @@ func importBind(args importArgs) { grouped := groupRecords(records) existing := map[string]*route53.ResourceRecordSet{} - if args.replace { + if args.replace || args.upsert { rrsets, err := ListAllRecordSets(r53, *zone.Id) fatalIfErr(err) for _, rrset := range rrsets { @@ -299,24 +300,34 @@ func importBind(args importArgs) { // no difference - leave it untouched delete(existing, key) } else { - // new record, add - change := route53.Change{ - Action: aws.String("CREATE"), - ResourceRecordSet: rrset, + // new record, add or upsert + if args.upsert { + change := route53.Change{ + Action: aws.String("UPSERT"), + ResourceRecordSet: rrset, + } + additions = append(additions, &change) + } else { + change := route53.Change{ + Action: aws.String("CREATE"), + ResourceRecordSet: rrset, + } + additions = append(additions, &change) } - additions = append(additions, &change) } } } // remaining records in existing should be deleted deletions := []*route53.Change{} - for _, rrset := range existing { - change := route53.Change{ - Action: aws.String("DELETE"), - ResourceRecordSet: rrset, + if !args.upsert { + for _, rrset := range existing { + change := route53.Change{ + Action: aws.String("DELETE"), + ResourceRecordSet: rrset, + } + deletions = append(deletions, &change) } - deletions = append(deletions, &change) } if args.dryrun { diff --git a/internal/features/import.feature b/internal/features/import.feature index e6ed05be..c8bbeaf4 100644 --- a/internal/features/import.feature +++ b/internal/features/import.feature @@ -72,6 +72,12 @@ Feature: import And I run "cli53 import --replace --file tests/replace2.txt $domain" Then the domain "$domain" export matches file "tests/replace2.txt" + Scenario: I can import (upsert) a zone + Given I have a domain "$domain" + When I run "cli53 import --file tests/upsert1.txt $domain" + And I run "cli53 import --upsert --file tests/upsert2.txt $domain" + Then the domain "$domain" export matches file "tests/upsert3.txt" + Scenario: I can import dry-run (with changes) Given I have a domain "$domain" When I run "cli53 import --file tests/replace1.txt $domain" diff --git a/main.go b/main.go index d8891fd7..16e64b87 100644 --- a/main.go +++ b/main.go @@ -153,6 +153,10 @@ func Main(args []string) int { Name: "replace", Usage: "replace all existing records", }, + &cli.BoolFlag{ + Name: "upsert", + Usage: "update or replace records, do not delete existing", + }, &cli.BoolFlag{ Name: "dry-run", Aliases: []string{"n"}, @@ -174,6 +178,7 @@ func Main(args []string) int { wait: c.Bool("wait"), editauth: c.Bool("editauth"), replace: c.Bool("replace"), + upsert: c.Bool("upsert"), dryrun: c.Bool("dry-run"), } importBind(args) diff --git a/tests/upsert1.txt b/tests/upsert1.txt new file mode 100644 index 00000000..2cd3af15 --- /dev/null +++ b/tests/upsert1.txt @@ -0,0 +1,14 @@ +@ 86400 IN A 10.0.0.1 +@ 86400 IN MX 10 mail.example.com. +@ 86400 IN MX 20 mail2.example.com. +@ 900 IN SOA ns1.somenameserver.com. blah.example.com. 1 7200 900 1209600 86400 +@ 172800 IN NS ns1.somenameserver.com. +@ 172800 IN NS ns2.somenameserver.com. +@ 86400 IN TXT "v=spf1 a mx a:cli53.example.com mx:mail.example.com ip4:10.0.0.0/24 ~all" +mail 86400 IN A 10.0.0.2 +mail2 86400 IN A 10.0.0.3 +test 86400 IN TXT "multivalued" " txt \"quoted\" record" +www 86400 IN A 10.0.0.1 +www2 86400 IN A 10.0.0.1 +unchanged 86400 IN A 10.1.0.1 +alias 86400 AWS ALIAS A www $self false diff --git a/tests/upsert2.txt b/tests/upsert2.txt new file mode 100644 index 00000000..c1984a65 --- /dev/null +++ b/tests/upsert2.txt @@ -0,0 +1,5 @@ +test 86400 IN TXT "multivalued" " txt \"quoted\" record" +www2 86400 IN A 10.0.0.5 +www3 86400 IN A 10.0.0.5 +unchanged 86400 IN A 10.1.0.1 +alias 86400 AWS ALIAS A www $self false diff --git a/tests/upsert3.txt b/tests/upsert3.txt new file mode 100644 index 00000000..59fcef4f --- /dev/null +++ b/tests/upsert3.txt @@ -0,0 +1,15 @@ +@ 86400 IN A 10.0.0.1 +@ 86400 IN MX 10 mail.example.com. +@ 86400 IN MX 20 mail2.example.com. +@ 900 IN SOA ns1.somenameserver.com. blah.example.com. 1 7200 900 1209600 86400 +@ 172800 IN NS ns1.somenameserver.com. +@ 172800 IN NS ns2.somenameserver.com. +@ 86400 IN TXT "v=spf1 a mx a:cli53.example.com mx:mail.example.com ip4:10.0.0.0/24 ~all" +mail 86400 IN A 10.0.0.2 +mail2 86400 IN A 10.0.0.3 +test 86400 IN TXT "multivalued" " txt \"quoted\" record" +www 86400 IN A 10.0.0.1 +www2 86400 IN A 10.0.0.5 +www3 86400 IN A 10.0.0.5 +unchanged 86400 IN A 10.1.0.1 +alias 86400 AWS ALIAS A www $self false