Skip to content

Commit 38c8863

Browse files
committed
Use Patch() to update status of CnsRegisterVolume CR insteaf of Update()
1 parent 9442b14 commit 38c8863

File tree

6 files changed

+349
-8
lines changed

6 files changed

+349
-8
lines changed

manifests/supervisorcluster/1.29/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ rules:
5959
verbs: ["get", "list", "update", "create", "delete"]
6060
- apiGroups: ["cns.vmware.com"]
6161
resources: ["cnsregistervolumes", "cnsregistervolumes/status", "cnsunregistervolumes", "cnsunregistervolumes/status"]
62-
verbs: ["get", "list", "watch", "update", "delete"]
62+
verbs: ["get", "list", "watch", "update", "delete", "patch"]
6363
- apiGroups: ["cns.vmware.com"]
6464
resources: ["triggercsifullsyncs"]
6565
verbs: ["create", "get", "update", "watch", "list"]

manifests/supervisorcluster/1.30/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ rules:
5959
verbs: ["get", "list", "update", "create", "delete"]
6060
- apiGroups: ["cns.vmware.com"]
6161
resources: ["cnsregistervolumes", "cnsregistervolumes/status", "cnsunregistervolumes", "cnsunregistervolumes/status"]
62-
verbs: ["get", "list", "watch", "update", "delete"]
62+
verbs: ["get", "list", "watch", "update", "delete", "patch"]
6363
- apiGroups: ["cns.vmware.com"]
6464
resources: ["triggercsifullsyncs"]
6565
verbs: ["create", "get", "update", "watch", "list"]

manifests/supervisorcluster/1.31/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ rules:
5959
verbs: ["get", "list", "update", "create", "delete"]
6060
- apiGroups: ["cns.vmware.com"]
6161
resources: ["cnsregistervolumes", "cnsregistervolumes/status", "cnsunregistervolumes", "cnsunregistervolumes/status"]
62-
verbs: ["get", "list", "watch", "update", "delete"]
62+
verbs: ["get", "list", "watch", "update", "delete", "patch"]
6363
- apiGroups: ["cns.vmware.com"]
6464
resources: ["triggercsifullsyncs"]
6565
verbs: ["create", "get", "update", "watch", "list"]

manifests/supervisorcluster/1.32/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ rules:
5959
verbs: ["get", "list", "update", "create", "delete"]
6060
- apiGroups: ["cns.vmware.com"]
6161
resources: ["cnsregistervolumes", "cnsregistervolumes/status", "cnsunregistervolumes", "cnsunregistervolumes/status"]
62-
verbs: ["get", "list", "watch", "update", "delete"]
62+
verbs: ["get", "list", "watch", "update", "delete", "patch"]
6363
- apiGroups: ["cns.vmware.com"]
6464
resources: ["triggercsifullsyncs"]
6565
verbs: ["create", "get", "update", "watch", "list"]

pkg/syncer/cnsoperator/controller/cnsregistervolume/cnsregistervolume_controller.go

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,10 +1173,12 @@ func validateAndFixPVVolumeMode(ctx context.Context, k8sclient clientset.Interfa
11731173
func setInstanceError(ctx context.Context, r *ReconcileCnsRegisterVolume,
11741174
instance *cnsregistervolumev1alpha1.CnsRegisterVolume, errMsg string) {
11751175
log := logger.GetLogger(ctx)
1176+
origInstance := instance.DeepCopy()
1177+
instance.Status.Registered = false
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,59 @@ func updateCnsRegisterVolume(ctx context.Context, client client.Client,
12731276
}
12741277
return err
12751278
}
1279+
1280+
// patchCnsRegisterVolumeStatus patches status field of CnsRegisterVolume instance in K8S.
1281+
// For status subresources with required fields, we need to ensure those fields are always
1282+
// included in the patch, even if they haven't changed. This is because Kubernetes validates
1283+
// the patch against the CRD schema which marks 'registered' as required.
1284+
func patchCnsRegisterVolumeStatus(ctx context.Context, cnsOperatorClient client.Client,
1285+
oldObj *cnsregistervolumev1alpha1.CnsRegisterVolume,
1286+
newObj *cnsregistervolumev1alpha1.CnsRegisterVolume) error {
1287+
log := logger.GetLogger(ctx)
1288+
1289+
// For status patches with required fields, we use a simple JSON patch that always
1290+
// includes required status fields to satisfy CRD validation
1291+
var statusPatch map[string]interface{}
1292+
if newObj.Status.Error != "" {
1293+
statusPatch = map[string]interface{}{
1294+
"status": map[string]interface{}{
1295+
"registered": newObj.Status.Registered,
1296+
"error": newObj.Status.Error,
1297+
},
1298+
}
1299+
} else {
1300+
statusPatch = map[string]interface{}{
1301+
"status": map[string]interface{}{
1302+
"registered": newObj.Status.Registered,
1303+
},
1304+
}
1305+
}
1306+
1307+
patchBytes, err := json.Marshal(statusPatch)
1308+
if err != nil {
1309+
log.Errorf("failed to marshal status patch. err: %v", err)
1310+
return err
1311+
}
1312+
1313+
rawPatch := client.RawPatch(apitypes.MergePatchType, patchBytes)
1314+
1315+
// Try to patch CnsRegisterVolume CR for 3 times
1316+
allowedRetries := 3
1317+
attempt := 0
1318+
for {
1319+
attempt++
1320+
err := cnsOperatorClient.Status().Patch(ctx, oldObj, rawPatch)
1321+
if err != nil && attempt >= allowedRetries {
1322+
log.Errorf("failed to patch CnsRegisterVolume instance %q on namespace %q, Error: %+v",
1323+
oldObj.Name, oldObj.Namespace, err)
1324+
return err
1325+
} else if err == nil {
1326+
log.Debugf("Successfully patched CnsRegisterVolume instance %q on namespace %q",
1327+
oldObj.Name, oldObj.Namespace)
1328+
return nil
1329+
}
1330+
log.Warnf("attempt %d, failed to patch CnsRegisterVolume instance %q on namespace %q with error %+v, "+
1331+
"will retry...", attempt, oldObj.Name, oldObj.Namespace, err)
1332+
time.Sleep(100 * time.Millisecond)
1333+
}
1334+
}

0 commit comments

Comments
 (0)