Skip to content

Commit

Permalink
Refactor loadbalancer config package. (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit91 authored Oct 28, 2024
1 parent 6807b30 commit 71c7d3e
Show file tree
Hide file tree
Showing 14 changed files with 520 additions and 329 deletions.
27 changes: 6 additions & 21 deletions metal/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"io"
"os"
"slices"
"strings"

metalgo "github.com/metal-stack/metal-go"
Expand All @@ -13,8 +12,7 @@ import (
"github.com/metal-stack/metal-ccm/pkg/controllers/housekeeping"
"github.com/metal-stack/metal-ccm/pkg/controllers/instances"
"github.com/metal-stack/metal-ccm/pkg/controllers/loadbalancer"
"github.com/metal-stack/metal-ccm/pkg/controllers/loadbalancer/cilium"
"github.com/metal-stack/metal-ccm/pkg/controllers/loadbalancer/metallb"
"github.com/metal-stack/metal-ccm/pkg/controllers/loadbalancer/config"
"github.com/metal-stack/metal-ccm/pkg/controllers/zones"
"github.com/metal-stack/metal-ccm/pkg/resources/constants"
"github.com/metal-stack/metal-ccm/pkg/resources/metal"
Expand Down Expand Up @@ -49,6 +47,10 @@ func NewCloud(_ io.Reader) (cloudprovider.Interface, error) {
partitionID := os.Getenv(constants.MetalPartitionIDEnvVar)
clusterID := os.Getenv(constants.MetalClusterIDEnvVar)
defaultExternalNetworkID := os.Getenv(constants.MetalDefaultExternalNetworkEnvVar)
loadbalancerType, err := config.LoadBalancerTypeFromString(os.Getenv(constants.Loadbalancer))
if err != nil {
return nil, err
}

var (
additionalNetworksString = os.Getenv(constants.MetalAdditionalNetworks)
Expand Down Expand Up @@ -81,7 +83,6 @@ func NewCloud(_ io.Reader) (cloudprovider.Interface, error) {
return nil, fmt.Errorf("environment variable %q or %q is required", constants.MetalAuthTokenEnvVar, constants.MetalAuthHMACEnvVar)
}

var err error
metalclient, err = metalgo.NewDriver(url, token, hmac)
if err != nil {
return nil, fmt.Errorf("unable to initialize metal ccm:%w", err)
Expand All @@ -97,7 +98,7 @@ func NewCloud(_ io.Reader) (cloudprovider.Interface, error) {

instancesController := instances.New(defaultExternalNetworkID)
zonesController := zones.New()
loadBalancerController := loadbalancer.New(partitionID, projectID, clusterID, defaultExternalNetworkID, additionalNetworks)
loadBalancerController := loadbalancer.New(partitionID, projectID, clusterID, defaultExternalNetworkID, additionalNetworks, loadbalancerType)

klog.Info("initialized cloud controller manager")
return &cloud{
Expand All @@ -116,11 +117,6 @@ func (c *cloud) Initialize(clientBuilder cloudprovider.ControllerClientBuilder,
projectID := os.Getenv(constants.MetalProjectIDEnvVar)
sshPublicKey := os.Getenv(constants.MetalSSHPublicKey)
clusterID := os.Getenv(constants.MetalClusterIDEnvVar)
loadbalancerType := os.Getenv(constants.Loadbalancer)

if !slices.Contains([]string{"cilium", "metallb", ""}, loadbalancerType) {
klog.Fatalf("only cilium or metallb load balancer types are supported")
}

k8sClientSet := clientBuilder.ClientOrDie("cloud-controller-manager")
k8sRestConfig, err := clientBuilder.Config("cloud-controller-manager")
Expand All @@ -145,24 +141,13 @@ func (c *cloud) Initialize(clientBuilder cloudprovider.ControllerClientBuilder,
klog.Fatalf("unable to create k8s client: %v", err)
}

var config loadbalancer.LoadBalancerConfig
switch loadbalancerType {
case "metallb":
config = metallb.NewMetalLBConfig()
case "cilium":
config = cilium.NewCiliumConfig(k8sClientSet)
default:
config = metallb.NewMetalLBConfig()
}

housekeeper := housekeeping.New(metalclient, stop, c.loadBalancer, k8sClientSet, projectID, sshPublicKey, clusterID)
ms := metal.New(metalclient, k8sClientSet, projectID)

c.instances.MetalService = ms
c.loadBalancer.K8sClientSet = k8sClientSet
c.loadBalancer.K8sClient = k8sClient
c.loadBalancer.MetalService = ms
c.loadBalancer.Config = config
c.zones.MetalService = ms

go housekeeper.Run()
Expand Down
4 changes: 2 additions & 2 deletions pkg/controllers/housekeeping/housekeeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ func (h *Housekeeper) watchNodes() {
oldNode := oldObj.(*v1.Node)
newNode := newObj.(*v1.Node)

oldTunnelAddress, _ := loadbalancer.NodeAddress(*oldNode)
newTunnelAddress, err := loadbalancer.NodeAddress(*newNode)
oldTunnelAddress, _ := kubernetes.NodeAddress(*oldNode)
newTunnelAddress, err := kubernetes.NodeAddress(*newNode)
if err != nil {
klog.Error("newNode does not have a tunnelAddress, ignoring")
return
Expand Down
58 changes: 0 additions & 58 deletions pkg/controllers/loadbalancer/addresspool.go

This file was deleted.

122 changes: 0 additions & 122 deletions pkg/controllers/loadbalancer/config.go

This file was deleted.

83 changes: 83 additions & 0 deletions pkg/controllers/loadbalancer/config/addresspool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package config

import (
"errors"
"fmt"
"net/netip"
"slices"
"strings"

"github.com/metal-stack/metal-go/api/models"
"github.com/metal-stack/metal-lib/pkg/pointer"
)

const (
bgpProtocol = "bgp"
)

type addressPool struct {
Name string
Protocol string
AutoAssign *bool
CIDRs []string // It is assumed that only host addresses (/32 for ipv4 or /128 for ipv6) are used.
}

type addressPools []addressPool

func newBGPAddressPool(name string) addressPool {
return addressPool{
Name: name,
Protocol: bgpProtocol,
AutoAssign: pointer.Pointer(false),
}
}

func (pool *addressPool) appendIP(ip *models.V1IPResponse) error {
if ip.Ipaddress == nil {
return errors.New("ip address is not set on ip")
}

parsed, err := netip.ParseAddr(*ip.Ipaddress)
if err != nil {
return err
}

cidr := fmt.Sprintf("%s/%d", parsed.String(), parsed.BitLen())

if slices.ContainsFunc(pool.CIDRs, func(elem string) bool {
return cidr == elem
}) {
return nil
}

pool.CIDRs = append(pool.CIDRs, cidr)

return nil
}

func (as addressPools) addPoolIP(poolName string, ip *models.V1IPResponse) (addressPools, error) {
idx := slices.IndexFunc(as, func(a addressPool) bool {
return a.Name == poolName
})

if idx < 0 {
as = append(as, newBGPAddressPool(poolName))
idx = 0
}

err := as[idx].appendIP(ip)
if err != nil {
return nil, err
}

return as, nil
}

func getPoolName(network string, ip *models.V1IPResponse) string {
poolType := models.V1IPBaseTypeEphemeral
if pointer.SafeDeref(ip.Type) == models.V1IPBaseTypeStatic {
poolType = models.V1IPBaseTypeStatic
}

return fmt.Sprintf("%s-%s", strings.ToLower(network), poolType)
}
Loading

0 comments on commit 71c7d3e

Please sign in to comment.