sigs.k8s.io/cluster-api-provider-azure@v1.17.0/api/v1beta1/azureclustertemplate_validation_test.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1beta1 18 19 import ( 20 "testing" 21 22 . "github.com/onsi/gomega" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/util/validation/field" 25 "k8s.io/utils/ptr" 26 ) 27 28 func TestValdateVnetCIDRs(t *testing.T) { 29 cases := []struct { 30 name string 31 clusterTemplate *AzureClusterTemplate 32 expectValid bool 33 }{ 34 { 35 name: "valid vnet", 36 clusterTemplate: &AzureClusterTemplate{ 37 ObjectMeta: metav1.ObjectMeta{ 38 Name: "test-cluster-template", 39 }, 40 Spec: AzureClusterTemplateSpec{ 41 Template: AzureClusterTemplateResource{ 42 Spec: AzureClusterTemplateResourceSpec{ 43 NetworkSpec: NetworkTemplateSpec{ 44 Vnet: VnetTemplateSpec{ 45 VnetClassSpec: VnetClassSpec{ 46 CIDRBlocks: []string{DefaultVnetCIDR}, 47 }, 48 }, 49 }, 50 }, 51 }, 52 }, 53 }, 54 expectValid: true, 55 }, 56 { 57 name: "invalid vnet CIDR", 58 clusterTemplate: &AzureClusterTemplate{ 59 ObjectMeta: metav1.ObjectMeta{ 60 Name: "test-cluster-template", 61 }, 62 Spec: AzureClusterTemplateSpec{ 63 Template: AzureClusterTemplateResource{ 64 Spec: AzureClusterTemplateResourceSpec{ 65 NetworkSpec: NetworkTemplateSpec{ 66 Vnet: VnetTemplateSpec{ 67 VnetClassSpec: VnetClassSpec{ 68 CIDRBlocks: []string{"1.2.3/12"}, 69 }, 70 }, 71 }, 72 }, 73 }, 74 }, 75 }, 76 expectValid: false, 77 }, 78 } 79 80 for _, c := range cases { 81 tc := c 82 t.Run(tc.name, func(t *testing.T) { 83 t.Parallel() 84 g := NewWithT(t) 85 res := validateVnetCIDR( 86 tc.clusterTemplate.Spec.Template.Spec.NetworkSpec.Vnet.CIDRBlocks, 87 field.NewPath("spec").Child("template").Child("spec"). 88 Child("networkSpec").Child("vnet").Child("cidrBlocks")) 89 90 if tc.expectValid { 91 g.Expect(res).To(BeNil()) 92 } else { 93 g.Expect(res).NotTo(BeNil()) 94 } 95 }) 96 } 97 } 98 99 func TestValidateSubnetTemplates(t *testing.T) { 100 cases := []struct { 101 name string 102 clusterTemplate *AzureClusterTemplate 103 expectValid bool 104 }{ 105 { 106 name: "valid subnets", 107 clusterTemplate: &AzureClusterTemplate{ 108 ObjectMeta: metav1.ObjectMeta{ 109 Name: "test-cluster-template", 110 }, 111 Spec: AzureClusterTemplateSpec{ 112 Template: AzureClusterTemplateResource{ 113 Spec: AzureClusterTemplateResourceSpec{ 114 NetworkSpec: NetworkTemplateSpec{ 115 Vnet: VnetTemplateSpec{ 116 VnetClassSpec: VnetClassSpec{ 117 CIDRBlocks: []string{DefaultVnetCIDR}, 118 }, 119 }, 120 Subnets: SubnetTemplatesSpec{ 121 { 122 SubnetClassSpec: SubnetClassSpec{ 123 Role: SubnetControlPlane, 124 CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR}, 125 Name: "foo-controlPlane-subnet", 126 }, 127 }, 128 { 129 SubnetClassSpec: SubnetClassSpec{ 130 Role: SubnetNode, 131 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 132 Name: "foo-workerSubnet-subnet", 133 }, 134 }, 135 }, 136 }, 137 }, 138 }, 139 }, 140 }, 141 expectValid: true, 142 }, 143 { 144 name: "invalid subnets - missing/empty subnet name", 145 clusterTemplate: &AzureClusterTemplate{ 146 ObjectMeta: metav1.ObjectMeta{ 147 Name: "test-cluster-template", 148 }, 149 Spec: AzureClusterTemplateSpec{ 150 Template: AzureClusterTemplateResource{ 151 Spec: AzureClusterTemplateResourceSpec{ 152 NetworkSpec: NetworkTemplateSpec{ 153 Vnet: VnetTemplateSpec{ 154 VnetClassSpec: VnetClassSpec{ 155 CIDRBlocks: []string{DefaultVnetCIDR}, 156 }, 157 }, 158 Subnets: SubnetTemplatesSpec{ 159 { 160 SubnetClassSpec: SubnetClassSpec{ 161 Role: SubnetControlPlane, 162 CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR}, 163 Name: "", 164 }, 165 }, 166 { 167 SubnetClassSpec: SubnetClassSpec{ 168 Role: SubnetNode, 169 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 170 Name: "", 171 }, 172 }, 173 }, 174 }, 175 }, 176 }, 177 }, 178 }, 179 expectValid: false, 180 }, 181 { 182 name: "invalid subnets - duplicate subnet names", 183 clusterTemplate: &AzureClusterTemplate{ 184 ObjectMeta: metav1.ObjectMeta{ 185 Name: "test-cluster-template", 186 }, 187 Spec: AzureClusterTemplateSpec{ 188 Template: AzureClusterTemplateResource{ 189 Spec: AzureClusterTemplateResourceSpec{ 190 NetworkSpec: NetworkTemplateSpec{ 191 Vnet: VnetTemplateSpec{ 192 VnetClassSpec: VnetClassSpec{ 193 CIDRBlocks: []string{DefaultVnetCIDR}, 194 }, 195 }, 196 Subnets: SubnetTemplatesSpec{ 197 { 198 SubnetClassSpec: SubnetClassSpec{ 199 Role: SubnetControlPlane, 200 CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR}, 201 Name: "foo-controlPlane-subnet", 202 }, 203 }, 204 { 205 SubnetClassSpec: SubnetClassSpec{ 206 Role: SubnetNode, 207 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 208 Name: "foo-workerSubnet-subnet", 209 }, 210 }, 211 { 212 SubnetClassSpec: SubnetClassSpec{ 213 Role: SubnetNode, 214 CIDRBlocks: []string{"10.2.0.0/16"}, 215 Name: "foo-workerSubnet-subnet", 216 }, 217 }, 218 }, 219 }, 220 }, 221 }, 222 }, 223 }, 224 expectValid: false, 225 }, 226 { 227 name: "invalid subnets - wrong security rule priorities - lower than minimum", 228 clusterTemplate: &AzureClusterTemplate{ 229 ObjectMeta: metav1.ObjectMeta{ 230 Name: "test-cluster-template", 231 }, 232 Spec: AzureClusterTemplateSpec{ 233 Template: AzureClusterTemplateResource{ 234 Spec: AzureClusterTemplateResourceSpec{ 235 NetworkSpec: NetworkTemplateSpec{ 236 Vnet: VnetTemplateSpec{ 237 VnetClassSpec: VnetClassSpec{ 238 CIDRBlocks: []string{DefaultVnetCIDR}, 239 }, 240 }, 241 Subnets: SubnetTemplatesSpec{ 242 { 243 SubnetClassSpec: SubnetClassSpec{ 244 Role: SubnetControlPlane, 245 CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR}, 246 }, 247 SecurityGroup: SecurityGroupClass{ 248 SecurityRules: SecurityRules{ 249 SecurityRule{ 250 Priority: 50, 251 }, 252 }, 253 }, 254 }, 255 { 256 SubnetClassSpec: SubnetClassSpec{ 257 Role: SubnetNode, 258 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 259 }, 260 }, 261 }, 262 }, 263 }, 264 }, 265 }, 266 }, 267 expectValid: false, 268 }, 269 { 270 name: "invalid subnets - wrong security rule priorities - higher than maximum", 271 clusterTemplate: &AzureClusterTemplate{ 272 ObjectMeta: metav1.ObjectMeta{ 273 Name: "test-cluster-template", 274 }, 275 Spec: AzureClusterTemplateSpec{ 276 Template: AzureClusterTemplateResource{ 277 Spec: AzureClusterTemplateResourceSpec{ 278 NetworkSpec: NetworkTemplateSpec{ 279 Vnet: VnetTemplateSpec{ 280 VnetClassSpec: VnetClassSpec{ 281 CIDRBlocks: []string{DefaultVnetCIDR}, 282 }, 283 }, 284 Subnets: SubnetTemplatesSpec{ 285 { 286 SubnetClassSpec: SubnetClassSpec{ 287 Role: SubnetControlPlane, 288 CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR}, 289 }, 290 SecurityGroup: SecurityGroupClass{ 291 SecurityRules: SecurityRules{ 292 SecurityRule{ 293 Priority: 4097, 294 }, 295 }, 296 }, 297 }, 298 { 299 SubnetClassSpec: SubnetClassSpec{ 300 Role: SubnetNode, 301 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 302 }, 303 }, 304 }, 305 }, 306 }, 307 }, 308 }, 309 }, 310 expectValid: false, 311 }, 312 { 313 name: "invalid subnet CIDR", 314 clusterTemplate: &AzureClusterTemplate{ 315 ObjectMeta: metav1.ObjectMeta{ 316 Name: "test-cluster-template", 317 }, 318 Spec: AzureClusterTemplateSpec{ 319 Template: AzureClusterTemplateResource{ 320 Spec: AzureClusterTemplateResourceSpec{ 321 NetworkSpec: NetworkTemplateSpec{ 322 Vnet: VnetTemplateSpec{ 323 VnetClassSpec: VnetClassSpec{ 324 CIDRBlocks: []string{DefaultVnetCIDR}, 325 }, 326 }, 327 Subnets: SubnetTemplatesSpec{ 328 { 329 SubnetClassSpec: SubnetClassSpec{ 330 Role: SubnetControlPlane, 331 CIDRBlocks: []string{"11.0.0.0/16"}, 332 }, 333 }, 334 { 335 SubnetClassSpec: SubnetClassSpec{ 336 Role: SubnetNode, 337 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 338 }, 339 }, 340 }, 341 }, 342 }, 343 }, 344 }, 345 }, 346 expectValid: false, 347 }, 348 { 349 name: "missing required control plane role", 350 clusterTemplate: &AzureClusterTemplate{ 351 ObjectMeta: metav1.ObjectMeta{ 352 Name: "test-cluster-template", 353 }, 354 Spec: AzureClusterTemplateSpec{ 355 Template: AzureClusterTemplateResource{ 356 Spec: AzureClusterTemplateResourceSpec{ 357 NetworkSpec: NetworkTemplateSpec{ 358 Vnet: VnetTemplateSpec{ 359 VnetClassSpec: VnetClassSpec{ 360 CIDRBlocks: []string{DefaultVnetCIDR}, 361 }, 362 }, 363 Subnets: SubnetTemplatesSpec{ 364 { 365 SubnetClassSpec: SubnetClassSpec{ 366 Role: SubnetNode, 367 CIDRBlocks: []string{DefaultNodeSubnetCIDR}, 368 }, 369 }, 370 }, 371 }, 372 }, 373 }, 374 }, 375 }, 376 expectValid: false, 377 }, 378 { 379 name: "missing required node role", 380 clusterTemplate: &AzureClusterTemplate{ 381 ObjectMeta: metav1.ObjectMeta{ 382 Name: "test-cluster-template", 383 }, 384 Spec: AzureClusterTemplateSpec{ 385 Template: AzureClusterTemplateResource{ 386 Spec: AzureClusterTemplateResourceSpec{ 387 NetworkSpec: NetworkTemplateSpec{ 388 Vnet: VnetTemplateSpec{ 389 VnetClassSpec: VnetClassSpec{ 390 CIDRBlocks: []string{DefaultVnetCIDR}, 391 }, 392 }, 393 Subnets: SubnetTemplatesSpec{ 394 { 395 SubnetClassSpec: SubnetClassSpec{ 396 Role: SubnetControlPlane, 397 CIDRBlocks: []string{DefaultControlPlaneSubnetCIDR}, 398 }, 399 }, 400 }, 401 }, 402 }, 403 }, 404 }, 405 }, 406 expectValid: false, 407 }, 408 } 409 410 for _, c := range cases { 411 tc := c 412 t.Run(tc.name, func(t *testing.T) { 413 t.Parallel() 414 g := NewWithT(t) 415 res := validateSubnetTemplates( 416 tc.clusterTemplate.Spec.Template.Spec.NetworkSpec.Subnets, 417 tc.clusterTemplate.Spec.Template.Spec.NetworkSpec.Vnet, 418 field.NewPath("spec").Child("template").Child("spec").Child("networkSpec").Child("subnets"), 419 ) 420 421 if tc.expectValid { 422 g.Expect(res).To(BeNil()) 423 } else { 424 g.Expect(res).NotTo(BeNil()) 425 } 426 }) 427 } 428 } 429 430 func TestValidateAPIServerLBTemplate(t *testing.T) { 431 cases := []struct { 432 name string 433 clusterTemplate *AzureClusterTemplate 434 expectValid bool 435 }{ 436 { 437 name: "valid lb", 438 clusterTemplate: &AzureClusterTemplate{ 439 ObjectMeta: metav1.ObjectMeta{ 440 Name: "test-cluster-template", 441 }, 442 Spec: AzureClusterTemplateSpec{ 443 Template: AzureClusterTemplateResource{ 444 Spec: AzureClusterTemplateResourceSpec{ 445 NetworkSpec: NetworkTemplateSpec{ 446 APIServerLB: LoadBalancerClassSpec{ 447 SKU: SKUStandard, 448 Type: Public, 449 IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes), 450 }, 451 }, 452 }, 453 }, 454 }, 455 }, 456 expectValid: true, 457 }, 458 { 459 name: "invalid lb SKU", 460 clusterTemplate: &AzureClusterTemplate{ 461 ObjectMeta: metav1.ObjectMeta{ 462 Name: "test-cluster-template", 463 }, 464 Spec: AzureClusterTemplateSpec{ 465 Template: AzureClusterTemplateResource{ 466 Spec: AzureClusterTemplateResourceSpec{ 467 NetworkSpec: NetworkTemplateSpec{ 468 APIServerLB: LoadBalancerClassSpec{ 469 SKU: SKU("wrong"), 470 Type: Public, 471 IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes), 472 }, 473 }, 474 }, 475 }, 476 }, 477 }, 478 expectValid: false, 479 }, 480 { 481 name: "invalid lb Type", 482 clusterTemplate: &AzureClusterTemplate{ 483 ObjectMeta: metav1.ObjectMeta{ 484 Name: "test-cluster-template", 485 }, 486 Spec: AzureClusterTemplateSpec{ 487 Template: AzureClusterTemplateResource{ 488 Spec: AzureClusterTemplateResourceSpec{ 489 NetworkSpec: NetworkTemplateSpec{ 490 APIServerLB: LoadBalancerClassSpec{ 491 SKU: SKUStandard, 492 Type: LBType("wrong"), 493 IdleTimeoutInMinutes: ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes), 494 }, 495 }, 496 }, 497 }, 498 }, 499 }, 500 expectValid: false, 501 }, 502 } 503 504 for _, c := range cases { 505 tc := c 506 t.Run(tc.name, func(t *testing.T) { 507 t.Parallel() 508 g := NewWithT(t) 509 res := tc.clusterTemplate.validateAPIServerLB( 510 field.NewPath("spec").Child("template").Child("spec").Child("networkSpec").Child("apiServerLB"), 511 ) 512 513 if tc.expectValid { 514 g.Expect(res).To(BeNil()) 515 } else { 516 g.Expect(res).NotTo(BeNil()) 517 } 518 }) 519 } 520 } 521 522 func TestControlPlaneOutboundLBTemplate(t *testing.T) { 523 cases := []struct { 524 name string 525 clusterTemplate *AzureClusterTemplate 526 expectValid bool 527 }{ 528 { 529 name: "valid controlplaneoutbound LB", 530 clusterTemplate: &AzureClusterTemplate{ 531 ObjectMeta: metav1.ObjectMeta{ 532 Name: "test-cluster-template", 533 }, 534 Spec: AzureClusterTemplateSpec{ 535 Template: AzureClusterTemplateResource{ 536 Spec: AzureClusterTemplateResourceSpec{ 537 NetworkSpec: NetworkTemplateSpec{ 538 APIServerLB: LoadBalancerClassSpec{ 539 Type: Public, 540 }, 541 }, 542 }, 543 }, 544 }, 545 }, 546 expectValid: true, 547 }, 548 { 549 name: "invalid controlplaneoutbound LB - should not have a controlplane outbound lb for public clusters", 550 clusterTemplate: &AzureClusterTemplate{ 551 ObjectMeta: metav1.ObjectMeta{ 552 Name: "test-cluster-template", 553 }, 554 Spec: AzureClusterTemplateSpec{ 555 Template: AzureClusterTemplateResource{ 556 Spec: AzureClusterTemplateResourceSpec{ 557 NetworkSpec: NetworkTemplateSpec{ 558 APIServerLB: LoadBalancerClassSpec{ 559 Type: Public, 560 }, 561 ControlPlaneOutboundLB: &LoadBalancerClassSpec{}, 562 }, 563 }, 564 }, 565 }, 566 }, 567 expectValid: false, 568 }, 569 { 570 name: "invalid controlplaneoutbound LB - IdleTimeoutInMinutes less than minimum for private clusters", 571 clusterTemplate: &AzureClusterTemplate{ 572 ObjectMeta: metav1.ObjectMeta{ 573 Name: "test-cluster-template", 574 }, 575 Spec: AzureClusterTemplateSpec{ 576 Template: AzureClusterTemplateResource{ 577 Spec: AzureClusterTemplateResourceSpec{ 578 NetworkSpec: NetworkTemplateSpec{ 579 APIServerLB: LoadBalancerClassSpec{ 580 Type: Internal, 581 }, 582 ControlPlaneOutboundLB: &LoadBalancerClassSpec{ 583 IdleTimeoutInMinutes: ptr.To[int32](2), 584 }, 585 }, 586 }, 587 }, 588 }, 589 }, 590 expectValid: false, 591 }, 592 { 593 name: "invalid controlplaneoutbound LB - IdleTimeoutInMinutes more than maximum for private clusters", 594 clusterTemplate: &AzureClusterTemplate{ 595 ObjectMeta: metav1.ObjectMeta{ 596 Name: "test-cluster-template", 597 }, 598 Spec: AzureClusterTemplateSpec{ 599 Template: AzureClusterTemplateResource{ 600 Spec: AzureClusterTemplateResourceSpec{ 601 NetworkSpec: NetworkTemplateSpec{ 602 APIServerLB: LoadBalancerClassSpec{ 603 Type: Internal, 604 }, 605 ControlPlaneOutboundLB: &LoadBalancerClassSpec{ 606 IdleTimeoutInMinutes: ptr.To[int32](60), 607 }, 608 }, 609 }, 610 }, 611 }, 612 }, 613 expectValid: false, 614 }, 615 { 616 name: "valid controlplaneoutbound LB - can be empty for private clusters", 617 clusterTemplate: &AzureClusterTemplate{ 618 ObjectMeta: metav1.ObjectMeta{ 619 Name: "test-cluster-template", 620 }, 621 Spec: AzureClusterTemplateSpec{ 622 Template: AzureClusterTemplateResource{ 623 Spec: AzureClusterTemplateResourceSpec{ 624 NetworkSpec: NetworkTemplateSpec{ 625 APIServerLB: LoadBalancerClassSpec{ 626 Type: Internal, 627 }, 628 }, 629 }, 630 }, 631 }, 632 }, 633 expectValid: true, 634 }, 635 } 636 637 for _, c := range cases { 638 tc := c 639 t.Run(tc.name, func(t *testing.T) { 640 t.Parallel() 641 g := NewWithT(t) 642 res := tc.clusterTemplate.validateControlPlaneOutboundLB() 643 644 if tc.expectValid { 645 g.Expect(res).To(BeNil()) 646 } else { 647 g.Expect(res).NotTo(BeNil()) 648 } 649 }) 650 } 651 } 652 653 func TestNodeOutboundLBTemplate(t *testing.T) { 654 cases := []struct { 655 name string 656 clusterTemplate *AzureClusterTemplate 657 expectValid bool 658 }{ 659 { 660 name: "cannot be nil for public clusters", 661 clusterTemplate: &AzureClusterTemplate{ 662 ObjectMeta: metav1.ObjectMeta{ 663 Name: "test-cluster-template", 664 }, 665 Spec: AzureClusterTemplateSpec{ 666 Template: AzureClusterTemplateResource{ 667 Spec: AzureClusterTemplateResourceSpec{ 668 NetworkSpec: NetworkTemplateSpec{ 669 APIServerLB: LoadBalancerClassSpec{ 670 Type: Public, 671 }, 672 }, 673 }, 674 }, 675 }, 676 }, 677 expectValid: false, 678 }, 679 { 680 name: "can be nil for private clusters", 681 clusterTemplate: &AzureClusterTemplate{ 682 ObjectMeta: metav1.ObjectMeta{ 683 Name: "test-cluster-template", 684 }, 685 Spec: AzureClusterTemplateSpec{ 686 Template: AzureClusterTemplateResource{ 687 Spec: AzureClusterTemplateResourceSpec{ 688 NetworkSpec: NetworkTemplateSpec{ 689 APIServerLB: LoadBalancerClassSpec{ 690 Type: Internal, 691 }, 692 }, 693 }, 694 }, 695 }, 696 }, 697 expectValid: true, 698 }, 699 { 700 name: "timeout should not be less than minimum", 701 clusterTemplate: &AzureClusterTemplate{ 702 ObjectMeta: metav1.ObjectMeta{ 703 Name: "test-cluster-template", 704 }, 705 Spec: AzureClusterTemplateSpec{ 706 Template: AzureClusterTemplateResource{ 707 Spec: AzureClusterTemplateResourceSpec{ 708 NetworkSpec: NetworkTemplateSpec{ 709 APIServerLB: LoadBalancerClassSpec{ 710 Type: Public, 711 }, 712 NodeOutboundLB: &LoadBalancerClassSpec{ 713 IdleTimeoutInMinutes: ptr.To[int32](2), 714 }, 715 }, 716 }, 717 }, 718 }, 719 }, 720 expectValid: false, 721 }, 722 { 723 name: "timeout should not be more than maximum", 724 clusterTemplate: &AzureClusterTemplate{ 725 ObjectMeta: metav1.ObjectMeta{ 726 Name: "test-cluster-template", 727 }, 728 Spec: AzureClusterTemplateSpec{ 729 Template: AzureClusterTemplateResource{ 730 Spec: AzureClusterTemplateResourceSpec{ 731 NetworkSpec: NetworkTemplateSpec{ 732 APIServerLB: LoadBalancerClassSpec{ 733 Type: Public, 734 }, 735 NodeOutboundLB: &LoadBalancerClassSpec{ 736 IdleTimeoutInMinutes: ptr.To[int32](60), 737 }, 738 }, 739 }, 740 }, 741 }, 742 }, 743 expectValid: false, 744 }, 745 } 746 747 for _, c := range cases { 748 tc := c 749 t.Run(tc.name, func(t *testing.T) { 750 t.Parallel() 751 g := NewWithT(t) 752 res := tc.clusterTemplate.validateNodeOutboundLB() 753 754 if tc.expectValid { 755 g.Expect(res).To(BeNil()) 756 } else { 757 g.Expect(res).NotTo(BeNil()) 758 } 759 }) 760 } 761 } 762 763 func TestValidatePrivateDNSZoneName(t *testing.T) { 764 cases := []struct { 765 name string 766 clusterTemplate *AzureClusterTemplate 767 expectValid bool 768 }{ 769 { 770 name: "not set", 771 clusterTemplate: &AzureClusterTemplate{ 772 ObjectMeta: metav1.ObjectMeta{ 773 Name: "test-cluster-template", 774 }, 775 Spec: AzureClusterTemplateSpec{ 776 Template: AzureClusterTemplateResource{ 777 Spec: AzureClusterTemplateResourceSpec{ 778 NetworkSpec: NetworkTemplateSpec{}, 779 }, 780 }, 781 }, 782 }, 783 expectValid: true, 784 }, 785 { 786 name: "show not be set if APIServerLB.Type is not internal", 787 clusterTemplate: &AzureClusterTemplate{ 788 ObjectMeta: metav1.ObjectMeta{ 789 Name: "test-cluster-template", 790 }, 791 Spec: AzureClusterTemplateSpec{ 792 Template: AzureClusterTemplateResource{ 793 Spec: AzureClusterTemplateResourceSpec{ 794 NetworkSpec: NetworkTemplateSpec{ 795 APIServerLB: LoadBalancerClassSpec{ 796 Type: Public, 797 }, 798 NetworkClassSpec: NetworkClassSpec{ 799 PrivateDNSZoneName: "a.b.c", 800 }, 801 }, 802 }, 803 }, 804 }, 805 }, 806 expectValid: false, 807 }, 808 } 809 810 for _, c := range cases { 811 tc := c 812 t.Run(tc.name, func(t *testing.T) { 813 t.Parallel() 814 g := NewWithT(t) 815 res := tc.clusterTemplate.validatePrivateDNSZoneName() 816 817 if tc.expectValid { 818 g.Expect(res).To(BeNil()) 819 } else { 820 g.Expect(res).NotTo(BeNil()) 821 } 822 }) 823 } 824 } 825 func TestValidateNetworkSpec(t *testing.T) { 826 cases := []struct { 827 name string 828 clusterTemplate *AzureClusterTemplate 829 expectValid bool 830 }{ 831 { 832 name: "subnet with SubnetNode role and enabled IPv6 triggers needOutboundLB and calls validateNodeOutboundLB", 833 clusterTemplate: &AzureClusterTemplate{ 834 ObjectMeta: metav1.ObjectMeta{ 835 Name: "test-cluster-template", 836 }, 837 Spec: AzureClusterTemplateSpec{ 838 Template: AzureClusterTemplateResource{ 839 Spec: AzureClusterTemplateResourceSpec{ 840 NetworkSpec: NetworkTemplateSpec{ 841 Subnets: SubnetTemplatesSpec{ 842 { 843 SubnetClassSpec: SubnetClassSpec{ 844 Role: SubnetNode, 845 CIDRBlocks: []string{"2001:beea::1/64"}, 846 }, 847 }, 848 }, 849 }, 850 }, 851 }, 852 }, 853 }, 854 expectValid: false, 855 }, 856 { 857 name: "subnet with non-SubnetNode role", 858 clusterTemplate: &AzureClusterTemplate{ 859 ObjectMeta: metav1.ObjectMeta{ 860 Name: "test-cluster-template", 861 }, 862 Spec: AzureClusterTemplateSpec{ 863 Template: AzureClusterTemplateResource{ 864 Spec: AzureClusterTemplateResourceSpec{ 865 NetworkSpec: NetworkTemplateSpec{ 866 Subnets: SubnetTemplatesSpec{ 867 { 868 SubnetClassSpec: SubnetClassSpec{ 869 Role: "SomeOtherRole", 870 CIDRBlocks: []string{"10.0.0.0/24"}, 871 }, 872 }, 873 }, 874 }, 875 }, 876 }, 877 }, 878 }, 879 expectValid: true, // No need for outbound LB when not SubnetNode 880 }, 881 } 882 883 for _, c := range cases { 884 tc := c 885 t.Run(tc.name, func(t *testing.T) { 886 t.Parallel() 887 g := NewWithT(t) 888 res := tc.clusterTemplate.validateNetworkSpec() 889 if tc.expectValid { 890 g.Expect(res).To(BeNil()) 891 } else { 892 g.Expect(res).NotTo(BeNil()) 893 } 894 }) 895 } 896 }