Skip to content

Commit 862388b

Browse files
committed
Enhancement - Optimise CNSFileAccessConfig reconciliation workflow
Updated reconciler to use status subresource endpoint to update status Updated reconciler to ignore updates without any generation change
1 parent b96d98d commit 862388b

File tree

7 files changed

+79
-76
lines changed

7 files changed

+79
-76
lines changed

manifests/supervisorcluster/1.29/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ rules:
4646
resources: ["volumeattachments/status"]
4747
verbs: ["patch"]
4848
- apiGroups: ["cns.vmware.com"]
49-
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs"]
49+
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs", "cnsfileaccessconfigs/status"]
5050
verbs: ["get", "list", "watch", "update"]
5151
- apiGroups: ["cns.vmware.com"]
5252
resources: ["cnsnodevmattachments", "cnsnodevmbatchattachments", "cnsnodevmbatchattachments/status", "cnsnodevmattachments/status"]

manifests/supervisorcluster/1.30/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ rules:
4646
resources: ["volumeattachments/status"]
4747
verbs: ["patch"]
4848
- apiGroups: ["cns.vmware.com"]
49-
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs"]
49+
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs", "cnsfileaccessconfigs/status"]
5050
verbs: ["get", "list", "watch", "update"]
5151
- apiGroups: ["cns.vmware.com"]
5252
resources: ["cnsnodevmattachments", "cnsnodevmbatchattachments", "cnsnodevmbatchattachments/status", "cnsnodevmattachments/status"]

manifests/supervisorcluster/1.31/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ rules:
4646
resources: ["volumeattachments/status"]
4747
verbs: ["patch"]
4848
- apiGroups: ["cns.vmware.com"]
49-
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs"]
49+
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs", "cnsfileaccessconfigs/status"]
5050
verbs: ["get", "list", "watch", "update"]
5151
- apiGroups: ["cns.vmware.com"]
5252
resources: ["cnsnodevmattachments", "cnsnodevmbatchattachments", "cnsnodevmbatchattachments/status", "cnsnodevmattachments/status"]

manifests/supervisorcluster/1.32/cns-csi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ rules:
4646
resources: ["volumeattachments/status"]
4747
verbs: ["patch"]
4848
- apiGroups: ["cns.vmware.com"]
49-
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs"]
49+
resources: ["cnsvolumemetadatas", "cnsfileaccessconfigs", "cnsfileaccessconfigs/status"]
5050
verbs: ["get", "list", "watch", "update"]
5151
- apiGroups: ["cns.vmware.com"]
5252
resources: ["cnsnodevmattachments", "cnsnodevmbatchattachments", "cnsnodevmbatchattachments/status", "cnsnodevmattachments/status"]

pkg/apis/cnsoperator/config/cnsfileaccessconfig_crd.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ spec:
7474
type: object
7575
served: true
7676
storage: true
77+
subresources:
78+
status: {}
7779
status:
7880
acceptedNames:
7981
kind: ""

