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
56 changes: 43 additions & 13 deletions providers/rwth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,50 @@ type RecordReply struct {
Editable bool `json:"editable"`
}

type dnssecKey struct {
CreatedAt time.Time `json:"created_at"`
}

// dnssecStatus supports both API variants:
// - dnssec: false
// - dnssec: { ...keys... }.
type dnssecStatus struct {
Enabled bool `json:"-"`
ZoneSigningKey *dnssecKey `json:"zone_signing_key,omitempty"`
KeySigningKey *dnssecKey `json:"key_signing_key,omitempty"`
}

func (d *dnssecStatus) UnmarshalJSON(data []byte) error {
// RWTH may return either a boolean or an object for the same field.
var enabled bool
if err := json.Unmarshal(data, &enabled); err == nil {
*d = dnssecStatus{Enabled: enabled}
return nil
}

var payload struct {
ZoneSigningKey *dnssecKey `json:"zone_signing_key"`
KeySigningKey *dnssecKey `json:"key_signing_key"`
}
if err := json.Unmarshal(data, &payload); err != nil {
return fmt.Errorf("invalid dnssec value: %w", err)
}

*d = dnssecStatus{
Enabled: true,
ZoneSigningKey: payload.ZoneSigningKey,
KeySigningKey: payload.KeySigningKey,
}
return nil
}

type zone struct {
ID int `json:"id"`
ZoneName string `json:"zone_name"`
Status string `json:"status"`
UpdatedAt time.Time `json:"updated_at"`
LastDeploy time.Time `json:"last_deploy"`
Dnssec struct {
ZoneSigningKey struct {
CreatedAt time.Time `json:"created_at"`
} `json:"zone_signing_key"`
KeySigningKey struct {
CreatedAt time.Time `json:"created_at"`
} `json:"key_signing_key"`
} `json:"dnssec"`
ID int `json:"id"`
ZoneName string `json:"zone_name"`
Status string `json:"status"`
UpdatedAt time.Time `json:"updated_at"`
LastDeploy time.Time `json:"last_deploy"`
Dnssec dnssecStatus `json:"dnssec"`
}

func checkIsLockedSystemAPIRecord(record RecordReply) error {
Expand Down
56 changes: 30 additions & 26 deletions providers/rwth/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package rwth

import (
"github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/diff"
"github.com/StackExchange/dnscontrol/v4/pkg/diff2"
)

// RWTHDefaultNs is the default DNS NS for this provider.
Expand Down Expand Up @@ -32,38 +32,42 @@ func (api *rwthProvider) GetNameservers(domain string) ([]*models.Nameserver, er
func (api *rwthProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, int, error) {
domain := dc.Name

toReport, create, del, modify, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(existingRecords)
instructions, actualChangeCount, err := diff2.ByRecord(existingRecords, dc, nil)
if err != nil {
return nil, 0, err
}
// Start corrections with the reports
corrections := diff.GenerateMessageCorrections(toReport)
var corrections []*models.Correction

for _, d := range create {
des := d.Desired
corrections = append(corrections, &models.Correction{
Msg: d.String(),
F: func() error { return api.createRecord(des) },
})
}
for _, d := range del {
existingRecord := d.Existing.Original.(RecordReply)
corrections = append(corrections, &models.Correction{
Msg: d.String(),
F: func() error { return api.destroyRecord(existingRecord) },
})
}
for _, d := range modify {
rec := d.Desired
existingID := d.Existing.Original.(RecordReply).ID
corrections = append(corrections, &models.Correction{
Msg: d.String(),
F: func() error { return api.updateRecord(existingID, *rec) },
})
for _, inst := range instructions {
switch inst.Type {
case diff2.REPORT:
corrections = append(corrections, &models.Correction{Msg: inst.MsgsJoined})
case diff2.CREATE:
rec := inst.New[0]
corrections = append(corrections, &models.Correction{
Msg: inst.MsgsJoined,
F: func() error { return api.createRecord(rec) },
})
case diff2.DELETE:
existingRecord := inst.Old[0].Original.(RecordReply)
corrections = append(corrections, &models.Correction{
Msg: inst.MsgsJoined,
F: func() error { return api.destroyRecord(existingRecord) },
})
case diff2.CHANGE:
rec := inst.New[0]
existingID := inst.Old[0].Original.(RecordReply).ID
corrections = append(corrections, &models.Correction{
Msg: inst.MsgsJoined,
F: func() error { return api.updateRecord(existingID, *rec) },
})
default:
panic("unhandled instruction type")
}
}

// And deploy if any corrections were applied
if len(corrections) > 0 {
if actualChangeCount > 0 {
corrections = append(corrections, &models.Correction{
Msg: "Deploy zone " + domain,
F: func() error { return api.deployZone(domain) },
Expand Down
1 change: 0 additions & 1 deletion providers/rwth/rwthProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ var features = providers.DocumentationNotes{
providers.CanAutoDNSSEC: providers.Unimplemented("Supported by RWTH but not implemented yet."),
providers.CanConcur: providers.Unimplemented(),
providers.CanGetZones: providers.Can(),
providers.CanOnlyDiff1Features: providers.Can(),
providers.CanUseAlias: providers.Cannot(),
providers.CanUseCAA: providers.Can(),
providers.CanUseDS: providers.Unimplemented("DS records are only supported at the apex and require a different API call that hasn't been implemented yet."),
Expand Down