Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
github.com/stackitcloud/stackit-sdk-go/core v0.24.0
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.6
github.com/stackitcloud/stackit-sdk-go/services/dns v0.19.2
github.com/stretchr/testify v1.11.1
go.uber.org/mock v0.6.0
go.uber.org/zap v1.27.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stackitcloud/stackit-sdk-go/core v0.24.0 h1:kHCcezCJ5OGSP7RRuGOxD5rF2wejpkEiRr/OdvNcuPQ=
github.com/stackitcloud/stackit-sdk-go/core v0.24.0/go.mod h1:osMglDby4csGZ5sIfhNyYq1bS1TxIdPY88+skE/kkmI=
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.6 h1:GBRb49x5Nax/oQQaaf2F3kKwv8DQQOL0TQOC0C/v/Ew=
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.6/go.mod h1:IX9iL3MigDZUmzwswTJMfYvyi118KAHrFMfjJUy5NYk=
github.com/stackitcloud/stackit-sdk-go/services/dns v0.19.2 h1:PE7TXoR2ZjVym5E4apZFJxEkApAid1/Z4x1Mz2QIcD0=
github.com/stackitcloud/stackit-sdk-go/services/dns v0.19.2/go.mod h1:3NZpITg0qJ+f1y0RUTcXKc4e122tFhHDIVm2mY0wWsw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down
14 changes: 7 additions & 7 deletions internal/stackitprovider/apply_changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"sync"

stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns"
stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns/v1api"
"go.uber.org/zap"
"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/plan"
Expand Down Expand Up @@ -124,7 +124,7 @@ func (d *StackitDNSProvider) createRRSet(
return fmt.Errorf("no matching zone found for %s", change.DNSName)
}

logFields := getLogFields(change, CREATE, *resultZone.Id)
logFields := getLogFields(change, CREATE, resultZone.Id)
d.logger.Info("create record set", logFields...)

