mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #111301 from mattcary/migration-feature
Upgrade CSIMigrationGCE feature gate to GA
This commit is contained in:
commit
369a465fae
@ -26,14 +26,11 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
kcache "k8s.io/client-go/tools/cache"
|
kcache "k8s.io/client-go/tools/cache"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
||||||
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
|
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/csi"
|
"k8s.io/kubernetes/pkg/volume/csi"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -431,15 +428,9 @@ func volumeAttachmentRecoveryTestCase(t *testing.T, tc vaTest) {
|
|||||||
informerFactory := informers.NewSharedInformerFactory(fakeKubeClient, time.Second*1)
|
informerFactory := informers.NewSharedInformerFactory(fakeKubeClient, time.Second*1)
|
||||||
var plugins []volume.VolumePlugin
|
var plugins []volume.VolumePlugin
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, tc.csiMigration)()
|
plugins = append(plugins, controllervolumetesting.CreateTestPlugin()...)
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InTreePluginGCEUnregister, tc.csiMigration)()
|
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()
|
nodeInformer := informerFactory.Core().V1().Nodes().Informer()
|
||||||
podInformer := informerFactory.Core().V1().Pods().Informer()
|
podInformer := informerFactory.Core().V1().Pods().Informer()
|
||||||
pvInformer := informerFactory.Core().V1().PersistentVolumes().Informer()
|
pvInformer := informerFactory.Core().V1().PersistentVolumes().Informer()
|
||||||
@ -522,7 +513,14 @@ func volumeAttachmentRecoveryTestCase(t *testing.T, tc vaTest) {
|
|||||||
podInformer.GetIndexer().Add(newPod)
|
podInformer.GetIndexer().Add(newPod)
|
||||||
}
|
}
|
||||||
if tc.pvName != "" {
|
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{})
|
_, err = adc.kubeClient.CoreV1().PersistentVolumes().Create(context.TODO(), newPv, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Run failed with error. Failed to create a new pv: <%v>", err)
|
t.Fatalf("Run failed with error. Failed to create a new pv: <%v>", err)
|
||||||
|
@ -26,19 +26,16 @@ import (
|
|||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
csitrans "k8s.io/csi-translation-lib"
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
||||||
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
|
controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume/csimigration"
|
"k8s.io/kubernetes/pkg/volume/csimigration"
|
||||||
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVolumesInUseMetricCollection(t *testing.T) {
|
func TestVolumesInUseMetricCollection(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
fakeVolumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
fakeVolumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
|
|
||||||
@ -101,6 +98,7 @@ func TestVolumesInUseMetricCollection(t *testing.T) {
|
|||||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse("5G"),
|
v1.ResourceName(v1.ResourceStorage): resource.MustParse("5G"),
|
||||||
},
|
},
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
|
// Note that as GCE CSI Migration is completed, this is handled by the PD CSI plugin.
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
|
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{},
|
||||||
},
|
},
|
||||||
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce, v1.ReadOnlyMany},
|
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))
|
t.Errorf("Expected one volume in use got %d", len(nodeUseMap))
|
||||||
}
|
}
|
||||||
testNodeMetric := nodeUseMap["metric-test-host"]
|
testNodeMetric := nodeUseMap["metric-test-host"]
|
||||||
pluginUseCount, ok := testNodeMetric["fake-plugin"]
|
pluginUseCount, ok := testNodeMetric["fake-plugin:pd.csi.storage.gke.io"]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("Expected fake plugin pvc got nothing")
|
t.Errorf("Expected fake plugin pvc got nothing")
|
||||||
}
|
}
|
||||||
|
@ -26,19 +26,15 @@ import (
|
|||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
csitrans "k8s.io/csi-translation-lib"
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume/csimigration"
|
"k8s.io/kubernetes/pkg/volume/csimigration"
|
||||||
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
|
func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
fakeVolumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
fakeVolumePluginMgr, _ := volumetesting.GetTestVolumePluginMgr(t)
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
|
|
||||||
@ -59,8 +55,8 @@ func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "dswp-test-volume-name",
|
Name: "dswp-test-volume-name",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "dswp-test-fake-device",
|
RBDImage: "dswp-test-fake-device",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -75,7 +71,7 @@ func TestFindAndAddActivePods_FindAndRemoveDeletedPods(t *testing.T) {
|
|||||||
|
|
||||||
podName := util.GetUniquePodName(pod)
|
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()
|
pvcLister := fakeInformerFactory.Core().V1().PersistentVolumeClaims().Lister()
|
||||||
pvLister := fakeInformerFactory.Core().V1().PersistentVolumes().Lister()
|
pvLister := fakeInformerFactory.Core().V1().PersistentVolumes().Lister()
|
||||||
|
@ -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) {
|
func attachVolumeToNode(nodes *v1.NodeList, volumeName, nodeName string) {
|
||||||
// if nodeName exists, get the object.. if not create node object
|
// if nodeName exists, get the object.. if not create node object
|
||||||
var node *v1.Node
|
var node *v1.Node
|
||||||
@ -366,7 +383,14 @@ func (plugin *TestPlugin) GetVolumeName(spec *volume.Spec) (string, error) {
|
|||||||
if spec.Volume != nil {
|
if spec.Volume != nil {
|
||||||
return spec.Name(), nil
|
return spec.Name(), nil
|
||||||
} else if spec.PersistentVolume != 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 {
|
} else {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ import (
|
|||||||
storagelisters "k8s.io/client-go/listers/storage/v1"
|
storagelisters "k8s.io/client-go/listers/storage/v1"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/component-base/featuregate"
|
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/component-helpers/storage/volume"
|
"k8s.io/component-helpers/storage/volume"
|
||||||
csitrans "k8s.io/csi-translation-lib"
|
csitrans "k8s.io/csi-translation-lib"
|
||||||
@ -471,107 +470,82 @@ func makeStorageClass(scName string, mode *storagev1.VolumeBindingMode) *storage
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAnnealMigrationAnnotations(t *testing.T) {
|
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 testPlugin = "non-migrated-plugin"
|
||||||
const gcePlugin = "kubernetes.io/gce-pd"
|
const migratedPlugin = "kubernetes.io/gce-pd"
|
||||||
const gceDriver = "pd.csi.storage.gke.io"
|
const migratedDriver = "pd.csi.storage.gke.io"
|
||||||
|
const nonmigratedPlugin = "kubernetes.io/rbd"
|
||||||
|
const nonmigratedDriver = "rbd.csi.ceph.com"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
volumeAnnotations map[string]string
|
volumeAnnotations map[string]string
|
||||||
expVolumeAnnotations map[string]string
|
expVolumeAnnotations map[string]string
|
||||||
claimAnnotations map[string]string
|
claimAnnotations map[string]string
|
||||||
expClaimAnnotations map[string]string
|
expClaimAnnotations map[string]string
|
||||||
migratedDriverGates []featuregate.Feature
|
testMigration bool
|
||||||
disabledDriverGates []featuregate.Feature
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "migration on for GCE",
|
name: "migration on",
|
||||||
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
|
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin},
|
||||||
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
|
||||||
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
|
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: migratedPlugin},
|
||||||
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
|
||||||
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
disabledDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "migration on for GCE with Beta storage provisioner annontation",
|
name: "migration on with Beta storage provisioner annontation",
|
||||||
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
|
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin},
|
||||||
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
|
||||||
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin},
|
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: migratedPlugin},
|
||||||
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: migratedPlugin, volume.AnnMigratedTo: migratedDriver},
|
||||||
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
disabledDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "migration off for GCE",
|
name: "migration off",
|
||||||
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
|
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
|
||||||
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
|
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
|
||||||
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
|
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin},
|
||||||
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
|
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin},
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "migration off for GCE removes migrated to (rollback)",
|
name: "migration off removes migrated to (rollback)",
|
||||||
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
|
||||||
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
|
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
|
||||||
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
|
||||||
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: gcePlugin},
|
expClaimAnnotations: map[string]string{volume.AnnStorageProvisioner: nonmigratedPlugin},
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "migration off for GCE removes migrated to (rollback) with Beta storage provisioner annontation",
|
name: "migration off removes migrated to (rollback) with Beta storage provisioner annontation",
|
||||||
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
|
||||||
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: gcePlugin},
|
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: nonmigratedPlugin},
|
||||||
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin, volume.AnnMigratedTo: gceDriver},
|
claimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: nonmigratedPlugin, volume.AnnMigratedTo: nonmigratedDriver},
|
||||||
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: gcePlugin},
|
expClaimAnnotations: map[string]string{volume.AnnBetaStorageProvisioner: nonmigratedPlugin},
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "migration on for GCE other plugin not affected",
|
name: "migration on, other plugin not affected",
|
||||||
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: testPlugin},
|
volumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: testPlugin},
|
||||||
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: testPlugin},
|
expVolumeAnnotations: map[string]string{volume.AnnDynamicallyProvisioned: testPlugin},
|
||||||
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: testPlugin},
|
claimAnnotations: map[string]string{volume.AnnStorageProvisioner: testPlugin},
|
||||||
expClaimAnnotations: 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{},
|
volumeAnnotations: map[string]string{},
|
||||||
expVolumeAnnotations: map[string]string{},
|
expVolumeAnnotations: map[string]string{},
|
||||||
claimAnnotations: map[string]string{},
|
claimAnnotations: map[string]string{},
|
||||||
expClaimAnnotations: map[string]string{},
|
expClaimAnnotations: map[string]string{},
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
testMigration: false,
|
||||||
disabledDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "not dynamically provisioned migration on for GCE",
|
name: "nil annotations",
|
||||||
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",
|
|
||||||
volumeAnnotations: nil,
|
volumeAnnotations: nil,
|
||||||
expVolumeAnnotations: nil,
|
expVolumeAnnotations: nil,
|
||||||
claimAnnotations: nil,
|
claimAnnotations: nil,
|
||||||
expClaimAnnotations: nil,
|
expClaimAnnotations: nil,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
testMigration: false,
|
||||||
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{},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,12 +554,6 @@ func TestAnnealMigrationAnnotations(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
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 {
|
if tc.volumeAnnotations != nil {
|
||||||
ann := tc.volumeAnnotations
|
ann := tc.volumeAnnotations
|
||||||
updateMigrationAnnotations(cmpm, translator, ann, false)
|
updateMigrationAnnotations(cmpm, translator, ann, false)
|
||||||
@ -607,11 +575,14 @@ func TestAnnealMigrationAnnotations(t *testing.T) {
|
|||||||
|
|
||||||
func TestModifyDeletionFinalizers(t *testing.T) {
|
func TestModifyDeletionFinalizers(t *testing.T) {
|
||||||
// This set of tests ensures that protection finalizer is removed when CSI migration is disabled
|
// 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.
|
// and PV controller needs to remove finalizers added by the external-provisioner. The rbd
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
// 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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.HonorPVReclaimPolicy, true)()
|
||||||
const gcePlugin = "kubernetes.io/gce-pd"
|
const nonmigratedDriver = "rbd.csi.ceph.com"
|
||||||
const gceDriver = "pd.csi.storage.gke.io"
|
const migratedPlugin = "kubernetes.io/gce-pd"
|
||||||
|
const migratedDriver = "pd.csi.storage.gke.io"
|
||||||
const customFinalizer = "test.volume.kubernetes.io/finalizer"
|
const customFinalizer = "test.volume.kubernetes.io/finalizer"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -619,24 +590,21 @@ func TestModifyDeletionFinalizers(t *testing.T) {
|
|||||||
volumeAnnotations map[string]string
|
volumeAnnotations map[string]string
|
||||||
expVolumeFinalizers []string
|
expVolumeFinalizers []string
|
||||||
expModified bool
|
expModified bool
|
||||||
migratedDriverGates []featuregate.Feature
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
// Represents a CSI volume provisioned through external-provisioner, no CSI migration enabled.
|
// Represents a CSI volume provisioned through external-provisioner, no CSI migration enabled.
|
||||||
name: "13-1 migration was never enabled, volume has the finalizer",
|
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},
|
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Represents a volume provisioned through external-provisioner but the external-provisioner has
|
// Represents a volume provisioned through external-provisioner but the external-provisioner has
|
||||||
// yet to sync the volume to add the new finalizer
|
// yet to sync the volume to add the new finalizer
|
||||||
name: "13-2 migration was never enabled, volume does not have the 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,
|
expVolumeFinalizers: nil,
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Represents an in-tree volume that has the migrated-to annotation but the external-provisioner is
|
// 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),
|
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},
|
expVolumeFinalizers: []string{customFinalizer, volume.PVDeletionInTreeProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "13-4 migration was disabled, volume has no finalizers",
|
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),
|
initialVolume: newVolumeWithFinalizers("volume-13-4", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
|
||||||
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
|
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Represents roll back scenario where the external-provisioner has added the pv deletion protection
|
// 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),
|
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},
|
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Represents roll-back of csi-migration as 13-5, here there are multiple finalizers, only the pv deletion
|
// 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),
|
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},
|
expVolumeFinalizers: []string{customFinalizer, volume.PVDeletionInTreeProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// csi migration is enabled, the pv controller should not delete the finalizer added by the
|
// 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.
|
// 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",
|
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),
|
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},
|
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{features.CSIMigrationGCE},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// csi-migration is not completely enabled as the specific plugin feature is not present. This is equivalent
|
// 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),
|
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},
|
expVolumeFinalizers: []string{volume.PVDeletionInTreeProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// same as 13-8 but multiple finalizers exists, only the pv deletion protection finalizer needs to be
|
// 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),
|
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},
|
expVolumeFinalizers: []string{customFinalizer, volume.PVDeletionInTreeProtectionFinalizer},
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// corner error case.
|
// 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}),
|
initialVolume: newVolumeWithFinalizers("volume-13-10", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, []string{volume.PVDeletionProtectionFinalizer}),
|
||||||
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
|
expVolumeFinalizers: []string{volume.PVDeletionProtectionFinalizer},
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "13-11 missing annotations and finalizers",
|
name: "13-11 missing annotations and finalizers",
|
||||||
initialVolume: newVolumeWithFinalizers("volume-13-11", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nil),
|
initialVolume: newVolumeWithFinalizers("volume-13-11", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimDelete, classCopper, nil),
|
||||||
expVolumeFinalizers: nil,
|
expVolumeFinalizers: nil,
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// When ReclaimPolicy is Retain ensure that in-tree pv deletion protection finalizer is not added.
|
// 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),
|
initialVolume: newVolumeWithFinalizers("volume-13-12", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classCopper, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
|
||||||
expVolumeFinalizers: nil,
|
expVolumeFinalizers: nil,
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// When ReclaimPolicy is Recycle ensure that in-tree pv deletion protection finalizer is not added.
|
// 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),
|
initialVolume: newVolumeWithFinalizers("volume-13-13", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimRecycle, classCopper, nil, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
|
||||||
expVolumeFinalizers: nil,
|
expVolumeFinalizers: nil,
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// When ReclaimPolicy is Retain ensure that in-tree pv deletion protection finalizer present is removed.
|
// 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),
|
initialVolume: newVolumeWithFinalizers("volume-13-14", "1Gi", "uid11-23", "claim11-23", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classCopper, []string{volume.PVDeletionInTreeProtectionFinalizer}, volume.AnnDynamicallyProvisioned, volume.AnnBoundByController),
|
||||||
expVolumeFinalizers: nil,
|
expVolumeFinalizers: nil,
|
||||||
expModified: true,
|
expModified: true,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Statically provisioned volumes should not have the in-tree pv deletion protection finalizer
|
// 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),
|
initialVolume: newVolumeWithFinalizers("volume-13-14", "1Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimDelete, classCopper, nil),
|
||||||
expVolumeFinalizers: nil,
|
expVolumeFinalizers: nil,
|
||||||
expModified: false,
|
expModified: false,
|
||||||
migratedDriverGates: []featuregate.Feature{},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,9 +714,6 @@ func TestModifyDeletionFinalizers(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
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 {
|
if tc.volumeAnnotations != nil {
|
||||||
tc.initialVolume.SetAnnotations(tc.volumeAnnotations)
|
tc.initialVolume.SetAnnotations(tc.volumeAnnotations)
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,7 @@ const (
|
|||||||
// owner: @davidz627
|
// owner: @davidz627
|
||||||
// alpha: v1.14
|
// alpha: v1.14
|
||||||
// beta: v1.17
|
// beta: v1.17
|
||||||
|
// GA: 1.25
|
||||||
//
|
//
|
||||||
// Enables the GCE PD in-tree driver to GCE CSI Driver migration feature.
|
// Enables the GCE PD in-tree driver to GCE CSI Driver migration feature.
|
||||||
CSIMigrationGCE featuregate.Feature = "CSIMigrationGCE"
|
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)
|
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
|
CSIMigrationOpenStack: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||||
|
|
||||||
|
@ -25,10 +25,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -103,8 +100,6 @@ func TestPodVolumesExist(t *testing.T) {
|
|||||||
t.Skip("skipping test in short mode.")
|
t.Skip("skipping test in short mode.")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||||
defer testKubelet.Cleanup()
|
defer testKubelet.Cleanup()
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
@ -131,8 +126,8 @@ func TestPodVolumesExist(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device1",
|
RBDImage: "fake1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -160,8 +155,8 @@ func TestPodVolumesExist(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol2",
|
Name: "vol2",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device2",
|
RBDImage: "fake2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -189,8 +184,8 @@ func TestPodVolumesExist(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol3",
|
Name: "vol3",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device3",
|
RBDImage: "fake3",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -219,8 +214,6 @@ func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
|
|||||||
t.Skip("skipping test in short mode.")
|
t.Skip("skipping test in short mode.")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||||
defer testKubelet.Cleanup()
|
defer testKubelet.Cleanup()
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
@ -241,8 +234,8 @@ func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device",
|
RBDImage: "fake",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -280,8 +273,6 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
|
|||||||
t.Skip("skipping test in short mode.")
|
t.Skip("skipping test in short mode.")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||||
defer testKubelet.Cleanup()
|
defer testKubelet.Cleanup()
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
@ -302,8 +293,8 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device",
|
RBDImage: "fake-device",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -371,8 +362,6 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
|
|||||||
t.Skip("skipping test in short mode.")
|
t.Skip("skipping test in short mode.")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
|
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
|
||||||
defer testKubelet.Cleanup()
|
defer testKubelet.Cleanup()
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
@ -410,8 +399,8 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device",
|
RBDImage: "fake-device",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -457,8 +446,6 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
|
|||||||
t.Skip("skipping test in short mode.")
|
t.Skip("skipping test in short mode.")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
|
testKubelet := newTestKubelet(t, true /* controllerAttachDetachEnabled */)
|
||||||
defer testKubelet.Cleanup()
|
defer testKubelet.Cleanup()
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
@ -496,8 +483,8 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "vol1",
|
Name: "vol1",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDVolumeSource{
|
||||||
PDName: "fake-device",
|
RBDImage: "fake-device",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -31,13 +31,10 @@ import (
|
|||||||
kubetypes "k8s.io/apimachinery/pkg/types"
|
kubetypes "k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
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/config"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||||
@ -56,8 +53,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
pvMode, podMode v1.PersistentVolumeMode
|
pvMode, podMode v1.PersistentVolumeMode
|
||||||
@ -145,8 +140,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't make a temp dir: %v", err)
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
@ -192,8 +185,6 @@ func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
|
func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, false)()
|
|
||||||
|
|
||||||
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't make a temp dir: %v", err)
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
@ -238,8 +229,8 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
PDName: "fake-device",
|
RBDImage: "fake-device",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ClaimRef: &v1.ObjectReference{
|
ClaimRef: &v1.ObjectReference{
|
||||||
@ -385,8 +376,8 @@ func createObjects(pvMode, podMode v1.PersistentVolumeMode) (*v1.Node, *v1.Pod,
|
|||||||
},
|
},
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
PDName: "fake-device",
|
RBDImage: "fake-device",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ClaimRef: &v1.ObjectReference{
|
ClaimRef: &v1.ObjectReference{
|
||||||
|
@ -33,19 +33,16 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||||
storageinformers "k8s.io/client-go/informers/storage/v1"
|
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
k8stesting "k8s.io/client-go/testing"
|
k8stesting "k8s.io/client-go/testing"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
"k8s.io/component-helpers/storage/volume"
|
"k8s.io/component-helpers/storage/volume"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
pvtesting "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing"
|
pvtesting "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -94,8 +91,9 @@ var (
|
|||||||
pvBoundImmediateNode2 = makeTestPV("pv-bound-immediate", "node2", "1G", "1", immediateBoundPVC, immediateClass)
|
pvBoundImmediateNode2 = makeTestPV("pv-bound-immediate", "node2", "1G", "1", immediateBoundPVC, immediateClass)
|
||||||
|
|
||||||
// PVs for CSI migration
|
// PVs for CSI migration
|
||||||
migrationPVBound = makeTestPVForCSIMigration(zone1Labels, boundMigrationPVC)
|
migrationPVBound = makeTestPVForCSIMigration(zone1Labels, boundMigrationPVC, true)
|
||||||
migrationPVBoundToUnbound = makeTestPVForCSIMigration(zone1Labels, unboundPVC)
|
migrationPVBoundToUnbound = makeTestPVForCSIMigration(zone1Labels, unboundPVC, true)
|
||||||
|
nonmigrationPVBoundToUnbound = makeTestPVForCSIMigration(zone1Labels, unboundPVC, false)
|
||||||
|
|
||||||
// storage class names
|
// storage class names
|
||||||
waitClass = "waitClass"
|
waitClass = "waitClass"
|
||||||
@ -693,17 +691,29 @@ func makeTestPV(name, node, capacity, version string, boundToPVC *v1.PersistentV
|
|||||||
return pv
|
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 := makeTestPV("pv-migration-bound", "node1", "1G", "1", pvc, waitClass)
|
||||||
pv.Spec.NodeAffinity = nil // Will be written by the CSI translation lib
|
pv.Spec.NodeAffinity = nil // Will be written by the CSI translation lib
|
||||||
pv.ObjectMeta.Labels = labels
|
pv.ObjectMeta.Labels = labels
|
||||||
pv.Spec.PersistentVolumeSource = v1.PersistentVolumeSource{
|
// GCEPersistentDisk is used when migration is enabled, as its featuregate is locked to GA.
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
// RBD is used for the nonmigrated case, as its featuregate is still alpha. When RBD migration goes GA,
|
||||||
PDName: "test-disk",
|
// a different nonmigrated plugin should be used instead. If there are no other plugins, then the
|
||||||
FSType: "ext4",
|
// nonmigrated test case is no longer relevant and can be removed.
|
||||||
Partition: 0,
|
if migrationEnabled {
|
||||||
ReadOnly: false,
|
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
|
return pv
|
||||||
}
|
}
|
||||||
@ -1217,8 +1227,6 @@ func TestFindPodVolumesWithCSIMigration(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, true)()
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
testEnv := newTestBinder(t, ctx.Done())
|
testEnv := newTestBinder(t, ctx.Done())
|
||||||
testEnv.initVolumes(scenario.pvs, scenario.pvs)
|
testEnv.initVolumes(scenario.pvs, scenario.pvs)
|
||||||
@ -1775,9 +1783,8 @@ func TestCheckBindingsWithCSIMigration(t *testing.T) {
|
|||||||
apiPVCs []*v1.PersistentVolumeClaim
|
apiPVCs []*v1.PersistentVolumeClaim
|
||||||
|
|
||||||
// Expected return values
|
// Expected return values
|
||||||
shouldFail bool
|
shouldFail bool
|
||||||
expectedBound bool
|
expectedBound bool
|
||||||
migrationEnabled bool
|
|
||||||
}
|
}
|
||||||
scenarios := map[string]scenarioType{
|
scenarios := map[string]scenarioType{
|
||||||
"provisioning-pvc-bound": {
|
"provisioning-pvc-bound": {
|
||||||
@ -1791,50 +1798,45 @@ func TestCheckBindingsWithCSIMigration(t *testing.T) {
|
|||||||
expectedBound: true,
|
expectedBound: true,
|
||||||
},
|
},
|
||||||
"binding-node-pv-same-zone": {
|
"binding-node-pv-same-zone": {
|
||||||
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
||||||
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
||||||
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
||||||
initNodes: []*v1.Node{node1Zone1},
|
initNodes: []*v1.Node{node1Zone1},
|
||||||
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
|
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
|
||||||
migrationEnabled: true,
|
|
||||||
},
|
},
|
||||||
"binding-without-csinode": {
|
"binding-without-csinode": {
|
||||||
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
||||||
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
||||||
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
||||||
initNodes: []*v1.Node{node1Zone1},
|
initNodes: []*v1.Node{node1Zone1},
|
||||||
initCSINodes: []*storagev1.CSINode{},
|
initCSINodes: []*storagev1.CSINode{},
|
||||||
migrationEnabled: true,
|
|
||||||
},
|
},
|
||||||
"binding-non-migrated-plugin": {
|
"binding-non-migrated-plugin": {
|
||||||
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
||||||
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
||||||
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
||||||
initNodes: []*v1.Node{node1Zone1},
|
initNodes: []*v1.Node{node1Zone1},
|
||||||
initCSINodes: []*storagev1.CSINode{csiNode1NotMigrated},
|
initCSINodes: []*storagev1.CSINode{csiNode1NotMigrated},
|
||||||
migrationEnabled: true,
|
|
||||||
},
|
},
|
||||||
"binding-node-pv-in-different-zones": {
|
"binding-node-pv-in-different-zones": {
|
||||||
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
||||||
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
||||||
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
||||||
initNodes: []*v1.Node{node1Zone2},
|
initNodes: []*v1.Node{node1Zone2},
|
||||||
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
|
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
|
||||||
migrationEnabled: true,
|
shouldFail: true,
|
||||||
shouldFail: true,
|
|
||||||
},
|
},
|
||||||
"binding-node-pv-different-zones-migration-off": {
|
"binding-node-pv-different-zones-migration-off": {
|
||||||
bindings: []*BindingInfo{makeBinding(unboundPVC, migrationPVBoundToUnbound)},
|
bindings: []*BindingInfo{makeBinding(unboundPVC, nonmigrationPVBoundToUnbound)},
|
||||||
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
provisionedPVCs: []*v1.PersistentVolumeClaim{},
|
||||||
initPVs: []*v1.PersistentVolume{migrationPVBoundToUnbound},
|
initPVs: []*v1.PersistentVolume{nonmigrationPVBoundToUnbound},
|
||||||
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
initPVCs: []*v1.PersistentVolumeClaim{unboundPVC},
|
||||||
initNodes: []*v1.Node{node1Zone2},
|
initNodes: []*v1.Node{node1Zone2},
|
||||||
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
|
initCSINodes: []*storagev1.CSINode{csiNode1Migrated},
|
||||||
migrationEnabled: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1842,8 +1844,6 @@ func TestCheckBindingsWithCSIMigration(t *testing.T) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigrationGCE, scenario.migrationEnabled)()
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
pod := makePod("test-pod").
|
pod := makePod("test-pod").
|
||||||
withNamespace("testns").
|
withNamespace("testns").
|
||||||
|
@ -39,8 +39,8 @@ func TestIsMigratable(t *testing.T) {
|
|||||||
spec *volume.Spec
|
spec *volume.Spec
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "GCE PD PV source with CSIMigrationGCE enabled",
|
name: "RBD PV source with CSIMigrationGCE enabled",
|
||||||
pluginFeature: features.CSIMigrationGCE,
|
pluginFeature: features.CSIMigrationRBD,
|
||||||
pluginFeatureEnabled: true,
|
pluginFeatureEnabled: true,
|
||||||
isMigratable: true,
|
isMigratable: true,
|
||||||
csiMigrationEnabled: true,
|
csiMigrationEnabled: true,
|
||||||
@ -48,11 +48,8 @@ func TestIsMigratable(t *testing.T) {
|
|||||||
PersistentVolume: &v1.PersistentVolume{
|
PersistentVolume: &v1.PersistentVolume{
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
PDName: "test-disk",
|
RBDImage: "test-disk",
|
||||||
FSType: "ext4",
|
|
||||||
Partition: 0,
|
|
||||||
ReadOnly: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -60,8 +57,8 @@ func TestIsMigratable(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "GCE PD PV Source with CSIMigrationGCE disabled",
|
name: "RBD PD PV Source with CSIMigrationGCE disabled",
|
||||||
pluginFeature: features.CSIMigrationGCE,
|
pluginFeature: features.CSIMigrationRBD,
|
||||||
pluginFeatureEnabled: false,
|
pluginFeatureEnabled: false,
|
||||||
isMigratable: false,
|
isMigratable: false,
|
||||||
csiMigrationEnabled: true,
|
csiMigrationEnabled: true,
|
||||||
@ -69,11 +66,8 @@ func TestIsMigratable(t *testing.T) {
|
|||||||
PersistentVolume: &v1.PersistentVolume{
|
PersistentVolume: &v1.PersistentVolume{
|
||||||
Spec: v1.PersistentVolumeSpec{
|
Spec: v1.PersistentVolumeSpec{
|
||||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
RBD: &v1.RBDPersistentVolumeSource{
|
||||||
PDName: "test-disk",
|
RBDImage: "test-disk",
|
||||||
FSType: "ext4",
|
|
||||||
Partition: 0,
|
|
||||||
ReadOnly: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -186,28 +180,6 @@ func TestMigrationFeatureFlagStatus(t *testing.T) {
|
|||||||
csiMigrationResult bool
|
csiMigrationResult bool
|
||||||
csiMigrationCompleteResult 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",
|
name: "gce-pd migration flag enabled and migration-complete flag disabled with CSI migration flag enabled",
|
||||||
pluginName: "kubernetes.io/gce-pd",
|
pluginName: "kubernetes.io/gce-pd",
|
||||||
@ -257,7 +229,12 @@ func TestMigrationFeatureFlagStatus(t *testing.T) {
|
|||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
pm := NewPluginManager(csiTranslator, utilfeature.DefaultFeatureGate)
|
pm := NewPluginManager(csiTranslator, utilfeature.DefaultFeatureGate)
|
||||||
t.Run(fmt.Sprintf("Testing %v", test.name), func(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, test.inTreePluginUnregister, test.inTreePluginUnregisterEnabled)()
|
||||||
|
|
||||||
csiMigrationResult := pm.IsMigrationEnabledForPlugin(test.pluginName)
|
csiMigrationResult := pm.IsMigrationEnabledForPlugin(test.pluginName)
|
||||||
|
@ -250,9 +250,14 @@ func (plugin *FakeVolumePlugin) GetVolumeName(spec *volume.Spec) (string, error)
|
|||||||
var volumeName string
|
var volumeName string
|
||||||
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
|
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
|
||||||
volumeName = spec.Volume.GCEPersistentDisk.PDName
|
volumeName = spec.Volume.GCEPersistentDisk.PDName
|
||||||
|
} else if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
volumeName = spec.Volume.RBD.RBDImage
|
||||||
} else if spec.PersistentVolume != nil &&
|
} else if spec.PersistentVolume != nil &&
|
||||||
spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
|
spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
|
||||||
volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
|
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 {
|
} else if spec.Volume != nil && spec.Volume.CSI != nil {
|
||||||
volumeName = spec.Volume.CSI.Driver
|
volumeName = spec.Volume.CSI.Driver
|
||||||
}
|
}
|
||||||
@ -671,9 +676,14 @@ func getUniqueVolumeName(spec *volume.Spec) (string, error) {
|
|||||||
var volumeName string
|
var volumeName string
|
||||||
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
|
if spec.Volume != nil && spec.Volume.GCEPersistentDisk != nil {
|
||||||
volumeName = spec.Volume.GCEPersistentDisk.PDName
|
volumeName = spec.Volume.GCEPersistentDisk.PDName
|
||||||
|
} else if spec.Volume != nil && spec.Volume.RBD != nil {
|
||||||
|
volumeName = spec.Volume.RBD.RBDImage
|
||||||
} else if spec.PersistentVolume != nil &&
|
} else if spec.PersistentVolume != nil &&
|
||||||
spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
|
spec.PersistentVolume.Spec.GCEPersistentDisk != nil {
|
||||||
volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
|
volumeName = spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
|
||||||
|
} else if spec.PersistentVolume != nil &&
|
||||||
|
spec.PersistentVolume.Spec.RBD != nil {
|
||||||
|
volumeName = spec.PersistentVolume.Spec.RBD.RBDImage
|
||||||
}
|
}
|
||||||
if volumeName == "" {
|
if volumeName == "" {
|
||||||
volumeName = spec.Name()
|
volumeName = spec.Name()
|
||||||
|
Loading…
Reference in New Issue
Block a user