@@ -18,6 +18,7 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
+ "fmt"
21
22
"sync"
22
23
23
24
"github.com/pkg/errors"
@@ -34,10 +35,13 @@ import (
34
35
"sigs.k8s.io/controller-runtime/pkg/controller"
35
36
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
36
37
"sigs.k8s.io/controller-runtime/pkg/handler"
38
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
37
39
"sigs.k8s.io/controller-runtime/pkg/source"
38
40
39
41
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
42
+ "sigs.k8s.io/cluster-api/api/v1beta1/index"
40
43
"sigs.k8s.io/cluster-api/controllers/external"
44
+ "sigs.k8s.io/cluster-api/controllers/noderefutil"
41
45
"sigs.k8s.io/cluster-api/controllers/remote"
42
46
expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
43
47
"sigs.k8s.io/cluster-api/util"
@@ -62,6 +66,7 @@ const (
62
66
type MachinePoolReconciler struct {
63
67
Client client.Client
64
68
APIReader client.Reader
69
+ Tracker * remote.ClusterCacheTracker
65
70
66
71
// WatchFilterValue is the label value used to filter events prior to reconciliation.
67
72
WatchFilterValue string
@@ -289,3 +294,80 @@ func (r *MachinePoolReconciler) reconcileDeleteExternal(ctx context.Context, m *
289
294
// Return true if there are no more external objects.
290
295
return len (objects ) == 0 , nil
291
296
}
297
+
298
+ func (r * MachinePoolReconciler ) watchClusterNodes (ctx context.Context , cluster * clusterv1.Cluster ) error {
299
+ log := ctrl .LoggerFrom (ctx )
300
+
301
+ if ! conditions .IsTrue (cluster , clusterv1 .ControlPlaneInitializedCondition ) {
302
+ log .V (5 ).Info ("Skipping node watching setup because control plane is not initialized" )
303
+ return nil
304
+ }
305
+
306
+ // If there is no tracker, don't watch remote nodes
307
+ if r .Tracker == nil {
308
+ return nil
309
+ }
310
+
311
+ return r .Tracker .Watch (ctx , remote.WatchInput {
312
+ Name : "machinepool-watchNodes" ,
313
+ Cluster : util .ObjectKey (cluster ),
314
+ Watcher : r .controller ,
315
+ Kind : & corev1.Node {},
316
+ EventHandler : handler .EnqueueRequestsFromMapFunc (r .nodeToMachinePool ),
317
+ })
318
+ }
319
+
320
+ func (r * MachinePoolReconciler ) nodeToMachinePool (o client.Object ) []reconcile.Request {
321
+ node , ok := o .(* corev1.Node )
322
+ if ! ok {
323
+ panic (fmt .Sprintf ("Expected a Node but got a %T" , o ))
324
+ }
325
+
326
+ var filters []client.ListOption
327
+ // Match by clusterName when the node has the annotation.
328
+ if clusterName , ok := node .GetAnnotations ()[clusterv1 .ClusterNameAnnotation ]; ok {
329
+ filters = append (filters , client.MatchingLabels {
330
+ clusterv1 .ClusterNameLabel : clusterName ,
331
+ })
332
+ }
333
+
334
+ // Match by namespace when the node has the annotation.
335
+ if namespace , ok := node .GetAnnotations ()[clusterv1 .ClusterNamespaceAnnotation ]; ok {
336
+ filters = append (filters , client .InNamespace (namespace ))
337
+ }
338
+
339
+ // Match by nodeName and status.nodeRef.name.
340
+ machinePoolList := & expv1.MachinePoolList {}
341
+ if err := r .Client .List (
342
+ context .TODO (),
343
+ machinePoolList ,
344
+ append (filters , client.MatchingFields {index .MachinePoolNodeNameField : node .Name })... ); err != nil {
345
+ return nil
346
+ }
347
+
348
+ // There should be exactly 1 MachinePool for the node.
349
+ if len (machinePoolList .Items ) == 1 {
350
+ return []reconcile.Request {{NamespacedName : util .ObjectKey (& machinePoolList .Items [0 ])}}
351
+ }
352
+
353
+ // Otherwise let's match by providerID. This is useful when e.g the NodeRef has not been set yet.
354
+ // Match by providerID
355
+ nodeProviderID , err := noderefutil .NewProviderID (node .Spec .ProviderID )
356
+ if err != nil {
357
+ return nil
358
+ }
359
+ machinePoolList = & expv1.MachinePoolList {}
360
+ if err := r .Client .List (
361
+ context .TODO (),
362
+ machinePoolList ,
363
+ append (filters , client.MatchingFields {index .MachinePoolProviderIDField : nodeProviderID .IndexKey ()})... ); err != nil {
364
+ return nil
365
+ }
366
+
367
+ // There should be exactly 1 MachinePool for the node.
368
+ if len (machinePoolList .Items ) == 1 {
369
+ return []reconcile.Request {{NamespacedName : util .ObjectKey (& machinePoolList .Items [0 ])}}
370
+ }
371
+
372
+ return nil
373
+ }
0 commit comments