mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-05 09:06:58 +02:00
* chore(codebase): enable testifylint * chore(codebase): enable testifylint Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> * chore(codebase): enable testifylint Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> --------- Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
1333 lines
45 KiB
Go
1333 lines
45 KiB
Go
/*
|
|
Copyright 2023 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 registry
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
|
|
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
|
dynamodbtypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
|
|
"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"
|
|
"sigs.k8s.io/external-dns/provider/inmemory"
|
|
)
|
|
|
|
func TestDynamoDBRegistryNew(t *testing.T) {
|
|
api, p := newDynamoDBAPIStub(t, nil)
|
|
|
|
_, err := NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "", "", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.NoError(t, err)
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "test-table", "testPrefix", "", "", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.NoError(t, err)
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "testSuffix", "", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.NoError(t, err)
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "", "testWildcard", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.NoError(t, err)
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "", "testWildcard", []string{}, []string{}, []byte(";k&l)nUC/33:{?d{3)54+,AD?]SX%yh^"), time.Hour)
|
|
require.NoError(t, err)
|
|
|
|
_, err = NewDynamoDBRegistry(p, "", api, "test-table", "", "", "", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.EqualError(t, err, "owner id cannot be empty")
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "", "", "", "", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.EqualError(t, err, "table cannot be empty")
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "", "", []string{}, []string{}, []byte(";k&l)nUC/33:{?d{3)54+,AD?]SX%yh^x"), time.Hour)
|
|
require.EqualError(t, err, "the AES Encryption key must be 32 bytes long, in either plain text or base64-encoded format")
|
|
|
|
_, err = NewDynamoDBRegistry(p, "test-owner", api, "test-table", "testPrefix", "testSuffix", "", []string{}, []string{}, []byte(""), time.Hour)
|
|
require.EqualError(t, err, "txt-prefix and txt-suffix are mutually exclusive")
|
|
}
|
|
|
|
func TestDynamoDBRegistryNew_EncryptionConfig(t *testing.T) {
|
|
api, p := newDynamoDBAPIStub(t, nil)
|
|
|
|
tests := []struct {
|
|
encEnabled bool
|
|
aesKeyRaw []byte
|
|
aesKeySanitized []byte
|
|
errorExpected bool
|
|
}{
|
|
{
|
|
encEnabled: true,
|
|
aesKeyRaw: []byte("123456789012345678901234567890asdfasdfasdfasdfa12"),
|
|
aesKeySanitized: []byte{},
|
|
errorExpected: true,
|
|
},
|
|
{
|
|
encEnabled: true,
|
|
aesKeyRaw: []byte("passphrasewhichneedstobe32bytes!"),
|
|
aesKeySanitized: []byte("passphrasewhichneedstobe32bytes!"),
|
|
errorExpected: false,
|
|
},
|
|
{
|
|
encEnabled: true,
|
|
aesKeyRaw: []byte("ZPitL0NGVQBZbTD6DwXJzD8RiStSazzYXQsdUowLURY="),
|
|
aesKeySanitized: []byte{100, 248, 173, 47, 67, 70, 85, 0, 89, 109, 48, 250, 15, 5, 201, 204, 63, 17, 137, 43, 82, 107, 60, 216, 93, 11, 29, 82, 140, 11, 81, 22},
|
|
errorExpected: false,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
actual, err := NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "", "", []string{}, []string{}, test.aesKeyRaw, time.Hour)
|
|
if test.errorExpected {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
assert.Equal(t, test.aesKeySanitized, actual.txtEncryptAESKey)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDynamoDBRegistryRecordsBadTable(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
setup func(desc *dynamodbtypes.TableDescription)
|
|
expected string
|
|
}{
|
|
{
|
|
name: "missing attribute k",
|
|
setup: func(desc *dynamodbtypes.TableDescription) {
|
|
desc.AttributeDefinitions[0].AttributeName = aws.String("wrong")
|
|
},
|
|
expected: "table \"test-table\" must have attribute \"k\" of type \"S\"",
|
|
},
|
|
{
|
|
name: "wrong attribute type",
|
|
setup: func(desc *dynamodbtypes.TableDescription) {
|
|
desc.AttributeDefinitions[0].AttributeType = "SS"
|
|
},
|
|
expected: "table \"test-table\" attribute \"k\" must have type \"S\"",
|
|
},
|
|
{
|
|
name: "wrong key",
|
|
setup: func(desc *dynamodbtypes.TableDescription) {
|
|
desc.KeySchema[0].AttributeName = aws.String("wrong")
|
|
},
|
|
expected: "table \"test-table\" must have hash key \"k\"",
|
|
},
|
|
{
|
|
name: "has range key",
|
|
setup: func(desc *dynamodbtypes.TableDescription) {
|
|
desc.AttributeDefinitions = append(desc.AttributeDefinitions, dynamodbtypes.AttributeDefinition{
|
|
AttributeName: aws.String("o"),
|
|
AttributeType: dynamodbtypes.ScalarAttributeTypeS,
|
|
})
|
|
desc.KeySchema = append(desc.KeySchema, dynamodbtypes.KeySchemaElement{
|
|
AttributeName: aws.String("o"),
|
|
KeyType: dynamodbtypes.KeyTypeRange,
|
|
})
|
|
},
|
|
expected: "table \"test-table\" must not have a range key",
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
api, p := newDynamoDBAPIStub(t, nil)
|
|
tc.setup(&api.tableDescription)
|
|
|
|
r, _ := NewDynamoDBRegistry(p, "test-owner", api, "test-table", "", "", "", []string{}, []string{}, nil, time.Hour)
|
|
|
|
_, err := r.Records(context.Background())
|
|
assert.EqualError(t, err, tc.expected)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDynamoDBRegistryRecords(t *testing.T) {
|
|
api, p := newDynamoDBAPIStub(t, nil)
|
|
|
|
ctx := context.Background()
|
|
expectedRecords := []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "migrate.test-zone.example.org",
|
|
Targets: endpoint.Targets{"3.3.3.3"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-3",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
ProviderSpecific: endpoint.ProviderSpecific{
|
|
{
|
|
Name: dynamodbAttributeMigrate,
|
|
Value: "true",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
DNSName: "txt.orphaned.test-zone.example.org",
|
|
Targets: endpoint.Targets{"\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/other-ingress\""},
|
|
RecordType: endpoint.RecordTypeTXT,
|
|
SetIdentifier: "set-3",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "txt.baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/other-ingress\""},
|
|
RecordType: endpoint.RecordTypeTXT,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
},
|
|
},
|
|
}
|
|
|
|
r, _ := NewDynamoDBRegistry(p, "test-owner", api, "test-table", "txt.", "", "", []string{}, []string{}, nil, time.Hour)
|
|
_ = p.(*wrappedProvider).Provider.ApplyChanges(context.Background(), &plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("migrate.test-zone.example.org", endpoint.RecordTypeA, "3.3.3.3").WithSetIdentifier("set-3"),
|
|
endpoint.NewEndpoint("txt.migrate.test-zone.example.org", endpoint.RecordTypeTXT, "\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/other-ingress\"").WithSetIdentifier("set-3"),
|
|
endpoint.NewEndpoint("txt.orphaned.test-zone.example.org", endpoint.RecordTypeTXT, "\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/other-ingress\"").WithSetIdentifier("set-3"),
|
|
endpoint.NewEndpoint("txt.baz.test-zone.example.org", endpoint.RecordTypeTXT, "\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/other-ingress\"").WithSetIdentifier("set-2"),
|
|
},
|
|
})
|
|
|
|
records, err := r.Records(ctx)
|
|
require.NoError(t, err)
|
|
|
|
assert.True(t, testutils.SameEndpoints(records, expectedRecords))
|
|
}
|
|
|
|
func TestDynamoDBRegistryApplyChanges(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name string
|
|
maxBatchSize uint8
|
|
stubConfig DynamoDBStubConfig
|
|
addRecords []*endpoint.Endpoint
|
|
changes plan.Changes
|
|
expectedError string
|
|
expectedRecords []*endpoint.Endpoint
|
|
}{
|
|
{
|
|
name: "create",
|
|
changes: plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "new.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectInsert: map[string]map[string]string{
|
|
"new.test-zone.example.org#CNAME#set-new": {endpoint.ResourceLabelKey: "ingress/default/new-ingress"},
|
|
},
|
|
ExpectDelete: sets.New("quux.test-zone.example.org#A#set-2"),
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "new.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "create more entries than DynamoDB batch size limit",
|
|
maxBatchSize: 2,
|
|
changes: plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "new1.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new1.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new1-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "new2.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new2.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new2-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "new3.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new3.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new3-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectInsert: map[string]map[string]string{
|
|
"new1.test-zone.example.org#CNAME#set-new": {endpoint.ResourceLabelKey: "ingress/default/new1-ingress"},
|
|
"new2.test-zone.example.org#CNAME#set-new": {endpoint.ResourceLabelKey: "ingress/default/new2-ingress"},
|
|
"new3.test-zone.example.org#CNAME#set-new": {endpoint.ResourceLabelKey: "ingress/default/new3-ingress"},
|
|
},
|
|
ExpectDelete: sets.New("quux.test-zone.example.org#A#set-2"),
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "new1.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new1.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new1-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "new2.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new2.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new2-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "new3.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new3.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new3-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "create orphaned",
|
|
changes: plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "quux.test-zone.example.org",
|
|
Targets: endpoint.Targets{"5.5.5.5"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/quux-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "quux.test-zone.example.org",
|
|
Targets: endpoint.Targets{"5.5.5.5"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/quux-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "create orphaned change",
|
|
changes: plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "quux.test-zone.example.org",
|
|
Targets: endpoint.Targets{"5.5.5.5"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectUpdate: map[string]map[string]string{
|
|
"quux.test-zone.example.org#A#set-2": {endpoint.ResourceLabelKey: "ingress/default/new-ingress"},
|
|
},
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "quux.test-zone.example.org",
|
|
Targets: endpoint.Targets{"5.5.5.5"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "create duplicate",
|
|
changes: plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "new.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectInsertError: map[string]dynamodbtypes.BatchStatementErrorCodeEnum{
|
|
"new.test-zone.example.org#CNAME#set-new": dynamodbtypes.BatchStatementErrorCodeEnumDuplicateItem,
|
|
},
|
|
ExpectDelete: sets.New("quux.test-zone.example.org#A#set-2"),
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "create error",
|
|
changes: plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "new.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
SetIdentifier: "set-new",
|
|
Labels: map[string]string{
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectInsertError: map[string]dynamodbtypes.BatchStatementErrorCodeEnum{
|
|
"new.test-zone.example.org#CNAME#set-new": "TestingError",
|
|
},
|
|
},
|
|
expectedError: "inserting dynamodb record \"new.test-zone.example.org#CNAME#set-new\": TestingError: testing error",
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update",
|
|
changes: plan.Changes{
|
|
UpdateOld: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
},
|
|
UpdateNew: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectDelete: sets.New("quux.test-zone.example.org#A#set-2"),
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update change",
|
|
changes: plan.Changes{
|
|
UpdateOld: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
},
|
|
UpdateNew: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectDelete: sets.New("quux.test-zone.example.org#A#set-2"),
|
|
ExpectUpdate: map[string]map[string]string{
|
|
"bar.test-zone.example.org#CNAME#": {endpoint.ResourceLabelKey: "ingress/default/new-ingress"},
|
|
},
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update migrate",
|
|
addRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "txt.bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/new-ingress\""},
|
|
RecordType: endpoint.RecordTypeTXT,
|
|
SetIdentifier: "set-1",
|
|
},
|
|
},
|
|
changes: plan.Changes{
|
|
UpdateOld: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
ProviderSpecific: endpoint.ProviderSpecific{
|
|
{
|
|
Name: dynamodbAttributeMigrate,
|
|
Value: "true",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
UpdateNew: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectDelete: sets.New("quux.test-zone.example.org#A#set-2"),
|
|
ExpectInsert: map[string]map[string]string{
|
|
"bar.test-zone.example.org#CNAME#": {endpoint.ResourceLabelKey: "ingress/default/new-ingress"},
|
|
},
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "txt.bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"\"heritage=external-dns,external-dns/owner=test-owner,external-dns/resource=ingress/default/new-ingress\""},
|
|
RecordType: endpoint.RecordTypeTXT,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "update error",
|
|
changes: plan.Changes{
|
|
UpdateOld: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
},
|
|
UpdateNew: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"new-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/new-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectUpdateError: map[string]dynamodbtypes.BatchStatementErrorCodeEnum{
|
|
"bar.test-zone.example.org#CNAME#": "TestingError",
|
|
},
|
|
},
|
|
expectedError: "updating dynamodb record \"bar.test-zone.example.org#CNAME#\": TestingError: testing error",
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "delete",
|
|
changes: plan.Changes{
|
|
Delete: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "bar.test-zone.example.org",
|
|
Targets: endpoint.Targets{"my-domain.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
stubConfig: DynamoDBStubConfig{
|
|
ExpectDelete: sets.New("bar.test-zone.example.org#CNAME#", "quux.test-zone.example.org#A#set-2"),
|
|
},
|
|
expectedRecords: []*endpoint.Endpoint{
|
|
{
|
|
DNSName: "foo.test-zone.example.org",
|
|
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
|
RecordType: endpoint.RecordTypeCNAME,
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"1.1.1.1"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-1",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/my-ingress",
|
|
},
|
|
},
|
|
{
|
|
DNSName: "baz.test-zone.example.org",
|
|
Targets: endpoint.Targets{"2.2.2.2"},
|
|
RecordType: endpoint.RecordTypeA,
|
|
SetIdentifier: "set-2",
|
|
Labels: map[string]string{
|
|
endpoint.OwnerLabelKey: "test-owner",
|
|
endpoint.ResourceLabelKey: "ingress/default/other-ingress",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
originalMaxBatchSize := dynamodbMaxBatchSize
|
|
if tc.maxBatchSize > 0 {
|
|
dynamodbMaxBatchSize = tc.maxBatchSize
|
|
}
|
|
|
|
api, p := newDynamoDBAPIStub(t, &tc.stubConfig)
|
|
if len(tc.addRecords) > 0 {
|
|
_ = p.(*wrappedProvider).Provider.ApplyChanges(context.Background(), &plan.Changes{
|
|
Create: tc.addRecords,
|
|
})
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
r, _ := NewDynamoDBRegistry(p, "test-owner", api, "test-table", "txt.", "", "", []string{}, []string{}, nil, time.Hour)
|
|
_, err := r.Records(ctx)
|
|
require.NoError(t, err)
|
|
|
|
err = r.ApplyChanges(ctx, &tc.changes)
|
|
if tc.expectedError == "" {
|
|
assert.NoError(t, err)
|
|
} else {
|
|
assert.EqualError(t, err, tc.expectedError)
|
|
}
|
|
|
|
assert.Empty(t, tc.stubConfig.ExpectInsert, "all expected inserts made")
|
|
assert.Empty(t, tc.stubConfig.ExpectDelete, "all expected deletions made")
|
|
|
|
records, err := r.Records(ctx)
|
|
require.NoError(t, err)
|
|
assert.True(t, testutils.SameEndpoints(records, tc.expectedRecords))
|
|
|
|
r.recordsCache = nil
|
|
records, err = r.Records(ctx)
|
|
require.NoError(t, err)
|
|
assert.True(t, testutils.SameEndpoints(records, tc.expectedRecords))
|
|
if tc.expectedError == "" {
|
|
assert.Empty(t, r.orphanedLabels)
|
|
}
|
|
|
|
dynamodbMaxBatchSize = originalMaxBatchSize
|
|
})
|
|
}
|
|
}
|
|
|
|
// DynamoDBAPIStub is a minimal implementation of DynamoDBAPI, used primarily for unit testing.
|
|
type DynamoDBStub struct {
|
|
t *testing.T
|
|
stubConfig *DynamoDBStubConfig
|
|
tableDescription dynamodbtypes.TableDescription
|
|
changesApplied bool
|
|
}
|
|
|
|
type DynamoDBStubConfig struct {
|
|
ExpectInsert map[string]map[string]string
|
|
ExpectInsertError map[string]dynamodbtypes.BatchStatementErrorCodeEnum
|
|
ExpectUpdate map[string]map[string]string
|
|
ExpectUpdateError map[string]dynamodbtypes.BatchStatementErrorCodeEnum
|
|
ExpectDelete sets.Set[string]
|
|
}
|
|
|
|
type wrappedProvider struct {
|
|
provider.Provider
|
|
stub *DynamoDBStub
|
|
}
|
|
|
|
func (w *wrappedProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
|
assert.False(w.stub.t, w.stub.changesApplied, "ApplyChanges already called")
|
|
w.stub.changesApplied = true
|
|
return w.Provider.ApplyChanges(ctx, changes)
|
|
}
|
|
|
|
func newDynamoDBAPIStub(t *testing.T, stubConfig *DynamoDBStubConfig) (*DynamoDBStub, provider.Provider) {
|
|
stub := &DynamoDBStub{
|
|
t: t,
|
|
stubConfig: stubConfig,
|
|
tableDescription: dynamodbtypes.TableDescription{
|
|
AttributeDefinitions: []dynamodbtypes.AttributeDefinition{
|
|
{
|
|
AttributeName: aws.String("k"),
|
|
AttributeType: dynamodbtypes.ScalarAttributeTypeS,
|
|
},
|
|
},
|
|
KeySchema: []dynamodbtypes.KeySchemaElement{
|
|
{
|
|
AttributeName: aws.String("k"),
|
|
KeyType: dynamodbtypes.KeyTypeHash,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
p := inmemory.NewInMemoryProvider()
|
|
_ = p.CreateZone(testZone)
|
|
_ = p.ApplyChanges(context.Background(), &plan.Changes{
|
|
Create: []*endpoint.Endpoint{
|
|
endpoint.NewEndpoint("foo.test-zone.example.org", endpoint.RecordTypeCNAME, "foo.loadbalancer.com"),
|
|
endpoint.NewEndpoint("bar.test-zone.example.org", endpoint.RecordTypeCNAME, "my-domain.com"),
|
|
endpoint.NewEndpoint("baz.test-zone.example.org", endpoint.RecordTypeA, "1.1.1.1").WithSetIdentifier("set-1"),
|
|
endpoint.NewEndpoint("baz.test-zone.example.org", endpoint.RecordTypeA, "2.2.2.2").WithSetIdentifier("set-2"),
|
|
},
|
|
})
|
|
return stub, &wrappedProvider{
|
|
Provider: p,
|
|
stub: stub,
|
|
}
|
|
}
|
|
|
|
func (r *DynamoDBStub) DescribeTable(ctx context.Context, input *dynamodb.DescribeTableInput, opts ...func(*dynamodb.Options)) (*dynamodb.DescribeTableOutput, error) {
|
|
assert.NotNil(r.t, ctx)
|
|
assert.Equal(r.t, "test-table", *input.TableName, "table name")
|
|
return &dynamodb.DescribeTableOutput{
|
|
Table: &r.tableDescription,
|
|
}, nil
|
|
}
|
|
|
|
func (r *DynamoDBStub) Scan(ctx context.Context, input *dynamodb.ScanInput, opts ...func(*dynamodb.Options)) (*dynamodb.ScanOutput, error) {
|
|
assert.NotNil(r.t, ctx)
|
|
assert.Equal(r.t, "test-table", *input.TableName, "table name")
|
|
assert.Equal(r.t, "o = :ownerval", *input.FilterExpression)
|
|
assert.Len(r.t, input.ExpressionAttributeValues, 1)
|
|
var owner string
|
|
assert.NoError(r.t, attributevalue.Unmarshal(input.ExpressionAttributeValues[":ownerval"], &owner))
|
|
assert.Equal(r.t, "test-owner", owner)
|
|
assert.Equal(r.t, "k,l", *input.ProjectionExpression)
|
|
assert.True(r.t, *input.ConsistentRead)
|
|
return &dynamodb.ScanOutput{
|
|
Items: []map[string]dynamodbtypes.AttributeValue{
|
|
{
|
|
"k": &dynamodbtypes.AttributeValueMemberS{Value: "bar.test-zone.example.org#CNAME#"},
|
|
"l": &dynamodbtypes.AttributeValueMemberM{Value: map[string]dynamodbtypes.AttributeValue{
|
|
endpoint.ResourceLabelKey: &dynamodbtypes.AttributeValueMemberS{Value: "ingress/default/my-ingress"},
|
|
}},
|
|
},
|
|
{
|
|
"k": &dynamodbtypes.AttributeValueMemberS{Value: "baz.test-zone.example.org#A#set-1"},
|
|
"l": &dynamodbtypes.AttributeValueMemberM{Value: map[string]dynamodbtypes.AttributeValue{
|
|
endpoint.ResourceLabelKey: &dynamodbtypes.AttributeValueMemberS{Value: "ingress/default/my-ingress"},
|
|
}},
|
|
},
|
|
{
|
|
"k": &dynamodbtypes.AttributeValueMemberS{Value: "baz.test-zone.example.org#A#set-2"},
|
|
"l": &dynamodbtypes.AttributeValueMemberM{Value: map[string]dynamodbtypes.AttributeValue{
|
|
endpoint.ResourceLabelKey: &dynamodbtypes.AttributeValueMemberS{Value: "ingress/default/other-ingress"},
|
|
}},
|
|
},
|
|
{
|
|
"k": &dynamodbtypes.AttributeValueMemberS{Value: "quux.test-zone.example.org#A#set-2"},
|
|
"l": &dynamodbtypes.AttributeValueMemberM{Value: map[string]dynamodbtypes.AttributeValue{
|
|
endpoint.ResourceLabelKey: &dynamodbtypes.AttributeValueMemberS{Value: "ingress/default/quux-ingress"},
|
|
}},
|
|
},
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (r *DynamoDBStub) BatchExecuteStatement(context context.Context, input *dynamodb.BatchExecuteStatementInput, option ...func(*dynamodb.Options)) (*dynamodb.BatchExecuteStatementOutput, error) {
|
|
assert.NotNil(r.t, context)
|
|
hasDelete := strings.HasPrefix(strings.ToLower(*input.Statements[0].Statement), "delete")
|
|
assert.Equal(r.t, hasDelete, r.changesApplied, "delete after provider changes, everything else before")
|
|
assert.LessOrEqual(r.t, len(input.Statements), 25)
|
|
responses := make([]dynamodbtypes.BatchStatementResponse, 0, len(input.Statements))
|
|
|
|
for _, statement := range input.Statements {
|
|
assert.Equal(r.t, hasDelete, strings.HasPrefix(strings.ToLower(*statement.Statement), "delete"))
|
|
switch *statement.Statement {
|
|
case "DELETE FROM \"test-table\" WHERE \"k\"=? AND \"o\"=?":
|
|
assert.True(r.t, r.changesApplied, "unexpected delete before provider changes")
|
|
|
|
var key string
|
|
require.NoError(r.t, attributevalue.Unmarshal(statement.Parameters[0], &key))
|
|
assert.True(r.t, r.stubConfig.ExpectDelete.Has(key), "unexpected delete for key %q", key)
|
|
r.stubConfig.ExpectDelete.Delete(key)
|
|
|
|
var testOwner string
|
|
assert.NoError(r.t, attributevalue.Unmarshal(statement.Parameters[1], &testOwner))
|
|
assert.Equal(r.t, "test-owner", testOwner)
|
|
|
|
responses = append(responses, dynamodbtypes.BatchStatementResponse{})
|
|
|
|
case "INSERT INTO \"test-table\" VALUE {'k':?, 'o':?, 'l':?}":
|
|
assert.False(r.t, r.changesApplied, "unexpected insert after provider changes")
|
|
|
|
var key string
|
|
assert.NoError(r.t, attributevalue.Unmarshal(statement.Parameters[0], &key))
|
|
if code, ok := r.stubConfig.ExpectInsertError[key]; ok {
|
|
delete(r.stubConfig.ExpectInsertError, key)
|
|
responses = append(responses, dynamodbtypes.BatchStatementResponse{
|
|
Error: &dynamodbtypes.BatchStatementError{
|
|
Code: code,
|
|
Message: aws.String("testing error"),
|
|
},
|
|
})
|
|
break
|
|
}
|
|
|
|
expectedLabels, found := r.stubConfig.ExpectInsert[key]
|
|
assert.True(r.t, found, "unexpected insert for key %q", key)
|
|
delete(r.stubConfig.ExpectInsert, key)
|
|
|
|
var testOwner string
|
|
require.NoError(r.t, attributevalue.Unmarshal(statement.Parameters[1], &testOwner))
|
|
assert.Equal(r.t, "test-owner", testOwner)
|
|
|
|
var labels map[string]string
|
|
err := attributevalue.Unmarshal(statement.Parameters[2], &labels)
|
|
assert.NoError(r.t, err)
|
|
|
|
for label, value := range labels {
|
|
expectedValue, found := expectedLabels[label]
|
|
assert.True(r.t, found, "insert for key %q has unexpected label %q", key, label)
|
|
delete(expectedLabels, label)
|
|
assert.Equal(r.t, expectedValue, value, "insert for key %q label %q value", key, label)
|
|
}
|
|
|
|
for label := range expectedLabels {
|
|
r.t.Errorf("insert for key %q did not get expected label %q", key, label)
|
|
}
|
|
|
|
responses = append(responses, dynamodbtypes.BatchStatementResponse{})
|
|
|
|
case "UPDATE \"test-table\" SET \"l\"=? WHERE \"k\"=?":
|
|
assert.False(r.t, r.changesApplied, "unexpected update after provider changes")
|
|
|
|
var key string
|
|
assert.NoError(r.t, attributevalue.Unmarshal(statement.Parameters[1], &key))
|
|
if code, exists := r.stubConfig.ExpectUpdateError[key]; exists {
|
|
delete(r.stubConfig.ExpectInsertError, key)
|
|
responses = append(responses, dynamodbtypes.BatchStatementResponse{
|
|
Error: &dynamodbtypes.BatchStatementError{
|
|
Code: code,
|
|
Message: aws.String("testing error"),
|
|
},
|
|
})
|
|
break
|
|
}
|
|
|
|
expectedLabels, found := r.stubConfig.ExpectUpdate[key]
|
|
assert.True(r.t, found, "unexpected update for key %q", key)
|
|
delete(r.stubConfig.ExpectUpdate, key)
|
|
|
|
var labels map[string]string
|
|
assert.NoError(r.t, attributevalue.Unmarshal(statement.Parameters[0], &labels))
|
|
|
|
for label, value := range labels {
|
|
expectedValue, found := expectedLabels[label]
|
|
assert.True(r.t, found, "update for key %q has unexpected label %q", key, label)
|
|
delete(expectedLabels, label)
|
|
assert.Equal(r.t, expectedValue, value, "update for key %q label %q value", key, label)
|
|
}
|
|
|
|
for label := range expectedLabels {
|
|
r.t.Errorf("update for key %q did not get expected label %q", key, label)
|
|
}
|
|
|
|
responses = append(responses, dynamodbtypes.BatchStatementResponse{})
|
|
|
|
default:
|
|
r.t.Errorf("unexpected statement: %s", *statement.Statement)
|
|
}
|
|
}
|
|
|
|
return &dynamodb.BatchExecuteStatementOutput{
|
|
Responses: responses,
|
|
}, nil
|
|
}
|