@@ -26,6 +26,7 @@ import (
2626 "sync"
2727 "time"
2828
29+ jsonpatch "github.com/evanphx/json-patch/v5"
2930 cnstypes "github.com/vmware/govmomi/cns/types"
3031 v1 "k8s.io/api/core/v1"
3132 apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -1173,10 +1174,11 @@ func validateAndFixPVVolumeMode(ctx context.Context, k8sclient clientset.Interfa
11731174func setInstanceError (ctx context.Context , r * ReconcileCnsRegisterVolume ,
11741175 instance * cnsregistervolumev1alpha1.CnsRegisterVolume , errMsg string ) {
11751176 log := logger .GetLogger (ctx )
1177+ origInstance := instance .DeepCopy ()
11761178 instance .Status .Error = errMsg
1177- err := k8s . UpdateStatus (ctx , r .client , instance )
1179+ err := patchCnsRegisterVolumeStatus (ctx , r .client , origInstance , instance )
11781180 if err != nil {
1179- log .Errorf ("updateCnsRegisterVolume failed. err: %v" , err )
1181+ log .Errorf ("patchCnsRegisterVolumeStatus failed. err: %v" , err )
11801182 return
11811183 }
11821184 recordEvent (ctx , r , instance , v1 .EventTypeWarning , errMsg )
@@ -1205,11 +1207,12 @@ func setInstanceSuccess(ctx context.Context, r *ReconcileCnsRegisterVolume,
12051207 return err
12061208 }
12071209 // Now update the status subresource with the fresh object
1210+ origInstance := instance .DeepCopy ()
12081211 instance .Status .Registered = true
12091212 instance .Status .Error = ""
1210- err = k8s . UpdateStatus (ctx , r .client , instance )
1213+ err = patchCnsRegisterVolumeStatus (ctx , r .client , origInstance , instance )
12111214 if err != nil {
1212- log .Errorf ("updateCnsRegisterVolume status failed. err: %v" , err )
1215+ log .Errorf ("patchCnsRegisterVolumeStatus failed. err: %v" , err )
12131216 return err
12141217 }
12151218 recordEvent (ctx , r , instance , v1 .EventTypeNormal , msg )
@@ -1273,3 +1276,51 @@ func updateCnsRegisterVolume(ctx context.Context, client client.Client,
12731276 }
12741277 return err
12751278}
1279+
1280+ func getPatchData (oldObj , newObj interface {}) ([]byte , error ) {
1281+ oldData , err := json .Marshal (oldObj )
1282+ if err != nil {
1283+ return nil , fmt .Errorf ("marshal old object failed: %v" , err )
1284+ }
1285+ newData , err := json .Marshal (newObj )
1286+ if err != nil {
1287+ return nil , fmt .Errorf ("marshal new object failed: %v" , err )
1288+ }
1289+ patchBytes , err := jsonpatch .CreateMergePatch (oldData , newData )
1290+ if err != nil {
1291+ return nil , fmt .Errorf ("CreateMergePatch failed: %v" , err )
1292+ }
1293+ return patchBytes , nil
1294+ }
1295+
1296+ // patchCnsRegisterVolumeStatus patches status field of CnsRegisterVolume instance in K8S.
1297+ func patchCnsRegisterVolumeStatus (ctx context.Context , cnsOperatorClient client.Client ,
1298+ oldObj * cnsregistervolumev1alpha1.CnsRegisterVolume ,
1299+ newObj * cnsregistervolumev1alpha1.CnsRegisterVolume ) error {
1300+ log := logger .GetLogger (ctx )
1301+ patch , err := getPatchData (oldObj , newObj )
1302+ if err != nil {
1303+ log .Errorf ("error fetching PatchData CnsRegisterVolume CR. err: %v" , err )
1304+ return err
1305+ }
1306+ rawPatch := client .RawPatch (apitypes .MergePatchType , patch )
1307+ // Try to patch CnsRegisterVolume CR for 3 times
1308+ allowedRetries := 3
1309+ attempt := 0
1310+ for {
1311+ attempt ++
1312+ err = cnsOperatorClient .Status ().Patch (ctx , oldObj , rawPatch )
1313+ if err != nil && attempt >= allowedRetries {
1314+ log .Errorf ("failed to patch CnsRegisterVolume instance %q on namespace %q, Error: %+v" ,
1315+ oldObj .Name , oldObj .Namespace , err )
1316+ return err
1317+ } else if err == nil {
1318+ log .Debugf ("Successfully patched CnsRegisterVolume instance %q on namespace %q" ,
1319+ oldObj .Name , oldObj .Namespace )
1320+ return nil
1321+ }
1322+ log .Warnf ("attempt %d, failed to patch CnsRegisterVolume instance %q on namespace %q with error %+v, " +
1323+ "will retry..." , attempt , oldObj .Name , oldObj .Namespace , err )
1324+ time .Sleep (100 * time .Millisecond )
1325+ }
1326+ }
0 commit comments