sigs.k8s.io/external-dns@v0.14.1/controller/controller_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 controller 18 19 import ( 20 "context" 21 "errors" 22 "math" 23 "reflect" 24 "sort" 25 "testing" 26 "time" 27 28 "github.com/prometheus/client_golang/prometheus" 29 30 "sigs.k8s.io/external-dns/endpoint" 31 "sigs.k8s.io/external-dns/internal/testutils" 32 "sigs.k8s.io/external-dns/pkg/apis/externaldns" 33 "sigs.k8s.io/external-dns/plan" 34 "sigs.k8s.io/external-dns/provider" 35 "sigs.k8s.io/external-dns/registry" 36 37 "github.com/stretchr/testify/assert" 38 "github.com/stretchr/testify/require" 39 ) 40 41 // mockProvider returns mock endpoints and validates changes. 42 type mockProvider struct { 43 provider.BaseProvider 44 RecordsStore []*endpoint.Endpoint 45 ExpectChanges *plan.Changes 46 } 47 48 type filteredMockProvider struct { 49 provider.BaseProvider 50 domainFilter endpoint.DomainFilter 51 RecordsStore []*endpoint.Endpoint 52 RecordsCallCount int 53 ApplyChangesCalls []*plan.Changes 54 } 55 56 type errorMockProvider struct { 57 mockProvider 58 } 59 60 func (p *filteredMockProvider) GetDomainFilter() endpoint.DomainFilter { 61 return p.domainFilter 62 } 63 64 // Records returns the desired mock endpoints. 65 func (p *filteredMockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) { 66 p.RecordsCallCount++ 67 return p.RecordsStore, nil 68 } 69 70 // ApplyChanges stores all calls for later check 71 func (p *filteredMockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error { 72 p.ApplyChangesCalls = append(p.ApplyChangesCalls, changes) 73 return nil 74 } 75 76 // Records returns the desired mock endpoints. 77 func (p *mockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) { 78 return p.RecordsStore, nil 79 } 80 81 func (p *errorMockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) { 82 return nil, errors.New("error for testing") 83 } 84 85 // ApplyChanges validates that the passed in changes satisfy the assumptions. 86 func (p *mockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error { 87 if err := verifyEndpoints(changes.Create, p.ExpectChanges.Create); err != nil { 88 return err 89 } 90 91 if err := verifyEndpoints(changes.UpdateNew, p.ExpectChanges.UpdateNew); err != nil { 92 return err 93 } 94 95 if err := verifyEndpoints(changes.UpdateOld, p.ExpectChanges.UpdateOld); err != nil { 96 return err 97 } 98 99 if err := verifyEndpoints(changes.Delete, p.ExpectChanges.Delete); err != nil { 100 return err 101 } 102 103 if !reflect.DeepEqual(ctx.Value(provider.RecordsContextKey), p.RecordsStore) { 104 return errors.New("context is wrong") 105 } 106 return nil 107 } 108 109 func verifyEndpoints(actual, expected []*endpoint.Endpoint) error { 110 if len(actual) != len(expected) { 111 return errors.New("number of records is wrong") 112 } 113 sort.Slice(actual, func(i, j int) bool { 114 return actual[i].DNSName < actual[j].DNSName 115 }) 116 for i := range actual { 117 if actual[i].DNSName != expected[i].DNSName || !actual[i].Targets.Same(expected[i].Targets) { 118 return errors.New("record is wrong") 119 } 120 } 121 return nil 122 } 123 124 // newMockProvider creates a new mockProvider returning the given endpoints and validating the desired changes. 125 func newMockProvider(endpoints []*endpoint.Endpoint, changes *plan.Changes) provider.Provider { 126 dnsProvider := &mockProvider{ 127 RecordsStore: endpoints, 128 ExpectChanges: changes, 129 } 130 131 return dnsProvider 132 } 133 134 // TestRunOnce tests that RunOnce correctly orchestrates the different components. 135 func TestRunOnce(t *testing.T) { 136 // Fake some desired endpoints coming from our source. 137 source := new(testutils.MockSource) 138 cfg := externaldns.NewConfig() 139 cfg.ManagedDNSRecordTypes = []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME} 140 source.On("Endpoints").Return([]*endpoint.Endpoint{ 141 { 142 DNSName: "create-record", 143 RecordType: endpoint.RecordTypeA, 144 Targets: endpoint.Targets{"1.2.3.4"}, 145 }, 146 { 147 DNSName: "update-record", 148 RecordType: endpoint.RecordTypeA, 149 Targets: endpoint.Targets{"8.8.4.4"}, 150 }, 151 { 152 DNSName: "create-aaaa-record", 153 RecordType: endpoint.RecordTypeAAAA, 154 Targets: endpoint.Targets{"2001:DB8::1"}, 155 }, 156 { 157 DNSName: "update-aaaa-record", 158 RecordType: endpoint.RecordTypeAAAA, 159 Targets: endpoint.Targets{"2001:DB8::2"}, 160 }, 161 }, nil) 162 163 // Fake some existing records in our DNS provider and validate some desired changes. 164 provider := newMockProvider( 165 []*endpoint.Endpoint{ 166 { 167 DNSName: "update-record", 168 RecordType: endpoint.RecordTypeA, 169 Targets: endpoint.Targets{"8.8.8.8"}, 170 }, 171 { 172 DNSName: "delete-record", 173 RecordType: endpoint.RecordTypeA, 174 Targets: endpoint.Targets{"4.3.2.1"}, 175 }, 176 { 177 DNSName: "update-aaaa-record", 178 RecordType: endpoint.RecordTypeAAAA, 179 Targets: endpoint.Targets{"2001:DB8::3"}, 180 }, 181 { 182 DNSName: "delete-aaaa-record", 183 RecordType: endpoint.RecordTypeAAAA, 184 Targets: endpoint.Targets{"2001:DB8::4"}, 185 }, 186 }, 187 &plan.Changes{ 188 Create: []*endpoint.Endpoint{ 189 {DNSName: "create-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1"}}, 190 {DNSName: "create-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"1.2.3.4"}}, 191 }, 192 UpdateNew: []*endpoint.Endpoint{ 193 {DNSName: "update-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::2"}}, 194 {DNSName: "update-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"8.8.4.4"}}, 195 }, 196 UpdateOld: []*endpoint.Endpoint{ 197 {DNSName: "update-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::3"}}, 198 {DNSName: "update-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"8.8.8.8"}}, 199 }, 200 Delete: []*endpoint.Endpoint{ 201 {DNSName: "delete-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::4"}}, 202 {DNSName: "delete-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"4.3.2.1"}}, 203 }, 204 }, 205 ) 206 207 r, err := registry.NewNoopRegistry(provider) 208 require.NoError(t, err) 209 210 // Run our controller once to trigger the validation. 211 ctrl := &Controller{ 212 Source: source, 213 Registry: r, 214 Policy: &plan.SyncPolicy{}, 215 ManagedRecordTypes: cfg.ManagedDNSRecordTypes, 216 } 217 218 assert.NoError(t, ctrl.RunOnce(context.Background())) 219 220 // Validate that the mock source was called. 221 source.AssertExpectations(t) 222 // check the verified records 223 assert.Equal(t, math.Float64bits(1), valueFromMetric(verifiedARecords)) 224 assert.Equal(t, math.Float64bits(1), valueFromMetric(verifiedAAAARecords)) 225 } 226 227 func valueFromMetric(metric prometheus.Gauge) uint64 { 228 ref := reflect.ValueOf(metric) 229 return reflect.Indirect(ref).FieldByName("valBits").Uint() 230 } 231 232 func TestShouldRunOnce(t *testing.T) { 233 ctrl := &Controller{Interval: 10 * time.Minute, MinEventSyncInterval: 5 * time.Second} 234 235 now := time.Now() 236 237 // First run of Run loop should execute RunOnce 238 assert.True(t, ctrl.ShouldRunOnce(now)) 239 240 // Second run should not 241 assert.False(t, ctrl.ShouldRunOnce(now)) 242 243 now = now.Add(10 * time.Second) 244 // Changes happen in ingresses or services 245 ctrl.ScheduleRunOnce(now) 246 ctrl.ScheduleRunOnce(now) 247 248 // Because we batch changes, ShouldRunOnce returns False at first 249 assert.False(t, ctrl.ShouldRunOnce(now)) 250 assert.False(t, ctrl.ShouldRunOnce(now.Add(100*time.Microsecond))) 251 252 // But after MinInterval we should run reconciliation 253 now = now.Add(5 * time.Second) 254 assert.True(t, ctrl.ShouldRunOnce(now)) 255 256 // But just one time 257 assert.False(t, ctrl.ShouldRunOnce(now)) 258 259 // We should wait maximum possible time after last reconciliation started 260 now = now.Add(10*time.Minute - time.Second) 261 assert.False(t, ctrl.ShouldRunOnce(now)) 262 263 // After exactly Interval it's OK again to reconcile 264 now = now.Add(time.Second) 265 assert.True(t, ctrl.ShouldRunOnce(now)) 266 267 // But not two times 268 assert.False(t, ctrl.ShouldRunOnce(now)) 269 270 // Multiple ingresses or services changes, closer than MinInterval from each other 271 firstChangeTime := now 272 secondChangeTime := firstChangeTime.Add(time.Second) 273 // First change 274 ctrl.ScheduleRunOnce(firstChangeTime) 275 // Second change 276 ctrl.ScheduleRunOnce(secondChangeTime) 277 // Should not postpone the reconciliation further than firstChangeTime + MinInterval 278 now = now.Add(ctrl.MinEventSyncInterval) 279 assert.True(t, ctrl.ShouldRunOnce(now)) 280 } 281 282 func testControllerFiltersDomains(t *testing.T, configuredEndpoints []*endpoint.Endpoint, domainFilter endpoint.DomainFilter, providerEndpoints []*endpoint.Endpoint, expectedChanges []*plan.Changes) { 283 t.Helper() 284 cfg := externaldns.NewConfig() 285 cfg.ManagedDNSRecordTypes = []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME} 286 287 source := new(testutils.MockSource) 288 source.On("Endpoints").Return(configuredEndpoints, nil) 289 290 // Fake some existing records in our DNS provider and validate some desired changes. 291 provider := &filteredMockProvider{ 292 RecordsStore: providerEndpoints, 293 } 294 r, err := registry.NewNoopRegistry(provider) 295 296 require.NoError(t, err) 297 298 ctrl := &Controller{ 299 Source: source, 300 Registry: r, 301 Policy: &plan.SyncPolicy{}, 302 DomainFilter: domainFilter, 303 ManagedRecordTypes: cfg.ManagedDNSRecordTypes, 304 } 305 306 assert.NoError(t, ctrl.RunOnce(context.Background())) 307 assert.Equal(t, 1, provider.RecordsCallCount) 308 require.Len(t, provider.ApplyChangesCalls, len(expectedChanges)) 309 for i, change := range expectedChanges { 310 assert.Equal(t, *change, *provider.ApplyChangesCalls[i]) 311 } 312 } 313 314 func TestControllerSkipsEmptyChanges(t *testing.T) { 315 testControllerFiltersDomains( 316 t, 317 []*endpoint.Endpoint{ 318 { 319 DNSName: "create-record.other.tld", 320 RecordType: endpoint.RecordTypeA, 321 Targets: endpoint.Targets{"1.2.3.4"}, 322 }, 323 { 324 DNSName: "some-record.used.tld", 325 RecordType: endpoint.RecordTypeA, 326 Targets: endpoint.Targets{"8.8.8.8"}, 327 }, 328 }, 329 endpoint.NewDomainFilter([]string{"used.tld"}), 330 []*endpoint.Endpoint{ 331 { 332 DNSName: "some-record.used.tld", 333 RecordType: endpoint.RecordTypeA, 334 Targets: endpoint.Targets{"8.8.8.8"}, 335 }, 336 }, 337 []*plan.Changes{}, 338 ) 339 } 340 341 func TestWhenNoFilterControllerConsidersAllComain(t *testing.T) { 342 testControllerFiltersDomains( 343 t, 344 []*endpoint.Endpoint{ 345 { 346 DNSName: "create-record.other.tld", 347 RecordType: endpoint.RecordTypeA, 348 Targets: endpoint.Targets{"1.2.3.4"}, 349 }, 350 { 351 DNSName: "some-record.used.tld", 352 RecordType: endpoint.RecordTypeA, 353 Targets: endpoint.Targets{"8.8.8.8"}, 354 }, 355 }, 356 endpoint.DomainFilter{}, 357 []*endpoint.Endpoint{ 358 { 359 DNSName: "some-record.used.tld", 360 RecordType: endpoint.RecordTypeA, 361 Targets: endpoint.Targets{"8.8.8.8"}, 362 }, 363 }, 364 []*plan.Changes{ 365 { 366 Create: []*endpoint.Endpoint{ 367 { 368 DNSName: "create-record.other.tld", 369 RecordType: endpoint.RecordTypeA, 370 Targets: endpoint.Targets{"1.2.3.4"}, 371 }, 372 }, 373 }, 374 }, 375 ) 376 } 377 378 func TestWhenMultipleControllerConsidersAllFilteredComain(t *testing.T) { 379 testControllerFiltersDomains( 380 t, 381 []*endpoint.Endpoint{ 382 { 383 DNSName: "create-record.other.tld", 384 RecordType: endpoint.RecordTypeA, 385 Targets: endpoint.Targets{"1.2.3.4"}, 386 }, 387 { 388 DNSName: "some-record.used.tld", 389 RecordType: endpoint.RecordTypeA, 390 Targets: endpoint.Targets{"1.1.1.1"}, 391 }, 392 { 393 DNSName: "create-record.unused.tld", 394 RecordType: endpoint.RecordTypeA, 395 Targets: endpoint.Targets{"1.2.3.4"}, 396 }, 397 }, 398 endpoint.NewDomainFilter([]string{"used.tld", "other.tld"}), 399 []*endpoint.Endpoint{ 400 { 401 DNSName: "some-record.used.tld", 402 RecordType: endpoint.RecordTypeA, 403 Targets: endpoint.Targets{"8.8.8.8"}, 404 }, 405 }, 406 []*plan.Changes{ 407 { 408 Create: []*endpoint.Endpoint{ 409 { 410 DNSName: "create-record.other.tld", 411 RecordType: endpoint.RecordTypeA, 412 Targets: endpoint.Targets{"1.2.3.4"}, 413 }, 414 }, 415 UpdateOld: []*endpoint.Endpoint{ 416 { 417 DNSName: "some-record.used.tld", 418 RecordType: endpoint.RecordTypeA, 419 Targets: endpoint.Targets{"8.8.8.8"}, 420 Labels: endpoint.Labels{}, 421 }, 422 }, 423 UpdateNew: []*endpoint.Endpoint{ 424 { 425 DNSName: "some-record.used.tld", 426 RecordType: endpoint.RecordTypeA, 427 Targets: endpoint.Targets{"1.1.1.1"}, 428 Labels: endpoint.Labels{ 429 "owner": "", 430 }, 431 }, 432 }, 433 }, 434 }, 435 ) 436 } 437 438 func TestVerifyARecords(t *testing.T) { 439 testControllerFiltersDomains( 440 t, 441 []*endpoint.Endpoint{ 442 { 443 DNSName: "create-record.used.tld", 444 RecordType: endpoint.RecordTypeA, 445 Targets: endpoint.Targets{"1.2.3.4"}, 446 }, 447 { 448 DNSName: "some-record.used.tld", 449 RecordType: endpoint.RecordTypeA, 450 Targets: endpoint.Targets{"8.8.8.8"}, 451 }, 452 }, 453 endpoint.NewDomainFilter([]string{"used.tld"}), 454 []*endpoint.Endpoint{ 455 { 456 DNSName: "some-record.used.tld", 457 RecordType: endpoint.RecordTypeA, 458 Targets: endpoint.Targets{"8.8.8.8"}, 459 }, 460 { 461 DNSName: "create-record.used.tld", 462 RecordType: endpoint.RecordTypeA, 463 Targets: endpoint.Targets{"1.2.3.4"}, 464 }, 465 }, 466 []*plan.Changes{}, 467 ) 468 assert.Equal(t, math.Float64bits(2), valueFromMetric(verifiedARecords)) 469 470 testControllerFiltersDomains( 471 t, 472 []*endpoint.Endpoint{ 473 { 474 DNSName: "some-record.1.used.tld", 475 RecordType: endpoint.RecordTypeA, 476 Targets: endpoint.Targets{"1.2.3.4"}, 477 }, 478 { 479 DNSName: "some-record.2.used.tld", 480 RecordType: endpoint.RecordTypeA, 481 Targets: endpoint.Targets{"8.8.8.8"}, 482 }, 483 { 484 DNSName: "some-record.3.used.tld", 485 RecordType: endpoint.RecordTypeA, 486 Targets: endpoint.Targets{"24.24.24.24"}, 487 }, 488 }, 489 endpoint.NewDomainFilter([]string{"used.tld"}), 490 []*endpoint.Endpoint{ 491 { 492 DNSName: "some-record.1.used.tld", 493 RecordType: endpoint.RecordTypeA, 494 Targets: endpoint.Targets{"1.2.3.4"}, 495 }, 496 { 497 DNSName: "some-record.2.used.tld", 498 RecordType: endpoint.RecordTypeA, 499 Targets: endpoint.Targets{"8.8.8.8"}, 500 }, 501 }, 502 []*plan.Changes{{ 503 Create: []*endpoint.Endpoint{ 504 { 505 DNSName: "some-record.3.used.tld", 506 RecordType: endpoint.RecordTypeA, 507 Targets: endpoint.Targets{"24.24.24.24"}, 508 }, 509 }, 510 }}, 511 ) 512 assert.Equal(t, math.Float64bits(2), valueFromMetric(verifiedARecords)) 513 assert.Equal(t, math.Float64bits(0), valueFromMetric(verifiedAAAARecords)) 514 } 515 516 func TestVerifyAAAARecords(t *testing.T) { 517 testControllerFiltersDomains( 518 t, 519 []*endpoint.Endpoint{ 520 { 521 DNSName: "create-record.used.tld", 522 RecordType: endpoint.RecordTypeAAAA, 523 Targets: endpoint.Targets{"2001:DB8::1"}, 524 }, 525 { 526 DNSName: "some-record.used.tld", 527 RecordType: endpoint.RecordTypeAAAA, 528 Targets: endpoint.Targets{"2001:DB8::2"}, 529 }, 530 }, 531 endpoint.NewDomainFilter([]string{"used.tld"}), 532 []*endpoint.Endpoint{ 533 { 534 DNSName: "some-record.used.tld", 535 RecordType: endpoint.RecordTypeAAAA, 536 Targets: endpoint.Targets{"2001:DB8::2"}, 537 }, 538 { 539 DNSName: "create-record.used.tld", 540 RecordType: endpoint.RecordTypeAAAA, 541 Targets: endpoint.Targets{"2001:DB8::1"}, 542 }, 543 }, 544 []*plan.Changes{}, 545 ) 546 assert.Equal(t, math.Float64bits(2), valueFromMetric(verifiedAAAARecords)) 547 548 testControllerFiltersDomains( 549 t, 550 []*endpoint.Endpoint{ 551 { 552 DNSName: "some-record.1.used.tld", 553 RecordType: endpoint.RecordTypeAAAA, 554 Targets: endpoint.Targets{"2001:DB8::1"}, 555 }, 556 { 557 DNSName: "some-record.2.used.tld", 558 RecordType: endpoint.RecordTypeAAAA, 559 Targets: endpoint.Targets{"2001:DB8::2"}, 560 }, 561 { 562 DNSName: "some-record.3.used.tld", 563 RecordType: endpoint.RecordTypeAAAA, 564 Targets: endpoint.Targets{"2001:DB8::3"}, 565 }, 566 }, 567 endpoint.NewDomainFilter([]string{"used.tld"}), 568 []*endpoint.Endpoint{ 569 { 570 DNSName: "some-record.1.used.tld", 571 RecordType: endpoint.RecordTypeAAAA, 572 Targets: endpoint.Targets{"2001:DB8::1"}, 573 }, 574 { 575 DNSName: "some-record.2.used.tld", 576 RecordType: endpoint.RecordTypeAAAA, 577 Targets: endpoint.Targets{"2001:DB8::2"}, 578 }, 579 }, 580 []*plan.Changes{{ 581 Create: []*endpoint.Endpoint{ 582 { 583 DNSName: "some-record.3.used.tld", 584 RecordType: endpoint.RecordTypeAAAA, 585 Targets: endpoint.Targets{"2001:DB8::3"}, 586 }, 587 }, 588 }}, 589 ) 590 assert.Equal(t, math.Float64bits(0), valueFromMetric(verifiedARecords)) 591 assert.Equal(t, math.Float64bits(2), valueFromMetric(verifiedAAAARecords)) 592 } 593 594 func TestARecords(t *testing.T) { 595 testControllerFiltersDomains( 596 t, 597 []*endpoint.Endpoint{ 598 { 599 DNSName: "record1.used.tld", 600 RecordType: endpoint.RecordTypeA, 601 Targets: endpoint.Targets{"1.2.3.4"}, 602 }, 603 { 604 DNSName: "record2.used.tld", 605 RecordType: endpoint.RecordTypeA, 606 Targets: endpoint.Targets{"8.8.8.8"}, 607 }, 608 { 609 DNSName: "_mysql-svc._tcp.mysql.used.tld", 610 RecordType: endpoint.RecordTypeSRV, 611 Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"}, 612 }, 613 }, 614 endpoint.NewDomainFilter([]string{"used.tld"}), 615 []*endpoint.Endpoint{ 616 { 617 DNSName: "record1.used.tld", 618 RecordType: endpoint.RecordTypeA, 619 Targets: endpoint.Targets{"1.2.3.4"}, 620 }, 621 { 622 DNSName: "_mysql-svc._tcp.mysql.used.tld", 623 RecordType: endpoint.RecordTypeSRV, 624 Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"}, 625 }, 626 }, 627 []*plan.Changes{{ 628 Create: []*endpoint.Endpoint{ 629 { 630 DNSName: "record2.used.tld", 631 RecordType: endpoint.RecordTypeA, 632 Targets: endpoint.Targets{"8.8.8.8"}, 633 }, 634 }, 635 }}, 636 ) 637 assert.Equal(t, math.Float64bits(2), valueFromMetric(sourceARecords)) 638 assert.Equal(t, math.Float64bits(1), valueFromMetric(registryARecords)) 639 } 640 641 func TestAAAARecords(t *testing.T) { 642 testControllerFiltersDomains( 643 t, 644 []*endpoint.Endpoint{ 645 { 646 DNSName: "record1.used.tld", 647 RecordType: endpoint.RecordTypeAAAA, 648 Targets: endpoint.Targets{"2001:DB8::1"}, 649 }, 650 { 651 DNSName: "record2.used.tld", 652 RecordType: endpoint.RecordTypeAAAA, 653 Targets: endpoint.Targets{"2001:DB8::2"}, 654 }, 655 { 656 DNSName: "_mysql-svc._tcp.mysql.used.tld", 657 RecordType: endpoint.RecordTypeSRV, 658 Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"}, 659 }, 660 }, 661 endpoint.NewDomainFilter([]string{"used.tld"}), 662 []*endpoint.Endpoint{ 663 { 664 DNSName: "record1.used.tld", 665 RecordType: endpoint.RecordTypeAAAA, 666 Targets: endpoint.Targets{"2001:DB8::1"}, 667 }, 668 { 669 DNSName: "_mysql-svc._tcp.mysql.used.tld", 670 RecordType: endpoint.RecordTypeSRV, 671 Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"}, 672 }, 673 }, 674 []*plan.Changes{{ 675 Create: []*endpoint.Endpoint{ 676 { 677 DNSName: "record2.used.tld", 678 RecordType: endpoint.RecordTypeAAAA, 679 Targets: endpoint.Targets{"2001:DB8::2"}, 680 }, 681 }, 682 }}, 683 ) 684 assert.Equal(t, math.Float64bits(2), valueFromMetric(sourceAAAARecords)) 685 assert.Equal(t, math.Float64bits(1), valueFromMetric(registryAAAARecords)) 686 }