sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/scope/machine_test.go (about) 1 /* 2 Copyright 2018 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 scope 18 19 import ( 20 "context" 21 "reflect" 22 "testing" 23 24 "github.com/Azure/azure-sdk-for-go/sdk/azidentity" 25 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2" 26 azureautorest "github.com/Azure/go-autorest/autorest/azure" 27 "github.com/Azure/go-autorest/autorest/azure/auth" 28 "github.com/google/go-cmp/cmp" 29 . "github.com/onsi/gomega" 30 "go.uber.org/mock/gomock" 31 "k8s.io/apimachinery/pkg/api/resource" 32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/utils/ptr" 34 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 35 "sigs.k8s.io/cluster-api-provider-azure/azure" 36 "sigs.k8s.io/cluster-api-provider-azure/azure/mock_azure" 37 "sigs.k8s.io/cluster-api-provider-azure/azure/services/disks" 38 "sigs.k8s.io/cluster-api-provider-azure/azure/services/inboundnatrules" 39 "sigs.k8s.io/cluster-api-provider-azure/azure/services/networkinterfaces" 40 "sigs.k8s.io/cluster-api-provider-azure/azure/services/publicips" 41 "sigs.k8s.io/cluster-api-provider-azure/azure/services/resourceskus" 42 "sigs.k8s.io/cluster-api-provider-azure/azure/services/roleassignments" 43 "sigs.k8s.io/cluster-api-provider-azure/azure/services/virtualmachineimages" 44 "sigs.k8s.io/cluster-api-provider-azure/azure/services/virtualmachineimages/mock_virtualmachineimages" 45 "sigs.k8s.io/cluster-api-provider-azure/azure/services/vmextensions" 46 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 47 ) 48 49 func TestMachineScope_Name(t *testing.T) { 50 tests := []struct { 51 name string 52 machineScope MachineScope 53 want string 54 testLength bool 55 }{ 56 { 57 name: "if provider ID exists, use it", 58 machineScope: MachineScope{ 59 AzureMachine: &infrav1.AzureMachine{ 60 ObjectMeta: metav1.ObjectMeta{ 61 Name: "machine-with-a-long-name", 62 }, 63 Spec: infrav1.AzureMachineSpec{ 64 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 65 OSDisk: infrav1.OSDisk{ 66 OSType: "Windows", 67 }, 68 }, 69 }, 70 }, 71 want: "machine-name", 72 }, 73 { 74 name: "linux can be any length", 75 machineScope: MachineScope{ 76 AzureMachine: &infrav1.AzureMachine{ 77 ObjectMeta: metav1.ObjectMeta{ 78 Name: "machine-with-really-really-long-name", 79 }, 80 Spec: infrav1.AzureMachineSpec{ 81 OSDisk: infrav1.OSDisk{ 82 OSType: "Linux", 83 }, 84 }, 85 }, 86 }, 87 want: "machine-with-really-really-long-name", 88 }, 89 { 90 name: "Windows name with long MachineName and short cluster name", 91 machineScope: MachineScope{ 92 ClusterScoper: &ClusterScope{ 93 Cluster: &clusterv1.Cluster{ 94 ObjectMeta: metav1.ObjectMeta{ 95 Name: "cluster", 96 }, 97 }, 98 }, 99 AzureMachine: &infrav1.AzureMachine{ 100 TypeMeta: metav1.TypeMeta{}, 101 ObjectMeta: metav1.ObjectMeta{ 102 Name: "machine-90123456", 103 }, 104 Spec: infrav1.AzureMachineSpec{ 105 OSDisk: infrav1.OSDisk{ 106 OSType: "Windows", 107 }, 108 }, 109 Status: infrav1.AzureMachineStatus{}, 110 }, 111 }, 112 want: "machine-9-23456", 113 testLength: true, 114 }, 115 { 116 name: "Windows name with long MachineName and long cluster name", 117 machineScope: MachineScope{ 118 ClusterScoper: &ClusterScope{ 119 Cluster: &clusterv1.Cluster{ 120 ObjectMeta: metav1.ObjectMeta{ 121 Name: "cluster8901234", 122 }, 123 }, 124 }, 125 AzureMachine: &infrav1.AzureMachine{ 126 TypeMeta: metav1.TypeMeta{}, 127 ObjectMeta: metav1.ObjectMeta{ 128 Name: "machine-90123456", 129 }, 130 Spec: infrav1.AzureMachineSpec{ 131 OSDisk: infrav1.OSDisk{ 132 OSType: "Windows", 133 }, 134 }, 135 Status: infrav1.AzureMachineStatus{}, 136 }, 137 }, 138 want: "machine-9-23456", 139 testLength: true, 140 }, 141 } 142 for _, tt := range tests { 143 t.Run(tt.name, func(t *testing.T) { 144 got := tt.machineScope.Name() 145 if got != tt.want { 146 t.Errorf("MachineScope.Name() = %v, want %v", got, tt.want) 147 } 148 149 if tt.testLength && len(got) > 15 { 150 t.Errorf("Length of MachineScope.Name() = %v, want less than %v", len(got), 15) 151 } 152 }) 153 } 154 } 155 156 func TestMachineScope_GetVMID(t *testing.T) { 157 tests := []struct { 158 name string 159 machineScope MachineScope 160 want string 161 }{ 162 { 163 name: "returns the vm name from provider ID", 164 machineScope: MachineScope{ 165 AzureMachine: &infrav1.AzureMachine{ 166 ObjectMeta: metav1.ObjectMeta{ 167 Name: "not-this-name", 168 }, 169 Spec: infrav1.AzureMachineSpec{ 170 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 171 }, 172 }, 173 }, 174 want: "machine-name", 175 }, 176 { 177 name: "returns empty if provider ID is invalid", 178 machineScope: MachineScope{ 179 AzureMachine: &infrav1.AzureMachine{ 180 ObjectMeta: metav1.ObjectMeta{ 181 Name: "machine-name", 182 }, 183 Spec: infrav1.AzureMachineSpec{ 184 ProviderID: ptr.To("foo"), 185 }, 186 }, 187 }, 188 want: "", 189 }, 190 } 191 for _, tt := range tests { 192 t.Run(tt.name, func(t *testing.T) { 193 got := tt.machineScope.GetVMID() 194 if got != tt.want { 195 t.Errorf("MachineScope.GetVMID() = %v, want %v", got, tt.want) 196 } 197 }) 198 } 199 } 200 201 func TestMachineScope_ProviderID(t *testing.T) { 202 tests := []struct { 203 name string 204 machineScope MachineScope 205 want string 206 }{ 207 { 208 name: "returns the entire provider ID", 209 machineScope: MachineScope{ 210 AzureMachine: &infrav1.AzureMachine{ 211 ObjectMeta: metav1.ObjectMeta{ 212 Name: "not-this-name", 213 }, 214 Spec: infrav1.AzureMachineSpec{ 215 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 216 }, 217 }, 218 }, 219 want: "azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name", 220 }, 221 { 222 name: "returns empty if provider ID is empty", 223 machineScope: MachineScope{ 224 AzureMachine: &infrav1.AzureMachine{ 225 ObjectMeta: metav1.ObjectMeta{ 226 Name: "machine-name", 227 }, 228 Spec: infrav1.AzureMachineSpec{ 229 ProviderID: ptr.To(""), 230 }, 231 }, 232 }, 233 want: "", 234 }, 235 } 236 for _, tt := range tests { 237 t.Run(tt.name, func(t *testing.T) { 238 got := tt.machineScope.ProviderID() 239 if got != tt.want { 240 t.Errorf("MachineScope.ProviderID() = %v, want %v", got, tt.want) 241 } 242 }) 243 } 244 } 245 246 func TestMachineScope_PublicIPSpecs(t *testing.T) { 247 tests := []struct { 248 name string 249 machineScope MachineScope 250 want []azure.ResourceSpecGetter 251 }{ 252 { 253 name: "returns nil if AllocatePublicIP is false", 254 machineScope: MachineScope{ 255 AzureMachine: &infrav1.AzureMachine{ 256 ObjectMeta: metav1.ObjectMeta{ 257 Name: "machine-name", 258 }, 259 Spec: infrav1.AzureMachineSpec{ 260 AllocatePublicIP: false, 261 }, 262 }, 263 }, 264 want: nil, 265 }, 266 { 267 name: "appends to PublicIPSpec for node if AllocatePublicIP is true", 268 machineScope: MachineScope{ 269 AzureMachine: &infrav1.AzureMachine{ 270 ObjectMeta: metav1.ObjectMeta{ 271 Name: "machine-name", 272 }, 273 Spec: infrav1.AzureMachineSpec{ 274 AllocatePublicIP: true, 275 }, 276 }, 277 ClusterScoper: &ClusterScope{ 278 Cluster: &clusterv1.Cluster{ 279 ObjectMeta: metav1.ObjectMeta{ 280 Name: "my-cluster", 281 // Note: m.ClusterName() takes the value from the Cluster object, not the AzureCluster object 282 }, 283 }, 284 AzureCluster: &infrav1.AzureCluster{ 285 ObjectMeta: metav1.ObjectMeta{ 286 Name: "my-cluster", 287 }, 288 Status: infrav1.AzureClusterStatus{ 289 FailureDomains: map[string]clusterv1.FailureDomainSpec{ 290 "failure-domain-id-1": {}, 291 "failure-domain-id-2": {}, 292 "failure-domain-id-3": {}, 293 }, 294 }, 295 Spec: infrav1.AzureClusterSpec{ 296 ResourceGroup: "my-rg", 297 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 298 SubscriptionID: "123", 299 Location: "centralIndia", 300 AdditionalTags: infrav1.Tags{ 301 "Name": "my-publicip-ipv6", 302 "sigs.k8s.io_cluster-api-provider-azure_cluster_my-cluster": "owned", 303 }, 304 }, 305 NetworkSpec: infrav1.NetworkSpec{ 306 APIServerLB: infrav1.LoadBalancerSpec{ 307 LoadBalancerClassSpec: infrav1.LoadBalancerClassSpec{ 308 Type: infrav1.Internal, 309 }, 310 }, 311 }, 312 }, 313 }, 314 }, 315 }, 316 want: []azure.ResourceSpecGetter{ 317 &publicips.PublicIPSpec{ 318 Name: "pip-machine-name", 319 ResourceGroup: "my-rg", 320 DNSName: "", 321 IsIPv6: false, 322 ClusterName: "my-cluster", 323 Location: "centralIndia", 324 FailureDomains: []*string{ptr.To("failure-domain-id-1"), ptr.To("failure-domain-id-2"), ptr.To("failure-domain-id-3")}, 325 AdditionalTags: infrav1.Tags{ 326 "Name": "my-publicip-ipv6", 327 "sigs.k8s.io_cluster-api-provider-azure_cluster_my-cluster": "owned", 328 }, 329 }, 330 }, 331 }, 332 } 333 for _, tt := range tests { 334 t.Run(tt.name, func(t *testing.T) { 335 if got := tt.machineScope.PublicIPSpecs(); !reflect.DeepEqual(got, tt.want) { 336 t.Errorf("PublicIPSpecs() expected but got: %s", cmp.Diff(tt.want, got)) 337 } 338 }) 339 } 340 } 341 342 func TestMachineScope_InboundNatSpecs(t *testing.T) { 343 tests := []struct { 344 name string 345 machineScope MachineScope 346 want []azure.ResourceSpecGetter 347 }{ 348 { 349 name: "returns empty when infra is not control plane", 350 machineScope: MachineScope{ 351 Machine: &clusterv1.Machine{}, 352 AzureMachine: &infrav1.AzureMachine{ 353 ObjectMeta: metav1.ObjectMeta{ 354 Name: "machine-name", 355 }, 356 }, 357 }, 358 want: []azure.ResourceSpecGetter{}, 359 }, 360 { 361 name: "returns InboundNatSpec when infra is control plane", 362 machineScope: MachineScope{ 363 Machine: &clusterv1.Machine{ 364 ObjectMeta: metav1.ObjectMeta{ 365 Labels: map[string]string{ 366 clusterv1.MachineControlPlaneLabel: "", 367 }, 368 }, 369 }, 370 AzureMachine: &infrav1.AzureMachine{ 371 ObjectMeta: metav1.ObjectMeta{ 372 Name: "machine-name", 373 }, 374 }, 375 ClusterScoper: &ClusterScope{ 376 AzureClients: AzureClients{ 377 EnvironmentSettings: auth.EnvironmentSettings{ 378 Values: map[string]string{ 379 auth.SubscriptionID: "123", 380 }, 381 }, 382 }, 383 AzureCluster: &infrav1.AzureCluster{ 384 Spec: infrav1.AzureClusterSpec{ 385 ResourceGroup: "my-rg", 386 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 387 SubscriptionID: "123", 388 }, 389 NetworkSpec: infrav1.NetworkSpec{ 390 APIServerLB: infrav1.LoadBalancerSpec{ 391 Name: "foo-loadbalancer", 392 FrontendIPs: []infrav1.FrontendIP{ 393 { 394 Name: "foo-frontend-ip", 395 }, 396 }, 397 }, 398 }, 399 }, 400 }, 401 }, 402 }, 403 want: []azure.ResourceSpecGetter{ 404 &inboundnatrules.InboundNatSpec{ 405 Name: "machine-name", 406 LoadBalancerName: "foo-loadbalancer", 407 ResourceGroup: "my-rg", 408 FrontendIPConfigurationID: ptr.To(azure.FrontendIPConfigID("123", "my-rg", "foo-loadbalancer", "foo-frontend-ip")), 409 }, 410 }, 411 }, 412 } 413 for _, tt := range tests { 414 tt := tt 415 t.Run(tt.name, func(t *testing.T) { 416 t.Parallel() 417 if got := tt.machineScope.InboundNatSpecs(); !reflect.DeepEqual(got, tt.want) { 418 t.Errorf("InboundNatSpecs() = %s, want %s", specArrayToString(got), specArrayToString(tt.want)) 419 } 420 }) 421 } 422 } 423 424 func TestMachineScope_RoleAssignmentSpecs(t *testing.T) { 425 tests := []struct { 426 name string 427 machineScope MachineScope 428 want []azure.ResourceSpecGetter 429 }{ 430 { 431 name: "returns empty if VM identity is not system assigned", 432 machineScope: MachineScope{ 433 Machine: &clusterv1.Machine{}, 434 AzureMachine: &infrav1.AzureMachine{ 435 ObjectMeta: metav1.ObjectMeta{ 436 Name: "machine-name", 437 }, 438 }, 439 }, 440 want: []azure.ResourceSpecGetter{}, 441 }, 442 { 443 name: "returns RoleAssignmentSpec if VM identity is system assigned", 444 machineScope: MachineScope{ 445 Machine: &clusterv1.Machine{}, 446 AzureMachine: &infrav1.AzureMachine{ 447 ObjectMeta: metav1.ObjectMeta{ 448 Name: "machine-name", 449 }, 450 Spec: infrav1.AzureMachineSpec{ 451 Identity: infrav1.VMIdentitySystemAssigned, 452 SystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 453 Name: "azure-role-assignment-name", 454 }, 455 }, 456 }, 457 ClusterScoper: &ClusterScope{ 458 AzureClients: AzureClients{ 459 EnvironmentSettings: auth.EnvironmentSettings{ 460 Values: map[string]string{ 461 auth.SubscriptionID: "123", 462 }, 463 }, 464 }, 465 AzureCluster: &infrav1.AzureCluster{ 466 Spec: infrav1.AzureClusterSpec{ 467 ResourceGroup: "my-rg", 468 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 469 Location: "westus", 470 }, 471 }, 472 }, 473 }, 474 }, 475 want: []azure.ResourceSpecGetter{ 476 &roleassignments.RoleAssignmentSpec{ 477 ResourceType: azure.VirtualMachine, 478 MachineName: "machine-name", 479 Name: "azure-role-assignment-name", 480 ResourceGroup: "my-rg", 481 PrincipalID: ptr.To("fakePrincipalID"), 482 PrincipalType: armauthorization.PrincipalTypeServicePrincipal, 483 }, 484 }, 485 }, 486 { 487 name: "returns RoleAssignmentSpec with specified scope and role assignment id", 488 machineScope: MachineScope{ 489 Machine: &clusterv1.Machine{}, 490 AzureMachine: &infrav1.AzureMachine{ 491 ObjectMeta: metav1.ObjectMeta{ 492 Name: "machine-name", 493 }, 494 Spec: infrav1.AzureMachineSpec{ 495 Identity: infrav1.VMIdentitySystemAssigned, 496 SystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 497 Name: "azure-role-assignment-name", 498 Scope: "/subscriptions/123/resourceGroups/my-rg", 499 DefinitionID: "/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Authorization/roleAssignments/123", 500 }, 501 }, 502 }, 503 ClusterScoper: &ClusterScope{ 504 AzureClients: AzureClients{ 505 EnvironmentSettings: auth.EnvironmentSettings{ 506 Values: map[string]string{ 507 auth.SubscriptionID: "123", 508 }, 509 }, 510 }, 511 AzureCluster: &infrav1.AzureCluster{ 512 Spec: infrav1.AzureClusterSpec{ 513 ResourceGroup: "my-rg", 514 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 515 Location: "westus", 516 }, 517 }, 518 }, 519 }, 520 }, 521 want: []azure.ResourceSpecGetter{ 522 &roleassignments.RoleAssignmentSpec{ 523 ResourceType: azure.VirtualMachine, 524 MachineName: "machine-name", 525 Name: "azure-role-assignment-name", 526 ResourceGroup: "my-rg", 527 Scope: "/subscriptions/123/resourceGroups/my-rg", 528 RoleDefinitionID: "/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Authorization/roleAssignments/123", 529 PrincipalID: ptr.To("fakePrincipalID"), 530 PrincipalType: armauthorization.PrincipalTypeServicePrincipal, 531 }, 532 }, 533 }, 534 } 535 for _, tt := range tests { 536 t.Run(tt.name, func(t *testing.T) { 537 if got := tt.machineScope.RoleAssignmentSpecs(ptr.To("fakePrincipalID")); !reflect.DeepEqual(got, tt.want) { 538 t.Errorf("RoleAssignmentSpecs() = %v, want %v", got, tt.want) 539 } 540 }) 541 } 542 } 543 544 func TestMachineScope_VMExtensionSpecs(t *testing.T) { 545 tests := []struct { 546 name string 547 machineScope MachineScope 548 want []azure.ResourceSpecGetter 549 }{ 550 { 551 name: "If OS type is Linux and cloud is AzurePublicCloud, it returns ExtensionSpec", 552 machineScope: MachineScope{ 553 Machine: &clusterv1.Machine{}, 554 AzureMachine: &infrav1.AzureMachine{ 555 ObjectMeta: metav1.ObjectMeta{ 556 Name: "machine-name", 557 }, 558 Spec: infrav1.AzureMachineSpec{ 559 OSDisk: infrav1.OSDisk{ 560 OSType: "Linux", 561 }, 562 }, 563 }, 564 ClusterScoper: &ClusterScope{ 565 AzureClients: AzureClients{ 566 EnvironmentSettings: auth.EnvironmentSettings{ 567 Environment: azureautorest.Environment{ 568 Name: azureautorest.PublicCloud.Name, 569 }, 570 }, 571 }, 572 AzureCluster: &infrav1.AzureCluster{ 573 Spec: infrav1.AzureClusterSpec{ 574 ResourceGroup: "my-rg", 575 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 576 Location: "westus", 577 }, 578 }, 579 }, 580 }, 581 cache: &MachineCache{ 582 VMSKU: resourceskus.SKU{}, 583 }, 584 }, 585 want: []azure.ResourceSpecGetter{ 586 &vmextensions.VMExtensionSpec{ 587 ExtensionSpec: azure.ExtensionSpec{ 588 Name: "CAPZ.Linux.Bootstrapping", 589 VMName: "machine-name", 590 Publisher: "Microsoft.Azure.ContainerUpstream", 591 Version: "1.0", 592 ProtectedSettings: map[string]string{ 593 "commandToExecute": azure.LinuxBootstrapExtensionCommand, 594 }, 595 }, 596 ResourceGroup: "my-rg", 597 Location: "westus", 598 }, 599 }, 600 }, 601 { 602 name: "If OS type is Linux and cloud is not AzurePublicCloud, it returns empty", 603 machineScope: MachineScope{ 604 Machine: &clusterv1.Machine{}, 605 AzureMachine: &infrav1.AzureMachine{ 606 ObjectMeta: metav1.ObjectMeta{ 607 Name: "machine-name", 608 }, 609 Spec: infrav1.AzureMachineSpec{ 610 OSDisk: infrav1.OSDisk{ 611 OSType: "Linux", 612 }, 613 }, 614 }, 615 ClusterScoper: &ClusterScope{ 616 AzureClients: AzureClients{ 617 EnvironmentSettings: auth.EnvironmentSettings{ 618 Environment: azureautorest.Environment{ 619 Name: azureautorest.USGovernmentCloud.Name, 620 }, 621 }, 622 }, 623 AzureCluster: &infrav1.AzureCluster{ 624 Spec: infrav1.AzureClusterSpec{ 625 ResourceGroup: "my-rg", 626 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 627 Location: "westus", 628 }, 629 }, 630 }, 631 }, 632 cache: &MachineCache{ 633 VMSKU: resourceskus.SKU{}, 634 }, 635 }, 636 want: []azure.ResourceSpecGetter{}, 637 }, 638 { 639 name: "If OS type is Windows and cloud is AzurePublicCloud, it returns ExtensionSpec", 640 machineScope: MachineScope{ 641 Machine: &clusterv1.Machine{}, 642 AzureMachine: &infrav1.AzureMachine{ 643 ObjectMeta: metav1.ObjectMeta{ 644 Name: "machine-name", 645 }, 646 Spec: infrav1.AzureMachineSpec{ 647 OSDisk: infrav1.OSDisk{ 648 OSType: "Windows", 649 }, 650 }, 651 }, 652 ClusterScoper: &ClusterScope{ 653 AzureClients: AzureClients{ 654 EnvironmentSettings: auth.EnvironmentSettings{ 655 Environment: azureautorest.Environment{ 656 Name: azureautorest.PublicCloud.Name, 657 }, 658 }, 659 }, 660 AzureCluster: &infrav1.AzureCluster{ 661 Spec: infrav1.AzureClusterSpec{ 662 ResourceGroup: "my-rg", 663 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 664 Location: "westus", 665 }, 666 }, 667 }, 668 }, 669 cache: &MachineCache{ 670 VMSKU: resourceskus.SKU{}, 671 }, 672 }, 673 want: []azure.ResourceSpecGetter{ 674 &vmextensions.VMExtensionSpec{ 675 ExtensionSpec: azure.ExtensionSpec{ 676 Name: "CAPZ.Windows.Bootstrapping", 677 VMName: "machine-name", 678 Publisher: "Microsoft.Azure.ContainerUpstream", 679 Version: "1.0", 680 ProtectedSettings: map[string]string{ 681 "commandToExecute": azure.WindowsBootstrapExtensionCommand, 682 }, 683 }, 684 ResourceGroup: "my-rg", 685 Location: "westus", 686 }, 687 }, 688 }, 689 { 690 name: "If OS type is Windows and cloud is not AzurePublicCloud, it returns empty", 691 machineScope: MachineScope{ 692 Machine: &clusterv1.Machine{}, 693 AzureMachine: &infrav1.AzureMachine{ 694 ObjectMeta: metav1.ObjectMeta{ 695 Name: "machine-name", 696 }, 697 Spec: infrav1.AzureMachineSpec{ 698 OSDisk: infrav1.OSDisk{ 699 OSType: "Windows", 700 }, 701 }, 702 }, 703 ClusterScoper: &ClusterScope{ 704 AzureClients: AzureClients{ 705 EnvironmentSettings: auth.EnvironmentSettings{ 706 Environment: azureautorest.Environment{ 707 Name: azureautorest.USGovernmentCloud.Name, 708 }, 709 }, 710 }, 711 AzureCluster: &infrav1.AzureCluster{ 712 Spec: infrav1.AzureClusterSpec{ 713 ResourceGroup: "my-rg", 714 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 715 Location: "westus", 716 }, 717 }, 718 }, 719 }, 720 cache: &MachineCache{ 721 VMSKU: resourceskus.SKU{}, 722 }, 723 }, 724 want: []azure.ResourceSpecGetter{}, 725 }, 726 { 727 name: "If OS type is not Linux or Windows and cloud is AzurePublicCloud, it returns empty", 728 machineScope: MachineScope{ 729 Machine: &clusterv1.Machine{}, 730 AzureMachine: &infrav1.AzureMachine{ 731 ObjectMeta: metav1.ObjectMeta{ 732 Name: "machine-name", 733 }, 734 Spec: infrav1.AzureMachineSpec{ 735 OSDisk: infrav1.OSDisk{ 736 OSType: "Other", 737 }, 738 }, 739 }, 740 ClusterScoper: &ClusterScope{ 741 AzureClients: AzureClients{ 742 EnvironmentSettings: auth.EnvironmentSettings{ 743 Environment: azureautorest.Environment{ 744 Name: azureautorest.PublicCloud.Name, 745 }, 746 }, 747 }, 748 AzureCluster: &infrav1.AzureCluster{ 749 Spec: infrav1.AzureClusterSpec{ 750 ResourceGroup: "my-rg", 751 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 752 Location: "westus", 753 }, 754 }, 755 }, 756 }, 757 cache: &MachineCache{ 758 VMSKU: resourceskus.SKU{}, 759 }, 760 }, 761 want: []azure.ResourceSpecGetter{}, 762 }, 763 { 764 name: "If OS type is not Windows or Linux and cloud is not AzurePublicCloud, it returns empty", 765 machineScope: MachineScope{ 766 Machine: &clusterv1.Machine{}, 767 AzureMachine: &infrav1.AzureMachine{ 768 ObjectMeta: metav1.ObjectMeta{ 769 Name: "machine-name", 770 }, 771 Spec: infrav1.AzureMachineSpec{ 772 OSDisk: infrav1.OSDisk{ 773 OSType: "Other", 774 }, 775 }, 776 }, 777 ClusterScoper: &ClusterScope{ 778 AzureClients: AzureClients{ 779 EnvironmentSettings: auth.EnvironmentSettings{ 780 Environment: azureautorest.Environment{ 781 Name: azureautorest.USGovernmentCloud.Name, 782 }, 783 }, 784 }, 785 AzureCluster: &infrav1.AzureCluster{ 786 Spec: infrav1.AzureClusterSpec{ 787 ResourceGroup: "my-rg", 788 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 789 Location: "westus", 790 }, 791 }, 792 }, 793 }, 794 cache: &MachineCache{ 795 VMSKU: resourceskus.SKU{}, 796 }, 797 }, 798 want: []azure.ResourceSpecGetter{}, 799 }, 800 { 801 name: "If a custom VM extension is specified, it returns the custom VM extension", 802 machineScope: MachineScope{ 803 Machine: &clusterv1.Machine{}, 804 AzureMachine: &infrav1.AzureMachine{ 805 ObjectMeta: metav1.ObjectMeta{ 806 Name: "machine-name", 807 }, 808 Spec: infrav1.AzureMachineSpec{ 809 OSDisk: infrav1.OSDisk{ 810 OSType: "Linux", 811 }, 812 VMExtensions: []infrav1.VMExtension{ 813 { 814 Name: "custom-vm-extension", 815 Publisher: "Microsoft.Azure.Extensions", 816 Version: "2.0", 817 Settings: map[string]string{ 818 "timestamp": "1234567890", 819 }, 820 ProtectedSettings: map[string]string{ 821 "commandToExecute": "echo hello world", 822 }, 823 }, 824 }, 825 }, 826 }, 827 ClusterScoper: &ClusterScope{ 828 AzureClients: AzureClients{ 829 EnvironmentSettings: auth.EnvironmentSettings{ 830 Environment: azureautorest.Environment{ 831 Name: azureautorest.PublicCloud.Name, 832 }, 833 }, 834 }, 835 AzureCluster: &infrav1.AzureCluster{ 836 Spec: infrav1.AzureClusterSpec{ 837 ResourceGroup: "my-rg", 838 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 839 Location: "westus", 840 }, 841 }, 842 }, 843 }, 844 cache: &MachineCache{ 845 VMSKU: resourceskus.SKU{}, 846 }, 847 }, 848 want: []azure.ResourceSpecGetter{ 849 &vmextensions.VMExtensionSpec{ 850 ExtensionSpec: azure.ExtensionSpec{ 851 Name: "custom-vm-extension", 852 VMName: "machine-name", 853 Publisher: "Microsoft.Azure.Extensions", 854 Version: "2.0", 855 Settings: map[string]string{ 856 "timestamp": "1234567890", 857 }, 858 ProtectedSettings: map[string]string{ 859 "commandToExecute": "echo hello world", 860 }, 861 }, 862 ResourceGroup: "my-rg", 863 Location: "westus", 864 }, 865 &vmextensions.VMExtensionSpec{ 866 ExtensionSpec: azure.ExtensionSpec{ 867 Name: "CAPZ.Linux.Bootstrapping", 868 VMName: "machine-name", 869 Publisher: "Microsoft.Azure.ContainerUpstream", 870 Version: "1.0", 871 ProtectedSettings: map[string]string{ 872 "commandToExecute": azure.LinuxBootstrapExtensionCommand, 873 }, 874 }, 875 ResourceGroup: "my-rg", 876 Location: "westus", 877 }, 878 }, 879 }, 880 } 881 for _, tt := range tests { 882 t.Run(tt.name, func(t *testing.T) { 883 if got := tt.machineScope.VMExtensionSpecs(); !reflect.DeepEqual(got, tt.want) { 884 t.Errorf("VMExtensionSpecs() = \n%s, want \n%s", specArrayToString(got), specArrayToString(tt.want)) 885 } 886 }) 887 } 888 } 889 890 func TestMachineScope_Subnet(t *testing.T) { 891 tests := []struct { 892 name string 893 machineScope MachineScope 894 want infrav1.SubnetSpec 895 }{ 896 { 897 name: "returns empty if no subnet is found at cluster scope", 898 machineScope: MachineScope{ 899 AzureMachine: &infrav1.AzureMachine{ 900 ObjectMeta: metav1.ObjectMeta{ 901 Name: "machine-name", 902 }, 903 Spec: infrav1.AzureMachineSpec{ 904 SubnetName: "machine-name-subnet", 905 }, 906 }, 907 ClusterScoper: &ClusterScope{ 908 AzureCluster: &infrav1.AzureCluster{ 909 Spec: infrav1.AzureClusterSpec{ 910 NetworkSpec: infrav1.NetworkSpec{ 911 Subnets: []infrav1.SubnetSpec{}, 912 }, 913 }, 914 }, 915 }, 916 }, 917 want: infrav1.SubnetSpec{}, 918 }, 919 { 920 name: "returns the machine subnet name if the same is present in the cluster scope", 921 machineScope: MachineScope{ 922 AzureMachine: &infrav1.AzureMachine{ 923 ObjectMeta: metav1.ObjectMeta{ 924 Name: "machine-name", 925 }, 926 Spec: infrav1.AzureMachineSpec{ 927 NetworkInterfaces: []infrav1.NetworkInterface{{ 928 SubnetName: "machine-name-subnet", 929 }}, 930 }, 931 }, 932 ClusterScoper: &ClusterScope{ 933 AzureCluster: &infrav1.AzureCluster{ 934 Spec: infrav1.AzureClusterSpec{ 935 NetworkSpec: infrav1.NetworkSpec{ 936 Subnets: []infrav1.SubnetSpec{ 937 { 938 SubnetClassSpec: infrav1.SubnetClassSpec{ 939 Name: "machine-name-subnet", 940 }, 941 }, 942 { 943 SubnetClassSpec: infrav1.SubnetClassSpec{ 944 Name: "another-machine-name-subnet", 945 }, 946 }, 947 }, 948 }, 949 }, 950 }, 951 }, 952 }, 953 want: infrav1.SubnetSpec{ 954 SubnetClassSpec: infrav1.SubnetClassSpec{ 955 Name: "machine-name-subnet", 956 }, 957 }, 958 }, 959 { 960 name: "returns empty if machine subnet name is not present in the cluster scope", 961 machineScope: MachineScope{ 962 AzureMachine: &infrav1.AzureMachine{ 963 ObjectMeta: metav1.ObjectMeta{ 964 Name: "machine-name", 965 }, 966 Spec: infrav1.AzureMachineSpec{ 967 SubnetName: "machine-name-subnet", 968 }, 969 }, 970 ClusterScoper: &ClusterScope{ 971 AzureCluster: &infrav1.AzureCluster{ 972 Spec: infrav1.AzureClusterSpec{ 973 NetworkSpec: infrav1.NetworkSpec{}, 974 }, 975 }, 976 }, 977 }, 978 want: infrav1.SubnetSpec{}, 979 }, 980 } 981 for _, tt := range tests { 982 t.Run(tt.name, func(t *testing.T) { 983 if got := tt.machineScope.Subnet(); !reflect.DeepEqual(got, tt.want) { 984 t.Errorf("Subnet() = %v, want %v", got, tt.want) 985 } 986 }) 987 } 988 } 989 990 func TestMachineScope_AvailabilityZone(t *testing.T) { 991 tests := []struct { 992 name string 993 machineScope MachineScope 994 want string 995 }{ 996 { 997 name: "returns empty if no failure domain is present", 998 machineScope: MachineScope{ 999 Machine: &clusterv1.Machine{ 1000 Spec: clusterv1.MachineSpec{}, 1001 }, 1002 AzureMachine: &infrav1.AzureMachine{ 1003 ObjectMeta: metav1.ObjectMeta{ 1004 Name: "machine-name", 1005 }, 1006 Spec: infrav1.AzureMachineSpec{}, 1007 }, 1008 }, 1009 want: "", 1010 }, 1011 { 1012 name: "returns failure domain from the machine spec", 1013 machineScope: MachineScope{ 1014 Machine: &clusterv1.Machine{ 1015 Spec: clusterv1.MachineSpec{ 1016 FailureDomain: ptr.To("dummy-failure-domain-from-machine-spec"), 1017 }, 1018 }, 1019 AzureMachine: &infrav1.AzureMachine{ 1020 ObjectMeta: metav1.ObjectMeta{ 1021 Name: "machine-name", 1022 }, 1023 Spec: infrav1.AzureMachineSpec{ 1024 FailureDomain: ptr.To("dummy-failure-domain-from-azuremachine-spec"), 1025 }, 1026 }, 1027 }, 1028 want: "dummy-failure-domain-from-machine-spec", 1029 }, 1030 { 1031 name: "returns failure domain from the azuremachine spec", 1032 machineScope: MachineScope{ 1033 Machine: &clusterv1.Machine{ 1034 Spec: clusterv1.MachineSpec{}, 1035 }, 1036 AzureMachine: &infrav1.AzureMachine{ 1037 ObjectMeta: metav1.ObjectMeta{ 1038 Name: "machine-name", 1039 }, 1040 Spec: infrav1.AzureMachineSpec{ 1041 FailureDomain: ptr.To("dummy-failure-domain-from-azuremachine-spec"), 1042 }, 1043 }, 1044 }, 1045 want: "dummy-failure-domain-from-azuremachine-spec", 1046 }, 1047 } 1048 for _, tt := range tests { 1049 t.Run(tt.name, func(t *testing.T) { 1050 if got := tt.machineScope.AvailabilityZone(); got != tt.want { 1051 t.Errorf("AvailabilityZone() = %v, want %v", got, tt.want) 1052 } 1053 }) 1054 } 1055 } 1056 1057 func TestMachineScope_Namespace(t *testing.T) { 1058 tests := []struct { 1059 name string 1060 machineScope MachineScope 1061 want string 1062 }{ 1063 { 1064 name: "returns azure machine namespace", 1065 machineScope: MachineScope{ 1066 AzureMachine: &infrav1.AzureMachine{ 1067 ObjectMeta: metav1.ObjectMeta{ 1068 Name: "machine-name", 1069 Namespace: "foo", 1070 }, 1071 }, 1072 }, 1073 want: "foo", 1074 }, 1075 { 1076 name: "returns azure machine namespace as empty if namespace is no specified", 1077 machineScope: MachineScope{ 1078 AzureMachine: &infrav1.AzureMachine{ 1079 ObjectMeta: metav1.ObjectMeta{ 1080 Name: "machine-name", 1081 }, 1082 }, 1083 }, 1084 want: "", 1085 }, 1086 } 1087 for _, tt := range tests { 1088 t.Run(tt.name, func(t *testing.T) { 1089 if got := tt.machineScope.Namespace(); got != tt.want { 1090 t.Errorf("Namespace() = %v, want %v", got, tt.want) 1091 } 1092 }) 1093 } 1094 } 1095 1096 func TestMachineScope_IsControlPlane(t *testing.T) { 1097 tests := []struct { 1098 name string 1099 machineScope MachineScope 1100 want bool 1101 }{ 1102 { 1103 name: "returns false when machine is not control plane", 1104 machineScope: MachineScope{ 1105 Machine: &clusterv1.Machine{}, 1106 AzureMachine: &infrav1.AzureMachine{ 1107 ObjectMeta: metav1.ObjectMeta{ 1108 Name: "machine-name", 1109 }, 1110 }, 1111 }, 1112 want: false, 1113 }, 1114 { 1115 name: "returns true when machine is control plane", 1116 machineScope: MachineScope{ 1117 Machine: &clusterv1.Machine{ 1118 ObjectMeta: metav1.ObjectMeta{ 1119 Labels: map[string]string{ 1120 clusterv1.MachineControlPlaneLabel: "", 1121 }, 1122 }, 1123 }, 1124 AzureMachine: &infrav1.AzureMachine{ 1125 ObjectMeta: metav1.ObjectMeta{ 1126 Name: "machine-name", 1127 }, 1128 }, 1129 }, 1130 want: true, 1131 }, 1132 } 1133 for _, tt := range tests { 1134 t.Run(tt.name, func(t *testing.T) { 1135 if got := tt.machineScope.IsControlPlane(); got != tt.want { 1136 t.Errorf("IsControlPlane() = %v, want %v", got, tt.want) 1137 } 1138 }) 1139 } 1140 } 1141 1142 func TestMachineScope_Role(t *testing.T) { 1143 tests := []struct { 1144 name string 1145 machineScope MachineScope 1146 want string 1147 }{ 1148 { 1149 name: "returns node when machine is worker", 1150 machineScope: MachineScope{ 1151 Machine: &clusterv1.Machine{}, 1152 AzureMachine: &infrav1.AzureMachine{ 1153 ObjectMeta: metav1.ObjectMeta{ 1154 Name: "machine-name", 1155 }, 1156 }, 1157 }, 1158 want: infrav1.Node, 1159 }, 1160 { 1161 name: "returns control-plane when machine is control plane", 1162 machineScope: MachineScope{ 1163 Machine: &clusterv1.Machine{ 1164 ObjectMeta: metav1.ObjectMeta{ 1165 Labels: map[string]string{ 1166 clusterv1.MachineControlPlaneLabel: "", 1167 }, 1168 }, 1169 }, 1170 AzureMachine: &infrav1.AzureMachine{ 1171 ObjectMeta: metav1.ObjectMeta{ 1172 Name: "machine-name", 1173 }, 1174 }, 1175 }, 1176 want: infrav1.ControlPlane, 1177 }, 1178 } 1179 for _, tt := range tests { 1180 t.Run(tt.name, func(t *testing.T) { 1181 if got := tt.machineScope.Role(); got != tt.want { 1182 t.Errorf("Role() = %v, want %v", got, tt.want) 1183 } 1184 }) 1185 } 1186 } 1187 1188 func TestMachineScope_AvailabilitySet(t *testing.T) { 1189 tests := []struct { 1190 name string 1191 machineScope MachineScope 1192 wantAvailabilitySetName string 1193 wantAvailabilitySetExistence bool 1194 }{ 1195 { 1196 name: "returns empty and false if availability set is not enabled", 1197 machineScope: MachineScope{ 1198 ClusterScoper: &ClusterScope{ 1199 Cluster: &clusterv1.Cluster{ 1200 ObjectMeta: metav1.ObjectMeta{ 1201 Name: "cluster", 1202 }, 1203 }, 1204 AzureCluster: &infrav1.AzureCluster{ 1205 Status: infrav1.AzureClusterStatus{ 1206 FailureDomains: clusterv1.FailureDomains{ 1207 "foo-failure-domain": clusterv1.FailureDomainSpec{}, 1208 }, 1209 }, 1210 }, 1211 }, 1212 Machine: &clusterv1.Machine{}, 1213 AzureMachine: &infrav1.AzureMachine{}, 1214 }, 1215 wantAvailabilitySetName: "", 1216 wantAvailabilitySetExistence: false, 1217 }, 1218 { 1219 name: "returns AvailabilitySet name and true if availability set is enabled and machine is control plane", 1220 machineScope: MachineScope{ 1221 1222 ClusterScoper: &ClusterScope{ 1223 Cluster: &clusterv1.Cluster{ 1224 ObjectMeta: metav1.ObjectMeta{ 1225 Name: "cluster", 1226 }, 1227 }, 1228 AzureCluster: &infrav1.AzureCluster{ 1229 Status: infrav1.AzureClusterStatus{}, 1230 }, 1231 }, 1232 Machine: &clusterv1.Machine{ 1233 ObjectMeta: metav1.ObjectMeta{ 1234 Labels: map[string]string{ 1235 clusterv1.MachineControlPlaneLabel: "", 1236 }, 1237 }, 1238 }, 1239 AzureMachine: &infrav1.AzureMachine{}, 1240 }, 1241 wantAvailabilitySetName: "cluster_control-plane-as", 1242 wantAvailabilitySetExistence: true, 1243 }, 1244 { 1245 name: "returns AvailabilitySet name and true if AvailabilitySet is enabled for worker machine which is part of machine deployment", 1246 machineScope: MachineScope{ 1247 1248 ClusterScoper: &ClusterScope{ 1249 Cluster: &clusterv1.Cluster{ 1250 ObjectMeta: metav1.ObjectMeta{ 1251 Name: "cluster", 1252 }, 1253 }, 1254 AzureCluster: &infrav1.AzureCluster{ 1255 Status: infrav1.AzureClusterStatus{}, 1256 }, 1257 }, 1258 Machine: &clusterv1.Machine{ 1259 ObjectMeta: metav1.ObjectMeta{ 1260 Labels: map[string]string{ 1261 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1262 }, 1263 }, 1264 }, 1265 AzureMachine: &infrav1.AzureMachine{}, 1266 }, 1267 wantAvailabilitySetName: "cluster_foo-machine-deployment-as", 1268 wantAvailabilitySetExistence: true, 1269 }, 1270 { 1271 name: "returns empty and false if machine is using spot instances", 1272 machineScope: MachineScope{ 1273 ClusterScoper: &ClusterScope{ 1274 Cluster: &clusterv1.Cluster{ 1275 ObjectMeta: metav1.ObjectMeta{ 1276 Name: "cluster", 1277 }, 1278 }, 1279 AzureCluster: &infrav1.AzureCluster{ 1280 Status: infrav1.AzureClusterStatus{}, 1281 }, 1282 }, 1283 Machine: &clusterv1.Machine{ 1284 ObjectMeta: metav1.ObjectMeta{ 1285 Labels: map[string]string{ 1286 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1287 }, 1288 }, 1289 }, 1290 AzureMachine: &infrav1.AzureMachine{ 1291 Spec: infrav1.AzureMachineSpec{ 1292 SpotVMOptions: &infrav1.SpotVMOptions{MaxPrice: resource.NewQuantity(-1, resource.DecimalSI)}, 1293 }, 1294 }, 1295 }, 1296 wantAvailabilitySetName: "", 1297 wantAvailabilitySetExistence: false, 1298 }, 1299 { 1300 name: "returns AvailabilitySet name and true if AvailabilitySet is enabled for worker machine which is part of machine set", 1301 machineScope: MachineScope{ 1302 1303 ClusterScoper: &ClusterScope{ 1304 Cluster: &clusterv1.Cluster{ 1305 ObjectMeta: metav1.ObjectMeta{ 1306 Name: "cluster", 1307 }, 1308 }, 1309 AzureCluster: &infrav1.AzureCluster{ 1310 Status: infrav1.AzureClusterStatus{}, 1311 }, 1312 }, 1313 Machine: &clusterv1.Machine{ 1314 ObjectMeta: metav1.ObjectMeta{ 1315 Labels: map[string]string{ 1316 clusterv1.MachineSetNameLabel: "foo-machine-set", 1317 }, 1318 }, 1319 }, 1320 AzureMachine: &infrav1.AzureMachine{}, 1321 }, 1322 wantAvailabilitySetName: "cluster_foo-machine-set-as", 1323 wantAvailabilitySetExistence: true, 1324 }, 1325 { 1326 name: "returns AvailabilitySet name and true if AvailabilitySet is enabled for worker machine and machine deployment name takes precedence over machine set name", 1327 machineScope: MachineScope{ 1328 1329 ClusterScoper: &ClusterScope{ 1330 Cluster: &clusterv1.Cluster{ 1331 ObjectMeta: metav1.ObjectMeta{ 1332 Name: "cluster", 1333 }, 1334 }, 1335 AzureCluster: &infrav1.AzureCluster{ 1336 Status: infrav1.AzureClusterStatus{}, 1337 }, 1338 }, 1339 Machine: &clusterv1.Machine{ 1340 ObjectMeta: metav1.ObjectMeta{ 1341 Labels: map[string]string{ 1342 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1343 clusterv1.MachineSetNameLabel: "foo-machine-set", 1344 }, 1345 }, 1346 }, 1347 AzureMachine: &infrav1.AzureMachine{}, 1348 }, 1349 wantAvailabilitySetName: "cluster_foo-machine-deployment-as", 1350 wantAvailabilitySetExistence: true, 1351 }, 1352 { 1353 name: "returns empty and false if AvailabilitySet is enabled but worker machine is not part of machine deployment or machine set", 1354 machineScope: MachineScope{ 1355 1356 ClusterScoper: &ClusterScope{ 1357 Cluster: &clusterv1.Cluster{ 1358 ObjectMeta: metav1.ObjectMeta{ 1359 Name: "cluster", 1360 }, 1361 }, 1362 AzureCluster: &infrav1.AzureCluster{ 1363 Status: infrav1.AzureClusterStatus{}, 1364 }, 1365 }, 1366 Machine: &clusterv1.Machine{ 1367 ObjectMeta: metav1.ObjectMeta{ 1368 Labels: map[string]string{}, 1369 }, 1370 }, 1371 AzureMachine: &infrav1.AzureMachine{}, 1372 }, 1373 wantAvailabilitySetName: "", 1374 wantAvailabilitySetExistence: false, 1375 }, 1376 } 1377 for _, tt := range tests { 1378 t.Run(tt.name, func(t *testing.T) { 1379 gotAvailabilitySetName, gotAvailabilitySetExistence := tt.machineScope.AvailabilitySet() 1380 if gotAvailabilitySetName != tt.wantAvailabilitySetName { 1381 t.Errorf("AvailabilitySet() gotAvailabilitySetName = %v, wantAvailabilitySetName %v", gotAvailabilitySetName, tt.wantAvailabilitySetName) 1382 } 1383 if gotAvailabilitySetExistence != tt.wantAvailabilitySetExistence { 1384 t.Errorf("AvailabilitySet() gotAvailabilitySetExistence = %v, wantAvailabilitySetExistence %v", gotAvailabilitySetExistence, tt.wantAvailabilitySetExistence) 1385 } 1386 }) 1387 } 1388 } 1389 1390 func TestMachineScope_VMState(t *testing.T) { 1391 tests := []struct { 1392 name string 1393 machineScope MachineScope 1394 want infrav1.ProvisioningState 1395 }{ 1396 { 1397 name: "returns the VMState if present in AzureMachine status", 1398 machineScope: MachineScope{ 1399 AzureMachine: &infrav1.AzureMachine{ 1400 ObjectMeta: metav1.ObjectMeta{ 1401 Name: "machine-name", 1402 }, 1403 Status: infrav1.AzureMachineStatus{ 1404 VMState: func() *infrav1.ProvisioningState { 1405 provisioningState := infrav1.Creating 1406 return &provisioningState 1407 }(), 1408 }, 1409 }, 1410 }, 1411 want: infrav1.Creating, 1412 }, 1413 { 1414 name: "returns empty if VMState is not present in AzureMachine status", 1415 machineScope: MachineScope{ 1416 AzureMachine: &infrav1.AzureMachine{ 1417 ObjectMeta: metav1.ObjectMeta{ 1418 Name: "machine-name", 1419 }, 1420 Status: infrav1.AzureMachineStatus{}, 1421 }, 1422 }, 1423 want: "", 1424 }, 1425 } 1426 for _, tt := range tests { 1427 t.Run(tt.name, func(t *testing.T) { 1428 if got := tt.machineScope.VMState(); got != tt.want { 1429 t.Errorf("VMState() = %v, want %v", got, tt.want) 1430 } 1431 }) 1432 } 1433 } 1434 1435 func TestMachineScope_GetVMImage(t *testing.T) { 1436 mockCtrl := gomock.NewController(t) 1437 defer mockCtrl.Finish() 1438 1439 clusterMock := mock_azure.NewMockClusterScoper(mockCtrl) 1440 clusterMock.EXPECT().Location().AnyTimes() 1441 clusterMock.EXPECT().SubscriptionID().AnyTimes() 1442 clusterMock.EXPECT().CloudEnvironment().AnyTimes() 1443 clusterMock.EXPECT().Token().Return(&azidentity.DefaultAzureCredential{}).AnyTimes() 1444 svc := virtualmachineimages.Service{Client: mock_virtualmachineimages.NewMockClient(mockCtrl)} 1445 1446 tests := []struct { 1447 name string 1448 machineScope MachineScope 1449 want *infrav1.Image 1450 expectedErr string 1451 }{ 1452 { 1453 name: "returns AzureMachine image is found if present in the AzureMachine spec", 1454 machineScope: MachineScope{ 1455 AzureMachine: &infrav1.AzureMachine{ 1456 ObjectMeta: metav1.ObjectMeta{ 1457 Name: "machine-name", 1458 }, 1459 Spec: infrav1.AzureMachineSpec{ 1460 Image: &infrav1.Image{ 1461 ID: ptr.To("1"), 1462 }, 1463 }, 1464 }, 1465 }, 1466 want: &infrav1.Image{ 1467 ID: ptr.To("1"), 1468 }, 1469 expectedErr: "", 1470 }, 1471 { 1472 name: "if no image is specified and os specified is windows with version below 1.22, returns windows dockershim image", 1473 machineScope: MachineScope{ 1474 Machine: &clusterv1.Machine{ 1475 ObjectMeta: metav1.ObjectMeta{ 1476 Name: "machine-name", 1477 }, 1478 Spec: clusterv1.MachineSpec{ 1479 Version: ptr.To("1.20.1"), 1480 }, 1481 }, 1482 AzureMachine: &infrav1.AzureMachine{ 1483 ObjectMeta: metav1.ObjectMeta{ 1484 Name: "machine-name", 1485 }, 1486 Spec: infrav1.AzureMachineSpec{ 1487 OSDisk: infrav1.OSDisk{ 1488 OSType: azure.WindowsOS, 1489 }, 1490 }, 1491 }, 1492 ClusterScoper: clusterMock, 1493 }, 1494 want: func() *infrav1.Image { 1495 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.20.1", "dockershim", "") 1496 return image 1497 }(), 1498 expectedErr: "", 1499 }, 1500 { 1501 name: "if no image is specified and os specified is windows with version is 1.22+ with no annotation, returns windows containerd image", 1502 machineScope: MachineScope{ 1503 Machine: &clusterv1.Machine{ 1504 ObjectMeta: metav1.ObjectMeta{ 1505 Name: "machine-name", 1506 }, 1507 Spec: clusterv1.MachineSpec{ 1508 Version: ptr.To("1.22.1"), 1509 }, 1510 }, 1511 AzureMachine: &infrav1.AzureMachine{ 1512 ObjectMeta: metav1.ObjectMeta{ 1513 Name: "machine-name", 1514 }, 1515 Spec: infrav1.AzureMachineSpec{ 1516 OSDisk: infrav1.OSDisk{ 1517 OSType: azure.WindowsOS, 1518 }, 1519 }, 1520 }, 1521 ClusterScoper: clusterMock, 1522 }, 1523 want: func() *infrav1.Image { 1524 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.22.1", "containerd", "") 1525 return image 1526 }(), 1527 expectedErr: "", 1528 }, 1529 { 1530 name: "if no image is specified and os specified is windows with version is 1.22+ with annotation dockershim, returns windows dockershim image", 1531 machineScope: MachineScope{ 1532 Machine: &clusterv1.Machine{ 1533 ObjectMeta: metav1.ObjectMeta{ 1534 Name: "machine-name", 1535 }, 1536 Spec: clusterv1.MachineSpec{ 1537 Version: ptr.To("1.22.1"), 1538 }, 1539 }, 1540 AzureMachine: &infrav1.AzureMachine{ 1541 ObjectMeta: metav1.ObjectMeta{ 1542 Name: "machine-name", 1543 Annotations: map[string]string{ 1544 "runtime": "dockershim", 1545 }, 1546 }, 1547 Spec: infrav1.AzureMachineSpec{ 1548 OSDisk: infrav1.OSDisk{ 1549 OSType: azure.WindowsOS, 1550 }, 1551 }, 1552 }, 1553 ClusterScoper: clusterMock, 1554 }, 1555 want: func() *infrav1.Image { 1556 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.22.1", "dockershim", "") 1557 return image 1558 }(), 1559 expectedErr: "", 1560 }, 1561 { 1562 name: "if no image is specified and os specified is windows with version is less and 1.22 with annotation dockershim, returns windows dockershim image", 1563 machineScope: MachineScope{ 1564 Machine: &clusterv1.Machine{ 1565 ObjectMeta: metav1.ObjectMeta{ 1566 Name: "machine-name", 1567 }, 1568 Spec: clusterv1.MachineSpec{ 1569 Version: ptr.To("1.21.1"), 1570 }, 1571 }, 1572 AzureMachine: &infrav1.AzureMachine{ 1573 ObjectMeta: metav1.ObjectMeta{ 1574 Name: "machine-name", 1575 Annotations: map[string]string{ 1576 "runtime": "dockershim", 1577 }, 1578 }, 1579 Spec: infrav1.AzureMachineSpec{ 1580 OSDisk: infrav1.OSDisk{ 1581 OSType: azure.WindowsOS, 1582 }, 1583 }, 1584 }, 1585 ClusterScoper: clusterMock, 1586 }, 1587 want: func() *infrav1.Image { 1588 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.21.1", "dockershim", "") 1589 return image 1590 }(), 1591 expectedErr: "", 1592 }, 1593 { 1594 name: "if no image is specified and os specified is windows with version is less and 1.22 with annotation containerd, returns error", 1595 machineScope: MachineScope{ 1596 Machine: &clusterv1.Machine{ 1597 ObjectMeta: metav1.ObjectMeta{ 1598 Name: "machine-name", 1599 }, 1600 Spec: clusterv1.MachineSpec{ 1601 Version: ptr.To("1.21.1"), 1602 }, 1603 }, 1604 AzureMachine: &infrav1.AzureMachine{ 1605 ObjectMeta: metav1.ObjectMeta{ 1606 Name: "machine-name", 1607 Annotations: map[string]string{ 1608 "runtime": "containerd", 1609 }, 1610 }, 1611 Spec: infrav1.AzureMachineSpec{ 1612 OSDisk: infrav1.OSDisk{ 1613 OSType: azure.WindowsOS, 1614 }, 1615 }, 1616 }, 1617 ClusterScoper: clusterMock, 1618 }, 1619 want: nil, 1620 expectedErr: "containerd image only supported in 1.22+", 1621 }, 1622 { 1623 name: "if no image is specified and os specified is windows with windowsServerVersion annotation set to 2019, retrurns 2019 image", 1624 machineScope: MachineScope{ 1625 Machine: &clusterv1.Machine{ 1626 ObjectMeta: metav1.ObjectMeta{ 1627 Name: "machine-name", 1628 }, 1629 Spec: clusterv1.MachineSpec{ 1630 Version: ptr.To("1.23.3"), 1631 }, 1632 }, 1633 AzureMachine: &infrav1.AzureMachine{ 1634 ObjectMeta: metav1.ObjectMeta{ 1635 Name: "machine-name", 1636 Annotations: map[string]string{ 1637 "windowsServerVersion": "windows-2019", 1638 }, 1639 }, 1640 Spec: infrav1.AzureMachineSpec{ 1641 OSDisk: infrav1.OSDisk{ 1642 OSType: azure.WindowsOS, 1643 }, 1644 }, 1645 }, 1646 ClusterScoper: clusterMock, 1647 }, 1648 want: func() *infrav1.Image { 1649 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.23.3", "", "windows-2019") 1650 return image 1651 }(), 1652 expectedErr: "", 1653 }, 1654 { 1655 name: "if no image is specified and os specified is windows with windowsServerVersion annotation set to 2022, retrurns 2022 image", 1656 machineScope: MachineScope{ 1657 Machine: &clusterv1.Machine{ 1658 ObjectMeta: metav1.ObjectMeta{ 1659 Name: "machine-name", 1660 }, 1661 Spec: clusterv1.MachineSpec{ 1662 Version: ptr.To("1.23.3"), 1663 }, 1664 }, 1665 AzureMachine: &infrav1.AzureMachine{ 1666 ObjectMeta: metav1.ObjectMeta{ 1667 Name: "machine-name", 1668 Annotations: map[string]string{ 1669 "windowsServerVersion": "windows-2022", 1670 }, 1671 }, 1672 Spec: infrav1.AzureMachineSpec{ 1673 OSDisk: infrav1.OSDisk{ 1674 OSType: azure.WindowsOS, 1675 }, 1676 }, 1677 }, 1678 ClusterScoper: clusterMock, 1679 }, 1680 want: func() *infrav1.Image { 1681 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.23.3", "", "windows-2022") 1682 return image 1683 }(), 1684 expectedErr: "", 1685 }, 1686 { 1687 name: "if no image and OS is specified, returns linux image", 1688 machineScope: MachineScope{ 1689 Machine: &clusterv1.Machine{ 1690 ObjectMeta: metav1.ObjectMeta{ 1691 Name: "machine-name", 1692 }, 1693 Spec: clusterv1.MachineSpec{ 1694 Version: ptr.To("1.20.1"), 1695 }, 1696 }, 1697 AzureMachine: &infrav1.AzureMachine{ 1698 ObjectMeta: metav1.ObjectMeta{ 1699 Name: "machine-name", 1700 }, 1701 }, 1702 ClusterScoper: clusterMock, 1703 }, 1704 want: func() *infrav1.Image { 1705 image, _ := svc.GetDefaultUbuntuImage(context.TODO(), "", "1.20.1") 1706 return image 1707 }(), 1708 expectedErr: "", 1709 }, 1710 } 1711 for _, tt := range tests { 1712 t.Run(tt.name, func(t *testing.T) { 1713 gotImage, err := tt.machineScope.GetVMImage(context.TODO()) 1714 if (err == nil && tt.expectedErr != "") || (err != nil && tt.expectedErr != err.Error()) { 1715 t.Errorf("expected error %v, got %v", tt.expectedErr, err) 1716 } 1717 if !reflect.DeepEqual(gotImage, tt.want) { 1718 t.Errorf("GetVMImage(), gotImage = %v, wantImage %v", gotImage, tt.want) 1719 } 1720 }) 1721 } 1722 } 1723 1724 func TestMachineScope_NICSpecs(t *testing.T) { 1725 tests := []struct { 1726 name string 1727 machineScope MachineScope 1728 want []azure.ResourceSpecGetter 1729 }{ 1730 { 1731 name: "Node Machine with no NAT gateway and no public IP address", 1732 machineScope: MachineScope{ 1733 ClusterScoper: &ClusterScope{ 1734 AzureClients: AzureClients{ 1735 EnvironmentSettings: auth.EnvironmentSettings{ 1736 Values: map[string]string{ 1737 auth.SubscriptionID: "123", 1738 }, 1739 }, 1740 }, 1741 Cluster: &clusterv1.Cluster{ 1742 ObjectMeta: metav1.ObjectMeta{ 1743 Name: "cluster", 1744 Namespace: "default", 1745 }, 1746 }, 1747 AzureCluster: &infrav1.AzureCluster{ 1748 ObjectMeta: metav1.ObjectMeta{ 1749 Name: "cluster", 1750 Namespace: "default", 1751 OwnerReferences: []metav1.OwnerReference{ 1752 { 1753 APIVersion: "cluster.x-k8s.io/v1beta1", 1754 Kind: "Cluster", 1755 Name: "cluster", 1756 }, 1757 }, 1758 }, 1759 Spec: infrav1.AzureClusterSpec{ 1760 ResourceGroup: "my-rg", 1761 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 1762 Location: "westus", 1763 }, 1764 NetworkSpec: infrav1.NetworkSpec{ 1765 Vnet: infrav1.VnetSpec{ 1766 Name: "vnet1", 1767 ResourceGroup: "rg1", 1768 }, 1769 Subnets: []infrav1.SubnetSpec{ 1770 { 1771 SubnetClassSpec: infrav1.SubnetClassSpec{ 1772 Role: infrav1.SubnetNode, 1773 Name: "subnet1", 1774 }, 1775 }, 1776 }, 1777 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 1778 Name: "outbound-lb", 1779 BackendPool: infrav1.BackendPool{ 1780 Name: "outbound-lb-outboundBackendPool", 1781 }, 1782 }, 1783 }, 1784 }, 1785 }, 1786 }, 1787 AzureMachine: &infrav1.AzureMachine{ 1788 ObjectMeta: metav1.ObjectMeta{ 1789 Name: "machine", 1790 }, 1791 Spec: infrav1.AzureMachineSpec{ 1792 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 1793 NetworkInterfaces: []infrav1.NetworkInterface{{ 1794 SubnetName: "subnet1", 1795 PrivateIPConfigs: 1, 1796 }}, 1797 }, 1798 }, 1799 Machine: &clusterv1.Machine{ 1800 ObjectMeta: metav1.ObjectMeta{ 1801 Name: "machine", 1802 Labels: map[string]string{ 1803 // clusterv1.MachineControlPlaneLabel: "true", 1804 }, 1805 }, 1806 }, 1807 }, 1808 want: []azure.ResourceSpecGetter{ 1809 &networkinterfaces.NICSpec{ 1810 Name: "machine-name-nic", 1811 ResourceGroup: "my-rg", 1812 Location: "westus", 1813 SubscriptionID: "123", 1814 MachineName: "machine-name", 1815 SubnetName: "subnet1", 1816 IPConfigs: []networkinterfaces.IPConfig{{}}, 1817 VNetName: "vnet1", 1818 VNetResourceGroup: "rg1", 1819 PublicLBName: "outbound-lb", 1820 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 1821 PublicLBNATRuleName: "", 1822 InternalLBName: "", 1823 InternalLBAddressPoolName: "", 1824 PublicIPName: "", 1825 AcceleratedNetworking: nil, 1826 DNSServers: nil, 1827 IPv6Enabled: false, 1828 EnableIPForwarding: false, 1829 SKU: nil, 1830 ClusterName: "cluster", 1831 AdditionalTags: infrav1.Tags{ 1832 "kubernetes.io_cluster_cluster": "owned", 1833 }, 1834 }, 1835 }, 1836 }, 1837 { 1838 name: "Node Machine with no NAT gateway and no public IP address and SKU is in machine cache", 1839 machineScope: MachineScope{ 1840 ClusterScoper: &ClusterScope{ 1841 AzureClients: AzureClients{ 1842 EnvironmentSettings: auth.EnvironmentSettings{ 1843 Values: map[string]string{ 1844 auth.SubscriptionID: "123", 1845 }, 1846 }, 1847 }, 1848 Cluster: &clusterv1.Cluster{ 1849 ObjectMeta: metav1.ObjectMeta{ 1850 Name: "cluster", 1851 Namespace: "default", 1852 }, 1853 }, 1854 AzureCluster: &infrav1.AzureCluster{ 1855 ObjectMeta: metav1.ObjectMeta{ 1856 Name: "cluster", 1857 Namespace: "default", 1858 OwnerReferences: []metav1.OwnerReference{ 1859 { 1860 APIVersion: "cluster.x-k8s.io/v1beta1", 1861 Kind: "Cluster", 1862 Name: "cluster", 1863 }, 1864 }, 1865 }, 1866 Spec: infrav1.AzureClusterSpec{ 1867 ResourceGroup: "my-rg", 1868 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 1869 Location: "westus", 1870 }, 1871 NetworkSpec: infrav1.NetworkSpec{ 1872 Vnet: infrav1.VnetSpec{ 1873 Name: "vnet1", 1874 ResourceGroup: "rg1", 1875 }, 1876 Subnets: []infrav1.SubnetSpec{ 1877 { 1878 SubnetClassSpec: infrav1.SubnetClassSpec{ 1879 Role: infrav1.SubnetNode, 1880 Name: "subnet1", 1881 }, 1882 }, 1883 }, 1884 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 1885 Name: "outbound-lb", 1886 BackendPool: infrav1.BackendPool{ 1887 Name: "outbound-lb-outboundBackendPool", 1888 }, 1889 }, 1890 }, 1891 }, 1892 }, 1893 }, 1894 AzureMachine: &infrav1.AzureMachine{ 1895 ObjectMeta: metav1.ObjectMeta{ 1896 Name: "machine", 1897 }, 1898 Spec: infrav1.AzureMachineSpec{ 1899 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 1900 NetworkInterfaces: []infrav1.NetworkInterface{{ 1901 SubnetName: "subnet1", 1902 PrivateIPConfigs: 1, 1903 }}, 1904 }, 1905 }, 1906 Machine: &clusterv1.Machine{ 1907 ObjectMeta: metav1.ObjectMeta{ 1908 Name: "machine", 1909 Labels: map[string]string{ 1910 // clusterv1.MachineControlPlaneLabel: "true", 1911 }, 1912 }, 1913 }, 1914 cache: &MachineCache{ 1915 VMSKU: resourceskus.SKU{ 1916 Name: ptr.To("Standard_D2v2"), 1917 }, 1918 }, 1919 }, 1920 want: []azure.ResourceSpecGetter{ 1921 &networkinterfaces.NICSpec{ 1922 Name: "machine-name-nic", 1923 ResourceGroup: "my-rg", 1924 Location: "westus", 1925 SubscriptionID: "123", 1926 MachineName: "machine-name", 1927 SubnetName: "subnet1", 1928 IPConfigs: []networkinterfaces.IPConfig{{}}, 1929 VNetName: "vnet1", 1930 VNetResourceGroup: "rg1", 1931 PublicLBName: "outbound-lb", 1932 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 1933 PublicLBNATRuleName: "", 1934 InternalLBName: "", 1935 InternalLBAddressPoolName: "", 1936 PublicIPName: "", 1937 AcceleratedNetworking: nil, 1938 DNSServers: nil, 1939 IPv6Enabled: false, 1940 EnableIPForwarding: false, 1941 SKU: &resourceskus.SKU{ 1942 Name: ptr.To("Standard_D2v2"), 1943 }, 1944 ClusterName: "cluster", 1945 AdditionalTags: infrav1.Tags{ 1946 "kubernetes.io_cluster_cluster": "owned", 1947 }, 1948 }, 1949 }, 1950 }, 1951 { 1952 name: "Node Machine with NAT gateway", 1953 machineScope: MachineScope{ 1954 ClusterScoper: &ClusterScope{ 1955 AzureClients: AzureClients{ 1956 EnvironmentSettings: auth.EnvironmentSettings{ 1957 Values: map[string]string{ 1958 auth.SubscriptionID: "123", 1959 }, 1960 }, 1961 }, 1962 Cluster: &clusterv1.Cluster{ 1963 ObjectMeta: metav1.ObjectMeta{ 1964 Name: "cluster", 1965 Namespace: "default", 1966 }, 1967 }, 1968 AzureCluster: &infrav1.AzureCluster{ 1969 ObjectMeta: metav1.ObjectMeta{ 1970 Name: "cluster", 1971 Namespace: "default", 1972 OwnerReferences: []metav1.OwnerReference{ 1973 { 1974 APIVersion: "cluster.x-k8s.io/v1beta1", 1975 Kind: "Cluster", 1976 Name: "cluster", 1977 }, 1978 }, 1979 }, 1980 Spec: infrav1.AzureClusterSpec{ 1981 ResourceGroup: "my-rg", 1982 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 1983 Location: "westus", 1984 }, 1985 NetworkSpec: infrav1.NetworkSpec{ 1986 Vnet: infrav1.VnetSpec{ 1987 Name: "vnet1", 1988 ResourceGroup: "rg1", 1989 }, 1990 Subnets: []infrav1.SubnetSpec{ 1991 { 1992 SubnetClassSpec: infrav1.SubnetClassSpec{ 1993 Role: infrav1.SubnetNode, 1994 Name: "subnet1", 1995 }, 1996 NatGateway: infrav1.NatGateway{ 1997 NatGatewayClassSpec: infrav1.NatGatewayClassSpec{ 1998 Name: "natgw", 1999 }, 2000 }, 2001 }, 2002 }, 2003 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2004 Name: "outbound-lb", 2005 }, 2006 }, 2007 }, 2008 }, 2009 }, 2010 AzureMachine: &infrav1.AzureMachine{ 2011 ObjectMeta: metav1.ObjectMeta{ 2012 Name: "machine", 2013 }, 2014 Spec: infrav1.AzureMachineSpec{ 2015 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2016 NetworkInterfaces: []infrav1.NetworkInterface{{ 2017 SubnetName: "subnet1", 2018 PrivateIPConfigs: 1, 2019 }}, 2020 }, 2021 }, 2022 Machine: &clusterv1.Machine{ 2023 ObjectMeta: metav1.ObjectMeta{ 2024 Name: "machine", 2025 Labels: map[string]string{ 2026 // clusterv1.MachineControlPlaneLabel: "true", 2027 }, 2028 }, 2029 }, 2030 }, 2031 want: []azure.ResourceSpecGetter{ 2032 &networkinterfaces.NICSpec{ 2033 Name: "machine-name-nic", 2034 ResourceGroup: "my-rg", 2035 Location: "westus", 2036 SubscriptionID: "123", 2037 MachineName: "machine-name", 2038 SubnetName: "subnet1", 2039 IPConfigs: []networkinterfaces.IPConfig{{}}, 2040 VNetName: "vnet1", 2041 VNetResourceGroup: "rg1", 2042 PublicLBName: "", 2043 PublicLBAddressPoolName: "", 2044 PublicLBNATRuleName: "", 2045 InternalLBName: "", 2046 InternalLBAddressPoolName: "", 2047 PublicIPName: "", 2048 AcceleratedNetworking: nil, 2049 DNSServers: nil, 2050 IPv6Enabled: false, 2051 EnableIPForwarding: false, 2052 SKU: nil, 2053 ClusterName: "cluster", 2054 AdditionalTags: infrav1.Tags{ 2055 "kubernetes.io_cluster_cluster": "owned", 2056 }, 2057 }, 2058 }, 2059 }, 2060 { 2061 name: "Node Machine with public IP address", 2062 machineScope: MachineScope{ 2063 ClusterScoper: &ClusterScope{ 2064 AzureClients: AzureClients{ 2065 EnvironmentSettings: auth.EnvironmentSettings{ 2066 Values: map[string]string{ 2067 auth.SubscriptionID: "123", 2068 }, 2069 }, 2070 }, 2071 Cluster: &clusterv1.Cluster{ 2072 ObjectMeta: metav1.ObjectMeta{ 2073 Name: "cluster", 2074 Namespace: "default", 2075 }, 2076 }, 2077 AzureCluster: &infrav1.AzureCluster{ 2078 ObjectMeta: metav1.ObjectMeta{ 2079 Name: "cluster", 2080 Namespace: "default", 2081 OwnerReferences: []metav1.OwnerReference{ 2082 { 2083 APIVersion: "cluster.x-k8s.io/v1beta1", 2084 Kind: "Cluster", 2085 Name: "cluster", 2086 }, 2087 }, 2088 }, 2089 Spec: infrav1.AzureClusterSpec{ 2090 ResourceGroup: "my-rg", 2091 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2092 Location: "westus", 2093 }, 2094 NetworkSpec: infrav1.NetworkSpec{ 2095 Vnet: infrav1.VnetSpec{ 2096 Name: "vnet1", 2097 ResourceGroup: "rg1", 2098 }, 2099 Subnets: []infrav1.SubnetSpec{ 2100 { 2101 SubnetClassSpec: infrav1.SubnetClassSpec{ 2102 Role: infrav1.SubnetNode, 2103 Name: "subnet1", 2104 }, 2105 }, 2106 }, 2107 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2108 Name: "outbound-lb", 2109 }, 2110 }, 2111 }, 2112 }, 2113 }, 2114 AzureMachine: &infrav1.AzureMachine{ 2115 ObjectMeta: metav1.ObjectMeta{ 2116 Name: "machine", 2117 }, 2118 Spec: infrav1.AzureMachineSpec{ 2119 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2120 NetworkInterfaces: []infrav1.NetworkInterface{{ 2121 SubnetName: "subnet1", 2122 PrivateIPConfigs: 1, 2123 }}, 2124 AllocatePublicIP: true, 2125 }, 2126 }, 2127 Machine: &clusterv1.Machine{ 2128 ObjectMeta: metav1.ObjectMeta{ 2129 Name: "machine", 2130 Labels: map[string]string{ 2131 // clusterv1.MachineControlPlaneLabel: "true", 2132 }, 2133 }, 2134 }, 2135 }, 2136 want: []azure.ResourceSpecGetter{ 2137 &networkinterfaces.NICSpec{ 2138 Name: "machine-name-nic", 2139 ResourceGroup: "my-rg", 2140 Location: "westus", 2141 SubscriptionID: "123", 2142 MachineName: "machine-name", 2143 SubnetName: "subnet1", 2144 IPConfigs: []networkinterfaces.IPConfig{{}}, 2145 VNetName: "vnet1", 2146 VNetResourceGroup: "rg1", 2147 PublicLBName: "", 2148 PublicLBAddressPoolName: "", 2149 PublicLBNATRuleName: "", 2150 InternalLBName: "", 2151 InternalLBAddressPoolName: "", 2152 PublicIPName: "pip-machine-name", 2153 AcceleratedNetworking: nil, 2154 DNSServers: nil, 2155 IPv6Enabled: false, 2156 EnableIPForwarding: false, 2157 SKU: nil, 2158 ClusterName: "cluster", 2159 AdditionalTags: infrav1.Tags{ 2160 "kubernetes.io_cluster_cluster": "owned", 2161 }, 2162 }, 2163 }, 2164 }, 2165 { 2166 name: "Control Plane Machine with private LB", 2167 machineScope: MachineScope{ 2168 ClusterScoper: &ClusterScope{ 2169 AzureClients: AzureClients{ 2170 EnvironmentSettings: auth.EnvironmentSettings{ 2171 Values: map[string]string{ 2172 auth.SubscriptionID: "123", 2173 }, 2174 }, 2175 }, 2176 Cluster: &clusterv1.Cluster{ 2177 ObjectMeta: metav1.ObjectMeta{ 2178 Name: "cluster", 2179 Namespace: "default", 2180 }, 2181 }, 2182 AzureCluster: &infrav1.AzureCluster{ 2183 ObjectMeta: metav1.ObjectMeta{ 2184 Name: "cluster", 2185 Namespace: "default", 2186 OwnerReferences: []metav1.OwnerReference{ 2187 { 2188 APIVersion: "cluster.x-k8s.io/v1beta1", 2189 Kind: "Cluster", 2190 Name: "cluster", 2191 }, 2192 }, 2193 }, 2194 Spec: infrav1.AzureClusterSpec{ 2195 ResourceGroup: "my-rg", 2196 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2197 Location: "westus", 2198 }, 2199 NetworkSpec: infrav1.NetworkSpec{ 2200 Vnet: infrav1.VnetSpec{ 2201 Name: "vnet1", 2202 ResourceGroup: "rg1", 2203 }, 2204 Subnets: []infrav1.SubnetSpec{ 2205 { 2206 SubnetClassSpec: infrav1.SubnetClassSpec{ 2207 Role: infrav1.SubnetNode, 2208 Name: "subnet1", 2209 }, 2210 }, 2211 }, 2212 APIServerLB: infrav1.LoadBalancerSpec{ 2213 Name: "api-lb", 2214 LoadBalancerClassSpec: infrav1.LoadBalancerClassSpec{ 2215 Type: infrav1.Internal, 2216 }, 2217 BackendPool: infrav1.BackendPool{ 2218 Name: "api-lb-backendPool", 2219 }, 2220 }, 2221 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2222 Name: "outbound-lb", 2223 }, 2224 }, 2225 }, 2226 }, 2227 }, 2228 AzureMachine: &infrav1.AzureMachine{ 2229 ObjectMeta: metav1.ObjectMeta{ 2230 Name: "machine", 2231 }, 2232 Spec: infrav1.AzureMachineSpec{ 2233 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2234 NetworkInterfaces: []infrav1.NetworkInterface{{ 2235 SubnetName: "subnet1", 2236 PrivateIPConfigs: 1, 2237 }}, 2238 }, 2239 }, 2240 Machine: &clusterv1.Machine{ 2241 ObjectMeta: metav1.ObjectMeta{ 2242 Name: "machine", 2243 Labels: map[string]string{ 2244 clusterv1.MachineControlPlaneLabel: "true", 2245 }, 2246 }, 2247 }, 2248 }, 2249 want: []azure.ResourceSpecGetter{ 2250 &networkinterfaces.NICSpec{ 2251 Name: "machine-name-nic", 2252 ResourceGroup: "my-rg", 2253 Location: "westus", 2254 SubscriptionID: "123", 2255 MachineName: "machine-name", 2256 SubnetName: "subnet1", 2257 IPConfigs: []networkinterfaces.IPConfig{{}}, 2258 VNetName: "vnet1", 2259 VNetResourceGroup: "rg1", 2260 PublicLBName: "", 2261 PublicLBAddressPoolName: "", 2262 PublicLBNATRuleName: "", 2263 InternalLBName: "api-lb", 2264 InternalLBAddressPoolName: "api-lb-backendPool", 2265 PublicIPName: "", 2266 AcceleratedNetworking: nil, 2267 DNSServers: nil, 2268 IPv6Enabled: false, 2269 EnableIPForwarding: false, 2270 SKU: nil, 2271 ClusterName: "cluster", 2272 AdditionalTags: infrav1.Tags{ 2273 "kubernetes.io_cluster_cluster": "owned", 2274 }, 2275 }, 2276 }, 2277 }, 2278 { 2279 name: "Control Plane Machine with public LB", 2280 machineScope: MachineScope{ 2281 ClusterScoper: &ClusterScope{ 2282 AzureClients: AzureClients{ 2283 EnvironmentSettings: auth.EnvironmentSettings{ 2284 Values: map[string]string{ 2285 auth.SubscriptionID: "123", 2286 }, 2287 }, 2288 }, 2289 Cluster: &clusterv1.Cluster{ 2290 ObjectMeta: metav1.ObjectMeta{ 2291 Name: "cluster", 2292 Namespace: "default", 2293 }, 2294 }, 2295 AzureCluster: &infrav1.AzureCluster{ 2296 ObjectMeta: metav1.ObjectMeta{ 2297 Name: "cluster", 2298 Namespace: "default", 2299 OwnerReferences: []metav1.OwnerReference{ 2300 { 2301 APIVersion: "cluster.x-k8s.io/v1beta1", 2302 Kind: "Cluster", 2303 Name: "cluster", 2304 }, 2305 }, 2306 }, 2307 Spec: infrav1.AzureClusterSpec{ 2308 ResourceGroup: "my-rg", 2309 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2310 Location: "westus", 2311 }, 2312 NetworkSpec: infrav1.NetworkSpec{ 2313 Vnet: infrav1.VnetSpec{ 2314 Name: "vnet1", 2315 ResourceGroup: "rg1", 2316 }, 2317 Subnets: []infrav1.SubnetSpec{ 2318 { 2319 SubnetClassSpec: infrav1.SubnetClassSpec{ 2320 Role: infrav1.SubnetNode, 2321 Name: "subnet1", 2322 }, 2323 }, 2324 }, 2325 APIServerLB: infrav1.LoadBalancerSpec{ 2326 Name: "api-lb", 2327 BackendPool: infrav1.BackendPool{ 2328 Name: "api-lb-backendPool", 2329 }, 2330 }, 2331 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2332 Name: "outbound-lb", 2333 }, 2334 }, 2335 }, 2336 }, 2337 }, 2338 AzureMachine: &infrav1.AzureMachine{ 2339 ObjectMeta: metav1.ObjectMeta{ 2340 Name: "machine", 2341 }, 2342 Spec: infrav1.AzureMachineSpec{ 2343 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2344 NetworkInterfaces: []infrav1.NetworkInterface{{ 2345 SubnetName: "subnet1", 2346 PrivateIPConfigs: 1, 2347 }}, 2348 }, 2349 }, 2350 Machine: &clusterv1.Machine{ 2351 ObjectMeta: metav1.ObjectMeta{ 2352 Name: "machine", 2353 Labels: map[string]string{ 2354 clusterv1.MachineControlPlaneLabel: "true", 2355 }, 2356 }, 2357 }, 2358 }, 2359 want: []azure.ResourceSpecGetter{ 2360 &networkinterfaces.NICSpec{ 2361 Name: "machine-name-nic", 2362 ResourceGroup: "my-rg", 2363 Location: "westus", 2364 SubscriptionID: "123", 2365 MachineName: "machine-name", 2366 SubnetName: "subnet1", 2367 IPConfigs: []networkinterfaces.IPConfig{{}}, 2368 VNetName: "vnet1", 2369 VNetResourceGroup: "rg1", 2370 PublicLBName: "api-lb", 2371 PublicLBAddressPoolName: "api-lb-backendPool", 2372 PublicLBNATRuleName: "machine-name", 2373 InternalLBName: "", 2374 InternalLBAddressPoolName: "", 2375 PublicIPName: "", 2376 AcceleratedNetworking: nil, 2377 DNSServers: nil, 2378 IPv6Enabled: false, 2379 EnableIPForwarding: false, 2380 SKU: nil, 2381 ClusterName: "cluster", 2382 AdditionalTags: infrav1.Tags{ 2383 "kubernetes.io_cluster_cluster": "owned", 2384 }, 2385 }, 2386 }, 2387 }, 2388 { 2389 name: "Control Plane Machine with public LB and Custom DNS Servers", 2390 machineScope: MachineScope{ 2391 ClusterScoper: &ClusterScope{ 2392 AzureClients: AzureClients{ 2393 EnvironmentSettings: auth.EnvironmentSettings{ 2394 Values: map[string]string{ 2395 auth.SubscriptionID: "123", 2396 }, 2397 }, 2398 }, 2399 Cluster: &clusterv1.Cluster{ 2400 ObjectMeta: metav1.ObjectMeta{ 2401 Name: "cluster", 2402 Namespace: "default", 2403 }, 2404 }, 2405 AzureCluster: &infrav1.AzureCluster{ 2406 ObjectMeta: metav1.ObjectMeta{ 2407 Name: "cluster", 2408 Namespace: "default", 2409 OwnerReferences: []metav1.OwnerReference{ 2410 { 2411 APIVersion: "cluster.x-k8s.io/v1beta1", 2412 Kind: "Cluster", 2413 Name: "cluster", 2414 }, 2415 }, 2416 }, 2417 Spec: infrav1.AzureClusterSpec{ 2418 ResourceGroup: "my-rg", 2419 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2420 Location: "westus", 2421 }, 2422 NetworkSpec: infrav1.NetworkSpec{ 2423 Vnet: infrav1.VnetSpec{ 2424 Name: "vnet1", 2425 ResourceGroup: "rg1", 2426 }, 2427 Subnets: []infrav1.SubnetSpec{ 2428 { 2429 SubnetClassSpec: infrav1.SubnetClassSpec{ 2430 Role: infrav1.SubnetNode, 2431 Name: "subnet1", 2432 }, 2433 }, 2434 }, 2435 APIServerLB: infrav1.LoadBalancerSpec{ 2436 Name: "api-lb", 2437 BackendPool: infrav1.BackendPool{ 2438 Name: "api-lb-backendPool", 2439 }, 2440 }, 2441 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2442 Name: "outbound-lb", 2443 }, 2444 }, 2445 }, 2446 }, 2447 }, 2448 AzureMachine: &infrav1.AzureMachine{ 2449 ObjectMeta: metav1.ObjectMeta{ 2450 Name: "machine", 2451 }, 2452 Spec: infrav1.AzureMachineSpec{ 2453 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2454 NetworkInterfaces: []infrav1.NetworkInterface{{ 2455 SubnetName: "subnet1", 2456 PrivateIPConfigs: 1, 2457 }}, 2458 DNSServers: []string{"123.123.123.123", "124.124.124.124"}, 2459 }, 2460 }, 2461 Machine: &clusterv1.Machine{ 2462 ObjectMeta: metav1.ObjectMeta{ 2463 Name: "machine", 2464 Labels: map[string]string{ 2465 clusterv1.MachineControlPlaneLabel: "true", 2466 }, 2467 }, 2468 }, 2469 }, 2470 want: []azure.ResourceSpecGetter{ 2471 &networkinterfaces.NICSpec{ 2472 Name: "machine-name-nic", 2473 ResourceGroup: "my-rg", 2474 Location: "westus", 2475 SubscriptionID: "123", 2476 MachineName: "machine-name", 2477 SubnetName: "subnet1", 2478 IPConfigs: []networkinterfaces.IPConfig{{}}, 2479 VNetName: "vnet1", 2480 VNetResourceGroup: "rg1", 2481 PublicLBName: "api-lb", 2482 PublicLBAddressPoolName: "api-lb-backendPool", 2483 PublicLBNATRuleName: "machine-name", 2484 InternalLBName: "", 2485 InternalLBAddressPoolName: "", 2486 PublicIPName: "", 2487 AcceleratedNetworking: nil, 2488 DNSServers: []string{"123.123.123.123", "124.124.124.124"}, 2489 IPv6Enabled: false, 2490 EnableIPForwarding: false, 2491 SKU: nil, 2492 ClusterName: "cluster", 2493 AdditionalTags: infrav1.Tags{ 2494 "kubernetes.io_cluster_cluster": "owned", 2495 }, 2496 }, 2497 }, 2498 }, 2499 { 2500 name: "Node Machine with multiple Network Interfaces", 2501 machineScope: MachineScope{ 2502 ClusterScoper: &ClusterScope{ 2503 AzureClients: AzureClients{ 2504 EnvironmentSettings: auth.EnvironmentSettings{ 2505 Values: map[string]string{ 2506 auth.SubscriptionID: "123", 2507 }, 2508 }, 2509 }, 2510 Cluster: &clusterv1.Cluster{ 2511 ObjectMeta: metav1.ObjectMeta{ 2512 Name: "cluster", 2513 Namespace: "default", 2514 }, 2515 }, 2516 AzureCluster: &infrav1.AzureCluster{ 2517 ObjectMeta: metav1.ObjectMeta{ 2518 Name: "cluster", 2519 Namespace: "default", 2520 OwnerReferences: []metav1.OwnerReference{ 2521 { 2522 APIVersion: "cluster.x-k8s.io/v1beta1", 2523 Kind: "Cluster", 2524 Name: "cluster", 2525 }, 2526 }, 2527 }, 2528 Spec: infrav1.AzureClusterSpec{ 2529 ResourceGroup: "my-rg", 2530 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2531 Location: "westus", 2532 }, 2533 NetworkSpec: infrav1.NetworkSpec{ 2534 Vnet: infrav1.VnetSpec{ 2535 Name: "vnet1", 2536 ResourceGroup: "rg1", 2537 }, 2538 Subnets: []infrav1.SubnetSpec{ 2539 { 2540 SubnetClassSpec: infrav1.SubnetClassSpec{ 2541 Role: infrav1.SubnetNode, 2542 Name: "subnet1", 2543 }, 2544 }, 2545 }, 2546 APIServerLB: infrav1.LoadBalancerSpec{ 2547 Name: "api-lb", 2548 }, 2549 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2550 Name: "outbound-lb", 2551 BackendPool: infrav1.BackendPool{ 2552 Name: "outbound-lb-outboundBackendPool", 2553 }, 2554 }, 2555 }, 2556 }, 2557 }, 2558 }, 2559 AzureMachine: &infrav1.AzureMachine{ 2560 ObjectMeta: metav1.ObjectMeta{ 2561 Name: "machine", 2562 }, 2563 Spec: infrav1.AzureMachineSpec{ 2564 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2565 NetworkInterfaces: []infrav1.NetworkInterface{ 2566 { 2567 SubnetName: "subnet1", 2568 AcceleratedNetworking: ptr.To(true), 2569 PrivateIPConfigs: 1, 2570 }, 2571 { 2572 SubnetName: "subnet2", 2573 AcceleratedNetworking: ptr.To(true), 2574 PrivateIPConfigs: 2, 2575 }, 2576 }, 2577 }, 2578 }, 2579 Machine: &clusterv1.Machine{ 2580 ObjectMeta: metav1.ObjectMeta{ 2581 Name: "machine", 2582 Labels: map[string]string{}, 2583 }, 2584 }, 2585 }, 2586 want: []azure.ResourceSpecGetter{ 2587 &networkinterfaces.NICSpec{ 2588 Name: "machine-name-nic-0", 2589 ResourceGroup: "my-rg", 2590 Location: "westus", 2591 SubscriptionID: "123", 2592 MachineName: "machine-name", 2593 SubnetName: "subnet1", 2594 IPConfigs: []networkinterfaces.IPConfig{{}}, 2595 VNetName: "vnet1", 2596 VNetResourceGroup: "rg1", 2597 PublicLBName: "outbound-lb", 2598 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 2599 PublicLBNATRuleName: "", 2600 InternalLBName: "", 2601 InternalLBAddressPoolName: "", 2602 PublicIPName: "", 2603 AcceleratedNetworking: ptr.To(true), 2604 IPv6Enabled: false, 2605 EnableIPForwarding: false, 2606 SKU: nil, 2607 ClusterName: "cluster", 2608 AdditionalTags: map[string]string{ 2609 "kubernetes.io_cluster_cluster": "owned", 2610 }, 2611 }, 2612 &networkinterfaces.NICSpec{ 2613 Name: "machine-name-nic-1", 2614 ResourceGroup: "my-rg", 2615 Location: "westus", 2616 SubscriptionID: "123", 2617 MachineName: "machine-name", 2618 SubnetName: "subnet2", 2619 IPConfigs: []networkinterfaces.IPConfig{{}, {}}, 2620 VNetName: "vnet1", 2621 VNetResourceGroup: "rg1", 2622 PublicLBName: "", 2623 PublicLBAddressPoolName: "", 2624 PublicLBNATRuleName: "", 2625 InternalLBName: "", 2626 InternalLBAddressPoolName: "", 2627 PublicIPName: "", 2628 AcceleratedNetworking: ptr.To(true), 2629 IPv6Enabled: false, 2630 EnableIPForwarding: false, 2631 SKU: nil, 2632 ClusterName: "cluster", 2633 AdditionalTags: map[string]string{ 2634 "kubernetes.io_cluster_cluster": "owned", 2635 }, 2636 }, 2637 }, 2638 }, 2639 { 2640 name: "Node Machine with multiple Network Interfaces and Public IP Allocation enabled", 2641 machineScope: MachineScope{ 2642 ClusterScoper: &ClusterScope{ 2643 AzureClients: AzureClients{ 2644 EnvironmentSettings: auth.EnvironmentSettings{ 2645 Values: map[string]string{ 2646 auth.SubscriptionID: "123", 2647 }, 2648 }, 2649 }, 2650 Cluster: &clusterv1.Cluster{ 2651 ObjectMeta: metav1.ObjectMeta{ 2652 Name: "cluster", 2653 Namespace: "default", 2654 }, 2655 }, 2656 AzureCluster: &infrav1.AzureCluster{ 2657 ObjectMeta: metav1.ObjectMeta{ 2658 Name: "cluster", 2659 Namespace: "default", 2660 OwnerReferences: []metav1.OwnerReference{ 2661 { 2662 APIVersion: "cluster.x-k8s.io/v1beta1", 2663 Kind: "Cluster", 2664 Name: "cluster", 2665 }, 2666 }, 2667 }, 2668 Spec: infrav1.AzureClusterSpec{ 2669 ResourceGroup: "my-rg", 2670 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2671 Location: "westus", 2672 }, 2673 NetworkSpec: infrav1.NetworkSpec{ 2674 Vnet: infrav1.VnetSpec{ 2675 Name: "vnet1", 2676 ResourceGroup: "rg1", 2677 }, 2678 Subnets: []infrav1.SubnetSpec{ 2679 { 2680 SubnetClassSpec: infrav1.SubnetClassSpec{ 2681 Role: infrav1.SubnetNode, 2682 Name: "subnet1", 2683 }, 2684 }, 2685 }, 2686 APIServerLB: infrav1.LoadBalancerSpec{ 2687 Name: "api-lb", 2688 }, 2689 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2690 Name: "outbound-lb", 2691 }, 2692 }, 2693 }, 2694 }, 2695 }, 2696 AzureMachine: &infrav1.AzureMachine{ 2697 ObjectMeta: metav1.ObjectMeta{ 2698 Name: "machine", 2699 }, 2700 Spec: infrav1.AzureMachineSpec{ 2701 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2702 AllocatePublicIP: true, 2703 NetworkInterfaces: []infrav1.NetworkInterface{ 2704 { 2705 SubnetName: "subnet1", 2706 AcceleratedNetworking: ptr.To(true), 2707 PrivateIPConfigs: 1, 2708 }, 2709 { 2710 SubnetName: "subnet2", 2711 AcceleratedNetworking: ptr.To(true), 2712 PrivateIPConfigs: 2, 2713 }, 2714 }, 2715 }, 2716 }, 2717 Machine: &clusterv1.Machine{ 2718 ObjectMeta: metav1.ObjectMeta{ 2719 Name: "machine", 2720 Labels: map[string]string{}, 2721 }, 2722 }, 2723 }, 2724 want: []azure.ResourceSpecGetter{ 2725 &networkinterfaces.NICSpec{ 2726 Name: "machine-name-nic-0", 2727 ResourceGroup: "my-rg", 2728 Location: "westus", 2729 SubscriptionID: "123", 2730 MachineName: "machine-name", 2731 SubnetName: "subnet1", 2732 IPConfigs: []networkinterfaces.IPConfig{{}}, 2733 VNetName: "vnet1", 2734 VNetResourceGroup: "rg1", 2735 PublicLBName: "", 2736 PublicLBAddressPoolName: "", 2737 PublicLBNATRuleName: "", 2738 InternalLBName: "", 2739 InternalLBAddressPoolName: "", 2740 PublicIPName: "pip-machine-name", 2741 AcceleratedNetworking: ptr.To(true), 2742 IPv6Enabled: false, 2743 EnableIPForwarding: false, 2744 SKU: nil, 2745 ClusterName: "cluster", 2746 AdditionalTags: map[string]string{ 2747 "kubernetes.io_cluster_cluster": "owned", 2748 }, 2749 }, 2750 &networkinterfaces.NICSpec{ 2751 Name: "machine-name-nic-1", 2752 ResourceGroup: "my-rg", 2753 Location: "westus", 2754 SubscriptionID: "123", 2755 MachineName: "machine-name", 2756 SubnetName: "subnet2", 2757 IPConfigs: []networkinterfaces.IPConfig{{}, {}}, 2758 VNetName: "vnet1", 2759 VNetResourceGroup: "rg1", 2760 PublicLBName: "", 2761 PublicLBAddressPoolName: "", 2762 PublicLBNATRuleName: "", 2763 InternalLBName: "", 2764 InternalLBAddressPoolName: "", 2765 PublicIPName: "", 2766 AcceleratedNetworking: ptr.To(true), 2767 IPv6Enabled: false, 2768 EnableIPForwarding: false, 2769 SKU: nil, 2770 ClusterName: "cluster", 2771 AdditionalTags: map[string]string{ 2772 "kubernetes.io_cluster_cluster": "owned", 2773 }, 2774 }, 2775 }, 2776 }, 2777 { 2778 name: "Node Machine with multiple IPConfigs", 2779 machineScope: MachineScope{ 2780 ClusterScoper: &ClusterScope{ 2781 AzureClients: AzureClients{ 2782 EnvironmentSettings: auth.EnvironmentSettings{ 2783 Values: map[string]string{ 2784 auth.SubscriptionID: "123", 2785 }, 2786 }, 2787 }, 2788 Cluster: &clusterv1.Cluster{ 2789 ObjectMeta: metav1.ObjectMeta{ 2790 Name: "cluster", 2791 Namespace: "default", 2792 }, 2793 }, 2794 AzureCluster: &infrav1.AzureCluster{ 2795 ObjectMeta: metav1.ObjectMeta{ 2796 Name: "cluster", 2797 Namespace: "default", 2798 OwnerReferences: []metav1.OwnerReference{ 2799 { 2800 APIVersion: "cluster.x-k8s.io/v1beta1", 2801 Kind: "Cluster", 2802 Name: "cluster", 2803 }, 2804 }, 2805 }, 2806 Spec: infrav1.AzureClusterSpec{ 2807 ResourceGroup: "my-rg", 2808 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2809 Location: "westus", 2810 }, 2811 NetworkSpec: infrav1.NetworkSpec{ 2812 Vnet: infrav1.VnetSpec{ 2813 Name: "vnet1", 2814 ResourceGroup: "rg1", 2815 }, 2816 Subnets: []infrav1.SubnetSpec{ 2817 { 2818 SubnetClassSpec: infrav1.SubnetClassSpec{ 2819 Role: infrav1.SubnetNode, 2820 Name: "subnet1", 2821 }, 2822 }, 2823 }, 2824 APIServerLB: infrav1.LoadBalancerSpec{ 2825 Name: "api-lb", 2826 }, 2827 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2828 Name: "outbound-lb", 2829 BackendPool: infrav1.BackendPool{ 2830 Name: "outbound-lb-outboundBackendPool", 2831 }, 2832 }, 2833 }, 2834 }, 2835 }, 2836 }, 2837 AzureMachine: &infrav1.AzureMachine{ 2838 ObjectMeta: metav1.ObjectMeta{ 2839 Name: "machine", 2840 }, 2841 Spec: infrav1.AzureMachineSpec{ 2842 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2843 NetworkInterfaces: []infrav1.NetworkInterface{ 2844 { 2845 SubnetName: "subnet1", 2846 AcceleratedNetworking: ptr.To(true), 2847 PrivateIPConfigs: 10, 2848 }, 2849 }, 2850 }, 2851 }, 2852 Machine: &clusterv1.Machine{ 2853 ObjectMeta: metav1.ObjectMeta{ 2854 Name: "machine", 2855 Labels: map[string]string{}, 2856 }, 2857 }, 2858 }, 2859 want: []azure.ResourceSpecGetter{ 2860 &networkinterfaces.NICSpec{ 2861 Name: "machine-name-nic", 2862 ResourceGroup: "my-rg", 2863 Location: "westus", 2864 SubscriptionID: "123", 2865 MachineName: "machine-name", 2866 SubnetName: "subnet1", 2867 IPConfigs: []networkinterfaces.IPConfig{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, 2868 VNetName: "vnet1", 2869 VNetResourceGroup: "rg1", 2870 PublicLBName: "outbound-lb", 2871 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 2872 PublicLBNATRuleName: "", 2873 InternalLBName: "", 2874 InternalLBAddressPoolName: "", 2875 PublicIPName: "", 2876 AcceleratedNetworking: ptr.To(true), 2877 IPv6Enabled: false, 2878 EnableIPForwarding: false, 2879 SKU: nil, 2880 ClusterName: "cluster", 2881 AdditionalTags: map[string]string{ 2882 "kubernetes.io_cluster_cluster": "owned", 2883 }, 2884 }, 2885 }, 2886 }, 2887 } 2888 for _, tt := range tests { 2889 t.Run(tt.name, func(t *testing.T) { 2890 g := NewWithT(t) 2891 gotNicSpecs := tt.machineScope.NICSpecs() 2892 if !reflect.DeepEqual(gotNicSpecs, tt.want) { 2893 g.Expect(gotNicSpecs).To(BeEquivalentTo(tt.want)) 2894 t.Errorf("NICSpecs(), gotNicSpecs = %s, want %s", specArrayToString(gotNicSpecs), specArrayToString(tt.want)) 2895 } 2896 }) 2897 } 2898 } 2899 2900 func TestDiskSpecs(t *testing.T) { 2901 testcases := []struct { 2902 name string 2903 machineScope MachineScope 2904 want []azure.ResourceSpecGetter 2905 }{ 2906 { 2907 name: "only os disk", 2908 machineScope: MachineScope{ 2909 ClusterScoper: &ClusterScope{ 2910 Cluster: &clusterv1.Cluster{ 2911 ObjectMeta: metav1.ObjectMeta{ 2912 Name: "cluster", 2913 }, 2914 }, 2915 AzureCluster: &infrav1.AzureCluster{ 2916 ObjectMeta: metav1.ObjectMeta{ 2917 Name: "cluster", 2918 }, 2919 Spec: infrav1.AzureClusterSpec{ 2920 ResourceGroup: "my-rg", 2921 }, 2922 }, 2923 }, 2924 AzureMachine: &infrav1.AzureMachine{ 2925 ObjectMeta: metav1.ObjectMeta{ 2926 Name: "my-azure-machine", 2927 }, 2928 Spec: infrav1.AzureMachineSpec{ 2929 OSDisk: infrav1.OSDisk{ 2930 DiskSizeGB: ptr.To[int32](30), 2931 OSType: "Linux", 2932 }, 2933 }, 2934 }, 2935 Machine: &clusterv1.Machine{ 2936 ObjectMeta: metav1.ObjectMeta{ 2937 Name: "machine", 2938 }, 2939 }, 2940 }, 2941 want: []azure.ResourceSpecGetter{ 2942 &disks.DiskSpec{ 2943 Name: "my-azure-machine_OSDisk", 2944 ResourceGroup: "my-rg", 2945 }, 2946 }, 2947 }, 2948 { 2949 name: "os and data disks", 2950 machineScope: MachineScope{ 2951 ClusterScoper: &ClusterScope{ 2952 Cluster: &clusterv1.Cluster{ 2953 ObjectMeta: metav1.ObjectMeta{ 2954 Name: "cluster", 2955 }, 2956 }, 2957 AzureCluster: &infrav1.AzureCluster{ 2958 ObjectMeta: metav1.ObjectMeta{ 2959 Name: "cluster", 2960 }, 2961 Spec: infrav1.AzureClusterSpec{ 2962 ResourceGroup: "my-rg", 2963 }, 2964 }, 2965 }, 2966 AzureMachine: &infrav1.AzureMachine{ 2967 ObjectMeta: metav1.ObjectMeta{ 2968 Name: "my-azure-machine", 2969 }, 2970 Spec: infrav1.AzureMachineSpec{ 2971 OSDisk: infrav1.OSDisk{ 2972 DiskSizeGB: ptr.To[int32](30), 2973 OSType: "Linux", 2974 }, 2975 DataDisks: []infrav1.DataDisk{ 2976 { 2977 NameSuffix: "etcddisk", 2978 }, 2979 }, 2980 }, 2981 }, 2982 Machine: &clusterv1.Machine{ 2983 ObjectMeta: metav1.ObjectMeta{ 2984 Name: "machine", 2985 }, 2986 }, 2987 }, 2988 want: []azure.ResourceSpecGetter{ 2989 &disks.DiskSpec{ 2990 Name: "my-azure-machine_OSDisk", 2991 ResourceGroup: "my-rg", 2992 }, 2993 &disks.DiskSpec{ 2994 Name: "my-azure-machine_etcddisk", 2995 ResourceGroup: "my-rg", 2996 }, 2997 }, 2998 }, { 2999 name: "os and multiple data disks", 3000 machineScope: MachineScope{ 3001 ClusterScoper: &ClusterScope{ 3002 Cluster: &clusterv1.Cluster{ 3003 ObjectMeta: metav1.ObjectMeta{ 3004 Name: "cluster", 3005 }, 3006 }, 3007 AzureCluster: &infrav1.AzureCluster{ 3008 ObjectMeta: metav1.ObjectMeta{ 3009 Name: "cluster", 3010 }, 3011 Spec: infrav1.AzureClusterSpec{ 3012 ResourceGroup: "my-rg", 3013 }, 3014 }, 3015 }, 3016 AzureMachine: &infrav1.AzureMachine{ 3017 ObjectMeta: metav1.ObjectMeta{ 3018 Name: "my-azure-machine", 3019 }, 3020 Spec: infrav1.AzureMachineSpec{ 3021 OSDisk: infrav1.OSDisk{ 3022 DiskSizeGB: ptr.To[int32](30), 3023 OSType: "Linux", 3024 }, 3025 DataDisks: []infrav1.DataDisk{ 3026 { 3027 NameSuffix: "etcddisk", 3028 }, 3029 { 3030 NameSuffix: "otherdisk", 3031 }, 3032 }, 3033 }, 3034 }, 3035 Machine: &clusterv1.Machine{ 3036 ObjectMeta: metav1.ObjectMeta{ 3037 Name: "machine", 3038 }, 3039 }, 3040 }, 3041 want: []azure.ResourceSpecGetter{ 3042 &disks.DiskSpec{ 3043 Name: "my-azure-machine_OSDisk", 3044 ResourceGroup: "my-rg", 3045 }, 3046 &disks.DiskSpec{ 3047 Name: "my-azure-machine_etcddisk", 3048 ResourceGroup: "my-rg", 3049 }, 3050 &disks.DiskSpec{ 3051 Name: "my-azure-machine_otherdisk", 3052 ResourceGroup: "my-rg", 3053 }, 3054 }, 3055 }, 3056 } 3057 3058 for _, tt := range testcases { 3059 tt := tt 3060 t.Run(tt.name, func(t *testing.T) { 3061 g := NewWithT(t) 3062 3063 t.Parallel() 3064 result := tt.machineScope.DiskSpecs() 3065 g.Expect(result).To(BeEquivalentTo(tt.want)) 3066 }) 3067 } 3068 }