Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions _example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,39 +46,37 @@ func main() {
if txtTestId != "" && aTestId != "" {
if deleteEntries {
fmt.Printf("Delete entry for %s (id:%s)\n", txtTestName, txtTestId)
_, err = provider.DeleteRecords(context.TODO(), zone, []libdns.Record{digitalocean.DNS{ID: txtTestId}})
_, err = provider.DeleteRecords(context.TODO(), zone, []libdns.Record{libdns.RR{Name: txtTestName, Type: "TXT"}})
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
}
fmt.Printf("Delete entry for %s (id:%s)\n", aTestName, aTestId)
_, err = provider.DeleteRecords(context.TODO(), zone, []libdns.Record{digitalocean.DNS{ID: aTestId}})
_, err = provider.DeleteRecords(context.TODO(), zone, []libdns.Record{libdns.RR{Name: aTestName, Type: "A"}})
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
}
} else {
fmt.Printf("Replacing entry for %s\n", txtTestName)
_, err = provider.SetRecords(context.TODO(), zone, []libdns.Record{digitalocean.DNS{
Record: libdns.RR{
_, err = provider.SetRecords(context.TODO(), zone, []libdns.Record{
libdns.RR{
Type: "TXT",
Name: txtTestName,
Data: fmt.Sprintf("Replacement test entry created by libdns %s", time.Now()),
TTL: time.Duration(30) * time.Second,
},
ID: txtTestId,
}})
})
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
}
fmt.Printf("Replacing entry for %s\n", aTestName)
_, err = provider.SetRecords(context.TODO(), zone, []libdns.Record{digitalocean.DNS{
Record: libdns.RR{
_, err = provider.SetRecords(context.TODO(), zone, []libdns.Record{
libdns.RR{
Type: "A",
Name: aTestName,
Data: "127.0.0.1",
TTL: time.Duration(30) * time.Second,
},
ID: aTestId,
}})
})
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
}
Expand Down
52 changes: 36 additions & 16 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package digitalocean

import (
"context"
"fmt"
"log"
"strconv"
"strings"
"sync"

"github.com/digitalocean/godo"
Expand Down Expand Up @@ -74,44 +77,61 @@ func (p *Provider) addDNSEntry(ctx context.Context, zone string, record libdns.R
return fromRecord(record, strconv.Itoa(rec.ID)), nil
}

func (p *Provider) removeDNSEntry(ctx context.Context, zone string, record libdns.Record) (libdns.Record, error) {
func (p *Provider) removeDNSEntry(ctx context.Context, zone string, id int, record libdns.Record) (libdns.Record, error) {
p.mutex.Lock()
defer p.mutex.Unlock()

p.getClient()

// Get ID from dns record
id, err := idFromRecord(record)
if err != nil {
return record, err
}

_, err = p.client.Domains.DeleteRecord(ctx, zone, id)
_, err := p.client.Domains.DeleteRecord(ctx, zone, id)
if err != nil {
return record, err
}

return record, nil
return fromRecord(record, strconv.Itoa(id)), nil
}

func (p *Provider) updateDNSEntry(ctx context.Context, zone string, record libdns.Record) (libdns.Record, error) {
func (p *Provider) updateDNSEntry(ctx context.Context, zone string, id int, record libdns.Record) (libdns.Record, error) {
p.mutex.Lock()
defer p.mutex.Unlock()

p.getClient()

// Get ID from dns record
id, err := idFromRecord(record)
entry := recordToGoDo(record)

_, _, err := p.client.Domains.EditRecord(ctx, zone, id, &entry)
if err != nil {
return record, err
}

entry := recordToGoDo(record)
return fromRecord(record, strconv.Itoa(id)), nil
}

_, _, err = p.client.Domains.EditRecord(ctx, zone, id, &entry)
func (p *Provider) idFromRecord(ctx context.Context, zone string, record libdns.Record) (int, error) {
// Try to get id from underlying DNS struct
id, err := idFromRecord(record)
if err == nil {
return id, err
}

// Failed to get ID from record, query the zone instead
p.mutex.Lock()
defer p.mutex.Unlock()

p.getClient()

// RecordsByTypeAndName requires the name to be a fqdn https://docs.digitalocean.com/reference/api/digitalocean/#tag/Domain-Records/operation/domains_list_records
fqdn := strings.Join([]string{record.RR().Name, zone}, ".")
records, _, err := p.client.Domains.RecordsByTypeAndName(ctx, zone, record.RR().Type, fqdn, &godo.ListOptions{})
if err != nil {
return record, err
return id, err
}
if len(records) == 0 {
return id, fmt.Errorf("record not found: %s %s %s", zone, record.RR().Type, record.RR().Name)
}
if len(records) > 1 {
log.Printf("libdns/digitalocean: warning: found multiple records with the same name and type, only the first record will be used")
}

return record, nil
return records[0].ID, nil
}
32 changes: 24 additions & 8 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ func TestClient_removeDNSEntry(t *testing.T) {
p := setupTest(nil, nil)
ctx := context.Background()

resultRecord, err := p.removeDNSEntry(ctx, "example.com", testRecord)
id, err := p.idFromRecord(ctx, "example.com", testRecord)
if err != nil {
t.Errorf("Client.idFromRecord() error = %v", err)
}
resultRecord, err := p.removeDNSEntry(ctx, "example.com", id, testRecord)

if err != nil {
t.Errorf("Client.removeDNSEntry() error = %v", err)
Expand All @@ -130,7 +134,11 @@ func TestClient_removeDNSEntry(t *testing.T) {
// Test error case - API error
p = setupTest(nil, errors.New("API error"))

_, err = p.removeDNSEntry(ctx, "example.com", testRecord)
id, err = p.idFromRecord(ctx, "example.com", testRecord)
if err != nil {
t.Errorf("Client.idFromRecord() error = %v", err)
}
_, err = p.removeDNSEntry(ctx, "example.com", id, testRecord)
if err == nil {
t.Error("Client.removeDNSEntry() expected error, got nil")
}
Expand All @@ -146,9 +154,9 @@ func TestClient_removeDNSEntry(t *testing.T) {
},
}

_, err = p.removeDNSEntry(ctx, "example.com", invalidIDRecord)
_, err = p.idFromRecord(ctx, "example.com", invalidIDRecord)
if err == nil {
t.Error("Client.removeDNSEntry() expected error for invalid ID, got nil")
t.Error("Client.idFromRecord() expected error, got nil")
}
}

Expand All @@ -168,7 +176,11 @@ func TestClient_updateDNSEntry(t *testing.T) {
p := setupTest(nil, nil)
ctx := context.Background()

resultRecord, err := p.updateDNSEntry(ctx, "example.com", testRecord)
id, err := p.idFromRecord(ctx, "example.com", testRecord)
if err != nil {
t.Errorf("Client.idFromRecord() error = %v", err)
}
resultRecord, err := p.updateDNSEntry(ctx, "example.com", id, testRecord)

if err != nil {
t.Errorf("Client.updateDNSEntry() error = %v", err)
Expand All @@ -185,7 +197,11 @@ func TestClient_updateDNSEntry(t *testing.T) {
// Test error case - API error
p = setupTest(nil, errors.New("API error"))

_, err = p.updateDNSEntry(ctx, "example.com", testRecord)
id, err = p.idFromRecord(ctx, "example.com", testRecord)
if err != nil {
t.Errorf("Client.idFromRecord() error = %v", err)
}
_, err = p.updateDNSEntry(ctx, "example.com", id, testRecord)
if err == nil {
t.Error("Client.updateDNSEntry() expected error, got nil")
}
Expand All @@ -201,8 +217,8 @@ func TestClient_updateDNSEntry(t *testing.T) {
},
}

_, err = p.updateDNSEntry(ctx, "example.com", invalidIDRecord)
_, err = p.idFromRecord(ctx, "example.com", invalidIDRecord)
if err == nil {
t.Error("Client.updateDNSEntry() expected error for invalid ID, got nil")
t.Error("Client.idFromRecord() expected error, got nil")
}
}
14 changes: 10 additions & 4 deletions provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []lib
var deletedRecords []libdns.Record

for _, record := range records {
deletedRecord, err := p.removeDNSEntry(ctx, p.unFQDN(zone), record)
id, err := p.idFromRecord(ctx, p.unFQDN(zone), record)
if err != nil {
return nil, err
}
deletedRecord, err := p.removeDNSEntry(ctx, p.unFQDN(zone), id, record)
if err != nil {
return nil, err
}
Expand All @@ -65,9 +69,11 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns
var setRecords []libdns.Record

for _, record := range records {
// TODO: if there is no ID, look up the Name, and fill it in, or call
// newRecord, err := p.addDNSEntry(ctx, zone, record)
setRecord, err := p.updateDNSEntry(ctx, p.unFQDN(zone), record)
id, err := p.idFromRecord(ctx, p.unFQDN(zone), record)
if err != nil {
return setRecords, err
}
setRecord, err := p.updateDNSEntry(ctx, p.unFQDN(zone), id, record)
if err != nil {
return setRecords, err
}
Expand Down
Loading