github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/k8s/configuration_test.go (about) 1 package k8s 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/google/go-cmp/cmp" 9 conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1" 10 conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1" 11 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/validation" 12 networking "k8s.io/api/networking/v1beta1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 ) 15 16 func createTestConfiguration() *Configuration { 17 lbc := LoadBalancerController{ 18 ingressClass: "nginx", 19 useIngressClassOnly: true, 20 } 21 isPlus := false 22 appProtectEnabled := false 23 internalRoutesEnabled := false 24 isTLSPassthroughEnabled := true 25 snippetsEnabled := true 26 return NewConfiguration( 27 lbc.HasCorrectIngressClass, 28 isPlus, 29 appProtectEnabled, 30 internalRoutesEnabled, 31 validation.NewVirtualServerValidator(isTLSPassthroughEnabled), 32 validation.NewGlobalConfigurationValidator(map[int]bool{ 33 80: true, 34 443: true, 35 }), 36 validation.NewTransportServerValidator(isTLSPassthroughEnabled, snippetsEnabled, isPlus), 37 isTLSPassthroughEnabled, 38 snippetsEnabled, 39 ) 40 } 41 42 func TestAddIngressForRegularIngress(t *testing.T) { 43 configuration := createTestConfiguration() 44 45 // no problems are expected for all cases 46 var expectedProblems []ConfigurationProblem 47 48 // Add a new Ingress 49 50 ing := createTestIngress("ingress", "foo.example.com") 51 expectedChanges := []ResourceChange{ 52 { 53 Op: AddOrUpdate, 54 Resource: &IngressConfiguration{ 55 Ingress: ing, 56 ValidHosts: map[string]bool{ 57 "foo.example.com": true, 58 }, 59 ChildWarnings: map[string][]string{}, 60 }, 61 }, 62 } 63 64 changes, problems := configuration.AddOrUpdateIngress(ing) 65 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 66 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 67 } 68 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 69 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 70 } 71 72 // Update the Ingress 73 74 updatedIng := ing.DeepCopy() 75 updatedIng.Annotations["nginx.org/max_fails"] = "1" 76 77 expectedChanges = []ResourceChange{ 78 { 79 Op: AddOrUpdate, 80 Resource: &IngressConfiguration{ 81 Ingress: updatedIng, 82 ValidHosts: map[string]bool{ 83 "foo.example.com": true, 84 }, 85 ChildWarnings: map[string][]string{}, 86 }, 87 }, 88 } 89 90 changes, problems = configuration.AddOrUpdateIngress(updatedIng) 91 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 92 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 93 } 94 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 95 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 96 } 97 98 // Make the Ingress invalid 99 100 invalidIng := updatedIng.DeepCopy() 101 invalidIng.Generation++ 102 invalidIng.Spec.Rules = []networking.IngressRule{ 103 { 104 Host: "foo.example.com", 105 IngressRuleValue: networking.IngressRuleValue{}, 106 }, 107 { 108 Host: "foo.example.com", 109 IngressRuleValue: networking.IngressRuleValue{}, 110 }, 111 } 112 113 expectedChanges = []ResourceChange{ 114 { 115 Op: Delete, 116 Resource: &IngressConfiguration{ 117 Ingress: updatedIng, 118 ValidHosts: map[string]bool{ 119 "foo.example.com": true, 120 }, 121 ChildWarnings: map[string][]string{}, 122 }, 123 Error: `spec.rules[1].host: Duplicate value: "foo.example.com"`, 124 }, 125 } 126 127 changes, problems = configuration.AddOrUpdateIngress(invalidIng) 128 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 129 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 130 } 131 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 132 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 133 } 134 135 // Restore the Ingress 136 137 expectedChanges = []ResourceChange{ 138 { 139 Op: AddOrUpdate, 140 Resource: &IngressConfiguration{ 141 Ingress: updatedIng, 142 ValidHosts: map[string]bool{ 143 "foo.example.com": true, 144 }, 145 ChildWarnings: map[string][]string{}, 146 }, 147 }, 148 } 149 150 changes, problems = configuration.AddOrUpdateIngress(updatedIng) 151 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 152 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 153 } 154 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 155 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 156 } 157 158 // Update the host of the Ingress 159 160 updatedHostIng := updatedIng.DeepCopy() 161 updatedHostIng.Generation++ 162 updatedHostIng.Spec.Rules = []networking.IngressRule{ 163 { 164 Host: "bar.example.com", 165 IngressRuleValue: networking.IngressRuleValue{}, 166 }, 167 } 168 169 expectedChanges = []ResourceChange{ 170 { 171 Op: AddOrUpdate, 172 Resource: &IngressConfiguration{ 173 Ingress: updatedHostIng, 174 ValidHosts: map[string]bool{ 175 "bar.example.com": true, 176 }, 177 ChildWarnings: map[string][]string{}, 178 }, 179 }, 180 } 181 182 changes, problems = configuration.AddOrUpdateIngress(updatedHostIng) 183 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 184 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 185 } 186 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 187 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 188 } 189 190 // Delete Ingress 191 expectedChanges = []ResourceChange{ 192 { 193 Op: Delete, 194 Resource: &IngressConfiguration{ 195 Ingress: updatedHostIng, 196 ValidHosts: map[string]bool{ 197 "bar.example.com": true, 198 }, 199 ChildWarnings: map[string][]string{}, 200 }, 201 }, 202 } 203 204 changes, problems = configuration.DeleteIngress("default/ingress") 205 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 206 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 207 } 208 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 209 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 210 } 211 } 212 213 func TestAddInvalidIngress(t *testing.T) { 214 configuration := createTestConfiguration() 215 216 ing := createTestIngress("ingress", "foo.example.com", "foo.example.com") 217 218 var expectedChanges []ResourceChange 219 expectedProblems := []ConfigurationProblem{ 220 { 221 Object: ing, 222 IsError: true, 223 Reason: "Rejected", 224 Message: `spec.rules[1].host: Duplicate value: "foo.example.com"`, 225 }, 226 } 227 228 changes, problems := configuration.AddOrUpdateIngress(ing) 229 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 230 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 231 } 232 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 233 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 234 } 235 } 236 237 func TestDeleteNonExistingIngress(t *testing.T) { 238 configuration := createTestConfiguration() 239 240 var expectedChanges []ResourceChange 241 var expectedProblems []ConfigurationProblem 242 243 changes, problems := configuration.DeleteIngress("default/ingress") 244 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 245 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 246 } 247 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 248 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 249 } 250 } 251 252 func TestAddIngressForMergeableIngresses(t *testing.T) { 253 configuration := createTestConfiguration() 254 255 // Add minion-1 256 257 minion1 := createTestIngressMinion("ingress-minion-1", "foo.example.com", "/path-1") 258 var expectedChanges []ResourceChange 259 expectedProblems := []ConfigurationProblem{ 260 { 261 Object: minion1, 262 Reason: "NoIngressMasterFound", 263 Message: "Ingress master is invalid or doesn't exist", 264 }, 265 } 266 267 changes, problems := configuration.AddOrUpdateIngress(minion1) 268 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 269 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 270 } 271 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 272 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 273 } 274 275 // Add master 276 277 master := createTestIngressMaster("ingress-master", "foo.example.com") 278 expectedChanges = []ResourceChange{ 279 { 280 Op: AddOrUpdate, 281 Resource: &IngressConfiguration{ 282 Ingress: master, 283 ValidHosts: map[string]bool{ 284 "foo.example.com": true, 285 }, 286 IsMaster: true, 287 Minions: []*MinionConfiguration{ 288 { 289 Ingress: minion1, 290 ValidPaths: map[string]bool{ 291 "/path-1": true, 292 }, 293 }, 294 }, 295 ChildWarnings: map[string][]string{}, 296 }, 297 }, 298 } 299 expectedProblems = nil 300 301 changes, problems = configuration.AddOrUpdateIngress(master) 302 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 303 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 304 } 305 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 306 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 307 } 308 309 // Add minion-2 310 311 minion2 := createTestIngressMinion("ingress-minion-2", "foo.example.com", "/path-2") 312 expectedChanges = []ResourceChange{ 313 { 314 Op: AddOrUpdate, 315 Resource: &IngressConfiguration{ 316 Ingress: master, 317 ValidHosts: map[string]bool{ 318 "foo.example.com": true, 319 }, 320 IsMaster: true, 321 Minions: []*MinionConfiguration{ 322 { 323 Ingress: minion1, 324 ValidPaths: map[string]bool{ 325 "/path-1": true, 326 }, 327 }, 328 { 329 Ingress: minion2, 330 ValidPaths: map[string]bool{ 331 "/path-2": true, 332 }, 333 }, 334 }, 335 ChildWarnings: map[string][]string{}, 336 }, 337 }, 338 } 339 expectedProblems = nil 340 341 changes, problems = configuration.AddOrUpdateIngress(minion2) 342 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 343 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 344 } 345 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 346 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 347 } 348 349 // Update minion-1 350 351 updatedMinion1 := minion1.DeepCopy() 352 updatedMinion1.Annotations["nginx.org/proxy-connect-timeout"] = "10s" 353 expectedChanges = []ResourceChange{ 354 { 355 Op: AddOrUpdate, 356 Resource: &IngressConfiguration{ 357 Ingress: master, 358 ValidHosts: map[string]bool{ 359 "foo.example.com": true, 360 }, 361 IsMaster: true, 362 Minions: []*MinionConfiguration{ 363 { 364 Ingress: updatedMinion1, 365 ValidPaths: map[string]bool{ 366 "/path-1": true, 367 }, 368 }, 369 { 370 Ingress: minion2, 371 ValidPaths: map[string]bool{ 372 "/path-2": true, 373 }, 374 }, 375 }, 376 ChildWarnings: map[string][]string{}, 377 }, 378 }, 379 } 380 expectedProblems = nil 381 382 changes, problems = configuration.AddOrUpdateIngress(updatedMinion1) 383 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 384 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 385 } 386 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 387 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 388 } 389 390 // Make minion-1 invalid 391 392 invalidMinion1 := updatedMinion1.DeepCopy() 393 invalidMinion1.Generation++ 394 invalidMinion1.Spec.Rules = []networking.IngressRule{ 395 { 396 Host: "example.com", 397 IngressRuleValue: networking.IngressRuleValue{}, 398 }, 399 { 400 Host: "example.com", 401 IngressRuleValue: networking.IngressRuleValue{}, 402 }, 403 } 404 405 expectedChanges = []ResourceChange{ 406 { 407 Op: AddOrUpdate, 408 Resource: &IngressConfiguration{ 409 Ingress: master, 410 ValidHosts: map[string]bool{ 411 "foo.example.com": true, 412 }, 413 IsMaster: true, 414 Minions: []*MinionConfiguration{ 415 { 416 Ingress: minion2, 417 ValidPaths: map[string]bool{ 418 "/path-2": true, 419 }, 420 }, 421 }, 422 ChildWarnings: map[string][]string{}, 423 }, 424 }, 425 } 426 expectedProblems = []ConfigurationProblem{ 427 { 428 Object: invalidMinion1, 429 IsError: true, 430 Reason: "Rejected", 431 Message: `[spec.rules[1].host: Duplicate value: "example.com", spec.rules: Too many: 2: must have at most 1 items]`, 432 }, 433 } 434 435 changes, problems = configuration.AddOrUpdateIngress(invalidMinion1) 436 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 437 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 438 } 439 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 440 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 441 } 442 443 // Restore minion-1 444 445 expectedChanges = []ResourceChange{ 446 { 447 Op: AddOrUpdate, 448 Resource: &IngressConfiguration{ 449 Ingress: master, 450 ValidHosts: map[string]bool{ 451 "foo.example.com": true, 452 }, 453 IsMaster: true, 454 Minions: []*MinionConfiguration{ 455 { 456 Ingress: updatedMinion1, 457 ValidPaths: map[string]bool{ 458 "/path-1": true, 459 }, 460 }, 461 { 462 Ingress: minion2, 463 ValidPaths: map[string]bool{ 464 "/path-2": true, 465 }, 466 }, 467 }, 468 ChildWarnings: map[string][]string{}, 469 }, 470 }, 471 } 472 expectedProblems = nil 473 474 changes, problems = configuration.AddOrUpdateIngress(updatedMinion1) 475 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 476 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 477 } 478 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 479 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 480 } 481 482 // Update host of minion-2 483 484 updatedMinion2 := minion2.DeepCopy() 485 updatedMinion2.Generation++ 486 updatedMinion2.Spec.Rules[0].Host = "bar.example.com" 487 488 expectedChanges = []ResourceChange{ 489 { 490 Op: AddOrUpdate, 491 Resource: &IngressConfiguration{ 492 Ingress: master, 493 ValidHosts: map[string]bool{ 494 "foo.example.com": true, 495 }, 496 IsMaster: true, 497 Minions: []*MinionConfiguration{ 498 { 499 Ingress: updatedMinion1, 500 ValidPaths: map[string]bool{ 501 "/path-1": true, 502 }, 503 }, 504 }, 505 ChildWarnings: map[string][]string{}, 506 }, 507 }, 508 } 509 expectedProblems = []ConfigurationProblem{ 510 { 511 Object: updatedMinion2, 512 Reason: "NoIngressMasterFound", 513 Message: "Ingress master is invalid or doesn't exist", 514 }, 515 } 516 517 changes, problems = configuration.AddOrUpdateIngress(updatedMinion2) 518 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 519 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 520 } 521 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 522 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 523 } 524 525 // Update host of master 526 527 updatedMaster := master.DeepCopy() 528 updatedMaster.Generation++ 529 updatedMaster.Spec.Rules[0].Host = "bar.example.com" 530 531 expectedChanges = []ResourceChange{ 532 { 533 Op: AddOrUpdate, 534 Resource: &IngressConfiguration{ 535 Ingress: updatedMaster, 536 ValidHosts: map[string]bool{ 537 "bar.example.com": true, 538 }, 539 IsMaster: true, 540 Minions: []*MinionConfiguration{ 541 { 542 Ingress: updatedMinion2, 543 ValidPaths: map[string]bool{ 544 "/path-2": true, 545 }, 546 }, 547 }, 548 ChildWarnings: map[string][]string{}, 549 }, 550 }, 551 } 552 expectedProblems = []ConfigurationProblem{ 553 { 554 Object: updatedMinion1, 555 Reason: "NoIngressMasterFound", 556 Message: "Ingress master is invalid or doesn't exist", 557 }, 558 } 559 560 changes, problems = configuration.AddOrUpdateIngress(updatedMaster) 561 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 562 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 563 } 564 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 565 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 566 } 567 568 // Restore host 569 expectedChanges = []ResourceChange{ 570 { 571 Op: AddOrUpdate, 572 Resource: &IngressConfiguration{ 573 Ingress: master, 574 ValidHosts: map[string]bool{ 575 "foo.example.com": true, 576 }, 577 IsMaster: true, 578 Minions: []*MinionConfiguration{ 579 { 580 Ingress: updatedMinion1, 581 ValidPaths: map[string]bool{ 582 "/path-1": true, 583 }, 584 }, 585 }, 586 ChildWarnings: map[string][]string{}, 587 }, 588 }, 589 } 590 expectedProblems = []ConfigurationProblem{ 591 { 592 Object: updatedMinion2, 593 Reason: "NoIngressMasterFound", 594 Message: "Ingress master is invalid or doesn't exist", 595 }, 596 } 597 598 changes, problems = configuration.AddOrUpdateIngress(master) 599 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 600 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 601 } 602 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 603 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 604 } 605 606 // Restore host of minion-2 607 608 expectedChanges = []ResourceChange{ 609 { 610 Op: AddOrUpdate, 611 Resource: &IngressConfiguration{ 612 Ingress: master, 613 ValidHosts: map[string]bool{ 614 "foo.example.com": true, 615 }, 616 IsMaster: true, 617 Minions: []*MinionConfiguration{ 618 { 619 Ingress: updatedMinion1, 620 ValidPaths: map[string]bool{ 621 "/path-1": true, 622 }, 623 }, 624 { 625 Ingress: minion2, 626 ValidPaths: map[string]bool{ 627 "/path-2": true, 628 }, 629 }, 630 }, 631 ChildWarnings: map[string][]string{}, 632 }, 633 }, 634 } 635 expectedProblems = nil 636 637 changes, problems = configuration.AddOrUpdateIngress(minion2) 638 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 639 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 640 } 641 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 642 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 643 } 644 645 // Remove minion-1 646 647 expectedChanges = []ResourceChange{ 648 { 649 Op: AddOrUpdate, 650 Resource: &IngressConfiguration{ 651 Ingress: master, 652 ValidHosts: map[string]bool{ 653 "foo.example.com": true, 654 }, 655 IsMaster: true, 656 Minions: []*MinionConfiguration{ 657 { 658 Ingress: minion2, 659 ValidPaths: map[string]bool{ 660 "/path-2": true, 661 }, 662 }, 663 }, 664 ChildWarnings: map[string][]string{}, 665 }, 666 }, 667 } 668 expectedProblems = nil 669 670 changes, problems = configuration.DeleteIngress("default/ingress-minion-1") 671 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 672 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 673 } 674 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 675 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 676 } 677 678 // Remove master 679 680 expectedChanges = []ResourceChange{ 681 { 682 Op: Delete, 683 Resource: &IngressConfiguration{ 684 Ingress: master, 685 ValidHosts: map[string]bool{ 686 "foo.example.com": true, 687 }, 688 IsMaster: true, 689 Minions: []*MinionConfiguration{ 690 { 691 Ingress: minion2, 692 ValidPaths: map[string]bool{ 693 "/path-2": true, 694 }, 695 }, 696 }, 697 ChildWarnings: map[string][]string{}, 698 }, 699 }, 700 } 701 expectedProblems = []ConfigurationProblem{ 702 { 703 Object: minion2, 704 Reason: "NoIngressMasterFound", 705 Message: "Ingress master is invalid or doesn't exist", 706 }, 707 } 708 709 changes, problems = configuration.DeleteIngress("default/ingress-master") 710 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 711 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 712 } 713 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 714 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 715 } 716 717 // Remove minion-2 718 719 expectedChanges = nil 720 expectedProblems = nil 721 722 changes, problems = configuration.DeleteIngress("default/ingress-minion-2") 723 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 724 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 725 } 726 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 727 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 728 } 729 } 730 731 func TestMinionPathCollisions(t *testing.T) { 732 configuration := createTestConfiguration() 733 734 // Add master 735 736 master := createTestIngressMaster("ingress-master", "foo.example.com") 737 expectedChanges := []ResourceChange{ 738 { 739 Op: AddOrUpdate, 740 Resource: &IngressConfiguration{ 741 Ingress: master, 742 ValidHosts: map[string]bool{ 743 "foo.example.com": true, 744 }, 745 IsMaster: true, 746 ChildWarnings: map[string][]string{}, 747 }, 748 }, 749 } 750 var expectedProblems []ConfigurationProblem 751 752 changes, problems := configuration.AddOrUpdateIngress(master) 753 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 754 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 755 } 756 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 757 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 758 } 759 760 // Add minion-1 761 762 minion1 := createTestIngressMinion("ingress-minion-1", "foo.example.com", "/") 763 expectedChanges = []ResourceChange{ 764 { 765 Op: AddOrUpdate, 766 Resource: &IngressConfiguration{ 767 Ingress: master, 768 ValidHosts: map[string]bool{ 769 "foo.example.com": true, 770 }, 771 IsMaster: true, 772 Minions: []*MinionConfiguration{ 773 { 774 Ingress: minion1, 775 ValidPaths: map[string]bool{ 776 "/": true, 777 }, 778 }, 779 }, 780 ChildWarnings: map[string][]string{}, 781 }, 782 }, 783 } 784 expectedProblems = nil 785 786 changes, problems = configuration.AddOrUpdateIngress(minion1) 787 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 788 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 789 } 790 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 791 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 792 } 793 794 // Add minion-2 795 796 minion2 := createTestIngressMinion("ingress-minion-2", "foo.example.com", "/") 797 expectedChanges = []ResourceChange{ 798 { 799 Op: AddOrUpdate, 800 Resource: &IngressConfiguration{ 801 Ingress: master, 802 ValidHosts: map[string]bool{ 803 "foo.example.com": true, 804 }, 805 IsMaster: true, 806 Minions: []*MinionConfiguration{ 807 { 808 Ingress: minion1, 809 ValidPaths: map[string]bool{ 810 "/": true, 811 }, 812 }, 813 { 814 Ingress: minion2, 815 ValidPaths: map[string]bool{}, 816 }, 817 }, 818 ChildWarnings: map[string][]string{ 819 "default/ingress-minion-2": { 820 "path / is taken by another resource", 821 }, 822 }, 823 }, 824 }, 825 } 826 expectedProblems = nil 827 828 changes, problems = configuration.AddOrUpdateIngress(minion2) 829 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 830 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 831 } 832 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 833 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 834 } 835 836 // Delete minion-1 837 expectedChanges = []ResourceChange{ 838 { 839 Op: AddOrUpdate, 840 Resource: &IngressConfiguration{ 841 Ingress: master, 842 ValidHosts: map[string]bool{ 843 "foo.example.com": true, 844 }, 845 IsMaster: true, 846 Minions: []*MinionConfiguration{ 847 { 848 Ingress: minion2, 849 ValidPaths: map[string]bool{ 850 "/": true, 851 }, 852 }, 853 }, 854 ChildWarnings: map[string][]string{}, 855 }, 856 }, 857 } 858 expectedProblems = nil 859 860 changes, problems = configuration.DeleteIngress("default/ingress-minion-1") 861 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 862 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 863 } 864 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 865 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 866 } 867 } 868 869 func TestAddIngressWithIncorrectClass(t *testing.T) { 870 configuration := createTestConfiguration() 871 872 // Add Ingress with incorrect class 873 874 ing := createTestIngress("regular-ingress", "foo.example.com") 875 ing.Annotations["kubernetes.io/ingress.class"] = "someproxy" 876 877 var expectedChanges []ResourceChange 878 var expectedProblems []ConfigurationProblem 879 880 changes, problems := configuration.AddOrUpdateIngress(ing) 881 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 882 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 883 } 884 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 885 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 886 } 887 888 // Make the class correct 889 890 updatedIng := ing.DeepCopy() 891 updatedIng.Annotations["kubernetes.io/ingress.class"] = "nginx" 892 893 expectedChanges = []ResourceChange{ 894 { 895 Op: AddOrUpdate, 896 Resource: &IngressConfiguration{ 897 Ingress: updatedIng, 898 ValidHosts: map[string]bool{ 899 "foo.example.com": true, 900 }, 901 ChildWarnings: map[string][]string{}, 902 }, 903 }, 904 } 905 expectedProblems = nil 906 907 changes, problems = configuration.AddOrUpdateIngress(updatedIng) 908 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 909 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 910 } 911 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 912 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 913 } 914 915 // Make the class incorrect 916 917 expectedChanges = []ResourceChange{ 918 { 919 Op: Delete, 920 Resource: &IngressConfiguration{ 921 Ingress: updatedIng, 922 ValidHosts: map[string]bool{ 923 "foo.example.com": true, 924 }, 925 ChildWarnings: map[string][]string{}, 926 }, 927 }, 928 } 929 expectedProblems = nil 930 931 changes, problems = configuration.AddOrUpdateIngress(ing) 932 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 933 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 934 } 935 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 936 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 937 } 938 } 939 940 func TestAddVirtualServer(t *testing.T) { 941 configuration := createTestConfiguration() 942 943 // no problems are expected for all cases 944 var expectedProblems []ConfigurationProblem 945 946 // Add a VirtualServer 947 948 vs := createTestVirtualServer("virtualserver", "foo.example.com") 949 expectedChanges := []ResourceChange{ 950 { 951 Op: AddOrUpdate, 952 Resource: &VirtualServerConfiguration{ 953 VirtualServer: vs, 954 }, 955 }, 956 } 957 958 changes, problems := configuration.AddOrUpdateVirtualServer(vs) 959 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 960 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 961 } 962 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 963 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 964 } 965 966 // Update VirtualServer 967 968 updatedVS := vs.DeepCopy() 969 updatedVS.Generation++ 970 updatedVS.Spec.ServerSnippets = "# snippet" 971 972 expectedChanges = []ResourceChange{ 973 { 974 Op: AddOrUpdate, 975 Resource: &VirtualServerConfiguration{ 976 VirtualServer: updatedVS, 977 }, 978 }, 979 } 980 981 changes, problems = configuration.AddOrUpdateVirtualServer(updatedVS) 982 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 983 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 984 } 985 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 986 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 987 } 988 989 // Make VirtualServer invalid 990 991 invalidVS := updatedVS.DeepCopy() 992 invalidVS.Generation++ 993 invalidVS.Spec.Host = "" 994 995 expectedChanges = []ResourceChange{ 996 { 997 Op: Delete, 998 Resource: &VirtualServerConfiguration{ 999 VirtualServer: updatedVS, 1000 }, 1001 Error: "spec.host: Required value", 1002 }, 1003 } 1004 1005 changes, problems = configuration.AddOrUpdateVirtualServer(invalidVS) 1006 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1007 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1008 } 1009 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1010 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1011 } 1012 1013 // Restore VirtualServer 1014 1015 expectedChanges = []ResourceChange{ 1016 { 1017 Op: AddOrUpdate, 1018 Resource: &VirtualServerConfiguration{ 1019 VirtualServer: updatedVS, 1020 }, 1021 }, 1022 } 1023 1024 changes, problems = configuration.AddOrUpdateVirtualServer(updatedVS) 1025 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1026 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1027 } 1028 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1029 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1030 } 1031 1032 // Update VirtualServer host 1033 1034 updatedHostVS := updatedVS.DeepCopy() 1035 updatedHostVS.Generation++ 1036 updatedHostVS.Spec.Host = "bar.example.com" 1037 1038 expectedChanges = []ResourceChange{ 1039 { 1040 Op: AddOrUpdate, 1041 Resource: &VirtualServerConfiguration{ 1042 VirtualServer: updatedHostVS, 1043 }, 1044 }, 1045 } 1046 1047 changes, problems = configuration.AddOrUpdateVirtualServer(updatedHostVS) 1048 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1049 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1050 } 1051 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1052 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1053 } 1054 1055 // Delete VirtualServer 1056 expectedChanges = []ResourceChange{ 1057 { 1058 Op: Delete, 1059 Resource: &VirtualServerConfiguration{ 1060 VirtualServer: updatedHostVS, 1061 }, 1062 }, 1063 } 1064 1065 changes, problems = configuration.DeleteVirtualServer("default/virtualserver") 1066 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1067 t.Errorf("DeleteVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1068 } 1069 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1070 t.Errorf("DeleteVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1071 } 1072 } 1073 1074 func TestAddInvalidVirtualServer(t *testing.T) { 1075 configuration := createTestConfiguration() 1076 1077 vs := createTestVirtualServer("virtualserver", "") 1078 1079 var expectedChanges []ResourceChange 1080 expectedProblems := []ConfigurationProblem{ 1081 { 1082 Object: vs, 1083 IsError: true, 1084 Reason: "Rejected", 1085 Message: "VirtualServer default/virtualserver was rejected with error: spec.host: Required value", 1086 }, 1087 } 1088 1089 changes, problems := configuration.AddOrUpdateVirtualServer(vs) 1090 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1091 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1092 } 1093 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1094 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1095 } 1096 } 1097 1098 func TestAddInvalidVirtualServerWithIncorrectClass(t *testing.T) { 1099 configuration := createTestConfiguration() 1100 1101 // Add VirtualServer with incorrect class 1102 1103 vs := createTestVirtualServer("virtualserver", "example.com") 1104 vs.Spec.IngressClass = "someproxy" 1105 1106 var expectedChanges []ResourceChange 1107 var expectedProblems []ConfigurationProblem 1108 1109 changes, problems := configuration.AddOrUpdateVirtualServer(vs) 1110 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1111 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1112 } 1113 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1114 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1115 } 1116 1117 // Make the class correct 1118 1119 updatedVS := vs.DeepCopy() 1120 updatedVS.Generation++ 1121 updatedVS.Spec.IngressClass = "nginx" 1122 1123 expectedChanges = []ResourceChange{ 1124 { 1125 Op: AddOrUpdate, 1126 Resource: &VirtualServerConfiguration{ 1127 VirtualServer: updatedVS, 1128 }, 1129 }, 1130 } 1131 expectedProblems = nil 1132 1133 changes, problems = configuration.AddOrUpdateVirtualServer(updatedVS) 1134 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1135 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1136 } 1137 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1138 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1139 } 1140 1141 // Make the class incorrect 1142 1143 expectedChanges = []ResourceChange{ 1144 { 1145 Op: Delete, 1146 Resource: &VirtualServerConfiguration{ 1147 VirtualServer: updatedVS, 1148 }, 1149 }, 1150 } 1151 expectedProblems = nil 1152 1153 changes, problems = configuration.AddOrUpdateVirtualServer(vs) 1154 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1155 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1156 } 1157 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1158 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1159 } 1160 } 1161 1162 func TestDeleteNonExistingVirtualServer(t *testing.T) { 1163 configuration := createTestConfiguration() 1164 1165 var expectedChanges []ResourceChange 1166 var expectedProblems []ConfigurationProblem 1167 1168 changes, problems := configuration.DeleteVirtualServer("default/virtualserver") 1169 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1170 t.Errorf("DeleteVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1171 } 1172 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1173 t.Errorf("DeleteVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1174 } 1175 } 1176 1177 func TestAddVirtualServerWithVirtualServerRoutes(t *testing.T) { 1178 configuration := createTestConfiguration() 1179 1180 // Add VirtualServerRoute-1 1181 1182 vsr1 := createTestVirtualServerRoute("virtualserverroute-1", "foo.example.com", "/first") 1183 var expectedChanges []ResourceChange 1184 expectedProblems := []ConfigurationProblem{ 1185 { 1186 Object: vsr1, 1187 Reason: "NoVirtualServerFound", 1188 Message: "VirtualServer is invalid or doesn't exist", 1189 }, 1190 } 1191 1192 changes, problems := configuration.AddOrUpdateVirtualServerRoute(vsr1) 1193 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1194 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1195 } 1196 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1197 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1198 } 1199 1200 // Add VirtualServer 1201 1202 vs := createTestVirtualServerWithRoutes( 1203 "virtualserver", 1204 "foo.example.com", 1205 []conf_v1.Route{ 1206 { 1207 Path: "/first", 1208 Route: "virtualserverroute-1", 1209 }, 1210 { 1211 Path: "/second", 1212 Route: "virtualserverroute-2", 1213 }, 1214 }) 1215 expectedChanges = []ResourceChange{ 1216 { 1217 Op: AddOrUpdate, 1218 Resource: &VirtualServerConfiguration{ 1219 VirtualServer: vs, 1220 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1}, 1221 Warnings: []string{"VirtualServerRoute default/virtualserverroute-2 doesn't exist or invalid"}, 1222 }, 1223 }, 1224 } 1225 expectedProblems = nil 1226 1227 changes, problems = configuration.AddOrUpdateVirtualServer(vs) 1228 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1229 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1230 } 1231 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1232 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1233 } 1234 1235 vsr2 := createTestVirtualServerRoute("virtualserverroute-2", "foo.example.com", "/second") 1236 1237 // Add VirtualServerRoute-2 1238 1239 expectedChanges = []ResourceChange{ 1240 { 1241 Op: AddOrUpdate, 1242 Resource: &VirtualServerConfiguration{ 1243 VirtualServer: vs, 1244 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1, vsr2}, 1245 }, 1246 }, 1247 } 1248 expectedProblems = nil 1249 1250 changes, problems = configuration.AddOrUpdateVirtualServerRoute(vsr2) 1251 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1252 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1253 } 1254 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1255 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1256 } 1257 1258 // Update VirtualServerRoute-1 1259 1260 updatedVSR1 := vsr1.DeepCopy() 1261 updatedVSR1.Generation++ 1262 updatedVSR1.Spec.Subroutes[0].LocationSnippets = "# snippet" 1263 expectedChanges = []ResourceChange{ 1264 { 1265 Op: AddOrUpdate, 1266 Resource: &VirtualServerConfiguration{ 1267 VirtualServer: vs, 1268 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{updatedVSR1, vsr2}, 1269 }, 1270 }, 1271 } 1272 expectedProblems = nil 1273 1274 changes, problems = configuration.AddOrUpdateVirtualServerRoute(updatedVSR1) 1275 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1276 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1277 } 1278 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1279 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1280 } 1281 1282 // Make VirtualServerRoute-1 invalid 1283 1284 invalidVSR1 := updatedVSR1.DeepCopy() 1285 invalidVSR1.Generation++ 1286 invalidVSR1.Spec.Host = "" 1287 expectedChanges = []ResourceChange{ 1288 { 1289 Op: AddOrUpdate, 1290 Resource: &VirtualServerConfiguration{ 1291 VirtualServer: vs, 1292 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr2}, 1293 Warnings: []string{"VirtualServerRoute default/virtualserverroute-1 doesn't exist or invalid"}, 1294 }, 1295 }, 1296 } 1297 expectedProblems = []ConfigurationProblem{ 1298 { 1299 Object: invalidVSR1, 1300 IsError: true, 1301 Reason: "Rejected", 1302 Message: "VirtualServerRoute default/virtualserverroute-1 was rejected with error: spec.host: Required value", 1303 }, 1304 } 1305 1306 changes, problems = configuration.AddOrUpdateVirtualServerRoute(invalidVSR1) 1307 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1308 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1309 } 1310 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1311 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1312 } 1313 1314 // Restore VirtualServerRoute-1 1315 1316 expectedChanges = []ResourceChange{ 1317 { 1318 Op: AddOrUpdate, 1319 Resource: &VirtualServerConfiguration{ 1320 VirtualServer: vs, 1321 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1, vsr2}, 1322 }, 1323 }, 1324 } 1325 expectedProblems = nil 1326 1327 changes, problems = configuration.AddOrUpdateVirtualServerRoute(vsr1) 1328 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1329 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1330 } 1331 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1332 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1333 } 1334 1335 // Make VirtualServerRoute-1 invalid for VirtualServer 1336 1337 invalidForVSVSR1 := vsr1.DeepCopy() 1338 invalidForVSVSR1.Generation++ 1339 invalidForVSVSR1.Spec.Subroutes[0].Path = "/" 1340 expectedChanges = []ResourceChange{ 1341 { 1342 Op: AddOrUpdate, 1343 Resource: &VirtualServerConfiguration{ 1344 VirtualServer: vs, 1345 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr2}, 1346 Warnings: []string{"VirtualServerRoute default/virtualserverroute-1 is invalid: spec.subroutes[0]: Invalid value: \"/\": must start with '/first'"}, 1347 }, 1348 }, 1349 } 1350 expectedProblems = []ConfigurationProblem{ 1351 { 1352 Object: invalidForVSVSR1, 1353 Reason: "Ignored", 1354 Message: "VirtualServer default/virtualserver ignores VirtualServerRoute", 1355 }, 1356 } 1357 1358 changes, problems = configuration.AddOrUpdateVirtualServerRoute(invalidForVSVSR1) 1359 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1360 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1361 } 1362 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1363 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1364 } 1365 1366 // Restore VirtualServerRoute-1 1367 1368 expectedChanges = []ResourceChange{ 1369 { 1370 Op: AddOrUpdate, 1371 Resource: &VirtualServerConfiguration{ 1372 VirtualServer: vs, 1373 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1, vsr2}, 1374 }, 1375 }, 1376 } 1377 expectedProblems = nil 1378 1379 changes, problems = configuration.AddOrUpdateVirtualServerRoute(vsr1) 1380 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1381 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1382 } 1383 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1384 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1385 } 1386 1387 // Update host of VirtualServerRoute-2 1388 1389 updatedVSR2 := vsr2.DeepCopy() 1390 updatedVSR2.Generation++ 1391 updatedVSR2.Spec.Host = "bar.example.com" 1392 expectedChanges = []ResourceChange{ 1393 { 1394 Op: AddOrUpdate, 1395 Resource: &VirtualServerConfiguration{ 1396 VirtualServer: vs, 1397 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1}, 1398 Warnings: []string{"VirtualServerRoute default/virtualserverroute-2 is invalid: spec.host: Invalid value: \"bar.example.com\": must be equal to 'foo.example.com'"}, 1399 }, 1400 }, 1401 } 1402 expectedProblems = []ConfigurationProblem{ 1403 { 1404 Object: updatedVSR2, 1405 Reason: "NoVirtualServerFound", 1406 Message: "VirtualServer is invalid or doesn't exist", 1407 }, 1408 } 1409 1410 changes, problems = configuration.AddOrUpdateVirtualServerRoute(updatedVSR2) 1411 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1412 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1413 } 1414 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1415 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1416 } 1417 1418 // Update host of VirtualServer 1419 1420 updatedVS := vs.DeepCopy() 1421 updatedVS.Generation++ 1422 updatedVS.Spec.Host = "bar.example.com" 1423 expectedChanges = []ResourceChange{ 1424 { 1425 Op: AddOrUpdate, 1426 Resource: &VirtualServerConfiguration{ 1427 VirtualServer: updatedVS, 1428 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{updatedVSR2}, 1429 Warnings: []string{"VirtualServerRoute default/virtualserverroute-1 is invalid: spec.host: Invalid value: \"foo.example.com\": must be equal to 'bar.example.com'"}, 1430 }, 1431 }, 1432 } 1433 expectedProblems = []ConfigurationProblem{ 1434 { 1435 Object: vsr1, 1436 Reason: "NoVirtualServerFound", 1437 Message: "VirtualServer is invalid or doesn't exist", 1438 }, 1439 } 1440 1441 changes, problems = configuration.AddOrUpdateVirtualServer(updatedVS) 1442 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1443 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1444 } 1445 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1446 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1447 } 1448 1449 // Restore host of VirtualServer 1450 1451 expectedChanges = []ResourceChange{ 1452 { 1453 Op: AddOrUpdate, 1454 Resource: &VirtualServerConfiguration{ 1455 VirtualServer: vs, 1456 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1}, 1457 Warnings: []string{"VirtualServerRoute default/virtualserverroute-2 is invalid: spec.host: Invalid value: \"bar.example.com\": must be equal to 'foo.example.com'"}, 1458 }, 1459 }, 1460 } 1461 expectedProblems = []ConfigurationProblem{ 1462 { 1463 Object: updatedVSR2, 1464 Reason: "NoVirtualServerFound", 1465 Message: "VirtualServer is invalid or doesn't exist", 1466 }, 1467 } 1468 1469 changes, problems = configuration.AddOrUpdateVirtualServer(vs) 1470 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1471 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1472 } 1473 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1474 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1475 } 1476 1477 // Restore host of VirtualServerRoute-2 1478 1479 expectedChanges = []ResourceChange{ 1480 { 1481 Op: AddOrUpdate, 1482 Resource: &VirtualServerConfiguration{ 1483 VirtualServer: vs, 1484 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr1, vsr2}, 1485 }, 1486 }, 1487 } 1488 expectedProblems = nil 1489 1490 changes, problems = configuration.AddOrUpdateVirtualServerRoute(vsr2) 1491 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1492 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1493 } 1494 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1495 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1496 } 1497 1498 // Remove VirtualServerRoute-1 1499 1500 expectedChanges = []ResourceChange{ 1501 { 1502 Op: AddOrUpdate, 1503 Resource: &VirtualServerConfiguration{ 1504 VirtualServer: vs, 1505 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr2}, 1506 Warnings: []string{"VirtualServerRoute default/virtualserverroute-1 doesn't exist or invalid"}, 1507 }, 1508 }, 1509 } 1510 expectedProblems = nil 1511 1512 changes, problems = configuration.DeleteVirtualServerRoute("default/virtualserverroute-1") 1513 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1514 t.Errorf("DeleteVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1515 } 1516 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1517 t.Errorf("DeleteVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1518 } 1519 1520 // Remove VirtualServer 1521 1522 expectedChanges = []ResourceChange{ 1523 { 1524 Op: Delete, 1525 Resource: &VirtualServerConfiguration{ 1526 VirtualServer: vs, 1527 VirtualServerRoutes: []*conf_v1.VirtualServerRoute{vsr2}, 1528 Warnings: []string{"VirtualServerRoute default/virtualserverroute-1 doesn't exist or invalid"}, 1529 }, 1530 }, 1531 } 1532 expectedProblems = []ConfigurationProblem{ 1533 { 1534 Object: vsr2, 1535 Reason: "NoVirtualServerFound", 1536 Message: "VirtualServer is invalid or doesn't exist", 1537 }, 1538 } 1539 1540 changes, problems = configuration.DeleteVirtualServer("default/virtualserver") 1541 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1542 t.Errorf("DeleteVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1543 } 1544 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1545 t.Errorf("DeleteVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1546 } 1547 1548 // Remove VirtualServerRoute-2 1549 1550 expectedChanges = nil 1551 expectedProblems = nil 1552 1553 changes, problems = configuration.DeleteVirtualServerRoute("default/virtualserverroute-2") 1554 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1555 t.Errorf("DeleteVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1556 } 1557 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1558 t.Errorf("DeleteVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1559 } 1560 } 1561 1562 func TestAddInvalidVirtualServerRoute(t *testing.T) { 1563 configuration := createTestConfiguration() 1564 1565 vsr := createTestVirtualServerRoute("virtualserverroute", "", "/") 1566 1567 var expectedChanges []ResourceChange 1568 expectedProblems := []ConfigurationProblem{ 1569 { 1570 Object: vsr, 1571 IsError: true, 1572 Reason: "Rejected", 1573 Message: "VirtualServerRoute default/virtualserverroute was rejected with error: spec.host: Required value", 1574 }, 1575 } 1576 1577 changes, problems := configuration.AddOrUpdateVirtualServerRoute(vsr) 1578 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1579 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1580 } 1581 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1582 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1583 } 1584 } 1585 1586 func TestAddVirtualServerWithIncorrectClass(t *testing.T) { 1587 configuration := createTestConfiguration() 1588 1589 vsr := createTestVirtualServerRoute("virtualserver", "foo.example.com", "/") 1590 vsr.Spec.IngressClass = "someproxy" 1591 1592 var expectedChanges []ResourceChange 1593 var expectedProblems []ConfigurationProblem 1594 1595 changes, problems := configuration.AddOrUpdateVirtualServerRoute(vsr) 1596 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1597 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1598 } 1599 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1600 t.Errorf("AddOrUpdateVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1601 } 1602 } 1603 1604 func TestDeleteNonExistingVirtualServerRoute(t *testing.T) { 1605 configuration := createTestConfiguration() 1606 1607 var expectedChanges []ResourceChange 1608 var expectedProblems []ConfigurationProblem 1609 1610 changes, problems := configuration.DeleteVirtualServerRoute("default/virtualserverroute") 1611 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1612 t.Errorf("DeleteVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1613 } 1614 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1615 t.Errorf("DeleteVirtualServerRoute() returned unexpected result (-want +got):\n%s", diff) 1616 } 1617 } 1618 1619 func TestHostCollisions(t *testing.T) { 1620 configuration := createTestConfiguration() 1621 1622 var expectedProblems []ConfigurationProblem 1623 1624 masterIng := createTestIngressMaster("master-ingress", "foo.example.com") 1625 regularIng := createTestIngress("regular-ingress", "foo.example.com", "bar.example.com") 1626 vs := createTestVirtualServer("virtualserver", "foo.example.com") 1627 regularIng2 := createTestIngress("regular-ingress-2", "foo.example.com") 1628 ts := createTestTLSPassthroughTransportServer("transportserver", "foo.example.com") 1629 1630 // Add TransportServer 1631 1632 expectedChanges := []ResourceChange{ 1633 { 1634 Op: AddOrUpdate, 1635 Resource: &TransportServerConfiguration{ 1636 ListenerPort: 0, 1637 TransportServer: ts, 1638 }, 1639 }, 1640 } 1641 expectedProblems = nil 1642 1643 changes, problems := configuration.AddOrUpdateTransportServer(ts) 1644 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1645 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1646 } 1647 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1648 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1649 } 1650 1651 // Add VirtualServer 1652 1653 expectedChanges = []ResourceChange{ 1654 { 1655 Op: Delete, 1656 Resource: &TransportServerConfiguration{ 1657 ListenerPort: 0, 1658 TransportServer: ts, 1659 Warnings: []string{"host foo.example.com is taken by another resource"}, 1660 }, 1661 }, 1662 { 1663 Op: AddOrUpdate, 1664 Resource: &VirtualServerConfiguration{ 1665 VirtualServer: vs, 1666 }, 1667 }, 1668 } 1669 expectedProblems = []ConfigurationProblem{ 1670 { 1671 Object: ts, 1672 IsError: false, 1673 Reason: "Rejected", 1674 Message: "Host is taken by another resource", 1675 }, 1676 } 1677 1678 changes, problems = configuration.AddOrUpdateVirtualServer(vs) 1679 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1680 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1681 } 1682 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1683 t.Errorf("AddOrUpdateVirtualServer() returned unexpected result (-want +got):\n%s", diff) 1684 } 1685 1686 // Add regular Ingress 1687 1688 expectedChanges = []ResourceChange{ 1689 { 1690 Op: Delete, 1691 Resource: &VirtualServerConfiguration{ 1692 VirtualServer: vs, 1693 Warnings: []string{"host foo.example.com is taken by another resource"}, 1694 }, 1695 }, 1696 { 1697 Op: AddOrUpdate, 1698 Resource: &IngressConfiguration{ 1699 Ingress: regularIng, 1700 ValidHosts: map[string]bool{"foo.example.com": true, "bar.example.com": true}, 1701 ChildWarnings: map[string][]string{}, 1702 }, 1703 }, 1704 } 1705 expectedProblems = []ConfigurationProblem{ 1706 { 1707 Object: vs, 1708 IsError: false, 1709 Reason: "Rejected", 1710 Message: "Host is taken by another resource", 1711 }, 1712 } 1713 1714 changes, problems = configuration.AddOrUpdateIngress(regularIng) 1715 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1716 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 1717 } 1718 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1719 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 1720 } 1721 1722 // Add master Ingress 1723 1724 expectedChanges = []ResourceChange{ 1725 { 1726 Op: AddOrUpdate, 1727 Resource: &IngressConfiguration{ 1728 Ingress: regularIng, 1729 ValidHosts: map[string]bool{"bar.example.com": true, "foo.example.com": false}, 1730 Warnings: []string{"host foo.example.com is taken by another resource"}, 1731 ChildWarnings: map[string][]string{}, 1732 }, 1733 }, 1734 { 1735 Op: AddOrUpdate, 1736 Resource: &IngressConfiguration{ 1737 Ingress: masterIng, 1738 IsMaster: true, 1739 ValidHosts: map[string]bool{"foo.example.com": true}, 1740 ChildWarnings: map[string][]string{}, 1741 }, 1742 }, 1743 } 1744 expectedProblems = nil 1745 1746 changes, problems = configuration.AddOrUpdateIngress(masterIng) 1747 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1748 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 1749 } 1750 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1751 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 1752 } 1753 1754 // Add regular Ingress-2 1755 1756 expectedChanges = nil 1757 expectedProblems = []ConfigurationProblem{ 1758 { 1759 Object: regularIng2, 1760 IsError: false, 1761 Reason: "Rejected", 1762 Message: "All hosts are taken by other resources", 1763 }, 1764 } 1765 1766 changes, problems = configuration.AddOrUpdateIngress(regularIng2) 1767 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1768 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 1769 } 1770 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1771 t.Errorf("AddOrUpdateIngress() returned unexpected result (-want +got):\n%s", diff) 1772 } 1773 1774 // Delete regular Ingress-2 1775 expectedChanges = nil 1776 expectedProblems = nil 1777 1778 changes, problems = configuration.DeleteIngress("default/regular-ingress-2") 1779 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1780 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1781 } 1782 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1783 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1784 } 1785 1786 // Delete master Ingress 1787 1788 expectedChanges = []ResourceChange{ 1789 { 1790 Op: Delete, 1791 Resource: &IngressConfiguration{ 1792 Ingress: masterIng, 1793 IsMaster: true, 1794 ValidHosts: map[string]bool{"foo.example.com": true}, 1795 ChildWarnings: map[string][]string{}, 1796 }, 1797 }, 1798 { 1799 Op: AddOrUpdate, 1800 Resource: &IngressConfiguration{ 1801 Ingress: regularIng, 1802 ValidHosts: map[string]bool{"foo.example.com": true, "bar.example.com": true}, 1803 ChildWarnings: map[string][]string{}, 1804 }, 1805 }, 1806 } 1807 expectedProblems = nil 1808 1809 changes, problems = configuration.DeleteIngress("default/master-ingress") 1810 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1811 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1812 } 1813 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1814 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1815 } 1816 1817 // Delete regular Ingress 1818 1819 expectedChanges = []ResourceChange{ 1820 { 1821 Op: Delete, 1822 Resource: &IngressConfiguration{ 1823 Ingress: regularIng, 1824 ValidHosts: map[string]bool{"foo.example.com": true, "bar.example.com": true}, 1825 ChildWarnings: map[string][]string{}, 1826 }, 1827 }, 1828 { 1829 Op: AddOrUpdate, 1830 Resource: &VirtualServerConfiguration{ 1831 VirtualServer: vs, 1832 }, 1833 }, 1834 } 1835 expectedProblems = nil 1836 1837 changes, problems = configuration.DeleteIngress("default/regular-ingress") 1838 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1839 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1840 } 1841 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1842 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1843 } 1844 1845 // Delete VirtualServer 1846 1847 expectedChanges = []ResourceChange{ 1848 { 1849 Op: Delete, 1850 Resource: &VirtualServerConfiguration{ 1851 VirtualServer: vs, 1852 }, 1853 }, 1854 { 1855 Op: AddOrUpdate, 1856 Resource: &TransportServerConfiguration{ 1857 ListenerPort: 0, 1858 TransportServer: ts, 1859 }, 1860 }, 1861 } 1862 expectedProblems = nil 1863 1864 changes, problems = configuration.DeleteVirtualServer("default/virtualserver") 1865 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1866 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1867 } 1868 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1869 t.Errorf("DeleteIngress() returned unexpected result (-want +got):\n%s", diff) 1870 } 1871 } 1872 1873 func TestAddTransportServer(t *testing.T) { 1874 configuration := createTestConfiguration() 1875 1876 listeners := []conf_v1alpha1.Listener{ 1877 { 1878 Name: "tcp-7777", 1879 Port: 7777, 1880 Protocol: "TCP", 1881 }, 1882 } 1883 gc := createTestGlobalConfiguration(listeners) 1884 mustInitGlobalConfiguration(configuration, gc) 1885 1886 ts := createTestTransportServer("transportserver", "tcp-7777", "TCP") 1887 1888 // no problems are expected for all cases 1889 var expectedProblems []ConfigurationProblem 1890 var expectedChanges []ResourceChange 1891 1892 // Add TransportServer 1893 1894 expectedChanges = []ResourceChange{ 1895 { 1896 Op: AddOrUpdate, 1897 Resource: &TransportServerConfiguration{ 1898 ListenerPort: 7777, 1899 TransportServer: ts, 1900 }, 1901 }, 1902 } 1903 1904 changes, problems := configuration.AddOrUpdateTransportServer(ts) 1905 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1906 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1907 } 1908 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1909 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1910 } 1911 1912 // Update TransportServer 1913 1914 updatedTS := ts.DeepCopy() 1915 updatedTS.Generation++ 1916 1917 expectedChanges = []ResourceChange{ 1918 { 1919 Op: AddOrUpdate, 1920 Resource: &TransportServerConfiguration{ 1921 ListenerPort: 7777, 1922 TransportServer: updatedTS, 1923 }, 1924 }, 1925 } 1926 1927 changes, problems = configuration.AddOrUpdateTransportServer(updatedTS) 1928 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1929 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1930 } 1931 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1932 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1933 } 1934 1935 // Make TransportServer invalid 1936 1937 invalidTS := updatedTS.DeepCopy() 1938 invalidTS.Generation++ 1939 invalidTS.Spec.Upstreams = nil 1940 1941 expectedChanges = []ResourceChange{ 1942 { 1943 Op: Delete, 1944 Resource: &TransportServerConfiguration{ 1945 ListenerPort: 7777, 1946 TransportServer: updatedTS, 1947 }, 1948 Error: `spec.action.pass: Not found: "myapp"`, 1949 }, 1950 } 1951 1952 changes, problems = configuration.AddOrUpdateTransportServer(invalidTS) 1953 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1954 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1955 } 1956 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1957 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1958 } 1959 1960 // Restore TransportServer 1961 1962 expectedChanges = []ResourceChange{ 1963 { 1964 Op: AddOrUpdate, 1965 Resource: &TransportServerConfiguration{ 1966 ListenerPort: 7777, 1967 TransportServer: updatedTS, 1968 }, 1969 }, 1970 } 1971 1972 changes, problems = configuration.AddOrUpdateTransportServer(updatedTS) 1973 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1974 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1975 } 1976 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1977 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 1978 } 1979 1980 // Delete TransportServer 1981 1982 expectedChanges = []ResourceChange{ 1983 { 1984 Op: Delete, 1985 Resource: &TransportServerConfiguration{ 1986 ListenerPort: 7777, 1987 TransportServer: updatedTS, 1988 }, 1989 }, 1990 } 1991 1992 changes, problems = configuration.DeleteTransportServer("default/transportserver") 1993 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 1994 t.Errorf("DeleteTransportServer() returned unexpected result (-want +got):\n%s", diff) 1995 } 1996 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 1997 t.Errorf("DeleteTransportServer() returned unexpected result (-want +got):\n%s", diff) 1998 } 1999 } 2000 2001 func TestAddTransportServerForTLSPassthrough(t *testing.T) { 2002 configuration := createTestConfiguration() 2003 2004 ts := createTestTLSPassthroughTransportServer("transportserver", "foo.example.com") 2005 2006 // no problems are expected for all cases 2007 var expectedProblems []ConfigurationProblem 2008 2009 // Add TransportServer 2010 2011 expectedChanges := []ResourceChange{ 2012 { 2013 Op: AddOrUpdate, 2014 Resource: &TransportServerConfiguration{ 2015 ListenerPort: 0, 2016 TransportServer: ts, 2017 }, 2018 }, 2019 } 2020 2021 changes, problems := configuration.AddOrUpdateTransportServer(ts) 2022 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2023 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2024 } 2025 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2026 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2027 } 2028 2029 // DeleteTransportServer 2030 2031 expectedChanges = []ResourceChange{ 2032 { 2033 Op: Delete, 2034 Resource: &TransportServerConfiguration{ 2035 ListenerPort: 0, 2036 TransportServer: ts, 2037 }, 2038 }, 2039 } 2040 2041 changes, problems = configuration.DeleteTransportServer("default/transportserver") 2042 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2043 t.Errorf("DeleteTransportServer() returned unexpected result (-want +got):\n%s", diff) 2044 } 2045 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2046 t.Errorf("DeleteTransportServer() returned unexpected result (-want +got):\n%s", diff) 2047 } 2048 } 2049 2050 func TestListenerFlip(t *testing.T) { 2051 configuration := createTestConfiguration() 2052 2053 listeners := []conf_v1alpha1.Listener{ 2054 { 2055 Name: "tcp-7777", 2056 Port: 7777, 2057 Protocol: "TCP", 2058 }, 2059 { 2060 Name: "tcp-8888", 2061 Port: 8888, 2062 Protocol: "TCP", 2063 }, 2064 } 2065 gc := createTestGlobalConfiguration(listeners) 2066 mustInitGlobalConfiguration(configuration, gc) 2067 2068 ts := createTestTransportServer("transportserver", "tcp-7777", "TCP") 2069 2070 // no problems are expected for all cases 2071 var expectedProblems []ConfigurationProblem 2072 var expectedChanges []ResourceChange 2073 2074 // Add TransportServer 2075 2076 expectedChanges = []ResourceChange{ 2077 { 2078 Op: AddOrUpdate, 2079 Resource: &TransportServerConfiguration{ 2080 ListenerPort: 7777, 2081 TransportServer: ts, 2082 }, 2083 }, 2084 } 2085 2086 changes, problems := configuration.AddOrUpdateTransportServer(ts) 2087 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2088 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2089 } 2090 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2091 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2092 } 2093 2094 // Update TransportServer listener 2095 2096 updatedListenerTS := ts.DeepCopy() 2097 updatedListenerTS.Generation++ 2098 updatedListenerTS.Spec.Listener.Name = "tcp-8888" 2099 2100 expectedChanges = []ResourceChange{ 2101 { 2102 Op: AddOrUpdate, 2103 Resource: &TransportServerConfiguration{ 2104 ListenerPort: 8888, 2105 TransportServer: updatedListenerTS, 2106 }, 2107 }, 2108 } 2109 2110 changes, problems = configuration.AddOrUpdateTransportServer(updatedListenerTS) 2111 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2112 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2113 } 2114 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2115 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2116 } 2117 2118 // Update TransportSever listener to TLS Passthrough 2119 2120 updatedWithPassthroughTS := updatedListenerTS.DeepCopy() 2121 updatedWithPassthroughTS.Generation++ 2122 updatedWithPassthroughTS.Spec.Listener.Name = "tls-passthrough" 2123 updatedWithPassthroughTS.Spec.Listener.Protocol = "TLS_PASSTHROUGH" 2124 updatedWithPassthroughTS.Spec.Host = "example.com" 2125 2126 expectedChanges = []ResourceChange{ 2127 { 2128 Op: Delete, 2129 Resource: &TransportServerConfiguration{ 2130 ListenerPort: 8888, 2131 TransportServer: updatedListenerTS, 2132 }, 2133 }, 2134 { 2135 Op: AddOrUpdate, 2136 Resource: &TransportServerConfiguration{ 2137 ListenerPort: 0, 2138 TransportServer: updatedWithPassthroughTS, 2139 }, 2140 }, 2141 } 2142 2143 changes, problems = configuration.AddOrUpdateTransportServer(updatedWithPassthroughTS) 2144 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2145 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2146 } 2147 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2148 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2149 } 2150 } 2151 2152 func TestAddInvalidTransportServer(t *testing.T) { 2153 configuration := createTestConfiguration() 2154 2155 ts := createTestTransportServer("transportserver", "", "TCP") 2156 2157 expectedProblems := []ConfigurationProblem{ 2158 { 2159 Object: ts, 2160 IsError: true, 2161 Reason: "Rejected", 2162 Message: "TransportServer default/transportserver was rejected with error: spec.listener.name: Required value", 2163 }, 2164 } 2165 var expectedChanges []ResourceChange 2166 2167 changes, problems := configuration.AddOrUpdateTransportServer(ts) 2168 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2169 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2170 } 2171 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2172 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2173 } 2174 } 2175 2176 func TestAddTransportServerWithIncorrectClass(t *testing.T) { 2177 configuration := createTestConfiguration() 2178 2179 // Add TransportServer with incorrect class 2180 2181 ts := createTestTLSPassthroughTransportServer("transportserver", "foo.example.com") 2182 ts.Spec.IngressClass = "someproxy" 2183 2184 var expectedProblems []ConfigurationProblem 2185 var expectedChanges []ResourceChange 2186 2187 changes, problems := configuration.AddOrUpdateTransportServer(ts) 2188 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2189 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2190 } 2191 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2192 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2193 } 2194 2195 // Make the class correct 2196 2197 updatedTS := ts.DeepCopy() 2198 updatedTS.Generation++ 2199 updatedTS.Spec.IngressClass = "nginx" 2200 2201 expectedChanges = []ResourceChange{ 2202 { 2203 Op: AddOrUpdate, 2204 Resource: &TransportServerConfiguration{ 2205 TransportServer: updatedTS, 2206 }, 2207 }, 2208 } 2209 expectedProblems = nil 2210 2211 changes, problems = configuration.AddOrUpdateTransportServer(updatedTS) 2212 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2213 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2214 } 2215 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2216 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2217 } 2218 2219 // Make the class incorrect 2220 2221 expectedChanges = []ResourceChange{ 2222 { 2223 Op: Delete, 2224 Resource: &TransportServerConfiguration{ 2225 TransportServer: updatedTS, 2226 }, 2227 }, 2228 } 2229 expectedProblems = nil 2230 2231 changes, problems = configuration.AddOrUpdateTransportServer(ts) 2232 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2233 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2234 } 2235 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2236 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2237 } 2238 } 2239 2240 func TestAddTransportServerWithNonExistingListener(t *testing.T) { 2241 configuration := createTestConfiguration() 2242 2243 gc := createTestGlobalConfiguration([]conf_v1alpha1.Listener{}) 2244 mustInitGlobalConfiguration(configuration, gc) 2245 2246 ts := createTestTransportServer("transportserver", "tcp-7777", "TCP") 2247 2248 expectedProblems := []ConfigurationProblem{ 2249 { 2250 Object: ts, 2251 IsError: false, 2252 Reason: "Rejected", 2253 Message: `Listener tcp-7777 doesn't exist`, 2254 }, 2255 } 2256 var expectedChanges []ResourceChange 2257 2258 changes, problems := configuration.AddOrUpdateTransportServer(ts) 2259 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2260 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2261 } 2262 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2263 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2264 } 2265 } 2266 2267 func TestDeleteNonExistingTransportServer(t *testing.T) { 2268 configuration := createTestConfiguration() 2269 2270 var expectedChanges []ResourceChange 2271 var expectedProblems []ConfigurationProblem 2272 2273 changes, problems := configuration.DeleteTransportServer("default/transportserver") 2274 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2275 t.Errorf("DeleteTransportServer() returned unexpected result (-want +got):\n%s", diff) 2276 } 2277 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2278 t.Errorf("DeleteTransportServer() returned unexpected result (-want +got):\n%s", diff) 2279 } 2280 } 2281 2282 func TestAddGlobalConfiguration(t *testing.T) { 2283 configuration := createTestConfiguration() 2284 2285 listeners := []conf_v1alpha1.Listener{ 2286 { 2287 Name: "tcp-7777", 2288 Port: 7777, 2289 Protocol: "TCP", 2290 }, 2291 { 2292 Name: "tcp-8888", 2293 Port: 8888, 2294 Protocol: "TCP", 2295 }, 2296 } 2297 gc := createTestGlobalConfiguration(listeners) 2298 2299 var expectedChanges []ResourceChange 2300 var expectedProblems []ConfigurationProblem 2301 2302 changes, problems, err := configuration.AddOrUpdateGlobalConfiguration(gc) 2303 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2304 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2305 } 2306 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2307 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2308 } 2309 if err != nil { 2310 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected error: %v", err) 2311 } 2312 2313 ts1 := createTestTransportServer("transportserver-1", "tcp-7777", "TCP") 2314 ts2 := createTestTransportServer("transportserver-2", "tcp-8888", "TCP") 2315 2316 // Add first TransportServer 2317 2318 expectedChanges = []ResourceChange{ 2319 { 2320 Op: AddOrUpdate, 2321 Resource: &TransportServerConfiguration{ 2322 ListenerPort: 7777, 2323 TransportServer: ts1, 2324 }, 2325 }, 2326 } 2327 expectedProblems = nil 2328 2329 changes, problems = configuration.AddOrUpdateTransportServer(ts1) 2330 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2331 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2332 } 2333 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2334 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2335 } 2336 2337 // Update GlobalConfiguration 2338 2339 updatedGC1 := gc.DeepCopy() 2340 updatedGC1.Spec.Listeners[0].Port = 7000 2341 2342 expectedChanges = []ResourceChange{ 2343 { 2344 Op: AddOrUpdate, 2345 Resource: &TransportServerConfiguration{ 2346 ListenerPort: 7000, 2347 TransportServer: ts1, 2348 }, 2349 }, 2350 } 2351 expectedProblems = nil 2352 2353 changes, problems, err = configuration.AddOrUpdateGlobalConfiguration(updatedGC1) 2354 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2355 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2356 } 2357 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2358 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2359 } 2360 if err != nil { 2361 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected error: %v", err) 2362 } 2363 2364 // Add second TransportServer 2365 2366 expectedChanges = []ResourceChange{ 2367 { 2368 Op: AddOrUpdate, 2369 Resource: &TransportServerConfiguration{ 2370 ListenerPort: 8888, 2371 TransportServer: ts2, 2372 }, 2373 }, 2374 } 2375 expectedProblems = nil 2376 2377 changes, problems = configuration.AddOrUpdateTransportServer(ts2) 2378 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2379 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2380 } 2381 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2382 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2383 } 2384 2385 // Swap listeners 2386 2387 // We need to hanlde this case in Controller propoperly - update config for all TransportServers and reload once 2388 // to avoid any race conditions 2389 // and errors like nginx: [emerg] duplicate "0.0.0.0:8888" address and port pair in /etc/nginx/nginx.conf:73 2390 2391 updatedGC2 := updatedGC1.DeepCopy() 2392 updatedGC2.Spec.Listeners[0].Port = 8888 2393 updatedGC2.Spec.Listeners[1].Port = 7000 2394 2395 expectedChanges = []ResourceChange{ 2396 { 2397 Op: AddOrUpdate, 2398 Resource: &TransportServerConfiguration{ 2399 ListenerPort: 8888, 2400 TransportServer: ts1, 2401 }, 2402 }, 2403 { 2404 Op: AddOrUpdate, 2405 Resource: &TransportServerConfiguration{ 2406 ListenerPort: 7000, 2407 TransportServer: ts2, 2408 }, 2409 }, 2410 } 2411 expectedProblems = nil 2412 2413 changes, problems, err = configuration.AddOrUpdateGlobalConfiguration(updatedGC2) 2414 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2415 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2416 } 2417 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2418 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2419 } 2420 if err != nil { 2421 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected error: %v", err) 2422 } 2423 2424 // Make GlobalConfiguration Invalid 2425 2426 invalidGC := updatedGC2.DeepCopy() 2427 invalidGC.Spec.Listeners[0].Port = -1 2428 2429 expectedChanges = []ResourceChange{ 2430 { 2431 Op: Delete, 2432 Resource: &TransportServerConfiguration{ 2433 ListenerPort: 8888, 2434 TransportServer: ts1, 2435 }, 2436 }, 2437 { 2438 Op: Delete, 2439 Resource: &TransportServerConfiguration{ 2440 ListenerPort: 7000, 2441 TransportServer: ts2, 2442 }, 2443 }, 2444 } 2445 expectedProblems = []ConfigurationProblem{ 2446 { 2447 Object: ts1, 2448 IsError: false, 2449 Reason: "Rejected", 2450 Message: "Listener tcp-7777 doesn't exist", 2451 }, 2452 { 2453 Object: ts2, 2454 IsError: false, 2455 Reason: "Rejected", 2456 Message: "Listener tcp-8888 doesn't exist", 2457 }, 2458 } 2459 expectedErrMsg := "spec.listeners[0].port: Invalid value: -1: must be between 1 and 65535, inclusive" 2460 2461 changes, problems, err = configuration.AddOrUpdateGlobalConfiguration(invalidGC) 2462 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2463 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2464 } 2465 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2466 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2467 } 2468 if err.Error() != expectedErrMsg { 2469 t.Errorf("AddOrUpdateGlobalConfiguration() returned error %v but expected %v", err, expectedErrMsg) 2470 } 2471 2472 // Restore 2473 2474 expectedChanges = []ResourceChange{ 2475 { 2476 Op: AddOrUpdate, 2477 Resource: &TransportServerConfiguration{ 2478 ListenerPort: 8888, 2479 TransportServer: ts1, 2480 }, 2481 }, 2482 { 2483 Op: AddOrUpdate, 2484 Resource: &TransportServerConfiguration{ 2485 ListenerPort: 7000, 2486 TransportServer: ts2, 2487 }, 2488 }, 2489 } 2490 expectedProblems = nil 2491 2492 changes, problems, err = configuration.AddOrUpdateGlobalConfiguration(updatedGC2) 2493 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2494 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2495 } 2496 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2497 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2498 } 2499 if err != nil { 2500 t.Errorf("AddOrUpdateGlobalConfiguration() returned unexpected error: %v", err) 2501 } 2502 2503 // Delete GlobalConfiguration 2504 2505 expectedChanges = []ResourceChange{ 2506 { 2507 Op: Delete, 2508 Resource: &TransportServerConfiguration{ 2509 ListenerPort: 8888, 2510 TransportServer: ts1, 2511 }, 2512 }, 2513 { 2514 Op: Delete, 2515 Resource: &TransportServerConfiguration{ 2516 ListenerPort: 7000, 2517 TransportServer: ts2, 2518 }, 2519 }, 2520 } 2521 expectedProblems = []ConfigurationProblem{ 2522 { 2523 Object: ts1, 2524 IsError: false, 2525 Reason: "Rejected", 2526 Message: "Listener tcp-7777 doesn't exist", 2527 }, 2528 { 2529 Object: ts2, 2530 IsError: false, 2531 Reason: "Rejected", 2532 Message: "Listener tcp-8888 doesn't exist", 2533 }, 2534 } 2535 2536 changes, problems = configuration.DeleteGlobalConfiguration() 2537 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2538 t.Errorf("DeleteGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2539 } 2540 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2541 t.Errorf("DeleteGlobalConfiguration() returned unexpected result (-want +got):\n%s", diff) 2542 } 2543 } 2544 2545 func TestPortCollisions(t *testing.T) { 2546 configuration := createTestConfiguration() 2547 2548 listeners := []conf_v1alpha1.Listener{ 2549 { 2550 Name: "tcp-7777", 2551 Port: 7777, 2552 Protocol: "TCP", 2553 }, 2554 } 2555 gc := createTestGlobalConfiguration(listeners) 2556 mustInitGlobalConfiguration(configuration, gc) 2557 2558 var expectedChanges []ResourceChange 2559 var expectedProblems []ConfigurationProblem 2560 2561 ts1 := createTestTransportServer("transportserver-1", "tcp-7777", "TCP") 2562 ts2 := createTestTransportServer("transportserver-2", "tcp-7777", "TCP") 2563 ts3 := createTestTransportServer("transportserver-3", "tcp-7777", "TCP") 2564 2565 expectedChanges = []ResourceChange{ 2566 { 2567 Op: AddOrUpdate, 2568 Resource: &TransportServerConfiguration{ 2569 ListenerPort: 7777, 2570 TransportServer: ts1, 2571 }, 2572 }, 2573 } 2574 expectedProblems = nil 2575 2576 // Add first TransportServer 2577 2578 changes, problems := configuration.AddOrUpdateTransportServer(ts1) 2579 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2580 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2581 } 2582 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2583 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2584 } 2585 2586 // Add second TransportServer 2587 2588 expectedChanges = nil 2589 expectedProblems = []ConfigurationProblem{ 2590 { 2591 Object: ts2, 2592 IsError: false, 2593 Reason: "Rejected", 2594 Message: "Listener tcp-7777 is taken by another resource", 2595 }, 2596 } 2597 2598 changes, problems = configuration.AddOrUpdateTransportServer(ts2) 2599 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2600 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2601 } 2602 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2603 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2604 } 2605 2606 // Add third TransportServer 2607 2608 expectedChanges = nil 2609 expectedProblems = []ConfigurationProblem{ 2610 { 2611 Object: ts3, 2612 IsError: false, 2613 Reason: "Rejected", 2614 Message: "Listener tcp-7777 is taken by another resource", 2615 }, 2616 } 2617 2618 changes, problems = configuration.AddOrUpdateTransportServer(ts3) 2619 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2620 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2621 } 2622 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2623 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2624 } 2625 2626 // Remove first TransportServer 2627 2628 expectedChanges = []ResourceChange{ 2629 { 2630 Op: Delete, 2631 Resource: &TransportServerConfiguration{ 2632 ListenerPort: 7777, 2633 TransportServer: ts1, 2634 }, 2635 }, 2636 { 2637 Op: AddOrUpdate, 2638 Resource: &TransportServerConfiguration{ 2639 ListenerPort: 7777, 2640 TransportServer: ts2, 2641 }, 2642 }, 2643 } 2644 expectedProblems = nil 2645 2646 changes, problems = configuration.DeleteTransportServer("default/transportserver-1") 2647 if diff := cmp.Diff(expectedChanges, changes); diff != "" { 2648 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2649 } 2650 if diff := cmp.Diff(expectedProblems, problems); diff != "" { 2651 t.Errorf("AddOrUpdateTransportServer() returned unexpected result (-want +got):\n%s", diff) 2652 } 2653 } 2654 2655 func mustInitGlobalConfiguration(c *Configuration, gc *conf_v1alpha1.GlobalConfiguration) { 2656 changes, problems, err := c.AddOrUpdateGlobalConfiguration(gc) 2657 2658 // when adding a valid GlobalConfiguration to a new Configuration, no changes, problems and errors are expected 2659 2660 if len(changes) > 0 { 2661 panic(fmt.Sprintf("AddOrUpdateGlobalConfiguration() returned %d changes, expected 0", len(changes))) 2662 } 2663 if len(problems) > 0 { 2664 panic(fmt.Sprintf("AddOrUpdateGlobalConfiguration() returned %d problems, expected 0", len(problems))) 2665 } 2666 if err != nil { 2667 panic(fmt.Sprintf("AddOrUpdateGlobalConfiguration() returned an unexpected error %v", err)) 2668 } 2669 } 2670 2671 func createTestIngressMaster(name string, host string) *networking.Ingress { 2672 ing := createTestIngress(name, host) 2673 ing.Annotations["nginx.org/mergeable-ingress-type"] = "master" 2674 return ing 2675 } 2676 2677 func createTestIngressMinion(name string, host string, path string) *networking.Ingress { 2678 ing := createTestIngress(name, host) 2679 ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{ 2680 HTTP: &networking.HTTPIngressRuleValue{ 2681 Paths: []networking.HTTPIngressPath{ 2682 { 2683 Path: path, 2684 }, 2685 }, 2686 }, 2687 } 2688 2689 ing.Annotations["nginx.org/mergeable-ingress-type"] = "minion" 2690 2691 return ing 2692 } 2693 2694 func createTestIngress(name string, hosts ...string) *networking.Ingress { 2695 var rules []networking.IngressRule 2696 2697 for _, h := range hosts { 2698 rules = append(rules, networking.IngressRule{ 2699 Host: h, 2700 IngressRuleValue: networking.IngressRuleValue{}, 2701 }) 2702 } 2703 2704 return &networking.Ingress{ 2705 ObjectMeta: metav1.ObjectMeta{ 2706 Name: name, 2707 Namespace: "default", 2708 CreationTimestamp: metav1.Now(), 2709 Annotations: map[string]string{ 2710 "kubernetes.io/ingress.class": "nginx", 2711 }, 2712 }, 2713 Spec: networking.IngressSpec{ 2714 Rules: rules, 2715 }, 2716 } 2717 } 2718 2719 func createTestVirtualServer(name string, host string) *conf_v1.VirtualServer { 2720 return &conf_v1.VirtualServer{ 2721 ObjectMeta: metav1.ObjectMeta{ 2722 Namespace: "default", 2723 Name: name, 2724 CreationTimestamp: metav1.Now(), 2725 }, 2726 Spec: conf_v1.VirtualServerSpec{ 2727 IngressClass: "nginx", 2728 Host: host, 2729 }, 2730 } 2731 } 2732 2733 func createTestVirtualServerWithRoutes(name string, host string, routes []conf_v1.Route) *conf_v1.VirtualServer { 2734 vs := createTestVirtualServer(name, host) 2735 vs.Spec.Routes = routes 2736 return vs 2737 } 2738 2739 func createTestVirtualServerRoute(name string, host string, path string) *conf_v1.VirtualServerRoute { 2740 return &conf_v1.VirtualServerRoute{ 2741 ObjectMeta: metav1.ObjectMeta{ 2742 Namespace: "default", 2743 Name: name, 2744 }, 2745 Spec: conf_v1.VirtualServerRouteSpec{ 2746 IngressClass: "nginx", 2747 Host: host, 2748 Subroutes: []conf_v1.Route{ 2749 { 2750 Path: path, 2751 Action: &conf_v1.Action{ 2752 Return: &conf_v1.ActionReturn{ 2753 Body: "vsr", 2754 }, 2755 }, 2756 }, 2757 }, 2758 }, 2759 } 2760 } 2761 2762 func createTestTransportServer(name string, listenerName string, listenerProtocol string) *conf_v1alpha1.TransportServer { 2763 return &conf_v1alpha1.TransportServer{ 2764 ObjectMeta: metav1.ObjectMeta{ 2765 Name: name, 2766 Namespace: "default", 2767 CreationTimestamp: metav1.Now(), 2768 Generation: 1, 2769 }, 2770 Spec: conf_v1alpha1.TransportServerSpec{ 2771 Listener: conf_v1alpha1.TransportServerListener{ 2772 Name: listenerName, 2773 Protocol: listenerProtocol, 2774 }, 2775 Upstreams: []conf_v1alpha1.Upstream{ 2776 { 2777 Name: "myapp", 2778 Service: "myapp-svc", 2779 Port: 1234, 2780 }, 2781 }, 2782 Action: &conf_v1alpha1.Action{ 2783 Pass: "myapp", 2784 }, 2785 }, 2786 } 2787 } 2788 2789 func createTestTLSPassthroughTransportServer(name string, host string) *conf_v1alpha1.TransportServer { 2790 ts := createTestTransportServer(name, conf_v1alpha1.TLSPassthroughListenerName, conf_v1alpha1.TLSPassthroughListenerProtocol) 2791 ts.Spec.Host = host 2792 2793 return ts 2794 } 2795 2796 func createTestGlobalConfiguration(listeners []conf_v1alpha1.Listener) *conf_v1alpha1.GlobalConfiguration { 2797 return &conf_v1alpha1.GlobalConfiguration{ 2798 ObjectMeta: metav1.ObjectMeta{ 2799 Name: "globalconfiguration", 2800 Namespace: "nginx-ingress", 2801 }, 2802 Spec: conf_v1alpha1.GlobalConfigurationSpec{ 2803 Listeners: listeners, 2804 }, 2805 } 2806 } 2807 2808 func TestChooseObjectMetaWinner(t *testing.T) { 2809 now := metav1.Now() 2810 afterNow := metav1.NewTime(now.Add(1 * time.Second)) 2811 2812 tests := []struct { 2813 meta1 *metav1.ObjectMeta 2814 meta2 *metav1.ObjectMeta 2815 msg string 2816 expected bool 2817 }{ 2818 { 2819 meta1: &metav1.ObjectMeta{ 2820 UID: "a", 2821 CreationTimestamp: now, 2822 }, 2823 meta2: &metav1.ObjectMeta{ 2824 UID: "b", 2825 CreationTimestamp: afterNow, 2826 }, 2827 msg: "first is older", 2828 expected: true, 2829 }, 2830 { 2831 meta1: &metav1.ObjectMeta{ 2832 UID: "a", 2833 CreationTimestamp: afterNow, 2834 }, 2835 meta2: &metav1.ObjectMeta{ 2836 UID: "b", 2837 CreationTimestamp: now, 2838 }, 2839 msg: "second is older", 2840 expected: false, 2841 }, 2842 { 2843 meta1: &metav1.ObjectMeta{ 2844 UID: "a", 2845 CreationTimestamp: now, 2846 }, 2847 meta2: &metav1.ObjectMeta{ 2848 UID: "b", 2849 CreationTimestamp: now, 2850 }, 2851 msg: "both not older, but second wins", 2852 expected: false, 2853 }, 2854 } 2855 2856 for _, test := range tests { 2857 result := chooseObjectMetaWinner(test.meta1, test.meta2) 2858 if result != test.expected { 2859 t.Errorf("chooseObjectMetaWinner() returned %v but expected %v for the case %s", result, test.expected, test.msg) 2860 } 2861 } 2862 } 2863 2864 func TestSquashResourceChanges(t *testing.T) { 2865 ingConfig := &IngressConfiguration{ 2866 Ingress: createTestIngress("test", "foo.example.com"), 2867 } 2868 2869 vsConfig := &VirtualServerConfiguration{ 2870 VirtualServer: createTestVirtualServer("test", "bar.example.com"), 2871 } 2872 2873 tests := []struct { 2874 changes []ResourceChange 2875 expected []ResourceChange 2876 msg string 2877 }{ 2878 { 2879 changes: []ResourceChange{ 2880 { 2881 Op: Delete, 2882 Resource: ingConfig, 2883 }, 2884 { 2885 Op: Delete, 2886 Resource: ingConfig, 2887 }, 2888 }, 2889 expected: []ResourceChange{ 2890 { 2891 Op: Delete, 2892 Resource: ingConfig, 2893 }, 2894 }, 2895 msg: "squash deletes", 2896 }, 2897 { 2898 changes: []ResourceChange{ 2899 { 2900 Op: AddOrUpdate, 2901 Resource: ingConfig, 2902 }, 2903 { 2904 Op: AddOrUpdate, 2905 Resource: ingConfig, 2906 }, 2907 }, 2908 expected: []ResourceChange{ 2909 { 2910 Op: AddOrUpdate, 2911 Resource: ingConfig, 2912 }, 2913 }, 2914 msg: "squash updates", 2915 }, 2916 { 2917 changes: []ResourceChange{ 2918 { 2919 Op: Delete, 2920 Resource: ingConfig, 2921 }, 2922 { 2923 Op: AddOrUpdate, 2924 Resource: ingConfig, 2925 }, 2926 }, 2927 expected: []ResourceChange{ 2928 { 2929 Op: AddOrUpdate, 2930 Resource: ingConfig, 2931 }, 2932 }, 2933 msg: "squash update and delete", 2934 }, 2935 { 2936 changes: []ResourceChange{ 2937 { 2938 Op: Delete, 2939 Resource: vsConfig, 2940 }, 2941 { 2942 Op: AddOrUpdate, 2943 Resource: ingConfig, 2944 }, 2945 }, 2946 expected: []ResourceChange{ 2947 { 2948 Op: Delete, 2949 Resource: vsConfig, 2950 }, 2951 { 2952 Op: AddOrUpdate, 2953 Resource: ingConfig, 2954 }, 2955 }, 2956 msg: "preserve the order", 2957 }, 2958 { 2959 changes: []ResourceChange{ 2960 { 2961 Op: Delete, 2962 Resource: ingConfig, 2963 }, 2964 { 2965 Op: AddOrUpdate, 2966 Resource: vsConfig, 2967 }, 2968 }, 2969 expected: []ResourceChange{ 2970 { 2971 Op: Delete, 2972 Resource: ingConfig, 2973 }, 2974 { 2975 Op: AddOrUpdate, 2976 Resource: vsConfig, 2977 }, 2978 }, 2979 msg: "do not squash different resource with same ns/name", 2980 }, 2981 { 2982 changes: []ResourceChange{ 2983 { 2984 Op: Delete, 2985 Resource: ingConfig, 2986 }, 2987 { 2988 Op: AddOrUpdate, 2989 Resource: ingConfig, 2990 }, 2991 { 2992 Op: Delete, 2993 Resource: vsConfig, 2994 }, 2995 }, 2996 expected: []ResourceChange{ 2997 { 2998 Op: Delete, 2999 Resource: vsConfig, 3000 }, 3001 { 3002 Op: AddOrUpdate, 3003 Resource: ingConfig, 3004 }, 3005 }, 3006 msg: "squashed delete and update must follow delete", 3007 }, 3008 } 3009 3010 for _, test := range tests { 3011 result := squashResourceChanges(test.changes) 3012 if diff := cmp.Diff(test.expected, result); diff != "" { 3013 t.Errorf("squashResourceChanges() returned unexpected result for the case of %s (-want +got):\n%s", test.msg, diff) 3014 } 3015 } 3016 } 3017 3018 type testReferenceChecker struct { 3019 resourceName string 3020 resourceNamespace string 3021 onlyIngresses bool 3022 onlyMinions bool 3023 onlyVirtualServers bool 3024 onlyVirtualServerRoutes bool 3025 onlyTransportServers bool 3026 } 3027 3028 func (rc *testReferenceChecker) IsReferencedByIngress(namespace string, name string, ing *networking.Ingress) bool { 3029 return rc.onlyIngresses && namespace == rc.resourceNamespace && name == rc.resourceName 3030 } 3031 3032 func (rc *testReferenceChecker) IsReferencedByMinion(namespace string, name string, ing *networking.Ingress) bool { 3033 return rc.onlyMinions && namespace == rc.resourceNamespace && name == rc.resourceName 3034 } 3035 3036 func (rc *testReferenceChecker) IsReferencedByVirtualServer(namespace string, name string, vs *conf_v1.VirtualServer) bool { 3037 return rc.onlyVirtualServers && namespace == rc.resourceNamespace && name == rc.resourceName 3038 } 3039 3040 func (rc *testReferenceChecker) IsReferencedByVirtualServerRoute(namespace string, name string, vsr *conf_v1.VirtualServerRoute) bool { 3041 return rc.onlyVirtualServerRoutes && namespace == rc.resourceNamespace && name == rc.resourceName 3042 } 3043 3044 func (rc *testReferenceChecker) IsReferencedByTransportServer(namespace string, name string, ts *conf_v1alpha1.TransportServer) bool { 3045 return rc.onlyTransportServers && namespace == rc.resourceNamespace && name == rc.resourceName 3046 } 3047 3048 func TestFindResourcesForResourceReference(t *testing.T) { 3049 regularIng := createTestIngress("regular-ingress", "foo.example.com") 3050 master := createTestIngressMaster("master-ingress", "bar.example.com") 3051 minion := createTestIngressMinion("minion-ingress", "bar.example.com", "/") 3052 vs := createTestVirtualServer("virtualserver-1", "qwe.example.com") 3053 vsWithVSR := createTestVirtualServerWithRoutes( 3054 "virtualserver-2", 3055 "asd.example.com", 3056 []conf_v1.Route{ 3057 { 3058 Path: "/", 3059 Route: "virtualserverroute", 3060 }, 3061 }) 3062 vsr := createTestVirtualServerRoute("virtualserverroute", "asd.example.com", "/") 3063 tsPassthrough := createTestTLSPassthroughTransportServer("transportserver-passthrough", "ts.example.com") 3064 listeners := []conf_v1alpha1.Listener{ 3065 { 3066 Name: "tcp-7777", 3067 Port: 7777, 3068 Protocol: "TCP", 3069 }, 3070 } 3071 gc := createTestGlobalConfiguration(listeners) 3072 tsTCP := createTestTransportServer("transportserver-tcp", "tcp-7777", "TCP") 3073 3074 configuration := createTestConfiguration() 3075 3076 configuration.AddOrUpdateIngress(regularIng) 3077 configuration.AddOrUpdateIngress(master) 3078 configuration.AddOrUpdateIngress(minion) 3079 configuration.AddOrUpdateVirtualServer(vs) 3080 configuration.AddOrUpdateVirtualServer(vsWithVSR) 3081 configuration.AddOrUpdateVirtualServerRoute(vsr) 3082 _, _, _ = configuration.AddOrUpdateGlobalConfiguration(gc) 3083 configuration.AddOrUpdateTransportServer(tsPassthrough) 3084 configuration.AddOrUpdateTransportServer(tsTCP) 3085 3086 tests := []struct { 3087 rc resourceReferenceChecker 3088 expected []Resource 3089 msg string 3090 }{ 3091 { 3092 rc: &testReferenceChecker{ 3093 resourceNamespace: "default", 3094 resourceName: "test", 3095 onlyIngresses: true, 3096 }, 3097 expected: []Resource{ 3098 configuration.hosts["bar.example.com"], 3099 configuration.hosts["foo.example.com"], 3100 }, 3101 msg: "only Ingresses", 3102 }, 3103 { 3104 rc: &testReferenceChecker{ 3105 resourceNamespace: "default", 3106 resourceName: "test", 3107 onlyMinions: true, 3108 }, 3109 expected: []Resource{ 3110 configuration.hosts["bar.example.com"], 3111 }, 3112 msg: "only Minions", 3113 }, 3114 { 3115 rc: &testReferenceChecker{ 3116 resourceNamespace: "default", 3117 resourceName: "test", 3118 onlyVirtualServers: true, 3119 }, 3120 expected: []Resource{ 3121 configuration.hosts["asd.example.com"], 3122 configuration.hosts["qwe.example.com"], 3123 }, 3124 msg: "only VirtualServers", 3125 }, 3126 { 3127 rc: &testReferenceChecker{ 3128 resourceNamespace: "default", 3129 resourceName: "test", 3130 onlyVirtualServerRoutes: true, 3131 }, 3132 expected: []Resource{ 3133 configuration.hosts["asd.example.com"], 3134 }, 3135 msg: "only VirtualServerRoutes", 3136 }, 3137 { 3138 rc: &testReferenceChecker{ 3139 resourceNamespace: "default", 3140 resourceName: "test", 3141 onlyTransportServers: true, 3142 }, 3143 expected: []Resource{ 3144 configuration.hosts["ts.example.com"], 3145 configuration.listeners["tcp-7777"], 3146 }, 3147 msg: "only TransportServers", 3148 }, 3149 } 3150 3151 for _, test := range tests { 3152 result := configuration.findResourcesForResourceReference("default", "test", test.rc) 3153 if diff := cmp.Diff(test.expected, result); diff != "" { 3154 t.Errorf("findResourcesForResourceReference() returned unexpected result for the case of %s (-want +got):\n%s", test.msg, diff) 3155 } 3156 3157 var noResources []Resource 3158 3159 result = configuration.findResourcesForResourceReference("default", "wrong", test.rc) 3160 if diff := cmp.Diff(noResources, result); diff != "" { 3161 t.Errorf("findResourcesForResourceReference() returned unexpected result for the case of %s and wrong name (-want +got):\n%s", test.msg, diff) 3162 } 3163 3164 result = configuration.findResourcesForResourceReference("wrong", "test", test.rc) 3165 if diff := cmp.Diff(noResources, result); diff != "" { 3166 t.Errorf("findResourcesForResourceReference() returned unexpected result for the case of %s and wrong namespace (-want +got):\n%s", test.msg, diff) 3167 } 3168 } 3169 } 3170 3171 func TestGetResources(t *testing.T) { 3172 ing := createTestIngress("ingress", "foo.example.com", "bar.example.com") 3173 vs := createTestVirtualServer("virtualserver", "qwe.example.com") 3174 3175 configuration := createTestConfiguration() 3176 configuration.AddOrUpdateIngress(ing) 3177 configuration.AddOrUpdateVirtualServer(vs) 3178 3179 expected := []Resource{ 3180 configuration.hosts["foo.example.com"], 3181 configuration.hosts["qwe.example.com"], 3182 } 3183 3184 result := configuration.GetResources() 3185 if diff := cmp.Diff(expected, result); diff != "" { 3186 t.Errorf("GetResources() returned unexpected result (-want +got):\n%s", diff) 3187 } 3188 3189 expected = []Resource{ 3190 configuration.hosts["foo.example.com"], 3191 } 3192 3193 result = configuration.GetResourcesWithFilter(resourceFilter{Ingresses: true}) 3194 if diff := cmp.Diff(expected, result); diff != "" { 3195 t.Errorf("GetResources() returned unexpected result (-want +got):\n%s", diff) 3196 } 3197 3198 expected = []Resource{ 3199 configuration.hosts["qwe.example.com"], 3200 } 3201 3202 result = configuration.GetResourcesWithFilter(resourceFilter{VirtualServers: true}) 3203 if diff := cmp.Diff(expected, result); diff != "" { 3204 t.Errorf("GetResources() returned unexpected result (-want +got):\n%s", diff) 3205 } 3206 } 3207 3208 func TestIsEqualForIngressConfigurationes(t *testing.T) { 3209 regularIng := createTestIngress("regular-ingress", "foo.example.com") 3210 3211 ingConfigWithInvalidHost := NewRegularIngressConfiguration(regularIng) 3212 ingConfigWithInvalidHost.ValidHosts["foo.example.com"] = false 3213 3214 ingConfigWithUpdatedIsMaster := NewRegularIngressConfiguration(regularIng) 3215 ingConfigWithUpdatedIsMaster.IsMaster = true 3216 3217 regularIngWithUpdatedGen := regularIng.DeepCopy() 3218 regularIngWithUpdatedGen.Generation++ 3219 3220 regularIngWithUpdatedAnnotations := regularIng.DeepCopy() 3221 regularIngWithUpdatedAnnotations.Annotations["new"] = "value" 3222 3223 masterIng := createTestIngressMaster("master-ingress", "bar.example.com") 3224 minionIng := createTestIngressMinion("minion-ingress", "bar.example.com", "/") 3225 3226 minionIngWithUpdatedGen := minionIng.DeepCopy() 3227 minionIngWithUpdatedGen.Generation++ 3228 3229 minionIngWithUpdatedAnnotations := minionIng.DeepCopy() 3230 minionIngWithUpdatedAnnotations.Annotations["new"] = "value" 3231 3232 tests := []struct { 3233 ingConfig1 *IngressConfiguration 3234 ingConfig2 *IngressConfiguration 3235 expected bool 3236 msg string 3237 }{ 3238 { 3239 ingConfig1: NewRegularIngressConfiguration(regularIng), 3240 ingConfig2: NewRegularIngressConfiguration(regularIng), 3241 expected: true, 3242 msg: "equal regular ingresses", 3243 }, 3244 { 3245 ingConfig1: NewRegularIngressConfiguration(regularIng), 3246 ingConfig2: ingConfigWithInvalidHost, 3247 expected: false, 3248 msg: "regular ingresses with different valid hosts", 3249 }, 3250 { 3251 ingConfig1: NewRegularIngressConfiguration(regularIng), 3252 ingConfig2: ingConfigWithUpdatedIsMaster, 3253 expected: false, 3254 msg: "regular ingresses with different IsMaster value", 3255 }, 3256 { 3257 ingConfig1: NewRegularIngressConfiguration(regularIng), 3258 ingConfig2: NewRegularIngressConfiguration(regularIngWithUpdatedGen), 3259 expected: false, 3260 msg: "regular ingresses with different generation", 3261 }, 3262 { 3263 ingConfig1: NewRegularIngressConfiguration(regularIng), 3264 ingConfig2: NewRegularIngressConfiguration(regularIngWithUpdatedAnnotations), 3265 expected: false, 3266 msg: "regular ingresses with different annotations", 3267 }, 3268 { 3269 ingConfig1: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIng)}, map[string][]string{}), 3270 ingConfig2: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIng)}, map[string][]string{}), 3271 expected: true, 3272 msg: "equal master ingresses", 3273 }, 3274 { 3275 ingConfig1: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIng)}, map[string][]string{}), 3276 ingConfig2: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{}, map[string][]string{}), 3277 expected: false, 3278 msg: "masters with different number of minions", 3279 }, 3280 { 3281 ingConfig1: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIng)}, map[string][]string{}), 3282 ingConfig2: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIngWithUpdatedGen)}, map[string][]string{}), 3283 expected: false, 3284 msg: "masters with minions with different generation", 3285 }, 3286 { 3287 ingConfig1: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIng)}, map[string][]string{}), 3288 ingConfig2: NewMasterIngressConfiguration(masterIng, []*MinionConfiguration{NewMinionConfiguration(minionIngWithUpdatedAnnotations)}, map[string][]string{}), 3289 expected: false, 3290 msg: "masters with minions with different annotations", 3291 }, 3292 } 3293 3294 for _, test := range tests { 3295 result := test.ingConfig1.IsEqual(test.ingConfig2) 3296 if result != test.expected { 3297 t.Errorf("IsEqual() returned %v but expected %v for the case of %s", result, test.expected, test.msg) 3298 } 3299 } 3300 } 3301 3302 func TestIsEqualForVirtualServers(t *testing.T) { 3303 vs := createTestVirtualServerWithRoutes( 3304 "virtualserver", 3305 "foo.example.com", 3306 []conf_v1.Route{ 3307 { 3308 Path: "/", 3309 Route: "virtualserverroute", 3310 }, 3311 }) 3312 vsr := createTestVirtualServerRoute("virtualserverroute", "foo.example.com", "/") 3313 3314 vsWithUpdatedGen := vs.DeepCopy() 3315 vsWithUpdatedGen.Generation++ 3316 3317 vsrWithUpdatedGen := vsr.DeepCopy() 3318 vsrWithUpdatedGen.Generation++ 3319 3320 tests := []struct { 3321 vsConfig1 *VirtualServerConfiguration 3322 vsConfig2 *VirtualServerConfiguration 3323 expected bool 3324 msg string 3325 }{ 3326 { 3327 vsConfig1: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{vsr}, []string{}), 3328 vsConfig2: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{vsr}, []string{}), 3329 expected: true, 3330 msg: "equal virtual servers", 3331 }, 3332 { 3333 vsConfig1: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{vsr}, []string{}), 3334 vsConfig2: NewVirtualServerConfiguration(vsWithUpdatedGen, []*conf_v1.VirtualServerRoute{vsr}, []string{}), 3335 expected: false, 3336 msg: "virtual servers with different generation", 3337 }, 3338 { 3339 vsConfig1: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{vsr}, []string{}), 3340 vsConfig2: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{}, []string{}), 3341 expected: false, 3342 msg: "virtual servers with different number of virtual server routes", 3343 }, 3344 { 3345 vsConfig1: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{vsr}, []string{}), 3346 vsConfig2: NewVirtualServerConfiguration(vs, []*conf_v1.VirtualServerRoute{vsrWithUpdatedGen}, []string{}), 3347 expected: false, 3348 msg: "virtual servers with virtual server routes with different generation", 3349 }, 3350 } 3351 3352 for _, test := range tests { 3353 result := test.vsConfig1.IsEqual(test.vsConfig2) 3354 if result != test.expected { 3355 t.Errorf("IsEqual() returned %v but expected %v for the case of %s", result, test.expected, test.msg) 3356 } 3357 } 3358 } 3359 3360 func TestIsEqualForDifferentResources(t *testing.T) { 3361 ingConfig := NewRegularIngressConfiguration(createTestIngress("ingress", "foo.example.com")) 3362 vsConfig := NewVirtualServerConfiguration(createTestVirtualServer("virtualserver", "bar.example.com"), []*conf_v1.VirtualServerRoute{}, []string{}) 3363 3364 result := ingConfig.IsEqual(vsConfig) 3365 if result != false { 3366 t.Error("IsEqual() for different resources returned true but expected false") 3367 } 3368 } 3369 3370 func TestCompareConfigurationProblems(t *testing.T) { 3371 tests := []struct { 3372 problem1 *ConfigurationProblem 3373 problem2 *ConfigurationProblem 3374 expected bool 3375 msg string 3376 }{ 3377 { 3378 problem1: &ConfigurationProblem{ 3379 IsError: false, 3380 Reason: "reason", 3381 Message: "message", 3382 }, 3383 problem2: &ConfigurationProblem{ 3384 IsError: false, 3385 Reason: "reason", 3386 Message: "message", 3387 }, 3388 expected: true, 3389 msg: "equal problems", 3390 }, 3391 { 3392 problem1: &ConfigurationProblem{ 3393 Object: createTestIngress("ingress-1", "foo.example.com"), 3394 IsError: false, 3395 Reason: "reason", 3396 Message: "message", 3397 }, 3398 problem2: &ConfigurationProblem{ 3399 Object: createTestIngress("ingress-2", "bar.example.com"), 3400 IsError: false, 3401 Reason: "reason", 3402 Message: "message", 3403 }, 3404 expected: true, 3405 msg: "equal problems although objects are different", 3406 }, 3407 { 3408 problem1: &ConfigurationProblem{ 3409 IsError: true, 3410 Reason: "reason", 3411 Message: "message", 3412 }, 3413 problem2: &ConfigurationProblem{ 3414 IsError: false, 3415 Reason: "reason", 3416 Message: "message", 3417 }, 3418 expected: false, 3419 msg: "different isError", 3420 }, 3421 { 3422 problem1: &ConfigurationProblem{ 3423 IsError: false, 3424 Reason: "reason", 3425 Message: "message", 3426 }, 3427 problem2: &ConfigurationProblem{ 3428 IsError: false, 3429 Reason: "another reason", 3430 Message: "message", 3431 }, 3432 expected: false, 3433 msg: "different Reason", 3434 }, 3435 { 3436 problem1: &ConfigurationProblem{ 3437 IsError: false, 3438 Reason: "reason", 3439 Message: "message", 3440 }, 3441 problem2: &ConfigurationProblem{ 3442 IsError: false, 3443 Reason: "reason", 3444 Message: "another message", 3445 }, 3446 expected: false, 3447 msg: "different Message", 3448 }, 3449 } 3450 3451 for _, test := range tests { 3452 result := compareConfigurationProblems(test.problem1, test.problem2) 3453 if result != test.expected { 3454 t.Errorf("compareConfigurationProblems() returned %v but expected %v for the case of %s", result, test.expected, test.msg) 3455 } 3456 } 3457 }