PV controller changes to support PV Deletion protection finalizer

Signed-off-by: Deepak Kinni <dkinni@vmware.com>
This commit is contained in:
Deepak Kinni
2021-10-19 14:26:28 -07:00
parent bafa87c553
commit bfd5f23a0b
6 changed files with 222 additions and 18 deletions

View File

@@ -59,6 +59,7 @@ var (
// can't reliably simulate periodic sync of volumes/claims - it would be
// either very timing-sensitive or slow to wait for real periodic sync.
func TestControllerSync(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HonorPVReclaimPolicy, true)()
tests := []controllerTest{
// [Unit test set 5] - controller tests.
// We test the controller as if
@@ -295,6 +296,23 @@ func TestControllerSync(t *testing.T) {
return nil
},
},
{
// Test that the finalizer gets removed if CSI migration is disabled.
"5-9 - volume has its PV deletion protection finalizer removed as CSI migration is disabled",
volumesWithFinalizers(
volumesWithAnnotation(pvutil.AnnMigratedTo, "pd.csi.storage.gke.io",
newVolumeArray("volume-5-9", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classEmpty, pvutil.AnnDynamicallyProvisioned)),
[]string{pvutil.PVDeletionProtectionFinalizer},
),
newVolumeArray("volume-5-9", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classEmpty, pvutil.AnnDynamicallyProvisioned),
noclaims,
noclaims,
noevents,
noerrors,
func(ctrl *PersistentVolumeController, reactor *pvtesting.VolumeReactor, test controllerTest) error {
return nil
},
},
}
doit := func(test controllerTest) {
@@ -642,14 +660,14 @@ func TestAnnealMigrationAnnotations(t *testing.T) {
}
if tc.volumeAnnotations != nil {
ann := tc.volumeAnnotations
updateMigrationAnnotations(cmpm, translator, ann, false)
updateMigrationAnnotationsAndFinalizers(cmpm, translator, ann, nil, false)
if !reflect.DeepEqual(tc.expVolumeAnnotations, ann) {
t.Errorf("got volume annoations: %v, but expected: %v", ann, tc.expVolumeAnnotations)
}
}
if tc.claimAnnotations != nil {
ann := tc.claimAnnotations
updateMigrationAnnotations(cmpm, translator, ann, true)
updateMigrationAnnotationsAndFinalizers(cmpm, translator, ann, nil, true)
if !reflect.DeepEqual(tc.expClaimAnnotations, ann) {
t.Errorf("got volume annoations: %v, but expected: %v", ann, tc.expVolumeAnnotations)
}
@@ -658,3 +676,157 @@ func TestAnnealMigrationAnnotations(t *testing.T) {
})
}
}
func TestUpdateFinalizer(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HonorPVReclaimPolicy, true)()
const gcePlugin = "kubernetes.io/gce-pd"
const gceDriver = "pd.csi.storage.gke.io"
const customFinalizer = "test.volume.kubernetes.io/finalizer"
tests := []struct {
name string
volumeAnnotations map[string]string
volumeFinalizers []string
expVolumeFinalizers []string
expModified bool
migratedDriverGates []featuregate.Feature
}{
{
// Represents a volume provisioned through external-provisioner
name: "13-1 migration was never enabled, volume has the finalizer",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gceDriver},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expVolumeFinalizers: []string{pvutil.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",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gceDriver},
volumeFinalizers: nil,
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents an in-tree volume that has the migrated-to annotation but the external-provisioner is
// yet to sync the volume and add the pv deletion protection finalizer. The custom finalizer is some
// pre-existing finalizer, for example the pv-protection finalizer. The csi-migration is disabled,
// the migrated-to annotation will be removed shortly when updateVolumeMigrationAnnotationsAndFinalizers is called.
name: "13-3 migration was disabled but still has migrated-to annotation, volume does not have pv deletion protection finalizer",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: []string{customFinalizer},
expVolumeFinalizers: []string{customFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
name: "13-4 migration was disabled but still has migrated-to annotation, volume has no finalizers",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: nil,
expVolumeFinalizers: nil,
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents roll back scenario where the external-provisioner has added the pv deletion protection
// finalizer and later the csi migration was disabled. The pv deletion protection finalizer added through
// external-provisioner will be removed.
name: "13-5 migration was disabled as it has the migrated-to annotation, volume has the finalizer",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expVolumeFinalizers: nil,
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// Represents roll-back of csi-migration as 13-5, here there are multiple finalizers, only the pv deletion
// protection finalizer added by external-provisioner needs to be removed.
name: "13-6 migration was disabled as it has the migrated-to annotation, volume has multiple finalizers",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer, customFinalizer},
expVolumeFinalizers: []string{customFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{},
},
{
// csi migration is enabled, the pv controller should not delete the finalizer added by the
// external-provisioner.
name: "13-7 migration is enabled, has the migrated-to annotation, volume has the finalizer",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expVolumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expModified: false,
migratedDriverGates: []featuregate.Feature{features.CSIMigration, features.CSIMigrationGCE},
},
{
// csi-migration is not completely enabled as the specific plugin feature is not present. This is equivalent
// of disabled csi-migration.
name: "13-8 migration is enabled but plugin migration feature is disabled, has the migrated-to annotation, volume has the finalizer",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expVolumeFinalizers: nil,
expModified: true,
migratedDriverGates: []featuregate.Feature{features.CSIMigration},
},
{
// same as 13-8 but multiple finalizers exists, only the pv deletion protection finalizer needs to be removed.
name: "13-9 migration is enabled but plugin migration feature is disabled, has the migrated-to annotation, volume has multiple finalizers",
volumeAnnotations: map[string]string{pvutil.AnnDynamicallyProvisioned: gcePlugin, pvutil.AnnMigratedTo: gceDriver},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer, customFinalizer},
expVolumeFinalizers: []string{customFinalizer},
expModified: true,
migratedDriverGates: []featuregate.Feature{features.CSIMigration},
},
{
// corner error case.
name: "13-10 missing annotations but finalizers exist",
volumeAnnotations: nil,
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expVolumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
name: "13-11 missing annotations and finalizers",
volumeAnnotations: nil,
volumeFinalizers: nil,
expVolumeFinalizers: nil,
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
{
// corner error case
name: "13-12 missing provisioned-by annotation, existing finalizers",
volumeAnnotations: map[string]string{"fake": gcePlugin},
volumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expVolumeFinalizers: []string{pvutil.PVDeletionProtectionFinalizer},
expModified: false,
migratedDriverGates: []featuregate.Feature{},
},
}
translator := csitrans.New()
cmpm := csimigration.NewPluginManager(translator, utilfeature.DefaultFeatureGate)
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 {
ann := tc.volumeAnnotations
finalizers := tc.volumeFinalizers
modified := updateMigrationAnnotationsAndFinalizers(cmpm, translator, ann, &finalizers, false)
if modified != tc.expModified {
t.Errorf("got modified: %v, but expected: %v", modified, tc.expModified)
}
if !reflect.DeepEqual(tc.expVolumeFinalizers, finalizers) {
t.Errorf("got volume finaliers: %v, but expected: %v", finalizers, tc.expVolumeFinalizers)
}
}
})
}
}