Skip to content

Commit

Permalink
fixup! refactor: updated IP controller for new ipam
Browse files Browse the repository at this point in the history
  • Loading branch information
fra98 committed Nov 15, 2024
1 parent 35247ce commit cffe693
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 27 deletions.
2 changes: 1 addition & 1 deletion apis/ipam/v1alpha1/ip_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type IPSpec struct {
// NetworkRef is the reference to the Network CR containing the CIDR where the desired IP should be allocated from.
// It is optional, if left empty the IP will be allocated in a default network CIDR (e.g., external CIDR).
// +kubebuilder:validation:Optional
NetworkRef *v1.ObjectReference `json:"cidr,omitempty"`
NetworkRef *v1.ObjectReference `json:"networkRef,omitempty"`
// ServiceTemplate contains the template to create the associated service (and endpointslice) for the IP endopoint.
// If empty the creation of the service is disabled (default).
// +kubebuilder:validation:Optional
Expand Down
26 changes: 13 additions & 13 deletions deployments/liqo/charts/liqo-crds/crds/ipam.liqo.io_ips.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,19 @@ spec:
spec:
description: IPSpec defines a local IP.
properties:
cidr:
ip:
description: IP is the local IP.
format: ipv4
type: string
x-kubernetes-validations:
- message: IP field is immutable
rule: self == oldSelf
masquerade:
description: |-
Masquerade is a flag to enable masquerade for the local IP on nodes.
If empty the masquerade is disabled.
type: boolean
networkRef:
description: |-
NetworkRef is the reference to the Network CR containing the CIDR where the desired IP should be allocated from.
It is optional, if left empty the IP will be allocated in a default network CIDR (e.g., external CIDR).
Expand Down Expand Up @@ -99,18 +111,6 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
ip:
description: IP is the local IP.
format: ipv4
type: string
x-kubernetes-validations:
- message: IP field is immutable
rule: self == oldSelf
masquerade:
description: |-
Masquerade is a flag to enable masquerade for the local IP on nodes.
If empty the masquerade is disabled.
type: boolean
serviceTemplate:
description: |-
ServiceTemplate contains the template to create the associated service (and endpointslice) for the IP endopoint.
Expand Down
5 changes: 5 additions & 0 deletions pkg/consts/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ const (
// IPTypeAPIServerProxy is the constant representing an IP of type APIServerProxy.
IPTypeAPIServerProxy = "api-server-proxy"

// NetworkNamespaceLabelKey is the label key used to indicate the namespace of a Network.
NetworkNamespaceLabelKey = "ipam.liqo.io/network-namespace"
// NetworkNameLabelKey is the label key used to indicate the name of a Network.
NetworkNameLabelKey = "ipam.liqo.io/network-name"

// DefaultCIDRValue is the default value for a string that contains a CIDR.
DefaultCIDRValue = "None"
)
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
networkingv1beta1 "github.com/liqotech/liqo/apis/networking/v1beta1"
Expand All @@ -45,6 +50,9 @@ type IPReconciler struct {
Scheme *runtime.Scheme

ipamClient ipam.IPAMClient

externalCidrRef v1.ObjectReference
externalCidr networkingv1beta1.CIDR
}

// NewIPReconciler returns a new IPReconciler.
Expand All @@ -61,6 +69,7 @@ func NewIPReconciler(cl client.Client, s *runtime.Scheme, ipamClient ipam.IPAMCl
// +kubebuilder:rbac:groups=ipam.liqo.io,resources=ips/status,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ipam.liqo.io,resources=ips/finalizers,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ipam.liqo.io,resources=networks,verbs=get;list;watch
// +kubebuilder:rbac:groups=ipam.liqo.io,resources=networks/status,verbs=get;list;watch
// +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=discovery.k8s.io,resources=endpointslices,verbs=get;list;watch;create;update;patch;delete

Expand All @@ -77,7 +86,7 @@ func (r *IPReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re
return ctrl.Result{}, err
}

_, cidr, err := r.handleNetworkRef(ctx, &ip)
networkRef, cidr, err := r.handleNetworkRef(ctx, &ip)
if err != nil {
klog.Errorf("error while handling NetworkRef for IP %q: %v", req.NamespacedName, err)
return ctrl.Result{}, err
Expand All @@ -99,6 +108,18 @@ func (r *IPReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Re
return ctrl.Result{}, nil
}

// Add network reference to the IP in the labels. This is used to trigger the reconciliation
// of the IP by watching deletion events of the father Network.
if ip.Labels == nil {
ip.Labels = make(map[string]string)
}
ip.Labels[consts.NetworkNamespaceLabelKey] = networkRef.Namespace
ip.Labels[consts.NetworkNameLabelKey] = networkRef.Name
if err := r.Update(ctx, &ip); err != nil {
klog.Errorf("error while updating IP %q: %v", req.NamespacedName, err)
return ctrl.Result{}, err
}

if ip.Status.IP == "" {
if err := r.forgeIPStatus(ctx, &ip, cidr); err != nil {
klog.Errorf("error while forging IP status for IP %q: %v", req.NamespacedName, err)
Expand Down Expand Up @@ -146,35 +167,76 @@ func (r *IPReconciler) SetupWithManager(mgr ctrl.Manager, workers int) error {
For(&ipamv1alpha1.IP{}).
Owns(&v1.Service{}).
Owns(&discoveryv1.EndpointSlice{}).
Watches(&ipamv1alpha1.Network{},
handler.EnqueueRequestsFromMapFunc(r.ipEnqueuerFromNetwork),
builder.WithPredicates(nwPredicates)).
WithOptions(controller.Options{MaxConcurrentReconciles: workers}).
Complete(r)
}

var nwPredicates = predicate.Funcs{
CreateFunc: func(_ event.CreateEvent) bool { return false },
UpdateFunc: func(_ event.UpdateEvent) bool { return false },
DeleteFunc: func(_ event.DeleteEvent) bool { return true },
GenericFunc: func(_ event.GenericEvent) bool { return false },
}

func (r *IPReconciler) ipEnqueuerFromNetwork(ctx context.Context, obj client.Object) []ctrl.Request {
var requests []reconcile.Request

// Get the IPs associated with the Network.
var ipList ipamv1alpha1.IPList
if err := r.List(ctx, &ipList, client.MatchingLabels{
consts.NetworkNamespaceLabelKey: obj.GetNamespace(),
consts.NetworkNameLabelKey: obj.GetName(),
}); err != nil {
klog.Errorf("error while listing IPs associated with Network %q: %v", client.ObjectKeyFromObject(obj), err)
return nil
}

// Enqueue reconcile requests for each IP associated with the Network.
for i := range ipList.Items {
requests = append(requests, reconcile.Request{
NamespacedName: client.ObjectKeyFromObject(&ipList.Items[i]),
})
}

return requests
}

// handleNetworkRef get the CIDR of the Network referenced by the IP, or default to the
// external CIDR of the local cluster if the IP has no NetworkRef set.
func (r *IPReconciler) handleNetworkRef(ctx context.Context, ip *ipamv1alpha1.IP) (*ipamv1alpha1.Network, networkingv1beta1.CIDR, error) {
func (r *IPReconciler) handleNetworkRef(ctx context.Context, ip *ipamv1alpha1.IP) (*v1.ObjectReference, networkingv1beta1.CIDR, error) {
// If the IP has not set a reference to a Network CIDR, we remap it on the external CIDR of the local cluster.
if ip.Spec.NetworkRef == nil {
network, err := ipamutils.GetExternalCIDRNetwork(ctx, r.Client)
if err != nil {
return nil, "", err
}
// The externalCIDR Network has no CIDR set yet, we return an error.
if network.Status.CIDR == "" {
return nil, "", fmt.Errorf("externalCIDR is not set yet. Configure it to correctly handle IP mapping")
if r.externalCidr == "" {
network, err := ipamutils.GetExternalCIDRNetwork(ctx, r.Client)
if err != nil {
return nil, "", err
}
// The externalCIDR Network has no CIDR set yet, we return an error.
if network.Status.CIDR == "" {
return nil, "", fmt.Errorf("externalCIDR is not set yet. Configure it to correctly handle IP mapping")
}

r.externalCidrRef = v1.ObjectReference{
Namespace: network.Namespace,
Name: network.Name,
}
r.externalCidr = network.Status.CIDR
}
return network, network.Status.CIDR, nil
return &r.externalCidrRef, r.externalCidr, nil
}

// Retrieve the Network object referenced by the IP.
var network ipamv1alpha1.Network
if err := r.Get(ctx, client.ObjectKey{Namespace: ip.Spec.NetworkRef.Namespace, Name: ip.Spec.NetworkRef.Name}, &network); err != nil {
return nil, "", err
}
if network.Status.CIDR != "" {
if network.Status.CIDR == "" {
return nil, "", fmt.Errorf("network %s/%s has no CIDR set yet", network.Namespace, network.Name)
}
return &network, network.Status.CIDR, nil
return ip.Spec.NetworkRef, network.Status.CIDR, nil
}

// forgeIPStatus forge the IP status.
Expand Down
3 changes: 2 additions & 1 deletion pkg/liqoctl/authenticate/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
authv1beta1 "github.com/liqotech/liqo/apis/authentication/v1beta1"
liqov1beta1 "github.com/liqotech/liqo/apis/core/v1beta1"
ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
"github.com/liqotech/liqo/pkg/consts"
authutils "github.com/liqotech/liqo/pkg/liqo-controller-manager/authentication/utils"
"github.com/liqotech/liqo/pkg/liqoctl/factory"
"github.com/liqotech/liqo/pkg/liqoctl/output"
Expand Down Expand Up @@ -220,7 +221,7 @@ func (c *Cluster) GetAPIServerProxyRemappedIP(ctx context.Context) (string, erro
var ip ipamv1alpha1.IP
err := c.local.CRClient.Get(ctx, types.NamespacedName{
Namespace: c.local.LiqoNamespace,
Name: "api-server-proxy",
Name: consts.IPTypeAPIServerProxy,
}, &ip)
if err != nil {
return "", err
Expand Down

0 comments on commit cffe693

Please sign in to comment.