diff --git a/cmd/kube-controller-manager/app/BUILD b/cmd/kube-controller-manager/app/BUILD index b21230fb345..8ee0819ce86 100644 --- a/cmd/kube-controller-manager/app/BUILD +++ b/cmd/kube-controller-manager/app/BUILD @@ -141,6 +141,7 @@ go_library( "//staging/src/k8s.io/component-base/cli/globalflag:go_default_library", "//staging/src/k8s.io/component-base/version:go_default_library", "//staging/src/k8s.io/component-base/version/verflag:go_default_library", + "//staging/src/k8s.io/csi-translation-lib:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library", diff --git a/cmd/kube-controller-manager/app/core.go b/cmd/kube-controller-manager/app/core.go index 2a5d7ec64c5..a172716f74a 100644 --- a/cmd/kube-controller-manager/app/core.go +++ b/cmd/kube-controller-manager/app/core.go @@ -36,6 +36,7 @@ import ( clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/metadata" restclient "k8s.io/client-go/rest" + csitrans "k8s.io/csi-translation-lib" "k8s.io/kubernetes/pkg/controller" cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud" endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint" @@ -309,7 +310,8 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err ctx.InformerFactory.Core().V1().PersistentVolumes(), ctx.InformerFactory.Storage().V1().StorageClasses(), ctx.Cloud, - ProbeExpandableVolumePlugins(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration)) + ProbeExpandableVolumePlugins(ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration), + csitrans.New()) if expandControllerErr != nil { return nil, true, fmt.Errorf("failed to start volume expand controller : %v", expandControllerErr) diff --git a/pkg/controller/volume/expand/BUILD b/pkg/controller/volume/expand/BUILD index 11c7d30c94d..d814ed0108e 100644 --- a/pkg/controller/volume/expand/BUILD +++ b/pkg/controller/volume/expand/BUILD @@ -32,7 +32,6 @@ go_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/cloud-provider:go_default_library", - "//staging/src/k8s.io/csi-translation-lib:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) @@ -75,6 +74,7 @@ go_test( "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", + "//staging/src/k8s.io/csi-translation-lib:go_default_library", "//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library", ], ) diff --git a/pkg/controller/volume/expand/expand_controller.go b/pkg/controller/volume/expand/expand_controller.go index 2a1f04a3769..c21f55fc0b9 100644 --- a/pkg/controller/volume/expand/expand_controller.go +++ b/pkg/controller/volume/expand/expand_controller.go @@ -41,7 +41,6 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" cloudprovider "k8s.io/cloud-provider" - csitranslation "k8s.io/csi-translation-lib" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/controller/volume/events" "k8s.io/kubernetes/pkg/util/mount" @@ -62,6 +61,11 @@ type ExpandController interface { Run(stopCh <-chan struct{}) } +// CSINameTranslator can get the CSI Driver name based on the in-tree plugin name +type CSINameTranslator interface { + GetCSINameFromInTreeName(pluginName string) (string, error) +} + type expandController struct { // kubeClient is the kube API client used by volumehost to communicate with // the API server. @@ -92,6 +96,8 @@ type expandController struct { operationGenerator operationexecutor.OperationGenerator queue workqueue.RateLimitingInterface + + translator CSINameTranslator } // NewExpandController expands the pvs @@ -101,7 +107,8 @@ func NewExpandController( pvInformer coreinformers.PersistentVolumeInformer, scInformer storageclassinformer.StorageClassInformer, cloud cloudprovider.Interface, - plugins []volume.VolumePlugin) (ExpandController, error) { + plugins []volume.VolumePlugin, + translator CSINameTranslator) (ExpandController, error) { expc := &expandController{ kubeClient: kubeClient, @@ -113,6 +120,7 @@ func NewExpandController( classLister: scInformer.Lister(), classListerSynced: scInformer.Informer().HasSynced, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"), + translator: translator, } if err := expc.volumePluginMgr.InitPlugins(plugins, nil, expc); err != nil { @@ -255,7 +263,7 @@ func (expc *expandController) syncHandler(key string) error { if volumePlugin.IsMigratedToCSI() { msg := fmt.Sprintf("CSI migration enabled for %s; waiting for external resizer to expand the pvc", volumeResizerName) expc.recorder.Event(pvc, v1.EventTypeNormal, events.ExternalExpanding, msg) - csiResizerName, err := csitranslation.GetCSINameFromInTreeName(class.Provisioner) + csiResizerName, err := expc.translator.GetCSINameFromInTreeName(class.Provisioner) if err != nil { 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) diff --git a/pkg/controller/volume/expand/expand_controller_test.go b/pkg/controller/volume/expand/expand_controller_test.go index 5226e94e897..4eb44d753eb 100644 --- a/pkg/controller/volume/expand/expand_controller_test.go +++ b/pkg/controller/volume/expand/expand_controller_test.go @@ -33,6 +33,7 @@ import ( "k8s.io/client-go/informers" coretesting "k8s.io/client-go/testing" featuregatetesting "k8s.io/component-base/featuregate/testing" + csitrans "k8s.io/csi-translation-lib" csitranslationplugins "k8s.io/csi-translation-lib/plugins" "k8s.io/kubernetes/pkg/controller" controllervolumetesting "k8s.io/kubernetes/pkg/controller/volume/attachdetach/testing" @@ -123,7 +124,7 @@ func TestSyncHandler(t *testing.T) { if tc.storageClass != nil { informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass) } - expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins) + expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, csitrans.New()) if err != nil { t.Fatalf("error creating expand controller : %v", err) } diff --git a/pkg/controller/volume/persistentvolume/BUILD b/pkg/controller/volume/persistentvolume/BUILD index c0f10a34e48..310af33dfed 100644 --- a/pkg/controller/volume/persistentvolume/BUILD +++ b/pkg/controller/volume/persistentvolume/BUILD @@ -101,6 +101,7 @@ go_test( "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/reference:go_default_library", "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", + "//staging/src/k8s.io/csi-translation-lib:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/pkg/controller/volume/persistentvolume/framework_test.go b/pkg/controller/volume/persistentvolume/framework_test.go index d578da7fbaf..860f4b3e7c5 100644 --- a/pkg/controller/volume/persistentvolume/framework_test.go +++ b/pkg/controller/volume/persistentvolume/framework_test.go @@ -521,6 +521,12 @@ func wrapTestWithProvisionCalls(expectedProvisionCalls []provisionCall, toWrap t return wrapTestWithPluginCalls(nil, nil, expectedProvisionCalls, toWrap) } +type fakeCSINameTranslator struct{} + +func (t fakeCSINameTranslator) GetCSINameFromInTreeName(pluginName string) (string, error) { + return "vendor.com/MockCSIPlugin", nil +} + // wrapTestWithCSIMigrationProvisionCalls returns a testCall that: // - configures controller with a volume plugin that emulates CSI migration // - calls given testCall @@ -530,9 +536,7 @@ func wrapTestWithCSIMigrationProvisionCalls(toWrap testCall) testCall { isMigratedToCSI: true, } ctrl.volumePluginMgr.InitPlugins([]vol.VolumePlugin{plugin}, nil /* prober */, ctrl) - ctrl.csiNameFromIntreeNameHook = func(string) (string, error) { - return "vendor.com/MockCSIPlugin", nil - } + ctrl.translator = fakeCSINameTranslator{} return toWrap(ctrl, reactor, test) } } diff --git a/pkg/controller/volume/persistentvolume/pv_controller.go b/pkg/controller/volume/persistentvolume/pv_controller.go index 56f2cba5a6a..a6012339fbd 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller.go +++ b/pkg/controller/volume/persistentvolume/pv_controller.go @@ -39,7 +39,6 @@ import ( "k8s.io/client-go/util/workqueue" cloudprovider "k8s.io/cloud-provider" volerr "k8s.io/cloud-provider/volume/errors" - csitranslation "k8s.io/csi-translation-lib" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/controller/volume/events" "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics" @@ -134,6 +133,11 @@ const createProvisionedPVRetryCount = 5 // Interval between retries when we create a PV object for a provisioned volume. const createProvisionedPVInterval = 10 * time.Second +// CSINameTranslator can get the CSI Driver name based on the in-tree plugin name +type CSINameTranslator interface { + GetCSINameFromInTreeName(pluginName string) (string, error) +} + // PersistentVolumeController is a controller that synchronizes // PersistentVolumeClaims and PersistentVolumes. It starts two // cache.Controllers that watch PersistentVolume and PersistentVolumeClaim @@ -200,10 +204,6 @@ type PersistentVolumeController struct { createProvisionedPVRetryCount int createProvisionedPVInterval time.Duration - // For testing only: hook to intercept CSI driver name <=> Intree plugin name mapping - // Not used when set to nil - csiNameFromIntreeNameHook func(pluginName string) (string, error) - // operationTimestamps caches start timestamp of operations // (currently provision + binding/deletion) for metric recording. // Detailed lifecyle/key for each operation @@ -225,6 +225,8 @@ type PersistentVolumeController struct { // the corresponding timestamp entry will be deleted from cache // abort: N.A. operationTimestamps metrics.OperationStartTimeCache + + translator CSINameTranslator } // syncClaim is the main controller method to decide what to do with a claim. @@ -1355,13 +1357,6 @@ func (ctrl *PersistentVolumeController) provisionClaim(claim *v1.PersistentVolum return nil } -func (ctrl *PersistentVolumeController) getCSINameFromIntreeName(pluginName string) (string, error) { - if ctrl.csiNameFromIntreeNameHook != nil { - return ctrl.csiNameFromIntreeNameHook(pluginName) - } - return csitranslation.GetCSINameFromInTreeName(pluginName) -} - // provisionClaimOperation provisions a volume. This method is running in // standalone goroutine and already has all necessary locks. func (ctrl *PersistentVolumeController) provisionClaimOperation( @@ -1571,7 +1566,7 @@ func (ctrl *PersistentVolumeController) provisionClaimOperationExternal( provisionerName := storageClass.Provisioner if plugin != nil { // update the provisioner name to use the CSI in-tree name - provisionerName, err = ctrl.getCSINameFromIntreeName(storageClass.Provisioner) + provisionerName, err = ctrl.translator.GetCSINameFromInTreeName(storageClass.Provisioner) if err != nil { strerr := fmt.Sprintf("error getting CSI name for In tree plugin %s: %v", storageClass.Provisioner, err) klog.V(2).Infof("%s", strerr) @@ -1732,7 +1727,7 @@ func (ctrl *PersistentVolumeController) getProvisionerNameFromVolume(volume *v1. return "N/A" } if plugin != nil { - provisionerName, err := ctrl.getCSINameFromIntreeName(class.Provisioner) + provisionerName, err := ctrl.translator.GetCSINameFromInTreeName(class.Provisioner) if err == nil { return provisionerName } @@ -1747,7 +1742,7 @@ func (ctrl *PersistentVolumeController) getProvisionerName(plugin vol.Provisiona return plugin.GetPluginName() } else if plugin != nil { // get the CSI in-tree name from storage class provisioner name - provisionerName, err := ctrl.getCSINameFromIntreeName(storageClass.Provisioner) + provisionerName, err := ctrl.translator.GetCSINameFromInTreeName(storageClass.Provisioner) if err != nil { return "N/A" } diff --git a/pkg/controller/volume/persistentvolume/pv_controller_base.go b/pkg/controller/volume/persistentvolume/pv_controller_base.go index bb7aa88b8ae..d3965c1bffd 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller_base.go +++ b/pkg/controller/volume/persistentvolume/pv_controller_base.go @@ -38,6 +38,7 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" cloudprovider "k8s.io/cloud-provider" + csitrans "k8s.io/csi-translation-lib" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics" pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util" @@ -93,6 +94,7 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error) volumeQueue: workqueue.NewNamed("volumes"), resyncPeriod: p.SyncPeriod, operationTimestamps: metrics.NewOperationStartTimeCache(), + translator: csitrans.New(), } // Prober is nil because PV is not aware of Flexvolume. diff --git a/pkg/controller/volume/persistentvolume/pv_controller_test.go b/pkg/controller/volume/persistentvolume/pv_controller_test.go index 3fee6f6aafc..ba4da77e501 100644 --- a/pkg/controller/volume/persistentvolume/pv_controller_test.go +++ b/pkg/controller/volume/persistentvolume/pv_controller_test.go @@ -30,6 +30,7 @@ import ( storagelisters "k8s.io/client-go/listers/storage/v1" core "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" + csitrans "k8s.io/csi-translation-lib" "k8s.io/klog" "k8s.io/kubernetes/pkg/controller" pvtesting "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing" @@ -438,6 +439,7 @@ func TestDelayBindingMode(t *testing.T) { classInformer := informerFactory.Storage().V1().StorageClasses() ctrl := &PersistentVolumeController{ classLister: classInformer.Lister(), + translator: csitrans.New(), } for _, class := range classes { diff --git a/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go b/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go index ad86873897b..66dd49e7fd1 100644 --- a/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go +++ b/pkg/scheduler/algorithm/predicates/csi_volume_predicate.go @@ -23,7 +23,7 @@ import ( storagev1beta1 "k8s.io/api/storage/v1beta1" "k8s.io/apimachinery/pkg/util/rand" utilfeature "k8s.io/apiserver/pkg/util/feature" - csilib "k8s.io/csi-translation-lib" + csitrans "k8s.io/csi-translation-lib" "k8s.io/klog" v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/features" @@ -31,6 +31,16 @@ import ( volumeutil "k8s.io/kubernetes/pkg/volume/util" ) +// InTreeToCSITranslator contains methods required to check migratable status +// and perform translations from InTree PV's to CSI +type InTreeToCSITranslator interface { + IsPVMigratable(pv *v1.PersistentVolume) bool + IsMigratableIntreePluginByName(inTreePluginName string) bool + GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) + GetCSINameFromInTreeName(pluginName string) (string, error) + TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) +} + // CSIMaxVolumeLimitChecker defines predicate needed for counting CSI volumes type CSIMaxVolumeLimitChecker struct { csiNodeInfo CSINodeInfo @@ -39,6 +49,8 @@ type CSIMaxVolumeLimitChecker struct { scInfo StorageClassInfo randomVolumeIDPrefix string + + translator InTreeToCSITranslator } // NewCSIMaxVolumeLimitPredicate returns a predicate for counting CSI volumes @@ -50,6 +62,7 @@ func NewCSIMaxVolumeLimitPredicate( pvcInfo: pvcInfo, scInfo: scInfo, randomVolumeIDPrefix: rand.String(32), + translator: csitrans.New(), } return c.attachableLimitPredicate } @@ -201,11 +214,11 @@ func (c *CSIMaxVolumeLimitChecker) getCSIDriverInfo(csiNode *storagev1beta1.CSIN csiSource := pv.Spec.PersistentVolumeSource.CSI if csiSource == nil { // We make a fast path for non-CSI volumes that aren't migratable - if !csilib.IsPVMigratable(pv) { + if !c.translator.IsPVMigratable(pv) { return "", "" } - pluginName, err := csilib.GetInTreePluginNameFromSpec(pv, nil) + pluginName, err := c.translator.GetInTreePluginNameFromSpec(pv, nil) if err != nil { klog.V(5).Infof("Unable to look up plugin name from PV spec: %v", err) return "", "" @@ -216,7 +229,7 @@ func (c *CSIMaxVolumeLimitChecker) getCSIDriverInfo(csiNode *storagev1beta1.CSIN return "", "" } - csiPV, err := csilib.TranslateInTreePVToCSI(pv) + csiPV, err := c.translator.TranslateInTreePVToCSI(pv) if err != nil { klog.V(5).Infof("Unable to translate in-tree volume to CSI: %v", err) return "", "" @@ -258,13 +271,13 @@ func (c *CSIMaxVolumeLimitChecker) getCSIDriverInfoFromSC(csiNode *storagev1beta volumeHandle := fmt.Sprintf("%s-%s/%s", c.randomVolumeIDPrefix, namespace, pvcName) provisioner := storageClass.Provisioner - if csilib.IsMigratableIntreePluginByName(provisioner) { + if c.translator.IsMigratableIntreePluginByName(provisioner) { if !isCSIMigrationOn(csiNode, provisioner) { klog.V(5).Infof("CSI Migration of plugin %s is not enabled", provisioner) return "", "" } - driverName, err := csilib.GetCSINameFromInTreeName(provisioner) + driverName, err := c.translator.GetCSINameFromInTreeName(provisioner) if err != nil { klog.V(5).Infof("Unable to look up driver name from plugin name: %v", err) return "", "" diff --git a/pkg/volume/util/operationexecutor/BUILD b/pkg/volume/util/operationexecutor/BUILD index 6204312d371..b0ccffe22f7 100644 --- a/pkg/volume/util/operationexecutor/BUILD +++ b/pkg/volume/util/operationexecutor/BUILD @@ -67,6 +67,7 @@ go_test( "//staging/src/k8s.io/component-base/featuregate:go_default_library", "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", "//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library", + "//staging/src/k8s.io/csi-translation-lib:go_default_library", "//staging/src/k8s.io/csi-translation-lib/plugins:go_default_library", "//vendor/github.com/prometheus/client_model/go:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/pkg/volume/util/operationexecutor/fakegenerator.go b/pkg/volume/util/operationexecutor/fakegenerator.go index 69c1ab693cc..38d75763cd4 100644 --- a/pkg/volume/util/operationexecutor/fakegenerator.go +++ b/pkg/volume/util/operationexecutor/fakegenerator.go @@ -21,6 +21,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + csitrans "k8s.io/csi-translation-lib" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util/hostutil" volumetypes "k8s.io/kubernetes/pkg/volume/util/types" @@ -88,6 +89,10 @@ func (f *fakeOGCounter) GetVolumePluginMgr() *volume.VolumePluginMgr { return nil } +func (f *fakeOGCounter) GetCSITranslator() InTreeToCSITranslator { + return csitrans.New() +} + func (f *fakeOGCounter) GenerateBulkVolumeVerifyFunc( map[types.NodeName][]*volume.Spec, string, diff --git a/pkg/volume/util/operationexecutor/operation_executor.go b/pkg/volume/util/operationexecutor/operation_executor.go index 434c14a8eea..fbad284378b 100644 --- a/pkg/volume/util/operationexecutor/operation_executor.go +++ b/pkg/volume/util/operationexecutor/operation_executor.go @@ -641,14 +641,14 @@ func (oe *operationExecutor) VerifyVolumesAreAttached( } // Migration: Must also check the Node since Attach would have been done with in-tree if node is not using Migration - nu, err := nodeUsingCSIPlugin(oe.operationGenerator, volumeAttached.VolumeSpec, node) + nu, err := nodeUsingCSIPlugin(oe.operationGenerator.GetCSITranslator(), oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec, node) if err != nil { klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error()) continue } var volumePlugin volume.VolumePlugin - if useCSIPlugin(oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec) && nu { + if useCSIPlugin(oe.operationGenerator.GetCSITranslator(), oe.operationGenerator.GetVolumePluginMgr(), volumeAttached.VolumeSpec) && nu { // The volume represented by this spec is CSI and thus should be migrated volumePlugin, err = oe.operationGenerator.GetVolumePluginMgr().FindPluginByName(csi.CSIPluginName) if err != nil || volumePlugin == nil { @@ -661,7 +661,7 @@ func (oe *operationExecutor) VerifyVolumesAreAttached( continue } - csiSpec, err := translateSpec(volumeAttached.VolumeSpec) + csiSpec, err := translateSpec(oe.operationGenerator.GetCSITranslator(), volumeAttached.VolumeSpec) if err != nil { klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error()) continue diff --git a/pkg/volume/util/operationexecutor/operation_executor_test.go b/pkg/volume/util/operationexecutor/operation_executor_test.go index 326f86c99d4..adc199a004f 100644 --- a/pkg/volume/util/operationexecutor/operation_executor_test.go +++ b/pkg/volume/util/operationexecutor/operation_executor_test.go @@ -25,6 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/uuid" + csitrans "k8s.io/csi-translation-lib" "k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume/util/hostutil" volumetypes "k8s.io/kubernetes/pkg/volume/util/types" @@ -520,6 +521,10 @@ func (fopg *fakeOperationGenerator) GetVolumePluginMgr() *volume.VolumePluginMgr return nil } +func (fopg *fakeOperationGenerator) GetCSITranslator() InTreeToCSITranslator { + return csitrans.New() +} + func getTestPodWithSecret(podName, secretName string) *v1.Pod { return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/volume/util/operationexecutor/operation_generator.go b/pkg/volume/util/operationexecutor/operation_generator.go index 82d8e133170..183991784bf 100644 --- a/pkg/volume/util/operationexecutor/operation_generator.go +++ b/pkg/volume/util/operationexecutor/operation_generator.go @@ -32,7 +32,7 @@ import ( clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" volerr "k8s.io/cloud-provider/volume/errors" - csilib "k8s.io/csi-translation-lib" + csitrans "k8s.io/csi-translation-lib" "k8s.io/klog" "k8s.io/kubernetes/pkg/features" kevents "k8s.io/kubernetes/pkg/kubelet/events" @@ -49,6 +49,18 @@ const ( unknownAttachableVolumePlugin string = "UnknownAttachableVolumePlugin" ) +// InTreeToCSITranslator contains methods required to check migratable status +// and perform translations from InTree PVs and Inline to CSI +type InTreeToCSITranslator interface { + IsPVMigratable(pv *v1.PersistentVolume) bool + IsInlineMigratable(vol *v1.Volume) bool + IsMigratableIntreePluginByName(inTreePluginName string) bool + GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) + GetCSINameFromInTreeName(pluginName string) (string, error) + TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) + TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) +} + var _ OperationGenerator = &operationGenerator{} type operationGenerator struct { @@ -70,6 +82,8 @@ type operationGenerator struct { // blkUtil provides volume path related operations for block volume blkUtil volumepathhandler.BlockVolumePathHandler + + translator InTreeToCSITranslator } // NewOperationGenerator is returns instance of operationGenerator @@ -85,6 +99,7 @@ func NewOperationGenerator(kubeClient clientset.Interface, recorder: recorder, checkNodeCapabilitiesBeforeMount: checkNodeCapabilitiesBeforeMount, blkUtil: blkUtil, + translator: csitrans.New(), } } @@ -123,6 +138,9 @@ type OperationGenerator interface { // GetVolumePluginMgr returns volume plugin manager GetVolumePluginMgr() *volume.VolumePluginMgr + // GetCSITranslator returns the CSI Translation Library + GetCSITranslator() InTreeToCSITranslator + GenerateBulkVolumeVerifyFunc( map[types.NodeName][]*volume.Spec, string, @@ -153,14 +171,14 @@ func (og *operationGenerator) GenerateVolumesAreAttachedFunc( } // Migration: Must also check the Node since Attach would have been done with in-tree if node is not using Migration - nu, err := nodeUsingCSIPlugin(og, volumeAttached.VolumeSpec, nodeName) + nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeAttached.VolumeSpec, nodeName) if err != nil { klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.NodeUsingCSIPlugin failed", err).Error()) continue } var volumePlugin volume.VolumePlugin - if useCSIPlugin(og.volumePluginMgr, volumeAttached.VolumeSpec) && nu { + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeAttached.VolumeSpec) && nu { // The volume represented by this spec is CSI and thus should be migrated volumePlugin, err = og.volumePluginMgr.FindPluginByName(csi.CSIPluginName) if err != nil || volumePlugin == nil { @@ -168,7 +186,7 @@ func (og *operationGenerator) GenerateVolumesAreAttachedFunc( continue } - csiSpec, err := translateSpec(volumeAttached.VolumeSpec) + csiSpec, err := translateSpec(og.translator, volumeAttached.VolumeSpec) if err != nil { klog.Errorf(volumeAttached.GenerateErrorDetailed("VolumesAreAttached.TranslateSpec failed", err).Error()) continue @@ -330,20 +348,20 @@ func (og *operationGenerator) GenerateAttachVolumeFunc( attachVolumeFunc := func() (error, error) { var attachableVolumePlugin volume.AttachableVolumePlugin - nu, err := nodeUsingCSIPlugin(og, volumeToAttach.VolumeSpec, volumeToAttach.NodeName) + nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec, volumeToAttach.NodeName) if err != nil { return volumeToAttach.GenerateError("AttachVolume.NodeUsingCSIPlugin failed", err) } // useCSIPlugin will check both CSIMigration and the plugin specific feature gates - if useCSIPlugin(og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu { + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu { // The volume represented by this spec is CSI and thus should be migrated attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName) if err != nil || attachableVolumePlugin == nil { return volumeToAttach.GenerateError("AttachVolume.FindAttachablePluginByName failed", err) } - csiSpec, err := translateSpec(volumeToAttach.VolumeSpec) + csiSpec, err := translateSpec(og.translator, volumeToAttach.VolumeSpec) if err != nil { return volumeToAttach.GenerateError("AttachVolume.TranslateSpec failed", err) } @@ -416,15 +434,15 @@ func (og *operationGenerator) GenerateAttachVolumeFunc( // involves determining the plugin_name for the metric generating "CompleteFunc" // during the actual "OperationFunc" and not during this generation function - nu, err := nodeUsingCSIPlugin(og, volumeToAttach.VolumeSpec, volumeToAttach.NodeName) + nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec, volumeToAttach.NodeName) if err != nil { klog.Errorf("GenerateAttachVolumeFunc failed to check if node is using CSI Plugin, metric for this operation may be inaccurate: %v", err) } // Need to translate the spec here if the plugin is migrated so that the metrics // emitted show the correct (migrated) plugin - if useCSIPlugin(og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu { - csiSpec, err := translateSpec(volumeToAttach.VolumeSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToAttach.VolumeSpec) && nu { + csiSpec, err := translateSpec(og.translator, volumeToAttach.VolumeSpec) if err == nil { volumeToAttach.VolumeSpec = csiSpec } @@ -456,6 +474,10 @@ func (og *operationGenerator) GetVolumePluginMgr() *volume.VolumePluginMgr { return og.volumePluginMgr } +func (og *operationGenerator) GetCSITranslator() InTreeToCSITranslator { + return og.translator +} + func (og *operationGenerator) GenerateDetachVolumeFunc( volumeToDetach AttachedVolume, verifySafeToDetach bool, @@ -467,20 +489,20 @@ func (og *operationGenerator) GenerateDetachVolumeFunc( if volumeToDetach.VolumeSpec != nil { // Get attacher plugin - nu, err := nodeUsingCSIPlugin(og, volumeToDetach.VolumeSpec, volumeToDetach.NodeName) + nu, err := nodeUsingCSIPlugin(og.translator, og.volumePluginMgr, volumeToDetach.VolumeSpec, volumeToDetach.NodeName) if err != nil { return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.NodeUsingCSIPlugin failed", err) } // useCSIPlugin will check both CSIMigration and the plugin specific feature gate - if useCSIPlugin(og.volumePluginMgr, volumeToDetach.VolumeSpec) && nu { + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToDetach.VolumeSpec) && nu { // The volume represented by this spec is CSI and thus should be migrated attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName) if err != nil || attachableVolumePlugin == nil { return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.FindAttachablePluginBySpec failed", err) } - csiSpec, err := translateSpec(volumeToDetach.VolumeSpec) + csiSpec, err := translateSpec(og.translator, volumeToDetach.VolumeSpec) if err != nil { return volumetypes.GeneratedOperations{}, volumeToDetach.GenerateErrorDetailed("DetachVolume.TranslateSpec failed", err) } @@ -511,7 +533,7 @@ func (og *operationGenerator) GenerateDetachVolumeFunc( // TODO(dyzz): This case can't distinguish between PV and In-line which is necessary because // if it was PV it may have been migrated, but the same plugin with in-line may not have been. // Suggestions welcome... - if csilib.IsMigratableIntreePluginByName(pluginName) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) { + if og.translator.IsMigratableIntreePluginByName(pluginName) && utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) { // The volume represented by this spec is CSI and thus should be migrated attachableVolumePlugin, err = og.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName) if err != nil || attachableVolumePlugin == nil { @@ -582,8 +604,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc( volumePluginName := unknownVolumePlugin // Need to translate the spec here if the plugin is migrated so that the metrics // emitted show the correct (migrated) plugin - if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) { - csiSpec, err := translateSpec(volumeToMount.VolumeSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) { + csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec) if err == nil { volumeToMount.VolumeSpec = csiSpec } @@ -601,8 +623,8 @@ func (og *operationGenerator) GenerateMountVolumeFunc( mountVolumeFunc := func() (error, error) { // Get mounter plugin - if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) { - csiSpec, err := translateSpec(volumeToMount.VolumeSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) { + csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec) if err != nil { return volumeToMount.GenerateError("MountVolume.TranslateSpec failed", err) } @@ -795,7 +817,7 @@ func (og *operationGenerator) GenerateUnmountVolumeFunc( podsDir string) (volumetypes.GeneratedOperations, error) { var pluginName string - if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.volumePluginMgr, volumeToUnmount.VolumeSpec) { + if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.translator, og.volumePluginMgr, volumeToUnmount.VolumeSpec) { pluginName = csi.CSIPluginName } else { pluginName = volumeToUnmount.PluginName @@ -863,9 +885,9 @@ func (og *operationGenerator) GenerateUnmountDeviceFunc( hostutil hostutil.HostUtils) (volumetypes.GeneratedOperations, error) { var pluginName string - if useCSIPlugin(og.volumePluginMgr, deviceToDetach.VolumeSpec) { + if useCSIPlugin(og.translator, og.volumePluginMgr, deviceToDetach.VolumeSpec) { pluginName = csi.CSIPluginName - csiSpec, err := translateSpec(deviceToDetach.VolumeSpec) + csiSpec, err := translateSpec(og.translator, deviceToDetach.VolumeSpec) if err != nil { return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmountDevice.TranslateSpec failed", err) } @@ -965,8 +987,8 @@ func (og *operationGenerator) GenerateMapVolumeFunc( originalSpec := volumeToMount.VolumeSpec // Translate to CSI spec if migration enabled - if useCSIPlugin(og.volumePluginMgr, originalSpec) { - csiSpec, err := translateSpec(originalSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, originalSpec) { + csiSpec, err := translateSpec(og.translator, originalSpec) if err != nil { return volumetypes.GeneratedOperations{}, volumeToMount.GenerateErrorDetailed("MapVolume.TranslateSpec failed", err) } @@ -1153,8 +1175,8 @@ func (og *operationGenerator) GenerateUnmapVolumeFunc( var err error // Translate to CSI spec if migration enabled // And get block volume unmapper plugin - if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.volumePluginMgr, volumeToUnmount.VolumeSpec) { - csiSpec, err := translateSpec(volumeToUnmount.VolumeSpec) + if volumeToUnmount.VolumeSpec != nil && useCSIPlugin(og.translator, og.volumePluginMgr, volumeToUnmount.VolumeSpec) { + csiSpec, err := translateSpec(og.translator, volumeToUnmount.VolumeSpec) if err != nil { return volumetypes.GeneratedOperations{}, volumeToUnmount.GenerateErrorDetailed("UnmapVolume.TranslateSpec failed", err) } @@ -1249,8 +1271,8 @@ func (og *operationGenerator) GenerateUnmapDeviceFunc( var blockVolumePlugin volume.BlockVolumePlugin var err error // Translate to CSI spec if migration enabled - if useCSIPlugin(og.volumePluginMgr, deviceToDetach.VolumeSpec) { - csiSpec, err := translateSpec(deviceToDetach.VolumeSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, deviceToDetach.VolumeSpec) { + csiSpec, err := translateSpec(og.translator, deviceToDetach.VolumeSpec) if err != nil { return volumetypes.GeneratedOperations{}, deviceToDetach.GenerateErrorDetailed("UnmapDevice.TranslateSpec failed", err) } @@ -1564,8 +1586,8 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc( fsResizeFunc := func() (error, error) { // Need to translate the spec here if the plugin is migrated so that the metrics // emitted show the correct (migrated) plugin - if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) { - csiSpec, err := translateSpec(volumeToMount.VolumeSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) { + csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec) if err != nil { return volumeToMount.GenerateError("NodeExpandVolume.translateSpec failed", err) } @@ -1636,8 +1658,8 @@ func (og *operationGenerator) GenerateExpandInUseVolumeFunc( // Need to translate the spec here if the plugin is migrated so that the metrics // emitted show the correct (migrated) plugin - if useCSIPlugin(og.volumePluginMgr, volumeToMount.VolumeSpec) { - csiSpec, err := translateSpec(volumeToMount.VolumeSpec) + if useCSIPlugin(og.translator, og.volumePluginMgr, volumeToMount.VolumeSpec) { + csiSpec, err := translateSpec(og.translator, volumeToMount.VolumeSpec) if err == nil { volumeToMount.VolumeSpec = csiSpec } @@ -1796,7 +1818,7 @@ func isDeviceOpened(deviceToDetach AttachedVolume, hostUtil hostutil.HostUtils) return deviceOpened, nil } -func useCSIPlugin(vpm *volume.VolumePluginMgr, spec *volume.Spec) bool { +func useCSIPlugin(tr InTreeToCSITranslator, vpm *volume.VolumePluginMgr, spec *volume.Spec) bool { // TODO(#75146) Check whether the driver is installed as well so that // we can throw a better error when the driver is not installed. // The error should be of the approximate form: @@ -1804,7 +1826,7 @@ func useCSIPlugin(vpm *volume.VolumePluginMgr, spec *volume.Spec) bool { if !utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) { return false } - if csilib.IsPVMigratable(spec.PersistentVolume) || csilib.IsInlineMigratable(spec.Volume) { + if tr.IsPVMigratable(spec.PersistentVolume) || tr.IsInlineMigratable(spec.Volume) { migratable, err := vpm.IsPluginMigratableBySpec(spec) if err == nil && migratable { return true @@ -1813,9 +1835,7 @@ func useCSIPlugin(vpm *volume.VolumePluginMgr, spec *volume.Spec) bool { return false } -func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types.NodeName) (bool, error) { - vpm := og.GetVolumePluginMgr() - +func nodeUsingCSIPlugin(tr InTreeToCSITranslator, vpm *volume.VolumePluginMgr, spec *volume.Spec, nodeName types.NodeName) (bool, error) { migratable, err := vpm.IsPluginMigratableBySpec(spec) if err != nil { return false, err @@ -1869,7 +1889,7 @@ func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types mpaSet = sets.NewString(tok...) } - pluginName, err := csilib.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume) + pluginName, err := tr.GetInTreePluginNameFromSpec(spec.PersistentVolume, spec.Volume) if err != nil { return false, err } @@ -1883,7 +1903,7 @@ func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types if isMigratedOnNode { installed := false - driverName, err := csilib.GetCSINameFromInTreeName(pluginName) + driverName, err := tr.GetCSINameFromInTreeName(pluginName) if err != nil { return isMigratedOnNode, err } @@ -1902,19 +1922,19 @@ func nodeUsingCSIPlugin(og OperationGenerator, spec *volume.Spec, nodeName types } -func translateSpec(spec *volume.Spec) (*volume.Spec, error) { +func translateSpec(tr InTreeToCSITranslator, spec *volume.Spec) (*volume.Spec, error) { var csiPV *v1.PersistentVolume var err error inlineVolume := false if spec.PersistentVolume != nil { // TranslateInTreePVToCSI will create a new PV - csiPV, err = csilib.TranslateInTreePVToCSI(spec.PersistentVolume) + csiPV, err = tr.TranslateInTreePVToCSI(spec.PersistentVolume) if err != nil { return nil, fmt.Errorf("failed to translate in tree pv to CSI: %v", err) } } else if spec.Volume != nil { // TranslateInTreeInlineVolumeToCSI will create a new PV - csiPV, err = csilib.TranslateInTreeInlineVolumeToCSI(spec.Volume) + csiPV, err = tr.TranslateInTreeInlineVolumeToCSI(spec.Volume) if err != nil { return nil, fmt.Errorf("failed to translate in tree inline volume to CSI: %v", err) } diff --git a/pkg/volume/util/operationexecutor/operation_generator_test.go b/pkg/volume/util/operationexecutor/operation_generator_test.go index a2c7bbb8cd2..8e128d1fb3c 100644 --- a/pkg/volume/util/operationexecutor/operation_generator_test.go +++ b/pkg/volume/util/operationexecutor/operation_generator_test.go @@ -125,7 +125,7 @@ func TestOperationGenerator_GenerateUnmapVolumeFunc_PluginName(t *testing.T) { // csi plugin looks a file that contains some information about the volume, // and GenerateUnmapVolumeFuncfails if csi plugin can't find that file. // So the reason for calling plugin.NewBlockVolumeMapper for csi enabled case is creating that file. - csiSpec, err := translateSpec(volumeToUnmount.VolumeSpec) + csiSpec, err := translateSpec(operationGenerator.GetCSITranslator(), volumeToUnmount.VolumeSpec) if err != nil { t.Fatalf("Can't translate volume to CSI") } diff --git a/staging/src/k8s.io/csi-translation-lib/translate.go b/staging/src/k8s.io/csi-translation-lib/translate.go index dbe2e34a125..609083b49b5 100644 --- a/staging/src/k8s.io/csi-translation-lib/translate.go +++ b/staging/src/k8s.io/csi-translation-lib/translate.go @@ -35,9 +35,20 @@ var ( } ) +// CSITranslator translates in-tree storage API objects to their equivalent CSI +// API objects. It also provides many helper functions to determine whether +// translation logic exists and the mappings between "in-tree plugin <-> csi driver" +type CSITranslator struct{} + +// New creates a new CSITranslator which does real translation +// for "in-tree plugins <-> csi drivers" +func New() CSITranslator { + return CSITranslator{} +} + // TranslateInTreeStorageClassToCSI takes in-tree Storage Class // and translates it to a set of parameters consumable by CSI plugin -func TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) { +func (ctl CSITranslator) TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) { newSC := sc.DeepCopy() for _, curPlugin := range inTreePlugins { if inTreePluginName == curPlugin.GetInTreePluginName() { @@ -50,7 +61,7 @@ func TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.Stora // TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate // the in-tree volume source to a CSIPersistentVolumeSource (wrapped in a PV) // if the translation logic has been implemented. -func TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) { +func (ctl CSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) { if volume == nil { return nil, fmt.Errorf("persistent volume was nil") } @@ -66,7 +77,7 @@ func TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, // the in-tree source to a CSI Source if the translation logic // has been implemented. The input persistent volume will not // be modified -func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { +func (ctl CSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { if pv == nil { return nil, errors.New("persistent volume was nil") } @@ -82,7 +93,7 @@ func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, erro // TranslateCSIPVToInTree takes a PV with a CSI PersistentVolume Source and will translate // it to a in-tree Persistent Volume Source for the specific in-tree volume specified // by the `Driver` field in the CSI Source. The input PV object will not be modified. -func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { +func (ctl CSITranslator) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) { if pv == nil || pv.Spec.CSI == nil { return nil, errors.New("CSI persistent volume was nil") } @@ -97,7 +108,7 @@ func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, erro // IsMigratableIntreePluginByName tests whether there is migration logic for the in-tree plugin // whose name matches the given name -func IsMigratableIntreePluginByName(inTreePluginName string) bool { +func (ctl CSITranslator) IsMigratableIntreePluginByName(inTreePluginName string) bool { for _, curPlugin := range inTreePlugins { if curPlugin.GetInTreePluginName() == inTreePluginName { return true @@ -108,7 +119,7 @@ func IsMigratableIntreePluginByName(inTreePluginName string) bool { // IsMigratedCSIDriverByName tests whether there exists an in-tree plugin with logic // to migrate to the CSI driver with given name -func IsMigratedCSIDriverByName(csiPluginName string) bool { +func (ctl CSITranslator) IsMigratedCSIDriverByName(csiPluginName string) bool { if _, ok := inTreePlugins[csiPluginName]; ok { return true } @@ -116,7 +127,7 @@ func IsMigratedCSIDriverByName(csiPluginName string) bool { } // GetInTreePluginNameFromSpec returns the plugin name -func GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) { +func (ctl CSITranslator) GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) { if pv != nil { for _, curPlugin := range inTreePlugins { if curPlugin.CanSupport(pv) { @@ -138,7 +149,7 @@ func GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (strin // GetCSINameFromInTreeName returns the name of a CSI driver that supersedes the // in-tree plugin with the given name -func GetCSINameFromInTreeName(pluginName string) (string, error) { +func (ctl CSITranslator) GetCSINameFromInTreeName(pluginName string) (string, error) { for csiDriverName, curPlugin := range inTreePlugins { if curPlugin.GetInTreePluginName() == pluginName { return csiDriverName, nil @@ -149,7 +160,7 @@ func GetCSINameFromInTreeName(pluginName string) (string, error) { // GetInTreeNameFromCSIName returns the name of the in-tree plugin superseded by // a CSI driver with the given name -func GetInTreeNameFromCSIName(pluginName string) (string, error) { +func (ctl CSITranslator) GetInTreeNameFromCSIName(pluginName string) (string, error) { if plugin, ok := inTreePlugins[pluginName]; ok { return plugin.GetInTreePluginName(), nil } @@ -157,7 +168,7 @@ func GetInTreeNameFromCSIName(pluginName string) (string, error) { } // IsPVMigratable tests whether there is migration logic for the given Persistent Volume -func IsPVMigratable(pv *v1.PersistentVolume) bool { +func (ctl CSITranslator) IsPVMigratable(pv *v1.PersistentVolume) bool { for _, curPlugin := range inTreePlugins { if curPlugin.CanSupport(pv) { return true @@ -167,7 +178,7 @@ func IsPVMigratable(pv *v1.PersistentVolume) bool { } // IsInlineMigratable tests whether there is Migration logic for the given Inline Volume -func IsInlineMigratable(vol *v1.Volume) bool { +func (ctl CSITranslator) IsInlineMigratable(vol *v1.Volume) bool { for _, curPlugin := range inTreePlugins { if curPlugin.CanSupportInline(vol) { return true diff --git a/staging/src/k8s.io/csi-translation-lib/translate_test.go b/staging/src/k8s.io/csi-translation-lib/translate_test.go index f095ced630e..a78f46ae923 100644 --- a/staging/src/k8s.io/csi-translation-lib/translate_test.go +++ b/staging/src/k8s.io/csi-translation-lib/translate_test.go @@ -61,12 +61,13 @@ func TestTranslationStability(t *testing.T) { }, } for _, test := range testCases { + ctl := New() t.Logf("Testing %v", test.name) - csiSource, err := TranslateInTreePVToCSI(test.pv) + csiSource, err := ctl.TranslateInTreePVToCSI(test.pv) if err != nil { t.Errorf("Error when translating to CSI: %v", err) } - newPV, err := TranslateCSIPVToInTree(csiSource) + newPV, err := ctl.TranslateCSIPVToInTree(csiSource) if err != nil { t.Errorf("Error when translating CSI Source to in tree volume: %v", err) } @@ -95,18 +96,19 @@ func TestPluginNameMappings(t *testing.T) { } for _, test := range testCases { t.Logf("Testing %v", test.name) - csiPluginName, err := GetCSINameFromInTreeName(test.inTreePluginName) + ctl := New() + csiPluginName, err := ctl.GetCSINameFromInTreeName(test.inTreePluginName) if err != nil { t.Errorf("Error when mapping In-tree plugin name to CSI plugin name %s", err) } - if !IsMigratedCSIDriverByName(csiPluginName) { + if !ctl.IsMigratedCSIDriverByName(csiPluginName) { t.Errorf("%s expected to supersede an In-tree plugin", csiPluginName) } - inTreePluginName, err := GetInTreeNameFromCSIName(csiPluginName) + inTreePluginName, err := ctl.GetInTreeNameFromCSIName(csiPluginName) if err != nil { t.Errorf("Error when mapping CSI plugin name to In-tree plugin name %s", err) } - if !IsMigratableIntreePluginByName(inTreePluginName) { + if !ctl.IsMigratableIntreePluginByName(inTreePluginName) { t.Errorf("%s expected to be migratable to a CSI name", inTreePluginName) } if inTreePluginName != test.inTreePluginName || csiPluginName != test.csiPluginName { diff --git a/test/e2e/storage/testsuites/base.go b/test/e2e/storage/testsuites/base.go index dcb6cf06cf7..d7626666a20 100644 --- a/test/e2e/storage/testsuites/base.go +++ b/test/e2e/storage/testsuites/base.go @@ -34,7 +34,7 @@ import ( utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" clientset "k8s.io/client-go/kubernetes" - csilib "k8s.io/csi-translation-lib" + csitrans "k8s.io/csi-translation-lib" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework/metrics" "k8s.io/kubernetes/test/e2e/framework/podlogs" @@ -557,7 +557,8 @@ func addOpCounts(o1 opCounts, o2 opCounts) opCounts { func getMigrationVolumeOpCounts(cs clientset.Interface, pluginName string) (opCounts, opCounts) { if len(pluginName) > 0 { var migratedOps opCounts - csiName, err := csilib.GetCSINameFromInTreeName(pluginName) + l := csitrans.New() + csiName, err := l.GetCSINameFromInTreeName(pluginName) if err != nil { framework.Logf("Could not find CSI Name for in-tree plugin %v", pluginName) migratedOps = opCounts{}