Skip to content

Commit 7a6acd9

Browse files
authored
Revert "Add ":detaching" suffix to batch attach CR only if it isn't already present." (#3736)
This reverts commit dc07f12.
1 parent b7552df commit 7a6acd9

File tree

3 files changed

+57
-178
lines changed

3 files changed

+57
-178
lines changed

pkg/syncer/cnsoperator/controller/cnsnodevmbatchattachment/cnsnodevmbatchattachment_controller.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,9 @@ func (r *Reconciler) Reconcile(ctx context.Context,
305305

306306
patchErr := removeFinalizerFromCRDInstance(batchAttachCtx, instance, r.client)
307307
if patchErr != nil {
308+
recordEvent(batchAttachCtx, r, instance, v1.EventTypeWarning, patchErr.Error())
308309
log.Errorf("failed to update CnsNodeVMBatchAttachment %s. Err: +%v", instance.Name, patchErr)
309-
return r.completeReconciliationWithError(batchAttachCtx, instance, request.NamespacedName, timeout, err)
310+
return reconcile.Result{RequeueAfter: timeout}, nil
310311
}
311312
log.Infof("Successfully removed finalizer %s from instance %s",
312313
cnsoperatortypes.CNSFinalizer, request.NamespacedName.String())
@@ -315,7 +316,10 @@ func (r *Reconciler) Reconcile(ctx context.Context,
315316
delete(backOffDuration, request.NamespacedName)
316317
backOffDurationMapMutex.Unlock()
317318

318-
return r.completeReconciliationWithSuccess(batchAttachCtx, instance, request.NamespacedName, timeout)
319+
msg := fmt.Sprintf("ReconcileCnsNodeVMBatchAttachment: Successfully processed instance %s",
320+
request.NamespacedName.String())
321+
recordEvent(batchAttachCtx, r, instance, v1.EventTypeNormal, msg)
322+
return reconcile.Result{}, nil
319323
}
320324

321325
// The CR is not being deleted, so call attach and detach for volumes.

pkg/syncer/cnsoperator/controller/cnsnodevmbatchattachment/cnsnodevmbatchattachment_helper.go

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"errors"
2323
"fmt"
2424
"slices"
25-
"strconv"
2625
"strings"
2726
"sync"
2827

@@ -249,53 +248,18 @@ func updatePvcStatusEntryName(ctx context.Context,
249248
instance *v1alpha1.CnsNodeVMBatchAttachment, pvcsToDetach map[string]string) {
250249
log := logger.GetLogger(ctx)
251250

252-
allVolumeNamesInStatus := getVolumeNamesInStatus(instance)
253-
254251
for i, volume := range instance.Status.VolumeStatus {
255252
if _, ok := pvcsToDetach[volume.PersistentVolumeClaim.ClaimName]; !ok {
256253
continue
257254
}
258-
if strings.HasSuffix(instance.Status.VolumeStatus[i].Name, detachSuffix) {
259-
log.Infof("VolumeName %s for PVC %s already contains suffix %s. Skipping.",
260-
instance.Status.VolumeStatus[i].Name, volume.PersistentVolumeClaim.ClaimName,
261-
detachSuffix)
262-
continue
263-
}
264-
// First ensure that the volumeName with the suffix is unique.
265-
newVolumeName := getUniqueVolumeName(instance.Status.VolumeStatus[i].Name,
266-
allVolumeNamesInStatus)
255+
newVolumeName := instance.Status.VolumeStatus[i].Name + detachSuffix
267256
instance.Status.VolumeStatus[i].Name = newVolumeName
268-
// Add the new volumename to allVolumeNamesInStatus
269-
allVolumeNamesInStatus[newVolumeName] = true
270257
log.Infof("Updating status name entry to %s for detaching PVC %s",
271258
newVolumeName,
272259
volume.PersistentVolumeClaim.ClaimName)
273260
}
274261
}
275262

276-
// getUniqueVolumeName finds a unque name for volume status entry.
277-
func getUniqueVolumeName(currentName string, allVolumeNamesInStatus map[string]bool) string {
278-
detachingSuffixIndex := 1
279-
newVolumeName := currentName + "-" + strconv.Itoa(detachingSuffixIndex) + detachSuffix
280-
for {
281-
// Unique name found.
282-
if _, exists := allVolumeNamesInStatus[newVolumeName]; !exists {
283-
return newVolumeName
284-
}
285-
detachingSuffixIndex++
286-
newVolumeName = currentName + "-" + strconv.Itoa(detachingSuffixIndex) + detachSuffix
287-
}
288-
}
289-
290-
// getVolumeNamesInStatus returns all the names of the volume in the instance.
291-
func getVolumeNamesInStatus(instance *v1alpha1.CnsNodeVMBatchAttachment) map[string]bool {
292-
volumeNamesInStatus := make(map[string]bool)
293-
for _, volumeStatus := range instance.Status.VolumeStatus {
294-
volumeNamesInStatus[volumeStatus.Name] = true
295-
}
296-
return volumeNamesInStatus
297-
}
298-
299263
// updateInstanceStatus updates the given nodevmbatchattachment instance's status.
300264
func updateInstanceStatus(ctx context.Context, cnsoperatorclient client.Client,
301265
instance *v1alpha1.CnsNodeVMBatchAttachment) error {

pkg/syncer/cnsoperator/controller/cnsnodevmbatchattachment/cnsnodevmbatchattachment_test.go

Lines changed: 50 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@ package cnsnodevmbatchattachment
1919
import (
2020
"context"
2121
"fmt"
22-
"reflect"
23-
"strconv"
2422
"sync"
2523
"testing"
2624
"time"
2725

2826
"github.com/stretchr/testify/assert"
2927
"github.com/vmware/govmomi/object"
3028
v1 "k8s.io/api/core/v1"
29+
"k8s.io/apimachinery/pkg/api/errors"
3130
"k8s.io/apimachinery/pkg/api/resource"
3231
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3332
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -234,6 +233,55 @@ func TestCnsNodeVMBatchAttachmentWhenVmOnVcenterReturnsError(t *testing.T) {
234233
})
235234
}
236235

236+
func TestCnsNodeVMBatchAttachmentWhenVmOnVcenterReturnsNotFoundError(t *testing.T) {
237+
238+
t.Run("TestCnsNodeVMBatchAttachmentWhenVmOnVcenterReturnsNotFoundError", func(t *testing.T) {
239+
testCnsNodeVMBatchAttachment := setupTestCnsNodeVMBatchAttachment()
240+
testCnsNodeVMBatchAttachment.Spec.InstanceUUID = "test-3"
241+
242+
r := setTestEnvironment(&testCnsNodeVMBatchAttachment, true)
243+
244+
req := reconcile.Request{
245+
NamespacedName: types.NamespacedName{
246+
Name: testCnsNodeVMBatchAttachmentName,
247+
Namespace: testNamespace,
248+
},
249+
}
250+
251+
GetVMFromVcenter = MockGetVMFromVcenter
252+
commonco.ContainerOrchestratorUtility = &unittestcommon.FakeK8SOrchestrator{}
253+
254+
// Override with fake client
255+
newClientFunc = func(ctx context.Context) (kubernetes.Interface, error) {
256+
fakeK8sClient := getClientSetWithPvc()
257+
return fakeK8sClient, nil
258+
}
259+
260+
res, err := r.Reconcile(context.TODO(), req)
261+
if err != nil {
262+
t.Fatal("Unexpected reconcile error")
263+
}
264+
expectedReconcileResult := reconcile.Result{}
265+
var expectedReconcileError error
266+
267+
assert.Equal(t, expectedReconcileResult, res)
268+
assert.Equal(t, expectedReconcileError, err)
269+
270+
updatedCnsNodeVMBatchAttachment := &v1alpha1.CnsNodeVMBatchAttachment{}
271+
err = r.client.Get(context.TODO(), req.NamespacedName, updatedCnsNodeVMBatchAttachment)
272+
if err == nil {
273+
t.Fatalf("failed to get cnsnodevmbatchattachemnt instance")
274+
}
275+
276+
// Error should be not found
277+
if statusErr, ok := err.(*errors.StatusError); ok {
278+
assert.Equal(t, metav1.StatusReasonNotFound, statusErr.Status().Reason)
279+
} else {
280+
t.Fatalf("Unable to verify CnsNodeVMBatchAttachment error")
281+
}
282+
})
283+
}
284+
237285
func TestCnsNodeVMBatchAttachmentWhenVmOnVcenterReturnsNotFoundErrorAndInstanceIsNotDeleted(t *testing.T) {
238286
t.Run("TestCnsNodeVMBatchAttachmentWhenVmOnVcenterReturnsNotFoundErrorAndInstanceIsNotDeleted",
239287
func(t *testing.T) {
@@ -692,143 +740,6 @@ func TestIsSharedPvc(t *testing.T) {
692740
}
693741
}
694742

695-
func TestGetUniqueVolumeName(t *testing.T) {
696-
tests := []struct {
697-
name string
698-
currentName string
699-
allVolumeNamesInStatus map[string]bool
700-
expected string
701-
}{
702-
{
703-
name: "No existing volumes — first name available",
704-
currentName: "vol1",
705-
allVolumeNamesInStatus: map[string]bool{},
706-
expected: "vol1-1" + detachSuffix,
707-
},
708-
{
709-
name: "First detaching name already exists — use next index",
710-
currentName: "vol1",
711-
allVolumeNamesInStatus: map[string]bool{
712-
"vol1-1:detaching": true,
713-
},
714-
expected: "vol1-2" + detachSuffix,
715-
},
716-
{
717-
name: "Several existing detaching names — find next available",
718-
currentName: "vol1",
719-
allVolumeNamesInStatus: map[string]bool{
720-
"vol1-1:detaching": true,
721-
"vol1-2:detaching": true,
722-
"vol1-3:detaching": true,
723-
},
724-
expected: "vol1-4" + detachSuffix,
725-
},
726-
{
727-
name: "Different volume names in status — should not affect result",
728-
currentName: "volX",
729-
allVolumeNamesInStatus: map[string]bool{
730-
"volA-1:detaching": true,
731-
"volB-2:detaching": true,
732-
},
733-
expected: "volX-1" + detachSuffix,
734-
},
735-
{
736-
name: "Handles long existing name list gracefully",
737-
currentName: "vol99",
738-
allVolumeNamesInStatus: func() map[string]bool {
739-
m := make(map[string]bool)
740-
for i := 1; i <= 50; i++ {
741-
m["vol99-"+strconv.Itoa(i)+":detaching"] = true
742-
}
743-
return m
744-
}(),
745-
expected: "vol99-51" + detachSuffix,
746-
},
747-
}
748-
749-
for _, tc := range tests {
750-
t.Run(tc.name, func(t *testing.T) {
751-
got := getUniqueVolumeName(tc.currentName, tc.allVolumeNamesInStatus)
752-
if got != tc.expected {
753-
t.Errorf("expected %s, got %s", tc.expected, got)
754-
}
755-
})
756-
}
757-
}
758-
759-
func TestGetVolumeNamesInStatus(t *testing.T) {
760-
tests := []struct {
761-
name string
762-
instance v1alpha1.CnsNodeVMBatchAttachment
763-
expected map[string]bool
764-
}{
765-
{
766-
name: "No volumes in status",
767-
instance: v1alpha1.CnsNodeVMBatchAttachment{
768-
Status: v1alpha1.CnsNodeVMBatchAttachmentStatus{
769-
VolumeStatus: []v1alpha1.VolumeStatus{},
770-
},
771-
},
772-
expected: map[string]bool{},
773-
},
774-
{
775-
name: "Single volume in status",
776-
instance: v1alpha1.CnsNodeVMBatchAttachment{
777-
Status: v1alpha1.CnsNodeVMBatchAttachmentStatus{
778-
VolumeStatus: []v1alpha1.VolumeStatus{
779-
{Name: "vol1"},
780-
},
781-
},
782-
},
783-
expected: map[string]bool{
784-
"vol1": true,
785-
},
786-
},
787-
{
788-
name: "Multiple unique volumes",
789-
instance: v1alpha1.CnsNodeVMBatchAttachment{
790-
Status: v1alpha1.CnsNodeVMBatchAttachmentStatus{
791-
VolumeStatus: []v1alpha1.VolumeStatus{
792-
{Name: "vol1"},
793-
{Name: "vol2"},
794-
{Name: "vol3"},
795-
},
796-
},
797-
},
798-
expected: map[string]bool{
799-
"vol1": true,
800-
"vol2": true,
801-
"vol3": true,
802-
},
803-
},
804-
{
805-
name: "Duplicate volume names should not create duplicates in map",
806-
instance: v1alpha1.CnsNodeVMBatchAttachment{
807-
Status: v1alpha1.CnsNodeVMBatchAttachmentStatus{
808-
VolumeStatus: []v1alpha1.VolumeStatus{
809-
{Name: "vol1"},
810-
{Name: "vol1"},
811-
{Name: "vol2"},
812-
},
813-
},
814-
},
815-
expected: map[string]bool{
816-
"vol1": true,
817-
"vol2": true,
818-
},
819-
},
820-
}
821-
822-
for _, tc := range tests {
823-
t.Run(tc.name, func(t *testing.T) {
824-
got := getVolumeNamesInStatus(&tc.instance)
825-
if !reflect.DeepEqual(got, tc.expected) {
826-
t.Errorf("expected %+v, got %+v", tc.expected, got)
827-
}
828-
})
829-
}
830-
}
831-
832743
func MockGetVMFromVcenter(ctx context.Context, nodeUUID string,
833744
configInfo config.ConfigurationInfo) (*cnsvsphere.VirtualMachine, error) {
834745
var vm *cnsvsphere.VirtualMachine

0 commit comments

Comments
 (0)