mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
* Endpoint.Target is now Endpoint.Targets. This is its own type representing mutliple targets for a single DNS name while adding some convenience for sorting and comparing * Made everything compile and tests run through with the new Endpoint.Targets * The ingress source can now properly handle multiple target ips per host * Added custom conflict resolver, to better understand how conflict resolution has to work for me * My custom conflict resolver behaves a bit different than the PerResource resolver, therefore I needed to modify the expected test result Removed unnecessary FIXME * The ingress source now creates CNAME endpoints with multiple targets to let the DNS provider decide how to handle multiple CNAME targets. This could be interesting for weighted targets etc. * Adopted the expected results to the new way we create endpoints for CNAMEs * Removed Add method from Targets since manipulating the slice through here is unnecessary complicated and doesn't deliver enough convenience * Reverted ConflictResolver to the original one. There is some discussing to do what the best way is to handle conflicts * Added missing documenting comment to IsLess of Targets * Added documenting comments to Targets,Targets.Same and NewTargets to clarify their intention and usage * Service source now also generates endpoints with multiple targets * Service and Ingress source now sort all Targets for every Endpoint to make order of Targets predictable * Endpoints generated by the Google Cloud DNS provider now also have sorted Targets to make order of Targets predictable * Modified provider dyn to be able to compile with multi target changes * Fixed small nitpicks, so my code is acceptable * Fixed merge method after updating to new Targets. Replacing '!=' with .Same of course needs a boolean negation * Tests for dyn provider now also use the new Targets instead of Target * Simplified extractServiceIps as implied by linki to make it more readable * ref: change service ClusterIP retrieval again * Added entry to CHANGELOG.md describing the new features contained in this PR
This commit is contained in:
parent
f5b0d93e91
commit
5d54849699
@ -1,5 +1,6 @@
|
||||
- DigitalOcean: DigitalOcean creates entries with host in them twice (#459) @njuettner
|
||||
- Bugfix: Retrive all DNSimple response pages (#468) @jbowes
|
||||
- external-dns does now provide support for multiple targets for A records. This is currently only supported by the Google Cloud DNS provider (#418) @dereulenspiegel
|
||||
- Graceful handling of misconfigure password for dyn provider (#470) @jvassev
|
||||
- Don't log sensitive data on start (#463) @jvassev
|
||||
- Google: Improve logging to help trace misconfigurations (#388) @stealthybox
|
||||
|
@ -48,25 +48,25 @@ func (p *mockProvider) ApplyChanges(changes *plan.Changes) error {
|
||||
}
|
||||
|
||||
for i := range changes.Create {
|
||||
if changes.Create[i].DNSName != p.ExpectChanges.Create[i].DNSName || changes.Create[i].Target != p.ExpectChanges.Create[i].Target {
|
||||
if changes.Create[i].DNSName != p.ExpectChanges.Create[i].DNSName || !changes.Create[i].Targets.Same(p.ExpectChanges.Create[i].Targets) {
|
||||
return errors.New("created record is wrong")
|
||||
}
|
||||
}
|
||||
|
||||
for i := range changes.UpdateNew {
|
||||
if changes.UpdateNew[i].DNSName != p.ExpectChanges.UpdateNew[i].DNSName || changes.UpdateNew[i].Target != p.ExpectChanges.UpdateNew[i].Target {
|
||||
if changes.UpdateNew[i].DNSName != p.ExpectChanges.UpdateNew[i].DNSName || !changes.UpdateNew[i].Targets.Same(p.ExpectChanges.UpdateNew[i].Targets) {
|
||||
return errors.New("delete record is wrong")
|
||||
}
|
||||
}
|
||||
|
||||
for i := range changes.UpdateOld {
|
||||
if changes.UpdateOld[i].DNSName != p.ExpectChanges.UpdateOld[i].DNSName || changes.UpdateOld[i].Target != p.ExpectChanges.UpdateOld[i].Target {
|
||||
if changes.UpdateOld[i].DNSName != p.ExpectChanges.UpdateOld[i].DNSName || !changes.UpdateOld[i].Targets.Same(p.ExpectChanges.UpdateOld[i].Targets) {
|
||||
return errors.New("delete record is wrong")
|
||||
}
|
||||
}
|
||||
|
||||
for i := range changes.Delete {
|
||||
if changes.Delete[i].DNSName != p.ExpectChanges.Delete[i].DNSName || changes.Delete[i].Target != p.ExpectChanges.Delete[i].Target {
|
||||
if changes.Delete[i].DNSName != p.ExpectChanges.Delete[i].DNSName || !changes.Delete[i].Targets.Same(p.ExpectChanges.Delete[i].Targets) {
|
||||
return errors.New("delete record is wrong")
|
||||
}
|
||||
}
|
||||
@ -91,11 +91,11 @@ func TestRunOnce(t *testing.T) {
|
||||
source.On("Endpoints").Return([]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record",
|
||||
Target: "1.2.3.4",
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "update-record",
|
||||
Target: "8.8.4.4",
|
||||
Targets: endpoint.Targets{"8.8.4.4"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
@ -104,25 +104,25 @@ func TestRunOnce(t *testing.T) {
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "update-record",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "delete-record",
|
||||
Target: "4.3.2.1",
|
||||
Targets: endpoint.Targets{"4.3.2.1"},
|
||||
},
|
||||
},
|
||||
&plan.Changes{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{DNSName: "create-record", Target: "1.2.3.4"},
|
||||
{DNSName: "create-record", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{DNSName: "update-record", Target: "8.8.4.4"},
|
||||
{DNSName: "update-record", Targets: endpoint.Targets{"8.8.4.4"}},
|
||||
},
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{DNSName: "update-record", Target: "8.8.8.8"},
|
||||
{DNSName: "update-record", Targets: endpoint.Targets{"8.8.8.8"}},
|
||||
},
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{DNSName: "delete-record", Target: "4.3.2.1"},
|
||||
{DNSName: "delete-record", Targets: endpoint.Targets{"4.3.2.1"}},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
@ -18,6 +18,7 @@ package endpoint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -38,12 +39,78 @@ func (ttl TTL) IsConfigured() bool {
|
||||
return ttl > 0
|
||||
}
|
||||
|
||||
// Targets is a representation of a list of targets for an endpoint.
|
||||
type Targets []string
|
||||
|
||||
// NewTargets is a convenience method to create a new Targets object from a vararg of strings
|
||||
func NewTargets(target ...string) Targets {
|
||||
t := make(Targets, 0, len(target))
|
||||
t = append(t, target...)
|
||||
return t
|
||||
}
|
||||
|
||||
func (t Targets) String() string {
|
||||
return strings.Join(t, ";")
|
||||
}
|
||||
|
||||
func (t Targets) Len() int {
|
||||
return len(t)
|
||||
}
|
||||
|
||||
func (t Targets) Less(i, j int) bool {
|
||||
return t[i] < t[j]
|
||||
}
|
||||
|
||||
func (t Targets) Swap(i, j int) {
|
||||
t[i], t[j] = t[j], t[i]
|
||||
}
|
||||
|
||||
// Same compares to Targets and returns true if they are completely identical
|
||||
func (t Targets) Same(o Targets) bool {
|
||||
if len(t) != len(o) {
|
||||
return false
|
||||
}
|
||||
sort.Stable(t)
|
||||
sort.Stable(o)
|
||||
|
||||
for i, e := range t {
|
||||
if e != o[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsLess should fulfill the requirement to compare two targets and chosse the 'lesser' one.
|
||||
// In the past target was a simple string so simple string comparison could be used. Now we define 'less'
|
||||
// as either being the shorter list of targets or where the first entry is less.
|
||||
// FIXME We really need to define under which circumstances a list Targets is considered 'less'
|
||||
// than another.
|
||||
func (t Targets) IsLess(o Targets) bool {
|
||||
if len(t) < len(o) {
|
||||
return true
|
||||
}
|
||||
if len(t) > len(o) {
|
||||
return false
|
||||
}
|
||||
|
||||
sort.Sort(t)
|
||||
sort.Sort(o)
|
||||
|
||||
for i, e := range t {
|
||||
if e != o[i] {
|
||||
return e < o[i]
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Endpoint is a high-level way of a connection between a service and an IP
|
||||
type Endpoint struct {
|
||||
// The hostname of the DNS record
|
||||
DNSName string
|
||||
// The target the DNS record points to
|
||||
Target string
|
||||
// The targets the DNS record points to
|
||||
Targets Targets
|
||||
// RecordType type of record, e.g. CNAME, A, TXT etc
|
||||
RecordType string
|
||||
// TTL for the record
|
||||
@ -61,7 +128,7 @@ func NewEndpoint(dnsName, target, recordType string) *Endpoint {
|
||||
func NewEndpointWithTTL(dnsName, target, recordType string, ttl TTL) *Endpoint {
|
||||
return &Endpoint{
|
||||
DNSName: strings.TrimSuffix(dnsName, "."),
|
||||
Target: strings.TrimSuffix(target, "."),
|
||||
Targets: Targets{strings.TrimSuffix(target, ".")},
|
||||
RecordType: recordType,
|
||||
Labels: NewLabels(),
|
||||
RecordTTL: ttl,
|
||||
@ -69,5 +136,5 @@ func NewEndpointWithTTL(dnsName, target, recordType string, ttl TTL) *Endpoint {
|
||||
}
|
||||
|
||||
func (e *Endpoint) String() string {
|
||||
return fmt.Sprintf("%s %d IN %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Target)
|
||||
return fmt.Sprintf("%s %d IN %s %s", e.DNSName, e.RecordTTL, e.RecordType, e.Targets)
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
|
||||
func TestNewEndpoint(t *testing.T) {
|
||||
e := NewEndpoint("example.org", "foo.com", "CNAME")
|
||||
if e.DNSName != "example.org" || e.Target != "foo.com" || e.RecordType != "CNAME" {
|
||||
if e.DNSName != "example.org" || e.Targets[0] != "foo.com" || e.RecordType != "CNAME" {
|
||||
t.Error("endpoint is not initialized correctly")
|
||||
}
|
||||
if e.Labels == nil {
|
||||
@ -30,7 +30,7 @@ func TestNewEndpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
w := NewEndpoint("example.org.", "load-balancer.com.", "")
|
||||
if w.DNSName != "example.org" || w.Target != "load-balancer.com" || w.RecordType != "" {
|
||||
if w.DNSName != "example.org" || w.Targets[0] != "load-balancer.com" || w.RecordType != "" {
|
||||
t.Error("endpoint is not initialized correctly")
|
||||
}
|
||||
}
|
||||
|
@ -33,13 +33,12 @@ func (b byAllFields) Less(i, j int) bool {
|
||||
return true
|
||||
}
|
||||
if b[i].DNSName == b[j].DNSName {
|
||||
if b[i].Target < b[j].Target {
|
||||
return true
|
||||
}
|
||||
if b[i].Target == b[j].Target {
|
||||
// This rather bad, we need a more complex comparison for Targets, which considers all elements
|
||||
if b[i].Targets.Same(b[j].Targets) {
|
||||
return b[i].RecordType <= b[j].RecordType
|
||||
}
|
||||
return false
|
||||
return b[i].Targets.String() <= b[j].Targets.String()
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -47,7 +46,7 @@ func (b byAllFields) Less(i, j int) bool {
|
||||
// SameEndpoint returns true if two endpoints are same
|
||||
// considers example.org. and example.org DNSName/Target as different endpoints
|
||||
func SameEndpoint(a, b *endpoint.Endpoint) bool {
|
||||
return a.DNSName == b.DNSName && a.Target == b.Target && a.RecordType == b.RecordType &&
|
||||
return a.DNSName == b.DNSName && a.Targets.Same(b.Targets) && a.RecordType == b.RecordType &&
|
||||
a.Labels[endpoint.OwnerLabelKey] == b.Labels[endpoint.OwnerLabelKey] && a.RecordTTL == b.RecordTTL &&
|
||||
a.Labels[endpoint.ResourceLabelKey] == b.Labels[endpoint.ResourceLabelKey]
|
||||
}
|
||||
|
@ -27,31 +27,31 @@ func ExampleSameEndpoints() {
|
||||
eps := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "load-balancer.org",
|
||||
Targets: endpoint.Targets{"load-balancer.org"},
|
||||
},
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "load-balancer.org",
|
||||
Targets: endpoint.Targets{"load-balancer.org"},
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
},
|
||||
{
|
||||
DNSName: "abc.com",
|
||||
Target: "something",
|
||||
Targets: endpoint.Targets{"something"},
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
},
|
||||
{
|
||||
DNSName: "abc.com",
|
||||
Target: "1.2.3.4",
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
{
|
||||
DNSName: "bbc.com",
|
||||
Target: "foo.com",
|
||||
Targets: endpoint.Targets{"foo.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "cbc.com",
|
||||
Target: "foo.com",
|
||||
Targets: endpoint.Targets{"foo.com"},
|
||||
RecordType: "CNAME",
|
||||
RecordTTL: endpoint.TTL(60),
|
||||
},
|
||||
|
@ -64,7 +64,7 @@ func (s PerResource) ResolveUpdate(current *endpoint.Endpoint, candidates []*end
|
||||
|
||||
// less returns true if endpoint x is less than y
|
||||
func (s PerResource) less(x, y *endpoint.Endpoint) bool {
|
||||
return x.Target < y.Target
|
||||
return x.Targets.IsLess(y.Targets)
|
||||
}
|
||||
|
||||
// TODO: with cross-resource/cross-cluster setup alternative variations of ConflictResolver can be used
|
||||
|
@ -45,7 +45,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
// initialize endpoints used in tests
|
||||
suite.fooV1Cname = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "v1",
|
||||
Targets: endpoint.Targets{"v1"},
|
||||
RecordType: "CNAME",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-v1",
|
||||
@ -53,7 +53,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.fooV2Cname = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "v2",
|
||||
Targets: endpoint.Targets{"v2"},
|
||||
RecordType: "CNAME",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-v2",
|
||||
@ -61,7 +61,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.fooV2CnameDuplicate = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "v2",
|
||||
Targets: endpoint.Targets{"v2"},
|
||||
RecordType: "CNAME",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-v2-duplicate",
|
||||
@ -69,7 +69,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.fooA5 = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "5.5.5.5",
|
||||
Targets: endpoint.Targets{"5.5.5.5"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-5",
|
||||
@ -77,7 +77,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.bar127A = &endpoint.Endpoint{
|
||||
DNSName: "bar",
|
||||
Target: "127.0.0.1",
|
||||
Targets: endpoint.Targets{"127.0.0.1"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/bar-127",
|
||||
@ -85,7 +85,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.bar127AAnother = &endpoint.Endpoint{ //TODO: remove this once we move to multiple targets under same endpoint
|
||||
DNSName: "bar",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/bar-127",
|
||||
@ -93,7 +93,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.bar192A = &endpoint.Endpoint{
|
||||
DNSName: "bar",
|
||||
Target: "192.168.0.1",
|
||||
Targets: endpoint.Targets{"192.168.0.1"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/bar-192",
|
||||
@ -101,7 +101,7 @@ func (suite *ResolverSuite) SetupTest() {
|
||||
}
|
||||
suite.legacyBar192A = &endpoint.Endpoint{
|
||||
DNSName: "bar",
|
||||
Target: "192.168.0.1",
|
||||
Targets: endpoint.Targets{"192.168.0.1"},
|
||||
RecordType: "A",
|
||||
}
|
||||
}
|
||||
@ -120,7 +120,7 @@ func (suite *ResolverSuite) TestStrictResolver() {
|
||||
// should actually get the updated record (note ttl is different)
|
||||
newFooV1Cname := &endpoint.Endpoint{
|
||||
DNSName: suite.fooV1Cname.DNSName,
|
||||
Target: suite.fooV1Cname.Target,
|
||||
Targets: suite.fooV1Cname.Targets,
|
||||
Labels: suite.fooV1Cname.Labels,
|
||||
RecordType: suite.fooV1Cname.RecordType,
|
||||
RecordTTL: suite.fooV1Cname.RecordTTL + 1, // ttl is different
|
||||
|
@ -166,7 +166,7 @@ func inheritOwner(from, to *endpoint.Endpoint) {
|
||||
}
|
||||
|
||||
func targetChanged(desired, current *endpoint.Endpoint) bool {
|
||||
return desired.Target != current.Target
|
||||
return !desired.Targets.Same(current.Targets)
|
||||
}
|
||||
|
||||
func shouldUpdateTTL(desired, current *endpoint.Endpoint) bool {
|
||||
|
@ -39,7 +39,7 @@ type PlanTestSuite struct {
|
||||
func (suite *PlanTestSuite) SetupTest() {
|
||||
suite.fooV1Cname = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "v1",
|
||||
Targets: endpoint.Targets{"v1"},
|
||||
RecordType: "CNAME",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-v1",
|
||||
@ -49,7 +49,7 @@ func (suite *PlanTestSuite) SetupTest() {
|
||||
// same resource as fooV1Cname, but target is different. It will never be picked because its target lexicographically bigger than "v1"
|
||||
suite.fooV3CnameSameResource = &endpoint.Endpoint{ // TODO: remove this once endpoint can support multiple targets
|
||||
DNSName: "foo",
|
||||
Target: "v3",
|
||||
Targets: endpoint.Targets{"v3"},
|
||||
RecordType: "CNAME",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-v1",
|
||||
@ -58,7 +58,7 @@ func (suite *PlanTestSuite) SetupTest() {
|
||||
}
|
||||
suite.fooV2Cname = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "v2",
|
||||
Targets: endpoint.Targets{"v2"},
|
||||
RecordType: "CNAME",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-v2",
|
||||
@ -66,12 +66,12 @@ func (suite *PlanTestSuite) SetupTest() {
|
||||
}
|
||||
suite.fooV2CnameNoLabel = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "v2",
|
||||
Targets: endpoint.Targets{"v2"},
|
||||
RecordType: "CNAME",
|
||||
}
|
||||
suite.fooA5 = &endpoint.Endpoint{
|
||||
DNSName: "foo",
|
||||
Target: "5.5.5.5",
|
||||
Targets: endpoint.Targets{"5.5.5.5"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/foo-5",
|
||||
@ -79,7 +79,7 @@ func (suite *PlanTestSuite) SetupTest() {
|
||||
}
|
||||
suite.bar127A = &endpoint.Endpoint{
|
||||
DNSName: "bar",
|
||||
Target: "127.0.0.1",
|
||||
Targets: endpoint.Targets{"127.0.0.1"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/bar-127",
|
||||
@ -87,7 +87,7 @@ func (suite *PlanTestSuite) SetupTest() {
|
||||
}
|
||||
suite.bar127AWithTTL = &endpoint.Endpoint{
|
||||
DNSName: "bar",
|
||||
Target: "127.0.0.1",
|
||||
Targets: endpoint.Targets{"127.0.0.1"},
|
||||
RecordType: "A",
|
||||
RecordTTL: 300,
|
||||
Labels: map[string]string{
|
||||
@ -96,7 +96,7 @@ func (suite *PlanTestSuite) SetupTest() {
|
||||
}
|
||||
suite.bar192A = &endpoint.Endpoint{
|
||||
DNSName: "bar",
|
||||
Target: "192.168.0.1",
|
||||
Targets: endpoint.Targets{"192.168.0.1"},
|
||||
RecordType: "A",
|
||||
Labels: map[string]string{
|
||||
endpoint.ResourceLabelKey: "ingress/default/bar-192",
|
||||
@ -196,7 +196,7 @@ func (suite *PlanTestSuite) TestSyncSecondRoundWithOwnerInherited() {
|
||||
expectedUpdateOld := []*endpoint.Endpoint{suite.fooV1Cname}
|
||||
expectedUpdateNew := []*endpoint.Endpoint{{
|
||||
DNSName: suite.fooV2Cname.DNSName,
|
||||
Target: suite.fooV2Cname.Target,
|
||||
Targets: suite.fooV2Cname.Targets,
|
||||
RecordType: suite.fooV2Cname.RecordType,
|
||||
RecordTTL: suite.fooV2Cname.RecordTTL,
|
||||
Labels: map[string]string{
|
||||
|
@ -28,12 +28,12 @@ func TestApply(t *testing.T) {
|
||||
// empty list of records
|
||||
empty := []*endpoint.Endpoint{}
|
||||
// a simple entry
|
||||
fooV1 := []*endpoint.Endpoint{{DNSName: "foo", Target: "v1"}}
|
||||
fooV1 := []*endpoint.Endpoint{{DNSName: "foo", Targets: endpoint.Targets{"v1"}}}
|
||||
// the same entry but with different target
|
||||
fooV2 := []*endpoint.Endpoint{{DNSName: "foo", Target: "v2"}}
|
||||
fooV2 := []*endpoint.Endpoint{{DNSName: "foo", Targets: endpoint.Targets{"v2"}}}
|
||||
// another two simple entries
|
||||
bar := []*endpoint.Endpoint{{DNSName: "bar", Target: "v1"}}
|
||||
baz := []*endpoint.Endpoint{{DNSName: "baz", Target: "v1"}}
|
||||
bar := []*endpoint.Endpoint{{DNSName: "bar", Targets: endpoint.Targets{"v1"}}}
|
||||
baz := []*endpoint.Endpoint{{DNSName: "baz", Targets: endpoint.Targets{"v1"}}}
|
||||
|
||||
for _, tc := range []struct {
|
||||
policy Policy
|
||||
|
@ -378,8 +378,8 @@ func newChange(action string, endpoint *endpoint.Endpoint) *route53.Change {
|
||||
if isAWSLoadBalancer(endpoint) {
|
||||
change.ResourceRecordSet.Type = aws.String(route53.RRTypeA)
|
||||
change.ResourceRecordSet.AliasTarget = &route53.AliasTarget{
|
||||
DNSName: aws.String(endpoint.Target),
|
||||
HostedZoneId: aws.String(canonicalHostedZone(endpoint.Target)),
|
||||
DNSName: aws.String(endpoint.Targets[0]),
|
||||
HostedZoneId: aws.String(canonicalHostedZone(endpoint.Targets[0])),
|
||||
EvaluateTargetHealth: aws.Bool(evaluateTargetHealth),
|
||||
}
|
||||
} else {
|
||||
@ -391,7 +391,7 @@ func newChange(action string, endpoint *endpoint.Endpoint) *route53.Change {
|
||||
}
|
||||
change.ResourceRecordSet.ResourceRecords = []*route53.ResourceRecord{
|
||||
{
|
||||
Value: aws.String(endpoint.Target),
|
||||
Value: aws.String(endpoint.Targets[0]),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -429,7 +429,7 @@ func suitableZones(hostname string, zones map[string]*route53.HostedZone) []*rou
|
||||
// isAWSLoadBalancer determines if a given hostname belongs to an AWS load balancer.
|
||||
func isAWSLoadBalancer(ep *endpoint.Endpoint) bool {
|
||||
if ep.RecordType == endpoint.RecordTypeCNAME {
|
||||
return canonicalHostedZone(ep.Target) != ""
|
||||
return canonicalHostedZone(ep.Targets[0]) != ""
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -630,7 +630,7 @@ func TestAWSCreateRecordsWithCNAME(t *testing.T) {
|
||||
provider := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), false, []*endpoint.Endpoint{})
|
||||
|
||||
records := []*endpoint.Endpoint{
|
||||
{DNSName: "create-test.zone-1.ext-dns-test-2.teapot.zalan.do", Target: "foo.example.org", RecordType: endpoint.RecordTypeCNAME},
|
||||
{DNSName: "create-test.zone-1.ext-dns-test-2.teapot.zalan.do", Targets: endpoint.Targets{"foo.example.org"}, RecordType: endpoint.RecordTypeCNAME},
|
||||
}
|
||||
|
||||
require.NoError(t, provider.CreateRecords(records))
|
||||
@ -655,7 +655,7 @@ func TestAWSCreateRecordsWithALIAS(t *testing.T) {
|
||||
provider := newAWSProvider(t, NewDomainFilter([]string{"ext-dns-test-2.teapot.zalan.do."}), NewZoneIDFilter([]string{}), NewZoneTypeFilter(""), false, []*endpoint.Endpoint{})
|
||||
|
||||
records := []*endpoint.Endpoint{
|
||||
{DNSName: "create-test.zone-1.ext-dns-test-2.teapot.zalan.do", Target: "foo.eu-central-1.elb.amazonaws.com", RecordType: endpoint.RecordTypeCNAME},
|
||||
{DNSName: "create-test.zone-1.ext-dns-test-2.teapot.zalan.do", Targets: endpoint.Targets{"foo.eu-central-1.elb.amazonaws.com"}, RecordType: endpoint.RecordTypeCNAME},
|
||||
}
|
||||
|
||||
require.NoError(t, provider.CreateRecords(records))
|
||||
@ -685,7 +685,7 @@ func TestAWSisLoadBalancer(t *testing.T) {
|
||||
{"foo.example.org", endpoint.RecordTypeCNAME, false},
|
||||
} {
|
||||
ep := &endpoint.Endpoint{
|
||||
Target: tc.target,
|
||||
Targets: endpoint.Targets{tc.target},
|
||||
RecordType: tc.recordType,
|
||||
}
|
||||
assert.Equal(t, tc.expected, isAWSLoadBalancer(ep))
|
||||
|
@ -163,7 +163,7 @@ func (p *AzureProvider) Records() (endpoints []*endpoint.Endpoint, _ error) {
|
||||
"Found %s record for '%s' with target '%s'.",
|
||||
ep.RecordType,
|
||||
ep.DNSName,
|
||||
ep.Target,
|
||||
ep.Targets,
|
||||
)
|
||||
endpoints = append(endpoints, ep)
|
||||
return true
|
||||
@ -323,7 +323,7 @@ func (p *AzureProvider) updateRecords(updated azureChangeMap) {
|
||||
"Would update %s record named '%s' to '%s' for Azure DNS zone '%s'.",
|
||||
endpoint.RecordType,
|
||||
name,
|
||||
endpoint.Target,
|
||||
endpoint.Targets,
|
||||
zone,
|
||||
)
|
||||
continue
|
||||
@ -333,7 +333,7 @@ func (p *AzureProvider) updateRecords(updated azureChangeMap) {
|
||||
"Updating %s record named '%s' to '%s' for Azure DNS zone '%s'.",
|
||||
endpoint.RecordType,
|
||||
name,
|
||||
endpoint.Target,
|
||||
endpoint.Targets,
|
||||
zone,
|
||||
)
|
||||
|
||||
@ -354,7 +354,7 @@ func (p *AzureProvider) updateRecords(updated azureChangeMap) {
|
||||
"Failed to update %s record named '%s' to '%s' for DNS zone '%s': %v",
|
||||
endpoint.RecordType,
|
||||
name,
|
||||
endpoint.Target,
|
||||
endpoint.Targets,
|
||||
zone,
|
||||
err,
|
||||
)
|
||||
@ -388,7 +388,7 @@ func (p *AzureProvider) newRecordSet(endpoint *endpoint.Endpoint) (dns.RecordSet
|
||||
TTL: to.Int64Ptr(ttl),
|
||||
ARecords: &[]dns.ARecord{
|
||||
{
|
||||
Ipv4Address: to.StringPtr(endpoint.Target),
|
||||
Ipv4Address: to.StringPtr(endpoint.Targets[0]),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -398,7 +398,7 @@ func (p *AzureProvider) newRecordSet(endpoint *endpoint.Endpoint) (dns.RecordSet
|
||||
RecordSetProperties: &dns.RecordSetProperties{
|
||||
TTL: to.Int64Ptr(ttl),
|
||||
CnameRecord: &dns.CnameRecord{
|
||||
Cname: to.StringPtr(endpoint.Target),
|
||||
Cname: to.StringPtr(endpoint.Targets[0]),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
@ -409,7 +409,7 @@ func (p *AzureProvider) newRecordSet(endpoint *endpoint.Endpoint) (dns.RecordSet
|
||||
TxtRecords: &[]dns.TxtRecord{
|
||||
{
|
||||
Value: &[]string{
|
||||
endpoint.Target,
|
||||
endpoint.Targets[0],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -290,7 +290,7 @@ func newCloudFlareChange(action string, endpoint *endpoint.Endpoint, proxied boo
|
||||
TTL: 1,
|
||||
Proxied: proxied,
|
||||
Type: endpoint.RecordType,
|
||||
Content: endpoint.Target,
|
||||
Content: endpoint.Targets[0],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudflare/cloudflare-go"
|
||||
|
||||
"github.com/kubernetes-incubator/external-dns/endpoint"
|
||||
"github.com/kubernetes-incubator/external-dns/plan"
|
||||
|
||||
cloudflare "github.com/cloudflare/cloudflare-go"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -336,12 +336,12 @@ func (m *mockCloudFlareUpdateRecordsFail) ListZones(zoneID ...string) ([]cloudfl
|
||||
}
|
||||
|
||||
func TestNewCloudFlareChanges(t *testing.T) {
|
||||
endpoints := []*endpoint.Endpoint{{DNSName: "new", Target: "target"}}
|
||||
endpoints := []*endpoint.Endpoint{{DNSName: "new", Targets: endpoint.Targets{"target"}}}
|
||||
newCloudFlareChanges(cloudFlareCreate, endpoints, true)
|
||||
}
|
||||
|
||||
func TestNewCloudFlareChangeNoProxied(t *testing.T) {
|
||||
change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: "A", Target: "target"}, false)
|
||||
change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: "A", Targets: endpoint.Targets{"target"}}, false)
|
||||
assert.False(t, change.ResourceRecordSet.Proxied)
|
||||
}
|
||||
|
||||
@ -361,7 +361,7 @@ func TestNewCloudFlareChangeProxiable(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, cloudFlareType := range cloudFlareTypes {
|
||||
change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: cloudFlareType.recordType, Target: "target"}, true)
|
||||
change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "new", RecordType: cloudFlareType.recordType, Targets: endpoint.Targets{"target"}}, true)
|
||||
|
||||
if cloudFlareType.proxiable {
|
||||
assert.True(t, change.ResourceRecordSet.Proxied)
|
||||
@ -370,7 +370,7 @@ func TestNewCloudFlareChangeProxiable(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "*.foo", RecordType: "A", Target: "target"}, true)
|
||||
change := newCloudFlareChange(cloudFlareCreate, &endpoint.Endpoint{DNSName: "*.foo", RecordType: "A", Targets: endpoint.Targets{"target"}}, true)
|
||||
assert.False(t, change.ResourceRecordSet.Proxied)
|
||||
}
|
||||
|
||||
@ -433,10 +433,10 @@ func TestApplyChanges(t *testing.T) {
|
||||
provider := &CloudFlareProvider{
|
||||
Client: &mockCloudFlareClient{},
|
||||
}
|
||||
changes.Create = []*endpoint.Endpoint{{DNSName: "new.ext-dns-test.zalando.to.", Target: "target"}, {DNSName: "new.ext-dns-test.unrelated.to.", Target: "target"}}
|
||||
changes.Delete = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.zalando.to.", Target: "target"}}
|
||||
changes.UpdateOld = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.zalando.to.", Target: "target-old"}}
|
||||
changes.UpdateNew = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.zalando.to.", Target: "target-new"}}
|
||||
changes.Create = []*endpoint.Endpoint{{DNSName: "new.ext-dns-test.zalando.to.", Targets: endpoint.Targets{"target"}}, {DNSName: "new.ext-dns-test.unrelated.to.", Targets: endpoint.Targets{"target"}}}
|
||||
changes.Delete = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.zalando.to.", Targets: endpoint.Targets{"target"}}}
|
||||
changes.UpdateOld = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.zalando.to.", Targets: endpoint.Targets{"target-old"}}}
|
||||
changes.UpdateNew = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.zalando.to.", Targets: endpoint.Targets{"target-new"}}}
|
||||
err := provider.ApplyChanges(changes)
|
||||
if err != nil {
|
||||
t.Errorf("should not fail, %s", err)
|
||||
|
@ -260,7 +260,7 @@ func newDigitalOceanChange(action string, endpoint *endpoint.Endpoint) *DigitalO
|
||||
ResourceRecordSet: godo.DomainRecord{
|
||||
Name: endpoint.DNSName,
|
||||
Type: endpoint.RecordType,
|
||||
Data: endpoint.Target,
|
||||
Data: endpoint.Targets[0],
|
||||
},
|
||||
}
|
||||
return change
|
||||
|
@ -400,7 +400,7 @@ func (m *mockDigitalOceanCreateRecordsFail) Records(ctx context.Context, domain
|
||||
|
||||
func TestNewDigitalOceanChanges(t *testing.T) {
|
||||
action := DigitalOceanCreate
|
||||
endpoints := []*endpoint.Endpoint{{DNSName: "new", Target: "target"}}
|
||||
endpoints := []*endpoint.Endpoint{{DNSName: "new", Targets: endpoint.Targets{"target"}}}
|
||||
_ = newDigitalOceanChanges(action, endpoints)
|
||||
}
|
||||
|
||||
@ -425,10 +425,10 @@ func TestDigitalOceanApplyChanges(t *testing.T) {
|
||||
provider := &DigitalOceanProvider{
|
||||
Client: &mockDigitalOceanClient{},
|
||||
}
|
||||
changes.Create = []*endpoint.Endpoint{{DNSName: "new.ext-dns-test.bar.com", Target: "target"}, {DNSName: "new.ext-dns-test.unexpected.com", Target: "target"}}
|
||||
changes.Delete = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.bar.com", Target: "target"}}
|
||||
changes.UpdateOld = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.bar.de", Target: "target-old"}}
|
||||
changes.UpdateNew = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.foo.com", Target: "target-new"}}
|
||||
changes.Create = []*endpoint.Endpoint{{DNSName: "new.ext-dns-test.bar.com", Targets: endpoint.Targets{"target"}}, {DNSName: "new.ext-dns-test.unexpected.com", Targets: endpoint.Targets{"target"}}}
|
||||
changes.Delete = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.bar.com", Targets: endpoint.Targets{"target"}}}
|
||||
changes.UpdateOld = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.bar.de", Targets: endpoint.Targets{"target-old"}}}
|
||||
changes.UpdateNew = []*endpoint.Endpoint{{DNSName: "foobar.ext-dns-test.foo.com", Targets: endpoint.Targets{"target-new"}}}
|
||||
err := provider.ApplyChanges(changes)
|
||||
if err != nil {
|
||||
t.Errorf("should not fail, %s", err)
|
||||
|
@ -192,7 +192,7 @@ func newDnsimpleChange(action string, e *endpoint.Endpoint) *dnsimpleChange {
|
||||
ResourceRecordSet: dnsimple.ZoneRecord{
|
||||
Name: e.DNSName,
|
||||
Type: e.RecordType,
|
||||
Content: e.Target,
|
||||
Content: e.Targets[0],
|
||||
},
|
||||
}
|
||||
return change
|
||||
|
@ -138,9 +138,9 @@ func testDnsimpleProviderRecords(t *testing.T) {
|
||||
}
|
||||
func testDnsimpleProviderApplyChanges(t *testing.T) {
|
||||
changes := &plan.Changes{}
|
||||
changes.Create = []*endpoint.Endpoint{{DNSName: "example.example.com", Target: "target", RecordType: endpoint.RecordTypeCNAME}}
|
||||
changes.Delete = []*endpoint.Endpoint{{DNSName: "example-beta.example.com", Target: "127.0.0.1", RecordType: endpoint.RecordTypeA}}
|
||||
changes.UpdateNew = []*endpoint.Endpoint{{DNSName: "example.example.com", Target: "target", RecordType: endpoint.RecordTypeCNAME}}
|
||||
changes.Create = []*endpoint.Endpoint{{DNSName: "example.example.com", Targets: endpoint.Targets{"target"}, RecordType: endpoint.RecordTypeCNAME}}
|
||||
changes.Delete = []*endpoint.Endpoint{{DNSName: "example-beta.example.com", Targets: endpoint.Targets{"127.0.0.1"}, RecordType: endpoint.RecordTypeA}}
|
||||
changes.UpdateNew = []*endpoint.Endpoint{{DNSName: "example.example.com", Targets: endpoint.Targets{"target"}, RecordType: endpoint.RecordTypeCNAME}}
|
||||
|
||||
mockProvider.accountID = "1"
|
||||
err := mockProvider.ApplyChanges(changes)
|
||||
|
@ -214,7 +214,7 @@ func merge(updateOld, updateNew []*endpoint.Endpoint) []*endpoint.Endpoint {
|
||||
continue
|
||||
}
|
||||
|
||||
if matchingNew.Target != old.Target {
|
||||
if !matchingNew.Targets.Same(old.Targets) {
|
||||
// new target: always update, TTL will be overwritten too if necessary
|
||||
result = append(result, matchingNew)
|
||||
continue
|
||||
@ -275,7 +275,7 @@ func (d *dynProviderState) recordLinkToEndpoint(client *dynect.Client, recordLin
|
||||
DNSName: rec.Data.FQDN,
|
||||
RecordTTL: endpoint.TTL(rec.Data.TTL),
|
||||
RecordType: rec.Data.RecordType,
|
||||
Target: target,
|
||||
Targets: endpoint.Targets{target},
|
||||
}
|
||||
|
||||
log.Debugf("Fetched new endpoint for %s: %+v", recordLink, result)
|
||||
@ -297,11 +297,11 @@ func endpointToRecord(ep *endpoint.Endpoint) *dynect.DataBlock {
|
||||
result := dynect.DataBlock{}
|
||||
|
||||
if ep.RecordType == endpoint.RecordTypeA {
|
||||
result.Address = ep.Target
|
||||
result.Address = ep.Targets[0]
|
||||
} else if ep.RecordType == endpoint.RecordTypeCNAME {
|
||||
result.CName = ep.Target
|
||||
result.CName = ep.Targets[0]
|
||||
} else if ep.RecordType == endpoint.RecordTypeTXT {
|
||||
result.TxtData = ep.Target
|
||||
result.TxtData = ep.Targets[0]
|
||||
}
|
||||
|
||||
return &result
|
||||
|
@ -32,13 +32,13 @@ func TestDynMerge_NoUpdateOnTTL0Changes(t *testing.T) {
|
||||
updateOld := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
@ -47,13 +47,13 @@ func TestDynMerge_NoUpdateOnTTL0Changes(t *testing.T) {
|
||||
updateNew := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(0),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(0),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -66,13 +66,13 @@ func TestDynMerge_UpdateOnTTLChanges(t *testing.T) {
|
||||
updateOld := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -81,13 +81,13 @@ func TestDynMerge_UpdateOnTTLChanges(t *testing.T) {
|
||||
updateNew := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(77),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(10),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -102,13 +102,13 @@ func TestDynMerge_AlwaysUpdateTarget(t *testing.T) {
|
||||
updateOld := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -117,13 +117,13 @@ func TestDynMerge_AlwaysUpdateTarget(t *testing.T) {
|
||||
updateNew := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1-changed",
|
||||
Targets: endpoint.Targets{"target1-changed"},
|
||||
RecordTTL: endpoint.TTL(0),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(0),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -131,20 +131,20 @@ func TestDynMerge_AlwaysUpdateTarget(t *testing.T) {
|
||||
|
||||
merged := merge(updateOld, updateNew)
|
||||
assert.Equal(t, 1, len(merged))
|
||||
assert.Equal(t, "target1-changed", merged[0].Target)
|
||||
assert.Equal(t, "target1-changed", merged[0].Targets[0])
|
||||
}
|
||||
|
||||
func TestDynMerge_NoUpdateIfTTLUnchanged(t *testing.T) {
|
||||
updateOld := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(55),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(55),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -153,13 +153,13 @@ func TestDynMerge_NoUpdateIfTTLUnchanged(t *testing.T) {
|
||||
updateNew := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "name1",
|
||||
Target: "target1",
|
||||
Targets: endpoint.Targets{"target1"},
|
||||
RecordTTL: endpoint.TTL(55),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "name2",
|
||||
Target: "target2",
|
||||
Targets: endpoint.Targets{"target2"},
|
||||
RecordTTL: endpoint.TTL(55),
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
@ -271,7 +271,7 @@ func TestDyn_cachePut(t *testing.T) {
|
||||
|
||||
c.Put("link", &endpoint.Endpoint{
|
||||
DNSName: "name",
|
||||
Target: "target",
|
||||
Targets: endpoint.Targets{"target"},
|
||||
RecordTTL: endpoint.TTL(10000),
|
||||
RecordType: "A",
|
||||
})
|
||||
@ -287,7 +287,7 @@ func TestDyn_cachePutExpired(t *testing.T) {
|
||||
|
||||
c.Put("link", &endpoint.Endpoint{
|
||||
DNSName: "name",
|
||||
Target: "target",
|
||||
Targets: endpoint.Targets{"target"},
|
||||
RecordTTL: endpoint.TTL(0),
|
||||
RecordType: "A",
|
||||
})
|
||||
|
@ -18,6 +18,7 @@ package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/linki/instrumented_http"
|
||||
@ -191,13 +192,20 @@ func (p *GoogleProvider) Records() (endpoints []*endpoint.Endpoint, _ error) {
|
||||
|
||||
f := func(resp *dns.ResourceRecordSetsListResponse) error {
|
||||
for _, r := range resp.Rrsets {
|
||||
|
||||
if !supportedRecordType(r.Type) {
|
||||
continue
|
||||
}
|
||||
ep := &endpoint.Endpoint{
|
||||
DNSName: strings.TrimSuffix(r.Name, "."),
|
||||
RecordType: r.Type,
|
||||
Targets: make(endpoint.Targets, 0, len(r.Rrdatas)),
|
||||
}
|
||||
for _, rr := range r.Rrdatas {
|
||||
// each page is processed sequentially, no need for a mutex here.
|
||||
if supportedRecordType(r.Type) {
|
||||
endpoints = append(endpoints, endpoint.NewEndpoint(r.Name, rr, r.Type))
|
||||
}
|
||||
ep.Targets = append(ep.Targets, strings.TrimSuffix(rr, "."))
|
||||
}
|
||||
sort.Sort(ep.Targets)
|
||||
endpoints = append(endpoints, ep)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -347,9 +355,10 @@ func newRecord(ep *endpoint.Endpoint) *dns.ResourceRecordSet {
|
||||
// TODO(linki): works around appending a trailing dot to TXT records. I think
|
||||
// we should go back to storing DNS names with a trailing dot internally. This
|
||||
// way we can use it has is here and trim it off if it exists when necessary.
|
||||
target := ep.Target
|
||||
targets := make([]string, len(ep.Targets))
|
||||
copy(targets, []string(ep.Targets))
|
||||
if ep.RecordType == endpoint.RecordTypeCNAME {
|
||||
target = ensureTrailingDot(target)
|
||||
targets[0] = ensureTrailingDot(targets[0])
|
||||
}
|
||||
|
||||
// no annotation results in a Ttl of 0, default to 300 for backwards-compatability
|
||||
@ -360,7 +369,7 @@ func newRecord(ep *endpoint.Endpoint) *dns.ResourceRecordSet {
|
||||
|
||||
return &dns.ResourceRecordSet{
|
||||
Name: ensureTrailingDot(ep.DNSName),
|
||||
Rrdatas: []string{target},
|
||||
Rrdatas: targets,
|
||||
Ttl: ttl,
|
||||
Type: ep.RecordType,
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ func (p *InfobloxProvider) recordSet(ep *endpoint.Endpoint, getObject bool) (rec
|
||||
obj := ibclient.NewRecordA(
|
||||
ibclient.RecordA{
|
||||
Name: ep.DNSName,
|
||||
Ipv4Addr: ep.Target,
|
||||
Ipv4Addr: ep.Targets[0],
|
||||
},
|
||||
)
|
||||
if getObject {
|
||||
@ -275,7 +275,7 @@ func (p *InfobloxProvider) recordSet(ep *endpoint.Endpoint, getObject bool) (rec
|
||||
obj := ibclient.NewRecordCNAME(
|
||||
ibclient.RecordCNAME{
|
||||
Name: ep.DNSName,
|
||||
Canonical: ep.Target,
|
||||
Canonical: ep.Targets[0],
|
||||
},
|
||||
)
|
||||
if getObject {
|
||||
@ -292,13 +292,13 @@ func (p *InfobloxProvider) recordSet(ep *endpoint.Endpoint, getObject bool) (rec
|
||||
var res []ibclient.RecordTXT
|
||||
// The Infoblox API strips enclosing double quotes from TXT records lacking whitespace.
|
||||
// Here we reconcile that fact by making this state match that reality.
|
||||
if target, err2 := strconv.Unquote(ep.Target); err2 == nil && !strings.Contains(ep.Target, " ") {
|
||||
ep.Target = target
|
||||
if target, err2 := strconv.Unquote(ep.Targets[0]); err2 == nil && !strings.Contains(ep.Targets[0], " ") {
|
||||
ep.Targets = endpoint.Targets{target}
|
||||
}
|
||||
obj := ibclient.NewRecordTXT(
|
||||
ibclient.RecordTXT{
|
||||
Name: ep.DNSName,
|
||||
Text: ep.Target,
|
||||
Text: ep.Targets[0],
|
||||
},
|
||||
)
|
||||
if getObject {
|
||||
@ -323,7 +323,7 @@ func (p *InfobloxProvider) createRecords(created infobloxChangeMap) {
|
||||
"Would create %s record named '%s' to '%s' for Infoblox DNS zone '%s'.",
|
||||
ep.RecordType,
|
||||
ep.DNSName,
|
||||
ep.Target,
|
||||
ep.Targets,
|
||||
zone,
|
||||
)
|
||||
continue
|
||||
@ -333,7 +333,7 @@ func (p *InfobloxProvider) createRecords(created infobloxChangeMap) {
|
||||
"Creating %s record named '%s' to '%s' for Infoblox DNS zone '%s'.",
|
||||
ep.RecordType,
|
||||
ep.DNSName,
|
||||
ep.Target,
|
||||
ep.Targets,
|
||||
zone,
|
||||
)
|
||||
|
||||
@ -343,7 +343,7 @@ func (p *InfobloxProvider) createRecords(created infobloxChangeMap) {
|
||||
"Failed to retrieve %s record named '%s' to '%s' for DNS zone '%s': %v",
|
||||
ep.RecordType,
|
||||
ep.DNSName,
|
||||
ep.Target,
|
||||
ep.Targets,
|
||||
zone,
|
||||
err,
|
||||
)
|
||||
@ -355,7 +355,7 @@ func (p *InfobloxProvider) createRecords(created infobloxChangeMap) {
|
||||
"Failed to create %s record named '%s' to '%s' for DNS zone '%s': %v",
|
||||
ep.RecordType,
|
||||
ep.DNSName,
|
||||
ep.Target,
|
||||
ep.Targets,
|
||||
zone,
|
||||
err,
|
||||
)
|
||||
@ -378,7 +378,7 @@ func (p *InfobloxProvider) deleteRecords(deleted infobloxChangeMap) {
|
||||
"Failed to retrieve %s record named '%s' to '%s' for DNS zone '%s': %v",
|
||||
ep.RecordType,
|
||||
ep.DNSName,
|
||||
ep.Target,
|
||||
ep.Targets,
|
||||
zone,
|
||||
err,
|
||||
)
|
||||
|
@ -203,7 +203,7 @@ func convertToInMemoryRecord(endpoints []*endpoint.Endpoint) []*inMemoryRecord {
|
||||
records = append(records, &inMemoryRecord{
|
||||
Type: ep.RecordType,
|
||||
Name: ep.DNSName,
|
||||
Target: ep.Target,
|
||||
Target: ep.Targets[0],
|
||||
})
|
||||
}
|
||||
return records
|
||||
|
@ -186,16 +186,17 @@ func testInMemoryRecords(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
{
|
||||
DNSName: "example.org",
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Targets: endpoint.Targets{""},
|
||||
},
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
},
|
||||
@ -214,7 +215,7 @@ func testInMemoryRecords(t *testing.T) {
|
||||
assert.EqualError(t, err, ErrZoneNotFound.Error())
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.True(t, testutils.SameEndpoints(ti.expected, records))
|
||||
assert.True(t, testutils.SameEndpoints(ti.expected, records), "Endpoints not the same: Expected: %+v Records: %+v", ti.expected, records)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -314,7 +315,7 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -333,14 +334,14 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -358,14 +359,14 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -383,12 +384,12 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
{
|
||||
DNSName: "foo.org",
|
||||
Target: "4.4.4.4",
|
||||
Targets: endpoint.Targets{"4.4.4.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -408,7 +409,7 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -416,7 +417,7 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -433,12 +434,12 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -458,7 +459,7 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "new.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -478,7 +479,7 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "new.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -497,7 +498,7 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.org",
|
||||
Target: "5.5.5.5",
|
||||
Targets: endpoint.Targets{"5.5.5.5"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -512,21 +513,21 @@ func testInMemoryValidateChangeBatch(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.new.org",
|
||||
Target: "4.8.8.9",
|
||||
Targets: endpoint.Targets{"4.8.8.9"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.org",
|
||||
Target: "4.8.8.4",
|
||||
Targets: endpoint.Targets{"4.8.8.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.org",
|
||||
Target: "5.5.5.5",
|
||||
Targets: endpoint.Targets{"5.5.5.5"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -608,7 +609,7 @@ func testInMemoryApplyChanges(t *testing.T) {
|
||||
changes: &plan.Changes{
|
||||
Create: []*endpoint.Endpoint{{
|
||||
DNSName: "example.de",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
}},
|
||||
UpdateNew: []*endpoint.Endpoint{},
|
||||
@ -625,7 +626,7 @@ func testInMemoryApplyChanges(t *testing.T) {
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -633,7 +634,7 @@ func testInMemoryApplyChanges(t *testing.T) {
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -649,7 +650,7 @@ func testInMemoryApplyChanges(t *testing.T) {
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.org",
|
||||
Target: "5.5.5.5",
|
||||
Targets: endpoint.Targets{"5.5.5.5"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -697,28 +698,28 @@ func testInMemoryApplyChanges(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.new.org",
|
||||
Target: "4.8.8.9",
|
||||
Targets: endpoint.Targets{"4.8.8.9"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.org",
|
||||
Target: "4.8.8.4",
|
||||
Targets: endpoint.Targets{"4.8.8.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar.org",
|
||||
Target: "5.5.5.5",
|
||||
Targets: endpoint.Targets{"5.5.5.5"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
|
@ -49,7 +49,7 @@ func testNoopRecords(t *testing.T) {
|
||||
providerRecords := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "example-lb.com",
|
||||
Targets: endpoint.Targets{"example-lb.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
}
|
||||
@ -71,19 +71,19 @@ func testNoopApplyChanges(t *testing.T) {
|
||||
providerRecords := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "old-lb.com",
|
||||
Targets: endpoint.Targets{"old-lb.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
}
|
||||
expectedUpdate := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "new-example-lb.com",
|
||||
Targets: endpoint.Targets{"new-example-lb.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "new-record.org",
|
||||
Target: "new-lb.org",
|
||||
Targets: endpoint.Targets{"new-lb.org"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
}
|
||||
@ -98,7 +98,7 @@ func testNoopApplyChanges(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "lb.com",
|
||||
Targets: endpoint.Targets{"lb.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
},
|
||||
@ -110,21 +110,21 @@ func testNoopApplyChanges(t *testing.T) {
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "new-record.org",
|
||||
Target: "new-lb.org",
|
||||
Targets: endpoint.Targets{"new-lb.org"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "new-example-lb.com",
|
||||
Targets: endpoint.Targets{"new-example-lb.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
},
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "old-lb.com",
|
||||
Targets: endpoint.Targets{"old-lb.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
},
|
||||
|
@ -66,7 +66,8 @@ func (im *TXTRegistry) Records() ([]*endpoint.Endpoint, error) {
|
||||
endpoints = append(endpoints, record)
|
||||
continue
|
||||
}
|
||||
labels, err := endpoint.NewLabelsFromString(record.Target)
|
||||
// We simply assume that TXT records for the registry will always have only one target.
|
||||
labels, err := endpoint.NewLabelsFromString(record.Targets[0])
|
||||
if err == endpoint.ErrInvalidHeritage {
|
||||
//if no heritage is found or it is invalid
|
||||
//case when value of txt record cannot be identified
|
||||
|
@ -82,7 +82,7 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) {
|
||||
expectedRecords := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.test-zone.example.org",
|
||||
Target: "foo.loadbalancer.com",
|
||||
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -90,7 +90,7 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "bar.test-zone.example.org",
|
||||
Target: "my-domain.com",
|
||||
Targets: endpoint.Targets{"my-domain.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "owner",
|
||||
@ -98,7 +98,7 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "txt.bar.test-zone.example.org",
|
||||
Target: "baz.test-zone.example.org",
|
||||
Targets: endpoint.Targets{"baz.test-zone.example.org"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -106,7 +106,7 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "qux.test-zone.example.org",
|
||||
Target: "random",
|
||||
Targets: endpoint.Targets{"random"},
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -114,7 +114,7 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "tar.test-zone.example.org",
|
||||
Target: "tar.loadbalancer.com",
|
||||
Targets: endpoint.Targets{"tar.loadbalancer.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "owner-2",
|
||||
@ -122,7 +122,7 @@ func testTXTRegistryRecordsPrefixed(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "foobar.test-zone.example.org",
|
||||
Target: "foobar.loadbalancer.com",
|
||||
Targets: endpoint.Targets{"foobar.loadbalancer.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -155,7 +155,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) {
|
||||
expectedRecords := []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.test-zone.example.org",
|
||||
Target: "foo.loadbalancer.com",
|
||||
Targets: endpoint.Targets{"foo.loadbalancer.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -163,7 +163,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "bar.test-zone.example.org",
|
||||
Target: "my-domain.com",
|
||||
Targets: endpoint.Targets{"my-domain.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -171,7 +171,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "txt.bar.test-zone.example.org",
|
||||
Target: "baz.test-zone.example.org",
|
||||
Targets: endpoint.Targets{"baz.test-zone.example.org"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "owner",
|
||||
@ -180,7 +180,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "qux.test-zone.example.org",
|
||||
Target: "random",
|
||||
Targets: endpoint.Targets{"random"},
|
||||
RecordType: endpoint.RecordTypeTXT,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -188,7 +188,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "tar.test-zone.example.org",
|
||||
Target: "tar.loadbalancer.com",
|
||||
Targets: endpoint.Targets{"tar.loadbalancer.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "",
|
||||
@ -196,7 +196,7 @@ func testTXTRegistryRecordsNoPrefix(t *testing.T) {
|
||||
},
|
||||
{
|
||||
DNSName: "foobar.test-zone.example.org",
|
||||
Target: "foobar.loadbalancer.com",
|
||||
Targets: endpoint.Targets{"foobar.loadbalancer.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: map[string]string{
|
||||
endpoint.OwnerLabelKey: "owner",
|
||||
|
@ -43,7 +43,7 @@ func (ms *dedupSource) Endpoints() ([]*endpoint.Endpoint, error) {
|
||||
}
|
||||
|
||||
for _, ep := range endpoints {
|
||||
identifier := ep.DNSName + " / " + ep.Target
|
||||
identifier := ep.DNSName + " / " + ep.Targets.String()
|
||||
|
||||
if _, ok := collected[identifier]; ok {
|
||||
log.Debugf("Removing duplicate endpoint %s", ep)
|
||||
|
@ -40,53 +40,53 @@ func testDedupEndpoints(t *testing.T) {
|
||||
{
|
||||
"one endpoint returns one endpoint",
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"two different endpoints return two endpoints",
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "4.5.6.7"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"4.5.6.7"}},
|
||||
},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "4.5.6.7"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"4.5.6.7"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"two endpoints with same dnsname and different targets return two endpoints",
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Target: "4.5.6.7"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"4.5.6.7"}},
|
||||
},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Target: "4.5.6.7"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"4.5.6.7"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"two endpoints with different dnsname and same target return two endpoints",
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
"two endpoints with same dnsname and same target return one endpoint",
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
@ -60,7 +60,7 @@ func TestFakeEndpointsResolveToIPAddresses(t *testing.T) {
|
||||
endpoints := generateTestEndpoints()
|
||||
|
||||
for _, e := range endpoints {
|
||||
ip := net.ParseIP(e.Target)
|
||||
ip := net.ParseIP(e.Targets[0])
|
||||
|
||||
if ip == nil {
|
||||
t.Error(e)
|
||||
|
@ -19,6 +19,7 @@ package source
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@ -109,33 +110,32 @@ func (sc *ingressSource) Endpoints() ([]*endpoint.Endpoint, error) {
|
||||
endpoints = append(endpoints, ingEndpoints...)
|
||||
}
|
||||
|
||||
for _, ep := range endpoints {
|
||||
sort.Sort(ep.Targets)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
// get endpoints from optional "target" annotation
|
||||
// Returns empty endpoints array if none are found.
|
||||
func getEndpointsFromTargetAnnotation(ing *v1beta1.Ingress, hostname string) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
func getTargetsFromTargetAnnotation(ing *v1beta1.Ingress) endpoint.Targets {
|
||||
var targets endpoint.Targets
|
||||
|
||||
// Get the desired hostname of the ingress from the annotation.
|
||||
targetAnnotation, exists := ing.Annotations[targetAnnotationKey]
|
||||
if exists {
|
||||
ttl, err := getTTLFromAnnotations(ing.Annotations)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
// splits the hostname annotation and removes the trailing periods
|
||||
targetsList := strings.Split(strings.Replace(targetAnnotation, " ", "", -1), ",")
|
||||
for _, targetHostname := range targetsList {
|
||||
targetHostname = strings.TrimSuffix(targetHostname, ".")
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(hostname, targetHostname, suitableType(targetHostname), ttl))
|
||||
targets = append(targets, targetHostname)
|
||||
}
|
||||
}
|
||||
return endpoints
|
||||
return targets
|
||||
}
|
||||
|
||||
func (sc *ingressSource) endpointsFromTemplate(ing *v1beta1.Ingress) ([]*endpoint.Endpoint, error) {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := sc.fqdnTemplate.Execute(&buf, ing)
|
||||
@ -145,26 +145,18 @@ func (sc *ingressSource) endpointsFromTemplate(ing *v1beta1.Ingress) ([]*endpoin
|
||||
|
||||
hostname := buf.String()
|
||||
|
||||
endpoints = getEndpointsFromTargetAnnotation(ing, hostname)
|
||||
|
||||
if len(endpoints) != 0 {
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
ttl, err := getTTLFromAnnotations(ing.Annotations)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
for _, lb := range ing.Status.LoadBalancer.Ingress {
|
||||
if lb.IP != "" {
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(hostname, lb.IP, endpoint.RecordTypeA, ttl))
|
||||
}
|
||||
if lb.Hostname != "" {
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(hostname, lb.Hostname, endpoint.RecordTypeCNAME, ttl))
|
||||
}
|
||||
|
||||
targets := getTargetsFromTargetAnnotation(ing)
|
||||
|
||||
if len(targets) == 0 {
|
||||
targets = targetsFromIngressStatus(ing.Status)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
return endpointsForHostname(hostname, targets, ttl), nil
|
||||
}
|
||||
|
||||
// filterByAnnotations filters a list of ingresses by a given annotation selector.
|
||||
@ -208,32 +200,77 @@ func (sc *ingressSource) setResourceLabel(ingress v1beta1.Ingress, endpoints []*
|
||||
func endpointsFromIngress(ing *v1beta1.Ingress) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
for _, rule := range ing.Spec.Rules {
|
||||
if rule.Host == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
annotationEndpoints := getEndpointsFromTargetAnnotation(ing, rule.Host)
|
||||
|
||||
if len(annotationEndpoints) != 0 {
|
||||
endpoints = append(endpoints, annotationEndpoints...)
|
||||
continue
|
||||
}
|
||||
|
||||
ttl, err := getTTLFromAnnotations(ing.Annotations)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
|
||||
for _, lb := range ing.Status.LoadBalancer.Ingress {
|
||||
if lb.IP != "" {
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(rule.Host, lb.IP, endpoint.RecordTypeA, ttl))
|
||||
targets := getTargetsFromTargetAnnotation(ing)
|
||||
|
||||
if len(targets) == 0 {
|
||||
targets = targetsFromIngressStatus(ing.Status)
|
||||
}
|
||||
if lb.Hostname != "" {
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(rule.Host, lb.Hostname, endpoint.RecordTypeCNAME, ttl))
|
||||
|
||||
for _, rule := range ing.Spec.Rules {
|
||||
if rule.Host == "" {
|
||||
continue
|
||||
}
|
||||
endpoints = append(endpoints, endpointsForHostname(rule.Host, targets, ttl)...)
|
||||
}
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoint.TTL) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
var aTargets endpoint.Targets
|
||||
var cnameTargets endpoint.Targets
|
||||
|
||||
for _, t := range targets {
|
||||
switch suitableType(t) {
|
||||
case endpoint.RecordTypeA:
|
||||
aTargets = append(aTargets, t)
|
||||
default:
|
||||
cnameTargets = append(cnameTargets, t)
|
||||
}
|
||||
}
|
||||
|
||||
if len(aTargets) > 0 {
|
||||
epA := &endpoint.Endpoint{
|
||||
DNSName: strings.TrimSuffix(hostname, "."),
|
||||
Targets: aTargets,
|
||||
RecordTTL: ttl,
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Labels: endpoint.NewLabels(),
|
||||
}
|
||||
endpoints = append(endpoints, epA)
|
||||
}
|
||||
|
||||
if len(cnameTargets) > 0 {
|
||||
epCNAME := &endpoint.Endpoint{
|
||||
DNSName: strings.TrimSuffix(hostname, "."),
|
||||
Targets: cnameTargets,
|
||||
RecordTTL: ttl,
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: endpoint.NewLabels(),
|
||||
}
|
||||
endpoints = append(endpoints, epCNAME)
|
||||
}
|
||||
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func targetsFromIngressStatus(status v1beta1.IngressStatus) endpoint.Targets {
|
||||
var targets endpoint.Targets
|
||||
|
||||
for _, lb := range status.LoadBalancer.Ingress {
|
||||
if lb.IP != "" {
|
||||
targets = append(targets, lb.IP)
|
||||
}
|
||||
if lb.Hostname != "" {
|
||||
targets = append(targets, lb.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
return targets
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ func testEndpointsFromIngress(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar",
|
||||
Target: "lb.com",
|
||||
Targets: endpoint.Targets{"lb.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -147,7 +147,7 @@ func testEndpointsFromIngress(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -161,19 +161,11 @@ func testEndpointsFromIngress(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "foo.bar",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8", "127.0.0.1"},
|
||||
},
|
||||
{
|
||||
DNSName: "foo.bar",
|
||||
Target: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
DNSName: "foo.bar",
|
||||
Target: "elb.com",
|
||||
},
|
||||
{
|
||||
DNSName: "foo.bar",
|
||||
Target: "alb.com",
|
||||
Targets: endpoint.Targets{"elb.com", "alb.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -244,11 +236,11 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "new.org",
|
||||
Target: "lb.com",
|
||||
Targets: endpoint.Targets{"lb.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -272,11 +264,11 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "new.org",
|
||||
Target: "lb.com",
|
||||
Targets: endpoint.Targets{"lb.com"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -300,7 +292,7 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -322,7 +314,7 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -379,7 +371,7 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -417,7 +409,7 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -455,11 +447,11 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "fake1.ext-dns.test.com",
|
||||
Target: "8.8.8.8",
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "fake1.ext-dns.test.com",
|
||||
Target: "elb.com",
|
||||
Targets: endpoint.Targets{"elb.com"},
|
||||
},
|
||||
},
|
||||
fqdnTemplate: "{{.Name}}.ext-dns.test.com",
|
||||
@ -516,17 +508,17 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "ingress-target.com",
|
||||
Targets: endpoint.Targets{"ingress-target.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "example2.org",
|
||||
Target: "ingress-target.com",
|
||||
Targets: endpoint.Targets{"ingress-target.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "example3.org",
|
||||
Target: "1.2.3.4",
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
@ -559,12 +551,12 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "example.org",
|
||||
Target: "ingress-target.com",
|
||||
Targets: endpoint.Targets{"ingress-target.com"},
|
||||
RecordTTL: endpoint.TTL(6),
|
||||
},
|
||||
{
|
||||
DNSName: "example2.org",
|
||||
Target: "ingress-target.com",
|
||||
Targets: endpoint.Targets{"ingress-target.com"},
|
||||
RecordTTL: endpoint.TTL(1),
|
||||
},
|
||||
},
|
||||
@ -606,17 +598,17 @@ func testIngressEndpoints(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "fake1.ext-dns.test.com",
|
||||
Target: "ingress-target.com",
|
||||
Targets: endpoint.Targets{"ingress-target.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "fake2.ext-dns.test.com",
|
||||
Target: "ingress-target.com",
|
||||
Targets: endpoint.Targets{"ingress-target.com"},
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
},
|
||||
{
|
||||
DNSName: "fake3.ext-dns.test.com",
|
||||
Target: "1.2.3.4",
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
},
|
||||
},
|
||||
|
@ -40,8 +40,8 @@ func testMultiSourceImplementsSource(t *testing.T) {
|
||||
|
||||
// testMultiSourceEndpoints tests merged endpoints from children are returned.
|
||||
func testMultiSourceEndpoints(t *testing.T) {
|
||||
foo := &endpoint.Endpoint{DNSName: "foo", Target: "8.8.8.8"}
|
||||
bar := &endpoint.Endpoint{DNSName: "bar", Target: "8.8.4.4"}
|
||||
foo := &endpoint.Endpoint{DNSName: "foo", Targets: endpoint.Targets{"8.8.8.8"}}
|
||||
bar := &endpoint.Endpoint{DNSName: "bar", Targets: endpoint.Targets{"8.8.4.4"}}
|
||||
|
||||
for _, tc := range []struct {
|
||||
title string
|
||||
|
@ -19,6 +19,7 @@ package source
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
@ -32,6 +33,10 @@ import (
|
||||
"github.com/kubernetes-incubator/external-dns/endpoint"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTargetsCapacity = 10
|
||||
)
|
||||
|
||||
// serviceSource is an implementation of Source for Kubernetes service objects.
|
||||
// It will find all services that are under our jurisdiction, i.e. annotated
|
||||
// desired hostname and matching or no controller annotation. For each of the
|
||||
@ -119,10 +124,14 @@ func (sc *serviceSource) Endpoints() ([]*endpoint.Endpoint, error) {
|
||||
endpoints = append(endpoints, svcEndpoints...)
|
||||
}
|
||||
|
||||
for _, ep := range endpoints {
|
||||
sort.Sort(ep.Targets)
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
func (sc *serviceSource) extractHeadlessEndpoint(svc *v1.Service, hostname string) []*endpoint.Endpoint {
|
||||
func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname string) []*endpoint.Endpoint {
|
||||
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
@ -138,6 +147,7 @@ func (sc *serviceSource) extractHeadlessEndpoint(svc *v1.Service, hostname strin
|
||||
if v.Spec.Hostname != "" {
|
||||
headlessDomain = v.Spec.Hostname + "." + headlessDomain
|
||||
}
|
||||
|
||||
log.Debugf("Generating matching endpoint %s with HostIP %s", headlessDomain, v.Status.HostIP)
|
||||
// To reduce traffice on the DNS API only add record for running Pods. Good Idea?
|
||||
if v.Status.Phase == v1.PodRunning {
|
||||
@ -221,54 +231,82 @@ func (sc *serviceSource) setResourceLabel(service v1.Service, endpoints []*endpo
|
||||
}
|
||||
|
||||
func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
|
||||
hostname = strings.TrimSuffix(hostname, ".")
|
||||
ttl, err := getTTLFromAnnotations(svc.Annotations)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
|
||||
epA := &endpoint.Endpoint{
|
||||
RecordTTL: ttl,
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Labels: endpoint.NewLabels(),
|
||||
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
|
||||
DNSName: hostname,
|
||||
}
|
||||
|
||||
epCNAME := &endpoint.Endpoint{
|
||||
RecordTTL: ttl,
|
||||
RecordType: endpoint.RecordTypeCNAME,
|
||||
Labels: endpoint.NewLabels(),
|
||||
Targets: make(endpoint.Targets, 0, defaultTargetsCapacity),
|
||||
DNSName: hostname,
|
||||
}
|
||||
|
||||
var endpoints []*endpoint.Endpoint
|
||||
var targets endpoint.Targets
|
||||
|
||||
switch svc.Spec.Type {
|
||||
case v1.ServiceTypeLoadBalancer:
|
||||
endpoints = append(endpoints, extractLoadBalancerEndpoints(svc, hostname)...)
|
||||
targets = append(targets, extractLoadBalancerTargets(svc)...)
|
||||
case v1.ServiceTypeClusterIP:
|
||||
if sc.publishInternal {
|
||||
endpoints = append(endpoints, extractServiceIps(svc, hostname)...)
|
||||
targets = append(targets, extractServiceIps(svc)...)
|
||||
}
|
||||
if svc.Spec.ClusterIP == v1.ClusterIPNone {
|
||||
endpoints = append(endpoints, sc.extractHeadlessEndpoint(svc, hostname)...)
|
||||
endpoints = append(endpoints, sc.extractHeadlessEndpoints(svc, hostname)...)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for _, t := range targets {
|
||||
if suitableType(t) == endpoint.RecordTypeA {
|
||||
epA.Targets = append(epA.Targets, t)
|
||||
}
|
||||
if suitableType(t) == endpoint.RecordTypeCNAME {
|
||||
epCNAME.Targets = append(epCNAME.Targets, t)
|
||||
}
|
||||
}
|
||||
|
||||
if len(epA.Targets) > 0 {
|
||||
endpoints = append(endpoints, epA)
|
||||
}
|
||||
if len(epCNAME.Targets) > 0 {
|
||||
endpoints = append(endpoints, epCNAME)
|
||||
}
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func extractServiceIps(svc *v1.Service, hostname string) []*endpoint.Endpoint {
|
||||
ttl, err := getTTLFromAnnotations(svc.Annotations)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
func extractServiceIps(svc *v1.Service) endpoint.Targets {
|
||||
if svc.Spec.ClusterIP == v1.ClusterIPNone {
|
||||
log.Debugf("Unable to associate %s headless service with a Cluster IP", svc.Name)
|
||||
return []*endpoint.Endpoint{}
|
||||
return endpoint.Targets{}
|
||||
}
|
||||
|
||||
return []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(hostname, svc.Spec.ClusterIP, endpoint.RecordTypeA, ttl)}
|
||||
return endpoint.Targets{svc.Spec.ClusterIP}
|
||||
}
|
||||
|
||||
func extractLoadBalancerEndpoints(svc *v1.Service, hostname string) []*endpoint.Endpoint {
|
||||
var endpoints []*endpoint.Endpoint
|
||||
func extractLoadBalancerTargets(svc *v1.Service) endpoint.Targets {
|
||||
var targets endpoint.Targets
|
||||
|
||||
ttl, err := getTTLFromAnnotations(svc.Annotations)
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
}
|
||||
// Create a corresponding endpoint for each configured external entrypoint.
|
||||
for _, lb := range svc.Status.LoadBalancer.Ingress {
|
||||
if lb.IP != "" {
|
||||
//TODO(ideahitme): consider retrieving record type from resource annotation instead of empty
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(hostname, lb.IP, endpoint.RecordTypeA, ttl))
|
||||
targets = append(targets, lb.IP)
|
||||
}
|
||||
if lb.Hostname != "" {
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(hostname, lb.Hostname, endpoint.RecordTypeCNAME, ttl))
|
||||
targets = append(targets, lb.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
return endpoints
|
||||
return targets
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -229,8 +229,8 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -250,8 +250,8 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -271,7 +271,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"lb.example.com"}, // Kubernetes omits the trailing dot
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "lb.example.com"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"lb.example.com"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -291,8 +291,8 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4", "lb.example.com"}, // Kubernetes omits the trailing dot
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Target: "lb.example.com"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"lb.example.com"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -313,7 +313,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -352,7 +352,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -390,7 +390,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -411,7 +411,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -470,7 +470,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -512,7 +512,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
false,
|
||||
},
|
||||
{
|
||||
"multiple external entrypoints return multiple endpoints",
|
||||
"multiple external entrypoints return a single endpoint with multiple targets",
|
||||
"",
|
||||
"",
|
||||
"testing",
|
||||
@ -527,8 +527,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4", "8.8.8.8"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Target: "8.8.8.8"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4", "8.8.8.8"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -566,7 +565,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -588,8 +587,8 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "bar.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "bar.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -607,8 +606,8 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4", "elb.com"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.bar.example.com", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.bar.example.com", Target: "elb.com"},
|
||||
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"elb.com"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -628,8 +627,8 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4", "elb.com"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Target: "elb.com"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"elb.com"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -649,7 +648,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "mate.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "mate.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -685,7 +684,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4", RecordTTL: endpoint.TTL(0)},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}, RecordTTL: endpoint.TTL(0)},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -706,7 +705,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4", RecordTTL: endpoint.TTL(0)},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}, RecordTTL: endpoint.TTL(0)},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -727,7 +726,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4", RecordTTL: endpoint.TTL(10)},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}, RecordTTL: endpoint.TTL(10)},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -748,7 +747,7 @@ func testServiceSourceEndpoints(t *testing.T) {
|
||||
"",
|
||||
[]string{"1.2.3.4"},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4", RecordTTL: endpoint.TTL(0)},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}, RecordTTL: endpoint.TTL(0)},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -846,7 +845,7 @@ func TestClusterIpServices(t *testing.T) {
|
||||
"1.2.3.4",
|
||||
[]string{},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.example.org", Target: "1.2.3.4"},
|
||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -864,7 +863,7 @@ func TestClusterIpServices(t *testing.T) {
|
||||
"4.5.6.7",
|
||||
[]string{},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo.bar.example.com", Target: "4.5.6.7"},
|
||||
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"4.5.6.7"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -988,8 +987,8 @@ func TestHeadlessServices(t *testing.T) {
|
||||
[]string{"foo-0", "foo-1"},
|
||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo-0.service.example.org", Target: "1.1.1.1"},
|
||||
{DNSName: "foo-1.service.example.org", Target: "1.1.1.1"},
|
||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||
{DNSName: "foo-1.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -1015,7 +1014,7 @@ func TestHeadlessServices(t *testing.T) {
|
||||
[]string{"foo-0", "foo-1"},
|
||||
[]v1.PodPhase{v1.PodRunning, v1.PodFailed},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "foo-0.service.example.org", Target: "1.1.1.1"},
|
||||
{DNSName: "foo-0.service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -1041,8 +1040,8 @@ func TestHeadlessServices(t *testing.T) {
|
||||
[]string{"", ""},
|
||||
[]v1.PodPhase{v1.PodRunning, v1.PodRunning},
|
||||
[]*endpoint.Endpoint{
|
||||
{DNSName: "service.example.org", Target: "1.1.1.1"},
|
||||
{DNSName: "service.example.org", Target: "1.1.1.1"},
|
||||
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||
{DNSName: "service.example.org", Targets: endpoint.Targets{"1.1.1.1"}},
|
||||
},
|
||||
false,
|
||||
},
|
||||
|
@ -39,8 +39,8 @@ func validateEndpoint(t *testing.T, endpoint, expected *endpoint.Endpoint) {
|
||||
t.Errorf("expected %s, got %s", expected.DNSName, endpoint.DNSName)
|
||||
}
|
||||
|
||||
if endpoint.Target != expected.Target {
|
||||
t.Errorf("expected %s, got %s", expected.Target, endpoint.Target)
|
||||
if !endpoint.Targets.Same(expected.Targets) {
|
||||
t.Errorf("expected %s, got %s", expected.Targets, endpoint.Targets)
|
||||
}
|
||||
|
||||
if endpoint.RecordTTL != expected.RecordTTL {
|
||||
|
Loading…
Reference in New Issue
Block a user