pkg/kubernetes/kubernetes.go

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import (
5151
ccV1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
5252
"sigs.k8s.io/controller-runtime/pkg/client"
5353
apiutils "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
54+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
5455
cr_log "sigs.k8s.io/controller-runtime/pkg/log"
5556

5657
"github.com/go-logr/zapr"
@@ -798,14 +799,48 @@ func DeletePersistentVolume(ctx context.Context, k8sClient clientset.Interface,
798799
// If the object is a Custom Resource, make sure that the `subresources` field in the
799800
// CustomResourceDefinition includes `status` to enable status subresource updates.
800801
func UpdateStatus(ctx context.Context, c client.Client, obj client.Object) error {
801-
log := logger.GetLogger(ctx)
802+
log := logger.GetLogger(ctx).
803+
With("kind", obj.GetObjectKind().GroupVersionKind().Kind).
804+
With("name", obj.GetNamespace()+"/"+obj.GetName())
802805
if err := c.Status().Update(ctx, obj); err != nil {
803-
log.Errorf("Failed to update status for %s %s/%s: %v", obj.GetObjectKind().GroupVersionKind().Kind,
804-
obj.GetNamespace(), obj.GetName(), err)
806+
log.Errorf("Failed to update status. err: %v", err)
805807
return err
806808
}
807809

808-
log.Infof("Successfully updated status for %s %s/%s", obj.GetObjectKind().GroupVersionKind().Kind,
809-
obj.GetNamespace(), obj.GetName())
810+
log.Debug("Successfully updated status.")
810811
return nil
811812
}
813+
814+
// AddFinalizer adds the specified finalizer to the given Kubernetes object if it is not already present.
815+
// It updates the object in the Kubernetes cluster to persist the change.
816+
func AddFinalizer(ctx context.Context, c client.Client, obj client.Object, finalizer string) error {
817+
log := logger.GetLogger(ctx).
818+
With("finalizer", finalizer).
819+
With("kind", obj.GetObjectKind().GroupVersionKind().Kind).
820+
With("name", obj.GetNamespace()+"/"+obj.GetName())
821+
822+
if !controllerutil.AddFinalizer(obj, finalizer) {
823+
log.Debug("Finalizer already present. No update needed.")
824+
return nil
825+
}
826+
827+
log.Info("Adding finalizer to object.")
828+
return c.Update(ctx, obj)
829+
}
830+
831+
// RemoveFinalizer removes the specified finalizer from the given Kubernetes object if it is present.
832+
// It updates the object in the Kubernetes cluster to persist the change.
833+
func RemoveFinalizer(ctx context.Context, c client.Client, obj client.Object, finalizer string) error {
834+
log := logger.GetLogger(ctx).
835+
With("finalizer", finalizer).
836+
With("kind", obj.GetObjectKind().GroupVersionKind().Kind).
837+
With("name", obj.GetNamespace()+"/"+obj.GetName())
838+
839+
if !controllerutil.RemoveFinalizer(obj, finalizer) {
840+
log.Debug("Finalizer not present. No update needed.")
841+
return nil
842+
}
843+
844+
log.Info("Removing finalizer from object.")
845+
return c.Update(ctx, obj)
846+
}

pkg/syncer/cnsoperator/controller/cnsfileaccessconfig/cnsfileaccessconfig_controller.go

Lines changed: 33 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ import (
3636
"k8s.io/client-go/kubernetes/scheme"
3737
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
3838
"k8s.io/client-go/tools/record"
39+
ctrl "sigs.k8s.io/controller-runtime"
3940
"sigs.k8s.io/controller-runtime/pkg/client"
4041
"sigs.k8s.io/controller-runtime/pkg/client/config"
4142
"sigs.k8s.io/controller-runtime/pkg/controller"
4243
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
43-
"sigs.k8s.io/controller-runtime/pkg/handler"
4444
"sigs.k8s.io/controller-runtime/pkg/manager"
45+
"sigs.k8s.io/controller-runtime/pkg/predicate"
4546
"sigs.k8s.io/controller-runtime/pkg/reconcile"
46-
"sigs.k8s.io/controller-runtime/pkg/source"
4747
cnsoperatorapis "sigs.k8s.io/vsphere-csi-driver/v3/pkg/apis/cnsoperator"
48-
cnsfileaccessconfigv1alpha1 "sigs.k8s.io/vsphere-csi-driver/v3/pkg/apis/cnsoperator/cnsfileaccessconfig/v1alpha1"
48+
v1a1 "sigs.k8s.io/vsphere-csi-driver/v3/pkg/apis/cnsoperator/cnsfileaccessconfig/v1alpha1"
4949
volumes "sigs.k8s.io/vsphere-csi-driver/v3/pkg/common/cns-lib/volume"
5050
commonconfig "sigs.k8s.io/vsphere-csi-driver/v3/pkg/common/config"
5151
"sigs.k8s.io/vsphere-csi-driver/v3/pkg/csi/service/common"
@@ -179,25 +179,17 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
179179
maxWorkerThreads := util.GetMaxWorkerThreads(ctx,
180180
workerThreadsEnvVar, defaultMaxWorkerThreads)
181181
// Create a new controller.
182-
c, err := controller.New("cnsfileaccessconfig-controller", mgr,
183-
controller.Options{Reconciler: r, MaxConcurrentReconciles: maxWorkerThreads})
182+
err := ctrl.NewControllerManagedBy(mgr).Named("cnsfileaccessconfig-controller").
183+
For(&v1a1.CnsFileAccessConfig{}).
184+
WithEventFilter(predicate.GenerationChangedPredicate{}).
185+
WithOptions(controller.Options{MaxConcurrentReconciles: maxWorkerThreads}).
186+
Complete(r)
184187
if err != nil {
185-
log.Errorf("Failed to create new CnsFileAccessConfig controller with error: %+v", err)
188+
log.Errorf("Failed to build application controller. Err: %v", err)
186189
return err
187190
}
188191

189192
backOffDuration = make(map[types.NamespacedName]time.Duration)
190-
191-
// Watch for changes to primary resource CnsFileAccessConfig.
192-
err = c.Watch(source.Kind(
193-
mgr.GetCache(),
194-
&cnsfileaccessconfigv1alpha1.CnsFileAccessConfig{},
195-
&handler.TypedEnqueueRequestForObject[*cnsfileaccessconfigv1alpha1.CnsFileAccessConfig]{},
196-
))
197-
if err != nil {
198-
log.Errorf("Failed to watch for changes to CnsFileAccessConfig resource with error: %+v", err)
199-
return err
200-
}
201193
return nil
202194
}
203195

@@ -228,7 +220,7 @@ func (r *ReconcileCnsFileAccessConfig) Reconcile(ctx context.Context,
228220
request reconcile.Request) (reconcile.Result, error) {
229221
log := logger.GetLogger(ctx)
230222
// Fetch the CnsFileAccessConfig instance.
231-
instance := &cnsfileaccessconfigv1alpha1.CnsFileAccessConfig{}
223+
instance := &v1a1.CnsFileAccessConfig{}
232224
err := r.client.Get(ctx, request.NamespacedName, instance)
233225
if err != nil {
234226
if apierrors.IsNotFound(err) {
@@ -297,11 +289,10 @@ func (r *ReconcileCnsFileAccessConfig) Reconcile(ctx context.Context,
297289
}
298290

299291
// Remove finalizer from CnsFileAccessConfig CRD
300-
removeFinalizerFromCRDInstance(ctx, instance)
301-
err = updateCnsFileAccessConfig(ctx, r.client, instance)
292+
err = k8s.RemoveFinalizer(ctx, r.client, instance, cnsoperatortypes.CNSFinalizer)
302293
if err != nil {
303-
msg := fmt.Sprintf("failed to update CnsFileAccessConfig instance: %q on namespace: %q. Error: %+v",
304-
instance.Name, instance.Namespace, err)
294+
msg := fmt.Sprintf("failed to remove finalizer from CnsFileAccessConfig "+
295+
"instance: %q on namespace: %q. Error: %+v", instance.Name, instance.Namespace, err)
305296
recordEvent(ctx, r, instance, v1.EventTypeWarning, msg)
306297
return reconcile.Result{RequeueAfter: timeout}, nil
307298
}
@@ -370,8 +361,7 @@ func (r *ReconcileCnsFileAccessConfig) Reconcile(ctx context.Context,
370361
return reconcile.Result{RequeueAfter: timeout}, nil
371362
}
372363
}
373-
removeFinalizerFromCRDInstance(ctx, instance)
374-
err = updateCnsFileAccessConfig(ctx, r.client, instance)
364+
err = k8s.RemoveFinalizer(ctx, r.client, instance, cnsoperatortypes.CNSFinalizer)
375365
if err != nil {
376366
msg := fmt.Sprintf("failed to update CnsFileAccessConfig instance: %q on namespace: %q. Error: %+v",
377367
instance.Name, instance.Namespace, err)
@@ -396,24 +386,14 @@ func (r *ReconcileCnsFileAccessConfig) Reconcile(ctx context.Context,
396386
backOffDurationMapMutex.Unlock()
397387
return reconcile.Result{}, nil
398388
}
399-
cnsFinalizerExists := false
400-
// Check if finalizer already exists.
401-
for _, finalizer := range instance.Finalizers {
402-
if finalizer == cnsoperatortypes.CNSFinalizer {
403-
cnsFinalizerExists = true
404-
break
405-
}
406-
}
407-
if !cnsFinalizerExists {
408-
// Add finalizer.
409-
instance.Finalizers = append(instance.Finalizers, cnsoperatortypes.CNSFinalizer)
410-
err = updateCnsFileAccessConfig(ctx, r.client, instance)
411-
if err != nil {
412-
msg := fmt.Sprintf("failed to update CnsFileAccessConfig instance: %q on namespace: %q. Error: %+v",
413-
instance.Name, instance.Namespace, err)
414-
recordEvent(ctx, r, instance, v1.EventTypeWarning, msg)
415-
return reconcile.Result{RequeueAfter: timeout}, nil
416-
}
389+
390+
// Add finalizer to CnsFileAccessConfig instance if it does not already exist.
391+
err = k8s.AddFinalizer(ctx, r.client, instance, cnsoperatortypes.CNSFinalizer)
392+
if err != nil {
393+
msg := fmt.Sprintf("failed to add finalizer on CnsFileAccessConfig instance: %q on namespace: %q. Error: %+v",
394+
instance.Name, instance.Namespace, err)
395+
recordEvent(ctx, r, instance, v1.EventTypeWarning, msg)
396+
return reconcile.Result{RequeueAfter: timeout}, nil
417397
}
418398

419399
vmOwnerRefExists := false
@@ -528,7 +508,7 @@ func (r *ReconcileCnsFileAccessConfig) Reconcile(ctx context.Context,
528508
// addPvcFinalizer checks if CnsPvcFinalizer exists on PVC.
529509
// If it does not exist, it updates the PVC with it.
530510
func addPvcFinalizer(ctx context.Context,
531-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig, client client.Client) error {
511+
instance *v1a1.CnsFileAccessConfig, client client.Client) error {
532512
log := logger.GetLogger(ctx)
533513

534514
if !commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.FileVolumesWithVmService) {
@@ -566,7 +546,7 @@ func addPvcFinalizer(ctx context.Context,
566546

567547
// isPvcInUse returns true if there is at least 1 VM which is using the given PVC.
568548
func isPvcInUse(ctx context.Context, pvcName string,
569-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig) (bool, error) {
549+
instance *v1a1.CnsFileAccessConfig) (bool, error) {
570550
log := logger.GetLogger(ctx)
571551

572552
cnsFileVolumeClientInstance, err := cnsfilevolumeclient.GetFileVolumeClientInstance(ctx)
@@ -581,7 +561,7 @@ func isPvcInUse(ctx context.Context, pvcName string,
581561
// removeFinalizerFromPVC will remove the CNS Finalizer, cns.vmware.com/pvc-protection,
582562
// from a given PersistentVolumeClaim.
583563
func removeFinalizerFromPVC(ctx context.Context, client client.Client,
584-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig) error {
564+
instance *v1a1.CnsFileAccessConfig) error {
585565
log := logger.GetLogger(ctx)
586566

587567
if !commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.FileVolumesWithVmService) {
@@ -640,7 +620,7 @@ func removeFinalizerFromPVC(ctx context.Context, client client.Client,
640620
// This method is used when we don't have VM instance. It fetches the VM IP from CNSFileVolumeClient
641621
// instance for the VM name associated with CnsFileAccessConfig.
642622
func (r *ReconcileCnsFileAccessConfig) removePermissionsForFileVolume(ctx context.Context, volumeID string,
643-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig, skipConfigureVolumeACL bool) error {
623+
instance *v1a1.CnsFileAccessConfig, skipConfigureVolumeACL bool) error {
644624
log := logger.GetLogger(ctx)
645625
volumePermissionLock, _ := volumePermissionLockMap.LoadOrStore(volumeID, &sync.Mutex{})
646626
instanceLock, _ := volumePermissionLock.(*sync.Mutex)
@@ -685,7 +665,7 @@ func (r *ReconcileCnsFileAccessConfig) removePermissionsForFileVolume(ctx contex
685665
// permissions by setting the parameter removePermission to true or false
686666
// respectively. Returns error if any operation fails.
687667
func (r *ReconcileCnsFileAccessConfig) configureNetPermissionsForFileVolume(ctx context.Context,
688-
volumeID string, vm *vmoperatortypes.VirtualMachine, instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig,
668+
volumeID string, vm *vmoperatortypes.VirtualMachine, instance *v1a1.CnsFileAccessConfig,
689669
removePermission bool) error {
690670
log := logger.GetLogger(ctx)
691671
volumePermissionLock, _ := volumePermissionLockMap.LoadOrStore(volumeID, &sync.Mutex{})
@@ -865,10 +845,10 @@ func validateVmAndPvc(ctx context.Context, instanceLabels map[string]string, ins
865845
// setInstanceSuccess sets instance to success and records an event on the
866846
// CnsFileAccessConfig instance.
867847
func setInstanceSuccess(ctx context.Context, r *ReconcileCnsFileAccessConfig,
868-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig, msg string) error {
848+
instance *v1a1.CnsFileAccessConfig, msg string) error {
869849
instance.Status.Done = true
870850
instance.Status.Error = ""
871-
err := updateCnsFileAccessConfig(ctx, r.client, instance)
851+
err := k8s.UpdateStatus(ctx, r.client, instance)
872852
if err != nil {
873853
return err
874854
}
@@ -879,18 +859,18 @@ func setInstanceSuccess(ctx context.Context, r *ReconcileCnsFileAccessConfig,
879859
// setInstanceError sets error and records an event on the CnsFileAccessConfig
880860
// instance.
881861
func setInstanceError(ctx context.Context, r *ReconcileCnsFileAccessConfig,
882-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig, errMsg string) {
862+
instance *v1a1.CnsFileAccessConfig, errMsg string) {
883863
log := logger.GetLogger(ctx)
884864
instance.Status.Error = errMsg
885-
err := updateCnsFileAccessConfig(ctx, r.client, instance)
865+
err := k8s.UpdateStatus(ctx, r.client, instance)
886866
if err != nil {
887867
log.Errorf("updateCnsFileAccessConfig failed. err: %v", err)
888868
}
889869
recordEvent(ctx, r, instance, v1.EventTypeWarning, errMsg)
890870
}
891871

892872
func updateCnsFileAccessConfig(ctx context.Context, client client.Client,
893-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig) error {
873+
instance *v1a1.CnsFileAccessConfig) error {
894874
log := logger.GetLogger(ctx)
895875
err := client.Update(ctx, instance)
896876
if err != nil {
@@ -904,7 +884,7 @@ func updateCnsFileAccessConfig(ctx context.Context, client client.Client,
904884
// appropriately and logs the message.
905885
// backOffDuration is reset to 1 second on success and doubled on failure.
906886
func recordEvent(ctx context.Context, r *ReconcileCnsFileAccessConfig,
907-
instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig, eventtype string, msg string) {
887+
instance *v1a1.CnsFileAccessConfig, eventtype string, msg string) {
908888
log := logger.GetLogger(ctx)
909889
log.Debugf("Event type is %s", eventtype)
910890
namespacedName := types.NamespacedName{
@@ -927,17 +907,3 @@ func recordEvent(ctx context.Context, r *ReconcileCnsFileAccessConfig,
927907
backOffDurationMapMutex.Unlock()
928908
}
929909
}
930-
931-
// removeFinalizerFromCRDInstance will remove the CNS Finalizer = cns.vmware.com,
932-
// from a given CnsFileAccessConfig instance.
933-
func removeFinalizerFromCRDInstance(ctx context.Context, instance *cnsfileaccessconfigv1alpha1.CnsFileAccessConfig) {
934-
log := logger.GetLogger(ctx)
935-
for i, finalizer := range instance.Finalizers {
936-
if finalizer == cnsoperatortypes.CNSFinalizer {
937-
log.Debugf("Removing %q finalizer from CnsFileAccessConfig instance with name: %q on namespace: %q",
938-
cnsoperatortypes.CNSFinalizer, instance.Name, instance.Namespace)
939-
instance.Finalizers = append(instance.Finalizers[:i], instance.Finalizers[i+1:]...)
940-
break
941-
}
942-
}
943-
}

0 commit comments

Comments
 (0)