mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-05 17:16:59 +02:00
624 lines
30 KiB
Go
624 lines
30 KiB
Go
/*
|
|
Copyright 2017 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package azure
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
azcoreruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
|
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
|
dns "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"sigs.k8s.io/external-dns/endpoint"
|
|
"sigs.k8s.io/external-dns/internal/testutils"
|
|
"sigs.k8s.io/external-dns/plan"
|
|
"sigs.k8s.io/external-dns/provider"
|
|
)
|
|
|
|
// mockZonesClient implements the methods of the Azure DNS Zones Client which are used in the Azure Provider
|
|
// and returns static results which are defined per test
|
|
type mockZonesClient struct {
|
|
pagingHandler azcoreruntime.PagingHandler[dns.ZonesClientListByResourceGroupResponse]
|
|
}
|
|
|
|
func newMockZonesClient(zones []*dns.Zone) mockZonesClient {
|
|
pagingHandler := azcoreruntime.PagingHandler[dns.ZonesClientListByResourceGroupResponse]{
|
|
More: func(resp dns.ZonesClientListByResourceGroupResponse) bool {
|
|
return false
|
|
},
|
|
Fetcher: func(context.Context, *dns.ZonesClientListByResourceGroupResponse) (dns.ZonesClientListByResourceGroupResponse, error) {
|
|
return dns.ZonesClientListByResourceGroupResponse{
|
|
ZoneListResult: dns.ZoneListResult{
|
|
Value: zones,
|
|
},
|
|
}, nil
|
|
},
|
|
}
|
|
return mockZonesClient{
|
|
pagingHandler: pagingHandler,
|
|
}
|
|
}
|
|
|
|
func (client *mockZonesClient) NewListByResourceGroupPager(resourceGroupName string, options *dns.ZonesClientListByResourceGroupOptions) *azcoreruntime.Pager[dns.ZonesClientListByResourceGroupResponse] {
|
|
return azcoreruntime.NewPager(client.pagingHandler)
|
|
}
|
|
|
|
// mockZonesClient implements the methods of the Azure DNS RecordSet Client which are used in the Azure Provider
|
|
// and returns static results which are defined per test
|
|
type mockRecordSetsClient struct {
|
|
pagingHandler azcoreruntime.PagingHandler[dns.RecordSetsClientListAllByDNSZoneResponse]
|
|
deletedEndpoints []*endpoint.Endpoint
|
|
updatedEndpoints []*endpoint.Endpoint
|
|
}
|
|
|
|
func newMockRecordSetsClient(recordSets []*dns.RecordSet) mockRecordSetsClient {
|
|
pagingHandler := azcoreruntime.PagingHandler[dns.RecordSetsClientListAllByDNSZoneResponse]{
|
|
More: func(resp dns.RecordSetsClientListAllByDNSZoneResponse) bool {
|
|
return false
|
|
},
|
|
Fetcher: func(context.Context, *dns.RecordSetsClientListAllByDNSZoneResponse) (dns.RecordSetsClientListAllByDNSZoneResponse, error) {
|
|
return dns.RecordSetsClientListAllByDNSZoneResponse{
|
|
RecordSetListResult: dns.RecordSetListResult{
|
|
Value: recordSets,
|
|
},
|
|
}, nil
|
|
},
|
|
}
|
|
return mockRecordSetsClient{
|
|
pagingHandler: pagingHandler,
|
|
}
|
|
}
|
|
|
|
func (client *mockRecordSetsClient) NewListAllByDNSZonePager(resourceGroupName string, zoneName string, options *dns.RecordSetsClientListAllByDNSZoneOptions) *azcoreruntime.Pager[dns.RecordSetsClientListAllByDNSZoneResponse] {
|
|
return azcoreruntime.NewPager(client.pagingHandler)
|
|
}
|
|
|
|
func (client *mockRecordSetsClient) Delete(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, options *dns.RecordSetsClientDeleteOptions) (dns.RecordSetsClientDeleteResponse, error) {
|
|
client.deletedEndpoints = append(
|
|
client.deletedEndpoints,
|
|
endpoint.NewEndpoint(
|
|
formatAzureDNSName(relativeRecordSetName, zoneName),
|
|
string(recordType),
|
|
"",
|
|
),
|
|
)
|
|
return dns.RecordSetsClientDeleteResponse{}, nil
|
|
}
|
|
|
|
func (client *mockRecordSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, zoneName string, relativeRecordSetName string, recordType dns.RecordType, parameters dns.RecordSet, options *dns.RecordSetsClientCreateOrUpdateOptions) (dns.RecordSetsClientCreateOrUpdateResponse, error) {
|
|
var ttl endpoint.TTL
|
|
if parameters.Properties.TTL != nil {
|
|
ttl = endpoint.TTL(*parameters.Properties.TTL)
|
|
}
|
|
client.updatedEndpoints = append(
|
|
client.updatedEndpoints,
|
|
endpoint.NewEndpointWithTTL(
|
|
formatAzureDNSName(relativeRecordSetName, zoneName),
|
|
string(recordType),
|
|
ttl,
|
|
extractAzureTargets(¶meters)...,
|
|
),
|
|
)
|
|
return dns.RecordSetsClientCreateOrUpdateResponse{}, nil
|
|
}
|
|
|
|
func createMockZone(zone string, id string) *dns.Zone {
|
|
return &dns.Zone{
|
|
ID: to.Ptr(id),
|
|
Name: to.Ptr(zone),
|
|
}
|
|
}
|
|
|
|
func aRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
aRecords := make([]*dns.ARecord, len(values))
|
|
for i, value := range values {
|
|
aRecords[i] = &dns.ARecord{
|
|
IPv4Address: to.Ptr(value),
|
|
}
|
|
}
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
ARecords: aRecords,
|
|
}
|
|
}
|
|
|
|
func aaaaRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
aaaaRecords := make([]*dns.AaaaRecord, len(values))
|
|
for i, value := range values {
|
|
aaaaRecords[i] = &dns.AaaaRecord{
|
|
IPv6Address: to.Ptr(value),
|
|
}
|
|
}
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
AaaaRecords: aaaaRecords,
|
|
}
|
|
}
|
|
|
|
func cNameRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
CnameRecord: &dns.CnameRecord{
|
|
Cname: to.Ptr(values[0]),
|
|
},
|
|
}
|
|
}
|
|
|
|
func mxRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
mxRecords := make([]*dns.MxRecord, len(values))
|
|
for i, target := range values {
|
|
mxRecord, _ := parseMxTarget[dns.MxRecord](target)
|
|
mxRecords[i] = &mxRecord
|
|
}
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
MxRecords: mxRecords,
|
|
}
|
|
}
|
|
|
|
func nsRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
nsRecords := make([]*dns.NsRecord, len(values))
|
|
for i, value := range values {
|
|
nsRecords[i] = &dns.NsRecord{
|
|
Nsdname: to.Ptr(value),
|
|
}
|
|
}
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
NsRecords: nsRecords,
|
|
}
|
|
}
|
|
|
|
func txtRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
TxtRecords: []*dns.TxtRecord{
|
|
{
|
|
Value: []*string{to.Ptr(values[0])},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func othersRecordSetPropertiesGetter(values []string, ttl int64) *dns.RecordSetProperties {
|
|
return &dns.RecordSetProperties{
|
|
TTL: to.Ptr(ttl),
|
|
}
|
|
}
|
|
|
|
func createMockRecordSet(name, recordType string, values ...string) *dns.RecordSet {
|
|
return createMockRecordSetMultiWithTTL(name, recordType, 0, values...)
|
|
}
|
|
|
|
func createMockRecordSetWithTTL(name, recordType, value string, ttl int64) *dns.RecordSet {
|
|
return createMockRecordSetMultiWithTTL(name, recordType, ttl, value)
|
|
}
|
|
|
|
func createMockRecordSetMultiWithTTL(name, recordType string, ttl int64, values ...string) *dns.RecordSet {
|
|
var getterFunc func(values []string, ttl int64) *dns.RecordSetProperties
|
|
|
|
switch recordType {
|
|
case endpoint.RecordTypeA:
|
|
getterFunc = aRecordSetPropertiesGetter
|
|
case endpoint.RecordTypeAAAA:
|
|
getterFunc = aaaaRecordSetPropertiesGetter
|
|
case endpoint.RecordTypeCNAME:
|
|
getterFunc = cNameRecordSetPropertiesGetter
|
|
case endpoint.RecordTypeMX:
|
|
getterFunc = mxRecordSetPropertiesGetter
|
|
case endpoint.RecordTypeNS:
|
|
getterFunc = nsRecordSetPropertiesGetter
|
|
case endpoint.RecordTypeTXT:
|
|
getterFunc = txtRecordSetPropertiesGetter
|
|
default:
|
|
getterFunc = othersRecordSetPropertiesGetter
|
|
}
|
|
return &dns.RecordSet{
|
|
Name: to.Ptr(name),
|
|
Type: to.Ptr("Microsoft.Network/dnszones/" + recordType),
|
|
Properties: getterFunc(values, ttl),
|
|
}
|
|
}
|
|
|
|
// newMockedAzureProvider creates an AzureProvider comprising the mocked clients for zones and recordsets
|
|
func newMockedAzureProvider(domainFilter *endpoint.DomainFilter, zoneNameFilter *endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, userAssignedIdentityClientID string, activeDirectoryAuthorityHost string, zones []*dns.Zone, recordSets []*dns.RecordSet, maxRetriesCount int) (*AzureProvider, error) {
|
|
zonesClient := newMockZonesClient(zones)
|
|
recordSetsClient := newMockRecordSetsClient(recordSets)
|
|
return newAzureProvider(domainFilter, zoneNameFilter, zoneIDFilter, dryRun, resourceGroup, userAssignedIdentityClientID, activeDirectoryAuthorityHost, &zonesClient, &recordSetsClient, maxRetriesCount), nil
|
|
}
|
|
|
|
func newAzureProvider(domainFilter *endpoint.DomainFilter, zoneNameFilter *endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool, resourceGroup string, userAssignedIdentityClientID string, activeDirectoryAuthorityHost string, zonesClient ZonesClient, recordsClient RecordSetsClient, maxRetriesCount int) *AzureProvider {
|
|
return &AzureProvider{
|
|
domainFilter: domainFilter,
|
|
zoneNameFilter: zoneNameFilter,
|
|
zoneIDFilter: zoneIDFilter,
|
|
dryRun: dryRun,
|
|
resourceGroup: resourceGroup,
|
|
userAssignedIdentityClientID: userAssignedIdentityClientID,
|
|
activeDirectoryAuthorityHost: activeDirectoryAuthorityHost,
|
|
zonesClient: zonesClient,
|
|
zonesCache: &zonesCache[dns.Zone]{duration: 0},
|
|
recordSetsClient: recordsClient,
|
|
maxRetriesCount: maxRetriesCount,
|
|
}
|
|
}
|
|
|
|
func validateAzureEndpoints(t *testing.T, endpoints []*endpoint.Endpoint, expected []*endpoint.Endpoint) {
|
|
assert.True(t, testutils.SameEndpoints(endpoints, expected), "actual and expected endpoints don't match. %s:%s", endpoints, expected)
|
|
}
|
|
|
|
func TestAzureRecord(t *testing.T) {
|
|
provider, err := newMockedAzureProvider(endpoint.NewDomainFilter([]string{"example.com"}), endpoint.NewDomainFilter([]string{}), provider.NewZoneIDFilter([]string{""}), true, "k8s", "", "",
|
|
[]*dns.Zone{
|
|
createMockZone("example.com", "/dnszones/example.com"),
|
|
},
|
|
[]*dns.RecordSet{
|
|
createMockRecordSet("@", endpoint.RecordTypeNS, "ns1-03.azure-dns.com."),
|
|
createMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"),
|
|
createMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122"),
|
|
createMockRecordSet("@", endpoint.RecordTypeAAAA, "2001::123:123:123:122"),
|
|
createMockRecordSet("cloud", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
createMockRecordSet("@", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeA, "123.123.123.123", 3600),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeAAAA, "2001::123:123:123:123", 3600),
|
|
createMockRecordSetWithTTL("cloud-ttl", endpoint.RecordTypeNS, "ns1-ttl.example.com.", 10),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default", recordTTL),
|
|
createMockRecordSetWithTTL("hack", endpoint.RecordTypeCNAME, "hack.azurewebsites.net", 10),
|
|
createMockRecordSetMultiWithTTL("mail", endpoint.RecordTypeMX, 4000, "10 example.com"),
|
|
}, 3)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
actual, err := provider.Records(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeNS, "ns1-03.azure-dns.com."),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "123.123.123.122"),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::123:123:123:122"),
|
|
endpoint.NewEndpoint("cloud.example.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123"),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeAAAA, 3600, "2001::123:123:123:123"),
|
|
endpoint.NewEndpointWithTTL("cloud-ttl.example.com", endpoint.RecordTypeNS, 10, "ns1-ttl.example.com."),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeTXT, recordTTL, "heritage=external-dns,external-dns/owner=default"),
|
|
endpoint.NewEndpointWithTTL("hack.example.com", endpoint.RecordTypeCNAME, 10, "hack.azurewebsites.net"),
|
|
endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeMX, 4000, "10 example.com"),
|
|
}
|
|
|
|
validateAzureEndpoints(t, actual, expected)
|
|
}
|
|
|
|
func TestAzureMultiRecord(t *testing.T) {
|
|
provider, err := newMockedAzureProvider(endpoint.NewDomainFilter([]string{"example.com"}), endpoint.NewDomainFilter([]string{}), provider.NewZoneIDFilter([]string{""}), true, "k8s", "", "",
|
|
[]*dns.Zone{
|
|
createMockZone("example.com", "/dnszones/example.com"),
|
|
},
|
|
[]*dns.RecordSet{
|
|
createMockRecordSet("@", endpoint.RecordTypeNS, "ns1-03.azure-dns.com."),
|
|
createMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"),
|
|
createMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122", "234.234.234.233"),
|
|
createMockRecordSet("@", endpoint.RecordTypeAAAA, "2001::123:123:123:122", "2001::234:234:234:233"),
|
|
createMockRecordSet("cloud", endpoint.RecordTypeNS, "ns1.example.com.", "ns2.example.com."),
|
|
createMockRecordSet("@", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"),
|
|
createMockRecordSetMultiWithTTL("nginx", endpoint.RecordTypeA, 3600, "123.123.123.123", "234.234.234.234"),
|
|
createMockRecordSetMultiWithTTL("nginx", endpoint.RecordTypeAAAA, 3600, "2001::123:123:123:123", "2001::234:234:234:234"),
|
|
createMockRecordSetMultiWithTTL("cloud-ttl", endpoint.RecordTypeNS, 10, "ns1-ttl.example.com.", "ns2-ttl.example.com."),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default", recordTTL),
|
|
createMockRecordSetWithTTL("hack", endpoint.RecordTypeCNAME, "hack.azurewebsites.net", 10),
|
|
createMockRecordSetMultiWithTTL("mail", endpoint.RecordTypeMX, 4000, "10 example.com", "20 backup.example.com"),
|
|
}, 3)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
actual, err := provider.Records(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeNS, "ns1-03.azure-dns.com."),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "123.123.123.122", "234.234.234.233"),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::123:123:123:122", "2001::234:234:234:233"),
|
|
endpoint.NewEndpoint("cloud.example.com", endpoint.RecordTypeNS, "ns1.example.com.", "ns2.example.com."),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123", "234.234.234.234"),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeAAAA, 3600, "2001::123:123:123:123", "2001::234:234:234:234"),
|
|
endpoint.NewEndpointWithTTL("cloud-ttl.example.com", endpoint.RecordTypeNS, 10, "ns1-ttl.example.com.", "ns2-ttl.example.com."),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeTXT, recordTTL, "heritage=external-dns,external-dns/owner=default"),
|
|
endpoint.NewEndpointWithTTL("hack.example.com", endpoint.RecordTypeCNAME, 10, "hack.azurewebsites.net"),
|
|
endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeMX, 4000, "10 example.com", "20 backup.example.com"),
|
|
}
|
|
|
|
validateAzureEndpoints(t, actual, expected)
|
|
}
|
|
|
|
func TestAzureApplyChanges(t *testing.T) {
|
|
recordsClient := mockRecordSetsClient{}
|
|
|
|
testAzureApplyChangesInternal(t, false, &recordsClient)
|
|
|
|
validateAzureEndpoints(t, recordsClient.deletedEndpoints, []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("deleted.example.com", endpoint.RecordTypeA, ""),
|
|
endpoint.NewEndpoint("deletedaaaa.example.com", endpoint.RecordTypeAAAA, ""),
|
|
endpoint.NewEndpoint("deletedcname.example.com", endpoint.RecordTypeCNAME, ""),
|
|
endpoint.NewEndpoint("deletedns.example.com", endpoint.RecordTypeNS, ""),
|
|
})
|
|
|
|
validateAzureEndpoints(t, recordsClient.updatedEndpoints, []*endpoint.Endpoint{
|
|
endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
|
|
endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::1:2:3:4"),
|
|
endpoint.NewEndpointWithTTL("example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4", "1.2.3.5"),
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::1:2:3:4", "2001::1:2:3:5"),
|
|
endpoint.NewEndpointWithTTL("cloud.example.com", endpoint.RecordTypeNS, endpoint.TTL(recordTTL), "ns1.example.com."),
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
|
|
endpoint.NewEndpointWithTTL("bar.example.com", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "other.com"),
|
|
endpoint.NewEndpointWithTTL("bar.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
|
|
endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "5.6.7.8"),
|
|
endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::5:6:7:8"),
|
|
endpoint.NewEndpointWithTTL("cloud.other.com", endpoint.RecordTypeNS, endpoint.TTL(recordTTL), "ns2.other.com."),
|
|
endpoint.NewEndpointWithTTL("other.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
|
|
endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"),
|
|
endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeAAAA, 3600, "2001::111:222:111:222"),
|
|
endpoint.NewEndpointWithTTL("newcname.example.com", endpoint.RecordTypeCNAME, 10, "other.com"),
|
|
endpoint.NewEndpointWithTTL("newns.example.com", endpoint.RecordTypeNS, 10, "ns1.example.com."),
|
|
endpoint.NewEndpointWithTTL("newmail.example.com", endpoint.RecordTypeMX, 7200, "40 bar.other.com"),
|
|
endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeMX, endpoint.TTL(recordTTL), "10 other.com"),
|
|
endpoint.NewEndpointWithTTL("mail.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
|
|
})
|
|
}
|
|
|
|
func TestAzureApplyChangesDryRun(t *testing.T) {
|
|
recordsClient := mockRecordSetsClient{}
|
|
|
|
testAzureApplyChangesInternal(t, true, &recordsClient)
|
|
|
|
validateAzureEndpoints(t, recordsClient.deletedEndpoints, []*endpoint.Endpoint{})
|
|
|
|
validateAzureEndpoints(t, recordsClient.updatedEndpoints, []*endpoint.Endpoint{})
|
|
}
|
|
|
|
func testAzureApplyChangesInternal(t *testing.T, dryRun bool, client RecordSetsClient) {
|
|
zones := []*dns.Zone{
|
|
createMockZone("example.com", "/dnszones/example.com"),
|
|
createMockZone("other.com", "/dnszones/other.com"),
|
|
}
|
|
zonesClient := newMockZonesClient(zones)
|
|
|
|
provider := newAzureProvider(
|
|
endpoint.NewDomainFilter([]string{""}),
|
|
endpoint.NewDomainFilter([]string{""}),
|
|
provider.NewZoneIDFilter([]string{""}),
|
|
dryRun,
|
|
"group",
|
|
"",
|
|
"",
|
|
&zonesClient,
|
|
client,
|
|
3,
|
|
)
|
|
|
|
createRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "1.2.3.4"),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::1:2:3:4"),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeA, "1.2.3.5", "1.2.3.4"),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeAAAA, "2001::1:2:3:5", "2001::1:2:3:4"),
|
|
endpoint.NewEndpoint("cloud.example.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeCNAME, "other.com"),
|
|
endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("other.com", endpoint.RecordTypeA, "5.6.7.8"),
|
|
endpoint.NewEndpoint("other.com", endpoint.RecordTypeAAAA, "2001::5:6:7:8"),
|
|
endpoint.NewEndpoint("other.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("cloud.other.com", endpoint.RecordTypeNS, "ns2.other.com."),
|
|
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeA, "4.4.4.4"),
|
|
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeAAAA, "2001::4:4:4:4"),
|
|
endpoint.NewEndpoint("cloud.nope.com", endpoint.RecordTypeNS, "ns1.nope.com."),
|
|
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("mail.example.com", endpoint.RecordTypeMX, "10 other.com"),
|
|
endpoint.NewEndpoint("mail.example.com", endpoint.RecordTypeTXT, "tag"),
|
|
}
|
|
|
|
currentRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("old.example.com", endpoint.RecordTypeA, "121.212.121.212"),
|
|
endpoint.NewEndpoint("old.example.com", endpoint.RecordTypeA, "2001::111:222:111:222"),
|
|
endpoint.NewEndpoint("oldcname.example.com", endpoint.RecordTypeCNAME, "other.com"),
|
|
endpoint.NewEndpoint("oldns.example.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
endpoint.NewEndpoint("old.nope.com", endpoint.RecordTypeA, "121.212.121.212"),
|
|
endpoint.NewEndpoint("old.nope.com", endpoint.RecordTypeA, "121.212.121.212"),
|
|
endpoint.NewEndpoint("oldns.nope.com", endpoint.RecordTypeNS, "ns1.example.com"),
|
|
endpoint.NewEndpoint("oldmail.example.com", endpoint.RecordTypeMX, "20 foo.other.com"),
|
|
}
|
|
updatedRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"),
|
|
endpoint.NewEndpointWithTTL("new.example.com", endpoint.RecordTypeAAAA, 3600, "2001::111:222:111:222"),
|
|
endpoint.NewEndpointWithTTL("newcname.example.com", endpoint.RecordTypeCNAME, 10, "other.com"),
|
|
endpoint.NewEndpointWithTTL("newns.example.com", endpoint.RecordTypeNS, 10, "ns1.example.com."),
|
|
endpoint.NewEndpoint("new.nope.com", endpoint.RecordTypeA, "222.111.222.111"),
|
|
endpoint.NewEndpoint("new.nope.com", endpoint.RecordTypeAAAA, "2001::222:111:222:111"),
|
|
endpoint.NewEndpoint("newns.nope.com", endpoint.RecordTypeNS, "ns1.example.com"),
|
|
endpoint.NewEndpointWithTTL("newmail.example.com", endpoint.RecordTypeMX, 7200, "40 bar.other.com"),
|
|
}
|
|
|
|
deleteRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("deleted.example.com", endpoint.RecordTypeA, "111.222.111.222"),
|
|
endpoint.NewEndpoint("deletedaaaa.example.com", endpoint.RecordTypeAAAA, "2001::111:222:111:222"),
|
|
endpoint.NewEndpoint("deletedcname.example.com", endpoint.RecordTypeCNAME, "other.com"),
|
|
endpoint.NewEndpoint("deletedns.example.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
endpoint.NewEndpoint("deleted.nope.com", endpoint.RecordTypeA, "222.111.222.111"),
|
|
endpoint.NewEndpoint("deleted.nope.com", endpoint.RecordTypeAAAA, "2001::222:111:222:111"),
|
|
endpoint.NewEndpoint("deletedns.nope.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
}
|
|
|
|
update, err := plan.MkUpdates(currentRecords, updatedRecords)
|
|
assert.NoError(t, err)
|
|
changes := &plan.Changes{
|
|
Create: createRecords,
|
|
Update: update,
|
|
Delete: deleteRecords,
|
|
}
|
|
|
|
if err := provider.ApplyChanges(context.Background(), changes); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestAzureNameFilter(t *testing.T) {
|
|
provider, err := newMockedAzureProvider(endpoint.NewDomainFilter([]string{"nginx.example.com"}), endpoint.NewDomainFilter([]string{"example.com"}), provider.NewZoneIDFilter([]string{""}), true, "k8s", "", "",
|
|
[]*dns.Zone{
|
|
createMockZone("example.com", "/dnszones/example.com"),
|
|
},
|
|
|
|
[]*dns.RecordSet{
|
|
createMockRecordSet("@", "NS", "ns1-03.azure-dns.com."),
|
|
createMockRecordSet("@", "SOA", "Email: azuredns-hostmaster.microsoft.com"),
|
|
createMockRecordSet("@", endpoint.RecordTypeA, "123.123.123.122"),
|
|
createMockRecordSet("@", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default"),
|
|
createMockRecordSetWithTTL("test.nginx", endpoint.RecordTypeA, "123.123.123.123", 3600),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeA, "123.123.123.123", 3600),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeNS, "ns1.example.com.", 3600),
|
|
createMockRecordSetWithTTL("nginx", endpoint.RecordTypeTXT, "heritage=external-dns,external-dns/owner=default", recordTTL),
|
|
createMockRecordSetWithTTL("mail.nginx", endpoint.RecordTypeMX, "20 example.com", recordTTL),
|
|
createMockRecordSetWithTTL("hack", endpoint.RecordTypeCNAME, "hack.azurewebsites.net", 10),
|
|
createMockRecordSetWithTTL("hack", endpoint.RecordTypeNS, "ns1.example.com.", 3600),
|
|
}, 3)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
actual, err := provider.Records(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := []*endpoint.Endpoint{
|
|
endpoint.NewEndpointWithTTL("test.nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123"),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeA, 3600, "123.123.123.123"),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeNS, 3600, "ns1.example.com."),
|
|
endpoint.NewEndpointWithTTL("nginx.example.com", endpoint.RecordTypeTXT, recordTTL, "heritage=external-dns,external-dns/owner=default"),
|
|
endpoint.NewEndpointWithTTL("mail.nginx.example.com", endpoint.RecordTypeMX, recordTTL, "20 example.com"),
|
|
}
|
|
|
|
validateAzureEndpoints(t, actual, expected)
|
|
}
|
|
|
|
func TestAzureApplyChangesZoneName(t *testing.T) {
|
|
recordsClient := mockRecordSetsClient{}
|
|
|
|
testAzureApplyChangesInternalZoneName(t, false, &recordsClient)
|
|
|
|
validateAzureEndpoints(t, recordsClient.deletedEndpoints, []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("deleted.foo.example.com", endpoint.RecordTypeA, ""),
|
|
endpoint.NewEndpoint("deletedaaaa.foo.example.com", endpoint.RecordTypeAAAA, ""),
|
|
endpoint.NewEndpoint("deletedcname.foo.example.com", endpoint.RecordTypeCNAME, ""),
|
|
endpoint.NewEndpoint("deletedns.foo.example.com", endpoint.RecordTypeNS, ""),
|
|
})
|
|
|
|
validateAzureEndpoints(t, recordsClient.updatedEndpoints, []*endpoint.Endpoint{
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4", "1.2.3.5"),
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "2001::1:2:3:4", "2001::1:2:3:5"),
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeNS, endpoint.TTL(recordTTL), "ns1.example.com."),
|
|
endpoint.NewEndpointWithTTL("foo.example.com", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "tag"),
|
|
endpoint.NewEndpointWithTTL("new.foo.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"),
|
|
endpoint.NewEndpointWithTTL("new.foo.example.com", endpoint.RecordTypeAAAA, 3600, "2001::111:222:111:222"),
|
|
endpoint.NewEndpointWithTTL("newns.foo.example.com", endpoint.RecordTypeNS, 10, "ns1.foo.example.com."),
|
|
endpoint.NewEndpointWithTTL("newcname.foo.example.com", endpoint.RecordTypeCNAME, 10, "other.com"),
|
|
})
|
|
}
|
|
|
|
func testAzureApplyChangesInternalZoneName(t *testing.T, dryRun bool, client RecordSetsClient) {
|
|
zonesClient := newMockZonesClient([]*dns.Zone{createMockZone("example.com", "/dnszones/example.com")})
|
|
|
|
provider := newAzureProvider(
|
|
endpoint.NewDomainFilter([]string{"foo.example.com"}),
|
|
endpoint.NewDomainFilter([]string{"example.com"}),
|
|
provider.NewZoneIDFilter([]string{""}),
|
|
dryRun,
|
|
"group",
|
|
"",
|
|
"",
|
|
&zonesClient,
|
|
client,
|
|
3,
|
|
)
|
|
|
|
createRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeA, "1.2.3.4"),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeAAAA, "2001::1:2:3:4"),
|
|
endpoint.NewEndpoint("example.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeA, "1.2.3.5", "1.2.3.4"),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeAAAA, "2001::1:2:3:5", "2001::1:2:3:4"),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
endpoint.NewEndpoint("foo.example.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeCNAME, "other.com"),
|
|
endpoint.NewEndpoint("barns.example.com", endpoint.RecordTypeNS, "ns1.example.com."),
|
|
endpoint.NewEndpoint("bar.example.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("other.com", endpoint.RecordTypeA, "5.6.7.8"),
|
|
endpoint.NewEndpoint("foons.other.com", endpoint.RecordTypeNS, "ns1.other.com"),
|
|
endpoint.NewEndpoint("other.com", endpoint.RecordTypeTXT, "tag"),
|
|
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeA, "4.4.4.4"),
|
|
endpoint.NewEndpoint("nope.com", endpoint.RecordTypeTXT, "tag"),
|
|
}
|
|
|
|
currentRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("old.foo.example.com", endpoint.RecordTypeA, "121.212.121.212"),
|
|
endpoint.NewEndpoint("old.foo.example.com", endpoint.RecordTypeAAAA, "2001::111:222:111:222"),
|
|
endpoint.NewEndpoint("oldcname.foo.example.com", endpoint.RecordTypeCNAME, "other.com"),
|
|
endpoint.NewEndpoint("oldns.foo.example.com", endpoint.RecordTypeNS, "ns1.foo.example.com."),
|
|
endpoint.NewEndpoint("old.nope.example.com", endpoint.RecordTypeA, "121.212.121.212"),
|
|
endpoint.NewEndpoint("old.nope.example.com", endpoint.RecordTypeAAAA, "2001::222:111:222:111"),
|
|
endpoint.NewEndpoint("oldns.nope.example.com", endpoint.RecordTypeNS, "ns1.nope.example.com."),
|
|
}
|
|
updatedRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpointWithTTL("new.foo.example.com", endpoint.RecordTypeA, 3600, "111.222.111.222"),
|
|
endpoint.NewEndpointWithTTL("new.foo.example.com", endpoint.RecordTypeAAAA, 3600, "2001::111:222:111:222"),
|
|
endpoint.NewEndpointWithTTL("newcname.foo.example.com", endpoint.RecordTypeCNAME, 10, "other.com"),
|
|
endpoint.NewEndpointWithTTL("newns.foo.example.com", endpoint.RecordTypeNS, 10, "ns1.foo.example.com."),
|
|
endpoint.NewEndpoint("new.nope.example.com", endpoint.RecordTypeA, "222.111.222.111"),
|
|
endpoint.NewEndpoint("new.nope.example.com", endpoint.RecordTypeAAAA, "2001::222:111:222:111"),
|
|
endpoint.NewEndpointWithTTL("newns.nope.example.com", endpoint.RecordTypeNS, 10, "ns1.nope.example.com."),
|
|
}
|
|
|
|
deleteRecords := []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("deleted.foo.example.com", endpoint.RecordTypeA, "111.222.111.222"),
|
|
endpoint.NewEndpoint("deletedaaaa.foo.example.com", endpoint.RecordTypeAAAA, "2001::111:222:111:222"),
|
|
endpoint.NewEndpoint("deletedcname.foo.example.com", endpoint.RecordTypeCNAME, "other.com"),
|
|
endpoint.NewEndpoint("deletedns.foo.example.com", endpoint.RecordTypeNS, "ns1.foo.example.com."),
|
|
endpoint.NewEndpoint("deleted.nope.example.com", endpoint.RecordTypeA, "222.111.222.111"),
|
|
}
|
|
|
|
update, err := plan.MkUpdates(currentRecords, updatedRecords)
|
|
assert.NoError(t, err)
|
|
changes := &plan.Changes{
|
|
Create: createRecords,
|
|
Update: update,
|
|
Delete: deleteRecords,
|
|
}
|
|
|
|
if err := provider.ApplyChanges(context.Background(), changes); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|