diff --git a/acme/dns_challenge.go b/acme/dns_challenge.go index 63094064..f803d0a8 100644 --- a/acme/dns_challenge.go +++ b/acme/dns_challenge.go @@ -196,7 +196,7 @@ func checkAuthoritativeNss(fqdn, value string, nameservers []string) (bool, erro } if !found { - return false, fmt.Errorf("NS %s did not return the expected TXT record", ns) + return false, fmt.Errorf("NS %s did not return the expected TXT record [fqdn: %s]", ns, fqdn) } } diff --git a/providers/dns/ns1/ns1.go b/providers/dns/ns1/ns1.go index dab0b857..16be1c90 100644 --- a/providers/dns/ns1/ns1.go +++ b/providers/dns/ns1/ns1.go @@ -10,6 +10,7 @@ import ( "time" "github.com/xenolf/lego/acme" + "github.com/xenolf/lego/log" "github.com/xenolf/lego/platform/config/env" "gopkg.in/ns1/ns1-go.v2/rest" "gopkg.in/ns1/ns1-go.v2/rest/model/dns" @@ -90,10 +91,36 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { return fmt.Errorf("ns1: %v", err) } - record := d.newTxtRecord(zone, fqdn, value, d.config.TTL) - _, err = d.client.Records.Create(record) - if err != nil && err != rest.ErrRecordExists { - return fmt.Errorf("ns1: failed to create record [zone: %q, fqdn: %q]: %v", zone.Zone, fqdn, err) + record, _, err := d.client.Records.Get(zone.Zone, acme.UnFqdn(fqdn), "TXT") + + // Create a new record + if err == rest.ErrRecordMissing || record == nil { + log.Infof("Create a new record for [zone: %s, fqdn: %s, domain: %s]", zone.Zone, fqdn) + + record = dns.NewRecord(zone.Zone, acme.UnFqdn(fqdn), "TXT") + record.TTL = d.config.TTL + record.Answers = []*dns.Answer{{Rdata: []string{value}}} + + _, err = d.client.Records.Create(record) + if err != nil { + return fmt.Errorf("ns1: failed to create record [zone: %q, fqdn: %q]: %v", zone.Zone, fqdn, err) + } + + return nil + } + + if err != nil { + return fmt.Errorf("ns1: failed to get the existing record: %v", err) + } + + // Update the existing records + record.Answers = append(record.Answers, &dns.Answer{Rdata: []string{value}}) + + log.Infof("Update an existing record for [zone: %s, fqdn: %s, domain: %s]", zone.Zone, fqdn, domain) + + _, err = d.client.Records.Update(record) + if err != nil { + return fmt.Errorf("ns1: failed to update record [zone: %q, fqdn: %q]: %v", zone.Zone, fqdn, err) } return nil @@ -110,7 +137,10 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { name := acme.UnFqdn(fqdn) _, err = d.client.Records.Delete(zone.Zone, name, "TXT") - return fmt.Errorf("ns1: failed to delete record [zone: %q, domain: %q]: %v", zone.Zone, name, err) + if err != nil { + return fmt.Errorf("ns1: failed to delete record [zone: %q, domain: %q]: %v", zone.Zone, name, err) + } + return nil } // Timeout returns the timeout and interval to use when checking for DNS propagation. @@ -141,17 +171,3 @@ func getAuthZone(fqdn string) (string, error) { return strings.TrimSuffix(authZone, "."), nil } - -func (d *DNSProvider) newTxtRecord(zone *dns.Zone, fqdn, value string, ttl int) *dns.Record { - name := acme.UnFqdn(fqdn) - - return &dns.Record{ - Type: "TXT", - Zone: zone.Zone, - Domain: name, - TTL: ttl, - Answers: []*dns.Answer{ - {Rdata: []string{value}}, - }, - } -}