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 }