Skip to content

Commit 51d3103

Browse files
committed
fix cloudflare regional hostname
1 parent 44f1008 commit 51d3103

File tree

2 files changed

+110
-39
lines changed

2 files changed

+110
-39
lines changed

provider/cloudflare/cloudflare.go

+83-37
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ var recordTypeCustomHostnameSupported = map[string]bool{
7575
"CNAME": true,
7676
}
7777

78+
var recordTypeRegionalHostnameSupported = map[string]bool{
79+
"A": true,
80+
"AAAA": true,
81+
"CNAME": true,
82+
}
83+
7884
// cloudFlareDNS is the subset of the CloudFlare API that we actually use. Add methods as required. Signatures must match exactly.
7985
type cloudFlareDNS interface {
8086
UserDetails(ctx context.Context) (cloudflare.User, error)
@@ -86,7 +92,9 @@ type cloudFlareDNS interface {
8692
CreateDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.CreateDNSRecordParams) (cloudflare.DNSRecord, error)
8793
DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error
8894
UpdateDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDNSRecordParams) error
95+
CreateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.CreateDataLocalizationRegionalHostnameParams) error
8996
UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDataLocalizationRegionalHostnameParams) error
97+
DeleteDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, hostname string) error
9098
CustomHostnames(ctx context.Context, zoneID string, page int, filter cloudflare.CustomHostname) ([]cloudflare.CustomHostname, cloudflare.ResultInfo, error)
9199
DeleteCustomHostname(ctx context.Context, zoneID string, customHostnameID string) error
92100
CreateCustomHostname(ctx context.Context, zoneID string, ch cloudflare.CustomHostname) (*cloudflare.CustomHostnameResponse, error)
@@ -121,11 +129,20 @@ func (z zoneService) UpdateDNSRecord(ctx context.Context, rc *cloudflare.Resourc
121129
return err
122130
}
123131

132+
func (z zoneService) CreateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.CreateDataLocalizationRegionalHostnameParams) error {
133+
_, err := z.service.CreateDataLocalizationRegionalHostname(ctx, rc, rp)
134+
return err
135+
}
136+
124137
func (z zoneService) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDataLocalizationRegionalHostnameParams) error {
125138
_, err := z.service.UpdateDataLocalizationRegionalHostname(ctx, rc, rp)
126139
return err
127140
}
128141

142+
func (z zoneService) DeleteDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, hostname string) error {
143+
return z.service.DeleteDataLocalizationRegionalHostname(ctx, rc, hostname)
144+
}
145+
129146
func (z zoneService) DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error {
130147
return z.service.DeleteDNSRecord(ctx, rc, recordID)
131148
}
@@ -189,6 +206,14 @@ func updateDNSRecordParam(cfc cloudFlareChange) cloudflare.UpdateDNSRecordParams
189206
}
190207
}
191208

