sigs.k8s.io/external-dns@v0.14.1/provider/azure/azure_privatedns_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package azure 18 19 import ( 20 "context" 21 "testing" 22 23 azcoreruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" 24 "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" 25 privatedns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns" 26 "sigs.k8s.io/external-dns/endpoint" 27 "sigs.k8s.io/external-dns/plan" 28 "sigs.k8s.io/external-dns/provider" 29 ) 30 31 const ( 32 recordTTL = 300 33 ) 34 35 // mockPrivateZonesClient implements the methods of the Azure Private DNS Zones Client which are used in the Azure Private DNS Provider 36 // and returns static results which are defined per test 37 type mockPrivateZonesClient struct { 38 pagingHandler azcoreruntime.PagingHandler[privatedns.PrivateZonesClientListByResourceGroupResponse] 39 } 40 41 func newMockPrivateZonesClient(zones []*privatedns.PrivateZone) mockPrivateZonesClient { 42 pagingHandler := azcoreruntime.PagingHandler[privatedns.PrivateZonesClientListByResourceGroupResponse]{ 43 More: func(resp privatedns.PrivateZonesClientListByResourceGroupResponse) bool { 44 return false 45 }, 46 Fetcher: func(context.Context, *privatedns.PrivateZonesClientListByResourceGroupResponse) (privatedns.PrivateZonesClientListByResourceGroupResponse, error) { 47 return privatedns.PrivateZonesClientListByResourceGroupResponse{ 48 PrivateZoneListResult: privatedns.PrivateZoneListResult{ 49 Value: zones, 50 }, 51 }, nil 52 }, 53 } 54 return mockPrivateZonesClient{ 55 pagingHandler: pagingHandler, 56 } 57 } 58 59 func (client *mockPrivateZonesClient) NewListByResourceGroupPager(resourceGroupName string, options *privatedns.PrivateZonesClientListByResourceGroupOptions) *azcoreruntime.Pager[privatedns.PrivateZonesClientListByResourceGroupResponse] { 60 return azcoreruntime.NewPager(client.pagingHandler) 61 } 62 63 // mockPrivateRecordSetsClient implements the methods of the Azure Private DNS RecordSet Client which are used in the Azure Private DNS Provider 64 // and returns static results which are defined per test 65 type mockPrivateRecordSetsClient struct { 66 pagingHandler azcoreruntime.PagingHandler[privatedns.RecordSetsClientListResponse] 67 deletedEndpoints []*endpoint.Endpoint 68 updatedEndpoints []*endpoint.Endpoint 69 } 70 71 func newMockPrivateRecordSectsClient(recordSets []*privatedns.RecordSet) mockPrivateRecordSetsClient { 72 pagingHandler := azcoreruntime.PagingHandler[privatedns.RecordSetsClientListResponse]{ 73 More: func(resp privatedns.RecordSetsClientListResponse) bool { 74 return false 75 }, 76 Fetcher: func(context.Context, *privatedns.RecordSetsClientListResponse) (privatedns.RecordSetsClientListResponse, error) { 77 return privatedns.RecordSetsClientListResponse{ 78 RecordSetListResult: privatedns.RecordSetListResult{ 79 Value: recordSets, 80 }, 81 }, nil 82 }, 83 } 84 return mockPrivateRecordSetsClient{ 85 pagingHandler: pagingHandler, 86 } 87 } 88 89 func (client *mockPrivateRecordSetsClient) NewListPager(resourceGroupName string, privateZoneName string, options *privatedns.RecordSetsClientListOptions) *azcoreruntime.Pager[privatedns.RecordSetsClientListResponse] { 90 return azcoreruntime.NewPager(client.pagingHandler) 91 } 92 93 func (client *mockPrivateRecordSetsClient) Delete(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, options *privatedns.RecordSetsClientDeleteOptions) (privatedns.RecordSetsClientDeleteResponse, error) { 94 client.deletedEndpoints = append( 95 client.deletedEndpoints, 96 endpoint.NewEndpoint( 97 formatAzureDNSName(relativeRecordSetName, privateZoneName), 98 string(recordType), 99 "", 100 ), 101 ) 102 return privatedns.RecordSetsClientDeleteResponse{}, nil 103 } 104 105 func (client *mockPrivateRecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, privateZoneName string, recordType privatedns.RecordType, relativeRecordSetName string, parameters privatedns.RecordSet, options *privatedns.RecordSetsClientCreateOrUpdateOptions) (privatedns.RecordSetsClientCreateOrUpdateResponse, error) { 106 var ttl endpoint.TTL 107 if parameters.Properties.TTL != nil { 108 ttl = endpoint.TTL(*parameters.Properties.TTL) 109 } 110 client.updatedEndpoints = append( 111 client.updatedEndpoints, 112 endpoint.NewEndpointWithTTL( 113 formatAzureDNSName(relativeRecordSetName, privateZoneName), 114 string(recordType), 115 ttl, 116 extractAzurePrivateDNSTargets(¶meters)..., 117 ), 118 ) 119 return privatedns.RecordSetsClientCreateOrUpdateResponse{}, nil 120 //return parameters, nil 121 } 122 123 func createMockPrivateZone(zone string, id string) *privatedns.PrivateZone { 124 return &privatedns.PrivateZone{ 125 ID: to.Ptr(id), 126 Name: to.Ptr(zone), 127 } 128 } 129 130 func privateARecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { 131 aRecords := make([]*privatedns.ARecord, len(values)) 132 for i, value := range values { 133 aRecords[i] = &privatedns.ARecord{ 134 IPv4Address: to.Ptr(value), 135 } 136 } 137 return &privatedns.RecordSetProperties{ 138 TTL: to.Ptr(ttl), 139 ARecords: aRecords, 140 } 141 } 142 143 func privateAAAARecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { 144 aaaaRecords := make([]*privatedns.AaaaRecord, len(values)) 145 for i, value := range values { 146 aaaaRecords[i] = &privatedns.AaaaRecord{ 147 IPv6Address: to.Ptr(value), 148 } 149 } 150 return &privatedns.RecordSetProperties{ 151 TTL: to.Ptr(ttl), 152 AaaaRecords: aaaaRecords, 153 } 154 } 155 156 func privateCNameRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { 157 return &privatedns.RecordSetProperties{ 158 TTL: to.Ptr(ttl), 159 CnameRecord: &privatedns.CnameRecord{ 160 Cname: to.Ptr(values[0]), 161 }, 162 } 163 } 164 165 func privateMXRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { 166 mxRecords := make([]*privatedns.MxRecord, len(values)) 167 for i, target := range values { 168 mxRecord, _ := parseMxTarget[privatedns.MxRecord](target) 169 mxRecords[i] = &mxRecord 170 } 171 return &privatedns.RecordSetProperties{ 172 TTL: to.Ptr(ttl), 173 MxRecords: mxRecords, 174 } 175 } 176 177 func privateTxtRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { 178 return &privatedns.RecordSetProperties{ 179 TTL: to.Ptr(ttl), 180 TxtRecords: []*privatedns.TxtRecord{ 181 { 182 Value: []*string{&values[0]}, 183 }, 184 }, 185 } 186 } 187 188 func privateOthersRecordSetPropertiesGetter(values []string, ttl int64) *privatedns.RecordSetProperties { 189 return &privatedns.RecordSetProperties{ 190 TTL: to.Ptr(ttl), 191 } 192 } 193 194 func createPrivateMockRecordSet(name, recordType string, values ...string) *privatedns.RecordSet { 195 return createPrivateMockRecordSetMultiWithTTL(name, recordType, 0, values...) 196 } 197 198 func createPrivateMockRecordSetWithTTL(name, recordType, value string, ttl int64) *privatedns.RecordSet { 199 return createPrivateMockRecordSetMultiWithTTL(name, recordType, ttl, value) 200 } 201 202 func createPrivateMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values ...string) *privatedns.RecordSet { 203 var getterFunc func(values []string, ttl int64) *privatedns.RecordSetProperties 204 205 switch recordType { 206 case endpoint.RecordTypeA: 207 getterFunc = privateARecordSetPropertiesGetter 208 case endpoint.RecordTypeAAAA: 209 getterFunc = privateAAAARecordSetPropertiesGetter 210 case endpoint.RecordTypeCNAME: 211 getterFunc = privateCNameRecordSetPropertiesGetter 212 case endpoint.RecordTypeMX: 213 getterFunc = privateMXRecordSetPropertiesGetter 214 case endpoint.RecordTypeTXT: 215 getterFunc = privateTxtRecordSetPropertiesGetter 216 default: 217 getterFunc = privateOthersRecordSetPropertiesGetter 218 } 219 return &privatedns.RecordSet{ 220 Name: to.Ptr(name), 221 Type: to.Ptr("Microsoft.Network/privateDnsZones/" + recordType), 222 Properties: getterFunc(values, ttl), 223 } 224 } 225 226 // newMockedAzurePrivateDNSProvider creates an AzureProvider comprising the mocked clients for zones and recordsets 227 func newMockedAzurePrivateDNSProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, zones []*privatedns.PrivateZone, recordSets []*privatedns.RecordSet) (*AzurePrivateDNSProvider, error) { 228 zonesClient := newMockPrivateZonesClient(zones) 229 recordSetsClient := newMockPrivateRecordSectsClient(recordSets) 230 return newAzurePrivateDNSProvider(domainFilter, zoneIDFilter, dryRun, resourceGroup, &zonesClient, &recordSetsClient), nil 231 } 232 233 func newAzurePrivateDNSProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, privateZonesClient PrivateZonesClient, privateRecordsClient PrivateRecordSetsClient) *AzurePrivateDNSProvider { 234 return &AzurePrivateDNSProvider{ 235 domainFilter: domainFilter, 236 zoneIDFilter: zoneIDFilter, 237 dryRun: dryRun, 238 resourceGroup: resourceGroup, 239 zonesClient: privateZonesClient, 240 recordSetsClient: privateRecordsClient, 241 } 242 } 243 244 func TestAzurePrivateDNSRecord(t *testing.T) { 245 provider, err := newMockedAzurePrivateDNSProvider(endpoint.NewDomainFilter([]string{"example.com"}), provider.NewZoneIDFilter([]string{""}), true, "k8s", 246 []*privatedns.PrivateZone{ 247 createMockPrivateZone("example.com", "/privateDnsZones/example.com"), 248 }, 249 []*privatedns.RecordSet{ 250 createPrivateMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), 251 createPrivateMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), 252 createPrivateMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122"), 253 createPrivateMockRecordSet("@", endpoint.RecordTypeAAAA, "2001::123:123:123:122"), 254 createPrivateMockRecordSet("@", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"), 255 createPrivateMockRecordSetWithTTL("nginx", endpoint.RecordTypeA, "123.123.123.123", 3600), 256 createPrivateMockRecordSetWithTTL("nginx", endpoint.RecordTypeAAAA, "2001::123:123:123:123", 3600), 257 createPrivateMockRecordSetWithTTL("nginx", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default", recordTTL), 258 createPrivateMockRecordSetWithTTL("hack", endpoint.RecordTypeCNAME, "hack.azurewebsites.net", 10), 259 createPrivateMockRecordSetWithTTL("mail", endpoint.RecordTypeMX, "10 example.com", 4000), 260 }) 261 if err != nil { 262 t.Fatal(err) 263 } 264 265 actual, err := provider.Records(context.Background()) 266 if err != nil { 267 t.Fatal(err) 268 } 269 expected := []*endpoint.Endpoint{ 270 endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "123.123.123.122"), 271 endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::123:123:123:122"), 272 endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"), 273 endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123"), 274 endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeAAAA, 3600, "2001::123:123:123:123"), 275 endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeTXT, recordTTL, "heritage=external-dns,external-dns/owner=default"), 276 endpoint.NewEndpointWithTTL("hack.example.com", endpoint.RecordTypeCNAME, 10, "hack.azurewebsites.net"), 277 endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeMX, 4000, "10 example.com"), 278 } 279 280 validateAzureEndpoints(t, actual, expected) 281 } 282 283 func TestAzurePrivateDNSMultiRecord(t *testing.T) { 284 provider, err := newMockedAzurePrivateDNSProvider(endpoint.NewDomainFilter([]string{"example.com"}), provider.NewZoneIDFilter([]string{""}), true, "k8s", 285 []*privatedns.PrivateZone{ 286 createMockPrivateZone("example.com", "/privateDnsZones/example.com"), 287 }, 288 []*privatedns.RecordSet{ 289 createPrivateMockRecordSet("@", "NS", "ns1-03.azure-dns.com."), 290 createPrivateMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"), 291 createPrivateMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122", "234.234.234.233"), 292 createPrivateMockRecordSet("@", endpoint.RecordTypeAAAA, "2001::123:123:123:122", "2001::234:234:234:233"), 293 createPrivateMockRecordSet("@", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"), 294 createPrivateMockRecordSetMultiWithTTL("nginx", endpoint.RecordTypeA, 3600, "123.123.123.123", "234.234.234.234"), 295 createPrivateMockRecordSetMultiWithTTL("nginx", endpoint.RecordTypeAAAA, 3600, "2001::123:123:123:123", "2001::234:234:234:234"), 296 createPrivateMockRecordSetWithTTL("nginx", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default", recordTTL), 297 createPrivateMockRecordSetWithTTL("hack", endpoint.RecordTypeCNAME, "hack.azurewebsites.net", 10), 298 createPrivateMockRecordSetMultiWithTTL("mail", endpoint.RecordTypeMX, 4000, "10 example.com", "20 backup.example.com"), 299 }) 300 if err != nil { 301 t.Fatal(err) 302 } 303 304 actual, err := provider.Records(context.Background()) 305 if err != nil { 306 t.Fatal(err) 307 } 308 expected := []*endpoint.Endpoint{ 309 endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "123.123.123.122", "234.234.234.233"), 310 endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::123:123:123:122", "2001::234:234:234:233"), 311 endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"), 312 endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123", "234.234.234.234"), 313 endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeAAAA, 3600, "2001::123:123:123:123", "2001::234:234:234:234"), 314 endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeTXT, recordTTL, "heritage=external-dns,external-dns/owner=default"), 315 endpoint.NewEndpointWithTTL("hack.example.com", endpoint.RecordTypeCNAME, 10, "hack.azurewebsites.net"), 316 endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeMX, 4000, "10 example.com", "20 backup.example.com"), 317 } 318 319 validateAzureEndpoints(t, actual, expected) 320 } 321 322 func TestAzurePrivateDNSApplyChanges(t *testing.T) { 323 recordsClient := mockPrivateRecordSetsClient{} 324 325 testAzurePrivateDNSApplyChangesInternal(t, false, &recordsClient) 326 327 validateAzureEndpoints(t, recordsClient.deletedEndpoints, []*endpoint.Endpoint{ 328 endpoint.NewEndpoint("deleted.example.com", endpoint.RecordTypeA, ""), 329 endpoint.NewEndpoint("deletedaaaa.example.com", endpoint.RecordTypeAAAA, ""), 330 endpoint.NewEndpoint("deletedcname.example.com", endpoint.RecordTypeCNAME, ""), 331 }) 332 333 validateAzureEndpoints(t, recordsClient.updatedEndpoints, []*endpoint.Endpoint{ 334 endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"), 335 endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::1:2:3:4"), 336 endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"), 337 endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4", "1.2.3.5"), 338 endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::1:2:3:4", "2001::1:2:3:5"), 339 endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"), 340 endpoint.NewEndpointWithTTL("bar.example.com", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "other.com"), 341 endpoint.NewEndpointWithTTL("bar.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"), 342 endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "5.6.7.8"), 343 endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::5:6:7:8"), 344 endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"), 345 endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"), 346 endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeAAAA, 3600, "2001::111:222:111:222"), 347 endpoint.NewEndpointWithTTL("newcname.example.com", endpoint.RecordTypeCNAME, 10, "other.com"), 348 endpoint.NewEndpointWithTTL("newmail.example.com", endpoint.RecordTypeMX, 7200, "40 bar.other.com"), 349 endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeMX, endpoint.TTL(recordTTL), "10 other.com"), 350 endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"), 351 }) 352 } 353 354 func TestAzurePrivateDNSApplyChangesDryRun(t *testing.T) { 355 recordsClient := mockRecordSetsClient{} 356 357 testAzureApplyChangesInternal(t, true, &recordsClient) 358 359 validateAzureEndpoints(t, recordsClient.deletedEndpoints, []*endpoint.Endpoint{}) 360 361 validateAzureEndpoints(t, recordsClient.updatedEndpoints, []*endpoint.Endpoint{}) 362 } 363 364 func testAzurePrivateDNSApplyChangesInternal(t *testing.T, dryRun bool, client PrivateRecordSetsClient) { 365 zones := []*privatedns.PrivateZone{ 366 createMockPrivateZone("example.com", "/privateDnsZones/example.com"), 367 createMockPrivateZone("other.com", "/privateDnsZones/other.com"), 368 } 369 zonesClient := newMockPrivateZonesClient(zones) 370 371 provider := newAzurePrivateDNSProvider( 372 endpoint.NewDomainFilter([]string{""}), 373 provider.NewZoneIDFilter([]string{""}), 374 dryRun, 375 "group", 376 &zonesClient, 377 client, 378 ) 379 380 createRecords := []*endpoint.Endpoint{ 381 endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "1.2.3.4"), 382 endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::1:2:3:4"), 383 endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "tag"), 384 endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeA, "1.2.3.5", "1.2.3.4"), 385 endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeAAAA, "2001::1:2:3:5", "2001::1:2:3:4"), 386 endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeTXT, "tag"), 387 endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeCNAME, "other.com"), 388 endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeTXT, "tag"), 389 endpoint.NewEndpoint("other.com", endpoint.RecordTypeA, "5.6.7.8"), 390 endpoint.NewEndpoint("other.com", endpoint.RecordTypeAAAA, "2001::5:6:7:8"), 391 endpoint.NewEndpoint("other.com", endpoint.RecordTypeTXT, "tag"), 392 endpoint.NewEndpoint("nope.com", endpoint.RecordTypeA, "4.4.4.4"), 393 endpoint.NewEndpoint("nope.com", endpoint.RecordTypeAAAA, "2001::4:4:4:4"), 394 endpoint.NewEndpoint("nope.com", endpoint.RecordTypeTXT, "tag"), 395 endpoint.NewEndpoint("mail.example.com", endpoint.RecordTypeMX, "10 other.com"), 396 endpoint.NewEndpoint("mail.example.com", endpoint.RecordTypeTXT, "tag"), 397 } 398 399 currentRecords := []*endpoint.Endpoint{ 400 endpoint.NewEndpoint("old.example.com", endpoint.RecordTypeA, "121.212.121.212"), 401 endpoint.NewEndpoint("oldcname.example.com", endpoint.RecordTypeCNAME, "other.com"), 402 endpoint.NewEndpoint("old.nope.com", endpoint.RecordTypeA, "121.212.121.212"), 403 endpoint.NewEndpoint("oldmail.example.com", endpoint.RecordTypeMX, "20 foo.other.com"), 404 } 405 updatedRecords := []*endpoint.Endpoint{ 406 endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"), 407 endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeAAAA, 3600, "2001::111:222:111:222"), 408 endpoint.NewEndpointWithTTL("newcname.example.com", endpoint.RecordTypeCNAME, 10, "other.com"), 409 endpoint.NewEndpoint("new.nope.com", endpoint.RecordTypeA, "222.111.222.111"), 410 endpoint.NewEndpoint("new.nope.com", endpoint.RecordTypeAAAA, "2001::222:111:222:111"), 411 endpoint.NewEndpointWithTTL("newmail.example.com", endpoint.RecordTypeMX, 7200, "40 bar.other.com"), 412 } 413 414 deleteRecords := []*endpoint.Endpoint{ 415 endpoint.NewEndpoint("deleted.example.com", endpoint.RecordTypeA, "111.222.111.222"), 416 endpoint.NewEndpoint("deletedaaaa.example.com", endpoint.RecordTypeAAAA, "2001::111:222:111:222"), 417 endpoint.NewEndpoint("deletedcname.example.com", endpoint.RecordTypeCNAME, "other.com"), 418 endpoint.NewEndpoint("deleted.nope.com", endpoint.RecordTypeA, "222.111.222.111"), 419 endpoint.NewEndpoint("deleted.nope.com", endpoint.RecordTypeAAAA, "2001::222:111:222:111"), 420 } 421 422 changes := &plan.Changes{ 423 Create: createRecords, 424 UpdateNew: updatedRecords, 425 UpdateOld: currentRecords, 426 Delete: deleteRecords, 427 } 428 429 if err := provider.ApplyChanges(context.Background(), changes); err != nil { 430 t.Fatal(err) 431 } 432 }