Merge pull request #111301 from mattcary/migration-feature

Upgrade CSIMigrationGCE feature gate to GA
This commit is contained in:
Kubernetes Prow Robot 2022-08-02 13:58:57 -07:00 committed by GitHub
commit 369a465fae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 191 additions and 257 deletions

View File

@ -26,14 +26,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
kcache "k8s.io/client-go/tools/cache"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csi"
"k8s.io/kubernetes/pkg/volume/util"
@ -431,15 +428,9 @@ func volumeAttachmentRecoveryTestCase(t *testing.T, tc vaTest) {
informerFactory := informers.NewSharedInformerFactory(fakeKubeClient, time.Second*1)
var plugins []volume.VolumePlugin
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, tc.csiMigration)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InTreePluginGCEUnregister, tc.csiMigration)()
plugins = append(plugins, controllervolumetesting.CreateTestPlugin()...)
plugins = append(plugins, csi.ProbeVolumePlugins()...)
if tc.csiMigration {
// if InTreePluginGCEUnregister is enabled, only the CSI plugin is registered but not the in-tree one
plugins = append(plugins, csi.ProbeVolumePlugins()...)
} else {
plugins = controllervolumetesting.CreateTestPlugin()
}
nodeInformer := informerFactory.Core().V1().Nodes().Informer()
podInformer := informerFactory.Core().V1().Pods().Informer()
pvInformer := informerFactory.Core().V1().PersistentVolumes().Informer()
@ -522,7 +513,14 @@ func volumeAttachmentRecoveryTestCase(t *testing.T, tc vaTest) {
podInformer.GetIndexer().Add(newPod)
}
if tc.pvName != "" {
newPv := controllervolumetesting.NewPV(tc.pvName, tc.volName)
var newPv *v1.PersistentVolume
if tc.csiMigration {
// NewPV returns a GCEPersistentDisk volume, which is migrated.
newPv = controllervolumetesting.NewPV(tc.pvName, tc.volName)
} else {
// Otherwise use NFS, which is not subject to migration.
newPv = controllervolumetesting.NewNFSPV(tc.pvName, tc.volName)
}
_, err = adc.kubeClient.CoreV1().PersistentVolumes().Create(context.TODO(), newPv, metav1.CreateOptions{})
if err != nil {
t.Fatalf("Run failed with error. Failed to create a new pv: <%v>", err)

View File

@ -26,19 +26,16 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
featuregatetesting "k8s.io/component-base/featuregate/testing"
csitrans "k8s.io/csi-translation-lib"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume/csimigration"
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
"k8s.io/kubernetes/pkg/volume/util/types"
)
func TestVolumesInUseMetricCollection(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
fakeVolumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
fakeClient := &fake.Clientset{}
@ -101,6 +98,7 @@ func TestVolumesInUseMetricCollection(t *testing.T) {
v1.ResourceName(v1.ResourceStorage): resource.MustParse("5G"),
},
PersistentVolumeSource: v1.PersistentVolumeSource{
// Note that as GCE CSI Migration is completed, this is handled by the PD CSI plugin.
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
@ -128,7 +126,7 @@ func TestVolumesInUseMetricCollection(t *testing.T) {
t.Errorf("Expected one volume in use got %d", len(nodeUseMap))
}
testNodeMetric := nodeUseMap["metric-test-host"]
pluginUseCount, ok := testNodeMetric["fake-plugin"]
pluginUseCount, ok := testNodeMetric["fake-plugin:pd.csi.storage.gke.io"]
if !ok {
t.Errorf("Expected fake plugin pvc got nothing")
}

View File

@ -26,19 +26,15 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
featuregatetesting "k8s.io/component-base/featuregate/testing"
csitrans "k8s.io/csi-translation-lib"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume/csimigration"
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
"k8s.io/kubernetes/pkg/volume/util"
)
func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
fakeVolumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
fakeClient := &fake.Clientset{}
@ -59,8 +55,8 @@ func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
{
Name: "dswp-test-volume-name",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "dswp-test-fake-device",
RBD: &v1.RBDVolumeSource{
RBDImage: "dswp-test-fake-device",
},
},
},
@ -75,7 +71,7 @@ func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
podName := util.GetUniquePodName(pod)
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].GCEPersistentDisk.PDName
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].RBD.RBDImage
pvcLister := fakeInformerFactory.Core().V1().PersistentVolumeClaims().Lister()
pvLister := fakeInformerFactory.Core().V1().PersistentVolumes().Lister()

