@@ -22,6 +22,7 @@ import (
2222 "sync"
2323
2424 corev1 "k8s.io/api/core/v1"
25+ "k8s.io/apimachinery/pkg/types"
2526 "sigs.k8s.io/controller-runtime/pkg/client"
2627 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2728 logf "sigs.k8s.io/controller-runtime/pkg/log"
@@ -268,24 +269,38 @@ func NewAnnoAllocationSyncer(client client.Client) AllocationSyncer {
268269}
269270
270271func (syncer * annoAllocationSyncer ) SetAllocation (ctx context.Context , sandbox * sandboxv1alpha1.BatchSandbox , allocation * SandboxAllocation ) error {
271- old , ok := sandbox . DeepCopyObject ().( * sandboxv1alpha1. BatchSandbox )
272- if ! ok {
273- return fmt . Errorf ( "invalid object" )
272+ js , err := json . Marshal ( allocation )
273+ if err != nil {
274+ return err
274275 }
275276 anno := sandbox .GetAnnotations ()
276277 if anno == nil {
277278 anno = make (map [string ]string )
278279 }
279- js , err := json .Marshal (allocation )
280+ anno [AnnoAllocStatusKey ] = string (js )
281+ sandbox .SetAnnotations (anno )
282+
283+ needAddFinalizer := ! controllerutil .ContainsFinalizer (sandbox , FinalizerPoolAllocation )
284+ if needAddFinalizer {
285+ sandbox .SetFinalizers (append (sandbox .GetFinalizers (), FinalizerPoolAllocation ))
286+ }
287+
288+ meta := map [string ]any {
289+ "annotations" : map [string ]string {
290+ AnnoAllocStatusKey : string (js ),
291+ },
292+ }
293+ if needAddFinalizer {
294+ meta ["finalizers" ] = sandbox .GetFinalizers ()
295+ }
296+ patchData , err := json .Marshal (map [string ]any {"metadata" : meta })
280297 if err != nil {
281298 return err
282299 }
283- anno [AnnoAllocStatusKey ] = string (js )
284- sandbox .SetAnnotations (anno )
285- // Add finalizer to ensure the sandbox is not deleted before all pods are recycled.
286- controllerutil .AddFinalizer (sandbox , FinalizerPoolAllocation )
287- patch := client .MergeFrom (old )
288- return syncer .client .Patch (ctx , sandbox , patch )
300+ obj := & sandboxv1alpha1.BatchSandbox {}
301+ obj .Name = sandbox .Name
302+ obj .Namespace = sandbox .Namespace
303+ return syncer .client .Patch (ctx , obj , client .RawPatch (types .MergePatchType , patchData ))
289304}
290305
291306func (syncer * annoAllocationSyncer ) GetAllocation (ctx context.Context , sandbox * sandboxv1alpha1.BatchSandbox ) (* SandboxAllocation , error ) {
@@ -340,20 +355,18 @@ func (syncer *annoAllocationSyncer) GetReleased(ctx context.Context, sandbox *sa
340355}
341356
342357func (syncer * annoAllocationSyncer ) SetReleased (ctx context.Context , sandbox * sandboxv1alpha1.BatchSandbox , released * AllocationReleased ) error {
343- old , ok := sandbox . DeepCopyObject ().( * sandboxv1alpha1. BatchSandbox )
344- if ! ok {
345- return fmt . Errorf ( "invalid object" )
358+ js , err := json . Marshal ( released )
359+ if err != nil {
360+ return err
346361 }
347362 anno := sandbox .GetAnnotations ()
348363 if anno == nil {
349364 anno = make (map [string ]string )
350365 }
351- js , err := json .Marshal (released )
352- if err != nil {
353- return err
354- }
355366 anno [AnnoAllocReleasedKey ] = string (js )
356367 sandbox .SetAnnotations (anno )
368+
369+ needRemoveFinalizer := false
357370 // If the sandbox is being deleted and all allocated pods have been released,
358371 // remove the finalizer so the sandbox can be garbage collected.
359372 if ! sandbox .DeletionTimestamp .IsZero () {
@@ -372,12 +385,34 @@ func (syncer *annoAllocationSyncer) SetReleased(ctx context.Context, sandbox *sa
372385 break
373386 }
374387 }
375- if allReleased {
376- controllerutil .RemoveFinalizer (sandbox , FinalizerPoolAllocation )
388+ if allReleased && controllerutil .ContainsFinalizer (sandbox , FinalizerPoolAllocation ) {
389+ needRemoveFinalizer = true
390+ filtered := make ([]string , 0 , len (sandbox .GetFinalizers ()))
391+ for _ , f := range sandbox .GetFinalizers () {
392+ if f != FinalizerPoolAllocation {
393+ filtered = append (filtered , f )
394+ }
395+ }
396+ sandbox .SetFinalizers (filtered )
377397 }
378398 }
379- patch := client .MergeFrom (old )
380- return syncer .client .Patch (ctx , sandbox , patch )
399+
400+ meta := map [string ]any {
401+ "annotations" : map [string ]string {
402+ AnnoAllocReleasedKey : string (js ),
403+ },
404+ }
405+ if needRemoveFinalizer {
406+ meta ["finalizers" ] = sandbox .GetFinalizers ()
407+ }
408+ patchData , err := json .Marshal (map [string ]any {"metadata" : meta })
409+ if err != nil {
410+ return err
411+ }
412+ obj := & sandboxv1alpha1.BatchSandbox {}
413+ obj .Name = sandbox .Name
414+ obj .Namespace = sandbox .Namespace
415+ return syncer .client .Patch (ctx , obj , client .RawPatch (types .MergePatchType , patchData ))
381416}
382417
383418type AllocSpec struct {
0 commit comments