github.com/ironcore-dev/gardener-extension-provider-ironcore@v0.3.2-0.20240314231816-8336447fb9a0/pkg/controller/bastion/utils.go (about)

     1  // SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package bastion
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"strings"
    10  
    11  	extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
    12  	computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
    13  )
    14  
    15  // generateBastionHostResourceName returns a unique name for the Bastion host in
    16  // the Gardener Kubernetes cluster, based on the cluster name, Bastion name, and
    17  // UID. The function concatenates these values and truncates the resulting
    18  // string to 63 characters, if necessary, to comply with the Kubernetes naming
    19  // convention. In rare cases, this truncation may result in non-unique names,
    20  // but the likelihood of this happening is extremely low.
    21  func generateBastionHostResourceName(clusterName string, bastion *extensionsv1alpha1.Bastion) (string, error) {
    22  	bastionName := bastion.Name
    23  	if bastionName == "" {
    24  		return "", fmt.Errorf("bastionName can not be empty")
    25  	}
    26  	if clusterName == "" {
    27  		return "", fmt.Errorf("clusterName can not be empty")
    28  	}
    29  	staticName := clusterName + "-" + bastionName
    30  	nameSuffix := strings.Split(string(bastion.UID), "-")[0]
    31  	name := fmt.Sprintf("%s-bastion-%s", staticName, nameSuffix)
    32  	if len(name) > 63 {
    33  		name = name[:63]
    34  	}
    35  	return name, nil
    36  }
    37  
    38  func getIgnitionNameForMachine(machineName string) string {
    39  	return fmt.Sprintf("%s-%s", machineName, "ignition")
    40  }
    41  
    42  // getPrivateAndVirtualIPsFromNetworkInterfaces extracts the private IPv4 and
    43  // virtual IPv4 addresses from the given slice of NetworkInterfaceStatus
    44  // objects.
    45  //
    46  // If a network interface has multiple private IPs, only the first one will be
    47  // returned. If multiple network interfaces have a virtual IP, only the first
    48  // one will be returned.
    49  //
    50  // TODO: IPv6 addresses are ignored for now and will be
    51  // added in the future once Gardener extension supports IPv6.
    52  func getPrivateAndVirtualIPsFromNetworkInterfaces(networkInterfaces []computev1alpha1.NetworkInterfaceStatus) (string, string, error) {
    53  	var privateIP, virtualIP string
    54  
    55  	for _, ni := range networkInterfaces {
    56  		if ni.IPs == nil {
    57  			return "", "", fmt.Errorf("no private ip found for network interface: %s", ni.Name)
    58  		}
    59  		for _, ip := range ni.IPs {
    60  			parsedIP := net.ParseIP(ip.String())
    61  			if parsedIP == nil {
    62  				continue // skip invalid IP
    63  			}
    64  			if parsedIP.To4() != nil {
    65  				privateIP = parsedIP.String()
    66  				break
    67  			} else {
    68  				// IPv6 case
    69  				continue
    70  			}
    71  		}
    72  		if ni.VirtualIP != nil {
    73  			parsedIP := net.ParseIP(ni.VirtualIP.String())
    74  			if parsedIP == nil {
    75  				continue // skip invalid IP
    76  			}
    77  			if parsedIP.To4() != nil {
    78  				virtualIP = parsedIP.String()
    79  				break
    80  			} else {
    81  				// IPv6 case
    82  				continue
    83  			}
    84  		}
    85  	}
    86  	if privateIP == "" {
    87  		return "", "", fmt.Errorf("private IPv4 address not found")
    88  	}
    89  	if virtualIP == "" {
    90  		return "", "", fmt.Errorf("virtual IPv4 address not found")
    91  	}
    92  
    93  	return privateIP, virtualIP, nil
    94  }