sigs.k8s.io/cluster-api-provider-azure@v1.17.0/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 AzurePublicCloud and DisableExtensionOperations is true, 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 DisableExtensionOperations: ptr.To(true), 611 OSDisk: infrav1.OSDisk{ 612 OSType: "Linux", 613 }, 614 }, 615 }, 616 ClusterScoper: &ClusterScope{ 617 AzureClients: AzureClients{ 618 EnvironmentSettings: auth.EnvironmentSettings{ 619 Environment: azureautorest.Environment{ 620 Name: azureautorest.PublicCloud.Name, 621 }, 622 }, 623 }, 624 AzureCluster: &infrav1.AzureCluster{ 625 Spec: infrav1.AzureClusterSpec{ 626 ResourceGroup: "my-rg", 627 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 628 Location: "westus", 629 }, 630 }, 631 }, 632 }, 633 cache: &MachineCache{ 634 VMSKU: resourceskus.SKU{}, 635 }, 636 }, 637 want: []azure.ResourceSpecGetter{}, 638 }, 639 { 640 name: "If OS type is Linux and cloud is not AzurePublicCloud, it returns empty", 641 machineScope: MachineScope{ 642 Machine: &clusterv1.Machine{}, 643 AzureMachine: &infrav1.AzureMachine{ 644 ObjectMeta: metav1.ObjectMeta{ 645 Name: "machine-name", 646 }, 647 Spec: infrav1.AzureMachineSpec{ 648 OSDisk: infrav1.OSDisk{ 649 OSType: "Linux", 650 }, 651 }, 652 }, 653 ClusterScoper: &ClusterScope{ 654 AzureClients: AzureClients{ 655 EnvironmentSettings: auth.EnvironmentSettings{ 656 Environment: azureautorest.Environment{ 657 Name: azureautorest.USGovernmentCloud.Name, 658 }, 659 }, 660 }, 661 AzureCluster: &infrav1.AzureCluster{ 662 Spec: infrav1.AzureClusterSpec{ 663 ResourceGroup: "my-rg", 664 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 665 Location: "westus", 666 }, 667 }, 668 }, 669 }, 670 cache: &MachineCache{ 671 VMSKU: resourceskus.SKU{}, 672 }, 673 }, 674 want: []azure.ResourceSpecGetter{}, 675 }, 676 { 677 name: "If OS type is Windows and cloud is AzurePublicCloud, it returns ExtensionSpec", 678 machineScope: MachineScope{ 679 Machine: &clusterv1.Machine{}, 680 AzureMachine: &infrav1.AzureMachine{ 681 ObjectMeta: metav1.ObjectMeta{ 682 Name: "machine-name", 683 }, 684 Spec: infrav1.AzureMachineSpec{ 685 OSDisk: infrav1.OSDisk{ 686 OSType: "Windows", 687 }, 688 }, 689 }, 690 ClusterScoper: &ClusterScope{ 691 AzureClients: AzureClients{ 692 EnvironmentSettings: auth.EnvironmentSettings{ 693 Environment: azureautorest.Environment{ 694 Name: azureautorest.PublicCloud.Name, 695 }, 696 }, 697 }, 698 AzureCluster: &infrav1.AzureCluster{ 699 Spec: infrav1.AzureClusterSpec{ 700 ResourceGroup: "my-rg", 701 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 702 Location: "westus", 703 }, 704 }, 705 }, 706 }, 707 cache: &MachineCache{ 708 VMSKU: resourceskus.SKU{}, 709 }, 710 }, 711 want: []azure.ResourceSpecGetter{ 712 &vmextensions.VMExtensionSpec{ 713 ExtensionSpec: azure.ExtensionSpec{ 714 Name: "CAPZ.Windows.Bootstrapping", 715 VMName: "machine-name", 716 Publisher: "Microsoft.Azure.ContainerUpstream", 717 Version: "1.0", 718 ProtectedSettings: map[string]string{ 719 "commandToExecute": azure.WindowsBootstrapExtensionCommand, 720 }, 721 }, 722 ResourceGroup: "my-rg", 723 Location: "westus", 724 }, 725 }, 726 }, 727 { 728 name: "If OS type is Windows and cloud is not AzurePublicCloud, it returns empty", 729 machineScope: MachineScope{ 730 Machine: &clusterv1.Machine{}, 731 AzureMachine: &infrav1.AzureMachine{ 732 ObjectMeta: metav1.ObjectMeta{ 733 Name: "machine-name", 734 }, 735 Spec: infrav1.AzureMachineSpec{ 736 OSDisk: infrav1.OSDisk{ 737 OSType: "Windows", 738 }, 739 }, 740 }, 741 ClusterScoper: &ClusterScope{ 742 AzureClients: AzureClients{ 743 EnvironmentSettings: auth.EnvironmentSettings{ 744 Environment: azureautorest.Environment{ 745 Name: azureautorest.USGovernmentCloud.Name, 746 }, 747 }, 748 }, 749 AzureCluster: &infrav1.AzureCluster{ 750 Spec: infrav1.AzureClusterSpec{ 751 ResourceGroup: "my-rg", 752 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 753 Location: "westus", 754 }, 755 }, 756 }, 757 }, 758 cache: &MachineCache{ 759 VMSKU: resourceskus.SKU{}, 760 }, 761 }, 762 want: []azure.ResourceSpecGetter{}, 763 }, 764 { 765 name: "If OS type is not Linux or Windows and cloud is AzurePublicCloud, it returns empty", 766 machineScope: MachineScope{ 767 Machine: &clusterv1.Machine{}, 768 AzureMachine: &infrav1.AzureMachine{ 769 ObjectMeta: metav1.ObjectMeta{ 770 Name: "machine-name", 771 }, 772 Spec: infrav1.AzureMachineSpec{ 773 OSDisk: infrav1.OSDisk{ 774 OSType: "Other", 775 }, 776 }, 777 }, 778 ClusterScoper: &ClusterScope{ 779 AzureClients: AzureClients{ 780 EnvironmentSettings: auth.EnvironmentSettings{ 781 Environment: azureautorest.Environment{ 782 Name: azureautorest.PublicCloud.Name, 783 }, 784 }, 785 }, 786 AzureCluster: &infrav1.AzureCluster{ 787 Spec: infrav1.AzureClusterSpec{ 788 ResourceGroup: "my-rg", 789 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 790 Location: "westus", 791 }, 792 }, 793 }, 794 }, 795 cache: &MachineCache{ 796 VMSKU: resourceskus.SKU{}, 797 }, 798 }, 799 want: []azure.ResourceSpecGetter{}, 800 }, 801 { 802 name: "If OS type is not Windows or Linux and cloud is not AzurePublicCloud, it returns empty", 803 machineScope: MachineScope{ 804 Machine: &clusterv1.Machine{}, 805 AzureMachine: &infrav1.AzureMachine{ 806 ObjectMeta: metav1.ObjectMeta{ 807 Name: "machine-name", 808 }, 809 Spec: infrav1.AzureMachineSpec{ 810 OSDisk: infrav1.OSDisk{ 811 OSType: "Other", 812 }, 813 }, 814 }, 815 ClusterScoper: &ClusterScope{ 816 AzureClients: AzureClients{ 817 EnvironmentSettings: auth.EnvironmentSettings{ 818 Environment: azureautorest.Environment{ 819 Name: azureautorest.USGovernmentCloud.Name, 820 }, 821 }, 822 }, 823 AzureCluster: &infrav1.AzureCluster{ 824 Spec: infrav1.AzureClusterSpec{ 825 ResourceGroup: "my-rg", 826 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 827 Location: "westus", 828 }, 829 }, 830 }, 831 }, 832 cache: &MachineCache{ 833 VMSKU: resourceskus.SKU{}, 834 }, 835 }, 836 want: []azure.ResourceSpecGetter{}, 837 }, 838 { 839 name: "If a custom VM extension is specified, it returns the custom VM extension", 840 machineScope: MachineScope{ 841 Machine: &clusterv1.Machine{}, 842 AzureMachine: &infrav1.AzureMachine{ 843 ObjectMeta: metav1.ObjectMeta{ 844 Name: "machine-name", 845 }, 846 Spec: infrav1.AzureMachineSpec{ 847 OSDisk: infrav1.OSDisk{ 848 OSType: "Linux", 849 }, 850 VMExtensions: []infrav1.VMExtension{ 851 { 852 Name: "custom-vm-extension", 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 }, 863 }, 864 }, 865 ClusterScoper: &ClusterScope{ 866 AzureClients: AzureClients{ 867 EnvironmentSettings: auth.EnvironmentSettings{ 868 Environment: azureautorest.Environment{ 869 Name: azureautorest.PublicCloud.Name, 870 }, 871 }, 872 }, 873 AzureCluster: &infrav1.AzureCluster{ 874 Spec: infrav1.AzureClusterSpec{ 875 ResourceGroup: "my-rg", 876 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 877 Location: "westus", 878 }, 879 }, 880 }, 881 }, 882 cache: &MachineCache{ 883 VMSKU: resourceskus.SKU{}, 884 }, 885 }, 886 want: []azure.ResourceSpecGetter{ 887 &vmextensions.VMExtensionSpec{ 888 ExtensionSpec: azure.ExtensionSpec{ 889 Name: "custom-vm-extension", 890 VMName: "machine-name", 891 Publisher: "Microsoft.Azure.Extensions", 892 Version: "2.0", 893 Settings: map[string]string{ 894 "timestamp": "1234567890", 895 }, 896 ProtectedSettings: map[string]string{ 897 "commandToExecute": "echo hello world", 898 }, 899 }, 900 ResourceGroup: "my-rg", 901 Location: "westus", 902 }, 903 &vmextensions.VMExtensionSpec{ 904 ExtensionSpec: azure.ExtensionSpec{ 905 Name: "CAPZ.Linux.Bootstrapping", 906 VMName: "machine-name", 907 Publisher: "Microsoft.Azure.ContainerUpstream", 908 Version: "1.0", 909 ProtectedSettings: map[string]string{ 910 "commandToExecute": azure.LinuxBootstrapExtensionCommand, 911 }, 912 }, 913 ResourceGroup: "my-rg", 914 Location: "westus", 915 }, 916 }, 917 }, 918 } 919 for _, tt := range tests { 920 t.Run(tt.name, func(t *testing.T) { 921 if got := tt.machineScope.VMExtensionSpecs(); !reflect.DeepEqual(got, tt.want) { 922 t.Errorf("VMExtensionSpecs() = \n%s, want \n%s", specArrayToString(got), specArrayToString(tt.want)) 923 } 924 }) 925 } 926 } 927 928 func TestMachineScope_Subnet(t *testing.T) { 929 tests := []struct { 930 name string 931 machineScope MachineScope 932 want infrav1.SubnetSpec 933 }{ 934 { 935 name: "returns empty if no subnet is found at cluster scope", 936 machineScope: MachineScope{ 937 AzureMachine: &infrav1.AzureMachine{ 938 ObjectMeta: metav1.ObjectMeta{ 939 Name: "machine-name", 940 }, 941 Spec: infrav1.AzureMachineSpec{ 942 SubnetName: "machine-name-subnet", 943 }, 944 }, 945 ClusterScoper: &ClusterScope{ 946 AzureCluster: &infrav1.AzureCluster{ 947 Spec: infrav1.AzureClusterSpec{ 948 NetworkSpec: infrav1.NetworkSpec{ 949 Subnets: []infrav1.SubnetSpec{}, 950 }, 951 }, 952 }, 953 }, 954 }, 955 want: infrav1.SubnetSpec{}, 956 }, 957 { 958 name: "returns the machine subnet name if the same is present in the cluster scope", 959 machineScope: MachineScope{ 960 AzureMachine: &infrav1.AzureMachine{ 961 ObjectMeta: metav1.ObjectMeta{ 962 Name: "machine-name", 963 }, 964 Spec: infrav1.AzureMachineSpec{ 965 NetworkInterfaces: []infrav1.NetworkInterface{{ 966 SubnetName: "machine-name-subnet", 967 }}, 968 }, 969 }, 970 ClusterScoper: &ClusterScope{ 971 AzureCluster: &infrav1.AzureCluster{ 972 Spec: infrav1.AzureClusterSpec{ 973 NetworkSpec: infrav1.NetworkSpec{ 974 Subnets: []infrav1.SubnetSpec{ 975 { 976 SubnetClassSpec: infrav1.SubnetClassSpec{ 977 Name: "machine-name-subnet", 978 }, 979 }, 980 { 981 SubnetClassSpec: infrav1.SubnetClassSpec{ 982 Name: "another-machine-name-subnet", 983 }, 984 }, 985 }, 986 }, 987 }, 988 }, 989 }, 990 }, 991 want: infrav1.SubnetSpec{ 992 SubnetClassSpec: infrav1.SubnetClassSpec{ 993 Name: "machine-name-subnet", 994 }, 995 }, 996 }, 997 { 998 name: "returns empty if machine subnet name is not present in the cluster scope", 999 machineScope: MachineScope{ 1000 AzureMachine: &infrav1.AzureMachine{ 1001 ObjectMeta: metav1.ObjectMeta{ 1002 Name: "machine-name", 1003 }, 1004 Spec: infrav1.AzureMachineSpec{ 1005 SubnetName: "machine-name-subnet", 1006 }, 1007 }, 1008 ClusterScoper: &ClusterScope{ 1009 AzureCluster: &infrav1.AzureCluster{ 1010 Spec: infrav1.AzureClusterSpec{ 1011 NetworkSpec: infrav1.NetworkSpec{}, 1012 }, 1013 }, 1014 }, 1015 }, 1016 want: infrav1.SubnetSpec{}, 1017 }, 1018 } 1019 for _, tt := range tests { 1020 t.Run(tt.name, func(t *testing.T) { 1021 if got := tt.machineScope.Subnet(); !reflect.DeepEqual(got, tt.want) { 1022 t.Errorf("Subnet() = %v, want %v", got, tt.want) 1023 } 1024 }) 1025 } 1026 } 1027 1028 func TestMachineScope_AvailabilityZone(t *testing.T) { 1029 tests := []struct { 1030 name string 1031 machineScope MachineScope 1032 want string 1033 }{ 1034 { 1035 name: "returns empty if no failure domain is present", 1036 machineScope: MachineScope{ 1037 Machine: &clusterv1.Machine{ 1038 Spec: clusterv1.MachineSpec{}, 1039 }, 1040 AzureMachine: &infrav1.AzureMachine{ 1041 ObjectMeta: metav1.ObjectMeta{ 1042 Name: "machine-name", 1043 }, 1044 Spec: infrav1.AzureMachineSpec{}, 1045 }, 1046 }, 1047 want: "", 1048 }, 1049 { 1050 name: "returns failure domain from the machine spec", 1051 machineScope: MachineScope{ 1052 Machine: &clusterv1.Machine{ 1053 Spec: clusterv1.MachineSpec{ 1054 FailureDomain: ptr.To("dummy-failure-domain-from-machine-spec"), 1055 }, 1056 }, 1057 AzureMachine: &infrav1.AzureMachine{ 1058 ObjectMeta: metav1.ObjectMeta{ 1059 Name: "machine-name", 1060 }, 1061 Spec: infrav1.AzureMachineSpec{ 1062 FailureDomain: ptr.To("dummy-failure-domain-from-azuremachine-spec"), 1063 }, 1064 }, 1065 }, 1066 want: "dummy-failure-domain-from-machine-spec", 1067 }, 1068 { 1069 name: "returns failure domain from the azuremachine spec", 1070 machineScope: MachineScope{ 1071 Machine: &clusterv1.Machine{ 1072 Spec: clusterv1.MachineSpec{}, 1073 }, 1074 AzureMachine: &infrav1.AzureMachine{ 1075 ObjectMeta: metav1.ObjectMeta{ 1076 Name: "machine-name", 1077 }, 1078 Spec: infrav1.AzureMachineSpec{ 1079 FailureDomain: ptr.To("dummy-failure-domain-from-azuremachine-spec"), 1080 }, 1081 }, 1082 }, 1083 want: "dummy-failure-domain-from-azuremachine-spec", 1084 }, 1085 } 1086 for _, tt := range tests { 1087 t.Run(tt.name, func(t *testing.T) { 1088 if got := tt.machineScope.AvailabilityZone(); got != tt.want { 1089 t.Errorf("AvailabilityZone() = %v, want %v", got, tt.want) 1090 } 1091 }) 1092 } 1093 } 1094 1095 func TestMachineScope_Namespace(t *testing.T) { 1096 tests := []struct { 1097 name string 1098 machineScope MachineScope 1099 want string 1100 }{ 1101 { 1102 name: "returns azure machine namespace", 1103 machineScope: MachineScope{ 1104 AzureMachine: &infrav1.AzureMachine{ 1105 ObjectMeta: metav1.ObjectMeta{ 1106 Name: "machine-name", 1107 Namespace: "foo", 1108 }, 1109 }, 1110 }, 1111 want: "foo", 1112 }, 1113 { 1114 name: "returns azure machine namespace as empty if namespace is no specified", 1115 machineScope: MachineScope{ 1116 AzureMachine: &infrav1.AzureMachine{ 1117 ObjectMeta: metav1.ObjectMeta{ 1118 Name: "machine-name", 1119 }, 1120 }, 1121 }, 1122 want: "", 1123 }, 1124 } 1125 for _, tt := range tests { 1126 t.Run(tt.name, func(t *testing.T) { 1127 if got := tt.machineScope.Namespace(); got != tt.want { 1128 t.Errorf("Namespace() = %v, want %v", got, tt.want) 1129 } 1130 }) 1131 } 1132 } 1133 1134 func TestMachineScope_IsControlPlane(t *testing.T) { 1135 tests := []struct { 1136 name string 1137 machineScope MachineScope 1138 want bool 1139 }{ 1140 { 1141 name: "returns false when machine is not control plane", 1142 machineScope: MachineScope{ 1143 Machine: &clusterv1.Machine{}, 1144 AzureMachine: &infrav1.AzureMachine{ 1145 ObjectMeta: metav1.ObjectMeta{ 1146 Name: "machine-name", 1147 }, 1148 }, 1149 }, 1150 want: false, 1151 }, 1152 { 1153 name: "returns true when machine is control plane", 1154 machineScope: MachineScope{ 1155 Machine: &clusterv1.Machine{ 1156 ObjectMeta: metav1.ObjectMeta{ 1157 Labels: map[string]string{ 1158 clusterv1.MachineControlPlaneLabel: "", 1159 }, 1160 }, 1161 }, 1162 AzureMachine: &infrav1.AzureMachine{ 1163 ObjectMeta: metav1.ObjectMeta{ 1164 Name: "machine-name", 1165 }, 1166 }, 1167 }, 1168 want: true, 1169 }, 1170 } 1171 for _, tt := range tests { 1172 t.Run(tt.name, func(t *testing.T) { 1173 if got := tt.machineScope.IsControlPlane(); got != tt.want { 1174 t.Errorf("IsControlPlane() = %v, want %v", got, tt.want) 1175 } 1176 }) 1177 } 1178 } 1179 1180 func TestMachineScope_Role(t *testing.T) { 1181 tests := []struct { 1182 name string 1183 machineScope MachineScope 1184 want string 1185 }{ 1186 { 1187 name: "returns node when machine is worker", 1188 machineScope: MachineScope{ 1189 Machine: &clusterv1.Machine{}, 1190 AzureMachine: &infrav1.AzureMachine{ 1191 ObjectMeta: metav1.ObjectMeta{ 1192 Name: "machine-name", 1193 }, 1194 }, 1195 }, 1196 want: infrav1.Node, 1197 }, 1198 { 1199 name: "returns control-plane when machine is control plane", 1200 machineScope: MachineScope{ 1201 Machine: &clusterv1.Machine{ 1202 ObjectMeta: metav1.ObjectMeta{ 1203 Labels: map[string]string{ 1204 clusterv1.MachineControlPlaneLabel: "", 1205 }, 1206 }, 1207 }, 1208 AzureMachine: &infrav1.AzureMachine{ 1209 ObjectMeta: metav1.ObjectMeta{ 1210 Name: "machine-name", 1211 }, 1212 }, 1213 }, 1214 want: infrav1.ControlPlane, 1215 }, 1216 } 1217 for _, tt := range tests { 1218 t.Run(tt.name, func(t *testing.T) { 1219 if got := tt.machineScope.Role(); got != tt.want { 1220 t.Errorf("Role() = %v, want %v", got, tt.want) 1221 } 1222 }) 1223 } 1224 } 1225 1226 func TestMachineScope_AvailabilitySet(t *testing.T) { 1227 tests := []struct { 1228 name string 1229 machineScope MachineScope 1230 wantAvailabilitySetName string 1231 wantAvailabilitySetExistence bool 1232 }{ 1233 { 1234 name: "returns empty and false if availability set is not enabled", 1235 machineScope: MachineScope{ 1236 ClusterScoper: &ClusterScope{ 1237 Cluster: &clusterv1.Cluster{ 1238 ObjectMeta: metav1.ObjectMeta{ 1239 Name: "cluster", 1240 }, 1241 }, 1242 AzureCluster: &infrav1.AzureCluster{ 1243 Status: infrav1.AzureClusterStatus{ 1244 FailureDomains: clusterv1.FailureDomains{ 1245 "foo-failure-domain": clusterv1.FailureDomainSpec{}, 1246 }, 1247 }, 1248 }, 1249 }, 1250 Machine: &clusterv1.Machine{}, 1251 AzureMachine: &infrav1.AzureMachine{}, 1252 }, 1253 wantAvailabilitySetName: "", 1254 wantAvailabilitySetExistence: false, 1255 }, 1256 { 1257 name: "returns AvailabilitySet name and true if availability set is enabled and machine is control plane", 1258 machineScope: MachineScope{ 1259 1260 ClusterScoper: &ClusterScope{ 1261 Cluster: &clusterv1.Cluster{ 1262 ObjectMeta: metav1.ObjectMeta{ 1263 Name: "cluster", 1264 }, 1265 }, 1266 AzureCluster: &infrav1.AzureCluster{ 1267 Status: infrav1.AzureClusterStatus{}, 1268 }, 1269 }, 1270 Machine: &clusterv1.Machine{ 1271 ObjectMeta: metav1.ObjectMeta{ 1272 Labels: map[string]string{ 1273 clusterv1.MachineControlPlaneLabel: "", 1274 }, 1275 }, 1276 }, 1277 AzureMachine: &infrav1.AzureMachine{}, 1278 }, 1279 wantAvailabilitySetName: "cluster_control-plane-as", 1280 wantAvailabilitySetExistence: true, 1281 }, 1282 { 1283 name: "returns AvailabilitySet name and true if AvailabilitySet is enabled for worker machine which is part of machine deployment", 1284 machineScope: MachineScope{ 1285 1286 ClusterScoper: &ClusterScope{ 1287 Cluster: &clusterv1.Cluster{ 1288 ObjectMeta: metav1.ObjectMeta{ 1289 Name: "cluster", 1290 }, 1291 }, 1292 AzureCluster: &infrav1.AzureCluster{ 1293 Status: infrav1.AzureClusterStatus{}, 1294 }, 1295 }, 1296 Machine: &clusterv1.Machine{ 1297 ObjectMeta: metav1.ObjectMeta{ 1298 Labels: map[string]string{ 1299 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1300 }, 1301 }, 1302 }, 1303 AzureMachine: &infrav1.AzureMachine{}, 1304 }, 1305 wantAvailabilitySetName: "cluster_foo-machine-deployment-as", 1306 wantAvailabilitySetExistence: true, 1307 }, 1308 { 1309 name: "returns empty and false if machine is using spot instances", 1310 machineScope: MachineScope{ 1311 ClusterScoper: &ClusterScope{ 1312 Cluster: &clusterv1.Cluster{ 1313 ObjectMeta: metav1.ObjectMeta{ 1314 Name: "cluster", 1315 }, 1316 }, 1317 AzureCluster: &infrav1.AzureCluster{ 1318 Status: infrav1.AzureClusterStatus{}, 1319 }, 1320 }, 1321 Machine: &clusterv1.Machine{ 1322 ObjectMeta: metav1.ObjectMeta{ 1323 Labels: map[string]string{ 1324 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1325 }, 1326 }, 1327 }, 1328 AzureMachine: &infrav1.AzureMachine{ 1329 Spec: infrav1.AzureMachineSpec{ 1330 SpotVMOptions: &infrav1.SpotVMOptions{MaxPrice: resource.NewQuantity(-1, resource.DecimalSI)}, 1331 }, 1332 }, 1333 }, 1334 wantAvailabilitySetName: "", 1335 wantAvailabilitySetExistence: false, 1336 }, 1337 { 1338 name: "returns AvailabilitySet name and true if AvailabilitySet is enabled for worker machine which is part of machine set", 1339 machineScope: MachineScope{ 1340 1341 ClusterScoper: &ClusterScope{ 1342 Cluster: &clusterv1.Cluster{ 1343 ObjectMeta: metav1.ObjectMeta{ 1344 Name: "cluster", 1345 }, 1346 }, 1347 AzureCluster: &infrav1.AzureCluster{ 1348 Status: infrav1.AzureClusterStatus{}, 1349 }, 1350 }, 1351 Machine: &clusterv1.Machine{ 1352 ObjectMeta: metav1.ObjectMeta{ 1353 Labels: map[string]string{ 1354 clusterv1.MachineSetNameLabel: "foo-machine-set", 1355 }, 1356 }, 1357 }, 1358 AzureMachine: &infrav1.AzureMachine{}, 1359 }, 1360 wantAvailabilitySetName: "cluster_foo-machine-set-as", 1361 wantAvailabilitySetExistence: true, 1362 }, 1363 { 1364 name: "returns AvailabilitySet name and true if AvailabilitySet is enabled for worker machine and machine deployment name takes precedence over machine set name", 1365 machineScope: MachineScope{ 1366 1367 ClusterScoper: &ClusterScope{ 1368 Cluster: &clusterv1.Cluster{ 1369 ObjectMeta: metav1.ObjectMeta{ 1370 Name: "cluster", 1371 }, 1372 }, 1373 AzureCluster: &infrav1.AzureCluster{ 1374 Status: infrav1.AzureClusterStatus{}, 1375 }, 1376 }, 1377 Machine: &clusterv1.Machine{ 1378 ObjectMeta: metav1.ObjectMeta{ 1379 Labels: map[string]string{ 1380 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1381 clusterv1.MachineSetNameLabel: "foo-machine-set", 1382 }, 1383 }, 1384 }, 1385 AzureMachine: &infrav1.AzureMachine{}, 1386 }, 1387 wantAvailabilitySetName: "cluster_foo-machine-deployment-as", 1388 wantAvailabilitySetExistence: true, 1389 }, 1390 { 1391 name: "returns empty and false if AvailabilitySet is enabled but worker machine is not part of machine deployment or machine set", 1392 machineScope: MachineScope{ 1393 1394 ClusterScoper: &ClusterScope{ 1395 Cluster: &clusterv1.Cluster{ 1396 ObjectMeta: metav1.ObjectMeta{ 1397 Name: "cluster", 1398 }, 1399 }, 1400 AzureCluster: &infrav1.AzureCluster{ 1401 Status: infrav1.AzureClusterStatus{}, 1402 }, 1403 }, 1404 Machine: &clusterv1.Machine{ 1405 ObjectMeta: metav1.ObjectMeta{ 1406 Labels: map[string]string{}, 1407 }, 1408 }, 1409 AzureMachine: &infrav1.AzureMachine{}, 1410 }, 1411 wantAvailabilitySetName: "", 1412 wantAvailabilitySetExistence: false, 1413 }, 1414 { 1415 name: "returns empty and false if machine has failureDomain set", 1416 machineScope: MachineScope{ 1417 ClusterScoper: &ClusterScope{ 1418 Cluster: &clusterv1.Cluster{ 1419 ObjectMeta: metav1.ObjectMeta{ 1420 Name: "cluster", 1421 }, 1422 }, 1423 AzureCluster: &infrav1.AzureCluster{ 1424 Status: infrav1.AzureClusterStatus{}, 1425 }, 1426 }, 1427 Machine: &clusterv1.Machine{ 1428 ObjectMeta: metav1.ObjectMeta{ 1429 Labels: map[string]string{ 1430 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1431 }, 1432 }, 1433 Spec: clusterv1.MachineSpec{ 1434 FailureDomain: ptr.To("1"), 1435 }, 1436 }, 1437 AzureMachine: &infrav1.AzureMachine{ 1438 Spec: infrav1.AzureMachineSpec{}, 1439 }, 1440 }, 1441 wantAvailabilitySetName: "", 1442 wantAvailabilitySetExistence: false, 1443 }, 1444 { 1445 name: "returns empty and false if azureMachine has failureDomain set", 1446 machineScope: MachineScope{ 1447 ClusterScoper: &ClusterScope{ 1448 Cluster: &clusterv1.Cluster{ 1449 ObjectMeta: metav1.ObjectMeta{ 1450 Name: "cluster", 1451 }, 1452 }, 1453 AzureCluster: &infrav1.AzureCluster{ 1454 Status: infrav1.AzureClusterStatus{}, 1455 }, 1456 }, 1457 Machine: &clusterv1.Machine{ 1458 ObjectMeta: metav1.ObjectMeta{ 1459 Labels: map[string]string{ 1460 clusterv1.MachineDeploymentNameLabel: "foo-machine-deployment", 1461 }, 1462 }, 1463 }, 1464 AzureMachine: &infrav1.AzureMachine{ 1465 Spec: infrav1.AzureMachineSpec{ 1466 FailureDomain: ptr.To("1"), 1467 }, 1468 }, 1469 }, 1470 wantAvailabilitySetName: "", 1471 wantAvailabilitySetExistence: false, 1472 }, 1473 } 1474 for _, tt := range tests { 1475 t.Run(tt.name, func(t *testing.T) { 1476 gotAvailabilitySetName, gotAvailabilitySetExistence := tt.machineScope.AvailabilitySet() 1477 if gotAvailabilitySetName != tt.wantAvailabilitySetName { 1478 t.Errorf("AvailabilitySet() gotAvailabilitySetName = %v, wantAvailabilitySetName %v", gotAvailabilitySetName, tt.wantAvailabilitySetName) 1479 } 1480 if gotAvailabilitySetExistence != tt.wantAvailabilitySetExistence { 1481 t.Errorf("AvailabilitySet() gotAvailabilitySetExistence = %v, wantAvailabilitySetExistence %v", gotAvailabilitySetExistence, tt.wantAvailabilitySetExistence) 1482 } 1483 }) 1484 } 1485 } 1486 1487 func TestMachineScope_VMState(t *testing.T) { 1488 tests := []struct { 1489 name string 1490 machineScope MachineScope 1491 want infrav1.ProvisioningState 1492 }{ 1493 { 1494 name: "returns the VMState if present in AzureMachine status", 1495 machineScope: MachineScope{ 1496 AzureMachine: &infrav1.AzureMachine{ 1497 ObjectMeta: metav1.ObjectMeta{ 1498 Name: "machine-name", 1499 }, 1500 Status: infrav1.AzureMachineStatus{ 1501 VMState: func() *infrav1.ProvisioningState { 1502 provisioningState := infrav1.Creating 1503 return &provisioningState 1504 }(), 1505 }, 1506 }, 1507 }, 1508 want: infrav1.Creating, 1509 }, 1510 { 1511 name: "returns empty if VMState is not present in AzureMachine status", 1512 machineScope: MachineScope{ 1513 AzureMachine: &infrav1.AzureMachine{ 1514 ObjectMeta: metav1.ObjectMeta{ 1515 Name: "machine-name", 1516 }, 1517 Status: infrav1.AzureMachineStatus{}, 1518 }, 1519 }, 1520 want: "", 1521 }, 1522 } 1523 for _, tt := range tests { 1524 t.Run(tt.name, func(t *testing.T) { 1525 if got := tt.machineScope.VMState(); got != tt.want { 1526 t.Errorf("VMState() = %v, want %v", got, tt.want) 1527 } 1528 }) 1529 } 1530 } 1531 1532 func TestMachineScope_GetVMImage(t *testing.T) { 1533 mockCtrl := gomock.NewController(t) 1534 defer mockCtrl.Finish() 1535 1536 clusterMock := mock_azure.NewMockClusterScoper(mockCtrl) 1537 clusterMock.EXPECT().Location().AnyTimes() 1538 clusterMock.EXPECT().SubscriptionID().AnyTimes() 1539 clusterMock.EXPECT().CloudEnvironment().AnyTimes() 1540 clusterMock.EXPECT().Token().Return(&azidentity.DefaultAzureCredential{}).AnyTimes() 1541 svc := virtualmachineimages.Service{Client: mock_virtualmachineimages.NewMockClient(mockCtrl)} 1542 1543 tests := []struct { 1544 name string 1545 machineScope MachineScope 1546 want *infrav1.Image 1547 expectedErr string 1548 }{ 1549 { 1550 name: "returns AzureMachine image is found if present in the AzureMachine spec", 1551 machineScope: MachineScope{ 1552 AzureMachine: &infrav1.AzureMachine{ 1553 ObjectMeta: metav1.ObjectMeta{ 1554 Name: "machine-name", 1555 }, 1556 Spec: infrav1.AzureMachineSpec{ 1557 Image: &infrav1.Image{ 1558 ID: ptr.To("1"), 1559 }, 1560 }, 1561 }, 1562 }, 1563 want: &infrav1.Image{ 1564 ID: ptr.To("1"), 1565 }, 1566 expectedErr: "", 1567 }, 1568 { 1569 name: "if no image is specified and os specified is windows with version below 1.22, returns windows dockershim image", 1570 machineScope: MachineScope{ 1571 Machine: &clusterv1.Machine{ 1572 ObjectMeta: metav1.ObjectMeta{ 1573 Name: "machine-name", 1574 }, 1575 Spec: clusterv1.MachineSpec{ 1576 Version: ptr.To("1.20.1"), 1577 }, 1578 }, 1579 AzureMachine: &infrav1.AzureMachine{ 1580 ObjectMeta: metav1.ObjectMeta{ 1581 Name: "machine-name", 1582 }, 1583 Spec: infrav1.AzureMachineSpec{ 1584 OSDisk: infrav1.OSDisk{ 1585 OSType: azure.WindowsOS, 1586 }, 1587 }, 1588 }, 1589 ClusterScoper: clusterMock, 1590 }, 1591 want: func() *infrav1.Image { 1592 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.20.1", "dockershim", "") 1593 return image 1594 }(), 1595 expectedErr: "", 1596 }, 1597 { 1598 name: "if no image is specified and os specified is windows with version is 1.22+ with no annotation, returns windows containerd image", 1599 machineScope: MachineScope{ 1600 Machine: &clusterv1.Machine{ 1601 ObjectMeta: metav1.ObjectMeta{ 1602 Name: "machine-name", 1603 }, 1604 Spec: clusterv1.MachineSpec{ 1605 Version: ptr.To("1.22.1"), 1606 }, 1607 }, 1608 AzureMachine: &infrav1.AzureMachine{ 1609 ObjectMeta: metav1.ObjectMeta{ 1610 Name: "machine-name", 1611 }, 1612 Spec: infrav1.AzureMachineSpec{ 1613 OSDisk: infrav1.OSDisk{ 1614 OSType: azure.WindowsOS, 1615 }, 1616 }, 1617 }, 1618 ClusterScoper: clusterMock, 1619 }, 1620 want: func() *infrav1.Image { 1621 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.22.1", "containerd", "") 1622 return image 1623 }(), 1624 expectedErr: "", 1625 }, 1626 { 1627 name: "if no image is specified and os specified is windows with version is 1.22+ with annotation dockershim, returns windows dockershim image", 1628 machineScope: MachineScope{ 1629 Machine: &clusterv1.Machine{ 1630 ObjectMeta: metav1.ObjectMeta{ 1631 Name: "machine-name", 1632 }, 1633 Spec: clusterv1.MachineSpec{ 1634 Version: ptr.To("1.22.1"), 1635 }, 1636 }, 1637 AzureMachine: &infrav1.AzureMachine{ 1638 ObjectMeta: metav1.ObjectMeta{ 1639 Name: "machine-name", 1640 Annotations: map[string]string{ 1641 "runtime": "dockershim", 1642 }, 1643 }, 1644 Spec: infrav1.AzureMachineSpec{ 1645 OSDisk: infrav1.OSDisk{ 1646 OSType: azure.WindowsOS, 1647 }, 1648 }, 1649 }, 1650 ClusterScoper: clusterMock, 1651 }, 1652 want: func() *infrav1.Image { 1653 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.22.1", "dockershim", "") 1654 return image 1655 }(), 1656 expectedErr: "", 1657 }, 1658 { 1659 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", 1660 machineScope: MachineScope{ 1661 Machine: &clusterv1.Machine{ 1662 ObjectMeta: metav1.ObjectMeta{ 1663 Name: "machine-name", 1664 }, 1665 Spec: clusterv1.MachineSpec{ 1666 Version: ptr.To("1.21.1"), 1667 }, 1668 }, 1669 AzureMachine: &infrav1.AzureMachine{ 1670 ObjectMeta: metav1.ObjectMeta{ 1671 Name: "machine-name", 1672 Annotations: map[string]string{ 1673 "runtime": "dockershim", 1674 }, 1675 }, 1676 Spec: infrav1.AzureMachineSpec{ 1677 OSDisk: infrav1.OSDisk{ 1678 OSType: azure.WindowsOS, 1679 }, 1680 }, 1681 }, 1682 ClusterScoper: clusterMock, 1683 }, 1684 want: func() *infrav1.Image { 1685 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.21.1", "dockershim", "") 1686 return image 1687 }(), 1688 expectedErr: "", 1689 }, 1690 { 1691 name: "if no image is specified and os specified is windows with version is less and 1.22 with annotation containerd, returns error", 1692 machineScope: MachineScope{ 1693 Machine: &clusterv1.Machine{ 1694 ObjectMeta: metav1.ObjectMeta{ 1695 Name: "machine-name", 1696 }, 1697 Spec: clusterv1.MachineSpec{ 1698 Version: ptr.To("1.21.1"), 1699 }, 1700 }, 1701 AzureMachine: &infrav1.AzureMachine{ 1702 ObjectMeta: metav1.ObjectMeta{ 1703 Name: "machine-name", 1704 Annotations: map[string]string{ 1705 "runtime": "containerd", 1706 }, 1707 }, 1708 Spec: infrav1.AzureMachineSpec{ 1709 OSDisk: infrav1.OSDisk{ 1710 OSType: azure.WindowsOS, 1711 }, 1712 }, 1713 }, 1714 ClusterScoper: clusterMock, 1715 }, 1716 want: nil, 1717 expectedErr: "containerd image only supported in 1.22+", 1718 }, 1719 { 1720 name: "if no image is specified and os specified is windows with windowsServerVersion annotation set to 2019, retrurns 2019 image", 1721 machineScope: MachineScope{ 1722 Machine: &clusterv1.Machine{ 1723 ObjectMeta: metav1.ObjectMeta{ 1724 Name: "machine-name", 1725 }, 1726 Spec: clusterv1.MachineSpec{ 1727 Version: ptr.To("1.23.3"), 1728 }, 1729 }, 1730 AzureMachine: &infrav1.AzureMachine{ 1731 ObjectMeta: metav1.ObjectMeta{ 1732 Name: "machine-name", 1733 Annotations: map[string]string{ 1734 "windowsServerVersion": "windows-2019", 1735 }, 1736 }, 1737 Spec: infrav1.AzureMachineSpec{ 1738 OSDisk: infrav1.OSDisk{ 1739 OSType: azure.WindowsOS, 1740 }, 1741 }, 1742 }, 1743 ClusterScoper: clusterMock, 1744 }, 1745 want: func() *infrav1.Image { 1746 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.23.3", "", "windows-2019") 1747 return image 1748 }(), 1749 expectedErr: "", 1750 }, 1751 { 1752 name: "if no image is specified and os specified is windows with windowsServerVersion annotation set to 2022, retrurns 2022 image", 1753 machineScope: MachineScope{ 1754 Machine: &clusterv1.Machine{ 1755 ObjectMeta: metav1.ObjectMeta{ 1756 Name: "machine-name", 1757 }, 1758 Spec: clusterv1.MachineSpec{ 1759 Version: ptr.To("1.23.3"), 1760 }, 1761 }, 1762 AzureMachine: &infrav1.AzureMachine{ 1763 ObjectMeta: metav1.ObjectMeta{ 1764 Name: "machine-name", 1765 Annotations: map[string]string{ 1766 "windowsServerVersion": "windows-2022", 1767 }, 1768 }, 1769 Spec: infrav1.AzureMachineSpec{ 1770 OSDisk: infrav1.OSDisk{ 1771 OSType: azure.WindowsOS, 1772 }, 1773 }, 1774 }, 1775 ClusterScoper: clusterMock, 1776 }, 1777 want: func() *infrav1.Image { 1778 image, _ := svc.GetDefaultWindowsImage(context.TODO(), "", "1.23.3", "", "windows-2022") 1779 return image 1780 }(), 1781 expectedErr: "", 1782 }, 1783 { 1784 name: "if no image and OS is specified, returns linux image", 1785 machineScope: MachineScope{ 1786 Machine: &clusterv1.Machine{ 1787 ObjectMeta: metav1.ObjectMeta{ 1788 Name: "machine-name", 1789 }, 1790 Spec: clusterv1.MachineSpec{ 1791 Version: ptr.To("1.20.1"), 1792 }, 1793 }, 1794 AzureMachine: &infrav1.AzureMachine{ 1795 ObjectMeta: metav1.ObjectMeta{ 1796 Name: "machine-name", 1797 }, 1798 }, 1799 ClusterScoper: clusterMock, 1800 }, 1801 want: func() *infrav1.Image { 1802 image, _ := svc.GetDefaultUbuntuImage(context.TODO(), "", "1.20.1") 1803 return image 1804 }(), 1805 expectedErr: "", 1806 }, 1807 } 1808 for _, tt := range tests { 1809 t.Run(tt.name, func(t *testing.T) { 1810 gotImage, err := tt.machineScope.GetVMImage(context.TODO()) 1811 if (err == nil && tt.expectedErr != "") || (err != nil && tt.expectedErr != err.Error()) { 1812 t.Errorf("expected error %v, got %v", tt.expectedErr, err) 1813 } 1814 if !reflect.DeepEqual(gotImage, tt.want) { 1815 t.Errorf("GetVMImage(), gotImage = %v, wantImage %v", gotImage, tt.want) 1816 } 1817 }) 1818 } 1819 } 1820 1821 func TestMachineScope_NICSpecs(t *testing.T) { 1822 tests := []struct { 1823 name string 1824 machineScope MachineScope 1825 want []azure.ResourceSpecGetter 1826 }{ 1827 { 1828 name: "Node Machine with no NAT gateway and no public IP address", 1829 machineScope: MachineScope{ 1830 ClusterScoper: &ClusterScope{ 1831 AzureClients: AzureClients{ 1832 EnvironmentSettings: auth.EnvironmentSettings{ 1833 Values: map[string]string{ 1834 auth.SubscriptionID: "123", 1835 }, 1836 }, 1837 }, 1838 Cluster: &clusterv1.Cluster{ 1839 ObjectMeta: metav1.ObjectMeta{ 1840 Name: "cluster", 1841 Namespace: "default", 1842 }, 1843 }, 1844 AzureCluster: &infrav1.AzureCluster{ 1845 ObjectMeta: metav1.ObjectMeta{ 1846 Name: "cluster", 1847 Namespace: "default", 1848 OwnerReferences: []metav1.OwnerReference{ 1849 { 1850 APIVersion: "cluster.x-k8s.io/v1beta1", 1851 Kind: "Cluster", 1852 Name: "cluster", 1853 }, 1854 }, 1855 }, 1856 Spec: infrav1.AzureClusterSpec{ 1857 ResourceGroup: "my-rg", 1858 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 1859 Location: "westus", 1860 }, 1861 NetworkSpec: infrav1.NetworkSpec{ 1862 Vnet: infrav1.VnetSpec{ 1863 Name: "vnet1", 1864 ResourceGroup: "rg1", 1865 }, 1866 Subnets: []infrav1.SubnetSpec{ 1867 { 1868 SubnetClassSpec: infrav1.SubnetClassSpec{ 1869 Role: infrav1.SubnetNode, 1870 Name: "subnet1", 1871 }, 1872 }, 1873 }, 1874 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 1875 Name: "outbound-lb", 1876 BackendPool: infrav1.BackendPool{ 1877 Name: "outbound-lb-outboundBackendPool", 1878 }, 1879 }, 1880 }, 1881 }, 1882 }, 1883 }, 1884 AzureMachine: &infrav1.AzureMachine{ 1885 ObjectMeta: metav1.ObjectMeta{ 1886 Name: "machine", 1887 }, 1888 Spec: infrav1.AzureMachineSpec{ 1889 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 1890 NetworkInterfaces: []infrav1.NetworkInterface{{ 1891 SubnetName: "subnet1", 1892 PrivateIPConfigs: 1, 1893 }}, 1894 }, 1895 }, 1896 Machine: &clusterv1.Machine{ 1897 ObjectMeta: metav1.ObjectMeta{ 1898 Name: "machine", 1899 Labels: map[string]string{ 1900 // clusterv1.MachineControlPlaneLabel: "true", 1901 }, 1902 }, 1903 }, 1904 }, 1905 want: []azure.ResourceSpecGetter{ 1906 &networkinterfaces.NICSpec{ 1907 Name: "machine-name-nic", 1908 ResourceGroup: "my-rg", 1909 Location: "westus", 1910 SubscriptionID: "123", 1911 MachineName: "machine-name", 1912 SubnetName: "subnet1", 1913 IPConfigs: []networkinterfaces.IPConfig{{}}, 1914 VNetName: "vnet1", 1915 VNetResourceGroup: "rg1", 1916 PublicLBName: "outbound-lb", 1917 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 1918 PublicLBNATRuleName: "", 1919 InternalLBName: "", 1920 InternalLBAddressPoolName: "", 1921 PublicIPName: "", 1922 AcceleratedNetworking: nil, 1923 DNSServers: nil, 1924 IPv6Enabled: false, 1925 EnableIPForwarding: false, 1926 SKU: nil, 1927 ClusterName: "cluster", 1928 AdditionalTags: infrav1.Tags{ 1929 "kubernetes.io_cluster_cluster": "owned", 1930 }, 1931 }, 1932 }, 1933 }, 1934 { 1935 name: "Node Machine with no NAT gateway and no public IP address and SKU is in machine cache", 1936 machineScope: MachineScope{ 1937 ClusterScoper: &ClusterScope{ 1938 AzureClients: AzureClients{ 1939 EnvironmentSettings: auth.EnvironmentSettings{ 1940 Values: map[string]string{ 1941 auth.SubscriptionID: "123", 1942 }, 1943 }, 1944 }, 1945 Cluster: &clusterv1.Cluster{ 1946 ObjectMeta: metav1.ObjectMeta{ 1947 Name: "cluster", 1948 Namespace: "default", 1949 }, 1950 }, 1951 AzureCluster: &infrav1.AzureCluster{ 1952 ObjectMeta: metav1.ObjectMeta{ 1953 Name: "cluster", 1954 Namespace: "default", 1955 OwnerReferences: []metav1.OwnerReference{ 1956 { 1957 APIVersion: "cluster.x-k8s.io/v1beta1", 1958 Kind: "Cluster", 1959 Name: "cluster", 1960 }, 1961 }, 1962 }, 1963 Spec: infrav1.AzureClusterSpec{ 1964 ResourceGroup: "my-rg", 1965 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 1966 Location: "westus", 1967 }, 1968 NetworkSpec: infrav1.NetworkSpec{ 1969 Vnet: infrav1.VnetSpec{ 1970 Name: "vnet1", 1971 ResourceGroup: "rg1", 1972 }, 1973 Subnets: []infrav1.SubnetSpec{ 1974 { 1975 SubnetClassSpec: infrav1.SubnetClassSpec{ 1976 Role: infrav1.SubnetNode, 1977 Name: "subnet1", 1978 }, 1979 }, 1980 }, 1981 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 1982 Name: "outbound-lb", 1983 BackendPool: infrav1.BackendPool{ 1984 Name: "outbound-lb-outboundBackendPool", 1985 }, 1986 }, 1987 }, 1988 }, 1989 }, 1990 }, 1991 AzureMachine: &infrav1.AzureMachine{ 1992 ObjectMeta: metav1.ObjectMeta{ 1993 Name: "machine", 1994 }, 1995 Spec: infrav1.AzureMachineSpec{ 1996 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 1997 NetworkInterfaces: []infrav1.NetworkInterface{{ 1998 SubnetName: "subnet1", 1999 PrivateIPConfigs: 1, 2000 }}, 2001 }, 2002 }, 2003 Machine: &clusterv1.Machine{ 2004 ObjectMeta: metav1.ObjectMeta{ 2005 Name: "machine", 2006 Labels: map[string]string{ 2007 // clusterv1.MachineControlPlaneLabel: "true", 2008 }, 2009 }, 2010 }, 2011 cache: &MachineCache{ 2012 VMSKU: resourceskus.SKU{ 2013 Name: ptr.To("Standard_D2v2"), 2014 }, 2015 }, 2016 }, 2017 want: []azure.ResourceSpecGetter{ 2018 &networkinterfaces.NICSpec{ 2019 Name: "machine-name-nic", 2020 ResourceGroup: "my-rg", 2021 Location: "westus", 2022 SubscriptionID: "123", 2023 MachineName: "machine-name", 2024 SubnetName: "subnet1", 2025 IPConfigs: []networkinterfaces.IPConfig{{}}, 2026 VNetName: "vnet1", 2027 VNetResourceGroup: "rg1", 2028 PublicLBName: "outbound-lb", 2029 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 2030 PublicLBNATRuleName: "", 2031 InternalLBName: "", 2032 InternalLBAddressPoolName: "", 2033 PublicIPName: "", 2034 AcceleratedNetworking: nil, 2035 DNSServers: nil, 2036 IPv6Enabled: false, 2037 EnableIPForwarding: false, 2038 SKU: &resourceskus.SKU{ 2039 Name: ptr.To("Standard_D2v2"), 2040 }, 2041 ClusterName: "cluster", 2042 AdditionalTags: infrav1.Tags{ 2043 "kubernetes.io_cluster_cluster": "owned", 2044 }, 2045 }, 2046 }, 2047 }, 2048 { 2049 name: "Node Machine with NAT gateway", 2050 machineScope: MachineScope{ 2051 ClusterScoper: &ClusterScope{ 2052 AzureClients: AzureClients{ 2053 EnvironmentSettings: auth.EnvironmentSettings{ 2054 Values: map[string]string{ 2055 auth.SubscriptionID: "123", 2056 }, 2057 }, 2058 }, 2059 Cluster: &clusterv1.Cluster{ 2060 ObjectMeta: metav1.ObjectMeta{ 2061 Name: "cluster", 2062 Namespace: "default", 2063 }, 2064 }, 2065 AzureCluster: &infrav1.AzureCluster{ 2066 ObjectMeta: metav1.ObjectMeta{ 2067 Name: "cluster", 2068 Namespace: "default", 2069 OwnerReferences: []metav1.OwnerReference{ 2070 { 2071 APIVersion: "cluster.x-k8s.io/v1beta1", 2072 Kind: "Cluster", 2073 Name: "cluster", 2074 }, 2075 }, 2076 }, 2077 Spec: infrav1.AzureClusterSpec{ 2078 ResourceGroup: "my-rg", 2079 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2080 Location: "westus", 2081 }, 2082 NetworkSpec: infrav1.NetworkSpec{ 2083 Vnet: infrav1.VnetSpec{ 2084 Name: "vnet1", 2085 ResourceGroup: "rg1", 2086 }, 2087 Subnets: []infrav1.SubnetSpec{ 2088 { 2089 SubnetClassSpec: infrav1.SubnetClassSpec{ 2090 Role: infrav1.SubnetNode, 2091 Name: "subnet1", 2092 }, 2093 NatGateway: infrav1.NatGateway{ 2094 NatGatewayClassSpec: infrav1.NatGatewayClassSpec{ 2095 Name: "natgw", 2096 }, 2097 }, 2098 }, 2099 }, 2100 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2101 Name: "outbound-lb", 2102 }, 2103 }, 2104 }, 2105 }, 2106 }, 2107 AzureMachine: &infrav1.AzureMachine{ 2108 ObjectMeta: metav1.ObjectMeta{ 2109 Name: "machine", 2110 }, 2111 Spec: infrav1.AzureMachineSpec{ 2112 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2113 NetworkInterfaces: []infrav1.NetworkInterface{{ 2114 SubnetName: "subnet1", 2115 PrivateIPConfigs: 1, 2116 }}, 2117 }, 2118 }, 2119 Machine: &clusterv1.Machine{ 2120 ObjectMeta: metav1.ObjectMeta{ 2121 Name: "machine", 2122 Labels: map[string]string{ 2123 // clusterv1.MachineControlPlaneLabel: "true", 2124 }, 2125 }, 2126 }, 2127 }, 2128 want: []azure.ResourceSpecGetter{ 2129 &networkinterfaces.NICSpec{ 2130 Name: "machine-name-nic", 2131 ResourceGroup: "my-rg", 2132 Location: "westus", 2133 SubscriptionID: "123", 2134 MachineName: "machine-name", 2135 SubnetName: "subnet1", 2136 IPConfigs: []networkinterfaces.IPConfig{{}}, 2137 VNetName: "vnet1", 2138 VNetResourceGroup: "rg1", 2139 PublicLBName: "", 2140 PublicLBAddressPoolName: "", 2141 PublicLBNATRuleName: "", 2142 InternalLBName: "", 2143 InternalLBAddressPoolName: "", 2144 PublicIPName: "", 2145 AcceleratedNetworking: nil, 2146 DNSServers: nil, 2147 IPv6Enabled: false, 2148 EnableIPForwarding: false, 2149 SKU: nil, 2150 ClusterName: "cluster", 2151 AdditionalTags: infrav1.Tags{ 2152 "kubernetes.io_cluster_cluster": "owned", 2153 }, 2154 }, 2155 }, 2156 }, 2157 { 2158 name: "Node Machine with public IP address", 2159 machineScope: MachineScope{ 2160 ClusterScoper: &ClusterScope{ 2161 AzureClients: AzureClients{ 2162 EnvironmentSettings: auth.EnvironmentSettings{ 2163 Values: map[string]string{ 2164 auth.SubscriptionID: "123", 2165 }, 2166 }, 2167 }, 2168 Cluster: &clusterv1.Cluster{ 2169 ObjectMeta: metav1.ObjectMeta{ 2170 Name: "cluster", 2171 Namespace: "default", 2172 }, 2173 }, 2174 AzureCluster: &infrav1.AzureCluster{ 2175 ObjectMeta: metav1.ObjectMeta{ 2176 Name: "cluster", 2177 Namespace: "default", 2178 OwnerReferences: []metav1.OwnerReference{ 2179 { 2180 APIVersion: "cluster.x-k8s.io/v1beta1", 2181 Kind: "Cluster", 2182 Name: "cluster", 2183 }, 2184 }, 2185 }, 2186 Spec: infrav1.AzureClusterSpec{ 2187 ResourceGroup: "my-rg", 2188 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2189 Location: "westus", 2190 }, 2191 NetworkSpec: infrav1.NetworkSpec{ 2192 Vnet: infrav1.VnetSpec{ 2193 Name: "vnet1", 2194 ResourceGroup: "rg1", 2195 }, 2196 Subnets: []infrav1.SubnetSpec{ 2197 { 2198 SubnetClassSpec: infrav1.SubnetClassSpec{ 2199 Role: infrav1.SubnetNode, 2200 Name: "subnet1", 2201 }, 2202 }, 2203 }, 2204 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2205 Name: "outbound-lb", 2206 }, 2207 }, 2208 }, 2209 }, 2210 }, 2211 AzureMachine: &infrav1.AzureMachine{ 2212 ObjectMeta: metav1.ObjectMeta{ 2213 Name: "machine", 2214 }, 2215 Spec: infrav1.AzureMachineSpec{ 2216 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2217 NetworkInterfaces: []infrav1.NetworkInterface{{ 2218 SubnetName: "subnet1", 2219 PrivateIPConfigs: 1, 2220 }}, 2221 AllocatePublicIP: true, 2222 }, 2223 }, 2224 Machine: &clusterv1.Machine{ 2225 ObjectMeta: metav1.ObjectMeta{ 2226 Name: "machine", 2227 Labels: map[string]string{ 2228 // clusterv1.MachineControlPlaneLabel: "true", 2229 }, 2230 }, 2231 }, 2232 }, 2233 want: []azure.ResourceSpecGetter{ 2234 &networkinterfaces.NICSpec{ 2235 Name: "machine-name-nic", 2236 ResourceGroup: "my-rg", 2237 Location: "westus", 2238 SubscriptionID: "123", 2239 MachineName: "machine-name", 2240 SubnetName: "subnet1", 2241 IPConfigs: []networkinterfaces.IPConfig{{}}, 2242 VNetName: "vnet1", 2243 VNetResourceGroup: "rg1", 2244 PublicLBName: "", 2245 PublicLBAddressPoolName: "", 2246 PublicLBNATRuleName: "", 2247 InternalLBName: "", 2248 InternalLBAddressPoolName: "", 2249 PublicIPName: "pip-machine-name", 2250 AcceleratedNetworking: nil, 2251 DNSServers: nil, 2252 IPv6Enabled: false, 2253 EnableIPForwarding: false, 2254 SKU: nil, 2255 ClusterName: "cluster", 2256 AdditionalTags: infrav1.Tags{ 2257 "kubernetes.io_cluster_cluster": "owned", 2258 }, 2259 }, 2260 }, 2261 }, 2262 { 2263 name: "Control Plane Machine with private LB", 2264 machineScope: MachineScope{ 2265 ClusterScoper: &ClusterScope{ 2266 AzureClients: AzureClients{ 2267 EnvironmentSettings: auth.EnvironmentSettings{ 2268 Values: map[string]string{ 2269 auth.SubscriptionID: "123", 2270 }, 2271 }, 2272 }, 2273 Cluster: &clusterv1.Cluster{ 2274 ObjectMeta: metav1.ObjectMeta{ 2275 Name: "cluster", 2276 Namespace: "default", 2277 }, 2278 }, 2279 AzureCluster: &infrav1.AzureCluster{ 2280 ObjectMeta: metav1.ObjectMeta{ 2281 Name: "cluster", 2282 Namespace: "default", 2283 OwnerReferences: []metav1.OwnerReference{ 2284 { 2285 APIVersion: "cluster.x-k8s.io/v1beta1", 2286 Kind: "Cluster", 2287 Name: "cluster", 2288 }, 2289 }, 2290 }, 2291 Spec: infrav1.AzureClusterSpec{ 2292 ResourceGroup: "my-rg", 2293 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2294 Location: "westus", 2295 }, 2296 NetworkSpec: infrav1.NetworkSpec{ 2297 Vnet: infrav1.VnetSpec{ 2298 Name: "vnet1", 2299 ResourceGroup: "rg1", 2300 }, 2301 Subnets: []infrav1.SubnetSpec{ 2302 { 2303 SubnetClassSpec: infrav1.SubnetClassSpec{ 2304 Role: infrav1.SubnetNode, 2305 Name: "subnet1", 2306 }, 2307 }, 2308 }, 2309 APIServerLB: infrav1.LoadBalancerSpec{ 2310 Name: "api-lb", 2311 LoadBalancerClassSpec: infrav1.LoadBalancerClassSpec{ 2312 Type: infrav1.Internal, 2313 }, 2314 BackendPool: infrav1.BackendPool{ 2315 Name: "api-lb-backendPool", 2316 }, 2317 }, 2318 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2319 Name: "outbound-lb", 2320 }, 2321 }, 2322 }, 2323 }, 2324 }, 2325 AzureMachine: &infrav1.AzureMachine{ 2326 ObjectMeta: metav1.ObjectMeta{ 2327 Name: "machine", 2328 }, 2329 Spec: infrav1.AzureMachineSpec{ 2330 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2331 NetworkInterfaces: []infrav1.NetworkInterface{{ 2332 SubnetName: "subnet1", 2333 PrivateIPConfigs: 1, 2334 }}, 2335 }, 2336 }, 2337 Machine: &clusterv1.Machine{ 2338 ObjectMeta: metav1.ObjectMeta{ 2339 Name: "machine", 2340 Labels: map[string]string{ 2341 clusterv1.MachineControlPlaneLabel: "true", 2342 }, 2343 }, 2344 }, 2345 }, 2346 want: []azure.ResourceSpecGetter{ 2347 &networkinterfaces.NICSpec{ 2348 Name: "machine-name-nic", 2349 ResourceGroup: "my-rg", 2350 Location: "westus", 2351 SubscriptionID: "123", 2352 MachineName: "machine-name", 2353 SubnetName: "subnet1", 2354 IPConfigs: []networkinterfaces.IPConfig{{}}, 2355 VNetName: "vnet1", 2356 VNetResourceGroup: "rg1", 2357 PublicLBName: "", 2358 PublicLBAddressPoolName: "", 2359 PublicLBNATRuleName: "", 2360 InternalLBName: "api-lb", 2361 InternalLBAddressPoolName: "api-lb-backendPool", 2362 PublicIPName: "", 2363 AcceleratedNetworking: nil, 2364 DNSServers: nil, 2365 IPv6Enabled: false, 2366 EnableIPForwarding: false, 2367 SKU: nil, 2368 ClusterName: "cluster", 2369 AdditionalTags: infrav1.Tags{ 2370 "kubernetes.io_cluster_cluster": "owned", 2371 }, 2372 }, 2373 }, 2374 }, 2375 { 2376 name: "Control Plane Machine with public LB", 2377 machineScope: MachineScope{ 2378 ClusterScoper: &ClusterScope{ 2379 AzureClients: AzureClients{ 2380 EnvironmentSettings: auth.EnvironmentSettings{ 2381 Values: map[string]string{ 2382 auth.SubscriptionID: "123", 2383 }, 2384 }, 2385 }, 2386 Cluster: &clusterv1.Cluster{ 2387 ObjectMeta: metav1.ObjectMeta{ 2388 Name: "cluster", 2389 Namespace: "default", 2390 }, 2391 }, 2392 AzureCluster: &infrav1.AzureCluster{ 2393 ObjectMeta: metav1.ObjectMeta{ 2394 Name: "cluster", 2395 Namespace: "default", 2396 OwnerReferences: []metav1.OwnerReference{ 2397 { 2398 APIVersion: "cluster.x-k8s.io/v1beta1", 2399 Kind: "Cluster", 2400 Name: "cluster", 2401 }, 2402 }, 2403 }, 2404 Spec: infrav1.AzureClusterSpec{ 2405 ResourceGroup: "my-rg", 2406 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2407 Location: "westus", 2408 }, 2409 NetworkSpec: infrav1.NetworkSpec{ 2410 Vnet: infrav1.VnetSpec{ 2411 Name: "vnet1", 2412 ResourceGroup: "rg1", 2413 }, 2414 Subnets: []infrav1.SubnetSpec{ 2415 { 2416 SubnetClassSpec: infrav1.SubnetClassSpec{ 2417 Role: infrav1.SubnetNode, 2418 Name: "subnet1", 2419 }, 2420 }, 2421 }, 2422 APIServerLB: infrav1.LoadBalancerSpec{ 2423 Name: "api-lb", 2424 BackendPool: infrav1.BackendPool{ 2425 Name: "api-lb-backendPool", 2426 }, 2427 }, 2428 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2429 Name: "outbound-lb", 2430 }, 2431 }, 2432 }, 2433 }, 2434 }, 2435 AzureMachine: &infrav1.AzureMachine{ 2436 ObjectMeta: metav1.ObjectMeta{ 2437 Name: "machine", 2438 }, 2439 Spec: infrav1.AzureMachineSpec{ 2440 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2441 NetworkInterfaces: []infrav1.NetworkInterface{{ 2442 SubnetName: "subnet1", 2443 PrivateIPConfigs: 1, 2444 }}, 2445 }, 2446 }, 2447 Machine: &clusterv1.Machine{ 2448 ObjectMeta: metav1.ObjectMeta{ 2449 Name: "machine", 2450 Labels: map[string]string{ 2451 clusterv1.MachineControlPlaneLabel: "true", 2452 }, 2453 }, 2454 }, 2455 }, 2456 want: []azure.ResourceSpecGetter{ 2457 &networkinterfaces.NICSpec{ 2458 Name: "machine-name-nic", 2459 ResourceGroup: "my-rg", 2460 Location: "westus", 2461 SubscriptionID: "123", 2462 MachineName: "machine-name", 2463 SubnetName: "subnet1", 2464 IPConfigs: []networkinterfaces.IPConfig{{}}, 2465 VNetName: "vnet1", 2466 VNetResourceGroup: "rg1", 2467 PublicLBName: "api-lb", 2468 PublicLBAddressPoolName: "api-lb-backendPool", 2469 PublicLBNATRuleName: "machine-name", 2470 InternalLBName: "", 2471 InternalLBAddressPoolName: "", 2472 PublicIPName: "", 2473 AcceleratedNetworking: nil, 2474 DNSServers: nil, 2475 IPv6Enabled: false, 2476 EnableIPForwarding: false, 2477 SKU: nil, 2478 ClusterName: "cluster", 2479 AdditionalTags: infrav1.Tags{ 2480 "kubernetes.io_cluster_cluster": "owned", 2481 }, 2482 }, 2483 }, 2484 }, 2485 { 2486 name: "Control Plane Machine with public LB and Custom DNS Servers", 2487 machineScope: MachineScope{ 2488 ClusterScoper: &ClusterScope{ 2489 AzureClients: AzureClients{ 2490 EnvironmentSettings: auth.EnvironmentSettings{ 2491 Values: map[string]string{ 2492 auth.SubscriptionID: "123", 2493 }, 2494 }, 2495 }, 2496 Cluster: &clusterv1.Cluster{ 2497 ObjectMeta: metav1.ObjectMeta{ 2498 Name: "cluster", 2499 Namespace: "default", 2500 }, 2501 }, 2502 AzureCluster: &infrav1.AzureCluster{ 2503 ObjectMeta: metav1.ObjectMeta{ 2504 Name: "cluster", 2505 Namespace: "default", 2506 OwnerReferences: []metav1.OwnerReference{ 2507 { 2508 APIVersion: "cluster.x-k8s.io/v1beta1", 2509 Kind: "Cluster", 2510 Name: "cluster", 2511 }, 2512 }, 2513 }, 2514 Spec: infrav1.AzureClusterSpec{ 2515 ResourceGroup: "my-rg", 2516 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2517 Location: "westus", 2518 }, 2519 NetworkSpec: infrav1.NetworkSpec{ 2520 Vnet: infrav1.VnetSpec{ 2521 Name: "vnet1", 2522 ResourceGroup: "rg1", 2523 }, 2524 Subnets: []infrav1.SubnetSpec{ 2525 { 2526 SubnetClassSpec: infrav1.SubnetClassSpec{ 2527 Role: infrav1.SubnetNode, 2528 Name: "subnet1", 2529 }, 2530 }, 2531 }, 2532 APIServerLB: infrav1.LoadBalancerSpec{ 2533 Name: "api-lb", 2534 BackendPool: infrav1.BackendPool{ 2535 Name: "api-lb-backendPool", 2536 }, 2537 }, 2538 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2539 Name: "outbound-lb", 2540 }, 2541 }, 2542 }, 2543 }, 2544 }, 2545 AzureMachine: &infrav1.AzureMachine{ 2546 ObjectMeta: metav1.ObjectMeta{ 2547 Name: "machine", 2548 }, 2549 Spec: infrav1.AzureMachineSpec{ 2550 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2551 NetworkInterfaces: []infrav1.NetworkInterface{{ 2552 SubnetName: "subnet1", 2553 PrivateIPConfigs: 1, 2554 }}, 2555 DNSServers: []string{"123.123.123.123", "124.124.124.124"}, 2556 }, 2557 }, 2558 Machine: &clusterv1.Machine{ 2559 ObjectMeta: metav1.ObjectMeta{ 2560 Name: "machine", 2561 Labels: map[string]string{ 2562 clusterv1.MachineControlPlaneLabel: "true", 2563 }, 2564 }, 2565 }, 2566 }, 2567 want: []azure.ResourceSpecGetter{ 2568 &networkinterfaces.NICSpec{ 2569 Name: "machine-name-nic", 2570 ResourceGroup: "my-rg", 2571 Location: "westus", 2572 SubscriptionID: "123", 2573 MachineName: "machine-name", 2574 SubnetName: "subnet1", 2575 IPConfigs: []networkinterfaces.IPConfig{{}}, 2576 VNetName: "vnet1", 2577 VNetResourceGroup: "rg1", 2578 PublicLBName: "api-lb", 2579 PublicLBAddressPoolName: "api-lb-backendPool", 2580 PublicLBNATRuleName: "machine-name", 2581 InternalLBName: "", 2582 InternalLBAddressPoolName: "", 2583 PublicIPName: "", 2584 AcceleratedNetworking: nil, 2585 DNSServers: []string{"123.123.123.123", "124.124.124.124"}, 2586 IPv6Enabled: false, 2587 EnableIPForwarding: false, 2588 SKU: nil, 2589 ClusterName: "cluster", 2590 AdditionalTags: infrav1.Tags{ 2591 "kubernetes.io_cluster_cluster": "owned", 2592 }, 2593 }, 2594 }, 2595 }, 2596 { 2597 name: "Node Machine with multiple Network Interfaces", 2598 machineScope: MachineScope{ 2599 ClusterScoper: &ClusterScope{ 2600 AzureClients: AzureClients{ 2601 EnvironmentSettings: auth.EnvironmentSettings{ 2602 Values: map[string]string{ 2603 auth.SubscriptionID: "123", 2604 }, 2605 }, 2606 }, 2607 Cluster: &clusterv1.Cluster{ 2608 ObjectMeta: metav1.ObjectMeta{ 2609 Name: "cluster", 2610 Namespace: "default", 2611 }, 2612 }, 2613 AzureCluster: &infrav1.AzureCluster{ 2614 ObjectMeta: metav1.ObjectMeta{ 2615 Name: "cluster", 2616 Namespace: "default", 2617 OwnerReferences: []metav1.OwnerReference{ 2618 { 2619 APIVersion: "cluster.x-k8s.io/v1beta1", 2620 Kind: "Cluster", 2621 Name: "cluster", 2622 }, 2623 }, 2624 }, 2625 Spec: infrav1.AzureClusterSpec{ 2626 ResourceGroup: "my-rg", 2627 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2628 Location: "westus", 2629 }, 2630 NetworkSpec: infrav1.NetworkSpec{ 2631 Vnet: infrav1.VnetSpec{ 2632 Name: "vnet1", 2633 ResourceGroup: "rg1", 2634 }, 2635 Subnets: []infrav1.SubnetSpec{ 2636 { 2637 SubnetClassSpec: infrav1.SubnetClassSpec{ 2638 Role: infrav1.SubnetNode, 2639 Name: "subnet1", 2640 }, 2641 }, 2642 }, 2643 APIServerLB: infrav1.LoadBalancerSpec{ 2644 Name: "api-lb", 2645 }, 2646 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2647 Name: "outbound-lb", 2648 BackendPool: infrav1.BackendPool{ 2649 Name: "outbound-lb-outboundBackendPool", 2650 }, 2651 }, 2652 }, 2653 }, 2654 }, 2655 }, 2656 AzureMachine: &infrav1.AzureMachine{ 2657 ObjectMeta: metav1.ObjectMeta{ 2658 Name: "machine", 2659 }, 2660 Spec: infrav1.AzureMachineSpec{ 2661 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2662 NetworkInterfaces: []infrav1.NetworkInterface{ 2663 { 2664 SubnetName: "subnet1", 2665 AcceleratedNetworking: ptr.To(true), 2666 PrivateIPConfigs: 1, 2667 }, 2668 { 2669 SubnetName: "subnet2", 2670 AcceleratedNetworking: ptr.To(true), 2671 PrivateIPConfigs: 2, 2672 }, 2673 }, 2674 }, 2675 }, 2676 Machine: &clusterv1.Machine{ 2677 ObjectMeta: metav1.ObjectMeta{ 2678 Name: "machine", 2679 Labels: map[string]string{}, 2680 }, 2681 }, 2682 }, 2683 want: []azure.ResourceSpecGetter{ 2684 &networkinterfaces.NICSpec{ 2685 Name: "machine-name-nic-0", 2686 ResourceGroup: "my-rg", 2687 Location: "westus", 2688 SubscriptionID: "123", 2689 MachineName: "machine-name", 2690 SubnetName: "subnet1", 2691 IPConfigs: []networkinterfaces.IPConfig{{}}, 2692 VNetName: "vnet1", 2693 VNetResourceGroup: "rg1", 2694 PublicLBName: "outbound-lb", 2695 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 2696 PublicLBNATRuleName: "", 2697 InternalLBName: "", 2698 InternalLBAddressPoolName: "", 2699 PublicIPName: "", 2700 AcceleratedNetworking: ptr.To(true), 2701 IPv6Enabled: false, 2702 EnableIPForwarding: false, 2703 SKU: nil, 2704 ClusterName: "cluster", 2705 AdditionalTags: map[string]string{ 2706 "kubernetes.io_cluster_cluster": "owned", 2707 }, 2708 }, 2709 &networkinterfaces.NICSpec{ 2710 Name: "machine-name-nic-1", 2711 ResourceGroup: "my-rg", 2712 Location: "westus", 2713 SubscriptionID: "123", 2714 MachineName: "machine-name", 2715 SubnetName: "subnet2", 2716 IPConfigs: []networkinterfaces.IPConfig{{}, {}}, 2717 VNetName: "vnet1", 2718 VNetResourceGroup: "rg1", 2719 PublicLBName: "", 2720 PublicLBAddressPoolName: "", 2721 PublicLBNATRuleName: "", 2722 InternalLBName: "", 2723 InternalLBAddressPoolName: "", 2724 PublicIPName: "", 2725 AcceleratedNetworking: ptr.To(true), 2726 IPv6Enabled: false, 2727 EnableIPForwarding: false, 2728 SKU: nil, 2729 ClusterName: "cluster", 2730 AdditionalTags: map[string]string{ 2731 "kubernetes.io_cluster_cluster": "owned", 2732 }, 2733 }, 2734 }, 2735 }, 2736 { 2737 name: "Node Machine with multiple Network Interfaces and Public IP Allocation enabled", 2738 machineScope: MachineScope{ 2739 ClusterScoper: &ClusterScope{ 2740 AzureClients: AzureClients{ 2741 EnvironmentSettings: auth.EnvironmentSettings{ 2742 Values: map[string]string{ 2743 auth.SubscriptionID: "123", 2744 }, 2745 }, 2746 }, 2747 Cluster: &clusterv1.Cluster{ 2748 ObjectMeta: metav1.ObjectMeta{ 2749 Name: "cluster", 2750 Namespace: "default", 2751 }, 2752 }, 2753 AzureCluster: &infrav1.AzureCluster{ 2754 ObjectMeta: metav1.ObjectMeta{ 2755 Name: "cluster", 2756 Namespace: "default", 2757 OwnerReferences: []metav1.OwnerReference{ 2758 { 2759 APIVersion: "cluster.x-k8s.io/v1beta1", 2760 Kind: "Cluster", 2761 Name: "cluster", 2762 }, 2763 }, 2764 }, 2765 Spec: infrav1.AzureClusterSpec{ 2766 ResourceGroup: "my-rg", 2767 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2768 Location: "westus", 2769 }, 2770 NetworkSpec: infrav1.NetworkSpec{ 2771 Vnet: infrav1.VnetSpec{ 2772 Name: "vnet1", 2773 ResourceGroup: "rg1", 2774 }, 2775 Subnets: []infrav1.SubnetSpec{ 2776 { 2777 SubnetClassSpec: infrav1.SubnetClassSpec{ 2778 Role: infrav1.SubnetNode, 2779 Name: "subnet1", 2780 }, 2781 }, 2782 }, 2783 APIServerLB: infrav1.LoadBalancerSpec{ 2784 Name: "api-lb", 2785 }, 2786 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2787 Name: "outbound-lb", 2788 }, 2789 }, 2790 }, 2791 }, 2792 }, 2793 AzureMachine: &infrav1.AzureMachine{ 2794 ObjectMeta: metav1.ObjectMeta{ 2795 Name: "machine", 2796 }, 2797 Spec: infrav1.AzureMachineSpec{ 2798 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2799 AllocatePublicIP: true, 2800 NetworkInterfaces: []infrav1.NetworkInterface{ 2801 { 2802 SubnetName: "subnet1", 2803 AcceleratedNetworking: ptr.To(true), 2804 PrivateIPConfigs: 1, 2805 }, 2806 { 2807 SubnetName: "subnet2", 2808 AcceleratedNetworking: ptr.To(true), 2809 PrivateIPConfigs: 2, 2810 }, 2811 }, 2812 }, 2813 }, 2814 Machine: &clusterv1.Machine{ 2815 ObjectMeta: metav1.ObjectMeta{ 2816 Name: "machine", 2817 Labels: map[string]string{}, 2818 }, 2819 }, 2820 }, 2821 want: []azure.ResourceSpecGetter{ 2822 &networkinterfaces.NICSpec{ 2823 Name: "machine-name-nic-0", 2824 ResourceGroup: "my-rg", 2825 Location: "westus", 2826 SubscriptionID: "123", 2827 MachineName: "machine-name", 2828 SubnetName: "subnet1", 2829 IPConfigs: []networkinterfaces.IPConfig{{}}, 2830 VNetName: "vnet1", 2831 VNetResourceGroup: "rg1", 2832 PublicLBName: "", 2833 PublicLBAddressPoolName: "", 2834 PublicLBNATRuleName: "", 2835 InternalLBName: "", 2836 InternalLBAddressPoolName: "", 2837 PublicIPName: "pip-machine-name", 2838 AcceleratedNetworking: ptr.To(true), 2839 IPv6Enabled: false, 2840 EnableIPForwarding: false, 2841 SKU: nil, 2842 ClusterName: "cluster", 2843 AdditionalTags: map[string]string{ 2844 "kubernetes.io_cluster_cluster": "owned", 2845 }, 2846 }, 2847 &networkinterfaces.NICSpec{ 2848 Name: "machine-name-nic-1", 2849 ResourceGroup: "my-rg", 2850 Location: "westus", 2851 SubscriptionID: "123", 2852 MachineName: "machine-name", 2853 SubnetName: "subnet2", 2854 IPConfigs: []networkinterfaces.IPConfig{{}, {}}, 2855 VNetName: "vnet1", 2856 VNetResourceGroup: "rg1", 2857 PublicLBName: "", 2858 PublicLBAddressPoolName: "", 2859 PublicLBNATRuleName: "", 2860 InternalLBName: "", 2861 InternalLBAddressPoolName: "", 2862 PublicIPName: "", 2863 AcceleratedNetworking: ptr.To(true), 2864 IPv6Enabled: false, 2865 EnableIPForwarding: false, 2866 SKU: nil, 2867 ClusterName: "cluster", 2868 AdditionalTags: map[string]string{ 2869 "kubernetes.io_cluster_cluster": "owned", 2870 }, 2871 }, 2872 }, 2873 }, 2874 { 2875 name: "Node Machine with multiple IPConfigs", 2876 machineScope: MachineScope{ 2877 ClusterScoper: &ClusterScope{ 2878 AzureClients: AzureClients{ 2879 EnvironmentSettings: auth.EnvironmentSettings{ 2880 Values: map[string]string{ 2881 auth.SubscriptionID: "123", 2882 }, 2883 }, 2884 }, 2885 Cluster: &clusterv1.Cluster{ 2886 ObjectMeta: metav1.ObjectMeta{ 2887 Name: "cluster", 2888 Namespace: "default", 2889 }, 2890 }, 2891 AzureCluster: &infrav1.AzureCluster{ 2892 ObjectMeta: metav1.ObjectMeta{ 2893 Name: "cluster", 2894 Namespace: "default", 2895 OwnerReferences: []metav1.OwnerReference{ 2896 { 2897 APIVersion: "cluster.x-k8s.io/v1beta1", 2898 Kind: "Cluster", 2899 Name: "cluster", 2900 }, 2901 }, 2902 }, 2903 Spec: infrav1.AzureClusterSpec{ 2904 ResourceGroup: "my-rg", 2905 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 2906 Location: "westus", 2907 }, 2908 NetworkSpec: infrav1.NetworkSpec{ 2909 Vnet: infrav1.VnetSpec{ 2910 Name: "vnet1", 2911 ResourceGroup: "rg1", 2912 }, 2913 Subnets: []infrav1.SubnetSpec{ 2914 { 2915 SubnetClassSpec: infrav1.SubnetClassSpec{ 2916 Role: infrav1.SubnetNode, 2917 Name: "subnet1", 2918 }, 2919 }, 2920 }, 2921 APIServerLB: infrav1.LoadBalancerSpec{ 2922 Name: "api-lb", 2923 }, 2924 NodeOutboundLB: &infrav1.LoadBalancerSpec{ 2925 Name: "outbound-lb", 2926 BackendPool: infrav1.BackendPool{ 2927 Name: "outbound-lb-outboundBackendPool", 2928 }, 2929 }, 2930 }, 2931 }, 2932 }, 2933 }, 2934 AzureMachine: &infrav1.AzureMachine{ 2935 ObjectMeta: metav1.ObjectMeta{ 2936 Name: "machine", 2937 }, 2938 Spec: infrav1.AzureMachineSpec{ 2939 ProviderID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/virtualMachines/machine-name"), 2940 NetworkInterfaces: []infrav1.NetworkInterface{ 2941 { 2942 SubnetName: "subnet1", 2943 AcceleratedNetworking: ptr.To(true), 2944 PrivateIPConfigs: 10, 2945 }, 2946 }, 2947 }, 2948 }, 2949 Machine: &clusterv1.Machine{ 2950 ObjectMeta: metav1.ObjectMeta{ 2951 Name: "machine", 2952 Labels: map[string]string{}, 2953 }, 2954 }, 2955 }, 2956 want: []azure.ResourceSpecGetter{ 2957 &networkinterfaces.NICSpec{ 2958 Name: "machine-name-nic", 2959 ResourceGroup: "my-rg", 2960 Location: "westus", 2961 SubscriptionID: "123", 2962 MachineName: "machine-name", 2963 SubnetName: "subnet1", 2964 IPConfigs: []networkinterfaces.IPConfig{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, 2965 VNetName: "vnet1", 2966 VNetResourceGroup: "rg1", 2967 PublicLBName: "outbound-lb", 2968 PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", 2969 PublicLBNATRuleName: "", 2970 InternalLBName: "", 2971 InternalLBAddressPoolName: "", 2972 PublicIPName: "", 2973 AcceleratedNetworking: ptr.To(true), 2974 IPv6Enabled: false, 2975 EnableIPForwarding: false, 2976 SKU: nil, 2977 ClusterName: "cluster", 2978 AdditionalTags: map[string]string{ 2979 "kubernetes.io_cluster_cluster": "owned", 2980 }, 2981 }, 2982 }, 2983 }, 2984 } 2985 for _, tt := range tests { 2986 t.Run(tt.name, func(t *testing.T) { 2987 g := NewWithT(t) 2988 gotNicSpecs := tt.machineScope.NICSpecs() 2989 if !reflect.DeepEqual(gotNicSpecs, tt.want) { 2990 g.Expect(gotNicSpecs).To(BeEquivalentTo(tt.want)) 2991 t.Errorf("NICSpecs(), gotNicSpecs = %s, want %s", specArrayToString(gotNicSpecs), specArrayToString(tt.want)) 2992 } 2993 }) 2994 } 2995 } 2996 2997 func TestDiskSpecs(t *testing.T) { 2998 testcases := []struct { 2999 name string 3000 machineScope MachineScope 3001 want []azure.ResourceSpecGetter 3002 }{ 3003 { 3004 name: "only os disk", 3005 machineScope: MachineScope{ 3006 ClusterScoper: &ClusterScope{ 3007 Cluster: &clusterv1.Cluster{ 3008 ObjectMeta: metav1.ObjectMeta{ 3009 Name: "cluster", 3010 }, 3011 }, 3012 AzureCluster: &infrav1.AzureCluster{ 3013 ObjectMeta: metav1.ObjectMeta{ 3014 Name: "cluster", 3015 }, 3016 Spec: infrav1.AzureClusterSpec{ 3017 ResourceGroup: "my-rg", 3018 }, 3019 }, 3020 }, 3021 AzureMachine: &infrav1.AzureMachine{ 3022 ObjectMeta: metav1.ObjectMeta{ 3023 Name: "my-azure-machine", 3024 }, 3025 Spec: infrav1.AzureMachineSpec{ 3026 OSDisk: infrav1.OSDisk{ 3027 DiskSizeGB: ptr.To[int32](30), 3028 OSType: "Linux", 3029 }, 3030 }, 3031 }, 3032 Machine: &clusterv1.Machine{ 3033 ObjectMeta: metav1.ObjectMeta{ 3034 Name: "machine", 3035 }, 3036 }, 3037 }, 3038 want: []azure.ResourceSpecGetter{ 3039 &disks.DiskSpec{ 3040 Name: "my-azure-machine_OSDisk", 3041 ResourceGroup: "my-rg", 3042 }, 3043 }, 3044 }, 3045 { 3046 name: "os and data disks", 3047 machineScope: MachineScope{ 3048 ClusterScoper: &ClusterScope{ 3049 Cluster: &clusterv1.Cluster{ 3050 ObjectMeta: metav1.ObjectMeta{ 3051 Name: "cluster", 3052 }, 3053 }, 3054 AzureCluster: &infrav1.AzureCluster{ 3055 ObjectMeta: metav1.ObjectMeta{ 3056 Name: "cluster", 3057 }, 3058 Spec: infrav1.AzureClusterSpec{ 3059 ResourceGroup: "my-rg", 3060 }, 3061 }, 3062 }, 3063 AzureMachine: &infrav1.AzureMachine{ 3064 ObjectMeta: metav1.ObjectMeta{ 3065 Name: "my-azure-machine", 3066 }, 3067 Spec: infrav1.AzureMachineSpec{ 3068 OSDisk: infrav1.OSDisk{ 3069 DiskSizeGB: ptr.To[int32](30), 3070 OSType: "Linux", 3071 }, 3072 DataDisks: []infrav1.DataDisk{ 3073 { 3074 NameSuffix: "etcddisk", 3075 }, 3076 }, 3077 }, 3078 }, 3079 Machine: &clusterv1.Machine{ 3080 ObjectMeta: metav1.ObjectMeta{ 3081 Name: "machine", 3082 }, 3083 }, 3084 }, 3085 want: []azure.ResourceSpecGetter{ 3086 &disks.DiskSpec{ 3087 Name: "my-azure-machine_OSDisk", 3088 ResourceGroup: "my-rg", 3089 }, 3090 &disks.DiskSpec{ 3091 Name: "my-azure-machine_etcddisk", 3092 ResourceGroup: "my-rg", 3093 }, 3094 }, 3095 }, { 3096 name: "os and multiple data disks", 3097 machineScope: MachineScope{ 3098 ClusterScoper: &ClusterScope{ 3099 Cluster: &clusterv1.Cluster{ 3100 ObjectMeta: metav1.ObjectMeta{ 3101 Name: "cluster", 3102 }, 3103 }, 3104 AzureCluster: &infrav1.AzureCluster{ 3105 ObjectMeta: metav1.ObjectMeta{ 3106 Name: "cluster", 3107 }, 3108 Spec: infrav1.AzureClusterSpec{ 3109 ResourceGroup: "my-rg", 3110 }, 3111 }, 3112 }, 3113 AzureMachine: &infrav1.AzureMachine{ 3114 ObjectMeta: metav1.ObjectMeta{ 3115 Name: "my-azure-machine", 3116 }, 3117 Spec: infrav1.AzureMachineSpec{ 3118 OSDisk: infrav1.OSDisk{ 3119 DiskSizeGB: ptr.To[int32](30), 3120 OSType: "Linux", 3121 }, 3122 DataDisks: []infrav1.DataDisk{ 3123 { 3124 NameSuffix: "etcddisk", 3125 }, 3126 { 3127 NameSuffix: "otherdisk", 3128 }, 3129 }, 3130 }, 3131 }, 3132 Machine: &clusterv1.Machine{ 3133 ObjectMeta: metav1.ObjectMeta{ 3134 Name: "machine", 3135 }, 3136 }, 3137 }, 3138 want: []azure.ResourceSpecGetter{ 3139 &disks.DiskSpec{ 3140 Name: "my-azure-machine_OSDisk", 3141 ResourceGroup: "my-rg", 3142 }, 3143 &disks.DiskSpec{ 3144 Name: "my-azure-machine_etcddisk", 3145 ResourceGroup: "my-rg", 3146 }, 3147 &disks.DiskSpec{ 3148 Name: "my-azure-machine_otherdisk", 3149 ResourceGroup: "my-rg", 3150 }, 3151 }, 3152 }, 3153 } 3154 3155 for _, tt := range testcases { 3156 tt := tt 3157 t.Run(tt.name, func(t *testing.T) { 3158 g := NewWithT(t) 3159 3160 t.Parallel() 3161 result := tt.machineScope.DiskSpecs() 3162 g.Expect(result).To(BeEquivalentTo(tt.want)) 3163 }) 3164 } 3165 } 3166 3167 func TestMachineScope_GetCapacityReservationGroupID(t *testing.T) { 3168 tests := []struct { 3169 name string 3170 machineScope MachineScope 3171 want string 3172 }{ 3173 { 3174 name: "returns the entire capacity reservation group ID", 3175 machineScope: MachineScope{ 3176 AzureMachine: &infrav1.AzureMachine{ 3177 ObjectMeta: metav1.ObjectMeta{ 3178 Name: "machine-name", 3179 }, 3180 Spec: infrav1.AzureMachineSpec{ 3181 CapacityReservationGroupID: ptr.To("azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/capacityReservationGroups/capacity-reservation-group-name"), 3182 }, 3183 }, 3184 }, 3185 want: "azure:///subscriptions/1234-5678/resourceGroups/my-cluster/providers/Microsoft.Compute/capacityReservationGroups/capacity-reservation-group-name", 3186 }, 3187 { 3188 name: "returns empty if capacity reservation group ID is empty", 3189 machineScope: MachineScope{ 3190 AzureMachine: &infrav1.AzureMachine{ 3191 ObjectMeta: metav1.ObjectMeta{ 3192 Name: "machine-name", 3193 }, 3194 Spec: infrav1.AzureMachineSpec{ 3195 CapacityReservationGroupID: ptr.To(""), 3196 }, 3197 }, 3198 }, 3199 want: "", 3200 }, 3201 } 3202 for _, tt := range tests { 3203 t.Run(tt.name, func(t *testing.T) { 3204 got := tt.machineScope.GetCapacityReservationGroupID() 3205 if got != tt.want { 3206 t.Errorf("MachineScope.GetCapacityReservationGroupID() = %v, want %v", got, tt.want) 3207 } 3208 }) 3209 } 3210 }