Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit ed3442f

Browse files
committed
feat: delete load balancers when clusters are deleted
Signed-off-by: Chris Privitere <[email protected]>
1 parent 105c296 commit ed3442f

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

controllers/packetcluster_controller.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package controllers
2020
import (
2121
"context"
2222
"errors"
23+
"fmt"
2324

2425
apierrors "k8s.io/apimachinery/pkg/api/errors"
2526
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -177,11 +178,26 @@ func (r *PacketClusterReconciler) reconcileNormal(ctx context.Context, clusterSc
177178
return nil
178179
}
179180

180-
func (r *PacketClusterReconciler) reconcileDelete(_ context.Context, _ *scope.ClusterScope) (ctrl.Result, error) {
181+
func (r *PacketClusterReconciler) reconcileDelete(ctx context.Context, clusterScope *scope.ClusterScope) (ctrl.Result, error) {
182+
log := ctrl.LoggerFrom(ctx).WithValues("cluster", clusterScope.Cluster.Name)
183+
log.Info("Reconciling PacketCluster Deletion")
184+
185+
packetCluster := clusterScope.PacketCluster
186+
187+
switch {
188+
case packetCluster.Spec.VIPManager == emlb.EMLBVIPID:
189+
// Create new EMLB object
190+
lb := emlb.NewEMLB(r.PacketClient.GetConfig().DefaultHeader["X-Auth-Token"], packetCluster.Spec.ProjectID, packetCluster.Spec.Metro)
191+
192+
if err := lb.DeleteLoadBalancer(ctx, clusterScope); err != nil {
193+
fmt.Println("It's ok!")
194+
}
195+
}
181196
// Initially I created this handler to remove an elastic IP when a cluster
182197
// gets delete, but it does not sound like a good idea. It is better to
183198
// leave to the users the ability to decide if they want to keep and resign
184199
// the IP or if they do not need it anymore
200+
185201
return ctrl.Result{}, nil
186202
}
187203

internal/emlb/emlb.go

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func NewEMLB(metalAPIKey, projectID, metro string) *EMLB {
9999
return manager
100100
}
101101

102-
// ReconcileLoadBalancer creates a new Equinix Metal Load Balancer.
102+
// ReconcileLoadBalancer creates a new Equinix Metal Load Balancer and associates it with the given ClusterScope.
103103
func (e *EMLB) ReconcileLoadBalancer(ctx context.Context, clusterScope *scope.ClusterScope) error {
104104
log := ctrl.LoggerFrom(ctx)
105105

@@ -233,6 +233,63 @@ func (e *EMLB) ReconcileVIPOrigin(ctx context.Context, machineScope *scope.Machi
233233
return nil
234234
}
235235

236+
// DeleteLoadBalancer deletes the Equinix Metal Load Balancer associated with a given ClusterScope.
237+
func (e *EMLB) DeleteLoadBalancer(ctx context.Context, clusterScope *scope.ClusterScope) error {
238+
log := ctrl.LoggerFrom(ctx)
239+
240+
packetCluster := clusterScope.PacketCluster
241+
clusterName := packetCluster.Name
242+
243+
// Make sure the cluster already has an EMLB ID in its packetCluster annotations, otherwise abort.
244+
lbID, exists := packetCluster.Annotations[loadBalancerIDAnnotation]
245+
if !exists || (lbID == "") {
246+
return fmt.Errorf("no Equinix Metal Load Balancer found in cluster's annotations")
247+
}
248+
249+
// See if the EMLB has a Port ID in its packetCluster annotations.
250+
lbPortNumber, exists := packetCluster.Annotations[loadBalancerPortNumberAnnotation]
251+
if !exists || (lbPortNumber == "") {
252+
return fmt.Errorf("no Equinix Metal Load Balancer Port Number found in cluster's annotations")
253+
}
254+
255+
log.Info("Deleting EMLB", "Cluster Metro", e.metro, "Cluster Name", clusterName, "Project ID", e.projectID, "Load Balancer ID", lbID)
256+
257+
// Fetch the Load Balancer object.
258+
lb, err := e.getLoadBalancer(ctx, lbID)
259+
if err != nil {
260+
log.Error(err, "failed to load the loadbalancer object, cannot proceed with deletion")
261+
return err
262+
}
263+
264+
// Get an int version of the listener port number.
265+
portNumber, err := strconv.ParseInt(lbPortNumber, 10, 32)
266+
if err != nil {
267+
log.Error(err, "failed to convert the loadbalancer port number to an int, cannot proceed with deletion")
268+
return err
269+
}
270+
271+
// Get the entire listener port object.
272+
lbPort, err := e.getLoadBalancerPort(ctx, lbID, int32(portNumber))
273+
if err != nil {
274+
log.Error(err, "failed to load the loadbalancer port object, cannot proceed with deletion")
275+
return err
276+
}
277+
278+
resp, err := e.deleteListenerPort(ctx, lbPort.GetId())
279+
if err != nil {
280+
log.Error(err, "LB Port Delete Failed", "EMLB ID", lb.GetId(), "Port ID", lbPort.GetId(), "Response Body", resp.Body)
281+
return err
282+
}
283+
284+
resp, err = e.deleteLoadBalancer(ctx, lb.GetId())
285+
if err != nil {
286+
log.Error(err, "LB Delete Failed", "EMLB ID", lb.GetId(), "Response Body", resp.Body)
287+
return err
288+
}
289+
290+
return nil
291+
}
292+
236293
// getLoadBalancer Returns a Load Balancer object given an id.
237294
func (e *EMLB) getLoadBalancer(ctx context.Context, id string) (*lbaas.LoadBalancer, error) {
238295
ctx = context.WithValue(ctx, lbaas.ContextOAuth2, e.tokenExchanger)
@@ -401,6 +458,22 @@ func (e *EMLB) createOrigin(ctx context.Context, poolID, originName string, targ
401458
return e.client.PoolsApi.CreateLoadBalancerPoolOrigin(ctx, poolID).LoadBalancerPoolOriginCreate(createOriginRequest).Execute()
402459
}
403460

461+
func (e *EMLB) deleteLoadBalancer(ctx context.Context, lbID string) (*http.Response, error) {
462+
return e.client.LoadBalancersApi.DeleteLoadBalancer(ctx, lbID).Execute()
463+
}
464+
465+
func (e *EMLB) deleteListenerPort(ctx context.Context, portID string) (*http.Response, error) {
466+
return e.client.PortsApi.DeleteLoadBalancerPort(ctx, portID).Execute()
467+
}
468+
469+
func (e *EMLB) deletePool(ctx context.Context, poolID string) (*http.Response, error) {
470+
return e.client.PoolsApi.DeleteLoadBalancerPool(ctx, poolID).Execute()
471+
}
472+
473+
func (e *EMLB) deleteOrigin(ctx context.Context, originID string) (*http.Response, error) {
474+
return e.client.OriginsApi.DeleteLoadBalancerOrigin(ctx, originID).Execute()
475+
}
476+
404477
func (e *EMLB) updateListenerPort(ctx context.Context, poolID, lbPortID string) (*lbaas.LoadBalancerPort, error) {
405478
ctx = context.WithValue(ctx, lbaas.ContextOAuth2, e.tokenExchanger)
406479

0 commit comments

Comments
 (0)