Skip to content
Closed
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
126 changes: 91 additions & 35 deletions provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package inwx

import (
"context"
"errors"
"fmt"
"strings"
"sync"
Expand Down Expand Up @@ -44,18 +45,20 @@ func (p *Provider) GetRecords(ctx context.Context, zone string) ([]libdns.Record
}

results := make([]libdns.Record, 0, len(inwxRecords))
var errs []error

for _, inwxRecord := range inwxRecords {
result, err := libdnsRecord(inwxRecord, zone)

if err != nil {
return nil, fmt.Errorf("parsing INWX DNS record %+v: %v", inwxRecord, err)
errs = append(errs, fmt.Errorf("parsing INWX DNS record %+v: %v", inwxRecord, err))
continue
}

results = append(results, result)
}

return results, nil
return results, errors.Join(errs...)
}

// AppendRecords adds records to the zone. It returns the records that were added.
Expand All @@ -68,18 +71,27 @@ func (p *Provider) AppendRecords(ctx context.Context, zone string, records []lib
}

var results []libdns.Record
var errs []error

for _, record := range records {
var _, err = client.createRecord(ctx, inwxRecord(record), getDomain(zone))
inwxRecord, err := inwxRecord(record)

if err != nil {
return nil, err
errs = append(errs, err)
continue
}

_, err = client.createRecord(ctx, *inwxRecord, getDomain(zone))

if err != nil {
errs = append(errs, err)
continue
}

results = append(results, record)
}

return results, nil
return results, errors.Join(errs...)
}

// SetRecords sets the records in the zone, either by updating existing records or creating new ones.
Expand All @@ -92,45 +104,74 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns
return nil, err
}

var results []libdns.Record

groupedRecords := map[string](map[string][]libdns.Record){}
for _, record := range records {
matches, err := p.client.findRecords(ctx, inwxRecord(record), getDomain(zone), false)

if err != nil {
return nil, err
rr := record.RR()
if _, ok := groupedRecords[rr.Type]; !ok {
groupedRecords[rr.Type] = map[string][]libdns.Record{}
}
groupedRecords[rr.Type][rr.Name] = append(groupedRecords[rr.Type][rr.Name], record)
}

if len(matches) == 0 {
_, err := client.createRecord(ctx, inwxRecord(record), getDomain(zone))
var results []libdns.Record
var errs []error

for recordType, typeGroup := range groupedRecords {
for recordName, nameGroup := range typeGroup {
matches, err := p.client.findRecords(ctx, nameserverRecord{Type: recordType, Name: recordName}, getDomain(zone), false)
if err != nil {
return nil, err
errs = append(errs, err)
continue
}
for i, record := range nameGroup {

results = append(results, record)
inwxRecord, err := inwxRecord(record)

continue
}
if err != nil {
errs = append(errs, err)
continue
}

if len(matches) > 1 {
return nil, fmt.Errorf("unexpectedly found more than 1 record for %v", record)
}
if i > len(matches)-1 {

inwxRecord := inwxRecord(record)
inwxRecord.ID = matches[0].ID
_, err := client.createRecord(ctx, *inwxRecord, getDomain(zone))

err = client.updateRecord(ctx, inwxRecord)
if err != nil {
errs = append(errs, err)
continue
}

if err != nil {
return nil, err
}
} else {

results = append(results, record)
inwxRecord.ID = matches[i].ID

err = client.updateRecord(ctx, *inwxRecord)

if err != nil {
errs = append(errs, err)
continue
}

}

results = append(results, record)
}

if len(matches) > len(nameGroup) {
for _, record := range matches[len(nameGroup):] {
err := client.deleteRecord(ctx, record)

if err != nil {
errs = append(errs, err)
continue
}
}

}
}
}

return results, nil
return results, errors.Join(errs...)
}

// DeleteRecords deletes the records from the zone. It returns the records that were deleted.
Expand All @@ -143,26 +184,36 @@ func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []lib
}

var results []libdns.Record
var errs []error

for _, record := range records {
exactMatches, err := p.client.findRecords(ctx, inwxRecord(record), getDomain(zone), true)
inwxRecord, err := inwxRecord(record)

if err != nil {
return nil, err
errs = append(errs, err)
continue
}

exactMatches, err := p.client.findRecords(ctx, *inwxRecord, getDomain(zone), true)

if err != nil {
results = append(results, record)
continue
}

for _, inwxRecord := range exactMatches {
err := client.deleteRecord(ctx, inwxRecord)

if err != nil {
return nil, err
errs = append(errs, err)
continue
}

results = append(results, record)
}
}

return results, nil
return results, errors.Join(errs...)
}

func (p *Provider) getClient(ctx context.Context) (*client, error) {
Expand Down Expand Up @@ -229,7 +280,7 @@ func libdnsRecord(record nameserverRecord, zone string) (libdns.Record, error) {
}.Parse()
}

func inwxRecord(record libdns.Record) nameserverRecord {
func inwxRecord(record libdns.Record) (*nameserverRecord, error) {
rr := record.RR()

inwxRecord := nameserverRecord{
Expand All @@ -239,7 +290,12 @@ func inwxRecord(record libdns.Record) nameserverRecord {
TTL: int(rr.TTL.Seconds()),
}

switch rec := record.(type) {
parsed, err := rr.Parse()
if err != nil {
return nil, fmt.Errorf("failed to parse record %s %s: %w", rr.Name, rr.Type, err)
}

switch rec := parsed.(type) {
case libdns.MX:
inwxRecord.Content = rec.Target
inwxRecord.Priority = uint(rec.Preference)
Expand All @@ -248,7 +304,7 @@ func inwxRecord(record libdns.Record) nameserverRecord {
inwxRecord.Priority = uint(rec.Priority)
}

return inwxRecord
return &inwxRecord, nil
}

// Interface guards
Expand Down
Loading