anexia-it/k8s-anexia-ccm

View on GitHub
anx/provider/loadbalancer/address/prefix.go

Summary

Maintainability
A
35 mins
Test Coverage
B
85%
package address
 
import (
"context"
"errors"
"fmt"
"net"
"net/http"
 
"github.com/go-logr/logr"
"go.anx.io/go-anxcloud/pkg/api"
"go.anx.io/go-anxcloud/pkg/api/types"
corev1 "go.anx.io/go-anxcloud/pkg/apis/core/v1"
"go.anx.io/go-anxcloud/pkg/ipam"
v1 "k8s.io/api/core/v1"
)
 
type prefix struct {
identifier string
prefix net.IPNet
family v1.IPFamily
addresses []net.IP
}
 
Function `newPrefix` has 5 arguments (exceeds 4 allowed). Consider refactoring.
func newPrefix(ctx context.Context, apiclient api.API, ipamClient ipam.API, identifier string, autoDiscoveryName *string) (*prefix, error) {
p, err := ipamClient.Prefix().Get(ctx, identifier)
if err != nil {
return nil, err
}
 
_, n, err := net.ParseCIDR(p.Name)
if err != nil {
return nil, err
}
 
ret := prefix{
identifier: identifier,
prefix: *n,
family: v1.IPv6Protocol,
}
 
if n.IP.To4() != nil {
ret.family = v1.IPv4Protocol
}
 
if autoDiscoveryName != nil {
tag := fmt.Sprintf("kubernetes-lb-vip-%s", *autoDiscoveryName)
vip, err := ret.discoverVIP(ctx, apiclient, ipamClient, tag)
if err != nil {
return nil, fmt.Errorf("error discovering VIP: %w", err)
}
 
if vip == nil {
// Fall back for backwards compatibility - remove once there are no autodiscovery clusters without tagged VIPs
vip = calculateVIP(ret.prefix)
logger := logr.FromContextOrDiscard(ctx)
logger.Info("Could not auto discover VIP, falling back to calculated VIP", "prefix-identifier", ret.identifier, "vip", vip.String())
}
 
ret.addresses = []net.IP{vip}
} else {
ret.addresses = []net.IP{calculateVIP(ret.prefix)}
}
 
return &ret, nil
}
 
func (p prefix) allocateAddress(ctx context.Context, fam v1.IPFamily) (net.IP, error) {
if fam != p.family {
return nil, errFamilyMismatch
}
 
log := logr.FromContextOrDiscard(ctx).WithValues(
"prefix", p.prefix.String(),
"prefix-identifier", p.identifier,
)
 
XXX found
// XXX: replace this with IPAM address allocation logic once we can add and remove LoadBalancer IPs
// See SYSENG-918 for more info.
ip := p.addresses[0]
 
log.V(1).Info(
"allocated external IP",
"prefix", p.prefix.String(),
"address", ip.String(),
)
 
return ip, nil
}
 
func (p prefix) discoverVIP(ctx context.Context, apiClient api.API, ipamClient ipam.API, tag string) (net.IP, error) {
logger := logr.FromContextOrDiscard(ctx)
 
ctx, cancel := context.WithCancel(ctx)
defer cancel()
 
var oc types.ObjectChannel
err := apiClient.List(ctx, &corev1.Resource{Tags: []string{tag}}, api.ObjectChannel(&oc))
if err != nil {
httpError := api.HTTPError{}
// nothing is tagged with autodiscover tag -> no VIP found, but also no error
if errors.As(err, &httpError) && httpError.StatusCode() == http.StatusUnprocessableEntity {
err = nil
} else {
err = fmt.Errorf("unable to autodiscover VIP address by tag %q: %w", tag, err)
}
 
return nil, err
}
 
for retriever := range oc {
var res corev1.Resource
err := retriever(&res)
if err != nil {
return nil, fmt.Errorf("error retrieving resource: %w", err)
}
 
address, err := ipamClient.Address().Get(ctx, res.Identifier)
if err != nil {
logger.Error(err, "Error retrieving Address, maybe something else is tagged with %q? Ignoring this one and continuing",
"identifier", res.Identifier,
)
continue
}
 
// If the address we discovered is not from the prefix for which we are allocating, skip it
if address.PrefixID != p.identifier {
continue
}
 
logger.V(1).Info("Found VIP Address via auto discovery", "identifier", address.ID)
return net.ParseIP(address.Name), err
}
 
// no VIP found, but also no error
return nil, nil
 
}