@@ -36,12 +36,15 @@ import (
36
36
"sigs.k8s.io/controller-runtime/pkg/builder"
37
37
"sigs.k8s.io/controller-runtime/pkg/client"
38
38
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
39
+ "sigs.k8s.io/controller-runtime/pkg/event"
39
40
"sigs.k8s.io/controller-runtime/pkg/handler"
40
41
"sigs.k8s.io/controller-runtime/pkg/log"
41
42
"sigs.k8s.io/controller-runtime/pkg/predicate"
42
43
"sigs.k8s.io/controller-runtime/pkg/reconcile"
43
44
)
44
45
46
+ const CrusoeClusterIDFlag = "crusoe-cluster-id" //nolint:gosec // false positive, this is a flag name
47
+
45
48
// ServiceReconciler reconciles a Service object
46
49
type ServiceReconciler struct {
47
50
client.Client
@@ -229,8 +232,19 @@ func (r *ServiceReconciler) handleCreate(ctx context.Context, svc *corev1.Servic
229
232
healthCheckOptions := ParseHealthCheckOptionsFromAnnotations (svc .Annotations )
230
233
231
234
// Prepare payload for the API call
235
+ // get vpc id
236
+ cluster , _ , err := r .CrusoeClient .KubernetesClustersApi .GetCluster (ctx , r .HostInstance .ProjectId , viper .GetString (CrusoeClusterIDFlag ))
237
+ if err != nil {
238
+ logger .Error (err , "Failed to get cluster" , "clusterID" , viper .GetString (CrusoeClusterIDFlag ))
239
+ return ctrl.Result {}, err
240
+ }
241
+ subnet , _ , err := r .CrusoeClient .VPCSubnetsApi .GetVPCSubnet (ctx , r .HostInstance .ProjectId , cluster .SubnetId )
242
+ if err != nil {
243
+ logger .Error (err , "Failed to get vpc network id from cluster subnet id " , "subnetID" , cluster .SubnetId )
244
+ return ctrl.Result {}, err
245
+ }
232
246
apiPayload := crusoeapi.ExternalLoadBalancerPostRequest {
233
- VpcId : viper . GetString ( CrusoeVPCIDFlag ) ,
247
+ VpcId : subnet . VpcNetworkId ,
234
248
Name : svc .Name ,
235
249
Location : r .HostInstance .Location ,
236
250
Protocol : "LOAD_BALANCER_PROTOCOL_TCP" , // only TCP supported currently
@@ -369,6 +383,40 @@ func (r *ServiceReconciler) SetupWithManager(mgr ctrl.Manager) error {
369
383
return ok && svc .Spec .Type == corev1 .ServiceTypeLoadBalancer
370
384
})
371
385
386
+ nodeCreateDeletePredicate := predicate.Funcs {
387
+ // Called for new Node objects
388
+ CreateFunc : func (e event.CreateEvent ) bool {
389
+ return true
390
+ },
391
+ // Called for Node updates e.g. node from not ready to ready
392
+ UpdateFunc : func (e event.UpdateEvent ) bool {
393
+ oldNode , oldOk := e .ObjectOld .(* corev1.Node )
394
+ newNode , newOk := e .ObjectNew .(* corev1.Node )
395
+ if ! oldOk || ! newOk {
396
+ return false
397
+ }
398
+
399
+ oldReady := isNodeReady (oldNode )
400
+ newReady := isNodeReady (newNode )
401
+
402
+ // Only trigger if the node transitioned from NotReady -> Ready or vice versa
403
+ if oldReady != newReady {
404
+ log .Log .Info ("Node readiness changed" , "node" , newNode .Name , "oldReady" , oldReady , "newReady" , newReady )
405
+ return true
406
+ }
407
+
408
+ return false // Skip other updates
409
+ },
410
+ // Called for Node deletions
411
+ DeleteFunc : func (e event.DeleteEvent ) bool {
412
+ return true
413
+ },
414
+ // Rare, generic events are usually no-ops here
415
+ GenericFunc : func (e event.GenericEvent ) bool {
416
+ return false
417
+ },
418
+ }
419
+
372
420
mapNodeToLBServices := handler .EnqueueRequestsFromMapFunc (func (ctx context.Context , obj client.Object ) []reconcile.Request {
373
421
374
422
node , ok := obj .(* corev1.Node )
@@ -398,15 +446,16 @@ func (r *ServiceReconciler) SetupWithManager(mgr ctrl.Manager) error {
398
446
},
399
447
)
400
448
return ctrl .NewControllerManagedBy (mgr ).
401
- // Watch only Service objects of type=LoadBalancer
449
+ // Watch Service objects of type=LoadBalancer
402
450
For (
403
451
& corev1.Service {},
404
452
builder .WithPredicates (loadBalancerPredicate ),
405
453
).
406
- // Also watch Node events, with no filter so they pass
454
+ // Also watch Node events to update backends list
407
455
Watches (
408
456
& corev1.Node {},
409
457
mapNodeToLBServices ,
458
+ builder .WithPredicates (nodeCreateDeletePredicate ),
410
459
).
411
460
Complete (r )
412
461
0 commit comments