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  }