sigs.k8s.io/external-dns@v0.14.1/source/multisource_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package source 18 19 import ( 20 "context" 21 "errors" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 27 "sigs.k8s.io/external-dns/endpoint" 28 "sigs.k8s.io/external-dns/internal/testutils" 29 ) 30 31 func TestMultiSource(t *testing.T) { 32 t.Parallel() 33 34 t.Run("Interface", testMultiSourceImplementsSource) 35 t.Run("Endpoints", testMultiSourceEndpoints) 36 t.Run("EndpointsWithError", testMultiSourceEndpointsWithError) 37 t.Run("EndpointsDefaultTargets", testMultiSourceEndpointsDefaultTargets) 38 } 39 40 // testMultiSourceImplementsSource tests that multiSource is a valid Source. 41 func testMultiSourceImplementsSource(t *testing.T) { 42 assert.Implements(t, (*Source)(nil), new(multiSource)) 43 } 44 45 // testMultiSourceEndpoints tests merged endpoints from children are returned. 46 func testMultiSourceEndpoints(t *testing.T) { 47 foo := &endpoint.Endpoint{DNSName: "foo", Targets: endpoint.Targets{"8.8.8.8"}} 48 bar := &endpoint.Endpoint{DNSName: "bar", Targets: endpoint.Targets{"8.8.4.4"}} 49 50 for _, tc := range []struct { 51 title string 52 nestedEndpoints [][]*endpoint.Endpoint 53 expected []*endpoint.Endpoint 54 }{ 55 { 56 "no child sources return no endpoints", 57 nil, 58 []*endpoint.Endpoint{}, 59 }, 60 { 61 "single empty child source returns no endpoints", 62 [][]*endpoint.Endpoint{{}}, 63 []*endpoint.Endpoint{}, 64 }, 65 { 66 "single non-empty child source returns child's endpoints", 67 [][]*endpoint.Endpoint{{foo}}, 68 []*endpoint.Endpoint{foo}, 69 }, 70 { 71 "multiple non-empty child sources returns merged children's endpoints", 72 [][]*endpoint.Endpoint{{foo}, {bar}}, 73 []*endpoint.Endpoint{foo, bar}, 74 }, 75 } { 76 tc := tc 77 t.Run(tc.title, func(t *testing.T) { 78 t.Parallel() 79 80 // Prepare the nested mock sources. 81 sources := make([]Source, 0, len(tc.nestedEndpoints)) 82 83 // Populate the nested mock sources. 84 for _, endpoints := range tc.nestedEndpoints { 85 src := new(testutils.MockSource) 86 src.On("Endpoints").Return(endpoints, nil) 87 88 sources = append(sources, src) 89 } 90 91 // Create our object under test and get the endpoints. 92 source := NewMultiSource(sources, nil) 93 94 // Get endpoints from the source. 95 endpoints, err := source.Endpoints(context.Background()) 96 require.NoError(t, err) 97 98 // Validate returned endpoints against desired endpoints. 99 validateEndpoints(t, endpoints, tc.expected) 100 101 // Validate that the nested sources were called. 102 for _, src := range sources { 103 src.(*testutils.MockSource).AssertExpectations(t) 104 } 105 }) 106 } 107 } 108 109 // testMultiSourceEndpointsWithError tests that an error by a nested source is bubbled up. 110 func testMultiSourceEndpointsWithError(t *testing.T) { 111 // Create the expected error. 112 errSomeError := errors.New("some error") 113 114 // Create a mocked source returning that error. 115 src := new(testutils.MockSource) 116 src.On("Endpoints").Return(nil, errSomeError) 117 118 // Create our object under test and get the endpoints. 119 source := NewMultiSource([]Source{src}, nil) 120 121 // Get endpoints from our source. 122 _, err := source.Endpoints(context.Background()) 123 assert.EqualError(t, err, "some error") 124 125 // Validate that the nested source was called. 126 src.AssertExpectations(t) 127 } 128 129 func testMultiSourceEndpointsDefaultTargets(t *testing.T) { 130 // Create the expected default targets 131 defaultTargetsA := []string{"127.0.0.1", "127.0.0.2"} 132 defaultTargetsAAAA := []string{"2001:db8::1"} 133 defaultTargetsCName := []string{"foo.example.org"} 134 defaultTargets := append(defaultTargetsA, defaultTargetsCName...) 135 defaultTargets = append(defaultTargets, defaultTargetsAAAA...) 136 labels := endpoint.Labels{"foo": "bar"} 137 138 // Create the expected endpoints 139 expectedEndpoints := []*endpoint.Endpoint{ 140 {DNSName: "foo", Targets: defaultTargetsA, RecordType: "A", Labels: labels}, 141 {DNSName: "bar", Targets: defaultTargetsA, RecordType: "A", Labels: labels}, 142 {DNSName: "foo", Targets: defaultTargetsAAAA, RecordType: "AAAA", Labels: labels}, 143 {DNSName: "bar", Targets: defaultTargetsAAAA, RecordType: "AAAA", Labels: labels}, 144 {DNSName: "foo", Targets: defaultTargetsCName, RecordType: "CNAME", Labels: labels}, 145 {DNSName: "bar", Targets: defaultTargetsCName, RecordType: "CNAME", Labels: labels}, 146 } 147 148 // Create the source endpoints with different targets 149 sourceEndpoints := []*endpoint.Endpoint{ 150 {DNSName: "foo", Targets: endpoint.Targets{"8.8.8.8"}, Labels: labels}, 151 {DNSName: "bar", Targets: endpoint.Targets{"8.8.4.4"}, Labels: labels}, 152 } 153 154 // Create a mocked source returning source targets 155 src := new(testutils.MockSource) 156 src.On("Endpoints").Return(sourceEndpoints, nil) 157 158 // Create our object under test with non-empty defaultTargets and get the endpoints. 159 source := NewMultiSource([]Source{src}, defaultTargets) 160 161 // Get endpoints from our source. 162 endpoints, err := source.Endpoints(context.Background()) 163 require.NoError(t, err) 164 165 // Validate returned endpoints against desired endpoints. 166 validateEndpoints(t, endpoints, expectedEndpoints) 167 168 // Validate that the nested sources were called. 169 src.AssertExpectations(t) 170 }