From 724169b15bdc58e983063209979f15a46f48cc4e Mon Sep 17 00:00:00 2001 From: VinayKumarHavanur <54576364+VinayKumarHavanur@users.noreply.github.com> Date: Tue, 18 Jul 2023 07:31:50 +0530 Subject: [PATCH] Feature gate for 23.07 Trident features Co-authored-by: Alex Meade --- config/config.go | 4 + frontend/crd/snapshot_restore.go | 5 ++ frontend/crd/snapshot_restore_test.go | 75 ++++++++++++++++++ frontend/crd/trident_action_mirror_update.go | 5 ++ .../crd/trident_action_mirror_update_test.go | 65 ++++++++++++++++ storage/backend.go | 6 ++ storage/backend_test.go | 61 +++++++++++++++ storage_drivers/ontap/ontap_nas_qtree.go | 5 +- storage_drivers/ontap/ontap_nas_qtree_test.go | 77 ++++++++++++++++++- 9 files changed, 301 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index ccc90a610..b78d8482a 100644 --- a/config/config.go +++ b/config/config.go @@ -248,6 +248,10 @@ var ( 6: "SINGLE_NODE_SINGLE_WRITER", 7: "SINGLE_NODE_MULTI_WRITER", } + + // DisableExtraFeatures makes a subset of Trident features disabled + // This can be removed when ACP replaces feature-gating + DisableExtraFeatures = true ) func IsValidProtocol(p Protocol) bool { diff --git a/frontend/crd/snapshot_restore.go b/frontend/crd/snapshot_restore.go index 714a73d81..c33e8f9f8 100644 --- a/frontend/crd/snapshot_restore.go +++ b/frontend/crd/snapshot_restore.go @@ -11,6 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/cache" + "github.com/netapp/trident/config" . "github.com/netapp/trident/logging" netappv1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" "github.com/netapp/trident/storage" @@ -61,6 +62,10 @@ func (c *TridentCrdController) handleActionSnapshotRestore(keyItem *KeyItem) (re } }() + if config.DisableExtraFeatures { + return errors.UnsupportedError("snapshot restore is not enabled") + } + // Detect a CR that is in progress but is not a retry from the workqueue. This can only happen // if Trident restarted while processing a CR, in which case we move the CR directly to Failed. if actionCR.InProgress() && !keyItem.isRetry { diff --git a/frontend/crd/snapshot_restore_test.go b/frontend/crd/snapshot_restore_test.go index 4b8c0f580..3a72498fe 100644 --- a/frontend/crd/snapshot_restore_test.go +++ b/frontend/crd/snapshot_restore_test.go @@ -14,6 +14,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/netapp/trident/config" mockcore "github.com/netapp/trident/mocks/mock_core" netappv1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" "github.com/netapp/trident/utils" @@ -141,6 +142,9 @@ func fakeTASR(name, namespace, pvcName, vsName string) *netappv1.TridentActionSn } func TestHandleActionSnapshotRestore(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) @@ -237,7 +241,78 @@ func TestHandleActionSnapshotRestore(t *testing.T) { assert.True(t, apierrors.IsNotFound(err), "TASR should not have been found") } +func TestHandleActionSnapshotRestore_Disabled(t *testing.T) { + mockCtrl := gomock.NewController(t) + orchestrator := mockcore.NewMockOrchestrator(mockCtrl) + + tridentNamespace := "trident" + kubeClient := GetTestKubernetesClientset() + snapClient := GetTestSnapshotClientset() + crdClient := GetTestCrdClientset() + crdController, err := newTridentCrdControllerImpl(orchestrator, tridentNamespace, kubeClient, snapClient, crdClient) + if err != nil { + t.Fatalf("cannot create Trident CRD controller frontend; %v", err) + } + + // Activate the CRD controller and start monitoring + if err = crdController.Activate(); err != nil { + t.Fatalf("error while activating; %v", err) + } + time.Sleep(250 * time.Millisecond) + + pvc := fakeSnapRestorePVC(snapRestorePVC1, namespace1, snapRestorePV1) + _, _ = kubeClient.CoreV1().PersistentVolumeClaims(namespace1).Create(ctx(), pvc, createOpts) + + pv := fakePV(snapRestorePVC1, namespace1, snapRestorePV1) + _, _ = kubeClient.CoreV1().PersistentVolumes().Create(ctx(), pv, createOpts) + + vs1Time := time.Now() + vs2Time := vs1Time.Add(1 * time.Second) + vs3Time := vs2Time.Add(1 * time.Second) + + vs1 := fakeVS(snapRestoreSnap1, namespace1, snapRestoreVSC1, snapRestorePVC1, vs1Time) + _, _ = snapClient.SnapshotV1().VolumeSnapshots(namespace1).Create(ctx(), vs1, createOpts) + + vsc1 := fakeVSC(snapRestoreSnap1, namespace1, snapRestoreVSC1, snapRestoreSnapHandle1, vs1Time) + _, _ = snapClient.SnapshotV1().VolumeSnapshotContents().Create(ctx(), vsc1, createOpts) + + vs2 := fakeVS(snapRestoreSnap2, namespace1, snapRestoreVSC2, snapRestorePVC1, vs2Time) + _, _ = snapClient.SnapshotV1().VolumeSnapshots(namespace1).Create(ctx(), vs2, createOpts) + + vsc2 := fakeVSC(snapRestoreSnap2, namespace1, snapRestoreVSC2, snapRestoreSnapHandle2, vs2Time) + _, _ = snapClient.SnapshotV1().VolumeSnapshotContents().Create(ctx(), vsc2, createOpts) + + vs3 := fakeVS(snapRestoreSnap3, namespace1, snapRestoreVSC3, snapRestorePVC1, vs3Time) + _, _ = snapClient.SnapshotV1().VolumeSnapshots(namespace1).Create(ctx(), vs3, createOpts) + + vsc3 := fakeVSC(snapRestoreSnap3, namespace1, snapRestoreVSC3, snapRestoreSnapHandle3, vs3Time) + _, _ = snapClient.SnapshotV1().VolumeSnapshotContents().Create(ctx(), vsc3, createOpts) + + tasr := fakeTASR(tasr1, namespace1, snapRestorePVC1, snapRestoreSnap3) + _, _ = crdClient.TridentV1().TridentActionSnapshotRestores(namespace1).Create(ctx(), tasr, createOpts) + + // Wait until the operation completes + for i := 0; i < 20; i++ { + time.Sleep(250 * time.Millisecond) + + tasr, err = crdClient.TridentV1().TridentActionSnapshotRestores(namespace1).Get(ctx(), tasr1, getOpts) + if err != nil { + if apierrors.IsNotFound(err) { + continue + } + break + } else if tasr.IsComplete() { + break + } + } + + assert.True(t, tasr.Failed(), "TASR operation did not fail") +} + func TestHandleActionSnapshotRestore_InProgressError(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) diff --git a/frontend/crd/trident_action_mirror_update.go b/frontend/crd/trident_action_mirror_update.go index 69e14665b..63e2de33d 100644 --- a/frontend/crd/trident_action_mirror_update.go +++ b/frontend/crd/trident_action_mirror_update.go @@ -11,6 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/cache" + "github.com/netapp/trident/config" . "github.com/netapp/trident/logging" netappv1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" "github.com/netapp/trident/storage" @@ -62,6 +63,10 @@ func (c *TridentCrdController) handleActionMirrorUpdate(keyItem *KeyItem) (updat } }() + if config.DisableExtraFeatures { + return errors.UnsupportedError("mirror update is not enabled") + } + // Detect a CR that is in progress but is not a retry from the workqueue. // This can only happen if Trident restarted while processing a CR, in which case we move the CR directly to Failed. if actionCR.InProgress() && !keyItem.isRetry { diff --git a/frontend/crd/trident_action_mirror_update_test.go b/frontend/crd/trident_action_mirror_update_test.go index a996ea8c9..32f9fba8e 100644 --- a/frontend/crd/trident_action_mirror_update_test.go +++ b/frontend/crd/trident_action_mirror_update_test.go @@ -13,6 +13,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/netapp/trident/config" mockcore "github.com/netapp/trident/mocks/mock_core" netappv1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" "github.com/netapp/trident/utils" @@ -107,6 +108,9 @@ func fakeTAMU(name, namespace, tmrName, snapshotHandle string) *netappv1.Trident } func TestHandleActionMirrorUpdate(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) @@ -258,6 +262,9 @@ func TestHandleActionMirrorUpdate_ValidateFailure(t *testing.T) { } func TestHandleActionMirrorUpdate_InProgress(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) @@ -320,7 +327,56 @@ func TestHandleActionMirrorUpdate_InProgress(t *testing.T) { assert.True(t, tamu.Succeeded(), "TAMU operation failed") } +func TestHandleActionMirrorUpdate_InProgress_Disabled(t *testing.T) { + mockCtrl := gomock.NewController(t) + orchestrator := mockcore.NewMockOrchestrator(mockCtrl) + + tridentNamespace := "trident" + kubeClient := GetTestKubernetesClientset() + snapClient := GetTestSnapshotClientset() + crdClient := GetTestCrdClientset() + crdController, err := newTridentCrdControllerImpl(orchestrator, tridentNamespace, kubeClient, snapClient, crdClient) + if err != nil { + t.Fatalf("cannot create Trident CRD controller frontend, error: %v", err.Error()) + } + + // Activate the CRD controller and start monitoring + if err = crdController.Activate(); err != nil { + t.Fatalf("error while activating: %v", err.Error()) + } + delaySeconds(1) + + pvc := fakePVC(pvc1, namespace1, pv1) + _, _ = kubeClient.CoreV1().PersistentVolumeClaims(namespace1).Create(ctx(), pvc, createOpts) + + tmr := fakeTMR(tmrName1, namespace1, pvc1) + _, _ = crdClient.TridentV1().TridentMirrorRelationships(namespace1).Create(ctx(), tmr, createOpts) + + tamu := fakeTAMU(tamu1, namespace1, tmrName1, snapHandle1) + _, _ = crdClient.TridentV1().TridentActionMirrorUpdates(namespace1).Create(ctx(), tamu, createOpts) + + // Wait until the operation completes + for i := 0; i < 5; i++ { + time.Sleep(250 * time.Millisecond) + + tamu, err = crdClient.TridentV1().TridentActionMirrorUpdates(namespace1).Get(ctx(), tamu1, getOpts) + if err != nil { + if apierrors.IsNotFound(err) { + continue + } + break + } else if tamu.IsComplete() { + break + } + } + + assert.True(t, tamu.Failed(), "TAMU operation was not disabled") +} + func TestHandleActionMirrorUpdate_InProgressAtStartup(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) @@ -362,6 +418,9 @@ func TestHandleActionMirrorUpdate_InProgressAtStartup(t *testing.T) { } func TestUpdateActionMirrorUpdateCRInProgress(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) transferTime, _ := time.Parse(utils.TimestampFormat, previousTransferTime) @@ -397,6 +456,9 @@ func TestUpdateActionMirrorUpdateCRInProgress(t *testing.T) { } func TestUpdateActionMirrorUpdateCRComplete_Succeeded(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) @@ -430,6 +492,9 @@ func TestUpdateActionMirrorUpdateCRComplete_Succeeded(t *testing.T) { } func TestUpdateActionMirrorUpdateCRComplete_Failed(t *testing.T) { + defer func() { config.DisableExtraFeatures = true }() + config.DisableExtraFeatures = false + mockCtrl := gomock.NewController(t) orchestrator := mockcore.NewMockOrchestrator(mockCtrl) diff --git a/storage/backend.go b/storage/backend.go index 9dd691f07..9c4acce3c 100644 --- a/storage/backend.go +++ b/storage/backend.go @@ -419,6 +419,12 @@ func (b *StorageBackend) CloneVolume( "cloneVolumeInternal": cloneVolConfig.InternalName, }).Debug("Attempting volume clone.") + if cloneVolConfig.ReadOnlyClone { + if tridentconfig.DisableExtraFeatures { + return nil, errors.UnsupportedError("read only clone is not supported") + } + } + // Ensure volume is managed if cloneVolConfig.ImportNotManaged { return nil, errors.NotManagedError("volume %s is not managed by Trident", cloneVolConfig.InternalName) diff --git a/storage/backend_test.go b/storage/backend_test.go index 60ba04ba7..24fab5576 100644 --- a/storage/backend_test.go +++ b/storage/backend_test.go @@ -7,6 +7,9 @@ import ( "testing" "github.com/stretchr/testify/assert" + + tridentconfig "github.com/netapp/trident/config" + "github.com/netapp/trident/utils/errors" ) func TestBackendState(t *testing.T) { @@ -143,3 +146,61 @@ func TestDeleteSnapshot_NotManaged(t *testing.T) { assert.Errorf(t, err, "expected err") } + +func TestCloneVolume_FeatureDisabled(t *testing.T) { + volumeName := "pvc-e9748b6b-8240-4fd8-97bc-868bf064ecd4" + volumeInternalName := "trident_pvc_e9748b6b_8240_4fd8_97bc_868bf064ecd4" + volumeConfig := &VolumeConfig{ + Version: "", + Name: volumeName, + InternalName: volumeInternalName, + } + volumeConfigDest := &VolumeConfig{ + Version: "", + Name: "pvc-deadbeef-8240-4fd8-97bc-868bf064ecd4", + InternalName: "trident_pvc_deadbeef_8240_4fd8_97bc_868bf064ecd4", + ReadOnlyClone: true, + } + + backend := &StorageBackend{ + state: Offline, + } + pool := NewStoragePool(nil, "test-pool1") + + // Both volume and snapshot not managed + _, err := backend.CloneVolume(context.Background(), volumeConfig, volumeConfigDest, pool, false) + + assert.Error(t, err, "expected err") + assert.True(t, errors.IsUnsupportedError(err)) +} + +func TestCloneVolume_BackendOffline(t *testing.T) { + volumeName := "pvc-e9748b6b-8240-4fd8-97bc-868bf064ecd4" + volumeInternalName := "trident_pvc_e9748b6b_8240_4fd8_97bc_868bf064ecd4" + volumeConfig := &VolumeConfig{ + Version: "", + Name: volumeName, + InternalName: volumeInternalName, + ReadOnlyClone: true, + } + volumeConfigDest := &VolumeConfig{ + Version: "", + Name: "pvc-deadbeef-8240-4fd8-97bc-868bf064ecd4", + InternalName: "trident_pvc_deadbeef_8240_4fd8_97bc_868bf064ecd4", + ReadOnlyClone: false, + } + + backend := &StorageBackend{ + state: Offline, + name: "test-backend", + } + pool := NewStoragePool(nil, "test-pool1") + + tridentconfig.DisableExtraFeatures = false + + // Both volume and snapshot not managed + _, err := backend.CloneVolume(context.Background(), volumeConfig, volumeConfigDest, pool, false) + + assert.Errorf(t, err, "expected err") + assert.Equal(t, err.Error(), "backend test-backend is not Online") +} diff --git a/storage_drivers/ontap/ontap_nas_qtree.go b/storage_drivers/ontap/ontap_nas_qtree.go index ed74a630a..8918db7a3 100644 --- a/storage_drivers/ontap/ontap_nas_qtree.go +++ b/storage_drivers/ontap/ontap_nas_qtree.go @@ -482,7 +482,6 @@ func (d *NASQtreeStorageDriver) CreateClone( // If RO clone is requested, validate the snapshot directory access and return if cloneVolConfig.ReadOnlyClone { - _, flexvol, _, err := d.ParseQtreeInternalID(sourceVolConfig.InternalID) if err != nil { return errors.WrapWithNotFoundError(err, "error while getting flexvol") @@ -902,6 +901,10 @@ func (d *NASQtreeStorageDriver) CreateSnapshot( Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> CreateSnapshot") defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< CreateSnapshot") + if tridentconfig.DisableExtraFeatures { + return nil, errors.UnsupportedError(fmt.Sprintf("snapshots are not supported by backend type %s", d.Name())) + } + if volConfig.ReadOnlyClone { // This is a read-only volume and hence do not create snapshot of it return nil, fmt.Errorf("snapshot is not supported for a read-only volume") diff --git a/storage_drivers/ontap/ontap_nas_qtree_test.go b/storage_drivers/ontap/ontap_nas_qtree_test.go index 2abe1f4b8..0116afc65 100644 --- a/storage_drivers/ontap/ontap_nas_qtree_test.go +++ b/storage_drivers/ontap/ontap_nas_qtree_test.go @@ -3761,7 +3761,30 @@ func TestCanSnapshot_InvalidSnapshotDir(t *testing.T) { assert.NotNil(t, result, "result is nil") } +func TestCreateSnapshot_Disabled(t *testing.T) { + _, driver := newMockOntapNasQtreeDriver(t) + volConfig := &storage.VolumeConfig{ + Size: "1g", + Encryption: "false", + FileSystem: "nfs", + InternalName: flexvol, + InternalID: volInternalID, + } + + snapConfig := &storage.SnapshotConfig{ + InternalName: "snap1", + VolumeInternalName: "vol1", + } + + _, err := driver.CreateSnapshot(ctx, snapConfig, volConfig) + + assert.Error(t, err, "no error occurred") +} + func TestCreateSnapshot_Success(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3794,6 +3817,9 @@ func TestCreateSnapshot_Success(t *testing.T) { } func TestCreateSnapshot_FailureErrorCheckingVolume(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3818,6 +3844,9 @@ func TestCreateSnapshot_FailureErrorCheckingVolume(t *testing.T) { } func TestCreateSnapshot_FailureNoVolumeExists(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3842,6 +3871,9 @@ func TestCreateSnapshot_FailureNoVolumeExists(t *testing.T) { } func TestCreateSnapshot_FailureSnapshotCreateFailed(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3867,6 +3899,9 @@ func TestCreateSnapshot_FailureSnapshotCreateFailed(t *testing.T) { } func TestCreateSnapshot_FailureSnapshotInfoFailed(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3899,6 +3934,9 @@ func TestCreateSnapshot_FailureSnapshotInfoFailed(t *testing.T) { } func TestCreateSnapshot_FailureNoSnapshots(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3927,6 +3965,9 @@ func TestCreateSnapshot_FailureNoSnapshots(t *testing.T) { } func TestCreateSnapshot_FailureWrongVolumeID(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3950,6 +3991,9 @@ func TestCreateSnapshot_FailureWrongVolumeID(t *testing.T) { } func TestGetSnapshot_Success(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3980,6 +4024,9 @@ func TestGetSnapshot_Success(t *testing.T) { } func TestGetSnapshot_FailureNoSnapshotReturned(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -3996,7 +4043,8 @@ func TestGetSnapshot_FailureNoSnapshotReturned(t *testing.T) { mockAPI.EXPECT().SVMName().AnyTimes().Return("SVM1") mockAPI.EXPECT().VolumeSnapshotInfo(ctx, snapConfig.InternalName, flexvol).Return( api.Snapshot{}, - errors.NotFoundError(fmt.Sprintf("snapshot %v not found for volume %v", snapConfig.InternalName, snapConfig.VolumeInternalName))) + errors.NotFoundError(fmt.Sprintf("snapshot %v not found for volume %v", snapConfig.InternalName, + snapConfig.VolumeInternalName))) snap, err := driver.GetSnapshot(ctx, snapConfig, volConfig) @@ -4005,6 +4053,9 @@ func TestGetSnapshot_FailureNoSnapshotReturned(t *testing.T) { } func TestGetSnapshot_FailureErrorFetchingSnapshots(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -4030,6 +4081,9 @@ func TestGetSnapshot_FailureErrorFetchingSnapshots(t *testing.T) { } func TestGetSnapshot_FailureWrongVolumeID(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -4052,6 +4106,9 @@ func TestGetSnapshot_FailureWrongVolumeID(t *testing.T) { } func TestGetSnapshots_Success(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -4077,6 +4134,9 @@ func TestGetSnapshots_Success(t *testing.T) { } func TestGetSnapshots_SuccessDockerContext(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -4102,6 +4162,9 @@ func TestGetSnapshots_SuccessDockerContext(t *testing.T) { } func TestGetSnapshots_FailureWrongVolumeID(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -4120,6 +4183,9 @@ func TestGetSnapshots_FailureWrongVolumeID(t *testing.T) { } func TestGetSnapshots_FailureSnapshotListErr(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ Size: "1g", @@ -4145,6 +4211,9 @@ func TestGetSnapshots_FailureSnapshotListErr(t *testing.T) { } func TestDeleteSnapshot_Success(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) volConfig := &storage.VolumeConfig{ @@ -4168,6 +4237,9 @@ func TestDeleteSnapshot_Success(t *testing.T) { } func TestDeleteSnapshot_FailureSnapshotBusy(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + mockAPI, driver := newMockOntapNasQtreeDriver(t) childVols := make([]string, 0) childVols = append(childVols, flexvol) @@ -4196,6 +4268,9 @@ func TestDeleteSnapshot_FailureSnapshotBusy(t *testing.T) { } func TestDeleteSnapshot_FailureWrongVolumeID(t *testing.T) { + defer func() { tridentconfig.DisableExtraFeatures = true }() + tridentconfig.DisableExtraFeatures = false + _, driver := newMockOntapNasQtreeDriver(t) childVols := make([]string, 0) childVols = append(childVols, flexvol)