From 379123e2f61acd08b076ad7771b50f0efd7a1155 Mon Sep 17 00:00:00 2001 From: Alexander Demichev Date: Mon, 11 Jul 2022 10:38:05 +0200 Subject: [PATCH] Allow to set custom backend pool names for load balancers Currently, there is no way to specify the backend pool name. This PR makes LB's backend pool name customizable. The changes introduced in this PR are backward compatible and should not break existing deployments. --- api/v1alpha3/zz_generated.conversion.go | 1 + api/v1alpha4/azurecluster_conversion.go | 13 + api/v1alpha4/zz_generated.conversion.go | 1 + api/v1beta1/azurecluster_default.go | 26 +- api/v1beta1/azurecluster_default_test.go | 225 +++++++++++++++++- api/v1beta1/types.go | 11 + api/v1beta1/zz_generated.deepcopy.go | 16 ++ azure/scope/cluster.go | 6 +- azure/scope/cluster_test.go | 144 +++++++++++ ...ucture.cluster.x-k8s.io_azureclusters.yaml | 30 +++ 10 files changed, 468 insertions(+), 5 deletions(-) diff --git a/api/v1alpha3/zz_generated.conversion.go b/api/v1alpha3/zz_generated.conversion.go index a982e6d06be..6ac37dfa03f 100644 --- a/api/v1alpha3/zz_generated.conversion.go +++ b/api/v1alpha3/zz_generated.conversion.go @@ -1369,6 +1369,7 @@ func autoConvert_v1beta1_LoadBalancerSpec_To_v1alpha3_LoadBalancerSpec(in *v1bet out.FrontendIPs = nil } // WARNING: in.FrontendIPsCount requires manual conversion: does not exist in peer-type + // WARNING: in.BackendPool requires manual conversion: does not exist in peer-type // WARNING: in.LoadBalancerClassSpec requires manual conversion: does not exist in peer-type return nil } diff --git a/api/v1alpha4/azurecluster_conversion.go b/api/v1alpha4/azurecluster_conversion.go index 53ed68846f6..980b12c9fbb 100644 --- a/api/v1alpha4/azurecluster_conversion.go +++ b/api/v1alpha4/azurecluster_conversion.go @@ -91,6 +91,19 @@ func (src *AzureCluster) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.BastionSpec.AzureBastion.Subnet.ServiceEndpoints = restored.Spec.BastionSpec.AzureBastion.Subnet.ServiceEndpoints } + // Restore load balancers' backend pool name + if restored.Spec.NetworkSpec.APIServerLB.BackendPool.Name != "" { + dst.Spec.NetworkSpec.APIServerLB.BackendPool.Name = restored.Spec.NetworkSpec.APIServerLB.BackendPool.Name + } + + if restored.Spec.NetworkSpec.NodeOutboundLB != nil && restored.Spec.NetworkSpec.NodeOutboundLB.BackendPool.Name != "" { + dst.Spec.NetworkSpec.NodeOutboundLB.BackendPool.Name = restored.Spec.NetworkSpec.NodeOutboundLB.BackendPool.Name + } + + if restored.Spec.NetworkSpec.ControlPlaneOutboundLB != nil && restored.Spec.NetworkSpec.ControlPlaneOutboundLB.BackendPool.Name != "" { + dst.Spec.NetworkSpec.ControlPlaneOutboundLB.BackendPool.Name = restored.Spec.NetworkSpec.ControlPlaneOutboundLB.BackendPool.Name + } + return nil } diff --git a/api/v1alpha4/zz_generated.conversion.go b/api/v1alpha4/zz_generated.conversion.go index e7da14caaa0..06856f8322c 100644 --- a/api/v1alpha4/zz_generated.conversion.go +++ b/api/v1alpha4/zz_generated.conversion.go @@ -1606,6 +1606,7 @@ func autoConvert_v1beta1_LoadBalancerSpec_To_v1alpha4_LoadBalancerSpec(in *v1bet out.FrontendIPs = nil } out.FrontendIPsCount = (*int32)(unsafe.Pointer(in.FrontendIPsCount)) + // WARNING: in.BackendPool requires manual conversion: does not exist in peer-type // WARNING: in.LoadBalancerClassSpec requires manual conversion: does not exist in peer-type return nil } diff --git a/api/v1beta1/azurecluster_default.go b/api/v1beta1/azurecluster_default.go index 03b2071bfef..1e38323f140 100644 --- a/api/v1beta1/azurecluster_default.go +++ b/api/v1beta1/azurecluster_default.go @@ -193,6 +193,10 @@ func (c *AzureCluster) setAPIServerLBDefaults() { } } } + + if lb.BackendPool.Name == "" { + lb.BackendPool.Name = generateBackendAddressPoolName(lb.Name) + } } // SetNodeOutboundLBDefaults sets the default values for the NodeOutboundLB. @@ -223,13 +227,19 @@ func (c *AzureCluster) SetNodeOutboundLBDefaults() { lb := c.Spec.NetworkSpec.NodeOutboundLB lb.LoadBalancerClassSpec.setNodeOutboundLBDefaults() - lb.Name = c.ObjectMeta.Name + if lb.Name == "" { + lb.Name = c.ObjectMeta.Name + } if lb.FrontendIPsCount == nil { lb.FrontendIPsCount = pointer.Int32Ptr(1) } c.setOutboundLBFrontendIPs(lb, generateNodeOutboundIPName) + + if lb.BackendPool.Name == "" { + lb.BackendPool.Name = generateOutboundBackendAddressPoolName(lb.Name) + } } // SetControlPlaneOutboundLBDefaults sets the default values for the control plane's outbound LB. @@ -248,6 +258,10 @@ func (c *AzureCluster) SetControlPlaneOutboundLBDefaults() { lb.FrontendIPsCount = pointer.Int32Ptr(1) } c.setOutboundLBFrontendIPs(lb, generateControlPlaneOutboundIPName) + + if lb.BackendPool.Name == "" { + lb.BackendPool.Name = generateOutboundBackendAddressPoolName(generateControlPlaneOutboundLBName(c.ObjectMeta.Name)) + } } // setOutboundLBFrontendIPs sets the frontend ips for the given load balancer. @@ -431,3 +445,13 @@ func generateNatGatewayIPName(clusterName, subnetName string) string { func withIndex(name string, n int) string { return fmt.Sprintf("%s-%d", name, n) } + +// generateBackendAddressPoolName generates a load balancer backend address pool name. +func generateBackendAddressPoolName(lbName string) string { + return fmt.Sprintf("%s-%s", lbName, "backendPool") +} + +// generateOutboundBackendAddressPoolName generates a load balancer outbound backend address pool name. +func generateOutboundBackendAddressPoolName(lbName string) string { + return fmt.Sprintf("%s-%s", lbName, "outboundBackendPool") +} diff --git a/api/v1beta1/azurecluster_default_test.go b/api/v1beta1/azurecluster_default_test.go index 102f41e5094..8306138f1bc 100644 --- a/api/v1beta1/azurecluster_default_test.go +++ b/api/v1beta1/azurecluster_default_test.go @@ -862,6 +862,9 @@ func TestAPIServerLBDefaults(t *testing.T) { }, }, }, + BackendPool: BackendPool{ + Name: "cluster-test-public-lb-backendPool", + }, LoadBalancerClassSpec: LoadBalancerClassSpec{ SKU: SKUStandard, Type: Public, @@ -903,6 +906,57 @@ func TestAPIServerLBDefaults(t *testing.T) { }, }, }, + BackendPool: BackendPool{ + Name: "cluster-test-internal-lb-backendPool", + }, + LoadBalancerClassSpec: LoadBalancerClassSpec{ + SKU: SKUStandard, + Type: Internal, + IdleTimeoutInMinutes: to.Int32Ptr(DefaultOutboundRuleIdleTimeoutInMinutes), + }, + Name: "cluster-test-internal-lb", + }, + }, + }, + }, + }, + { + name: "with custom backend pool name", + cluster: &AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{ + LoadBalancerClassSpec: LoadBalancerClassSpec{ + Type: Internal, + }, + BackendPool: BackendPool{ + Name: "custom-backend-pool", + }, + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{ + FrontendIPs: []FrontendIP{ + { + Name: "cluster-test-internal-lb-frontEnd", + FrontendIPClass: FrontendIPClass{ + PrivateIPAddress: DefaultInternalLBIPAddress, + }, + }, + }, + BackendPool: BackendPool{ + Name: "custom-backend-pool", + }, LoadBalancerClassSpec: LoadBalancerClassSpec{ SKU: SKUStandard, Type: Internal, @@ -1086,6 +1140,9 @@ func TestNodeOutboundLBDefaults(t *testing.T) { Name: "pip-cluster-test-node-outbound", }, }}, + BackendPool: BackendPool{ + Name: "cluster-test-outboundBackendPool", + }, FrontendIPsCount: to.Int32Ptr(1), LoadBalancerClassSpec: LoadBalancerClassSpec{ SKU: SKUStandard, @@ -1264,6 +1321,9 @@ func TestNodeOutboundLBDefaults(t *testing.T) { Name: "pip-cluster-test-node-outbound", }, }}, + BackendPool: BackendPool{ + Name: "cluster-test-outboundBackendPool", + }, FrontendIPsCount: to.Int32Ptr(1), LoadBalancerClassSpec: LoadBalancerClassSpec{ SKU: SKUStandard, @@ -1374,6 +1434,9 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }}, FrontendIPsCount: to.Int32Ptr(1), + BackendPool: BackendPool{ + Name: "cluster-test-outboundBackendPool", + }, LoadBalancerClassSpec: LoadBalancerClassSpec{ SKU: SKUStandard, Type: Public, @@ -1544,7 +1607,7 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }, { - name: "NodeOutboundLB declared as input with non-default IdleTimeoutInMinutes and FrontendIPsCount values", + name: "NodeOutboundLB declared as input with non-default IdleTimeoutInMinutes, FrontendIPsCount, BackendPool values", cluster: &AzureCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "cluster-test", @@ -1554,6 +1617,9 @@ func TestNodeOutboundLBDefaults(t *testing.T) { APIServerLB: LoadBalancerSpec{LoadBalancerClassSpec: LoadBalancerClassSpec{Type: Public}}, NodeOutboundLB: &LoadBalancerSpec{ FrontendIPsCount: to.Int32Ptr(2), + BackendPool: BackendPool{ + Name: "custom-backend-pool", + }, LoadBalancerClassSpec: LoadBalancerClassSpec{ IdleTimeoutInMinutes: to.Int32Ptr(15), }, @@ -1587,6 +1653,9 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }, }, + BackendPool: BackendPool{ + Name: "custom-backend-pool", + }, FrontendIPsCount: to.Int32Ptr(2), // we expect the original value to be respected here LoadBalancerClassSpec: LoadBalancerClassSpec{ SKU: SKUStandard, @@ -1599,6 +1668,102 @@ func TestNodeOutboundLBDefaults(t *testing.T) { }, }, }, + { + name: "ensure that existing lb names are not overwritten", + cluster: &AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{ + Name: "user-defined-name", + LoadBalancerClassSpec: LoadBalancerClassSpec{ + Type: Public, + }, + }, + Subnets: Subnets{ + { + SubnetClassSpec: SubnetClassSpec{ + Role: SubnetControlPlane, + Name: "control-plane-subnet", + }, + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + SubnetClassSpec: SubnetClassSpec{ + Role: SubnetNode, + Name: "node-subnet", + }, + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, + ControlPlaneOutboundLB: &LoadBalancerSpec{ + Name: "user-defined-name", + }, + NodeOutboundLB: &LoadBalancerSpec{ + Name: "user-defined-name", + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + Subnets: Subnets{ + { + SubnetClassSpec: SubnetClassSpec{ + Role: SubnetControlPlane, + Name: "control-plane-subnet", + }, + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + { + SubnetClassSpec: SubnetClassSpec{ + Role: SubnetNode, + Name: "node-subnet", + }, + SecurityGroup: SecurityGroup{}, + RouteTable: RouteTable{}, + }, + }, + APIServerLB: LoadBalancerSpec{ + Name: "user-defined-name", + LoadBalancerClassSpec: LoadBalancerClassSpec{ + Type: Public, + }, + }, + NodeOutboundLB: &LoadBalancerSpec{ + Name: "user-defined-name", + FrontendIPs: []FrontendIP{{ + Name: "user-defined-name-frontEnd", + PublicIP: &PublicIPSpec{ + Name: "pip-cluster-test-node-outbound", + }, + }}, + BackendPool: BackendPool{ + Name: "user-defined-name-outboundBackendPool", + }, + FrontendIPsCount: to.Int32Ptr(1), + LoadBalancerClassSpec: LoadBalancerClassSpec{ + SKU: SKUStandard, + Type: Public, + IdleTimeoutInMinutes: to.Int32Ptr(DefaultOutboundRuleIdleTimeoutInMinutes), + }, + }, + ControlPlaneOutboundLB: &LoadBalancerSpec{ + Name: "user-defined-name", + }, + }, + }, + }, + }, } for _, c := range cases { @@ -1706,6 +1871,9 @@ func TestControlPlaneOutboundLBDefaults(t *testing.T) { }, ControlPlaneOutboundLB: &LoadBalancerSpec{ Name: "cluster-test-outbound-lb", + BackendPool: BackendPool{ + Name: "cluster-test-outbound-lb-outboundBackendPool", + }, FrontendIPs: []FrontendIP{ { Name: "cluster-test-outbound-lb-frontEnd-1", @@ -1731,6 +1899,61 @@ func TestControlPlaneOutboundLBDefaults(t *testing.T) { }, }, }, + { + name: "custom outbound lb backend pool", + cluster: &AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{LoadBalancerClassSpec: LoadBalancerClassSpec{Type: Internal}}, + ControlPlaneOutboundLB: &LoadBalancerSpec{ + BackendPool: BackendPool{ + Name: "custom-outbound-lb", + }, + LoadBalancerClassSpec: LoadBalancerClassSpec{ + IdleTimeoutInMinutes: to.Int32Ptr(15), + }, + }, + }, + }, + }, + output: &AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "cluster-test", + }, + Spec: AzureClusterSpec{ + NetworkSpec: NetworkSpec{ + APIServerLB: LoadBalancerSpec{ + LoadBalancerClassSpec: LoadBalancerClassSpec{ + Type: Internal, + }, + }, + ControlPlaneOutboundLB: &LoadBalancerSpec{ + Name: "cluster-test-outbound-lb", + BackendPool: BackendPool{ + Name: "custom-outbound-lb", + }, + FrontendIPs: []FrontendIP{ + { + Name: "cluster-test-outbound-lb-frontEnd", + PublicIP: &PublicIPSpec{ + Name: "pip-cluster-test-controlplane-outbound", + }, + }, + }, + FrontendIPsCount: to.Int32Ptr(1), + LoadBalancerClassSpec: LoadBalancerClassSpec{ + SKU: SKUStandard, + Type: Public, + IdleTimeoutInMinutes: to.Int32Ptr(15), + }, + }, + }, + }, + }, + }, } for _, c := range cases { diff --git a/api/v1beta1/types.go b/api/v1beta1/types.go index cb042b3fa99..36036ed4da7 100644 --- a/api/v1beta1/types.go +++ b/api/v1beta1/types.go @@ -254,6 +254,9 @@ type LoadBalancerSpec struct { // FrontendIPsCount specifies the number of frontend IP addresses for the load balancer. // +optional FrontendIPsCount *int32 `json:"frontendIPsCount,omitempty"` + // BackendPool describes the backend pool of the load balancer. + // +optional + BackendPool BackendPool `json:"backendPool,omitempty"` LoadBalancerClassSpec `json:",inline"` } @@ -780,6 +783,14 @@ type AzureBastion struct { PublicIP PublicIPSpec `json:"publicIP,omitempty"` } +// BackendPool describes the backend pool of the load balancer. +type BackendPool struct { + // Name specifies the name of backend pool for the load balancer. If not specified, the default name will + // be set, depending on the load balancer role. + // +optional + Name string `json:"name,omitempty"` +} + // IsTerminalProvisioningState returns true if the ProvisioningState is a terminal state for an Azure resource. func IsTerminalProvisioningState(state ProvisioningState) bool { return state == Failed || state == Succeeded diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index cd6b2ffaedf..5f86a6b7171 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -856,6 +856,21 @@ func (in *BackOffConfig) DeepCopy() *BackOffConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackendPool) DeepCopyInto(out *BackendPool) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendPool. +func (in *BackendPool) DeepCopy() *BackendPool { + if in == nil { + return nil + } + out := new(BackendPool) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BastionSpec) DeepCopyInto(out *BastionSpec) { *out = *in @@ -1176,6 +1191,7 @@ func (in *LoadBalancerSpec) DeepCopyInto(out *LoadBalancerSpec) { *out = new(int32) **out = **in } + out.BackendPool = in.BackendPool in.LoadBalancerClassSpec.DeepCopyInto(&out.LoadBalancerClassSpec) } diff --git a/azure/scope/cluster.go b/azure/scope/cluster.go index ee476e5dd91..da4dd6b03ed 100644 --- a/azure/scope/cluster.go +++ b/azure/scope/cluster.go @@ -244,7 +244,7 @@ func (s *ClusterScope) LBSpecs() []azure.ResourceSpecGetter { Type: s.APIServerLB().Type, SKU: infrav1.SKUStandard, Role: infrav1.APIServerRole, - BackendPoolName: s.APIServerLBPoolName(s.APIServerLB().Name), + BackendPoolName: s.APIServerLB().BackendPool.Name, IdleTimeoutInMinutes: s.APIServerLB().IdleTimeoutInMinutes, AdditionalTags: s.AdditionalTags(), }, @@ -263,7 +263,7 @@ func (s *ClusterScope) LBSpecs() []azure.ResourceSpecGetter { FrontendIPConfigs: s.NodeOutboundLB().FrontendIPs, Type: s.NodeOutboundLB().Type, SKU: s.NodeOutboundLB().SKU, - BackendPoolName: s.OutboundPoolName(s.NodeOutboundLB().Name), + BackendPoolName: s.NodeOutboundLB().BackendPool.Name, IdleTimeoutInMinutes: s.NodeOutboundLB().IdleTimeoutInMinutes, Role: infrav1.NodeOutboundRole, AdditionalTags: s.AdditionalTags(), @@ -283,7 +283,7 @@ func (s *ClusterScope) LBSpecs() []azure.ResourceSpecGetter { FrontendIPConfigs: s.ControlPlaneOutboundLB().FrontendIPs, Type: s.ControlPlaneOutboundLB().Type, SKU: s.ControlPlaneOutboundLB().SKU, - BackendPoolName: s.OutboundPoolName(azure.GenerateControlPlaneOutboundLBName(s.ClusterName())), + BackendPoolName: s.ControlPlaneOutboundLB().BackendPool.Name, IdleTimeoutInMinutes: s.NodeOutboundLB().IdleTimeoutInMinutes, Role: infrav1.ControlPlaneOutboundRole, AdditionalTags: s.AdditionalTags(), diff --git a/azure/scope/cluster_test.go b/azure/scope/cluster_test.go index 3443f783933..6f7c15ade1c 100644 --- a/azure/scope/cluster_test.go +++ b/azure/scope/cluster_test.go @@ -33,6 +33,7 @@ import ( infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" "sigs.k8s.io/cluster-api-provider-azure/azure" "sigs.k8s.io/cluster-api-provider-azure/azure/services/bastionhosts" + "sigs.k8s.io/cluster-api-provider-azure/azure/services/loadbalancers" "sigs.k8s.io/cluster-api-provider-azure/azure/services/natgateways" "sigs.k8s.io/cluster-api-provider-azure/azure/services/publicips" "sigs.k8s.io/cluster-api-provider-azure/azure/services/routetables" @@ -2130,6 +2131,149 @@ func TestOutboundLBName(t *testing.T) { } } +func TestBackendPoolName(t *testing.T) { + tests := []struct { + name string + clusterName string + + customAPIServerBackendPoolName string + customNodeBackendPoolName string + customControlPlaneBackendPoolName string + + expectedAPIServerBackendPoolName string + expectedNodeBackendPoolName string + expectedControlPlaneBackendPoolName string + }{ + { + name: "With default backend pool names", + clusterName: "my-cluster", + expectedAPIServerBackendPoolName: "APIServerLBName-backendPool", + expectedNodeBackendPoolName: "NodeOutboundLBName-outboundBackendPool", + expectedControlPlaneBackendPoolName: "my-cluster-outbound-lb-outboundBackendPool", + }, + { + name: "With custom node backend pool name", + clusterName: "my-cluster", + + // setting custom name for node pool name only, others should stay the same + customNodeBackendPoolName: "custom-node-poolname", + + expectedAPIServerBackendPoolName: "APIServerLBName-backendPool", + expectedNodeBackendPoolName: "custom-node-poolname", + expectedControlPlaneBackendPoolName: "my-cluster-outbound-lb-outboundBackendPool", + }, + { + name: "With custom backends pool name", + clusterName: "my-cluster", + + // setting custom names for all backends pools + customAPIServerBackendPoolName: "custom-api-server-poolname", + customNodeBackendPoolName: "custom-node-poolname", + customControlPlaneBackendPoolName: "custom-control-plane-poolname", + + expectedAPIServerBackendPoolName: "custom-api-server-poolname", + expectedNodeBackendPoolName: "custom-node-poolname", + expectedControlPlaneBackendPoolName: "custom-control-plane-poolname", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + g := NewWithT(t) + scheme := runtime.NewScheme() + _ = infrav1.AddToScheme(scheme) + _ = clusterv1.AddToScheme(scheme) + + cluster := &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: tc.clusterName, + Namespace: "default", + }, + } + + azureCluster := &infrav1.AzureCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: tc.clusterName, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: "cluster.x-k8s.io/v1beta1", + Kind: "Cluster", + Name: tc.clusterName, + }, + }, + }, + Spec: infrav1.AzureClusterSpec{ + AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ + SubscriptionID: "123", + }, + NetworkSpec: infrav1.NetworkSpec{ + Subnets: infrav1.Subnets{ + { + SubnetClassSpec: infrav1.SubnetClassSpec{ + Role: infrav1.SubnetNode, + Name: "node", + }, + }, + }, + APIServerLB: infrav1.LoadBalancerSpec{ + Name: "APIServerLBName", + }, + ControlPlaneOutboundLB: &infrav1.LoadBalancerSpec{ + Name: "ControlPlaneOutboundLBName", + }, + NodeOutboundLB: &infrav1.LoadBalancerSpec{ + Name: "NodeOutboundLBName", + }, + }, + }, + } + + azureCluster.Default() + + if tc.customAPIServerBackendPoolName != "" { + azureCluster.Spec.NetworkSpec.APIServerLB.BackendPool.Name = tc.customAPIServerBackendPoolName + } + + if tc.customNodeBackendPoolName != "" { + azureCluster.Spec.NetworkSpec.NodeOutboundLB.BackendPool.Name = tc.customNodeBackendPoolName + } + + if tc.customControlPlaneBackendPoolName != "" { + azureCluster.Spec.NetworkSpec.ControlPlaneOutboundLB.BackendPool.Name = tc.customControlPlaneBackendPoolName + } + + initObjects := []runtime.Object{cluster, azureCluster} + fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjects...).Build() + + clusterScope, err := NewClusterScope(context.TODO(), ClusterScopeParams{ + AzureClients: AzureClients{ + Authorizer: autorest.NullAuthorizer{}, + }, + Cluster: cluster, + AzureCluster: azureCluster, + Client: fakeClient, + }) + g.Expect(err).NotTo(HaveOccurred()) + got := clusterScope.LBSpecs() + g.Expect(len(got)).To(Equal(3)) + + // API server backend pool name + apiServerLBSpec := got[0].(*loadbalancers.LBSpec) + g.Expect(apiServerLBSpec.BackendPoolName).To(Equal(tc.expectedAPIServerBackendPoolName)) + g.Expect(apiServerLBSpec.Role).To(Equal(infrav1.APIServerRole)) + + // Node backend pool name + NodeLBSpec := got[1].(*loadbalancers.LBSpec) + g.Expect(NodeLBSpec.BackendPoolName).To(Equal(tc.expectedNodeBackendPoolName)) + g.Expect(NodeLBSpec.Role).To(Equal(infrav1.NodeOutboundRole)) + + // Control Plane backend pool name + controlPlaneLBSpec := got[2].(*loadbalancers.LBSpec) + g.Expect(controlPlaneLBSpec.BackendPoolName).To(Equal(tc.expectedControlPlaneBackendPoolName)) + g.Expect(controlPlaneLBSpec.Role).To(Equal(infrav1.ControlPlaneOutboundRole)) + }) + } +} + func TestOutboundPoolName(t *testing.T) { tests := []struct { name string diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml index eb988013143..aaaf39c25bc 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_azureclusters.yaml @@ -1704,6 +1704,16 @@ spec: description: APIServerLB is the configuration for the control-plane load balancer. properties: + backendPool: + description: BackendPool describes the backend pool of the + load balancer. + properties: + name: + description: Name specifies the name of backend pool for + the load balancer. If not specified, the default name + will be set, depending on the load balancer role. + type: string + type: object frontendIPs: items: description: FrontendIP defines a load balancer frontend @@ -1777,6 +1787,16 @@ spec: APIServerLB, and is used only in private clusters (optionally) for enabling outbound traffic. properties: + backendPool: + description: BackendPool describes the backend pool of the + load balancer. + properties: + name: + description: Name specifies the name of backend pool for + the load balancer. If not specified, the default name + will be set, depending on the load balancer role. + type: string + type: object frontendIPs: items: description: FrontendIP defines a load balancer frontend @@ -1848,6 +1868,16 @@ spec: description: NodeOutboundLB is the configuration for the node outbound load balancer. properties: + backendPool: + description: BackendPool describes the backend pool of the + load balancer. + properties: + name: + description: Name specifies the name of backend pool for + the load balancer. If not specified, the default name + will be set, depending on the load balancer role. + type: string + type: object frontendIPs: items: description: FrontendIP defines a load balancer frontend