View File

@ -296,6 +296,23 @@ func NewPV(pvName, volumeName string) *v1.PersistentVolume {
}
}
// Returns an NFS PV. This can be used for an in-tree volume that is not migrated (unlike NewPV, which uses the GCE persistent disk).
func NewNFSPV(pvName, volumeName string) *v1.PersistentVolume {
return &v1.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
UID: types.UID(pvName),
Name: pvName,
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
NFS: &v1.NFSVolumeSource{
Server: volumeName,
},
},
},
}
}
func attachVolumeToNode(nodes *v1.NodeList, volumeName, nodeName string) {
// if nodeName exists, get the object.. if not create node object
var node *v1.Node
@ -366,7 +383,14 @@ func (plugin *TestPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
if spec.Volume != nil {
return spec.Name(), nil
} else if spec.PersistentVolume != nil {
return spec.PersistentVolume.Spec.PersistentVolumeSource.GCEPersistentDisk.PDName, nil
if spec.PersistentVolume.Spec.PersistentVolumeSource.GCEPersistentDisk != nil {
return spec.PersistentVolume.Spec.PersistentVolumeSource.GCEPersistentDisk.PDName, nil
} else if spec.PersistentVolume.Spec.PersistentVolumeSource.NFS != nil {
return spec.PersistentVolume.Spec.PersistentVolumeSource.NFS.Server, nil
} else if spec.PersistentVolume.Spec.PersistentVolumeSource.RBD != nil {
return spec.PersistentVolume.Spec.PersistentVolumeSource.RBD.RBDImage, nil
}
return "", fmt.Errorf("GetVolumeName called with unexpected PersistentVolume: %v", spec)
} else {
return "", nil
}

View File

@ -34,7 +34,6 @@ import (
storagelisters "k8s.io/client-go/listers/storage/v1"
core "k8s.io/client-go/testing"
"k8s.io/client-go/tools/cache"
"k8s.io/component-base/featuregate"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/component-helpers/storage/volume"
csitrans "k8s.io/csi-translation-lib"
@ -471,107 +470,82 @@ func makeStorageClass(scName string, mode *storagev1.VolumeBindingMode) *storage
}
func TestAnnealMigrationAnnotations(t *testing.T) {
// The gce-pd plugin is used to test a migrated plugin (as the feature is
// locked as of 1.25), and rbd is used as a non-migrated plugin (still alpha
// as of 1.25). As plugins are migrated, rbd should be changed to a non-
// migrated plugin. If there are no other non-migrated plugins, then those
// test cases are moot and they can be removed (keeping only the test cases
// with gce-pd).
const testPlugin = "non-migrated-plugin"
const gcePlugin = "kubernetes.io/gce-pd"
const gceDriver = "pd.csi.storage.gke.io"
const migratedPlugin = "kubernetes.io/gce-pd"
const migratedDriver = "pd.csi.storage.gke.io"
const nonmigratedPlugin = "kubernetes.io/rbd"
const nonmigratedDriver = "rbd.csi.ceph.com"
tests := []struct {
name string
volumeAnnotations map[string]string
expVolumeAnnotations map[string]string
claimAnnotations map[string]string
expClaimAnnotations map[string]string
migratedDriverGates []featuregate.Feature
disabledDriverGates []featuregate.Feature
testMigration bool
}{
{
name: "migration on for GCE",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
disabledDriverGates: []featuregate.Feature{},
name: "migration on",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: migratedPlugin},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
},
{
name: "migration on for GCE with Beta storage provisioner annontation",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin},
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
disabledDriverGates: []featuregate.Feature{},
name: "migration on with Beta storage provisioner annontation",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: migratedPlugin},
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
},
{
name: "migration off for GCE",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
migratedDriverGates: []featuregate.Feature{},
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
name: "migration off",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin},
},
{
name: "migration off for GCE removes migrated to (rollback)",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
migratedDriverGates: []featuregate.Feature{},
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
name: "migration off removes migrated to (rollback)",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin},
},
{
name: "migration off for GCE removes migrated to (rollback) with Beta storage provisioner annontation",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin},
migratedDriverGates: []featuregate.Feature{},
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
name: "migration off removes migrated to (rollback) with Beta storage provisioner annontation",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: nonmigratedPlugin},
},
{
name: "migration on for GCE other plugin not affected",
name: "migration on, other plugin not affected",
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: testPlugin},
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: testPlugin},
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: testPlugin},
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: testPlugin},
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
disabledDriverGates: []featuregate.Feature{},
},
{
name: "not dynamically provisioned migration off for GCE",
name: "not dynamically provisioned",
volumeAnnotations: map[string]string{},
expVolumeAnnotations: map[string]string{},
claimAnnotations: map[string]string{},
expClaimAnnotations: map[string]string{},
migratedDriverGates: []featuregate.Feature{},
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
testMigration: false,
},
{
name: "not dynamically provisioned migration on for GCE",
volumeAnnotations: map[string]string{},
expVolumeAnnotations: map[string]string{},
claimAnnotations: map[string]string{},
expClaimAnnotations: map[string]string{},
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
disabledDriverGates: []featuregate.Feature{},
},
{
name: "nil annotations migration off for GCE",
name: "nil annotations",
volumeAnnotations: nil,
expVolumeAnnotations: nil,
claimAnnotations: nil,
expClaimAnnotations: nil,
migratedDriverGates: []featuregate.Feature{},
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
},
{
name: "nil annotations migration on for GCE",
volumeAnnotations: nil,
expVolumeAnnotations: nil,
claimAnnotations: nil,
expClaimAnnotations: nil,
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
disabledDriverGates: []featuregate.Feature{},
testMigration: false,
},
}
@ -580,12 +554,6 @@ func TestAnnealMigrationAnnotations(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
for _, f := range tc.migratedDriverGates {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, true)()
}
for _, f := range tc.disabledDriverGates {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, false)()
}
if tc.volumeAnnotations != nil {
ann := tc.volumeAnnotations
updateMigrationAnnotations(cmpm, translator, ann, false)
@ -607,11 +575,14 @@ func TestAnnealMigrationAnnotations(t *testing.T) {
func TestModifyDeletionFinalizers(t *testing.T) {
// This set of tests ensures that protection finalizer is removed when CSI migration is disabled
// and PV controller needs to remove finalizers added by the external-provisioner.
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
// and PV controller needs to remove finalizers added by the external-provisioner. The rbd
// in-tree plugin is used as migration is disabled. When that plugin is migrated, a different
// non-migrated one should be used. If all plugins are migrated this test can be removed. The
// gce in-tree plugin is used for a migrated driver as it is feature-locked as of 1.25.
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HonorPVReclaimPolicy, true)()
const gcePlugin = "kubernetes.io/gce-pd"
const gceDriver = "pd.csi.storage.gke.io"
const nonmigratedDriver = "rbd.csi.ceph.com"
const migratedPlugin = "kubernetes.io/gce-pd"
const migratedDriver = "pd.csi.storage.gke.io"
const customFinalizer = "test.volume.kubernetes.io/finalizer"
tests := []struct {
name string
@ -619,24 +590,21 @@ func TestModifyDeletionFinalizers(t *testing.T) {
volumeAnnotations map[string]string
expVolumeFinalizers []string
expModified bool
migratedDriverGates []featuregate.Feature
}{
{
// Represents a CSI volume provisioned through external-provisioner, no CSI migration enabled.
name: "13-1 migration was never enabled, volume has the finalizer",
initialVolume: newExternalProvisionedVolume("volume-13-1", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, gceDriver, []string{volume.PVDeletionProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
initialVolume: newExternalProvisionedVolume("volume-13-1", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nonmigratedDriver, []string{volume.PVDeletionProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents a volume provisioned through external-provisioner but the external-provisioner has
// yet to sync the volume to add the new finalizer
name: "13-2 migration was never enabled, volume does not have the finalizer",
initialVolume: newExternalProvisionedVolume("volume-13-2", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, gceDriver, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
initialVolume: newExternalProvisionedVolume("volume-13-2", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nonmigratedDriver, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents an in-tree volume that has the migrated-to annotation but the external-provisioner is
@ -648,14 +616,12 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-3", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{customFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{customFinalizer, volume.PVDeletionInTreeProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
name: "13-4 migration was disabled, volume has no finalizers",
initialVolume: newVolumeWithFinalizers("volume-13-4", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents roll back scenario where the external-provisioner has added the pv deletion protection
@ -665,7 +631,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-5", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents roll-back of csi-migration as 13-5, here there are multiple finalizers, only the pv deletion
@ -675,17 +640,15 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-6", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer, customFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{customFinalizer, volume.PVDeletionInTreeProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// csi migration is enabled, the pv controller should not delete the finalizer added by the
// external-provisioner and the in-tree finalizer should be deleted.
name: "13-7 migration is enabled, volume has both the in-tree and external PV deletion protection finalizer",
initialVolume: newVolumeWithFinalizers("volume-13-7", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer, volume.PVDeletionInTreeProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
},
{
// csi-migration is not completely enabled as the specific plugin feature is not present. This is equivalent
@ -694,7 +657,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-8", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// same as 13-8 but multiple finalizers exists, only the pv deletion protection finalizer needs to be
@ -703,7 +665,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-9", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer, customFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: []string{customFinalizer, volume.PVDeletionInTreeProtectionFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// corner error case.
@ -711,14 +672,12 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-10", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer}),
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
name: "13-11 missing annotations and finalizers",
initialVolume: newVolumeWithFinalizers("volume-13-11", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nil),
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// When ReclaimPolicy is Retain ensure that in-tree pv deletion protection finalizer is not added.
@ -726,7 +685,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-12", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classCopper, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// When ReclaimPolicy is Recycle ensure that in-tree pv deletion protection finalizer is not added.
@ -734,7 +692,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-13", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimRecycle, classCopper, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// When ReclaimPolicy is Retain ensure that in-tree pv deletion protection finalizer present is removed.
@ -742,7 +699,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-14", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classCopper, []string{volume.PVDeletionInTreeProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
expVolumeFinalizers: nil,
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// Statically provisioned volumes should not have the in-tree pv deletion protection finalizer
@ -750,7 +706,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
initialVolume: newVolumeWithFinalizers("volume-13-14", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classCopper, nil),
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
}
@ -759,9 +714,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
for _, f := range tc.migratedDriverGates {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, true)()
}
if tc.volumeAnnotations != nil {
tc.initialVolume.SetAnnotations(tc.volumeAnnotations)
}

View File

@ -134,6 +134,7 @@ const (
// owner: @davidz627
// alpha: v1.14
// beta: v1.17
// GA: 1.25
//
// Enables the GCE PD in-tree driver to GCE CSI Driver migration feature.
CSIMigrationGCE featuregate.Feature = "CSIMigrationGCE"
@ -880,7 +881,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
CSIMigrationAzureFile: {Default: true, PreRelease: featuregate.Beta}, // On by default in 1.24 (requires Azure File CSI driver)
CSIMigrationGCE: {Default: true, PreRelease: featuregate.Beta}, // On by default in 1.23 (requires GCE PD CSI Driver)
CSIMigrationGCE: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.25 (requires GCE PD CSI Driver)
CSIMigrationOpenStack: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26

View File

@ -25,10 +25,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature"
core "k8s.io/client-go/testing"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume"
volumetest "k8s.io/kubernetes/pkg/volume/testing"
"k8s.io/kubernetes/pkg/volume/util"
@ -103,8 +100,6 @@ func TestPodVolumesExist(t *testing.T) {
t.Skip("skipping test in short mode.")
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
@ -131,8 +126,8 @@ func TestPodVolumesExist(t *testing.T) {
{
Name: "vol1",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device1",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake1",
},
},
},
@ -160,8 +155,8 @@ func TestPodVolumesExist(t *testing.T) {
{
Name: "vol2",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device2",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake2",
},
},
},
@ -189,8 +184,8 @@ func TestPodVolumesExist(t *testing.T) {
{
Name: "vol3",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device3",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake3",
},
},
},
@ -219,8 +214,6 @@ func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
t.Skip("skipping test in short mode.")
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
@ -241,8 +234,8 @@ func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
{
Name: "vol1",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake",
},
},
},
@ -280,8 +273,6 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
t.Skip("skipping test in short mode.")
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
@ -302,8 +293,8 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
{
Name: "vol1",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake-device",
},
},
},
@ -371,8 +362,6 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
t.Skip("skipping test in short mode.")
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
@ -410,8 +399,8 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
{
Name: "vol1",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake-device",
},
},
},
@ -457,8 +446,6 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
t.Skip("skipping test in short mode.")
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
@ -496,8 +483,8 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
{
Name: "vol1",
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device",
RBD: &v1.RBDVolumeSource{
RBDImage: "fake-device",
},
},
},

View File

@ -31,13 +31,10 @@ import (
kubetypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/record"
utiltesting "k8s.io/client-go/util/testing"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/config"
"k8s.io/kubernetes/pkg/kubelet/configmap"
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
@ -56,8 +53,6 @@ const (
)
func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
tests := []struct {
name string
pvMode, podMode v1.PersistentVolumeMode
@ -145,8 +140,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
}
func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
if err != nil {
t.Fatalf("can't make a temp dir: %v", err)
@ -192,8 +185,6 @@ func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
}
func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
if err != nil {
t.Fatalf("can't make a temp dir: %v", err)
@ -238,8 +229,8 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device",
RBD: &v1.RBDPersistentVolumeSource{
RBDImage: "fake-device",
},
},
ClaimRef: &v1.ObjectReference{
@ -385,8 +376,8 @@ func createObjects(pvMode, podMode v1.PersistentVolumeMode) (*v1.Node, *v1.Pod,
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "fake-device",
RBD: &v1.RBDPersistentVolumeSource{
RBDImage: "fake-device",
},
},
ClaimRef: &v1.ObjectReference{

View File

@ -33,19 +33,16 @@ import (
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers"
coreinformers "k8s.io/client-go/informers/core/v1"
storageinformers "k8s.io/client-go/informers/storage/v1"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
k8stesting "k8s.io/client-go/testing"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/component-helpers/storage/volume"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/controller"
pvtesting "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing"
"k8s.io/kubernetes/pkg/features"
)
var (
@ -94,8 +91,9 @@ var (
pvBoundImmediateNode2 = makeTestPV("pv-bound-immediate", "node2", "1G", "1", immediateBoundPVC, immediateClass)
// PVs for CSI migration
migrationPVBound = makeTestPVForCSIMigration(zone1Labels, boundMigrationPVC)
migrationPVBoundToUnbound = makeTestPVForCSIMigration(zone1Labels, unboundPVC)
migrationPVBound = makeTestPVForCSIMigration(zone1Labels, boundMigrationPVC, true)
migrationPVBoundToUnbound = makeTestPVForCSIMigration(zone1Labels, unboundPVC, true)
nonmigrationPVBoundToUnbound = makeTestPVForCSIMigration(zone1Labels, unboundPVC, false)
// storage class names
waitClass = "waitClass"
@ -693,17 +691,29 @@ func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentV
return pv
}
func makeTestPVForCSIMigration(labels map[string]string, pvc *v1.PersistentVolumeClaim) *v1.PersistentVolume {
func makeTestPVForCSIMigration(labels map[string]string, pvc *v1.PersistentVolumeClaim, migrationEnabled bool) *v1.PersistentVolume {
pv := makeTestPV("pv-migration-bound", "node1", "1G", "1", pvc, waitClass)
pv.Spec.NodeAffinity = nil // Will be written by the CSI translation lib
pv.ObjectMeta.Labels = labels
pv.Spec.PersistentVolumeSource = v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "test-disk",
FSType: "ext4",
Partition: 0,
ReadOnly: false,
},
// GCEPersistentDisk is used when migration is enabled, as its featuregate is locked to GA.
// RBD is used for the nonmigrated case, as its featuregate is still alpha. When RBD migration goes GA,
// a different nonmigrated plugin should be used instead. If there are no other plugins, then the
// nonmigrated test case is no longer relevant and can be removed.
if migrationEnabled {
pv.Spec.PersistentVolumeSource = v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "test-disk",
FSType: "ext4",
Partition: 0,
ReadOnly: false,
},
}
} else {
pv.Spec.PersistentVolumeSource = v1.PersistentVolumeSource{
RBD: &v1.RBDPersistentVolumeSource{
RBDImage: "test-disk",
},
}
}
return pv
}
@ -1217,8 +1227,6 @@ func TestFindPodVolumesWithCSIMigration(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, true)()
// Setup
testEnv := newTestBinder(t, ctx.Done())
testEnv.initVolumes(scenario.pvs, scenario.pvs)
@ -1775,9 +1783,8 @@ func TestCheckBindingsWithCSIMigration(t *testing.T) {
apiPVCs []*v1.PersistentVolumeClaim
// Expected return values
shouldFail bool
expectedBound bool
migrationEnabled bool
shouldFail bool
expectedBound bool
}
scenarios := map[string]scenarioType{
"provisioning-pvc-bound": {
@ -1791,50 +1798,45 @@ func TestCheckBindingsWithCSIMigration(t *testing.T) {
expectedBound: true,
},
"binding-node-pv-same-zone": {
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone1},
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
migrationEnabled: true,
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone1},
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
},
"binding-without-csinode": {
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone1},
initCSINodes: []*storagev1.CSINode{},
migrationEnabled: true,
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone1},
initCSINodes: []*storagev1.CSINode{},
},
"binding-non-migrated-plugin": {
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone1},
initCSINodes: []*storagev1.CSINode{csiNode1NotMigrated},
migrationEnabled: true,
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone1},
initCSINodes: []*storagev1.CSINode{csiNode1NotMigrated},
},
"binding-node-pv-in-different-zones": {
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone2},
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
migrationEnabled: true,
shouldFail: true,
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone2},
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
shouldFail: true,
},
"binding-node-pv-different-zones-migration-off": {
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone2},
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
migrationEnabled: false,
bindings: []*BindingInfo{makeBinding(unboundPVC, nonmigrationPVBoundToUnbound)},
provisionedPVCs: []*v1.PersistentVolumeClaim{},
initPVs: []*v1.PersistentVolume{nonmigrationPVBoundToUnbound},
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
initNodes: []*v1.Node{node1Zone2},
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
},
}
@ -1842,8 +1844,6 @@ func TestCheckBindingsWithCSIMigration(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, scenario.migrationEnabled)()
// Setup
pod := makePod("test-pod").
withNamespace("testns").