if d.dryRun {
Expand All @@ -138,7 +138,7 @@ func (d *StackitDNSProvider) createRRSet(
rrSetPayload := getStackitRecordSetPayload(change)

// ignore all errors to just retry on next run
_, err := d.apiClient.CreateRecordSet(ctx, d.projectId, *resultZone.Id).CreateRecordSetPayload(rrSetPayload).Execute()
_, err := d.apiClient.DefaultAPI.CreateRecordSet(ctx, d.projectId, resultZone.Id).CreateRecordSetPayload(rrSetPayload).Execute()
if err != nil {
d.logger.Error("error creating record set", zap.Error(err))

Expand All @@ -163,7 +163,7 @@ func (d *StackitDNSProvider) updateRRSet(
return err
}

logFields := getLogFields(change, UPDATE, *resultRRSet.Id)
logFields := getLogFields(change, UPDATE, resultRRSet.Id)
d.logger.Info("update record set", logFields...)

if d.dryRun {
Expand All @@ -174,7 +174,7 @@ func (d *StackitDNSProvider) updateRRSet(

rrSet := getStackitPartialUpdateRecordSetPayload(change)

_, err = d.apiClient.PartialUpdateRecordSet(ctx, d.projectId, *resultZone.Id, *resultRRSet.Id).PartialUpdateRecordSetPayload(rrSet).Execute()
_, err = d.apiClient.DefaultAPI.PartialUpdateRecordSet(ctx, d.projectId, resultZone.Id, resultRRSet.Id).PartialUpdateRecordSetPayload(rrSet).Execute()
if err != nil {
d.logger.Error("error updating record set", zap.Error(err))

Expand All @@ -199,7 +199,7 @@ func (d *StackitDNSProvider) deleteRRSet(
return err
}

logFields := getLogFields(change, DELETE, *resultRRSet.Id)
logFields := getLogFields(change, DELETE, resultRRSet.Id)
d.logger.Info("delete record set", logFields...)

if d.dryRun {
Expand All @@ -208,7 +208,7 @@ func (d *StackitDNSProvider) deleteRRSet(
return nil
}

_, err = d.apiClient.DeleteRecordSet(ctx, d.projectId, *resultZone.Id, *resultRRSet.Id).Execute()
_, err = d.apiClient.DefaultAPI.DeleteRecordSet(ctx, d.projectId, resultZone.Id, resultRRSet.Id).Execute()
if err != nil {
d.logger.Error("error deleting record set", zap.Error(err))

Expand Down
57 changes: 35 additions & 22 deletions internal/stackitprovider/apply_changes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"net/http/httptest"
"testing"

stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns"
stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns/v1api"
"github.com/stretchr/testify/assert"
"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/plan"
Expand Down Expand Up @@ -114,8 +114,7 @@ func TestNoRRSetFound(t *testing.T) {
ctx := context.Background()
validZoneResponse := getValidResponseZoneAllBytes(t)
rrSets := getValidResponseRRSetAll()
rrSet := *rrSets.RrSets
*rrSet[0].Name = "notfound.test.com"
rrSets.RrSets[0].Name = "notfound.test.com"
validRRSetResponse, err := json.Marshal(rrSets)
assert.NoError(t, err)

Expand Down Expand Up @@ -375,42 +374,56 @@ func getValidResponseZoneAllBytes(t *testing.T) []byte {

func getValidZoneResponseAll() stackitdnsclient.ListZonesResponse {
return stackitdnsclient.ListZonesResponse{
ItemsPerPage: pointerTo(int64(10)),
Message: pointerTo("success"),
TotalItems: pointerTo(int64(2)),
TotalPages: pointerTo(int64(1)),
Zones: &[]stackitdnsclient.Zone{
{Id: pointerTo("1234"), DnsName: pointerTo("test.com")},
{Id: pointerTo("5678"), DnsName: pointerTo("test2.com")},
ItemsPerPage: int32(10),
Message: new("success"),
TotalItems: int32(2),
TotalPages: int32(1),
Zones: []stackitdnsclient.Zone{
{Id: "1234", DnsName: "test.com"},
{Id: "5678", DnsName: "test2.com"},
},
}
}

func getValidResponseRRSetAllBytes(t *testing.T) []byte {
t.Helper()

rrSets := getValidResponseRRSetAll()
validRRSetResponse, err := json.Marshal(rrSets)
rrSetResponse := getValidRecordSetResponse()
validRRSetResponse, err := json.Marshal(rrSetResponse)
assert.NoError(t, err)

return validRRSetResponse
}

func getValidRecordSetResponse() stackitdnsclient.RecordSetResponse {
return stackitdnsclient.RecordSetResponse{
Message: new("success"),
Rrset: stackitdnsclient.RecordSet{
Name: "test.com",
Type: "A",
Ttl: int32(300),
Records: []stackitdnsclient.Record{
{Content: "1.2.3.4"},
},
},
}
}

func getValidResponseRRSetAll() stackitdnsclient.ListRecordSetsResponse {
return stackitdnsclient.ListRecordSetsResponse{
ItemsPerPage: pointerTo(int64(20)),
Message: pointerTo("success"),
RrSets: &[]stackitdnsclient.RecordSet{
ItemsPerPage: int32(20),
Message: new("success"),
RrSets: []stackitdnsclient.RecordSet{
{
Name: pointerTo("test.com"),
Type: pointerTo(stackitdnsclient.RECORDSETTYPE_A),
Ttl: pointerTo(int64(300)),
Records: &[]stackitdnsclient.Record{
{Content: pointerTo("1.2.3.4")},
Name: "test.com",
Type: "A",
Ttl: int32(300),
Records: []stackitdnsclient.Record{
{Content: "1.2.3.4"},
},
},
},
TotalItems: pointerTo(int64(2)),
TotalPages: pointerTo(int64(1)),
TotalItems: int32(2),
TotalPages: int32(1),
}
}
44 changes: 25 additions & 19 deletions internal/stackitprovider/helper.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package stackitprovider

import (
"math"
"strings"

stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns"
stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns/v1api"
"go.uber.org/zap"
"sigs.k8s.io/external-dns/endpoint"
)
Expand All @@ -20,10 +21,7 @@ func findBestMatchingZone(

for i := range zones {
zone := &zones[i]
if zone.DnsName == nil {
continue
}
if l := len(*zone.DnsName); l > count && strings.Contains(rrSetName, *zone.DnsName) {
if l := len(zone.DnsName); l > count && strings.Contains(rrSetName, zone.DnsName) {
count = l
domainZone = zone
}
Expand All @@ -43,10 +41,7 @@ func findRRSet(
) (*stackitdnsclient.RecordSet, bool) {
for i := range rrSets {
rrSet := &rrSets[i]
if rrSet.Name == nil || rrSet.Type == nil {
continue
}
if *rrSet.Name == rrSetName && string(*rrSet.Type) == recordType {
if rrSet.Name == rrSetName && rrSet.Type == recordType {
return rrSet, true
}
}
Expand Down Expand Up @@ -77,15 +72,15 @@ func getStackitRecordSetPayload(change *endpoint.Endpoint) stackitdnsclient.Crea
records := make([]stackitdnsclient.RecordPayload, len(change.Targets))
for i := range change.Targets {
records[i] = stackitdnsclient.RecordPayload{
Content: &change.Targets[i],
Content: change.Targets[i],
}
}

return stackitdnsclient.CreateRecordSetPayload{
Name: &change.DNSName,
Records: &records,
Ttl: pointerTo(int64(change.RecordTTL)),
Type: (stackitdnsclient.CreateRecordSetPayloadGetTypeAttributeType)(&change.RecordType),
Name: change.DNSName,
Records: records,
Ttl: safeTTLToInt32(change.RecordTTL),
Type: change.RecordType,
}
}

Expand All @@ -94,14 +89,14 @@ func getStackitPartialUpdateRecordSetPayload(change *endpoint.Endpoint) stackitd
records := make([]stackitdnsclient.RecordPayload, len(change.Targets))
for i := range change.Targets {
records[i] = stackitdnsclient.RecordPayload{
Content: &change.Targets[i],
Content: change.Targets[i],
}
}

return stackitdnsclient.PartialUpdateRecordSetPayload{
Name: &change.DNSName,
Records: &records,
Ttl: pointerTo(int64(change.RecordTTL)),
Records: records,
Ttl: safeTTLToInt32(change.RecordTTL),
}
}

Expand All @@ -116,7 +111,18 @@ func getLogFields(change *endpoint.Endpoint, action string, id string) []zap.Fie
}
}

// pointerTo returns a pointer to the given value.
func pointerTo[T any](v T) *T {
// safeTTLToInt32 safely converts an endpoint.TTL (int64) to *int32, clamping to valid bounds.
func safeTTLToInt32(ttl endpoint.TTL) *int32 {
var v int32

switch {
case int64(ttl) > math.MaxInt32:
v = math.MaxInt32
case int64(ttl) < 0:
v = 0
default:
v = int32(ttl) // #nosec G115 -- bounds checked above
}

return &v
}
36 changes: 18 additions & 18 deletions internal/stackitprovider/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"reflect"
"testing"

stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns"
stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns/v1api"
"go.uber.org/zap"
"sigs.k8s.io/external-dns/endpoint"
)
Expand Down Expand Up @@ -72,15 +72,15 @@ func TestGetStackitRRSetRecordPost(t *testing.T) {
},
}
expected := stackitdnsclient.CreateRecordSetPayload{
Name: pointerTo("test."),
Ttl: pointerTo(int64(300)),
Type: (stackitdnsclient.CreateRecordSetPayloadGetTypeAttributeType)(pointerTo("A")),
Records: &[]stackitdnsclient.RecordPayload{
Name: "test.",
Ttl: new(int32(300)),
Type: "A",
Records: []stackitdnsclient.RecordPayload{
{
Content: pointerTo("192.0.2.1"),
Content: "192.0.2.1",
},
{
Content: pointerTo("192.0.2.2"),
Content: "192.0.2.2",
},
},
}
Expand All @@ -94,9 +94,9 @@ func TestFindBestMatchingZone(t *testing.T) {
t.Parallel()

zones := []stackitdnsclient.Zone{
{DnsName: pointerTo("foo.com")},
{DnsName: pointerTo("bar.com")},
{DnsName: pointerTo("baz.com")},
{DnsName: "foo.com"},
{DnsName: "bar.com"},
{DnsName: "baz.com"},
}

tests := []struct {
Expand Down Expand Up @@ -125,9 +125,9 @@ func TestFindRRSet(t *testing.T) {
t.Parallel()

rrSets := []stackitdnsclient.RecordSet{
{Name: pointerTo("www.foo.com"), Type: pointerTo(stackitdnsclient.RECORDSETTYPE_A)},
{Name: pointerTo("www.bar.com"), Type: pointerTo(stackitdnsclient.RECORDSETTYPE_A)},
{Name: pointerTo("www.baz.com"), Type: pointerTo(stackitdnsclient.RECORDSETTYPE_A)},
{Name: "www.foo.com", Type: "A"},
{Name: "www.bar.com", Type: "A"},
{Name: "www.baz.com", Type: "A"},
}

tests := []struct {
Expand Down Expand Up @@ -196,14 +196,14 @@ func TestGetStackitRRSetRecordPatch(t *testing.T) {
}

expected := stackitdnsclient.PartialUpdateRecordSetPayload{
Name: pointerTo("test."),
Ttl: pointerTo(int64(300)),
Records: &[]stackitdnsclient.RecordPayload{
Name: new("test."),
Ttl: new(int32(300)),
Records: []stackitdnsclient.RecordPayload{
{
Content: pointerTo("192.0.2.1"),
Content: "192.0.2.1",
},
{
Content: pointerTo("192.0.2.2"),
Content: "192.0.2.2",
},
},
}
Expand Down
16 changes: 5 additions & 11 deletions internal/stackitprovider/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package stackitprovider
import (
"context"

stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns"
stackitdnsclient "github.com/stackitcloud/stackit-sdk-go/services/dns/v1api"
"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/provider"
)
Expand All @@ -25,10 +25,7 @@ func (d *StackitDNSProvider) Records(ctx context.Context) ([]*endpoint.Endpoint,

for i := range zones {
zone := &zones[i]
if zone.Id == nil {
continue
}
zoneIdsChannel <- *zone.Id
zoneIdsChannel <- zone.Id
}

for i := 0; i < len(zones); i++ {
Expand Down Expand Up @@ -104,23 +101,20 @@ func (d *StackitDNSProvider) collectEndPoints(
}

func recordSetCoreFields(r *stackitdnsclient.RecordSet) (name string, recordType string, ttl endpoint.TTL, records []stackitdnsclient.Record, ok bool) {
if r == nil || r.Type == nil || r.Name == nil || r.Ttl == nil || r.Records == nil {
if r == nil || len(r.Records) == 0 {
return "", "", 0, nil, false
}

return *r.Name, string(*r.Type), endpoint.TTL(*r.Ttl), *r.Records, true
return r.Name, r.Type, endpoint.TTL(r.Ttl), r.Records, true
}

func endpointsFromRecords(name, recordType string, ttl endpoint.TTL, records []stackitdnsclient.Record) []*endpoint.Endpoint {
endpoints := make([]*endpoint.Endpoint, 0, len(records))

for i := range records {
rec := &records[i]
if rec.Content == nil {
continue
}

endpoints = append(endpoints, endpoint.NewEndpointWithTTL(name, recordType, ttl, *rec.Content))
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(name, recordType, ttl, rec.Content))
}

return endpoints
Expand Down
Loading
Loading