sigs.k8s.io/external-dns@v0.14.1/provider/plural/plural_test.go (about)

     1  /*
     2  Copyright 2022 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 plural
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"sigs.k8s.io/external-dns/plan"
    24  
    25  	"sigs.k8s.io/external-dns/endpoint"
    26  	"sigs.k8s.io/external-dns/internal/testutils"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"sigs.k8s.io/external-dns/provider"
    30  )
    31  
    32  type ClientStub struct {
    33  	mockDnsRecords []*DnsRecord
    34  }
    35  
    36  // CreateRecord provides a mock function with given fields: record
    37  func (c *ClientStub) CreateRecord(record *DnsRecord) (*DnsRecord, error) {
    38  	c.mockDnsRecords = append(c.mockDnsRecords, record)
    39  	return record, nil
    40  }
    41  
    42  // DeleteRecord provides a mock function with given fields: name, ttype
    43  func (c *ClientStub) DeleteRecord(name string, ttype string) error {
    44  	newRecords := make([]*DnsRecord, 0)
    45  	for _, record := range c.mockDnsRecords {
    46  		if record.Name == name && record.Type == ttype {
    47  			continue
    48  		}
    49  		newRecords = append(newRecords, record)
    50  	}
    51  	c.mockDnsRecords = newRecords
    52  	return nil
    53  }
    54  
    55  // DnsRecords provides a mock function with given fields:
    56  func (c *ClientStub) DnsRecords() ([]*DnsRecord, error) {
    57  	return c.mockDnsRecords, nil
    58  }
    59  
    60  func newPluralProvider(pluralDNSRecord []*DnsRecord) *PluralProvider {
    61  	if pluralDNSRecord == nil {
    62  		pluralDNSRecord = make([]*DnsRecord, 0)
    63  	}
    64  	return &PluralProvider{
    65  		BaseProvider: provider.BaseProvider{},
    66  		Client: &ClientStub{
    67  			mockDnsRecords: pluralDNSRecord,
    68  		},
    69  	}
    70  }
    71  
    72  func TestPluralRecords(t *testing.T) {
    73  	tests := []struct {
    74  		name              string
    75  		expectedEndpoints []*endpoint.Endpoint
    76  		records           []*DnsRecord
    77  	}{
    78  		{
    79  			name: "check records",
    80  			records: []*DnsRecord{
    81  				{
    82  					Type:    endpoint.RecordTypeA,
    83  					Name:    "example.com",
    84  					Records: []string{"123.123.123.122"},
    85  				},
    86  				{
    87  					Type:    endpoint.RecordTypeA,
    88  					Name:    "nginx.example.com",
    89  					Records: []string{"123.123.123.123"},
    90  				},
    91  				{
    92  					Type:    endpoint.RecordTypeCNAME,
    93  					Name:    "hack.example.com",
    94  					Records: []string{"bluecatnetworks.com"},
    95  				},
    96  				{
    97  					Type:    endpoint.RecordTypeTXT,
    98  					Name:    "kdb.example.com",
    99  					Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   100  				},
   101  			},
   102  			expectedEndpoints: []*endpoint.Endpoint{
   103  				{
   104  					DNSName:    "example.com",
   105  					RecordType: endpoint.RecordTypeA,
   106  					Targets:    endpoint.Targets{"123.123.123.122"},
   107  				},
   108  				{
   109  					DNSName:    "nginx.example.com",
   110  					RecordType: endpoint.RecordTypeA,
   111  					Targets:    endpoint.Targets{"123.123.123.123"},
   112  				},
   113  				{
   114  					DNSName:    "hack.example.com",
   115  					RecordType: endpoint.RecordTypeCNAME,
   116  					Targets:    endpoint.Targets{"bluecatnetworks.com"},
   117  				},
   118  				{
   119  					DNSName:    "kdb.example.com",
   120  					RecordType: endpoint.RecordTypeTXT,
   121  					Targets:    endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   122  				},
   123  			},
   124  		},
   125  	}
   126  
   127  	for _, test := range tests {
   128  		t.Run(test.name, func(t *testing.T) {
   129  			provider := newPluralProvider(test.records)
   130  
   131  			actual, err := provider.Records(context.Background())
   132  			if err != nil {
   133  				t.Fatal(err)
   134  			}
   135  			validateEndpoints(t, actual, test.expectedEndpoints)
   136  		})
   137  	}
   138  }
   139  
   140  func TestPluralApplyChangesCreate(t *testing.T) {
   141  	tests := []struct {
   142  		name              string
   143  		expectedEndpoints []*endpoint.Endpoint
   144  	}{
   145  		{
   146  			name: "create new endpoints",
   147  			expectedEndpoints: []*endpoint.Endpoint{
   148  				{
   149  					DNSName:    "example.com",
   150  					RecordType: endpoint.RecordTypeA,
   151  					Targets:    endpoint.Targets{"123.123.123.122"},
   152  				},
   153  				{
   154  					DNSName:    "nginx.example.com",
   155  					RecordType: endpoint.RecordTypeA,
   156  					Targets:    endpoint.Targets{"123.123.123.123"},
   157  				},
   158  				{
   159  					DNSName:    "hack.example.com",
   160  					RecordType: endpoint.RecordTypeCNAME,
   161  					Targets:    endpoint.Targets{"bluecatnetworks.com"},
   162  				},
   163  				{
   164  					DNSName:    "kdb.example.com",
   165  					RecordType: endpoint.RecordTypeTXT,
   166  					Targets:    endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   167  				},
   168  			},
   169  		},
   170  	}
   171  
   172  	for _, test := range tests {
   173  		t.Run(test.name, func(t *testing.T) {
   174  			provider := newPluralProvider(nil)
   175  
   176  			// no records
   177  			actual, err := provider.Records(context.Background())
   178  			if err != nil {
   179  				t.Fatal(err)
   180  			}
   181  			assert.Equal(t, len(actual), 0, "expected no entries")
   182  
   183  			err = provider.ApplyChanges(context.Background(), &plan.Changes{Create: test.expectedEndpoints})
   184  			if err != nil {
   185  				t.Fatal(err)
   186  			}
   187  
   188  			actual, err = provider.Records(context.Background())
   189  			if err != nil {
   190  				t.Fatal(err)
   191  			}
   192  			validateEndpoints(t, actual, test.expectedEndpoints)
   193  		})
   194  	}
   195  }
   196  
   197  func TestPluralApplyChangesDelete(t *testing.T) {
   198  	tests := []struct {
   199  		name              string
   200  		records           []*DnsRecord
   201  		deleteEndpoints   []*endpoint.Endpoint
   202  		expectedEndpoints []*endpoint.Endpoint
   203  	}{
   204  		{
   205  			name: "delete not existing record",
   206  			records: []*DnsRecord{
   207  				{
   208  					Type:    endpoint.RecordTypeA,
   209  					Name:    "example.com",
   210  					Records: []string{"123.123.123.122"},
   211  				},
   212  				{
   213  					Type:    endpoint.RecordTypeA,
   214  					Name:    "nginx.example.com",
   215  					Records: []string{"123.123.123.123"},
   216  				},
   217  				{
   218  					Type:    endpoint.RecordTypeCNAME,
   219  					Name:    "hack.example.com",
   220  					Records: []string{"bluecatnetworks.com"},
   221  				},
   222  				{
   223  					Type:    endpoint.RecordTypeTXT,
   224  					Name:    "kdb.example.com",
   225  					Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   226  				},
   227  			},
   228  			deleteEndpoints: []*endpoint.Endpoint{
   229  				{
   230  					DNSName:    "fake.com",
   231  					RecordType: endpoint.RecordTypeA,
   232  					Targets:    endpoint.Targets{"1.2.3.4"},
   233  				},
   234  			},
   235  			expectedEndpoints: []*endpoint.Endpoint{
   236  				{
   237  					DNSName:    "example.com",
   238  					RecordType: endpoint.RecordTypeA,
   239  					Targets:    endpoint.Targets{"123.123.123.122"},
   240  				},
   241  				{
   242  					DNSName:    "nginx.example.com",
   243  					RecordType: endpoint.RecordTypeA,
   244  					Targets:    endpoint.Targets{"123.123.123.123"},
   245  				},
   246  				{
   247  					DNSName:    "hack.example.com",
   248  					RecordType: endpoint.RecordTypeCNAME,
   249  					Targets:    endpoint.Targets{"bluecatnetworks.com"},
   250  				},
   251  				{
   252  					DNSName:    "kdb.example.com",
   253  					RecordType: endpoint.RecordTypeTXT,
   254  					Targets:    endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   255  				},
   256  			},
   257  		},
   258  		{
   259  			name: "delete one record",
   260  			records: []*DnsRecord{
   261  				{
   262  					Type:    endpoint.RecordTypeA,
   263  					Name:    "example.com",
   264  					Records: []string{"123.123.123.122"},
   265  				},
   266  				{
   267  					Type:    endpoint.RecordTypeA,
   268  					Name:    "nginx.example.com",
   269  					Records: []string{"123.123.123.123"},
   270  				},
   271  				{
   272  					Type:    endpoint.RecordTypeCNAME,
   273  					Name:    "hack.example.com",
   274  					Records: []string{"bluecatnetworks.com"},
   275  				},
   276  				{
   277  					Type:    endpoint.RecordTypeTXT,
   278  					Name:    "kdb.example.com",
   279  					Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   280  				},
   281  			},
   282  			deleteEndpoints: []*endpoint.Endpoint{
   283  				{
   284  					DNSName:    "kdb.example.com",
   285  					RecordType: endpoint.RecordTypeTXT,
   286  					Targets:    endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   287  				},
   288  			},
   289  			expectedEndpoints: []*endpoint.Endpoint{
   290  				{
   291  					DNSName:    "example.com",
   292  					RecordType: endpoint.RecordTypeA,
   293  					Targets:    endpoint.Targets{"123.123.123.122"},
   294  				},
   295  				{
   296  					DNSName:    "nginx.example.com",
   297  					RecordType: endpoint.RecordTypeA,
   298  					Targets:    endpoint.Targets{"123.123.123.123"},
   299  				},
   300  				{
   301  					DNSName:    "hack.example.com",
   302  					RecordType: endpoint.RecordTypeCNAME,
   303  					Targets:    endpoint.Targets{"bluecatnetworks.com"},
   304  				},
   305  			},
   306  		},
   307  		{
   308  			name: "delete all records",
   309  			records: []*DnsRecord{
   310  				{
   311  					Type:    endpoint.RecordTypeA,
   312  					Name:    "example.com",
   313  					Records: []string{"123.123.123.122"},
   314  				},
   315  				{
   316  					Type:    endpoint.RecordTypeA,
   317  					Name:    "nginx.example.com",
   318  					Records: []string{"123.123.123.123"},
   319  				},
   320  				{
   321  					Type:    endpoint.RecordTypeCNAME,
   322  					Name:    "hack.example.com",
   323  					Records: []string{"bluecatnetworks.com"},
   324  				},
   325  				{
   326  					Type:    endpoint.RecordTypeTXT,
   327  					Name:    "kdb.example.com",
   328  					Records: []string{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   329  				},
   330  			},
   331  			deleteEndpoints: []*endpoint.Endpoint{
   332  				{
   333  					DNSName:    "kdb.example.com",
   334  					RecordType: endpoint.RecordTypeTXT,
   335  					Targets:    endpoint.Targets{"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/openshift-ingress/router-default"},
   336  				},
   337  				{
   338  					DNSName:    "example.com",
   339  					RecordType: endpoint.RecordTypeA,
   340  					Targets:    endpoint.Targets{"123.123.123.122"},
   341  				},
   342  				{
   343  					DNSName:    "nginx.example.com",
   344  					RecordType: endpoint.RecordTypeA,
   345  					Targets:    endpoint.Targets{"123.123.123.123"},
   346  				},
   347  				{
   348  					DNSName:    "hack.example.com",
   349  					RecordType: endpoint.RecordTypeCNAME,
   350  					Targets:    endpoint.Targets{"bluecatnetworks.com"},
   351  				},
   352  			},
   353  			expectedEndpoints: []*endpoint.Endpoint{},
   354  		},
   355  	}
   356  
   357  	for _, test := range tests {
   358  		t.Run(test.name, func(t *testing.T) {
   359  			provider := newPluralProvider(test.records)
   360  
   361  			err := provider.ApplyChanges(context.Background(), &plan.Changes{Delete: test.deleteEndpoints})
   362  			if err != nil {
   363  				t.Fatal(err)
   364  			}
   365  
   366  			actual, err := provider.Records(context.Background())
   367  			if err != nil {
   368  				t.Fatal(err)
   369  			}
   370  			validateEndpoints(t, actual, test.expectedEndpoints)
   371  		})
   372  	}
   373  }
   374  
   375  func validateEndpoints(t *testing.T, endpoints []*endpoint.Endpoint, expected []*endpoint.Endpoint) {
   376  	assert.True(t, testutils.SameEndpoints(endpoints, expected), "expected and actual endpoints don't match. %s:%s", endpoints, expected)
   377  }