diff --git a/azure/scope/machine_test.go b/azure/scope/machine_test.go index 9195e2ff29c..9171ea265ae 100644 --- a/azure/scope/machine_test.go +++ b/azure/scope/machine_test.go @@ -2078,6 +2078,238 @@ func TestMachineScope_NICSpecs(t *testing.T) { }, }, }, + { + name: "Node Machine with multiple Network Interfaces", + machineScope: MachineScope{ + ClusterScoper: &ClusterScope{ + AzureClients: AzureClients{ + EnvironmentSettings: auth.EnvironmentSettings{ + Values: map[string]string{ + auth.SubscriptionID: "123", + }, + }, + }, + Cluster: &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster", + Namespace: "default", + }, + }, + AzureCluster: &infrav1.AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster", + Namespace: "default", + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "cluster.x-k8s.io/v1beta1", + Kind: "Cluster", + Name: "cluster", + }, + }, + }, + Spec: infrav1.AzureClusterSpec{ + ResourceGroup: "my-rg", + AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ + Location: "westus", + }, + NetworkSpec: infrav1.NetworkSpec{ + Vnet: infrav1.VnetSpec{ + Name: "vnet1", + ResourceGroup: "rg1", + }, + Subnets: []infrav1.SubnetSpec{ + { + SubnetClassSpec: infrav1.SubnetClassSpec{ + Role: infrav1.SubnetNode, + }, + Name: "subnet1", + }, + }, + APIServerLB: infrav1.LoadBalancerSpec{ + Name: "api-lb", + }, + NodeOutboundLB: &infrav1.LoadBalancerSpec{ + Name: "outbound-lb", + }, + }, + }, + }, + }, + AzureMachine: &infrav1.AzureMachine{ + ObjectMeta: metav1.ObjectMeta{ + Name: "machine", + }, + Spec: infrav1.AzureMachineSpec{ + ProviderID: to.StringPtr("azure://compute/virtual-machines/machine-name"), + NetworkInterfaces: []infrav1.AzureNetworkInterface{ + { + SubnetName: "subnet1", + AcceleratedNetworking: pointer.Bool(true), + IPConfigs: []infrav1.AzureIPConfig{{}}, + }, + { + SubnetName: "subnet2", + AcceleratedNetworking: pointer.Bool(true), + IPConfigs: []infrav1.AzureIPConfig{{}}, + }, + }, + }, + }, + Machine: &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Name: "machine", + Labels: map[string]string{}, + }, + }, + }, + want: []azure.ResourceSpecGetter{ + &networkinterfaces.NICSpec{ + Name: "machine-name-nic-0", + ResourceGroup: "my-rg", + Location: "westus", + SubscriptionID: "123", + MachineName: "machine-name", + SubnetName: "subnet1", + IPConfigs: []networkinterfaces.IPConfig{{}}, + VNetName: "vnet1", + VNetResourceGroup: "rg1", + PublicLBName: "outbound-lb", + PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", + PublicLBNATRuleName: "", + InternalLBName: "", + InternalLBAddressPoolName: "", + PublicIPName: "", + AcceleratedNetworking: pointer.Bool(true), + IPv6Enabled: false, + EnableIPForwarding: false, + SKU: nil, + }, + &networkinterfaces.NICSpec{ + Name: "machine-name-nic-1", + ResourceGroup: "my-rg", + Location: "westus", + SubscriptionID: "123", + MachineName: "machine-name", + SubnetName: "subnet2", + IPConfigs: []networkinterfaces.IPConfig{{}}, + VNetName: "vnet1", + VNetResourceGroup: "rg1", + PublicLBName: "", + PublicLBAddressPoolName: "", + PublicLBNATRuleName: "", + InternalLBName: "", + InternalLBAddressPoolName: "", + PublicIPName: "", + AcceleratedNetworking: pointer.Bool(true), + IPv6Enabled: false, + EnableIPForwarding: false, + SKU: nil, + }, + }, + }, + { + name: "Node Machine with multiple IPConfigs", + machineScope: MachineScope{ + ClusterScoper: &ClusterScope{ + AzureClients: AzureClients{ + EnvironmentSettings: auth.EnvironmentSettings{ + Values: map[string]string{ + auth.SubscriptionID: "123", + }, + }, + }, + Cluster: &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster", + Namespace: "default", + }, + }, + AzureCluster: &infrav1.AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster", + Namespace: "default", + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "cluster.x-k8s.io/v1beta1", + Kind: "Cluster", + Name: "cluster", + }, + }, + }, + Spec: infrav1.AzureClusterSpec{ + ResourceGroup: "my-rg", + AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ + Location: "westus", + }, + NetworkSpec: infrav1.NetworkSpec{ + Vnet: infrav1.VnetSpec{ + Name: "vnet1", + ResourceGroup: "rg1", + }, + Subnets: []infrav1.SubnetSpec{ + { + SubnetClassSpec: infrav1.SubnetClassSpec{ + Role: infrav1.SubnetNode, + }, + Name: "subnet1", + }, + }, + APIServerLB: infrav1.LoadBalancerSpec{ + Name: "api-lb", + }, + NodeOutboundLB: &infrav1.LoadBalancerSpec{ + Name: "outbound-lb", + }, + }, + }, + }, + }, + AzureMachine: &infrav1.AzureMachine{ + ObjectMeta: metav1.ObjectMeta{ + Name: "machine", + }, + Spec: infrav1.AzureMachineSpec{ + ProviderID: to.StringPtr("azure://compute/virtual-machines/machine-name"), + NetworkInterfaces: []infrav1.AzureNetworkInterface{ + { + SubnetName: "subnet1", + AcceleratedNetworking: pointer.Bool(true), + IPConfigs: []infrav1.AzureIPConfig{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, + }, + }, + }, + }, + Machine: &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Name: "machine", + Labels: map[string]string{}, + }, + }, + }, + want: []azure.ResourceSpecGetter{ + &networkinterfaces.NICSpec{ + Name: "machine-name-nic-0", + ResourceGroup: "my-rg", + Location: "westus", + SubscriptionID: "123", + MachineName: "machine-name", + SubnetName: "subnet1", + IPConfigs: []networkinterfaces.IPConfig{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, + VNetName: "vnet1", + VNetResourceGroup: "rg1", + PublicLBName: "outbound-lb", + PublicLBAddressPoolName: "outbound-lb-outboundBackendPool", + PublicLBNATRuleName: "", + InternalLBName: "", + InternalLBAddressPoolName: "", + PublicIPName: "", + AcceleratedNetworking: pointer.Bool(true), + IPv6Enabled: false, + EnableIPForwarding: false, + SKU: nil, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/azure/services/scalesets/scalesets.go b/azure/services/scalesets/scalesets.go index 5028ab1a7fc..340ea2776ea 100644 --- a/azure/services/scalesets/scalesets.go +++ b/azure/services/scalesets/scalesets.go @@ -485,10 +485,22 @@ func (s *Service) buildVMSSFromSpec(ctx context.Context, vmssSpec azure.ScaleSet ipconfigs := []compute.VirtualMachineScaleSetIPConfiguration{} for j := range n.IPConfigs { ipconfig := compute.VirtualMachineScaleSetIPConfiguration{ - VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{}, + Name: to.StringPtr(fmt.Sprintf("ipConfig%v", j)), + VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{ + PrivateIPAddressVersion: compute.IPVersionIPv4, + Subnet: &compute.APIEntityReference{ + ID: to.StringPtr(azure.SubnetID(s.Scope.SubscriptionID(), vmssSpec.VNetResourceGroup, vmssSpec.VNetName, n.SubnetName)), + }, + }, } if j == 0 { ipconfig.Primary = to.BoolPtr(true) + if i == 0 { + // only set Load Balancer Backend Address Pool on primary nic/ipconfig + ipconfig.LoadBalancerBackendAddressPools = &backendAddressPools + } + } else { + ipconfig.Primary = to.BoolPtr(false) } ipconfig.Subnet = &compute.APIEntityReference{ ID: to.StringPtr(azure.SubnetID(s.Scope.SubscriptionID(), vmssSpec.VNetResourceGroup, vmssSpec.VNetName, n.SubnetName)), diff --git a/azure/services/scalesets/scalesets_test.go b/azure/services/scalesets/scalesets_test.go index 283dc81bc8f..aaab2f973b0 100644 --- a/azure/services/scalesets/scalesets_test.go +++ b/azure/services/scalesets/scalesets_test.go @@ -255,6 +255,79 @@ func TestReconcileVMSS(t *testing.T) { setupCreatingSucceededExpectations(s, m, newDefaultExistingVMSS("VM_SIZE_AN"), putFuture) }, }, + { + name: "should start creating vmss with custom networking when specified", + expectedError: "failed to get VMSS my-vmss after create or update: failed to get result from future: operation type PUT on Azure resource my-rg/my-vmss is not done", + expect: func(g *WithT, s *mock_scalesets.MockScaleSetScopeMockRecorder, m *mock_scalesets.MockClientMockRecorder) { + spec := newDefaultVMSSSpec() + spec.DataDisks = append(spec.DataDisks, infrav1.DataDisk{ + NameSuffix: "my_disk_with_ultra_disks", + DiskSizeGB: 128, + Lun: to.Int32Ptr(3), + ManagedDisk: &infrav1.ManagedDiskParameters{ + StorageAccountType: "UltraSSD_LRS", + }, + }) + spec.NetworkInterfaces = []infrav1.AzureNetworkInterface{ + { + SubnetName: "my-subnet", + IPConfigs: []infrav1.AzureIPConfig{{}}, + AcceleratedNetworking: pointer.Bool(true), + }, + { + SubnetName: "subnet2", + IPConfigs: []infrav1.AzureIPConfig{{}, {}}, + AcceleratedNetworking: pointer.Bool(true), + }, + } + s.ScaleSetSpec().Return(spec).AnyTimes() + setupDefaultVMSSStartCreatingExpectations(s, m) + vmss := newDefaultVMSS("VM_SIZE") + vmss.VirtualMachineScaleSetProperties.AdditionalCapabilities = &compute.AdditionalCapabilities{UltraSSDEnabled: pointer.Bool(true)} + netConfigs := vmss.VirtualMachineScaleSetProperties.VirtualMachineProfile.NetworkProfile.NetworkInterfaceConfigurations + (*netConfigs)[0].Name = to.StringPtr("my-vmss-0") + (*netConfigs)[0].EnableIPForwarding = nil + nic1IPConfigs := (*netConfigs)[0].IPConfigurations + (*nic1IPConfigs)[0].Name = to.StringPtr("ipConfig0") + (*nic1IPConfigs)[0].PrivateIPAddressVersion = compute.IPVersionIPv4 + (*netConfigs)[0].EnableAcceleratedNetworking = to.BoolPtr(true) + vmssIPConfigs := []compute.VirtualMachineScaleSetIPConfiguration{ + { + Name: to.StringPtr("ipConfig0"), + VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{ + Primary: to.BoolPtr(true), + PrivateIPAddressVersion: compute.IPVersionIPv4, + Subnet: &compute.APIEntityReference{ + ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/subnet2"), + }, + //LoadBalancerBackendAddressPools: &[]compute.SubResource{{ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/loadBalancers/capz-lb/backendAddressPools/backendPool")}}, + }, + }, + { + Name: to.StringPtr("ipConfig1"), + VirtualMachineScaleSetIPConfigurationProperties: &compute.VirtualMachineScaleSetIPConfigurationProperties{ + Primary: to.BoolPtr(false), + PrivateIPAddressVersion: compute.IPVersionIPv4, + Subnet: &compute.APIEntityReference{ + ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/virtualNetworks/my-vnet/subnets/subnet2"), + }, + //LoadBalancerBackendAddressPools: &[]compute.SubResource{{ID: to.StringPtr("/subscriptions/123/resourceGroups/my-rg/providers/Microsoft.Network/loadBalancers/capz-lb/backendAddressPools/backendPool")}}, + }, + }, + } + *netConfigs = append(*netConfigs, compute.VirtualMachineScaleSetNetworkConfiguration{ + Name: to.StringPtr("my-vmss-1"), + VirtualMachineScaleSetNetworkConfigurationProperties: &compute.VirtualMachineScaleSetNetworkConfigurationProperties{ + Primary: nil, + EnableAcceleratedNetworking: to.BoolPtr(true), + IPConfigurations: &vmssIPConfigs, + }, + }) + m.CreateOrUpdateAsync(gomockinternal.AContext(), defaultResourceGroup, defaultVMSSName, gomockinternal.DiffEq(vmss)). + Return(putFuture, nil) + setupCreatingSucceededExpectations(s, m, newDefaultExistingVMSS("VM_SIZE"), putFuture) + }, + }, { name: "should start creating a vmss with spot vm", expectedError: "failed to get VMSS my-vmss after create or update: failed to get result from future: operation type PUT on Azure resource my-rg/my-vmss is not done",