mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
Do not assume storageclass is still in-tree after csi migration
Signed-off-by: ialidzhikov <i.alidjikov@gmail.com>
This commit is contained in:
parent
e2a7bd5318
commit
3bc560225e
@ -381,7 +381,6 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err
|
|||||||
ctx.ClientBuilder.ClientOrDie("expand-controller"),
|
ctx.ClientBuilder.ClientOrDie("expand-controller"),
|
||||||
ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
|
ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
|
||||||
ctx.InformerFactory.Core().V1().PersistentVolumes(),
|
ctx.InformerFactory.Core().V1().PersistentVolumes(),
|
||||||
ctx.InformerFactory.Storage().V1().StorageClasses(),
|
|
||||||
ctx.Cloud,
|
ctx.Cloud,
|
||||||
plugins,
|
plugins,
|
||||||
csiTranslator,
|
csiTranslator,
|
||||||
|
@ -7,7 +7,6 @@ go_library(
|
|||||||
srcs = ["expand_controller.go"],
|
srcs = ["expand_controller.go"],
|
||||||
importpath = "k8s.io/kubernetes/pkg/controller/volume/expand",
|
importpath = "k8s.io/kubernetes/pkg/controller/volume/expand",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/core/v1/helper:go_default_library",
|
|
||||||
"//pkg/controller/volume/events:go_default_library",
|
"//pkg/controller/volume/events:go_default_library",
|
||||||
"//pkg/proxy/util:go_default_library",
|
"//pkg/proxy/util:go_default_library",
|
||||||
"//pkg/volume:go_default_library",
|
"//pkg/volume:go_default_library",
|
||||||
@ -24,12 +23,10 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library",
|
|
||||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/listers/storage/v1:go_default_library",
|
|
||||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||||
@ -67,7 +64,6 @@ go_test(
|
|||||||
"//pkg/volume/util/operationexecutor:go_default_library",
|
"//pkg/volume/util/operationexecutor:go_default_library",
|
||||||
"//pkg/volume/util/types:go_default_library",
|
"//pkg/volume/util/types:go_default_library",
|
||||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
@ -34,18 +34,15 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||||
storageclassinformer "k8s.io/client-go/informers/storage/v1"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
corelisters "k8s.io/client-go/listers/core/v1"
|
corelisters "k8s.io/client-go/listers/core/v1"
|
||||||
storagelisters "k8s.io/client-go/listers/storage/v1"
|
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
kcache "k8s.io/client-go/tools/cache"
|
kcache "k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
|
||||||
"k8s.io/kubernetes/pkg/controller/volume/events"
|
"k8s.io/kubernetes/pkg/controller/volume/events"
|
||||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
@ -85,10 +82,6 @@ type expandController struct {
|
|||||||
pvLister corelisters.PersistentVolumeLister
|
pvLister corelisters.PersistentVolumeLister
|
||||||
pvSynced kcache.InformerSynced
|
pvSynced kcache.InformerSynced
|
||||||
|
|
||||||
// storageClass lister for fetching provisioner name
|
|
||||||
classLister storagelisters.StorageClassLister
|
|
||||||
classListerSynced cache.InformerSynced
|
|
||||||
|
|
||||||
// cloud provider used by volume host
|
// cloud provider used by volume host
|
||||||
cloud cloudprovider.Interface
|
cloud cloudprovider.Interface
|
||||||
|
|
||||||
@ -114,7 +107,6 @@ func NewExpandController(
|
|||||||
kubeClient clientset.Interface,
|
kubeClient clientset.Interface,
|
||||||
pvcInformer coreinformers.PersistentVolumeClaimInformer,
|
pvcInformer coreinformers.PersistentVolumeClaimInformer,
|
||||||
pvInformer coreinformers.PersistentVolumeInformer,
|
pvInformer coreinformers.PersistentVolumeInformer,
|
||||||
scInformer storageclassinformer.StorageClassInformer,
|
|
||||||
cloud cloudprovider.Interface,
|
cloud cloudprovider.Interface,
|
||||||
plugins []volume.VolumePlugin,
|
plugins []volume.VolumePlugin,
|
||||||
translator CSINameTranslator,
|
translator CSINameTranslator,
|
||||||
@ -128,8 +120,6 @@ func NewExpandController(
|
|||||||
pvcsSynced: pvcInformer.Informer().HasSynced,
|
pvcsSynced: pvcInformer.Informer().HasSynced,
|
||||||
pvLister: pvInformer.Lister(),
|
pvLister: pvInformer.Lister(),
|
||||||
pvSynced: pvInformer.Informer().HasSynced,
|
pvSynced: pvInformer.Informer().HasSynced,
|
||||||
classLister: scInformer.Lister(),
|
|
||||||
classListerSynced: scInformer.Informer().HasSynced,
|
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"),
|
||||||
translator: translator,
|
translator: translator,
|
||||||
csiMigratedPluginManager: csiMigratedPluginManager,
|
csiMigratedPluginManager: csiMigratedPluginManager,
|
||||||
@ -243,19 +233,6 @@ func (expc *expandController) syncHandler(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
claimClass := v1helper.GetPersistentVolumeClaimClass(pvc)
|
|
||||||
if claimClass == "" {
|
|
||||||
klog.V(4).Infof("volume expansion is disabled for PVC without StorageClasses: %s", util.ClaimToClaimKey(pvc))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
class, err := expc.classLister.Get(claimClass)
|
|
||||||
if err != nil {
|
|
||||||
klog.V(4).Infof("failed to expand PVC: %s with error: %v", util.ClaimToClaimKey(pvc), err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
volumeResizerName := class.Provisioner
|
|
||||||
volumeSpec := volume.NewSpecFromPersistentVolume(pv, false)
|
volumeSpec := volume.NewSpecFromPersistentVolume(pv, false)
|
||||||
migratable, err := expc.csiMigratedPluginManager.IsMigratable(volumeSpec)
|
migratable, err := expc.csiMigratedPluginManager.IsMigratable(volumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -264,9 +241,15 @@ func (expc *expandController) syncHandler(key string) error {
|
|||||||
}
|
}
|
||||||
// handle CSI migration scenarios before invoking FindExpandablePluginBySpec for in-tree
|
// handle CSI migration scenarios before invoking FindExpandablePluginBySpec for in-tree
|
||||||
if migratable {
|
if migratable {
|
||||||
msg := fmt.Sprintf("CSI migration enabled for %s; waiting for external resizer to expand the pvc", volumeResizerName)
|
inTreePluginName, err := expc.csiMigratedPluginManager.GetInTreePluginNameFromSpec(volumeSpec.PersistentVolume, volumeSpec.Volume)
|
||||||
|
if err != nil {
|
||||||
|
klog.V(4).Infof("Error getting in-tree plugin name from persistent volume %s: %v", volumeSpec.PersistentVolume.Name, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("CSI migration enabled for %s; waiting for external resizer to expand the pvc", inTreePluginName)
|
||||||
expc.recorder.Event(pvc, v1.EventTypeNormal, events.ExternalExpanding, msg)
|
expc.recorder.Event(pvc, v1.EventTypeNormal, events.ExternalExpanding, msg)
|
||||||
csiResizerName, err := expc.translator.GetCSINameFromInTreeName(class.Provisioner)
|
csiResizerName, err := expc.translator.GetCSINameFromInTreeName(inTreePluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorMsg := fmt.Sprintf("error getting CSI driver name for pvc %s, with error %v", util.ClaimToClaimKey(pvc), err)
|
errorMsg := fmt.Sprintf("error getting CSI driver name for pvc %s, with error %v", util.ClaimToClaimKey(pvc), err)
|
||||||
expc.recorder.Event(pvc, v1.EventTypeWarning, events.ExternalExpanding, errorMsg)
|
expc.recorder.Event(pvc, v1.EventTypeWarning, events.ExternalExpanding, errorMsg)
|
||||||
@ -297,6 +280,7 @@ func (expc *expandController) syncHandler(key string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volumeResizerName := volumePlugin.GetPluginName()
|
||||||
return expc.expand(pvc, pv, volumeResizerName)
|
return expc.expand(pvc, pv, volumeResizerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +310,7 @@ func (expc *expandController) Run(stopCh <-chan struct{}) {
|
|||||||
klog.Infof("Starting expand controller")
|
klog.Infof("Starting expand controller")
|
||||||
defer klog.Infof("Shutting down expand controller")
|
defer klog.Infof("Shutting down expand controller")
|
||||||
|
|
||||||
if !cache.WaitForNamedCacheSync("expand", stopCh, expc.pvcsSynced, expc.pvSynced, expc.classListerSynced) {
|
if !cache.WaitForNamedCacheSync("expand", stopCh, expc.pvcsSynced, expc.pvSynced) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
storagev1 "k8s.io/api/storage/v1"
|
|
||||||
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"
|
||||||
@ -49,7 +48,6 @@ func TestSyncHandler(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
csiMigrationEnabled bool
|
csiMigrationEnabled bool
|
||||||
storageClass *storagev1.StorageClass
|
|
||||||
pvcKey string
|
pvcKey string
|
||||||
pv *v1.PersistentVolume
|
pv *v1.PersistentVolume
|
||||||
pvc *v1.PersistentVolumeClaim
|
pvc *v1.PersistentVolumeClaim
|
||||||
@ -59,27 +57,14 @@ func TestSyncHandler(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "when pvc has no PV binding",
|
name: "when pvc has no PV binding",
|
||||||
pvc: getFakePersistentVolumeClaim("no-pv-pvc", "", "", ""),
|
pvc: getFakePersistentVolumeClaim("no-pv-pvc", "", ""),
|
||||||
pvcKey: "default/no-pv-pvc",
|
pvcKey: "default/no-pv-pvc",
|
||||||
hasError: true,
|
hasError: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "when pvc has no storageclass",
|
|
||||||
pv: getFakePersistentVolume("vol-1", csitranslationplugins.AWSEBSInTreePluginName, "no-sc-pvc-vol-1"),
|
|
||||||
pvc: getFakePersistentVolumeClaim("no-sc-pvc", "vol-1", "", "no-sc-pvc-vol-1"),
|
|
||||||
pvcKey: "default/no-sc-pvc",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "when pvc storageclass is missing",
|
|
||||||
pv: getFakePersistentVolume("vol-2", csitranslationplugins.AWSEBSInTreePluginName, "missing-sc-pvc-vol-2"),
|
|
||||||
pvc: getFakePersistentVolumeClaim("missing-sc-pvc", "vol-2", "resizable", "missing-sc-pvc-vol-2"),
|
|
||||||
pvcKey: "default/missing-sc-pvc",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "when pvc and pv has everything for in-tree plugin",
|
name: "when pvc and pv has everything for in-tree plugin",
|
||||||
pv: getFakePersistentVolume("vol-3", csitranslationplugins.AWSEBSInTreePluginName, "good-pvc-vol-3"),
|
pv: getFakePersistentVolume("vol-3", csitranslationplugins.AWSEBSInTreePluginName, "good-pvc-vol-3"),
|
||||||
pvc: getFakePersistentVolumeClaim("good-pvc", "vol-3", "resizable2", "good-pvc-vol-3"),
|
pvc: getFakePersistentVolumeClaim("good-pvc", "vol-3", "good-pvc-vol-3"),
|
||||||
storageClass: getFakeStorageClass("resizable2", csitranslationplugins.AWSEBSInTreePluginName),
|
|
||||||
pvcKey: "default/good-pvc",
|
pvcKey: "default/good-pvc",
|
||||||
expansionCalled: true,
|
expansionCalled: true,
|
||||||
expectedAnnotation: map[string]string{volumetypes.VolumeResizerKey: csitranslationplugins.AWSEBSInTreePluginName},
|
expectedAnnotation: map[string]string{volumetypes.VolumeResizerKey: csitranslationplugins.AWSEBSInTreePluginName},
|
||||||
@ -88,16 +73,14 @@ func TestSyncHandler(t *testing.T) {
|
|||||||
name: "when csi migration is enabled for a in-tree plugin",
|
name: "when csi migration is enabled for a in-tree plugin",
|
||||||
csiMigrationEnabled: true,
|
csiMigrationEnabled: true,
|
||||||
pv: getFakePersistentVolume("vol-4", csitranslationplugins.AWSEBSInTreePluginName, "csi-pvc-vol-4"),
|
pv: getFakePersistentVolume("vol-4", csitranslationplugins.AWSEBSInTreePluginName, "csi-pvc-vol-4"),
|
||||||
pvc: getFakePersistentVolumeClaim("csi-pvc", "vol-4", "resizable3", "csi-pvc-vol-4"),
|
pvc: getFakePersistentVolumeClaim("csi-pvc", "vol-4", "csi-pvc-vol-4"),
|
||||||
storageClass: getFakeStorageClass("resizable3", csitranslationplugins.AWSEBSInTreePluginName),
|
|
||||||
pvcKey: "default/csi-pvc",
|
pvcKey: "default/csi-pvc",
|
||||||
expectedAnnotation: map[string]string{volumetypes.VolumeResizerKey: csitranslationplugins.AWSEBSDriverName},
|
expectedAnnotation: map[string]string{volumetypes.VolumeResizerKey: csitranslationplugins.AWSEBSDriverName},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "for csi plugin without migration path",
|
name: "for csi plugin without migration path",
|
||||||
pv: getFakePersistentVolume("vol-5", "com.csi.ceph", "ceph-csi-pvc-vol-5"),
|
pv: getFakePersistentVolume("vol-5", "com.csi.ceph", "ceph-csi-pvc-vol-5"),
|
||||||
pvc: getFakePersistentVolumeClaim("ceph-csi-pvc", "vol-5", "resizable4", "ceph-csi-pvc-vol-5"),
|
pvc: getFakePersistentVolumeClaim("ceph-csi-pvc", "vol-5", "ceph-csi-pvc-vol-5"),
|
||||||
storageClass: getFakeStorageClass("resizable4", "com.csi.ceph"),
|
|
||||||
pvcKey: "default/ceph-csi-pvc",
|
pvcKey: "default/ceph-csi-pvc",
|
||||||
expansionCalled: false,
|
expansionCalled: false,
|
||||||
hasError: false,
|
hasError: false,
|
||||||
@ -110,7 +93,6 @@ func TestSyncHandler(t *testing.T) {
|
|||||||
informerFactory := informers.NewSharedInformerFactory(fakeKubeClient, controller.NoResyncPeriodFunc())
|
informerFactory := informers.NewSharedInformerFactory(fakeKubeClient, controller.NoResyncPeriodFunc())
|
||||||
pvcInformer := informerFactory.Core().V1().PersistentVolumeClaims()
|
pvcInformer := informerFactory.Core().V1().PersistentVolumeClaims()
|
||||||
pvInformer := informerFactory.Core().V1().PersistentVolumes()
|
pvInformer := informerFactory.Core().V1().PersistentVolumes()
|
||||||
storageClassInformer := informerFactory.Storage().V1().StorageClasses()
|
|
||||||
|
|
||||||
pvc := test.pvc
|
pvc := test.pvc
|
||||||
if tc.pv != nil {
|
if tc.pv != nil {
|
||||||
@ -122,11 +104,8 @@ func TestSyncHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
allPlugins := []volume.VolumePlugin{}
|
allPlugins := []volume.VolumePlugin{}
|
||||||
allPlugins = append(allPlugins, awsebs.ProbeVolumePlugins()...)
|
allPlugins = append(allPlugins, awsebs.ProbeVolumePlugins()...)
|
||||||
if tc.storageClass != nil {
|
|
||||||
informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass)
|
|
||||||
}
|
|
||||||
translator := csitrans.New()
|
translator := csitrans.New()
|
||||||
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, translator, csimigration.NewPluginManager(translator), nil)
|
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, nil, allPlugins, translator, csimigration.NewPluginManager(translator), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating expand controller : %v", err)
|
t.Fatalf("error creating expand controller : %v", err)
|
||||||
}
|
}
|
||||||
@ -226,7 +205,7 @@ func getFakePersistentVolume(volumeName, pluginName string, pvcUID types.UID) *v
|
|||||||
return pv
|
return pv
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFakePersistentVolumeClaim(pvcName, volumeName, scName string, uid types.UID) *v1.PersistentVolumeClaim {
|
func getFakePersistentVolumeClaim(pvcName, volumeName string, uid types.UID) *v1.PersistentVolumeClaim {
|
||||||
pvc := &v1.PersistentVolumeClaim{
|
pvc := &v1.PersistentVolumeClaim{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: pvcName, Namespace: "default", UID: uid},
|
ObjectMeta: metav1.ObjectMeta{Name: pvcName, Namespace: "default", UID: uid},
|
||||||
Spec: v1.PersistentVolumeClaimSpec{},
|
Spec: v1.PersistentVolumeClaimSpec{},
|
||||||
@ -235,15 +214,5 @@ func getFakePersistentVolumeClaim(pvcName, volumeName, scName string, uid types.
|
|||||||
pvc.Spec.VolumeName = volumeName
|
pvc.Spec.VolumeName = volumeName
|
||||||
}
|
}
|
||||||
|
|
||||||
if scName != "" {
|
|
||||||
pvc.Spec.StorageClassName = &scName
|
|
||||||
}
|
|
||||||
return pvc
|
return pvc
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFakeStorageClass(scName, pluginName string) *storagev1.StorageClass {
|
|
||||||
return &storagev1.StorageClass{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: scName},
|
|
||||||
Provisioner: pluginName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user