mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2026-05-05 14:46:10 +02:00
FEAT: Use the new Delete GoDaddy API
This commit is contained in:
parent
d944cd530e
commit
ca9deae788
@ -32,11 +32,17 @@ import (
|
||||
|
||||
const (
|
||||
gdMinimalTTL = 600
|
||||
gdCreate = iota
|
||||
gdUpdate
|
||||
gdDelete
|
||||
gdCreate = 0
|
||||
gdUpdate = 1
|
||||
gdDelete = 2
|
||||
)
|
||||
|
||||
var actionNames = []string{
|
||||
"create",
|
||||
"update",
|
||||
"delete",
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrRecordToMutateNotFound when ApplyChange has to update/delete and didn't found the record in the existing zone (Change with no record ID)
|
||||
ErrRecordToMutateNotFound = errors.New("record to mutate not found in current zone")
|
||||
@ -77,6 +83,17 @@ type gdRecordField struct {
|
||||
Service *string `json:"service,omitempty"`
|
||||
}
|
||||
|
||||
type gdUpdateRecordField struct {
|
||||
Data string `json:"data"`
|
||||
Name string `json:"name"`
|
||||
TTL int64 `json:"ttl"`
|
||||
Port *int `json:"port,omitempty"`
|
||||
Priority *int `json:"priority,omitempty"`
|
||||
Weight *int64 `json:"weight,omitempty"`
|
||||
Protocol *string `json:"protocol,omitempty"`
|
||||
Service *string `json:"service,omitempty"`
|
||||
}
|
||||
|
||||
type gdRecords struct {
|
||||
records []gdRecordField
|
||||
changed bool
|
||||
@ -310,14 +327,6 @@ func (p *GDProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error)
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
func (p *GDProvider) flushRecords(patch bool, zoneRecord *gdRecords) error {
|
||||
if patch {
|
||||
return p.client.Patch(fmt.Sprintf("/v1/domains/%s/records", zoneRecord.zone), zoneRecord.records, nil)
|
||||
}
|
||||
|
||||
return p.client.Put(fmt.Sprintf("/v1/domains/%s/records", zoneRecord.zone), zoneRecord.records, nil)
|
||||
}
|
||||
|
||||
func (p *GDProvider) appendChange(action int, endpoints []*endpoint.Endpoint, allChanges []gdEndpoint) []gdEndpoint {
|
||||
for _, e := range endpoints {
|
||||
allChanges = append(allChanges, gdEndpoint{
|
||||
@ -329,15 +338,10 @@ func (p *GDProvider) appendChange(action int, endpoints []*endpoint.Endpoint, al
|
||||
return allChanges
|
||||
}
|
||||
|
||||
func (p *GDProvider) changeAllRecords(patch bool, endpoints []gdEndpoint, zoneRecords []*gdRecords) error {
|
||||
func (p *GDProvider) changeAllRecords(endpoints []gdEndpoint, zoneRecords []*gdRecords) error {
|
||||
zoneNameIDMapper := gdZoneIDName{}
|
||||
|
||||
for _, zoneRecord := range zoneRecords {
|
||||
if patch {
|
||||
zoneRecord.changed = false
|
||||
zoneRecord.records = nil
|
||||
}
|
||||
|
||||
zoneNameIDMapper.add(zoneRecord.zone, zoneRecord)
|
||||
}
|
||||
|
||||
@ -366,7 +370,15 @@ func (p *GDProvider) changeAllRecords(patch bool, endpoints []gdEndpoint, zoneRe
|
||||
change.TTL = maxOf(gdMinimalTTL, int64(e.endpoint.RecordTTL))
|
||||
}
|
||||
|
||||
zoneRecord.applyChange(e.action, change)
|
||||
if p.DryRun {
|
||||
log.Infof("DryRun: Apply change %s on record %s", actionNames[e.action], change)
|
||||
} else {
|
||||
if err := zoneRecord.applyChange(e.action, p.client, change); err != nil {
|
||||
log.Errorf("Unable to apply change %s on record %s, %v", actionNames[e.action], change, err)
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,15 +413,54 @@ func (p *GDProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) er
|
||||
|
||||
log.Infof("GoDaddy: %d changes will be done", len(allChanges))
|
||||
|
||||
patch := len(changes.UpdateOld)+len(changes.Delete) == 0
|
||||
|
||||
if err = p.changeAllRecords(patch, allChanges, changedZoneRecords); err != nil {
|
||||
if err = p.changeAllRecords(allChanges, changedZoneRecords); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, record := range changedZoneRecords {
|
||||
if record.changed {
|
||||
if err = p.flushRecords(patch, record); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *gdRecords) addRecord(client gdClient, change gdRecordField) error {
|
||||
var response GDErrorResponse
|
||||
|
||||
log.Debugf("GoDaddy: Add an entry %s to zone %s", change.String(), p.zone)
|
||||
|
||||
p.records = append(p.records, change)
|
||||
p.changed = true
|
||||
|
||||
if err := client.Patch(fmt.Sprintf("/v1/domains/%s/records", p.zone), []gdRecordField{change}, &response); err != nil {
|
||||
log.Errorf("Add record %s.%s of type %s failed: %v", change.Name, p.zone, change.Type, response)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *gdRecords) updateRecord(client gdClient, change gdRecordField) error {
|
||||
log.Debugf("GoDaddy: Update an entry %s to zone %s", change.String(), p.zone)
|
||||
|
||||
for index, record := range p.records {
|
||||
if record.Type == change.Type && record.Name == change.Name {
|
||||
var response GDErrorResponse
|
||||
|
||||
p.records[index] = change
|
||||
p.changed = true
|
||||
|
||||
changed := []gdUpdateRecordField{{
|
||||
Data: change.Data,
|
||||
Name: change.Name,
|
||||
TTL: change.TTL,
|
||||
Port: change.Port,
|
||||
Priority: change.Priority,
|
||||
Weight: change.Weight,
|
||||
Protocol: change.Protocol,
|
||||
Service: change.Service,
|
||||
}}
|
||||
|
||||
if err := client.Patch(fmt.Sprintf("/v1/domains/%s/records/%s", p.zone, change.Type), changed, &response); err != nil {
|
||||
log.Errorf("Update record %s.%s of type %s failed: %v", change.Name, p.zone, change.Type, response)
|
||||
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -418,27 +469,8 @@ func (p *GDProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *gdRecords) addRecord(change gdRecordField) {
|
||||
log.Debugf("GoDaddy: Add an entry %s to zone %s", change.String(), p.zone)
|
||||
|
||||
p.records = append(p.records, change)
|
||||
p.changed = true
|
||||
}
|
||||
|
||||
func (p *gdRecords) updateRecord(change gdRecordField) {
|
||||
log.Debugf("GoDaddy: Update an entry %s to zone %s", change.String(), p.zone)
|
||||
|
||||
for index, record := range p.records {
|
||||
if record.Type == change.Type && record.Name == change.Name {
|
||||
p.records[index] = change
|
||||
p.changed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove one record from the record list
|
||||
func (p *gdRecords) deleteRecord(change gdRecordField) {
|
||||
func (p *gdRecords) deleteRecord(client gdClient, change gdRecordField) error {
|
||||
log.Debugf("GoDaddy: Delete an entry %s to zone %s", change.String(), p.zone)
|
||||
|
||||
deleteIndex := -1
|
||||
@ -451,24 +483,36 @@ func (p *gdRecords) deleteRecord(change gdRecordField) {
|
||||
}
|
||||
|
||||
if deleteIndex >= 0 {
|
||||
var response GDErrorResponse
|
||||
|
||||
p.records[deleteIndex] = p.records[len(p.records)-1]
|
||||
|
||||
p.records = p.records[:len(p.records)-1]
|
||||
p.changed = true
|
||||
|
||||
if err := client.Delete(fmt.Sprintf("/v1/domains/%s/records/%s/%s", p.zone, change.Type, change.Name), &response); err != nil {
|
||||
log.Errorf("Delete record %s.%s of type %s failed: %v", change.Name, p.zone, change.Type, response)
|
||||
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Warnf("GoDaddy: record in zone %s not found %s to delete", p.zone, change.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *gdRecords) applyChange(action int, change gdRecordField) {
|
||||
func (p *gdRecords) applyChange(action int, client gdClient, change gdRecordField) error {
|
||||
switch action {
|
||||
case gdCreate:
|
||||
p.addRecord(change)
|
||||
return p.addRecord(client, change)
|
||||
case gdUpdate:
|
||||
p.updateRecord(change)
|
||||
return p.updateRecord(client, change)
|
||||
case gdDelete:
|
||||
p.deleteRecord(change)
|
||||
return p.deleteRecord(client, change)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c gdRecordField) String() string {
|
||||
|
||||
@ -19,6 +19,7 @@ package godaddy
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
@ -360,8 +361,8 @@ func TestGoDaddyChange(t *testing.T) {
|
||||
},
|
||||
}, nil).Once()
|
||||
|
||||
// Update domain
|
||||
client.On("Put", "/v1/domains/example.net/records", []gdRecordField{
|
||||
// Add entry
|
||||
client.On("Patch", "/v1/domains/example.net/records", []gdRecordField{
|
||||
{
|
||||
Name: "@",
|
||||
Type: "A",
|
||||
@ -370,7 +371,86 @@ func TestGoDaddyChange(t *testing.T) {
|
||||
},
|
||||
}).Return(nil, nil).Once()
|
||||
|
||||
// Delete entry
|
||||
client.On("Delete", "/v1/domains/example.net/records/A/godaddy").Return(nil, nil).Once()
|
||||
|
||||
assert.NoError(provider.ApplyChanges(context.TODO(), &changes))
|
||||
|
||||
client.AssertExpectations(t)
|
||||
}
|
||||
|
||||
var (
|
||||
status404 string = "404"
|
||||
notfound string = "Record not found"
|
||||
)
|
||||
|
||||
func TestGoDaddyErrorResponse(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
client := newMockGoDaddyClient(t)
|
||||
provider := &GDProvider{
|
||||
client: client,
|
||||
}
|
||||
|
||||
changes := plan.Changes{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: ".example.net",
|
||||
RecordType: "A",
|
||||
RecordTTL: gdMinimalTTL,
|
||||
Targets: []string{
|
||||
"203.0.113.42",
|
||||
},
|
||||
},
|
||||
},
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "godaddy.example.net",
|
||||
RecordType: "A",
|
||||
Targets: []string{
|
||||
"203.0.113.43",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Fetch domains
|
||||
client.On("Get", "/v1/domains?statuses=ACTIVE").Return([]gdZone{
|
||||
{
|
||||
Domain: zoneNameExampleNet,
|
||||
},
|
||||
}, nil).Once()
|
||||
|
||||
// Fetch record
|
||||
client.On("Get", "/v1/domains/example.net/records").Return([]gdRecordField{
|
||||
{
|
||||
Name: "godaddy",
|
||||
Type: "A",
|
||||
TTL: gdMinimalTTL,
|
||||
Data: "203.0.113.43",
|
||||
},
|
||||
}, nil).Once()
|
||||
|
||||
// Add entry
|
||||
client.On("Patch", "/v1/domains/example.net/records", []gdRecordField{
|
||||
{
|
||||
Name: "@",
|
||||
Type: "A",
|
||||
TTL: gdMinimalTTL,
|
||||
Data: "203.0.113.42",
|
||||
},
|
||||
}).Return(nil, nil).Once()
|
||||
|
||||
// Delete entry
|
||||
client.On("Delete", "/v1/domains/example.net/records/A/godaddy").Return(GDErrorResponse{
|
||||
Code: status404,
|
||||
Message: notfound,
|
||||
Fields: []GDErrorField{{
|
||||
Code: &status404,
|
||||
Message: ¬found,
|
||||
}},
|
||||
}, errors.New(notfound)).Once()
|
||||
|
||||
assert.Error(provider.ApplyChanges(context.TODO(), &changes))
|
||||
|
||||
client.AssertExpectations(t)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user