209+
// createDataLocalizationRegionalHostnameParams is a function that returns the appropriate RegionalHostname Param based on the cloudFlareChange passed in
210+
func createDataLocalizationRegionalHostnameParams(cfc cloudFlareChange) cloudflare.CreateDataLocalizationRegionalHostnameParams {
211+
return cloudflare.CreateDataLocalizationRegionalHostnameParams{
212+
Hostname: cfc.RegionalHostname.Hostname,
213+
RegionKey: cfc.RegionalHostname.RegionKey,
214+
}
215+
}
216+
192217
// updateDataLocalizationRegionalHostnameParams is a function that returns the appropriate RegionalHostname Param based on the cloudFlareChange passed in
193218
func updateDataLocalizationRegionalHostnameParams(cfc cloudFlareChange) cloudflare.UpdateDataLocalizationRegionalHostnameParams {
194219
return cloudflare.UpdateDataLocalizationRegionalHostnameParams{
@@ -427,6 +452,15 @@ func (p *CloudFlareProvider) submitChanges(ctx context.Context, changes []*cloud
427452
}
428453
}
429454
}
455+
if change.RegionalHostname.Hostname != "" {
456+
regionalHostnameParam := updateDataLocalizationRegionalHostnameParams(*change)
457+
log.WithFields(logFields).Debugf("Updating regional hostname %s", change.RegionalHostname.Hostname)
458+
regionalHostnameErr := p.Client.UpdateDataLocalizationRegionalHostname(ctx, resourceContainer, regionalHostnameParam)
459+
if regionalHostnameErr != nil {
460+
failedChange = true
461+
log.WithFields(logFields).Errorf("failed to update regional hostname: %v", regionalHostnameErr)
462+
}
463+
}
430464
recordID := p.getRecordID(records, change.ResourceRecord)
431465
if recordID == "" {
432466
log.WithFields(logFields).Errorf("failed to find previous record: %v", change.ResourceRecord)
@@ -439,13 +473,6 @@ func (p *CloudFlareProvider) submitChanges(ctx context.Context, changes []*cloud
439473
failedChange = true
440474
log.WithFields(logFields).Errorf("failed to update record: %v", err)
441475
}
442-
if regionalHostnameParam := updateDataLocalizationRegionalHostnameParams(*change); regionalHostnameParam.RegionKey != "" {
443-
regionalHostnameErr := p.Client.UpdateDataLocalizationRegionalHostname(ctx, resourceContainer, regionalHostnameParam)
444-
if regionalHostnameErr != nil {
445-
failedChange = true
446-
log.WithFields(logFields).Errorf("failed to update record when editing region: %v", regionalHostnameErr)
447-
}
448-
}
449476
} else if change.Action == cloudFlareDelete {
450477
recordID := p.getRecordID(records, change.ResourceRecord)
451478
if recordID == "" {
@@ -457,19 +484,26 @@ func (p *CloudFlareProvider) submitChanges(ctx context.Context, changes []*cloud
457484
failedChange = true
458485
log.WithFields(logFields).Errorf("failed to delete record: %v", err)
459486
}
460-
if change.CustomHostname.Hostname == "" {
461-
continue
462-
}
463-
log.WithFields(logFields).Infof("Deleting custom hostname %v", change.CustomHostname.Hostname)
464-
chID, _ := p.getCustomHostnameOrigin(chs, change.CustomHostname.Hostname)
465-
if chID == "" {
466-
log.WithFields(logFields).Infof("Custom hostname %v not found", change.CustomHostname.Hostname)
467-
continue
487+
if change.CustomHostname.Hostname != "" {
488+
log.WithFields(logFields).Infof("Deleting custom hostname %v", change.CustomHostname.Hostname)
489+
chID, _ := p.getCustomHostnameOrigin(chs, change.CustomHostname.Hostname)
490+
if chID != "" {
491+
chErr := p.Client.DeleteCustomHostname(ctx, zoneID, chID)
492+
if chErr != nil {
493+
failedChange = true
494+
log.WithFields(logFields).Errorf("failed to delete custom hostname %v/%v: %v", chID, change.CustomHostname.Hostname, chErr)
495+
}
496+
} else {
497+
log.WithFields(logFields).Infof("Custom hostname %v not found", change.CustomHostname.Hostname)
498+
}
468499
}
469-
chErr := p.Client.DeleteCustomHostname(ctx, zoneID, chID)
470-
if chErr != nil {
471-
failedChange = true
472-
log.WithFields(logFields).Errorf("failed to delete custom hostname %v/%v: %v", chID, change.CustomHostname.Hostname, chErr)
500+
if change.RegionalHostname.Hostname != "" {
501+
log.WithFields(logFields).Debugf("Deleting regional hostname %s", change.RegionalHostname.Hostname)
502+
regionalHostnameErr := p.Client.DeleteDataLocalizationRegionalHostname(ctx, resourceContainer, change.RegionalHostname.Hostname)
503+
if regionalHostnameErr != nil && !errors.Is(regionalHostnameErr, cloudflare.NotFoundError{}) {
504+
failedChange = true
505+
log.WithFields(logFields).Errorf("failed to delete regional hostname: %v", regionalHostnameErr)
506+
}
473507
}
474508
} else if change.Action == cloudFlareCreate {
475509
recordParam := getCreateDNSRecordParam(*change)
@@ -478,20 +512,28 @@ func (p *CloudFlareProvider) submitChanges(ctx context.Context, changes []*cloud
478512
failedChange = true
479513
log.WithFields(logFields).Errorf("failed to create record: %v", err)
480514
}
481-
if change.CustomHostname.Hostname == "" {
482-
continue
483-
}
484-
log.WithFields(logFields).Infof("Creating custom hostname %v", change.CustomHostname.Hostname)
485-
chID, chOrigin := p.getCustomHostnameOrigin(chs, change.CustomHostname.Hostname)
486-
if chID != "" {
487-
failedChange = true
488-
log.WithFields(logFields).Errorf("failed to create custom hostname, %v already exists for origin %v", change.CustomHostname.Hostname, chOrigin)
489-
continue
515+
if change.CustomHostname.Hostname != "" {
516+
log.WithFields(logFields).Infof("Creating custom hostname %v", change.CustomHostname.Hostname)
517+
chID, chOrigin := p.getCustomHostnameOrigin(chs, change.CustomHostname.Hostname)
518+
if chID == "" {
519+
_, chErr := p.Client.CreateCustomHostname(ctx, zoneID, change.CustomHostname)
520+
if chErr != nil {
521+
failedChange = true
522+
log.WithFields(logFields).Errorf("failed to create custom hostname %v: %v", change.CustomHostname.Hostname, chErr)
523+
}
524+
} else {
525+
failedChange = true
526+
log.WithFields(logFields).Errorf("failed to create custom hostname, %v already exists for origin %v", change.CustomHostname.Hostname, chOrigin)
527+
}
490528
}
491-
_, chErr := p.Client.CreateCustomHostname(ctx, zoneID, change.CustomHostname)
492-
if chErr != nil {
493-
failedChange = true
494-
log.WithFields(logFields).Errorf("failed to create custom hostname %v: %v", change.CustomHostname.Hostname, chErr)
529+
if change.RegionalHostname.Hostname != "" {
530+
log.WithFields(logFields).Debugf("Creating regional hostname %s", change.RegionalHostname.Hostname)
531+
regionalHostnameParam := createDataLocalizationRegionalHostnameParams(*change)
532+
regionalHostnameErr := p.Client.CreateDataLocalizationRegionalHostname(ctx, resourceContainer, regionalHostnameParam)
533+
if regionalHostnameErr != nil {
534+
failedChange = true
535+
log.WithFields(logFields).Errorf("failed to create regional hostname: %v", regionalHostnameErr)
536+
}
495537
}
496538
}
497539
}
@@ -583,6 +625,14 @@ func (p *CloudFlareProvider) newCloudFlareChange(action string, endpoint *endpoi
583625
SSL: getCustomHostnamesSSLOptions(endpoint, p.CustomHostnamesConfig),
584626
}
585627
}
628+
regionalHostname := cloudflare.RegionalHostname{}
629+
if p.RegionKey != "" && recordTypeRegionalHostnameSupported[endpoint.RecordType] {
630+
regionalHostname = cloudflare.RegionalHostname{
631+
Hostname: endpoint.DNSName,
632+
RegionKey: p.RegionKey,
633+
CreatedOn: &dt,
634+
}
635+
}
586636
return &cloudFlareChange{
587637
Action: action,
588638
ResourceRecord: cloudflare.DNSRecord{
@@ -597,11 +647,7 @@ func (p *CloudFlareProvider) newCloudFlareChange(action string, endpoint *endpoi
597647
"region": p.RegionKey,
598648
},
599649
},
600-
RegionalHostname: cloudflare.RegionalHostname{
601-
Hostname: endpoint.DNSName,
602-
RegionKey: p.RegionKey,
603-
CreatedOn: &dt,
604-
},
650+
RegionalHostname: regionalHostname,
605651
CustomHostnamePrev: customHostnamePrev,
606652
CustomHostname: newCustomHostname,
607653
}

provider/cloudflare/cloudflare_test.go

+27-2
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ func (m *mockCloudFlareClient) UpdateDNSRecord(ctx context.Context, rc *cloudfla
224224
return nil
225225
}
226226

227+
func (m *mockCloudFlareClient) CreateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.CreateDataLocalizationRegionalHostnameParams) error {
228+
m.Actions = append(m.Actions, MockAction{
229+
Name: "CreateDataLocalizationRegionalHostname",
230+
ZoneId: rc.Identifier,
231+
RecordId: "",
232+
RecordData: cloudflare.DNSRecord{
233+
Name: rp.Hostname,
234+
},
235+
})
236+
return nil
237+
}
238+
227239
func (m *mockCloudFlareClient) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDataLocalizationRegionalHostnameParams) error {
228240
m.Actions = append(m.Actions, MockAction{
229241
Name: "UpdateDataLocalizationRegionalHostname",
@@ -236,6 +248,18 @@ func (m *mockCloudFlareClient) UpdateDataLocalizationRegionalHostname(ctx contex
236248
return nil
237249
}
238250

251+
func (m *mockCloudFlareClient) DeleteDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, hostname string) error {
252+
m.Actions = append(m.Actions, MockAction{
253+
Name: "DeleteDataLocalizationRegionalHostname",
254+
ZoneId: rc.Identifier,
255+
RecordId: "",
256+
RecordData: cloudflare.DNSRecord{
257+
Name: hostname,
258+
},
259+
})
260+
return nil
261+
}
262+
239263
func (m *mockCloudFlareClient) DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error {
240264
m.Actions = append(m.Actions, MockAction{
241265
Name: "Delete",
@@ -1581,8 +1605,9 @@ func TestCloudFlareProvider_newCloudFlareChange(t *testing.T) {
15811605
}
15821606

15831607
endpoint := &endpoint.Endpoint{
1584-
DNSName: "example.com",
1585-
Targets: []string{"192.0.2.1"},
1608+
DNSName: "example.com",
1609+
RecordType: "A",
1610+
Targets: []string{"192.0.2.1"},
15861611
}
15871612

15881613
change := provider.newCloudFlareChange(cloudFlareCreate, endpoint, endpoint.Targets[0], nil)

0 commit comments

Comments
 (0)