From d021144db5f53637ab2d7c9b19f4618abfbde9ad Mon Sep 17 00:00:00 2001 From: Anders Ingemann Date: Thu, 5 Mar 2026 12:55:09 +0100 Subject: [PATCH 1/3] Handle updating records with multiple values --- provider.go | 61 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/provider.go b/provider.go index 86bdb0d..2853e02 100644 --- a/provider.go +++ b/provider.go @@ -92,42 +92,59 @@ 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 + 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 } + for i, record := range nameGroup { - results = append(results, record) + if i > len(matches)-1 { - continue - } + _, err := client.createRecord(ctx, inwxRecord(record), getDomain(zone)) - if len(matches) > 1 { - return nil, fmt.Errorf("unexpectedly found more than 1 record for %v", record) - } + if err != nil { + return nil, err + } - inwxRecord := inwxRecord(record) - inwxRecord.ID = matches[0].ID + } else { - err = client.updateRecord(ctx, inwxRecord) + inwxRecord := inwxRecord(record) + inwxRecord.ID = matches[i].ID - if err != nil { - return nil, err - } + err = client.updateRecord(ctx, inwxRecord) - results = append(results, record) + if err != nil { + return nil, err + } + + } + results = append(results, record) + } + + if len(matches) > len(nameGroup) { + for _, record := range matches[len(nameGroup):] { + err := client.deleteRecord(ctx, record) + + if err != nil { + return nil, err + } + } + + } + } } return results, nil From b7cb2603148bc45eafd9d288642bbfc22e84d8c4 Mon Sep 17 00:00:00 2001 From: Anders Ingemann Date: Tue, 10 Mar 2026 14:15:39 +0100 Subject: [PATCH 2/3] Improve error resilience by collecting errors and returning them all --- provider.go | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/provider.go b/provider.go index 2853e02..8952bb4 100644 --- a/provider.go +++ b/provider.go @@ -2,6 +2,7 @@ package inwx import ( "context" + "errors" "fmt" "strings" "sync" @@ -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. @@ -68,18 +71,20 @@ 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)) if err != nil { - return nil, err + 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. @@ -102,11 +107,14 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns } 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 { @@ -115,7 +123,8 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns _, err := client.createRecord(ctx, inwxRecord(record), getDomain(zone)) if err != nil { - return nil, err + errs = append(errs, err) + continue } } else { @@ -126,7 +135,8 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns err = client.updateRecord(ctx, inwxRecord) if err != nil { - return nil, err + errs = append(errs, err) + continue } } @@ -139,7 +149,8 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns err := client.deleteRecord(ctx, record) if err != nil { - return nil, err + errs = append(errs, err) + continue } } @@ -147,7 +158,7 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns } } - return results, nil + return results, errors.Join(errs...) } // DeleteRecords deletes the records from the zone. It returns the records that were deleted. @@ -160,26 +171,29 @@ 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) if err != nil { - return nil, err + 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) { From 41b9bdacb72b8de1bf0c8b7b05f7fa9eb14f6352 Mon Sep 17 00:00:00 2001 From: Anders Ingemann Date: Tue, 10 Mar 2026 14:11:41 +0100 Subject: [PATCH 3/3] Parse records before checking if they are MX or SRV records --- provider.go | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/provider.go b/provider.go index 8952bb4..7655f21 100644 --- a/provider.go +++ b/provider.go @@ -74,7 +74,14 @@ func (p *Provider) AppendRecords(ctx context.Context, zone string, records []lib var errs []error for _, record := range records { - var _, err = client.createRecord(ctx, inwxRecord(record), getDomain(zone)) + inwxRecord, err := inwxRecord(record) + + if err != nil { + errs = append(errs, err) + continue + } + + _, err = client.createRecord(ctx, *inwxRecord, getDomain(zone)) if err != nil { errs = append(errs, err) @@ -118,9 +125,16 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns } for i, record := range nameGroup { + inwxRecord, err := inwxRecord(record) + + if err != nil { + errs = append(errs, err) + continue + } + if i > len(matches)-1 { - _, err := client.createRecord(ctx, inwxRecord(record), getDomain(zone)) + _, err := client.createRecord(ctx, *inwxRecord, getDomain(zone)) if err != nil { errs = append(errs, err) @@ -129,10 +143,9 @@ func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns } else { - inwxRecord := inwxRecord(record) inwxRecord.ID = matches[i].ID - err = client.updateRecord(ctx, inwxRecord) + err = client.updateRecord(ctx, *inwxRecord) if err != nil { errs = append(errs, err) @@ -174,7 +187,14 @@ func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []lib 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 { + errs = append(errs, err) + continue + } + + exactMatches, err := p.client.findRecords(ctx, *inwxRecord, getDomain(zone), true) if err != nil { results = append(results, record) @@ -260,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{ @@ -270,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) @@ -279,7 +304,7 @@ func inwxRecord(record libdns.Record) nameserverRecord { inwxRecord.Priority = uint(rec.Priority) } - return inwxRecord + return &inwxRecord, nil } // Interface guards