sigs.k8s.io/cluster-api-provider-azure@v1.14.3/api/v1beta1/azurecluster_default.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1beta1
    18  
    19  import (
    20  	"fmt"
    21  
    22  	"k8s.io/utils/ptr"
    23  )
    24  
    25  const (
    26  	// DefaultVnetCIDR is the default Vnet CIDR.
    27  	DefaultVnetCIDR = "10.0.0.0/8"
    28  	// DefaultControlPlaneSubnetCIDR is the default Control Plane Subnet CIDR.
    29  	DefaultControlPlaneSubnetCIDR = "10.0.0.0/16"
    30  	// DefaultNodeSubnetCIDR is the default Node Subnet CIDR.
    31  	DefaultNodeSubnetCIDR = "10.1.0.0/16"
    32  	// DefaultClusterSubnetCIDR is the default Cluster Subnet CIDR.
    33  	DefaultClusterSubnetCIDR = "10.0.0.0/16"
    34  	// DefaultNodeSubnetCIDRPattern is the pattern that will be used to generate the default subnets CIDRs.
    35  	DefaultNodeSubnetCIDRPattern = "10.%d.0.0/16"
    36  	// DefaultAzureBastionSubnetCIDR is the default Subnet CIDR for AzureBastion.
    37  	DefaultAzureBastionSubnetCIDR = "10.255.255.224/27"
    38  	// DefaultAzureBastionSubnetName is the default Subnet Name for AzureBastion.
    39  	DefaultAzureBastionSubnetName = "AzureBastionSubnet"
    40  	// DefaultAzureBastionSubnetRole is the default Subnet role for AzureBastion.
    41  	DefaultAzureBastionSubnetRole = SubnetBastion
    42  	// DefaultInternalLBIPAddress is the default internal load balancer ip address.
    43  	DefaultInternalLBIPAddress = "10.0.0.100"
    44  	// DefaultOutboundRuleIdleTimeoutInMinutes is the default for IdleTimeoutInMinutes for the load balancer.
    45  	DefaultOutboundRuleIdleTimeoutInMinutes = 4
    46  	// DefaultAzureCloud is the public cloud that will be used by most users.
    47  	DefaultAzureCloud = "AzurePublicCloud"
    48  )
    49  
    50  func (c *AzureCluster) setDefaults() {
    51  	c.Spec.AzureClusterClassSpec.setDefaults()
    52  	c.setResourceGroupDefault()
    53  	c.setNetworkSpecDefaults()
    54  }
    55  
    56  func (c *AzureCluster) setNetworkSpecDefaults() {
    57  	c.setVnetDefaults()
    58  	c.setBastionDefaults()
    59  	c.setSubnetDefaults()
    60  	c.setVnetPeeringDefaults()
    61  	c.setAPIServerLBDefaults()
    62  	c.SetNodeOutboundLBDefaults()
    63  	c.SetControlPlaneOutboundLBDefaults()
    64  }
    65  
    66  func (c *AzureCluster) setResourceGroupDefault() {
    67  	if c.Spec.ResourceGroup == "" {
    68  		c.Spec.ResourceGroup = c.Name
    69  	}
    70  }
    71  
    72  func (c *AzureCluster) setAzureEnvironmentDefault() {
    73  	if c.Spec.AzureEnvironment == "" {
    74  		c.Spec.AzureEnvironment = DefaultAzureCloud
    75  	}
    76  }
    77  
    78  func (c *AzureCluster) setVnetDefaults() {
    79  	if c.Spec.NetworkSpec.Vnet.ResourceGroup == "" {
    80  		c.Spec.NetworkSpec.Vnet.ResourceGroup = c.Spec.ResourceGroup
    81  	}
    82  	if c.Spec.NetworkSpec.Vnet.Name == "" {
    83  		c.Spec.NetworkSpec.Vnet.Name = generateVnetName(c.ObjectMeta.Name)
    84  	}
    85  	c.Spec.NetworkSpec.Vnet.VnetClassSpec.setDefaults()
    86  }
    87  
    88  func (c *AzureCluster) setSubnetDefaults() {
    89  	clusterSubnet, err := c.Spec.NetworkSpec.GetSubnet(SubnetCluster)
    90  	clusterSubnetExists := err == nil
    91  	if clusterSubnetExists {
    92  		clusterSubnet.setClusterSubnetDefaults(c.ObjectMeta.Name)
    93  		c.Spec.NetworkSpec.UpdateSubnet(clusterSubnet, SubnetCluster)
    94  	}
    95  
    96  	/* if there is a cp subnet set defaults
    97  	   if no cp subnet and cluster subnet create a default cp subnet */
    98  	cpSubnet, errcp := c.Spec.NetworkSpec.GetSubnet(SubnetControlPlane)
    99  	if errcp == nil {
   100  		cpSubnet.setControlPlaneSubnetDefaults(c.ObjectMeta.Name)
   101  		c.Spec.NetworkSpec.UpdateSubnet(cpSubnet, SubnetControlPlane)
   102  	} else if !clusterSubnetExists {
   103  		cpSubnet = SubnetSpec{SubnetClassSpec: SubnetClassSpec{Role: SubnetControlPlane}}
   104  		cpSubnet.setControlPlaneSubnetDefaults(c.ObjectMeta.Name)
   105  		c.Spec.NetworkSpec.Subnets = append(c.Spec.NetworkSpec.Subnets, cpSubnet)
   106  	}
   107  
   108  	var nodeSubnetFound bool
   109  	var nodeSubnetCounter int
   110  	for i, subnet := range c.Spec.NetworkSpec.Subnets {
   111  		if subnet.Role != SubnetNode {
   112  			continue
   113  		}
   114  		nodeSubnetCounter++
   115  		nodeSubnetFound = true
   116  		subnet.setNodeSubnetDefaults(c.ObjectMeta.Name, nodeSubnetCounter)
   117  		c.Spec.NetworkSpec.Subnets[i] = subnet
   118  	}
   119  
   120  	if !nodeSubnetFound && !clusterSubnetExists {
   121  		nodeSubnet := SubnetSpec{
   122  			SubnetClassSpec: SubnetClassSpec{
   123  				Role:       SubnetNode,
   124  				CIDRBlocks: []string{DefaultNodeSubnetCIDR},
   125  				Name:       generateNodeSubnetName(c.ObjectMeta.Name),
   126  			},
   127  			SecurityGroup: SecurityGroup{
   128  				Name: generateNodeSecurityGroupName(c.ObjectMeta.Name),
   129  			},
   130  			RouteTable: RouteTable{
   131  				Name: generateNodeRouteTableName(c.ObjectMeta.Name),
   132  			},
   133  			NatGateway: NatGateway{
   134  				NatGatewayClassSpec: NatGatewayClassSpec{
   135  					Name: generateNatGatewayName(c.ObjectMeta.Name),
   136  				},
   137  			},
   138  		}
   139  		c.Spec.NetworkSpec.Subnets = append(c.Spec.NetworkSpec.Subnets, nodeSubnet)
   140  	}
   141  }
   142  
   143  func (s *SubnetSpec) setNodeSubnetDefaults(clusterName string, index int) {
   144  	if s.Name == "" {
   145  		s.Name = withIndex(generateNodeSubnetName(clusterName), index)
   146  	}
   147  	s.SubnetClassSpec.setDefaults(fmt.Sprintf(DefaultNodeSubnetCIDRPattern, index))
   148  
   149  	if s.SecurityGroup.Name == "" {
   150  		s.SecurityGroup.Name = generateNodeSecurityGroupName(clusterName)
   151  	}
   152  	s.SecurityGroup.SecurityGroupClass.setDefaults()
   153  
   154  	if s.RouteTable.Name == "" {
   155  		s.RouteTable.Name = generateNodeRouteTableName(clusterName)
   156  	}
   157  
   158  	// NAT gateway only supports the use of IPv4 public IP addresses for outbound connectivity.
   159  	// So default use the NAT gateway for outbound traffic in IPv4 cluster instead of loadbalancer.
   160  	// We assume that if the ID is set, the subnet already exists so we shouldn't add a NAT gateway.
   161  	if !s.IsIPv6Enabled() && s.ID == "" {
   162  		if s.NatGateway.Name == "" {
   163  			s.NatGateway.Name = withIndex(generateNatGatewayName(clusterName), index)
   164  		}
   165  		if s.NatGateway.NatGatewayIP.Name == "" {
   166  			s.NatGateway.NatGatewayIP.Name = generateNatGatewayIPName(s.NatGateway.Name)
   167  		}
   168  	}
   169  }
   170  
   171  func (s *SubnetSpec) setControlPlaneSubnetDefaults(clusterName string) {
   172  	if s.Name == "" {
   173  		s.Name = generateControlPlaneSubnetName(clusterName)
   174  	}
   175  
   176  	s.SubnetClassSpec.setDefaults(DefaultControlPlaneSubnetCIDR)
   177  
   178  	if s.SecurityGroup.Name == "" {
   179  		s.SecurityGroup.Name = generateControlPlaneSecurityGroupName(clusterName)
   180  	}
   181  	s.SecurityGroup.SecurityGroupClass.setDefaults()
   182  }
   183  
   184  func (s *SubnetSpec) setClusterSubnetDefaults(clusterName string) {
   185  	if s.Name == "" {
   186  		s.Name = generateClusterSubnetSubnetName(clusterName)
   187  	}
   188  	if s.SecurityGroup.Name == "" {
   189  		s.SecurityGroup.Name = generateClusterSecurityGroupName(clusterName)
   190  	}
   191  	if s.RouteTable.Name == "" {
   192  		s.RouteTable.Name = generateClustereRouteTableName(clusterName)
   193  	}
   194  	if s.NatGateway.Name == "" {
   195  		s.NatGateway.Name = generateClusterNatGatewayName(clusterName)
   196  	}
   197  	if !s.IsIPv6Enabled() && s.ID == "" && s.NatGateway.NatGatewayIP.Name == "" {
   198  		s.NatGateway.NatGatewayIP.Name = generateNatGatewayIPName(s.NatGateway.Name)
   199  	}
   200  	s.setDefaults(DefaultClusterSubnetCIDR)
   201  	s.SecurityGroup.SecurityGroupClass.setDefaults()
   202  }
   203  
   204  func (c *AzureCluster) setVnetPeeringDefaults() {
   205  	for i, peering := range c.Spec.NetworkSpec.Vnet.Peerings {
   206  		if peering.ResourceGroup == "" {
   207  			c.Spec.NetworkSpec.Vnet.Peerings[i].ResourceGroup = c.Spec.ResourceGroup
   208  		}
   209  	}
   210  }
   211  
   212  func (c *AzureCluster) setAPIServerLBDefaults() {
   213  	lb := &c.Spec.NetworkSpec.APIServerLB
   214  
   215  	lb.LoadBalancerClassSpec.setAPIServerLBDefaults()
   216  
   217  	if lb.Type == Public {
   218  		if lb.Name == "" {
   219  			lb.Name = generatePublicLBName(c.ObjectMeta.Name)
   220  		}
   221  		if len(lb.FrontendIPs) == 0 {
   222  			lb.FrontendIPs = []FrontendIP{
   223  				{
   224  					Name: generateFrontendIPConfigName(lb.Name),
   225  					PublicIP: &PublicIPSpec{
   226  						Name: generatePublicIPName(c.ObjectMeta.Name),
   227  					},
   228  				},
   229  			}
   230  		}
   231  	} else if lb.Type == Internal {
   232  		if lb.Name == "" {
   233  			lb.Name = generateInternalLBName(c.ObjectMeta.Name)
   234  		}
   235  		if len(lb.FrontendIPs) == 0 {
   236  			lb.FrontendIPs = []FrontendIP{
   237  				{
   238  					Name: generateFrontendIPConfigName(lb.Name),
   239  					FrontendIPClass: FrontendIPClass{
   240  						PrivateIPAddress: DefaultInternalLBIPAddress,
   241  					},
   242  				},
   243  			}
   244  		}
   245  	}
   246  	c.SetAPIServerLBBackendPoolNameDefault()
   247  }
   248  
   249  // SetNodeOutboundLBDefaults sets the default values for the NodeOutboundLB.
   250  func (c *AzureCluster) SetNodeOutboundLBDefaults() {
   251  	if c.Spec.NetworkSpec.NodeOutboundLB == nil {
   252  		if c.Spec.NetworkSpec.APIServerLB.Type == Internal {
   253  			return
   254  		}
   255  
   256  		var needsOutboundLB bool
   257  		for _, subnet := range c.Spec.NetworkSpec.Subnets {
   258  			if (subnet.Role == SubnetNode || subnet.Role == SubnetCluster) && subnet.IsIPv6Enabled() {
   259  				needsOutboundLB = true
   260  				break
   261  			}
   262  		}
   263  
   264  		// If we don't default the outbound LB when there are some subnets with NAT gateway,
   265  		// and some without, those without wouldn't have outbound traffic. So taking the
   266  		// safer route, we configure the outbound LB in that scenario.
   267  		if !needsOutboundLB {
   268  			return
   269  		}
   270  
   271  		c.Spec.NetworkSpec.NodeOutboundLB = &LoadBalancerSpec{}
   272  	}
   273  
   274  	lb := c.Spec.NetworkSpec.NodeOutboundLB
   275  	lb.LoadBalancerClassSpec.setNodeOutboundLBDefaults()
   276  
   277  	if lb.Name == "" {
   278  		lb.Name = c.ObjectMeta.Name
   279  	}
   280  
   281  	if lb.FrontendIPsCount == nil {
   282  		lb.FrontendIPsCount = ptr.To[int32](1)
   283  	}
   284  
   285  	c.setOutboundLBFrontendIPs(lb, generateNodeOutboundIPName)
   286  	c.SetNodeOutboundLBBackendPoolNameDefault()
   287  }
   288  
   289  // SetControlPlaneOutboundLBDefaults sets the default values for the control plane's outbound LB.
   290  func (c *AzureCluster) SetControlPlaneOutboundLBDefaults() {
   291  	lb := c.Spec.NetworkSpec.ControlPlaneOutboundLB
   292  
   293  	if lb == nil {
   294  		return
   295  	}
   296  
   297  	lb.LoadBalancerClassSpec.setControlPlaneOutboundLBDefaults()
   298  	if lb.Name == "" {
   299  		lb.Name = generateControlPlaneOutboundLBName(c.ObjectMeta.Name)
   300  	}
   301  	if lb.FrontendIPsCount == nil {
   302  		lb.FrontendIPsCount = ptr.To[int32](1)
   303  	}
   304  	c.setOutboundLBFrontendIPs(lb, generateControlPlaneOutboundIPName)
   305  	c.SetControlPlaneOutboundLBBackendPoolNameDefault()
   306  }
   307  
   308  // SetBackendPoolNameDefault defaults the backend pool name of the LBs.
   309  func (c *AzureCluster) SetBackendPoolNameDefault() {
   310  	c.SetAPIServerLBBackendPoolNameDefault()
   311  	c.SetNodeOutboundLBBackendPoolNameDefault()
   312  	c.SetControlPlaneOutboundLBBackendPoolNameDefault()
   313  }
   314  
   315  // SetAPIServerLBBackendPoolNameDefault defaults the name of the backend pool for apiserver LB.
   316  func (c *AzureCluster) SetAPIServerLBBackendPoolNameDefault() {
   317  	apiServerLB := &c.Spec.NetworkSpec.APIServerLB
   318  	if apiServerLB.BackendPool.Name == "" {
   319  		apiServerLB.BackendPool.Name = generateBackendAddressPoolName(apiServerLB.Name)
   320  	}
   321  }
   322  
   323  // SetNodeOutboundLBBackendPoolNameDefault defaults the name of the backend pool for node outbound LB.
   324  func (c *AzureCluster) SetNodeOutboundLBBackendPoolNameDefault() {
   325  	nodeOutboundLB := c.Spec.NetworkSpec.NodeOutboundLB
   326  	if nodeOutboundLB != nil && nodeOutboundLB.BackendPool.Name == "" {
   327  		nodeOutboundLB.BackendPool.Name = generateOutboundBackendAddressPoolName(nodeOutboundLB.Name)
   328  	}
   329  }
   330  
   331  // SetControlPlaneOutboundLBBackendPoolNameDefault defaults the name of the backend pool for control plane outbound LB.
   332  func (c *AzureCluster) SetControlPlaneOutboundLBBackendPoolNameDefault() {
   333  	controlPlaneOutboundLB := c.Spec.NetworkSpec.ControlPlaneOutboundLB
   334  	if controlPlaneOutboundLB != nil && controlPlaneOutboundLB.BackendPool.Name == "" {
   335  		controlPlaneOutboundLB.BackendPool.Name = generateOutboundBackendAddressPoolName(generateControlPlaneOutboundLBName(c.ObjectMeta.Name))
   336  	}
   337  }
   338  
   339  // setOutboundLBFrontendIPs sets the frontend ips for the given load balancer.
   340  // The name of the frontend ip is generated using generatePublicIPName function.
   341  func (c *AzureCluster) setOutboundLBFrontendIPs(lb *LoadBalancerSpec, generatePublicIPName func(string) string) {
   342  	switch *lb.FrontendIPsCount {
   343  	case 0:
   344  		lb.FrontendIPs = []FrontendIP{}
   345  	case 1:
   346  		lb.FrontendIPs = []FrontendIP{
   347  			{
   348  				Name: generateFrontendIPConfigName(lb.Name),
   349  				PublicIP: &PublicIPSpec{
   350  					Name: generatePublicIPName(c.ObjectMeta.Name),
   351  				},
   352  			},
   353  		}
   354  	default:
   355  		lb.FrontendIPs = make([]FrontendIP, *lb.FrontendIPsCount)
   356  		for i := 0; i < int(*lb.FrontendIPsCount); i++ {
   357  			lb.FrontendIPs[i] = FrontendIP{
   358  				Name: withIndex(generateFrontendIPConfigName(lb.Name), i+1),
   359  				PublicIP: &PublicIPSpec{
   360  					Name: withIndex(generatePublicIPName(c.ObjectMeta.Name), i+1),
   361  				},
   362  			}
   363  		}
   364  	}
   365  }
   366  
   367  func (c *AzureCluster) setBastionDefaults() {
   368  	if c.Spec.BastionSpec.AzureBastion != nil {
   369  		if c.Spec.BastionSpec.AzureBastion.Name == "" {
   370  			c.Spec.BastionSpec.AzureBastion.Name = generateAzureBastionName(c.ObjectMeta.Name)
   371  		}
   372  		// Ensure defaults for the Subnet settings.
   373  		if c.Spec.BastionSpec.AzureBastion.Subnet.Name == "" {
   374  			c.Spec.BastionSpec.AzureBastion.Subnet.Name = DefaultAzureBastionSubnetName
   375  		}
   376  		if len(c.Spec.BastionSpec.AzureBastion.Subnet.CIDRBlocks) == 0 {
   377  			c.Spec.BastionSpec.AzureBastion.Subnet.CIDRBlocks = []string{DefaultAzureBastionSubnetCIDR}
   378  		}
   379  		if c.Spec.BastionSpec.AzureBastion.Subnet.Role == "" {
   380  			c.Spec.BastionSpec.AzureBastion.Subnet.Role = DefaultAzureBastionSubnetRole
   381  		}
   382  		// Ensure defaults for the PublicIP settings.
   383  		if c.Spec.BastionSpec.AzureBastion.PublicIP.Name == "" {
   384  			c.Spec.BastionSpec.AzureBastion.PublicIP.Name = generateAzureBastionPublicIPName(c.ObjectMeta.Name)
   385  		}
   386  	}
   387  }
   388  
   389  func (lb *LoadBalancerClassSpec) setAPIServerLBDefaults() {
   390  	if lb.Type == "" {
   391  		lb.Type = Public
   392  	}
   393  	if lb.SKU == "" {
   394  		lb.SKU = SKUStandard
   395  	}
   396  	if lb.IdleTimeoutInMinutes == nil {
   397  		lb.IdleTimeoutInMinutes = ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes)
   398  	}
   399  }
   400  
   401  func (lb *LoadBalancerClassSpec) setNodeOutboundLBDefaults() {
   402  	lb.setOutboundLBDefaults()
   403  }
   404  
   405  func (lb *LoadBalancerClassSpec) setControlPlaneOutboundLBDefaults() {
   406  	lb.setOutboundLBDefaults()
   407  }
   408  
   409  func (lb *LoadBalancerClassSpec) setOutboundLBDefaults() {
   410  	lb.Type = Public
   411  	lb.SKU = SKUStandard
   412  	if lb.IdleTimeoutInMinutes == nil {
   413  		lb.IdleTimeoutInMinutes = ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes)
   414  	}
   415  }
   416  
   417  func setControlPlaneOutboundLBDefaults(lb *LoadBalancerClassSpec, apiserverLBType LBType) {
   418  	// public clusters don't need control plane outbound lb
   419  	if apiserverLBType == Public {
   420  		return
   421  	}
   422  
   423  	// private clusters can disable control plane outbound lb by setting it to nil.
   424  	if lb == nil {
   425  		return
   426  	}
   427  
   428  	lb.Type = Public
   429  	lb.SKU = SKUStandard
   430  
   431  	if lb.IdleTimeoutInMinutes == nil {
   432  		lb.IdleTimeoutInMinutes = ptr.To[int32](DefaultOutboundRuleIdleTimeoutInMinutes)
   433  	}
   434  }
   435  
   436  // generateVnetName generates a virtual network name, based on the cluster name.
   437  func generateVnetName(clusterName string) string {
   438  	return fmt.Sprintf("%s-%s", clusterName, "vnet")
   439  }
   440  
   441  // generateClusterSubnetSubnetName generates a subnet name, based on the cluster name.
   442  func generateClusterSubnetSubnetName(clusterName string) string {
   443  	return fmt.Sprintf("%s-%s", clusterName, "subnet")
   444  }
   445  
   446  // generateControlPlaneSubnetName generates a node subnet name, based on the cluster name.
   447  func generateControlPlaneSubnetName(clusterName string) string {
   448  	return fmt.Sprintf("%s-%s", clusterName, "controlplane-subnet")
   449  }
   450  
   451  // generateNodeSubnetName generates a node subnet name, based on the cluster name.
   452  func generateNodeSubnetName(clusterName string) string {
   453  	return fmt.Sprintf("%s-%s", clusterName, "node-subnet")
   454  }
   455  
   456  // generateAzureBastionName generates an azure bastion name.
   457  func generateAzureBastionName(clusterName string) string {
   458  	return fmt.Sprintf("%s-azure-bastion", clusterName)
   459  }
   460  
   461  // generateAzureBastionPublicIPName generates an azure bastion public ip name.
   462  func generateAzureBastionPublicIPName(clusterName string) string {
   463  	return fmt.Sprintf("%s-azure-bastion-pip", clusterName)
   464  }
   465  
   466  // generateClusterSecurityGroupName generates a security group name, based on the cluster name.
   467  func generateClusterSecurityGroupName(clusterName string) string {
   468  	return fmt.Sprintf("%s-%s", clusterName, "nsg")
   469  }
   470  
   471  // generateControlPlaneSecurityGroupName generates a control plane security group name, based on the cluster name.
   472  func generateControlPlaneSecurityGroupName(clusterName string) string {
   473  	return fmt.Sprintf("%s-%s", clusterName, "controlplane-nsg")
   474  }
   475  
   476  // generateNodeSecurityGroupName generates a node security group name, based on the cluster name.
   477  func generateNodeSecurityGroupName(clusterName string) string {
   478  	return fmt.Sprintf("%s-%s", clusterName, "node-nsg")
   479  }
   480  
   481  // generateClustereRouteTableName generates a route table name, based on the cluster name.
   482  func generateClustereRouteTableName(clusterName string) string {
   483  	return fmt.Sprintf("%s-%s", clusterName, "routetable")
   484  }
   485  
   486  // generateNodeRouteTableName generates a node route table name, based on the cluster name.
   487  func generateNodeRouteTableName(clusterName string) string {
   488  	return fmt.Sprintf("%s-%s", clusterName, "node-routetable")
   489  }
   490  
   491  // generateInternalLBName generates a internal load balancer name, based on the cluster name.
   492  func generateInternalLBName(clusterName string) string {
   493  	return fmt.Sprintf("%s-%s", clusterName, "internal-lb")
   494  }
   495  
   496  // generatePublicLBName generates a public load balancer name, based on the cluster name.
   497  func generatePublicLBName(clusterName string) string {
   498  	return fmt.Sprintf("%s-%s", clusterName, "public-lb")
   499  }
   500  
   501  // generateControlPlaneOutboundLBName generates the name of the control plane outbound LB.
   502  func generateControlPlaneOutboundLBName(clusterName string) string {
   503  	return fmt.Sprintf("%s-outbound-lb", clusterName)
   504  }
   505  
   506  // generatePublicIPName generates a public IP name, based on the cluster name and a hash.
   507  func generatePublicIPName(clusterName string) string {
   508  	return fmt.Sprintf("pip-%s-apiserver", clusterName)
   509  }
   510  
   511  // generateFrontendIPConfigName generates a load balancer frontend IP config name.
   512  func generateFrontendIPConfigName(lbName string) string {
   513  	return fmt.Sprintf("%s-%s", lbName, "frontEnd")
   514  }
   515  
   516  // generateNodeOutboundIPName generates a public IP name, based on the cluster name.
   517  func generateNodeOutboundIPName(clusterName string) string {
   518  	return fmt.Sprintf("pip-%s-node-outbound", clusterName)
   519  }
   520  
   521  // generateControlPlaneOutboundIPName generates a public IP name, based on the cluster name.
   522  func generateControlPlaneOutboundIPName(clusterName string) string {
   523  	return fmt.Sprintf("pip-%s-controlplane-outbound", clusterName)
   524  }
   525  
   526  // generateClusterNatGatewayName generates a NAT gateway name.
   527  func generateClusterNatGatewayName(clusterName string) string {
   528  	return fmt.Sprintf("%s-%s", clusterName, "natgw")
   529  }
   530  
   531  // generateNatGatewayName generates a NAT gateway name.
   532  func generateNatGatewayName(clusterName string) string {
   533  	return fmt.Sprintf("%s-%s", clusterName, "node-natgw")
   534  }
   535  
   536  // generateNatGatewayIPName generates a NAT gateway IP name.
   537  func generateNatGatewayIPName(natGatewayName string) string {
   538  	return fmt.Sprintf("pip-%s", natGatewayName)
   539  }
   540  
   541  // withIndex appends the index as suffix to a generated name.
   542  func withIndex(name string, n int) string {
   543  	return fmt.Sprintf("%s-%d", name, n)
   544  }
   545  
   546  // generateBackendAddressPoolName generates a load balancer backend address pool name.
   547  func generateBackendAddressPoolName(lbName string) string {
   548  	return fmt.Sprintf("%s-%s", lbName, "backendPool")
   549  }
   550  
   551  // generateOutboundBackendAddressPoolName generates a load balancer outbound backend address pool name.
   552  func generateOutboundBackendAddressPoolName(lbName string) string {
   553  	return fmt.Sprintf("%s-%s", lbName, "outboundBackendPool")
   554  }