Merge pull request #4646 from AndrewCharlesHay/cloudflare/region

feat(cloudflare): support cloudflare region
This commit is contained in:
Kubernetes Prow Robot 2024-11-04 17:25:31 +00:00 committed by GitHub
commit ea6d44b0d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 134 additions and 12 deletions

View File

@ -129,6 +129,7 @@ spec:
- --provider=cloudflare - --provider=cloudflare
- --cloudflare-proxied # (optional) enable the proxy feature of Cloudflare (DDOS protection, CDN...) - --cloudflare-proxied # (optional) enable the proxy feature of Cloudflare (DDOS protection, CDN...)
- --cloudflare-dns-records-per-page=5000 # (optional) configure how many DNS records to fetch per request - --cloudflare-dns-records-per-page=5000 # (optional) configure how many DNS records to fetch per request
- --cloudflare-region-key="eu" # (optional) configure which region can decrypt HTTPS requests
env: env:
- name: CF_API_KEY - name: CF_API_KEY
valueFrom: valueFrom:
@ -204,6 +205,7 @@ spec:
- --provider=cloudflare - --provider=cloudflare
- --cloudflare-proxied # (optional) enable the proxy feature of Cloudflare (DDOS protection, CDN...) - --cloudflare-proxied # (optional) enable the proxy feature of Cloudflare (DDOS protection, CDN...)
- --cloudflare-dns-records-per-page=5000 # (optional) configure how many DNS records to fetch per request - --cloudflare-dns-records-per-page=5000 # (optional) configure how many DNS records to fetch per request
- --cloudflare-region-key="eu" # (optional) configure which region can decrypt HTTPS requests
env: env:
- name: CF_API_KEY - name: CF_API_KEY
valueFrom: valueFrom:
@ -299,3 +301,9 @@ $ kubectl delete -f externaldns.yaml
## Setting cloudflare-proxied on a per-ingress basis ## Setting cloudflare-proxied on a per-ingress basis
Using the `external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"` annotation on your ingress, you can specify if the proxy feature of Cloudflare should be enabled for that record. This setting will override the global `--cloudflare-proxied` setting. Using the `external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"` annotation on your ingress, you can specify if the proxy feature of Cloudflare should be enabled for that record. This setting will override the global `--cloudflare-proxied` setting.
## Setting cloudflare-region-key to configure regional services
Using the `external-dns.alpha.kubernetes.io/cloudflare-region-key` annotation on your ingress, you can restrict which data centers can decrypt and serve HTTPS traffic. A list of available options can be seen [here](https://developers.cloudflare.com/data-localization/regional-services/get-started/).
If not set the value will default to `global`.

View File

@ -244,7 +244,7 @@ func main() {
case "civo": case "civo":
p, err = civo.NewCivoProvider(domainFilter, cfg.DryRun) p, err = civo.NewCivoProvider(domainFilter, cfg.DryRun)
case "cloudflare": case "cloudflare":
p, err = cloudflare.NewCloudFlareProvider(domainFilter, zoneIDFilter, cfg.CloudflareProxied, cfg.DryRun, cfg.CloudflareDNSRecordsPerPage) p, err = cloudflare.NewCloudFlareProvider(domainFilter, zoneIDFilter, cfg.CloudflareProxied, cfg.DryRun, cfg.CloudflareDNSRecordsPerPage, cfg.CloudflareRegionKey)
case "google": case "google":
p, err = google.NewGoogleProvider(ctx, cfg.GoogleProject, domainFilter, zoneIDFilter, cfg.GoogleBatchChangeSize, cfg.GoogleBatchChangeInterval, cfg.GoogleZoneVisibility, cfg.DryRun) p, err = google.NewGoogleProvider(ctx, cfg.GoogleProject, domainFilter, zoneIDFilter, cfg.GoogleBatchChangeSize, cfg.GoogleBatchChangeInterval, cfg.GoogleZoneVisibility, cfg.DryRun)
case "digitalocean": case "digitalocean":

View File

@ -108,6 +108,7 @@ type Config struct {
AzureZonesCacheDuration time.Duration AzureZonesCacheDuration time.Duration
CloudflareProxied bool CloudflareProxied bool
CloudflareDNSRecordsPerPage int CloudflareDNSRecordsPerPage int
CloudflareRegionKey string
CoreDNSPrefix string CoreDNSPrefix string
AkamaiServiceConsumerDomain string AkamaiServiceConsumerDomain string
AkamaiClientToken string AkamaiClientToken string
@ -267,6 +268,7 @@ var defaultConfig = &Config{
AzureZonesCacheDuration: 0 * time.Second, AzureZonesCacheDuration: 0 * time.Second,
CloudflareProxied: false, CloudflareProxied: false,
CloudflareDNSRecordsPerPage: 100, CloudflareDNSRecordsPerPage: 100,
CloudflareRegionKey: "earth",
CoreDNSPrefix: "/skydns/", CoreDNSPrefix: "/skydns/",
AkamaiServiceConsumerDomain: "", AkamaiServiceConsumerDomain: "",
AkamaiClientToken: "", AkamaiClientToken: "",
@ -492,6 +494,7 @@ func (cfg *Config) ParseFlags(args []string) error {
app.Flag("cloudflare-proxied", "When using the Cloudflare provider, specify if the proxy mode must be enabled (default: disabled)").BoolVar(&cfg.CloudflareProxied) app.Flag("cloudflare-proxied", "When using the Cloudflare provider, specify if the proxy mode must be enabled (default: disabled)").BoolVar(&cfg.CloudflareProxied)
app.Flag("cloudflare-dns-records-per-page", "When using the Cloudflare provider, specify how many DNS records listed per page, max possible 5,000 (default: 100)").Default(strconv.Itoa(defaultConfig.CloudflareDNSRecordsPerPage)).IntVar(&cfg.CloudflareDNSRecordsPerPage) app.Flag("cloudflare-dns-records-per-page", "When using the Cloudflare provider, specify how many DNS records listed per page, max possible 5,000 (default: 100)").Default(strconv.Itoa(defaultConfig.CloudflareDNSRecordsPerPage)).IntVar(&cfg.CloudflareDNSRecordsPerPage)
app.Flag("cloudflare-region-key", "When using the Cloudflare provider, specify the region (default: earth)").StringVar(&cfg.CloudflareRegionKey)
app.Flag("coredns-prefix", "When using the CoreDNS provider, specify the prefix name").Default(defaultConfig.CoreDNSPrefix).StringVar(&cfg.CoreDNSPrefix) app.Flag("coredns-prefix", "When using the CoreDNS provider, specify the prefix name").Default(defaultConfig.CoreDNSPrefix).StringVar(&cfg.CoreDNSPrefix)
app.Flag("akamai-serviceconsumerdomain", "When using the Akamai provider, specify the base URL (required when --provider=akamai and edgerc-path not specified)").Default(defaultConfig.AkamaiServiceConsumerDomain).StringVar(&cfg.AkamaiServiceConsumerDomain) app.Flag("akamai-serviceconsumerdomain", "When using the Akamai provider, specify the base URL (required when --provider=akamai and edgerc-path not specified)").Default(defaultConfig.AkamaiServiceConsumerDomain).StringVar(&cfg.AkamaiServiceConsumerDomain)
app.Flag("akamai-client-token", "When using the Akamai provider, specify the client token (required when --provider=akamai and edgerc-path not specified)").Default(defaultConfig.AkamaiClientToken).StringVar(&cfg.AkamaiClientToken) app.Flag("akamai-client-token", "When using the Akamai provider, specify the client token (required when --provider=akamai and edgerc-path not specified)").Default(defaultConfig.AkamaiClientToken).StringVar(&cfg.AkamaiClientToken)

View File

@ -75,6 +75,7 @@ var (
AzureSubscriptionID: "", AzureSubscriptionID: "",
CloudflareProxied: false, CloudflareProxied: false,
CloudflareDNSRecordsPerPage: 100, CloudflareDNSRecordsPerPage: 100,
CloudflareRegionKey: "",
CoreDNSPrefix: "/skydns/", CoreDNSPrefix: "/skydns/",
AkamaiServiceConsumerDomain: "", AkamaiServiceConsumerDomain: "",
AkamaiClientToken: "", AkamaiClientToken: "",
@ -175,6 +176,7 @@ var (
AzureSubscriptionID: "arg", AzureSubscriptionID: "arg",
CloudflareProxied: true, CloudflareProxied: true,
CloudflareDNSRecordsPerPage: 5000, CloudflareDNSRecordsPerPage: 5000,
CloudflareRegionKey: "us",
CoreDNSPrefix: "/coredns/", CoreDNSPrefix: "/coredns/",
AkamaiServiceConsumerDomain: "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net", AkamaiServiceConsumerDomain: "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net",
AkamaiClientToken: "o184671d5307a388180fbf7f11dbdf46", AkamaiClientToken: "o184671d5307a388180fbf7f11dbdf46",
@ -277,6 +279,7 @@ func TestParseFlags(t *testing.T) {
"--azure-subscription-id=arg", "--azure-subscription-id=arg",
"--cloudflare-proxied", "--cloudflare-proxied",
"--cloudflare-dns-records-per-page=5000", "--cloudflare-dns-records-per-page=5000",
"--cloudflare-region-key=us",
"--coredns-prefix=/coredns/", "--coredns-prefix=/coredns/",
"--akamai-serviceconsumerdomain=oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net", "--akamai-serviceconsumerdomain=oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net",
"--akamai-client-token=o184671d5307a388180fbf7f11dbdf46", "--akamai-client-token=o184671d5307a388180fbf7f11dbdf46",
@ -396,6 +399,7 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_AZURE_SUBSCRIPTION_ID": "arg", "EXTERNAL_DNS_AZURE_SUBSCRIPTION_ID": "arg",
"EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1", "EXTERNAL_DNS_CLOUDFLARE_PROXIED": "1",
"EXTERNAL_DNS_CLOUDFLARE_DNS_RECORDS_PER_PAGE": "5000", "EXTERNAL_DNS_CLOUDFLARE_DNS_RECORDS_PER_PAGE": "5000",
"EXTERNAL_DNS_CLOUDFLARE_REGION_KEY": "us",
"EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/", "EXTERNAL_DNS_COREDNS_PREFIX": "/coredns/",
"EXTERNAL_DNS_AKAMAI_SERVICECONSUMERDOMAIN": "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net", "EXTERNAL_DNS_AKAMAI_SERVICECONSUMERDOMAIN": "oooo-xxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxx.luna.akamaiapis.net",
"EXTERNAL_DNS_AKAMAI_CLIENT_TOKEN": "o184671d5307a388180fbf7f11dbdf46", "EXTERNAL_DNS_AKAMAI_CLIENT_TOKEN": "o184671d5307a388180fbf7f11dbdf46",

View File

@ -23,6 +23,7 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"time"
cloudflare "github.com/cloudflare/cloudflare-go" cloudflare "github.com/cloudflare/cloudflare-go"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -73,6 +74,7 @@ type cloudFlareDNS interface {
CreateDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.CreateDNSRecordParams) (cloudflare.DNSRecord, error) CreateDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.CreateDNSRecordParams) (cloudflare.DNSRecord, error)
DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error
UpdateDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDNSRecordParams) error UpdateDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDNSRecordParams) error
UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDataLocalizationRegionalHostnameParams) error
} }
type zoneService struct { type zoneService struct {
@ -104,6 +106,11 @@ func (z zoneService) UpdateDNSRecord(ctx context.Context, rc *cloudflare.Resourc
return err return err
} }
func (z zoneService) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDataLocalizationRegionalHostnameParams) error {
_, err := z.service.UpdateDataLocalizationRegionalHostname(ctx, rc, rp)
return err
}
func (z zoneService) DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error { func (z zoneService) DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error {
return z.service.DeleteDNSRecord(ctx, rc, recordID) return z.service.DeleteDNSRecord(ctx, rc, recordID)
} }
@ -126,12 +133,14 @@ type CloudFlareProvider struct {
proxiedByDefault bool proxiedByDefault bool
DryRun bool DryRun bool
DNSRecordsPerPage int DNSRecordsPerPage int
RegionKey string
} }
// cloudFlareChange differentiates between ChangActions // cloudFlareChange differentiates between ChangActions
type cloudFlareChange struct { type cloudFlareChange struct {
Action string Action string
ResourceRecord cloudflare.DNSRecord ResourceRecord cloudflare.DNSRecord
RegionalHostname cloudflare.RegionalHostname
} }
// RecordParamsTypes is a typeset of the possible Record Params that can be passed to cloudflare-go library // RecordParamsTypes is a typeset of the possible Record Params that can be passed to cloudflare-go library
@ -150,6 +159,14 @@ func updateDNSRecordParam(cfc cloudFlareChange) cloudflare.UpdateDNSRecordParams
} }
} }
// updateDataLocalizationRegionalHostnameParams is a function that returns the appropriate RegionalHostname Param based on the cloudFlareChange passed in
func updateDataLocalizationRegionalHostnameParams(cfc cloudFlareChange) cloudflare.UpdateDataLocalizationRegionalHostnameParams {
return cloudflare.UpdateDataLocalizationRegionalHostnameParams{
Hostname: cfc.RegionalHostname.Hostname,
RegionKey: cfc.RegionalHostname.RegionKey,
}
}
// getCreateDNSRecordParam is a function that returns the appropriate Record Param based on the cloudFlareChange passed in // getCreateDNSRecordParam is a function that returns the appropriate Record Param based on the cloudFlareChange passed in
func getCreateDNSRecordParam(cfc cloudFlareChange) cloudflare.CreateDNSRecordParams { func getCreateDNSRecordParam(cfc cloudFlareChange) cloudflare.CreateDNSRecordParams {
return cloudflare.CreateDNSRecordParams{ return cloudflare.CreateDNSRecordParams{
@ -162,7 +179,7 @@ func getCreateDNSRecordParam(cfc cloudFlareChange) cloudflare.CreateDNSRecordPar
} }
// NewCloudFlareProvider initializes a new CloudFlare DNS based Provider. // NewCloudFlareProvider initializes a new CloudFlare DNS based Provider.
func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, proxiedByDefault bool, dryRun bool, dnsRecordsPerPage int) (*CloudFlareProvider, error) { func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, proxiedByDefault bool, dryRun bool, dnsRecordsPerPage int, regionKey string) (*CloudFlareProvider, error) {
// initialize via chosen auth method and returns new API object // initialize via chosen auth method and returns new API object
var ( var (
config *cloudflare.API config *cloudflare.API
@ -192,6 +209,7 @@ func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter prov
proxiedByDefault: proxiedByDefault, proxiedByDefault: proxiedByDefault,
DryRun: dryRun, DryRun: dryRun,
DNSRecordsPerPage: dnsRecordsPerPage, DNSRecordsPerPage: dnsRecordsPerPage,
RegionKey: regionKey,
} }
return provider, nil return provider, nil
} }
@ -351,12 +369,18 @@ func (p *CloudFlareProvider) submitChanges(ctx context.Context, changes []*cloud
continue continue
} }
recordParam := updateDNSRecordParam(*change) recordParam := updateDNSRecordParam(*change)
regionalHostnameParam := updateDataLocalizationRegionalHostnameParams(*change)
recordParam.ID = recordID recordParam.ID = recordID
err := p.Client.UpdateDNSRecord(ctx, resourceContainer, recordParam) err := p.Client.UpdateDNSRecord(ctx, resourceContainer, recordParam)
if err != nil { if err != nil {
failedChange = true failedChange = true
log.WithFields(logFields).Errorf("failed to update record: %v", err) log.WithFields(logFields).Errorf("failed to update record: %v", err)
} }
regionalHostnameErr := p.Client.UpdateDataLocalizationRegionalHostname(ctx, resourceContainer, regionalHostnameParam)
if regionalHostnameErr != nil {
failedChange = true
log.WithFields(logFields).Errorf("failed to update record: %v", regionalHostnameErr)
}
} else if change.Action == cloudFlareDelete { } else if change.Action == cloudFlareDelete {
recordID := p.getRecordID(records, change.ResourceRecord) recordID := p.getRecordID(records, change.ResourceRecord)
if recordID == "" { if recordID == "" {
@ -443,7 +467,7 @@ func (p *CloudFlareProvider) newCloudFlareChange(action string, endpoint *endpoi
if endpoint.RecordTTL.IsConfigured() { if endpoint.RecordTTL.IsConfigured() {
ttl = int(endpoint.RecordTTL) ttl = int(endpoint.RecordTTL)
} }
dt := time.Now()
return &cloudFlareChange{ return &cloudFlareChange{
Action: action, Action: action,
ResourceRecord: cloudflare.DNSRecord{ ResourceRecord: cloudflare.DNSRecord{
@ -452,6 +476,14 @@ func (p *CloudFlareProvider) newCloudFlareChange(action string, endpoint *endpoi
Proxied: &proxied, Proxied: &proxied,
Type: endpoint.RecordType, Type: endpoint.RecordType,
Content: target, Content: target,
Meta: map[string]interface{}{
"region": p.RegionKey,
},
},
RegionalHostname: cloudflare.RegionalHostname{
Hostname: endpoint.DNSName,
RegionKey: p.RegionKey,
CreatedOn: &dt,
}, },
} }
} }

View File

@ -204,6 +204,18 @@ func (m *mockCloudFlareClient) UpdateDNSRecord(ctx context.Context, rc *cloudfla
return nil return nil
} }
func (m *mockCloudFlareClient) UpdateDataLocalizationRegionalHostname(ctx context.Context, rc *cloudflare.ResourceContainer, rp cloudflare.UpdateDataLocalizationRegionalHostnameParams) error {
m.Actions = append(m.Actions, MockAction{
Name: "UpdateDataLocalizationRegionalHostname",
ZoneId: rc.Identifier,
RecordId: "",
RecordData: cloudflare.DNSRecord{
Name: rp.Hostname,
},
})
return nil
}
func (m *mockCloudFlareClient) DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error { func (m *mockCloudFlareClient) DeleteDNSRecord(ctx context.Context, rc *cloudflare.ResourceContainer, recordID string) error {
m.Actions = append(m.Actions, MockAction{ m.Actions = append(m.Actions, MockAction{
Name: "Delete", Name: "Delete",
@ -706,7 +718,8 @@ func TestCloudflareProvider(t *testing.T) {
provider.NewZoneIDFilter([]string{""}), provider.NewZoneIDFilter([]string{""}),
false, false,
true, true,
5000) 5000,
"")
if err != nil { if err != nil {
t.Errorf("should not fail, %s", err) t.Errorf("should not fail, %s", err)
} }
@ -722,7 +735,8 @@ func TestCloudflareProvider(t *testing.T) {
provider.NewZoneIDFilter([]string{""}), provider.NewZoneIDFilter([]string{""}),
false, false,
true, true,
5000) 5000,
"")
if err != nil { if err != nil {
t.Errorf("should not fail, %s", err) t.Errorf("should not fail, %s", err)
} }
@ -735,7 +749,8 @@ func TestCloudflareProvider(t *testing.T) {
provider.NewZoneIDFilter([]string{""}), provider.NewZoneIDFilter([]string{""}),
false, false,
true, true,
5000) 5000,
"")
if err != nil { if err != nil {
t.Errorf("should not fail, %s", err) t.Errorf("should not fail, %s", err)
} }
@ -747,7 +762,8 @@ func TestCloudflareProvider(t *testing.T) {
provider.NewZoneIDFilter([]string{""}), provider.NewZoneIDFilter([]string{""}),
false, false,
true, true,
5000) 5000,
"")
if err == nil { if err == nil {
t.Errorf("expected to fail") t.Errorf("expected to fail")
} }
@ -1225,7 +1241,6 @@ func TestCloudflareComplexUpdate(t *testing.T) {
client := NewMockCloudFlareClientWithRecords(map[string][]cloudflare.DNSRecord{ client := NewMockCloudFlareClientWithRecords(map[string][]cloudflare.DNSRecord{
"001": ExampleDomain, "001": ExampleDomain,
}) })
provider := &CloudFlareProvider{ provider := &CloudFlareProvider{
Client: client, Client: client,
} }
@ -1267,7 +1282,7 @@ func TestCloudflareComplexUpdate(t *testing.T) {
t.Errorf("should not fail, %s", err) t.Errorf("should not fail, %s", err)
} }
td.CmpDeeply(t, client.Actions, []MockAction{ mockAction := []MockAction{
{ {
Name: "Delete", Name: "Delete",
ZoneId: "001", ZoneId: "001",
@ -1296,7 +1311,17 @@ func TestCloudflareComplexUpdate(t *testing.T) {
Proxied: proxyEnabled, Proxied: proxyEnabled,
}, },
}, },
}) {
Name: "UpdateDataLocalizationRegionalHostname",
ZoneId: "001",
RecordData: cloudflare.DNSRecord{
Name: "foobar.bar.com",
TTL: 0,
Proxiable: false,
},
},
}
td.CmpDeeply(t, client.Actions, mockAction)
} }
func TestCustomTTLWithEnabledProxyNotChanged(t *testing.T) { func TestCustomTTLWithEnabledProxyNotChanged(t *testing.T) {
@ -1355,3 +1380,53 @@ func TestCustomTTLWithEnabledProxyNotChanged(t *testing.T) {
assert.Equal(t, 0, len(planned.Changes.UpdateOld), "no new changes should be here") assert.Equal(t, 0, len(planned.Changes.UpdateOld), "no new changes should be here")
assert.Equal(t, 0, len(planned.Changes.Delete), "no new changes should be here") assert.Equal(t, 0, len(planned.Changes.Delete), "no new changes should be here")
} }
func TestCloudFlareProvider_Region(t *testing.T) {
_ = os.Setenv("CF_API_TOKEN", "abc123def")
_ = os.Setenv("CF_API_EMAIL", "test@test.com")
provider, err := NewCloudFlareProvider(endpoint.NewDomainFilter([]string{"example.com"}), provider.ZoneIDFilter{}, true, false, 50, "us")
if err != nil {
t.Fatal(err)
}
if provider.RegionKey != "us" {
t.Errorf("expected region key to be 'us', but got '%s'", provider.RegionKey)
}
}
func TestCloudFlareProvider_updateDataLocalizationRegionalHostnameParams(t *testing.T) {
change := &cloudFlareChange{
RegionalHostname: cloudflare.RegionalHostname{
Hostname: "example.com",
RegionKey: "us",
},
}
params := updateDataLocalizationRegionalHostnameParams(*change)
if params.Hostname != "example.com" {
t.Errorf("expected hostname to be 'example.com', but got '%s'", params.Hostname)
}
if params.RegionKey != "us" {
t.Errorf("expected region key to be 'us', but got '%s'", params.RegionKey)
}
}
func TestCloudFlareProvider_newCloudFlareChange(t *testing.T) {
_ = os.Setenv("CF_API_KEY", "xxxxxxxxxxxxxxxxx")
_ = os.Setenv("CF_API_EMAIL", "test@test.com")
provider, err := NewCloudFlareProvider(endpoint.NewDomainFilter([]string{"example.com"}), provider.ZoneIDFilter{}, true, false, 50, "us")
if err != nil {
t.Fatal(err)
}
endpoint := &endpoint.Endpoint{
DNSName: "example.com",
Targets: []string{"192.0.2.1"},
}
change := provider.newCloudFlareChange(cloudFlareCreate, endpoint, endpoint.Targets[0])
if change.RegionalHostname.RegionKey != "us" {
t.Errorf("expected region key to be 'us', but got '%s'", change.RegionalHostname.RegionKey)
}
}