View File

@ -39,8 +39,8 @@ func TestIsMigratable(t *testing.T) {
spec *volume.Spec
}{
{
name: "GCE PD PV source with CSIMigrationGCE enabled",
pluginFeature: features.CSIMigrationGCE,
name: "RBD PV source with CSIMigrationGCE enabled",
pluginFeature: features.CSIMigrationRBD,
pluginFeatureEnabled: true,
isMigratable: true,
csiMigrationEnabled: true,
@ -48,11 +48,8 @@ func TestIsMigratable(t *testing.T) {
PersistentVolume: &v1.PersistentVolume{
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "test-disk",
FSType: "ext4",
Partition: 0,
ReadOnly: false,
RBD: &v1.RBDPersistentVolumeSource{
RBDImage: "test-disk",
},
},
},
@ -60,8 +57,8 @@ func TestIsMigratable(t *testing.T) {
},
},
{
name: "GCE PD PV Source with CSIMigrationGCE disabled",
pluginFeature: features.CSIMigrationGCE,
name: "RBD PD PV Source with CSIMigrationGCE disabled",
pluginFeature: features.CSIMigrationRBD,
pluginFeatureEnabled: false,
isMigratable: false,
csiMigrationEnabled: true,
@ -69,11 +66,8 @@ func TestIsMigratable(t *testing.T) {
PersistentVolume: &v1.PersistentVolume{
Spec: v1.PersistentVolumeSpec{
PersistentVolumeSource: v1.PersistentVolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "test-disk",
FSType: "ext4",
Partition: 0,
ReadOnly: false,
RBD: &v1.RBDPersistentVolumeSource{
RBDImage: "test-disk",
},
},
},
@ -186,28 +180,6 @@ func TestMigrationFeatureFlagStatus(t *testing.T) {
csiMigrationResult bool
csiMigrationCompleteResult bool
}{
{
name: "gce-pd migration flag disabled and migration-complete flag disabled with CSI migration flag disabled",
pluginName: "kubernetes.io/gce-pd",
pluginFeature: features.CSIMigrationGCE,
pluginFeatureEnabled: false,
csiMigrationEnabled: false,
inTreePluginUnregister: features.InTreePluginGCEUnregister,
inTreePluginUnregisterEnabled: false,
csiMigrationResult: false,
csiMigrationCompleteResult: false,
},
{
name: "gce-pd migration flag disabled and migration-complete flag disabled with CSI migration flag enabled",
pluginName: "kubernetes.io/gce-pd",
pluginFeature: features.CSIMigrationGCE,
pluginFeatureEnabled: false,
csiMigrationEnabled: true,
inTreePluginUnregister: features.InTreePluginGCEUnregister,
inTreePluginUnregisterEnabled: false,
csiMigrationResult: false,
csiMigrationCompleteResult: false,
},
{
name: "gce-pd migration flag enabled and migration-complete flag disabled with CSI migration flag enabled",
pluginName: "kubernetes.io/gce-pd",
@ -257,7 +229,12 @@ func TestMigrationFeatureFlagStatus(t *testing.T) {
for _, test := range testCases {
pm := NewPluginManager(csiTranslator, utilfeature.DefaultFeatureGate)
t.Run(fmt.Sprintf("Testing %v", test.name), func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeature, test.pluginFeatureEnabled)()
// CSIMigrationGCE is locked to on, so it cannot be enabled or disabled. There are a couple
// of test cases that check correct behavior when CSIMigrationGCE is enabled, but there are
// no longer any tests cases for CSIMigrationGCE being disabled as that is not possible.
if test.pluginFeature != features.CSIMigrationGCE {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.pluginFeature, test.pluginFeatureEnabled)()
}
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.inTreePluginUnregister, test.inTreePluginUnregisterEnabled)()
csiMigrationResult := pm.IsMigrationEnabledForPlugin(test.pluginName)

View File

@ -250,9 +250,14 @@ func (plugin *FakeVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error)
var volumeName string
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
volumeName = spec.Volume.GCEPersistentDisk.PDName
} else if spec.Volume != nil && spec.Volume.RBD != nil {
volumeName = spec.Volume.RBD.RBDImage
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
} else if spec.Volume != nil && spec.Volume.CSI != nil {
volumeName = spec.Volume.CSI.Driver
}
@ -671,9 +676,14 @@ func getUniqueVolumeName(spec *volume.Spec) (string, error) {
var volumeName string
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
volumeName = spec.Volume.GCEPersistentDisk.PDName
} else if spec.Volume != nil && spec.Volume.RBD != nil {
volumeName = spec.Volume.RBD.RBDImage
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
} else if spec.PersistentVolume != nil &&
spec.PersistentVolume.Spec.RBD != nil {
volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
}
if volumeName == "" {
volumeName = spec.Name()