@@ -18,6 +18,7 @@ package controller
1818
1919import (
2020 "context"
21+ "errors"
2122 "fmt"
2223 "math"
2324 "os"
@@ -38,13 +39,15 @@ import (
3839 "sigs.k8s.io/controller-runtime/pkg/predicate"
3940 "sigs.k8s.io/controller-runtime/pkg/reconcile"
4041
41- kwasmv1 "github.com/spinkube/runtime-class-manager/api/v1alpha1"
42+ rcmv1 "github.com/spinkube/runtime-class-manager/api/v1alpha1"
4243)
4344
4445const (
45- KwasmOperatorFinalizer = "kwasm.sh/finalizer"
46- INSTALL = "install"
47- UNINSTALL = "uninstall"
46+ RCMOperatorFinalizer = "rcm.spinkube.dev/finalizer"
47+ INSTALL = "install"
48+ UNINSTALL = "uninstall"
49+ ProvisioningStatusProvisioned = "provisioned"
50+ ProvisioningStatusPending = "pending"
4851)
4952
5053// ShimReconciler reconciles a Shim object
@@ -60,7 +63,7 @@ type ShimReconciler struct {
6063// SetupWithManager sets up the controller with the Manager.
6164func (sr * ShimReconciler ) SetupWithManager (mgr ctrl.Manager ) error {
6265 return ctrl .NewControllerManagedBy (mgr ).
63- For (& kwasmv1 .Shim {}).
66+ For (& rcmv1 .Shim {}).
6467 // As we create and own the created jobs
6568 // Jobs are important for us to update the Shims installation status
6669 // on respective nodes
@@ -91,12 +94,20 @@ func (sr *ShimReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
9194 ctx = log .WithContext (ctx )
9295
9396 // 1. Check if the shim resource exists
94- var shimResource kwasmv1 .Shim
97+ var shimResource rcmv1 .Shim
9598 if err := sr .Client .Get (ctx , req .NamespacedName , & shimResource ); err != nil {
9699 log .Err (err ).Msg ("Unable to fetch shimResource" )
97100 return ctrl.Result {}, client .IgnoreNotFound (err )
98101 }
99102
103+ // Ensure the finalizer is called even if a return happens before
104+ defer func () {
105+ err := sr .ensureFinalizerForShim (ctx , & shimResource , RCMOperatorFinalizer )
106+ if err != nil {
107+ log .Error ().Msgf ("Failed to ensure finalizer: %s" , err )
108+ }
109+ }()
110+
100111 // 2. Get list of nodes where this shim is supposed to be deployed on
101112 nodes , err := sr .getNodeListFromShimsNodeSelctor (ctx , & shimResource )
102113 if err != nil {
@@ -137,15 +148,11 @@ func (sr *ShimReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
137148 // 4. Deploy job to each node in list
138149 if len (nodes .Items ) > 0 {
139150 _ , err = sr .handleInstallShim (ctx , & shimResource , nodes )
140- if err != nil {
141- return ctrl.Result {}, err
142- }
143151 } else {
144152 log .Info ().Msg ("No nodes found" )
145153 }
146154
147- err = sr .ensureFinalizerForShim (ctx , & shimResource , KwasmOperatorFinalizer )
148- return ctrl.Result {}, client .IgnoreNotFound (err )
155+ return ctrl.Result {}, err
149156}
150157
151158// findShimsToReconcile finds all Shims that need to be reconciled.
@@ -154,7 +161,7 @@ func (sr *ShimReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
154161// that the shim is deployed on the node if it should be.
155162func (sr * ShimReconciler ) findShimsToReconcile (ctx context.Context , node client.Object ) []reconcile.Request {
156163 _ = node
157- shimList := & kwasmv1 .ShimList {}
164+ shimList := & rcmv1 .ShimList {}
158165 listOps := & client.ListOptions {
159166 Namespace : "" ,
160167 }
@@ -175,15 +182,15 @@ func (sr *ShimReconciler) findShimsToReconcile(ctx context.Context, node client.
175182 return requests
176183}
177184
178- func (sr * ShimReconciler ) updateStatus (ctx context.Context , shim * kwasmv1 .Shim , nodes * corev1.NodeList ) error {
185+ func (sr * ShimReconciler ) updateStatus (ctx context.Context , shim * rcmv1 .Shim , nodes * corev1.NodeList ) error {
179186 log := log .Ctx (ctx )
180187
181188 shim .Status .NodeCount = len (nodes .Items )
182189 shim .Status .NodeReadyCount = 0
183190
184191 if len (nodes .Items ) > 0 {
185192 for _ , node := range nodes .Items {
186- if node .Labels [shim .Name ] == "provisioned" {
193+ if node .Labels [shim .Name ] == ProvisioningStatusProvisioned {
187194 shim .Status .NodeReadyCount ++
188195 }
189196 }
@@ -205,43 +212,50 @@ func (sr *ShimReconciler) updateStatus(ctx context.Context, shim *kwasmv1.Shim,
205212}
206213
207214// handleInstallShim deploys a Job to each node in a list.
208- func (sr * ShimReconciler ) handleInstallShim (ctx context.Context , shim * kwasmv1 .Shim , nodes * corev1.NodeList ) (ctrl.Result , error ) {
215+ func (sr * ShimReconciler ) handleInstallShim (ctx context.Context , shim * rcmv1 .Shim , nodes * corev1.NodeList ) (ctrl.Result , error ) {
209216 log := log .Ctx (ctx )
210217
211218 switch shim .Spec .RolloutStrategy .Type {
212- case "rolling" :
219+ case rcmv1 . RolloutStrategyTypeRolling :
213220 {
214221 log .Debug ().Msgf ("Rolling strategy selected: maxUpdate=%d" , shim .Spec .RolloutStrategy .Rolling .MaxUpdate )
222+ return ctrl.Result {}, errors .New ("Rolling strategy not implemented yet" )
215223 }
216- case "recreate" :
224+ case rcmv1 . RolloutStrategyTypeRecreate :
217225 {
218226 log .Debug ().Msgf ("Recreate strategy selected" )
219- for i := range nodes .Items {
220- node := nodes .Items [i ]
221-
222- shimProvisioned := node .Labels [shim .Name ] == "provisioned"
223- shimPending := node .Labels [shim .Name ] == "pending"
224- if ! shimProvisioned && ! shimPending {
225- err := sr .deployJobOnNode (ctx , shim , node , INSTALL )
226- if err != nil {
227- return ctrl.Result {}, err
228- }
229- } else {
230- log .Info ().Msgf ("Shim %s already provisioned on Node %s" , shim .Name , node .Name )
231- }
232- }
227+ return sr .recreateStrategyRollout (ctx , shim , nodes )
233228 }
234229 default :
235230 {
236- log .Debug ().Msgf ("No rollout strategy selected; using default: rolling" )
231+ log .Debug ().Msgf ("No rollout strategy selected; using default: recreate" )
232+ return sr .recreateStrategyRollout (ctx , shim , nodes )
237233 }
238234 }
235+ }
239236
240- return ctrl.Result {}, nil
237+ func (sr * ShimReconciler ) recreateStrategyRollout (ctx context.Context , shim * rcmv1.Shim , nodes * corev1.NodeList ) (ctrl.Result , error ) {
238+ log := log .Ctx (ctx )
239+ shimInstallationErrors := []error {}
240+ for i := range nodes .Items {
241+ node := nodes .Items [i ]
242+
243+ shimProvisioned := node .Labels [shim .Name ] == ProvisioningStatusProvisioned
244+ shimPending := node .Labels [shim .Name ] == ProvisioningStatusPending
245+ if ! shimProvisioned && ! shimPending {
246+ err := sr .deployJobOnNode (ctx , shim , node , INSTALL )
247+ shimInstallationErrors = append (shimInstallationErrors , err )
248+ }
249+
250+ if shimProvisioned {
251+ log .Info ().Msgf ("Shim %s already provisioned on Node %s" , shim .Name , node .Name )
252+ }
253+ }
254+ return ctrl.Result {}, errors .Join (shimInstallationErrors ... )
241255}
242256
243257// deployUninstallJob deploys an uninstall Job for a Shim.
244- func (sr * ShimReconciler ) deployJobOnNode (ctx context.Context , shim * kwasmv1 .Shim , node corev1.Node , jobType string ) error {
258+ func (sr * ShimReconciler ) deployJobOnNode (ctx context.Context , shim * rcmv1 .Shim , node corev1.Node , jobType string ) error {
245259 log := log .Ctx (ctx )
246260
247261 if err := sr .Client .Get (ctx , types.NamespacedName {Name : node .Name }, & node ); err != nil {
@@ -255,7 +269,7 @@ func (sr *ShimReconciler) deployJobOnNode(ctx context.Context, shim *kwasmv1.Shi
255269
256270 switch jobType {
257271 case INSTALL :
258- err := sr .updateNodeLabels (ctx , & node , shim , "pending" )
272+ err := sr .updateNodeLabels (ctx , & node , shim , ProvisioningStatusPending )
259273 if err != nil {
260274 log .Error ().Msgf ("Unable to update node label %s: %s" , shim .Name , err )
261275 }
@@ -297,7 +311,7 @@ func (sr *ShimReconciler) deployJobOnNode(ctx context.Context, shim *kwasmv1.Shi
297311 return nil
298312}
299313
300- func (sr * ShimReconciler ) updateNodeLabels (ctx context.Context , node * corev1.Node , shim * kwasmv1 .Shim , status string ) error {
314+ func (sr * ShimReconciler ) updateNodeLabels (ctx context.Context , node * corev1.Node , shim * rcmv1 .Shim , status string ) error {
301315 node .Labels [shim .Name ] = status
302316
303317 if err := sr .Update (ctx , node ); err != nil {
@@ -308,16 +322,12 @@ func (sr *ShimReconciler) updateNodeLabels(ctx context.Context, node *corev1.Nod
308322}
309323
310324// createJobManifest creates a Job manifest for a Shim.
311- func (sr * ShimReconciler ) createJobManifest (shim * kwasmv1 .Shim , node * corev1.Node , operation string ) (* batchv1.Job , error ) {
325+ func (sr * ShimReconciler ) createJobManifest (shim * rcmv1 .Shim , node * corev1.Node , operation string ) (* batchv1.Job , error ) {
312326 priv := true
313327 name := node .Name + "-" + shim .Name + "-" + operation
314328 nameMax := int (math .Min (float64 (len (name )), 63 ))
315329
316330 job := & batchv1.Job {
317- TypeMeta : metav1.TypeMeta {
318- Kind : "Job" ,
319- APIVersion : "batch/v1" ,
320- },
321331 ObjectMeta : metav1.ObjectMeta {
322332 Name : name [:nameMax ],
323333 Namespace : os .Getenv ("CONTROLLER_NAMESPACE" ),
@@ -397,7 +407,7 @@ func (sr *ShimReconciler) createJobManifest(shim *kwasmv1.Shim, node *corev1.Nod
397407}
398408
399409// handleDeployRuntimeClass deploys a RuntimeClass for a Shim.
400- func (sr * ShimReconciler ) handleDeployRuntimeClass (ctx context.Context , shim * kwasmv1 .Shim ) (ctrl.Result , error ) {
410+ func (sr * ShimReconciler ) handleDeployRuntimeClass (ctx context.Context , shim * rcmv1 .Shim ) (ctrl.Result , error ) {
401411 log := log .Ctx (ctx )
402412
403413 log .Info ().Msgf ("Deploying RuntimeClass: %s" , shim .Spec .RuntimeClass .Name )
@@ -423,7 +433,7 @@ func (sr *ShimReconciler) handleDeployRuntimeClass(ctx context.Context, shim *kw
423433}
424434
425435// createRuntimeClassManifest creates a RuntimeClass manifest for a Shim.
426- func (sr * ShimReconciler ) createRuntimeClassManifest (shim * kwasmv1 .Shim ) (* nodev1.RuntimeClass , error ) {
436+ func (sr * ShimReconciler ) createRuntimeClassManifest (shim * rcmv1 .Shim ) (* nodev1.RuntimeClass , error ) {
427437 name := shim .Name
428438 nameMax := int (math .Min (float64 (len (name )), 63 ))
429439
@@ -433,14 +443,9 @@ func (sr *ShimReconciler) createRuntimeClassManifest(shim *kwasmv1.Shim) (*nodev
433443 }
434444
435445 runtimeClass := & nodev1.RuntimeClass {
436- TypeMeta : metav1.TypeMeta {
437- Kind : "RuntimeClass" ,
438- APIVersion : "node.k8s.io/v1" ,
439- },
440446 ObjectMeta : metav1.ObjectMeta {
441- Name : name [:nameMax ],
442- Namespace : os .Getenv ("CONTROLLER_NAMESPACE" ),
443- Labels : map [string ]string {name [:nameMax ]: "true" },
447+ Name : name [:nameMax ],
448+ Labels : map [string ]string {name [:nameMax ]: "true" },
444449 },
445450 Handler : shim .Spec .RuntimeClass .Handler ,
446451 Scheduling : & nodev1.Scheduling {
@@ -456,7 +461,7 @@ func (sr *ShimReconciler) createRuntimeClassManifest(shim *kwasmv1.Shim) (*nodev
456461}
457462
458463// handleDeleteShim deletes all possible child resources of a Shim. It will ignore NotFound errors.
459- func (sr * ShimReconciler ) handleDeleteShim (ctx context.Context , shim * kwasmv1 .Shim , nodes * corev1.NodeList ) error {
464+ func (sr * ShimReconciler ) handleDeleteShim (ctx context.Context , shim * rcmv1 .Shim , nodes * corev1.NodeList ) error {
460465 // deploy uninstall job on every node in node list
461466 for i := range nodes .Items {
462467 node := nodes .Items [i ]
@@ -473,15 +478,15 @@ func (sr *ShimReconciler) handleDeleteShim(ctx context.Context, shim *kwasmv1.Sh
473478 return nil
474479}
475480
476- func (sr * ShimReconciler ) getNodeListFromShimsNodeSelctor (ctx context.Context , shim * kwasmv1 .Shim ) (* corev1.NodeList , error ) {
481+ func (sr * ShimReconciler ) getNodeListFromShimsNodeSelctor (ctx context.Context , shim * rcmv1 .Shim ) (* corev1.NodeList , error ) {
477482 nodes := & corev1.NodeList {}
478483 if shim .Spec .NodeSelector != nil {
479- err := sr .List (ctx , nodes , client .InNamespace ( shim . Namespace ), client . MatchingLabels (shim .Spec .NodeSelector ))
484+ err := sr .List (ctx , nodes , client .MatchingLabels (shim .Spec .NodeSelector ))
480485 if err != nil {
481486 return & corev1.NodeList {}, fmt .Errorf ("failed to get node list: %w" , err )
482487 }
483488 } else {
484- err := sr .List (ctx , nodes , client . InNamespace ( shim . Namespace ) )
489+ err := sr .List (ctx , nodes )
485490 if err != nil {
486491 return & corev1.NodeList {}, fmt .Errorf ("failed to get node list: %w" , err )
487492 }
@@ -491,7 +496,7 @@ func (sr *ShimReconciler) getNodeListFromShimsNodeSelctor(ctx context.Context, s
491496}
492497
493498// runtimeClassExists checks whether a RuntimeClass for a Shim exists.
494- func (sr * ShimReconciler ) runtimeClassExists (ctx context.Context , shim * kwasmv1 .Shim ) (bool , error ) {
499+ func (sr * ShimReconciler ) runtimeClassExists (ctx context.Context , shim * rcmv1 .Shim ) (bool , error ) {
495500 log := log .Ctx (ctx )
496501
497502 if shim .Spec .RuntimeClass .Name != "" {
@@ -509,7 +514,7 @@ func (sr *ShimReconciler) runtimeClassExists(ctx context.Context, shim *kwasmv1.
509514}
510515
511516// getRuntimeClass finds a RuntimeClass.
512- func (sr * ShimReconciler ) getRuntimeClass (ctx context.Context , shim * kwasmv1 .Shim ) (* nodev1.RuntimeClass , error ) {
517+ func (sr * ShimReconciler ) getRuntimeClass (ctx context.Context , shim * rcmv1 .Shim ) (* nodev1.RuntimeClass , error ) {
513518 rc := nodev1.RuntimeClass {}
514519 err := sr .Client .Get (ctx , types.NamespacedName {Name : shim .Spec .RuntimeClass .Name , Namespace : shim .Namespace }, & rc )
515520 if err != nil {
@@ -519,9 +524,9 @@ func (sr *ShimReconciler) getRuntimeClass(ctx context.Context, shim *kwasmv1.Shi
519524}
520525
521526// removeFinalizerFromShim removes the finalizer from a Shim.
522- func (sr * ShimReconciler ) removeFinalizerFromShim (ctx context.Context , shim * kwasmv1 .Shim ) error {
523- if controllerutil .ContainsFinalizer (shim , KwasmOperatorFinalizer ) {
524- controllerutil .RemoveFinalizer (shim , KwasmOperatorFinalizer )
527+ func (sr * ShimReconciler ) removeFinalizerFromShim (ctx context.Context , shim * rcmv1 .Shim ) error {
528+ if controllerutil .ContainsFinalizer (shim , RCMOperatorFinalizer ) {
529+ controllerutil .RemoveFinalizer (shim , RCMOperatorFinalizer )
525530 if err := sr .Client .Update (ctx , shim ); err != nil {
526531 return fmt .Errorf ("failed to remove finalizer: %w" , err )
527532 }
@@ -530,7 +535,7 @@ func (sr *ShimReconciler) removeFinalizerFromShim(ctx context.Context, shim *kwa
530535}
531536
532537// ensureFinalizerForShim ensures the finalizer is present on a Shim resource.
533- func (sr * ShimReconciler ) ensureFinalizerForShim (ctx context.Context , shim * kwasmv1 .Shim , finalizer string ) error {
538+ func (sr * ShimReconciler ) ensureFinalizerForShim (ctx context.Context , shim * rcmv1 .Shim , finalizer string ) error {
534539 if ! controllerutil .ContainsFinalizer (shim , finalizer ) {
535540 controllerutil .AddFinalizer (shim , finalizer )
536541 if err := sr .Client .Update (ctx , shim ); err != nil {
0 commit comments