@@ -30,6 +30,7 @@ import (
30
30
"sigs.k8s.io/controller-runtime/pkg/log"
31
31
)
32
32
33
+ //+kubebuilder:rbac:groups="core",resources=namespaces,verbs=get;list;patch;watch
33
34
//+kubebuilder:rbac:groups="core",resources=nodes,verbs=get;watch
34
35
//+kubebuilder:rbac:groups=kmm.sigs.x-k8s.io,resources=nodemodulesconfigs,verbs=get;list;watch;patch;create;delete
35
36
@@ -47,6 +48,7 @@ type schedulingData struct {
47
48
48
49
type ModuleNMCReconciler struct {
49
50
filter * filter.Filter
51
+ nsLabeler namespaceLabeler
50
52
reconHelper moduleNMCReconcilerHelperAPI
51
53
}
52
54
@@ -59,6 +61,7 @@ func NewModuleNMCReconciler(client client.Client,
59
61
reconHelper := newModuleNMCReconcilerHelper (client , kernelAPI , registryAPI , nmcHelper , scheme )
60
62
return & ModuleNMCReconciler {
61
63
filter : filter ,
64
+ nsLabeler : newNamespaceLabeler (client ),
62
65
reconHelper : reconHelper ,
63
66
}
64
67
}
@@ -78,13 +81,21 @@ func (mnr *ModuleNMCReconciler) Reconcile(ctx context.Context, req ctrl.Request)
78
81
}
79
82
if mod .GetDeletionTimestamp () != nil {
80
83
//Module is being deleted
84
+ if err = mnr .nsLabeler .tryRemovingLabel (ctx , mod .Namespace , mod .Name ); err != nil {
85
+ return ctrl.Result {}, fmt .Errorf ("error while trying to remove the label on namespace %s: %v" , mod .Namespace , err )
86
+ }
87
+
81
88
err = mnr .reconHelper .finalizeModule (ctx , mod )
82
89
if err != nil {
83
90
return ctrl.Result {}, fmt .Errorf ("failed to finalize %s Module: %v" , req .NamespacedName , err )
84
91
}
85
92
return ctrl.Result {}, nil
86
93
}
87
94
95
+ if err = mnr .nsLabeler .setLabel (ctx , mod .Namespace ); err != nil {
96
+ return ctrl.Result {}, fmt .Errorf ("could not set label %q on namespace %s: %v" , constants .NamespaceLabelKey , mod .Namespace , err )
97
+ }
98
+
88
99
err = mnr .reconHelper .setFinalizerAndStatus (ctx , mod )
89
100
if err != nil {
90
101
return ctrl.Result {}, fmt .Errorf ("failed to set finalizer on %s Module: %v" , req .NamespacedName , err )
@@ -145,7 +156,7 @@ func (mnr *ModuleNMCReconciler) SetupWithManager(mgr ctrl.Manager) error {
145
156
Complete (mnr )
146
157
}
147
158
148
- //go:generate mockgen -source=module_nmc_reconciler.go -package=controllers -destination=mock_module_nmc_reconciler.go moduleNMCReconcilerHelperAPI
159
+ //go:generate mockgen -source=module_nmc_reconciler.go -package=controllers -destination=mock_module_nmc_reconciler.go moduleNMCReconcilerHelperAPI,namespaceLabeler
149
160
150
161
type moduleNMCReconcilerHelperAPI interface {
151
162
setFinalizerAndStatus (ctx context.Context , mod * kmmv1beta1.Module ) error
@@ -439,6 +450,80 @@ func (mnrh *moduleNMCReconcilerHelper) moduleUpdateWorkerPodsStatus(ctx context.
439
450
return mnrh .client .Status ().Patch (ctx , mod , client .MergeFrom (unmodifiedMod ))
440
451
}
441
452
453
+ type namespaceLabeler interface {
454
+ setLabel (ctx context.Context , name string ) error
455
+ tryRemovingLabel (ctx context.Context , name , moduleName string ) error
456
+ }
457
+
458
+ type namespaceLabelerImpl struct {
459
+ client client.Client
460
+ }
461
+
462
+ func newNamespaceLabeler (client client.Client ) namespaceLabeler {
463
+ return & namespaceLabelerImpl {client : client }
464
+ }
465
+
466
+ func (h * namespaceLabelerImpl ) setLabel (ctx context.Context , name string ) error {
467
+ logger := log .FromContext (ctx )
468
+
469
+ ns := v1.Namespace {}
470
+
471
+ if err := h .client .Get (ctx , types.NamespacedName {Name : name }, & ns ); err != nil {
472
+ return fmt .Errorf ("could not get namespace %s: %v" , name , err )
473
+ }
474
+
475
+ if ! meta .HasLabel (& ns , constants .NamespaceLabelKey ) {
476
+ nsCopy := ns .DeepCopy ()
477
+
478
+ logger .Info ("Setting namespace label" )
479
+ meta .SetLabel (& ns , constants .NamespaceLabelKey , "" )
480
+
481
+ return h .client .Patch (ctx , & ns , client .MergeFrom (nsCopy ))
482
+ }
483
+
484
+ return nil
485
+ }
486
+
487
+ func (h * namespaceLabelerImpl ) tryRemovingLabel (ctx context.Context , name , moduleName string ) error {
488
+ logger := log .FromContext (ctx )
489
+
490
+ modList := kmmv1beta1.ModuleList {}
491
+
492
+ opt := client .InNamespace (name )
493
+
494
+ if err := h .client .List (ctx , & modList , opt ); err != nil {
495
+ return fmt .Errorf ("could not list modules in namespace %s: %v" , name , err )
496
+ }
497
+
498
+ if count := len (modList .Items ); count > 1 {
499
+ logger .Info ("Namespace still contains modules; not removing the label" , "count" , count )
500
+
501
+ if verboseLogger := logger .V (1 ); verboseLogger .Enabled () {
502
+ modNames := make ([]string , 0 , count )
503
+
504
+ for _ , m := range modList .Items {
505
+ modNames = append (modNames , m .Name )
506
+ }
507
+
508
+ verboseLogger .Info ("Remaining modules" , "names" , modNames )
509
+ }
510
+
511
+ return nil
512
+ }
513
+
514
+ ns := & v1.Namespace {}
515
+
516
+ if err := h .client .Get (ctx , types.NamespacedName {Name : name }, ns ); err != nil {
517
+ return fmt .Errorf ("could not get namespace %s: %v" , name , err )
518
+ }
519
+
520
+ nsCopy := ns .DeepCopy ()
521
+
522
+ meta .RemoveLabel (ns , constants .NamespaceLabelKey )
523
+
524
+ return h .client .Patch (ctx , ns , client .MergeFrom (nsCopy ))
525
+ }
526
+
442
527
func prepareNodeSchedulingData (node v1.Node , mld * api.ModuleLoaderData , currentNMCs sets.Set [string ]) schedulingData {
443
528
versionLabel := ""
444
529
present := false
0 commit comments