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 }