sigs.k8s.io/external-dns@v0.14.1/provider/exoscale/exoscale_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 exoscale
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	egoscale "github.com/exoscale/egoscale/v2"
    24  	"github.com/stretchr/testify/assert"
    25  
    26  	"sigs.k8s.io/external-dns/endpoint"
    27  	"sigs.k8s.io/external-dns/plan"
    28  
    29  	"github.com/google/uuid"
    30  )
    31  
    32  type createRecordExoscale struct {
    33  	domainID string
    34  	record   *egoscale.DNSDomainRecord
    35  }
    36  
    37  type deleteRecordExoscale struct {
    38  	domainID string
    39  	recordID string
    40  }
    41  
    42  type updateRecordExoscale struct {
    43  	domainID string
    44  	record   *egoscale.DNSDomainRecord
    45  }
    46  
    47  var (
    48  	createExoscale []createRecordExoscale
    49  	deleteExoscale []deleteRecordExoscale
    50  	updateExoscale []updateRecordExoscale
    51  )
    52  
    53  var defaultTTL int64 = 3600
    54  var domainIDs = []string{uuid.New().String(), uuid.New().String(), uuid.New().String(), uuid.New().String()}
    55  var groups = map[string][]egoscale.DNSDomainRecord{
    56  	domainIDs[0]: {
    57  		{ID: strPtr(uuid.New().String()), Name: strPtr("v1"), Type: strPtr("TXT"), Content: strPtr("test"), TTL: &defaultTTL},
    58  		{ID: strPtr(uuid.New().String()), Name: strPtr("v2"), Type: strPtr("CNAME"), Content: strPtr("test"), TTL: &defaultTTL},
    59  	},
    60  	domainIDs[1]: {
    61  		{ID: strPtr(uuid.New().String()), Name: strPtr("v2"), Type: strPtr("A"), Content: strPtr("test"), TTL: &defaultTTL},
    62  		{ID: strPtr(uuid.New().String()), Name: strPtr("v3"), Type: strPtr("ALIAS"), Content: strPtr("test"), TTL: &defaultTTL},
    63  	},
    64  	domainIDs[2]: {
    65  		{ID: strPtr(uuid.New().String()), Name: strPtr("v1"), Type: strPtr("TXT"), Content: strPtr("test"), TTL: &defaultTTL},
    66  	},
    67  	domainIDs[3]: {
    68  		{ID: strPtr(uuid.New().String()), Name: strPtr("v4"), Type: strPtr("ALIAS"), Content: strPtr("test"), TTL: &defaultTTL},
    69  	},
    70  }
    71  
    72  func strPtr(s string) *string {
    73  	return &s
    74  }
    75  
    76  type ExoscaleClientStub struct{}
    77  
    78  func NewExoscaleClientStub() EgoscaleClientI {
    79  	ep := &ExoscaleClientStub{}
    80  	return ep
    81  }
    82  
    83  func (ep *ExoscaleClientStub) ListDNSDomains(ctx context.Context, _ string) ([]egoscale.DNSDomain, error) {
    84  	domains := []egoscale.DNSDomain{
    85  		{ID: &domainIDs[0], UnicodeName: strPtr("foo.com")},
    86  		{ID: &domainIDs[1], UnicodeName: strPtr("bar.com")},
    87  	}
    88  	return domains, nil
    89  }
    90  
    91  func (ep *ExoscaleClientStub) ListDNSDomainRecords(ctx context.Context, _, domainID string) ([]egoscale.DNSDomainRecord, error) {
    92  	return groups[domainID], nil
    93  }
    94  
    95  func (ep *ExoscaleClientStub) CreateDNSDomainRecord(ctx context.Context, _, domainID string, record *egoscale.DNSDomainRecord) (*egoscale.DNSDomainRecord, error) {
    96  	createExoscale = append(createExoscale, createRecordExoscale{domainID: domainID, record: record})
    97  	return record, nil
    98  }
    99  
   100  func (ep *ExoscaleClientStub) DeleteDNSDomainRecord(ctx context.Context, _, domainID string, record *egoscale.DNSDomainRecord) error {
   101  	deleteExoscale = append(deleteExoscale, deleteRecordExoscale{domainID: domainID, recordID: *record.ID})
   102  	return nil
   103  }
   104  
   105  func (ep *ExoscaleClientStub) UpdateDNSDomainRecord(ctx context.Context, _, domainID string, record *egoscale.DNSDomainRecord) error {
   106  	updateExoscale = append(updateExoscale, updateRecordExoscale{domainID: domainID, record: record})
   107  	return nil
   108  }
   109  
   110  func contains(arr []*endpoint.Endpoint, name string) bool {
   111  	for _, a := range arr {
   112  		if a.DNSName == name {
   113  			return true
   114  		}
   115  	}
   116  	return false
   117  }
   118  
   119  func TestExoscaleGetRecords(t *testing.T) {
   120  	provider := NewExoscaleProviderWithClient(NewExoscaleClientStub(), "", "", false)
   121  
   122  	recs, err := provider.Records(context.Background())
   123  	if err == nil {
   124  		assert.Equal(t, 3, len(recs))
   125  		assert.True(t, contains(recs, "v1.foo.com"))
   126  		assert.True(t, contains(recs, "v2.bar.com"))
   127  		assert.True(t, contains(recs, "v2.foo.com"))
   128  		assert.False(t, contains(recs, "v3.bar.com"))
   129  		assert.False(t, contains(recs, "v1.foobar.com"))
   130  	} else {
   131  		assert.Error(t, err)
   132  	}
   133  }
   134  
   135  func TestExoscaleApplyChanges(t *testing.T) {
   136  	provider := NewExoscaleProviderWithClient(NewExoscaleClientStub(), "", "", false)
   137  
   138  	plan := &plan.Changes{
   139  		Create: []*endpoint.Endpoint{
   140  			{
   141  				DNSName:    "v1.foo.com",
   142  				RecordType: "A",
   143  				Targets:    []string{""},
   144  			},
   145  			{
   146  				DNSName:    "v1.foobar.com",
   147  				RecordType: "TXT",
   148  				Targets:    []string{""},
   149  			},
   150  		},
   151  		Delete: []*endpoint.Endpoint{
   152  			{
   153  				DNSName:    "v1.foo.com",
   154  				RecordType: "A",
   155  				Targets:    []string{""},
   156  			},
   157  			{
   158  				DNSName:    "v1.foobar.com",
   159  				RecordType: "TXT",
   160  				Targets:    []string{""},
   161  			},
   162  		},
   163  		UpdateOld: []*endpoint.Endpoint{
   164  			{
   165  				DNSName:    "v1.foo.com",
   166  				RecordType: "A",
   167  				Targets:    []string{""},
   168  			},
   169  			{
   170  				DNSName:    "v1.foobar.com",
   171  				RecordType: "TXT",
   172  				Targets:    []string{""},
   173  			},
   174  		},
   175  		UpdateNew: []*endpoint.Endpoint{
   176  			{
   177  				DNSName:    "v1.foo.com",
   178  				RecordType: "A",
   179  				Targets:    []string{""},
   180  			},
   181  			{
   182  				DNSName:    "v1.foobar.com",
   183  				RecordType: "TXT",
   184  				Targets:    []string{""},
   185  			},
   186  		},
   187  	}
   188  	createExoscale = make([]createRecordExoscale, 0)
   189  	deleteExoscale = make([]deleteRecordExoscale, 0)
   190  
   191  	provider.ApplyChanges(context.Background(), plan)
   192  
   193  	assert.Equal(t, 1, len(createExoscale))
   194  	assert.Equal(t, domainIDs[0], createExoscale[0].domainID)
   195  	assert.Equal(t, "v1", *createExoscale[0].record.Name)
   196  
   197  	assert.Equal(t, 1, len(deleteExoscale))
   198  	assert.Equal(t, domainIDs[0], deleteExoscale[0].domainID)
   199  	assert.Equal(t, *groups[domainIDs[0]][0].ID, deleteExoscale[0].recordID)
   200  
   201  	assert.Equal(t, 1, len(updateExoscale))
   202  	assert.Equal(t, domainIDs[0], updateExoscale[0].domainID)
   203  	assert.Equal(t, *groups[domainIDs[0]][0].ID, *updateExoscale[0].record.ID)
   204  }
   205  
   206  func TestExoscaleMerge_NoUpdateOnTTL0Changes(t *testing.T) {
   207  	updateOld := []*endpoint.Endpoint{
   208  		{
   209  			DNSName:    "name1",
   210  			Targets:    endpoint.Targets{"target1"},
   211  			RecordTTL:  endpoint.TTL(1),
   212  			RecordType: endpoint.RecordTypeA,
   213  		},
   214  		{
   215  			DNSName:    "name2",
   216  			Targets:    endpoint.Targets{"target2"},
   217  			RecordTTL:  endpoint.TTL(1),
   218  			RecordType: endpoint.RecordTypeA,
   219  		},
   220  	}
   221  
   222  	updateNew := []*endpoint.Endpoint{
   223  		{
   224  			DNSName:    "name1",
   225  			Targets:    endpoint.Targets{"target1"},
   226  			RecordTTL:  endpoint.TTL(0),
   227  			RecordType: endpoint.RecordTypeCNAME,
   228  		},
   229  		{
   230  			DNSName:    "name2",
   231  			Targets:    endpoint.Targets{"target2"},
   232  			RecordTTL:  endpoint.TTL(0),
   233  			RecordType: endpoint.RecordTypeCNAME,
   234  		},
   235  	}
   236  
   237  	assert.Equal(t, 0, len(merge(updateOld, updateNew)))
   238  }
   239  
   240  func TestExoscaleMerge_UpdateOnTTLChanges(t *testing.T) {
   241  	updateOld := []*endpoint.Endpoint{
   242  		{
   243  			DNSName:    "name1",
   244  			Targets:    endpoint.Targets{"target1"},
   245  			RecordTTL:  endpoint.TTL(1),
   246  			RecordType: endpoint.RecordTypeCNAME,
   247  		},
   248  		{
   249  			DNSName:    "name2",
   250  			Targets:    endpoint.Targets{"target2"},
   251  			RecordTTL:  endpoint.TTL(1),
   252  			RecordType: endpoint.RecordTypeCNAME,
   253  		},
   254  	}
   255  
   256  	updateNew := []*endpoint.Endpoint{
   257  		{
   258  			DNSName:    "name1",
   259  			Targets:    endpoint.Targets{"target1"},
   260  			RecordTTL:  endpoint.TTL(77),
   261  			RecordType: endpoint.RecordTypeCNAME,
   262  		},
   263  		{
   264  			DNSName:    "name2",
   265  			Targets:    endpoint.Targets{"target2"},
   266  			RecordTTL:  endpoint.TTL(10),
   267  			RecordType: endpoint.RecordTypeCNAME,
   268  		},
   269  	}
   270  
   271  	merged := merge(updateOld, updateNew)
   272  	assert.Equal(t, 2, len(merged))
   273  	assert.Equal(t, "name1", merged[0].DNSName)
   274  }
   275  
   276  func TestExoscaleMerge_AlwaysUpdateTarget(t *testing.T) {
   277  	updateOld := []*endpoint.Endpoint{
   278  		{
   279  			DNSName:    "name1",
   280  			Targets:    endpoint.Targets{"target1"},
   281  			RecordTTL:  endpoint.TTL(1),
   282  			RecordType: endpoint.RecordTypeCNAME,
   283  		},
   284  		{
   285  			DNSName:    "name2",
   286  			Targets:    endpoint.Targets{"target2"},
   287  			RecordTTL:  endpoint.TTL(1),
   288  			RecordType: endpoint.RecordTypeCNAME,
   289  		},
   290  	}
   291  
   292  	updateNew := []*endpoint.Endpoint{
   293  		{
   294  			DNSName:    "name1",
   295  			Targets:    endpoint.Targets{"target1-changed"},
   296  			RecordTTL:  endpoint.TTL(0),
   297  			RecordType: endpoint.RecordTypeCNAME,
   298  		},
   299  		{
   300  			DNSName:    "name2",
   301  			Targets:    endpoint.Targets{"target2"},
   302  			RecordTTL:  endpoint.TTL(0),
   303  			RecordType: endpoint.RecordTypeCNAME,
   304  		},
   305  	}
   306  
   307  	merged := merge(updateOld, updateNew)
   308  	assert.Equal(t, 1, len(merged))
   309  	assert.Equal(t, "target1-changed", merged[0].Targets[0])
   310  }
   311  
   312  func TestExoscaleMerge_NoUpdateIfTTLUnchanged(t *testing.T) {
   313  	updateOld := []*endpoint.Endpoint{
   314  		{
   315  			DNSName:    "name1",
   316  			Targets:    endpoint.Targets{"target1"},
   317  			RecordTTL:  endpoint.TTL(55),
   318  			RecordType: endpoint.RecordTypeCNAME,
   319  		},
   320  		{
   321  			DNSName:    "name2",
   322  			Targets:    endpoint.Targets{"target2"},
   323  			RecordTTL:  endpoint.TTL(55),
   324  			RecordType: endpoint.RecordTypeCNAME,
   325  		},
   326  	}
   327  
   328  	updateNew := []*endpoint.Endpoint{
   329  		{
   330  			DNSName:    "name1",
   331  			Targets:    endpoint.Targets{"target1"},
   332  			RecordTTL:  endpoint.TTL(55),
   333  			RecordType: endpoint.RecordTypeCNAME,
   334  		},
   335  		{
   336  			DNSName:    "name2",
   337  			Targets:    endpoint.Targets{"target2"},
   338  			RecordTTL:  endpoint.TTL(55),
   339  			RecordType: endpoint.RecordTypeCNAME,
   340  		},
   341  	}
   342  
   343  	merged := merge(updateOld, updateNew)
   344  	assert.Equal(t, 0, len(merged))
   345  }