mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
* feat(aws): support hostnames as endpoint targets * docs: describe how to run ExternalDNS on AWS * docs: update changelog with CNAME feature * docs: update changelog to include AWS documentation * fix(aws): test that updating records removes the old value * feat(google): add CNAME support to Google provider * fix(source): sanitize source and target hostnames * docs: update changelog to include latest changes * docs(aws): mention that ExternalDNS takes full ownership of a hosted zone * fix(aws): switch route53 tests to use endpoint pointers * docs: add TODO to remove record filtering once ownership is in place
1021 lines
25 KiB
Go
1021 lines
25 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 provider
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/service/route53"
|
|
|
|
"github.com/kubernetes-incubator/external-dns/endpoint"
|
|
"github.com/kubernetes-incubator/external-dns/plan"
|
|
)
|
|
|
|
// Compile time check for interface conformance
|
|
var _ Route53API = &Route53APIStub{}
|
|
|
|
// Route53APIStub is a minimal implementation of Route53API, used primarily for unit testing.
|
|
// See http://http://docs.aws.amazon.com/sdk-for-go/api/service/route53.html for descriptions
|
|
// of all of its methods.
|
|
// mostly taken from: https://github.com/kubernetes/kubernetes/blob/853167624edb6bc0cfdcdfb88e746e178f5db36c/federation/pkg/dnsprovider/providers/aws/route53/stubs/route53api.go
|
|
type Route53APIStub struct {
|
|
zones map[string]*route53.HostedZone
|
|
recordSets map[string]map[string][]*route53.ResourceRecordSet
|
|
}
|
|
|
|
// NewRoute53APIStub returns an initialized Route53APIStub
|
|
func NewRoute53APIStub() *Route53APIStub {
|
|
return &Route53APIStub{
|
|
zones: make(map[string]*route53.HostedZone),
|
|
recordSets: make(map[string]map[string][]*route53.ResourceRecordSet),
|
|
}
|
|
}
|
|
|
|
func (r *Route53APIStub) ListResourceRecordSetsPages(input *route53.ListResourceRecordSetsInput, fn func(p *route53.ListResourceRecordSetsOutput, lastPage bool) (shouldContinue bool)) error {
|
|
output := route53.ListResourceRecordSetsOutput{} // TODO: Support optional input args.
|
|
if len(r.recordSets) <= 0 {
|
|
output.ResourceRecordSets = []*route53.ResourceRecordSet{}
|
|
} else if _, ok := r.recordSets[aws.StringValue(input.HostedZoneId)]; !ok {
|
|
output.ResourceRecordSets = []*route53.ResourceRecordSet{}
|
|
} else {
|
|
for _, rrsets := range r.recordSets[aws.StringValue(input.HostedZoneId)] {
|
|
for _, rrset := range rrsets {
|
|
output.ResourceRecordSets = append(output.ResourceRecordSets, rrset)
|
|
}
|
|
}
|
|
}
|
|
lastPage := true
|
|
fn(&output, lastPage)
|
|
return nil
|
|
}
|
|
|
|
func (r *Route53APIStub) ChangeResourceRecordSets(input *route53.ChangeResourceRecordSetsInput) (*route53.ChangeResourceRecordSetsOutput, error) {
|
|
_, ok := r.zones[aws.StringValue(input.HostedZoneId)]
|
|
if !ok {
|
|
return nil, fmt.Errorf("Hosted zone doesn't exist: %s", aws.StringValue(input.HostedZoneId))
|
|
}
|
|
|
|
if len(input.ChangeBatch.Changes) == 0 {
|
|
return nil, fmt.Errorf("ChangeBatch doesn't contain any changes")
|
|
}
|
|
|
|
output := &route53.ChangeResourceRecordSetsOutput{}
|
|
recordSets, ok := r.recordSets[aws.StringValue(input.HostedZoneId)]
|
|
if !ok {
|
|
recordSets = make(map[string][]*route53.ResourceRecordSet)
|
|
}
|
|
|
|
for _, change := range input.ChangeBatch.Changes {
|
|
if aws.StringValue(change.ResourceRecordSet.Type) == route53.RRTypeA {
|
|
for _, rrs := range change.ResourceRecordSet.ResourceRecords {
|
|
if net.ParseIP(aws.StringValue(rrs.Value)) == nil {
|
|
return nil, fmt.Errorf("A records must point to IPs")
|
|
}
|
|
}
|
|
}
|
|
|
|
key := aws.StringValue(change.ResourceRecordSet.Name) + "::" + aws.StringValue(change.ResourceRecordSet.Type)
|
|
switch aws.StringValue(change.Action) {
|
|
case route53.ChangeActionCreate:
|
|
if _, found := recordSets[key]; found {
|
|
return nil, fmt.Errorf("Attempt to create duplicate rrset %s", key) // TODO: Return AWS errors with codes etc
|
|
}
|
|
recordSets[key] = append(recordSets[key], change.ResourceRecordSet)
|
|
case route53.ChangeActionDelete:
|
|
if _, found := recordSets[key]; !found {
|
|
return nil, fmt.Errorf("Attempt to delete non-existent rrset %s", key) // TODO: Check other fields too
|
|
}
|
|
delete(recordSets, key)
|
|
case route53.ChangeActionUpsert:
|
|
recordSets[key] = []*route53.ResourceRecordSet{change.ResourceRecordSet}
|
|
}
|
|
}
|
|
r.recordSets[aws.StringValue(input.HostedZoneId)] = recordSets
|
|
return output, nil // TODO: We should ideally return status etc, but we don't' use that yet.
|
|
}
|
|
|
|
func (r *Route53APIStub) ListHostedZonesPages(input *route53.ListHostedZonesInput, fn func(p *route53.ListHostedZonesOutput, lastPage bool) (shouldContinue bool)) error {
|
|
output := &route53.ListHostedZonesOutput{}
|
|
for _, zone := range r.zones {
|
|
output.HostedZones = append(output.HostedZones, zone)
|
|
}
|
|
lastPage := true
|
|
fn(output, lastPage)
|
|
return nil
|
|
}
|
|
|
|
func (r *Route53APIStub) ListHostedZonesByName(input *route53.ListHostedZonesByNameInput) (*route53.ListHostedZonesByNameOutput, error) {
|
|
output := &route53.ListHostedZonesByNameOutput{}
|
|
for _, zone := range r.zones {
|
|
if strings.Contains(*input.DNSName, aws.StringValue(zone.Name)) {
|
|
output.HostedZones = append(output.HostedZones, zone)
|
|
}
|
|
}
|
|
return output, nil
|
|
}
|
|
|
|
func (r *Route53APIStub) CreateHostedZone(input *route53.CreateHostedZoneInput) (*route53.CreateHostedZoneOutput, error) {
|
|
name := aws.StringValue(input.Name)
|
|
id := "/hostedzone/" + name
|
|
if _, ok := r.zones[id]; ok {
|
|
return nil, fmt.Errorf("Error creating hosted DNS zone: %s already exists", id)
|
|
}
|
|
r.zones[id] = &route53.HostedZone{
|
|
Id: aws.String(id),
|
|
Name: aws.String(name),
|
|
}
|
|
return &route53.CreateHostedZoneOutput{HostedZone: r.zones[id]}, nil
|
|
}
|
|
|
|
func (r *Route53APIStub) DeleteHostedZone(input *route53.DeleteHostedZoneInput) (*route53.DeleteHostedZoneOutput, error) {
|
|
if _, ok := r.zones[aws.StringValue(input.Id)]; !ok {
|
|
return nil, fmt.Errorf("Error deleting hosted DNS zone: %s does not exist", aws.StringValue(input.Id))
|
|
}
|
|
if len(r.recordSets[aws.StringValue(input.Id)]) > 0 {
|
|
return nil, fmt.Errorf("Error deleting hosted DNS zone: %s has resource records", aws.StringValue(input.Id))
|
|
}
|
|
delete(r.zones, aws.StringValue(input.Id))
|
|
return &route53.DeleteHostedZoneOutput{}, nil
|
|
}
|
|
|
|
func TestAWSZones(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
zones, err := provider.Zones()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(zones) != 1 {
|
|
t.Fatalf("expected %d zones, got %d", 1, len(zones))
|
|
}
|
|
|
|
zone := zones[0]
|
|
|
|
if zone != "ext-dns-test.teapot.zalan.do." {
|
|
t.Errorf("expected %s, got %s", "ext-dns-test.teapot.zalan.do.", zone)
|
|
}
|
|
}
|
|
|
|
func TestAWSZone(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
hostedZone, err := provider.CreateZone("list-ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
zone, err := provider.Zone("list-ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if aws.StringValue(zone.Id) != aws.StringValue(hostedZone.Id) {
|
|
t.Errorf("expected %s, got %s", aws.StringValue(hostedZone.Id), aws.StringValue(zone.Id))
|
|
}
|
|
|
|
if aws.StringValue(zone.Name) != "list-ext-dns-test.teapot.zalan.do." {
|
|
t.Errorf("expected %s, got %s", "list-ext-dns-test.teapot.zalan.do.", aws.StringValue(zone.Name))
|
|
}
|
|
}
|
|
|
|
func TestAWSCreateZone(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
zones, err := provider.Zones()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, z := range zones {
|
|
if z == "ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("ext-dns-test.teapot.zalan.do. should be there")
|
|
}
|
|
}
|
|
|
|
func TestAWSDeleteZone(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
zone, err := provider.CreateZone("ext-dns-test-2.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = provider.DeleteZone(aws.StringValue(zone.Id))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
zones, err := provider.Zones()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
for _, z := range zones {
|
|
if z == "ext-dns-test-2.teapot.zalan.do." {
|
|
t.Fatal("ext-dns-test-2.teapot.zalan.do.")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAWSRecords(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("list-ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "list-test.list-ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("list-ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("list-ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if len(records) != 1 {
|
|
t.Errorf("expected %d records, got %d", 1, len(records))
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "list-test.list-ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("list-test.list-ext-dns-test.teapot.zalan.do. should be there")
|
|
}
|
|
}
|
|
|
|
func TestAWSCreateRecords(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "create-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "create-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("create-test.ext-dns-test.teapot.zalan.do. should be there")
|
|
}
|
|
}
|
|
|
|
func TestAWSUpdateRecords(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
oldRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", oldRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
newRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "1.2.3.4"}}
|
|
|
|
err = provider.UpdateRecords("ext-dns-test.teapot.zalan.do.", newRecords, oldRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err := provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "1.2.3.4" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to 1.2.3.4")
|
|
}
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to 1.2.3.4")
|
|
}
|
|
}
|
|
|
|
func TestAWSDeleteRecords(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "delete-test.ext-dns-test.teapot.zalan.do.", Target: "20.153.88.175"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = provider.DeleteRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "delete-test.ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("delete-test.ext-dns-test.teapot.zalan.do. should be gone")
|
|
}
|
|
}
|
|
|
|
func TestAWSApply(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
updateRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", updateRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
deleteRecords := []*endpoint.Endpoint{{DNSName: "delete-test.ext-dns-test.teapot.zalan.do.", Target: "20.153.88.175"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", deleteRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
createRecords := []*endpoint.Endpoint{{DNSName: "create-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
updateNewRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "1.2.3.4"}}
|
|
|
|
changes := &plan.Changes{
|
|
Create: createRecords,
|
|
UpdateNew: updateNewRecords,
|
|
UpdateOld: updateRecords,
|
|
Delete: deleteRecords,
|
|
}
|
|
|
|
err = provider.ApplyChanges("ext-dns-test.teapot.zalan.do.", changes)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// create validation
|
|
|
|
records, err := provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "create-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("create-test.ext-dns-test.teapot.zalan.do. should be there")
|
|
}
|
|
|
|
// update validation
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "1.2.3.4" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to 1.2.3.4")
|
|
}
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to 1.2.3.4")
|
|
}
|
|
|
|
// delete validation
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "delete-test.ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("delete-test.ext-dns-test.teapot.zalan.do. should be gone")
|
|
}
|
|
}
|
|
|
|
func TestAWSApplyNoChanges(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = provider.ApplyChanges("ext-dns-test.teapot.zalan.do.", &plan.Changes{})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestAWSCreateRecordDryRun(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
provider.DryRun = true
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "create-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "create-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("create-test.ext-dns-test.teapot.zalan.do. should not be there")
|
|
}
|
|
}
|
|
|
|
func TestAWSUpdateRecordDryRun(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
oldRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", oldRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
provider.DryRun = true
|
|
|
|
newRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "1.2.3.4"}}
|
|
|
|
err = provider.UpdateRecords("ext-dns-test.teapot.zalan.do.", newRecords, oldRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err := provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "1.2.3.4" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should not point to 1.2.3.4")
|
|
}
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to 8.8.8.8")
|
|
}
|
|
}
|
|
|
|
func TestAWSDeleteRecordDryRun(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "delete-test.ext-dns-test.teapot.zalan.do.", Target: "20.153.88.175"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
provider.DryRun = true
|
|
|
|
err = provider.DeleteRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "delete-test.ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("delete-test.ext-dns-test.teapot.zalan.do. should not be gone")
|
|
}
|
|
}
|
|
|
|
func TestAWSApplyDryRun(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
updateRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", updateRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
deleteRecords := []*endpoint.Endpoint{{DNSName: "delete-test.ext-dns-test.teapot.zalan.do.", Target: "20.153.88.175"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", deleteRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
provider.DryRun = true
|
|
|
|
createRecords := []*endpoint.Endpoint{{DNSName: "create-test.ext-dns-test.teapot.zalan.do.", Target: "8.8.8.8"}}
|
|
updateNewRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "1.2.3.4"}}
|
|
|
|
changes := &plan.Changes{
|
|
Create: createRecords,
|
|
UpdateNew: updateNewRecords,
|
|
UpdateOld: updateRecords,
|
|
Delete: deleteRecords,
|
|
}
|
|
|
|
err = provider.ApplyChanges("ext-dns-test.teapot.zalan.do.", changes)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// create validation
|
|
|
|
records, err := provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "create-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("create-test.ext-dns-test.teapot.zalan.do. should not be there")
|
|
}
|
|
|
|
// update validation
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "1.2.3.4" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should not point to 1.2.3.4")
|
|
}
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "8.8.8.8" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to 8.8.8.8")
|
|
}
|
|
|
|
// delete validation
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "delete-test.ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("delete-test.ext-dns-test.teapot.zalan.do. should not be gone")
|
|
}
|
|
}
|
|
|
|
func TestAWSCreateRecordsCNAME(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "create-test.ext-dns-test.teapot.zalan.do.", Target: "foo.elb.amazonaws.com"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "create-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "foo.elb.amazonaws.com" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("create-test.ext-dns-test.teapot.zalan.do. should be there")
|
|
}
|
|
}
|
|
|
|
func TestAWSUpdateRecordsCNAME(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
oldRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "foo.elb.amazonaws.com"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", oldRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
newRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "bar.elb.amazonaws.com"}}
|
|
|
|
err = provider.UpdateRecords("ext-dns-test.teapot.zalan.do.", newRecords, oldRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err := provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "bar.elb.amazonaws.com" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to bar.elb.amazonaws.com")
|
|
}
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "foo.elb.amazonaws.com" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to bar.elb.amazonaws.com")
|
|
}
|
|
}
|
|
|
|
func TestAWSDeleteRecordsCNAME(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records := []*endpoint.Endpoint{{DNSName: "delete-test.ext-dns-test.teapot.zalan.do.", Target: "baz.elb.amazonaws.com"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = provider.DeleteRecords("ext-dns-test.teapot.zalan.do.", records)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
records, err = provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "delete-test.ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("delete-test.ext-dns-test.teapot.zalan.do. should be gone")
|
|
}
|
|
}
|
|
|
|
func TestAWSApplyCNAME(t *testing.T) {
|
|
provider := newAWSProvider(t, false)
|
|
|
|
_, err := provider.CreateZone("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
updateRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "foo.elb.amazonaws.com"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", updateRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
deleteRecords := []*endpoint.Endpoint{{DNSName: "delete-test.ext-dns-test.teapot.zalan.do.", Target: "baz.elb.amazonaws.com"}}
|
|
|
|
err = provider.CreateRecords("ext-dns-test.teapot.zalan.do.", deleteRecords)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
createRecords := []*endpoint.Endpoint{{DNSName: "create-test.ext-dns-test.teapot.zalan.do.", Target: "foo.elb.amazonaws.com"}}
|
|
updateNewRecords := []*endpoint.Endpoint{{DNSName: "update-test.ext-dns-test.teapot.zalan.do.", Target: "bar.elb.amazonaws.com"}}
|
|
|
|
changes := &plan.Changes{
|
|
Create: createRecords,
|
|
UpdateNew: updateNewRecords,
|
|
UpdateOld: updateRecords,
|
|
Delete: deleteRecords,
|
|
}
|
|
|
|
err = provider.ApplyChanges("ext-dns-test.teapot.zalan.do.", changes)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// create validation
|
|
|
|
records, err := provider.Records("ext-dns-test.teapot.zalan.do.")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "create-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "foo.elb.amazonaws.com" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("create-test.ext-dns-test.teapot.zalan.do. should be there")
|
|
}
|
|
|
|
// update validation
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "bar.elb.amazonaws.com" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to bar.elb.amazonaws.com")
|
|
}
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "update-test.ext-dns-test.teapot.zalan.do." {
|
|
if r.Target == "foo.elb.amazonaws.com" {
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("update-test.ext-dns-test.teapot.zalan.do. should point to bar.elb.amazonaws.com")
|
|
}
|
|
|
|
// delete validation
|
|
|
|
found = false
|
|
|
|
for _, r := range records {
|
|
if r.DNSName == "delete-test.ext-dns-test.teapot.zalan.do." {
|
|
found = true
|
|
}
|
|
}
|
|
|
|
if found {
|
|
t.Fatal("delete-test.ext-dns-test.teapot.zalan.do. should be gone")
|
|
}
|
|
}
|
|
|
|
func newAWSProvider(t *testing.T, dryRun bool) *AWSProvider {
|
|
client := NewRoute53APIStub()
|
|
|
|
return &AWSProvider{
|
|
Client: client,
|
|
DryRun: dryRun,
|
|
}
|
|
}
|