mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 03:57:41 +00:00
csi-translation-lib: Support structured and contextual logging
This commit is contained in:
parent
8ba158c7f4
commit
1298c8a5fe
@ -136,6 +136,7 @@ linters-settings: # please keep this alphabetized
|
|||||||
contextual k8s.io/component-helpers/.*
|
contextual k8s.io/component-helpers/.*
|
||||||
contextual k8s.io/cri-api/.*
|
contextual k8s.io/cri-api/.*
|
||||||
contextual k8s.io/cri-client/.*
|
contextual k8s.io/cri-client/.*
|
||||||
|
contextual k8s.io/csi-translation-lib/.*
|
||||||
contextual k8s.io/dynamic-resource-allocation/.*
|
contextual k8s.io/dynamic-resource-allocation/.*
|
||||||
contextual k8s.io/endpointslice/.*
|
contextual k8s.io/endpointslice/.*
|
||||||
contextual k8s.io/kms/.*
|
contextual k8s.io/kms/.*
|
||||||
|
@ -182,6 +182,7 @@ linters-settings: # please keep this alphabetized
|
|||||||
contextual k8s.io/component-helpers/.*
|
contextual k8s.io/component-helpers/.*
|
||||||
contextual k8s.io/cri-api/.*
|
contextual k8s.io/cri-api/.*
|
||||||
contextual k8s.io/cri-client/.*
|
contextual k8s.io/cri-client/.*
|
||||||
|
contextual k8s.io/csi-translation-lib/.*
|
||||||
contextual k8s.io/dynamic-resource-allocation/.*
|
contextual k8s.io/dynamic-resource-allocation/.*
|
||||||
contextual k8s.io/endpointslice/.*
|
contextual k8s.io/endpointslice/.*
|
||||||
contextual k8s.io/kms/.*
|
contextual k8s.io/kms/.*
|
||||||
|
@ -185,6 +185,7 @@ linters-settings: # please keep this alphabetized
|
|||||||
contextual k8s.io/component-helpers/.*
|
contextual k8s.io/component-helpers/.*
|
||||||
contextual k8s.io/cri-api/.*
|
contextual k8s.io/cri-api/.*
|
||||||
contextual k8s.io/cri-client/.*
|
contextual k8s.io/cri-client/.*
|
||||||
|
contextual k8s.io/csi-translation-lib/.*
|
||||||
contextual k8s.io/dynamic-resource-allocation/.*
|
contextual k8s.io/dynamic-resource-allocation/.*
|
||||||
contextual k8s.io/endpointslice/.*
|
contextual k8s.io/endpointslice/.*
|
||||||
contextual k8s.io/kms/.*
|
contextual k8s.io/kms/.*
|
||||||
|
@ -32,6 +32,7 @@ contextual k8s.io/client-go/tools/record/.*
|
|||||||
contextual k8s.io/component-helpers/.*
|
contextual k8s.io/component-helpers/.*
|
||||||
contextual k8s.io/cri-api/.*
|
contextual k8s.io/cri-api/.*
|
||||||
contextual k8s.io/cri-client/.*
|
contextual k8s.io/cri-client/.*
|
||||||
|
contextual k8s.io/csi-translation-lib/.*
|
||||||
contextual k8s.io/dynamic-resource-allocation/.*
|
contextual k8s.io/dynamic-resource-allocation/.*
|
||||||
contextual k8s.io/endpointslice/.*
|
contextual k8s.io/endpointslice/.*
|
||||||
contextual k8s.io/kms/.*
|
contextual k8s.io/kms/.*
|
||||||
|
@ -711,7 +711,7 @@ func (adc *attachDetachController) processVolumeAttachments(logger klog.Logger)
|
|||||||
// PV is migrated and should be handled by the CSI plugin instead of the in-tree one
|
// PV is migrated and should be handled by the CSI plugin instead of the in-tree one
|
||||||
plugin, _ = adc.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
plugin, _ = adc.volumePluginMgr.FindAttachablePluginByName(csi.CSIPluginName)
|
||||||
// podNamespace is not needed here for Azurefile as the volumeName generated will be the same with or without podNamespace
|
// podNamespace is not needed here for Azurefile as the volumeName generated will be the same with or without podNamespace
|
||||||
volumeSpec, err = csimigration.TranslateInTreeSpecToCSI(volumeSpec, "" /* podNamespace */, adc.intreeToCSITranslator)
|
volumeSpec, err = csimigration.TranslateInTreeSpecToCSI(logger, volumeSpec, "" /* podNamespace */, adc.intreeToCSITranslator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to translate intree volumeSpec to CSI volumeSpec for volume", "node", klog.KRef("", string(nodeName)), "inTreePluginName", inTreePluginName, "vaName", va.Name, "PV", klog.KRef("", *pvName))
|
logger.Error(err, "Failed to translate intree volumeSpec to CSI volumeSpec for volume", "node", klog.KRef("", string(nodeName)), "inTreePluginName", inTreePluginName, "vaName", va.Name, "PV", klog.KRef("", *pvName))
|
||||||
continue
|
continue
|
||||||
|
@ -81,7 +81,7 @@ func CreateVolumeSpec(logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, node
|
|||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
volumeSpec, err = translateInTreeSpecToCSIIfNeeded(volumeSpec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
|
volumeSpec, err = translateInTreeSpecToCSIIfNeeded(logger, volumeSpec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"error performing CSI migration checks and translation for PVC %q/%q: %v",
|
"error performing CSI migration checks and translation for PVC %q/%q: %v",
|
||||||
@ -100,7 +100,7 @@ func CreateVolumeSpec(logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, node
|
|||||||
clonedPodVolume := podVolume.DeepCopy()
|
clonedPodVolume := podVolume.DeepCopy()
|
||||||
|
|
||||||
origspec := volume.NewSpecFromVolume(clonedPodVolume)
|
origspec := volume.NewSpecFromVolume(clonedPodVolume)
|
||||||
spec, err := translateInTreeSpecToCSIIfNeeded(origspec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
|
spec, err := translateInTreeSpecToCSIIfNeeded(logger, origspec, nodeName, vpm, csiMigratedPluginManager, csiTranslator, pod.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"error performing CSI migration checks and translation for inline volume %q: %v",
|
"error performing CSI migration checks and translation for inline volume %q: %v",
|
||||||
@ -241,7 +241,7 @@ func ProcessPodVolumes(logger klog.Logger, pod *v1.Pod, addVolumes bool, desired
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func translateInTreeSpecToCSIIfNeeded(spec *volume.Spec, nodeName types.NodeName, vpm *volume.VolumePluginMgr, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator, podNamespace string) (*volume.Spec, error) {
|
func translateInTreeSpecToCSIIfNeeded(logger klog.Logger, spec *volume.Spec, nodeName types.NodeName, vpm *volume.VolumePluginMgr, csiMigratedPluginManager csimigration.PluginManager, csiTranslator csimigration.InTreeToCSITranslator, podNamespace string) (*volume.Spec, error) {
|
||||||
translatedSpec := spec
|
translatedSpec := spec
|
||||||
migratable, err := csiMigratedPluginManager.IsMigratable(spec)
|
migratable, err := csiMigratedPluginManager.IsMigratable(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -256,7 +256,7 @@ func translateInTreeSpecToCSIIfNeeded(spec *volume.Spec, nodeName types.NodeName
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if migratable && migrationSupportedOnNode {
|
if migratable && migrationSupportedOnNode {
|
||||||
translatedSpec, err = csimigration.TranslateInTreeSpecToCSI(spec, podNamespace, csiTranslator)
|
translatedSpec, err = csimigration.TranslateInTreeSpecToCSI(logger, spec, podNamespace, csiTranslator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1648,7 @@ func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) {
|
|||||||
kl.warnCgroupV1Usage()
|
kl.warnCgroupV1Usage()
|
||||||
|
|
||||||
// Start volume manager
|
// Start volume manager
|
||||||
go kl.volumeManager.Run(kl.sourcesReady, wait.NeverStop)
|
go kl.volumeManager.Run(ctx, kl.sourcesReady)
|
||||||
|
|
||||||
if kl.kubeClient != nil {
|
if kl.kubeClient != nil {
|
||||||
// Start two go-routines to update the status.
|
// Start two go-routines to update the status.
|
||||||
|
@ -2997,12 +2997,6 @@ func simulateVolumeInUseUpdate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runVolumeManager(kubelet *Kubelet) chan struct{} {
|
|
||||||
stopCh := make(chan struct{})
|
|
||||||
go kubelet.volumeManager.Run(kubelet.sourcesReady, stopCh)
|
|
||||||
return stopCh
|
|
||||||
}
|
|
||||||
|
|
||||||
// dirExists returns true if the path exists and represents a directory.
|
// dirExists returns true if the path exists and represents a directory.
|
||||||
func dirExists(path string) bool {
|
func dirExists(path string) bool {
|
||||||
s, err := os.Stat(path)
|
s, err := os.Stat(path)
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"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"
|
||||||
|
"k8s.io/kubernetes/test/utils/ktesting"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListVolumesForPod(t *testing.T) {
|
func TestListVolumesForPod(t *testing.T) {
|
||||||
@ -78,8 +79,9 @@ func TestListVolumesForPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||||
err := kubelet.volumeManager.WaitForAttachAndMount(context.Background(), pod)
|
err := kubelet.volumeManager.WaitForAttachAndMount(context.Background(), pod)
|
||||||
@ -196,8 +198,9 @@ func TestPodVolumesExist(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
kubelet.podManager.SetPods(pods)
|
kubelet.podManager.SetPods(pods)
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
@ -255,8 +258,9 @@ func TestPodVolumeDeadlineAttachAndMount(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
kubelet.podManager.SetPods(pods)
|
kubelet.podManager.SetPods(pods)
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
@ -316,8 +320,9 @@ func TestPodVolumeDeadlineUnmount(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
kubelet.podManager.SetPods(pods)
|
kubelet.podManager.SetPods(pods)
|
||||||
for i, pod := range pods {
|
for i, pod := range pods {
|
||||||
@ -369,8 +374,9 @@ func TestVolumeAttachAndMountControllerDisabled(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||||
err := kubelet.volumeManager.WaitForAttachAndMount(context.Background(), pod)
|
err := kubelet.volumeManager.WaitForAttachAndMount(context.Background(), pod)
|
||||||
@ -428,8 +434,9 @@ func TestVolumeUnmountAndDetachControllerDisabled(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
// Add pod
|
// Add pod
|
||||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||||
@ -534,15 +541,16 @@ func TestVolumeAttachAndMountControllerEnabled(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||||
|
|
||||||
// Fake node status update
|
// Fake node status update
|
||||||
go simulateVolumeInUseUpdate(
|
go simulateVolumeInUseUpdate(
|
||||||
v1.UniqueVolumeName("fake/fake-device"),
|
v1.UniqueVolumeName("fake/fake-device"),
|
||||||
stopCh,
|
tCtx.Done(),
|
||||||
kubelet.volumeManager)
|
kubelet.volumeManager)
|
||||||
|
|
||||||
assert.NoError(t, kubelet.volumeManager.WaitForAttachAndMount(context.Background(), pod))
|
assert.NoError(t, kubelet.volumeManager.WaitForAttachAndMount(context.Background(), pod))
|
||||||
@ -618,8 +626,9 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
stopCh := runVolumeManager(kubelet)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
go kubelet.volumeManager.Run(tCtx, kubelet.sourcesReady)
|
||||||
|
|
||||||
// Add pod
|
// Add pod
|
||||||
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
kubelet.podManager.SetPods([]*v1.Pod{pod})
|
||||||
@ -627,7 +636,7 @@ func TestVolumeUnmountAndDetachControllerEnabled(t *testing.T) {
|
|||||||
// Fake node status update
|
// Fake node status update
|
||||||
go simulateVolumeInUseUpdate(
|
go simulateVolumeInUseUpdate(
|
||||||
v1.UniqueVolumeName("fake/fake-device"),
|
v1.UniqueVolumeName("fake/fake-device"),
|
||||||
stopCh,
|
tCtx.Done(),
|
||||||
kubelet.volumeManager)
|
kubelet.volumeManager)
|
||||||
|
|
||||||
// Verify volumes attached
|
// Verify volumes attached
|
||||||
|
@ -50,7 +50,7 @@ import (
|
|||||||
// if it has volumes. It also verifies that the pods in the desired state of the
|
// if it has volumes. It also verifies that the pods in the desired state of the
|
||||||
// world cache still exist, if not, it removes them.
|
// world cache still exist, if not, it removes them.
|
||||||
type DesiredStateOfWorldPopulator interface {
|
type DesiredStateOfWorldPopulator interface {
|
||||||
Run(sourcesReady config.SourcesReady, stopCh <-chan struct{})
|
Run(ctx context.Context, sourcesReady config.SourcesReady)
|
||||||
|
|
||||||
// ReprocessPod sets value for the specified pod in processedPods
|
// ReprocessPod sets value for the specified pod in processedPods
|
||||||
// to false, forcing it to be reprocessed. This is required to enable
|
// to false, forcing it to be reprocessed. This is required to enable
|
||||||
@ -141,21 +141,22 @@ type processedPods struct {
|
|||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dswp *desiredStateOfWorldPopulator) Run(sourcesReady config.SourcesReady, stopCh <-chan struct{}) {
|
func (dswp *desiredStateOfWorldPopulator) Run(ctx context.Context, sourcesReady config.SourcesReady) {
|
||||||
// Wait for the completion of a loop that started after sources are all ready, then set hasAddedPods accordingly
|
// Wait for the completion of a loop that started after sources are all ready, then set hasAddedPods accordingly
|
||||||
klog.InfoS("Desired state populator starts to run")
|
logger := klog.FromContext(ctx)
|
||||||
wait.PollUntil(dswp.loopSleepDuration, func() (bool, error) {
|
logger.Info("Desired state populator starts to run")
|
||||||
|
_ = wait.PollUntilContextCancel(ctx, dswp.loopSleepDuration, false, func(ctx context.Context) (bool, error) {
|
||||||
done := sourcesReady.AllReady()
|
done := sourcesReady.AllReady()
|
||||||
dswp.populatorLoop()
|
dswp.populatorLoop(ctx)
|
||||||
return done, nil
|
return done, nil
|
||||||
}, stopCh)
|
})
|
||||||
dswp.hasAddedPodsLock.Lock()
|
dswp.hasAddedPodsLock.Lock()
|
||||||
if !dswp.hasAddedPods {
|
if !dswp.hasAddedPods {
|
||||||
klog.InfoS("Finished populating initial desired state of world")
|
logger.Info("Finished populating initial desired state of world")
|
||||||
dswp.hasAddedPods = true
|
dswp.hasAddedPods = true
|
||||||
}
|
}
|
||||||
dswp.hasAddedPodsLock.Unlock()
|
dswp.hasAddedPodsLock.Unlock()
|
||||||
wait.Until(dswp.populatorLoop, dswp.loopSleepDuration, stopCh)
|
wait.UntilWithContext(ctx, dswp.populatorLoop, dswp.loopSleepDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dswp *desiredStateOfWorldPopulator) ReprocessPod(
|
func (dswp *desiredStateOfWorldPopulator) ReprocessPod(
|
||||||
@ -169,14 +170,14 @@ func (dswp *desiredStateOfWorldPopulator) HasAddedPods() bool {
|
|||||||
return dswp.hasAddedPods
|
return dswp.hasAddedPods
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dswp *desiredStateOfWorldPopulator) populatorLoop() {
|
func (dswp *desiredStateOfWorldPopulator) populatorLoop(ctx context.Context) {
|
||||||
dswp.findAndAddNewPods()
|
dswp.findAndAddNewPods(ctx)
|
||||||
dswp.findAndRemoveDeletedPods()
|
dswp.findAndRemoveDeletedPods()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through all pods and add to desired state of world if they don't
|
// Iterate through all pods and add to desired state of world if they don't
|
||||||
// exist but should
|
// exist but should
|
||||||
func (dswp *desiredStateOfWorldPopulator) findAndAddNewPods() {
|
func (dswp *desiredStateOfWorldPopulator) findAndAddNewPods(ctx context.Context) {
|
||||||
// Map unique pod name to outer volume name to MountedVolume.
|
// Map unique pod name to outer volume name to MountedVolume.
|
||||||
mountedVolumesForPod := make(map[volumetypes.UniquePodName]map[string]cache.MountedVolume)
|
mountedVolumesForPod := make(map[volumetypes.UniquePodName]map[string]cache.MountedVolume)
|
||||||
for _, mountedVolume := range dswp.actualStateOfWorld.GetMountedVolumes() {
|
for _, mountedVolume := range dswp.actualStateOfWorld.GetMountedVolumes() {
|
||||||
@ -201,7 +202,7 @@ func (dswp *desiredStateOfWorldPopulator) findAndAddNewPods() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dswp.processPodVolumes(pod, mountedVolumesForPod)
|
dswp.processPodVolumes(ctx, pod, mountedVolumesForPod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,12 +285,14 @@ func (dswp *desiredStateOfWorldPopulator) findAndRemoveDeletedPods() {
|
|||||||
// processPodVolumes processes the volumes in the given pod and adds them to the
|
// processPodVolumes processes the volumes in the given pod and adds them to the
|
||||||
// desired state of the world.
|
// desired state of the world.
|
||||||
func (dswp *desiredStateOfWorldPopulator) processPodVolumes(
|
func (dswp *desiredStateOfWorldPopulator) processPodVolumes(
|
||||||
|
ctx context.Context,
|
||||||
pod *v1.Pod,
|
pod *v1.Pod,
|
||||||
mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume) {
|
mountedVolumesForPod map[volumetypes.UniquePodName]map[string]cache.MountedVolume) {
|
||||||
if pod == nil {
|
if pod == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger := klog.FromContext(ctx)
|
||||||
uniquePodName := util.GetUniquePodName(pod)
|
uniquePodName := util.GetUniquePodName(pod)
|
||||||
if dswp.podPreviouslyProcessed(uniquePodName) {
|
if dswp.podPreviouslyProcessed(uniquePodName) {
|
||||||
return
|
return
|
||||||
@ -302,14 +305,14 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(
|
|||||||
for _, podVolume := range pod.Spec.Volumes {
|
for _, podVolume := range pod.Spec.Volumes {
|
||||||
if !mounts.Has(podVolume.Name) && !devices.Has(podVolume.Name) {
|
if !mounts.Has(podVolume.Name) && !devices.Has(podVolume.Name) {
|
||||||
// Volume is not used in the pod, ignore it.
|
// Volume is not used in the pod, ignore it.
|
||||||
klog.V(4).InfoS("Skipping unused volume", "pod", klog.KObj(pod), "volumeName", podVolume.Name)
|
logger.V(4).Info("Skipping unused volume", "pod", klog.KObj(pod), "volumeName", podVolume.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
pvc, volumeSpec, volumeGidValue, err :=
|
pvc, volumeSpec, volumeGidValue, err :=
|
||||||
dswp.createVolumeSpec(podVolume, pod, mounts, devices)
|
dswp.createVolumeSpec(logger, podVolume, pod, mounts, devices)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "Error processing volume", "pod", klog.KObj(pod), "volumeName", podVolume.Name)
|
logger.Error(err, "Error processing volume", "pod", klog.KObj(pod), "volumeName", podVolume.Name)
|
||||||
dswp.desiredStateOfWorld.AddErrorToPod(uniquePodName, err.Error())
|
dswp.desiredStateOfWorld.AddErrorToPod(uniquePodName, err.Error())
|
||||||
allVolumesAdded = false
|
allVolumesAdded = false
|
||||||
continue
|
continue
|
||||||
@ -319,11 +322,11 @@ func (dswp *desiredStateOfWorldPopulator) processPodVolumes(
|
|||||||
_, err = dswp.desiredStateOfWorld.AddPodToVolume(
|
_, err = dswp.desiredStateOfWorld.AddPodToVolume(
|
||||||
uniquePodName, pod, volumeSpec, podVolume.Name, volumeGidValue, seLinuxContainerContexts[podVolume.Name])
|
uniquePodName, pod, volumeSpec, podVolume.Name, volumeGidValue, seLinuxContainerContexts[podVolume.Name])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "Failed to add volume to desiredStateOfWorld", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name())
|
logger.Error(err, "Failed to add volume to desiredStateOfWorld", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name())
|
||||||
dswp.desiredStateOfWorld.AddErrorToPod(uniquePodName, err.Error())
|
dswp.desiredStateOfWorld.AddErrorToPod(uniquePodName, err.Error())
|
||||||
allVolumesAdded = false
|
allVolumesAdded = false
|
||||||
} else {
|
} else {
|
||||||
klog.V(4).InfoS("Added volume to desired state", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name())
|
logger.V(4).Info("Added volume to desired state", "pod", klog.KObj(pod), "volumeName", podVolume.Name, "volumeSpecName", volumeSpec.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec, uniquePodName, mountedVolumesForPod)
|
dswp.checkVolumeFSResize(pod, podVolume, pvc, volumeSpec, uniquePodName, mountedVolumesForPod)
|
||||||
@ -455,7 +458,7 @@ func (dswp *desiredStateOfWorldPopulator) deleteProcessedPod(
|
|||||||
// specified volume. It dereference any PVC to get PV objects, if needed.
|
// specified volume. It dereference any PVC to get PV objects, if needed.
|
||||||
// Returns an error if unable to obtain the volume at this time.
|
// Returns an error if unable to obtain the volume at this time.
|
||||||
func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
||||||
podVolume v1.Volume, pod *v1.Pod, mounts, devices sets.Set[string]) (*v1.PersistentVolumeClaim, *volume.Spec, string, error) {
|
logger klog.Logger, podVolume v1.Volume, pod *v1.Pod, mounts, devices sets.Set[string]) (*v1.PersistentVolumeClaim, *volume.Spec, string, error) {
|
||||||
pvcSource := podVolume.VolumeSource.PersistentVolumeClaim
|
pvcSource := podVolume.VolumeSource.PersistentVolumeClaim
|
||||||
isEphemeral := pvcSource == nil && podVolume.VolumeSource.Ephemeral != nil
|
isEphemeral := pvcSource == nil && podVolume.VolumeSource.Ephemeral != nil
|
||||||
if isEphemeral {
|
if isEphemeral {
|
||||||
@ -468,7 +471,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pvcSource != nil {
|
if pvcSource != nil {
|
||||||
klog.V(5).InfoS("Found PVC", "PVC", klog.KRef(pod.Namespace, pvcSource.ClaimName))
|
logger.V(5).Info("Found PVC", "PVC", klog.KRef(pod.Namespace, pvcSource.ClaimName))
|
||||||
// If podVolume is a PVC, fetch the real PV behind the claim
|
// If podVolume is a PVC, fetch the real PV behind the claim
|
||||||
pvc, err := dswp.getPVCExtractPV(
|
pvc, err := dswp.getPVCExtractPV(
|
||||||
pod.Namespace, pvcSource.ClaimName)
|
pod.Namespace, pvcSource.ClaimName)
|
||||||
@ -485,7 +488,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pvName, pvcUID := pvc.Spec.VolumeName, pvc.UID
|
pvName, pvcUID := pvc.Spec.VolumeName, pvc.UID
|
||||||
klog.V(5).InfoS("Found bound PV for PVC", "PVC", klog.KRef(pod.Namespace, pvcSource.ClaimName), "PVCUID", pvcUID, "PVName", pvName)
|
logger.V(5).Info("Found bound PV for PVC", "PVC", klog.KRef(pod.Namespace, pvcSource.ClaimName), "PVCUID", pvcUID, "PVName", pvName)
|
||||||
// Fetch actual PV object
|
// Fetch actual PV object
|
||||||
volumeSpec, volumeGidValue, err :=
|
volumeSpec, volumeGidValue, err :=
|
||||||
dswp.getPVSpec(pvName, pvcSource.ReadOnly, pvcUID)
|
dswp.getPVSpec(pvName, pvcSource.ReadOnly, pvcUID)
|
||||||
@ -496,13 +499,13 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
|||||||
pvcSource.ClaimName,
|
pvcSource.ClaimName,
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
klog.V(5).InfoS("Extracted volumeSpec from bound PV and PVC", "PVC", klog.KRef(pod.Namespace, pvcSource.ClaimName), "PVCUID", pvcUID, "PVName", pvName, "volumeSpecName", volumeSpec.Name())
|
logger.V(5).Info("Extracted volumeSpec from bound PV and PVC", "PVC", klog.KRef(pod.Namespace, pvcSource.ClaimName), "PVCUID", pvcUID, "PVName", pvName, "volumeSpecName", volumeSpec.Name())
|
||||||
migratable, err := dswp.csiMigratedPluginManager.IsMigratable(volumeSpec)
|
migratable, err := dswp.csiMigratedPluginManager.IsMigratable(volumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
if migratable {
|
if migratable {
|
||||||
volumeSpec, err = csimigration.TranslateInTreeSpecToCSI(volumeSpec, pod.Namespace, dswp.intreeToCSITranslator)
|
volumeSpec, err = csimigration.TranslateInTreeSpecToCSI(logger, volumeSpec, pod.Namespace, dswp.intreeToCSITranslator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
@ -538,7 +541,7 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
|||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
if migratable {
|
if migratable {
|
||||||
spec, err = csimigration.TranslateInTreeSpecToCSI(spec, pod.Namespace, dswp.intreeToCSITranslator)
|
spec, err = csimigration.TranslateInTreeSpecToCSI(logger, spec, pod.Namespace, dswp.intreeToCSITranslator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,11 @@ limitations under the License.
|
|||||||
package populator
|
package populator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog/v2/ktesting"
|
|
||||||
"k8s.io/utils/ptr"
|
|
||||||
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
@ -46,6 +43,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
|
"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
|
"k8s.io/kubernetes/test/utils/ktesting"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -165,7 +164,8 @@ func TestFindAndAddNewPods_WithDifferentConditions(t *testing.T) {
|
|||||||
|
|
||||||
dswp.hasAddedPods = tc.hasAddedPods
|
dswp.hasAddedPods = tc.hasAddedPods
|
||||||
// Action
|
// Action
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
// Verify
|
// Verify
|
||||||
podsInDSW := dswp.desiredStateOfWorld.GetPods()
|
podsInDSW := dswp.desiredStateOfWorld.GetPods()
|
||||||
@ -204,7 +204,8 @@ func TestFindAndAddNewPods_WithReprocessPodAndVolumeRetrievalError(t *testing.T)
|
|||||||
|
|
||||||
podName := util.GetUniquePodName(pod)
|
podName := util.GetUniquePodName(pod)
|
||||||
|
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
if !dswp.podPreviouslyProcessed(podName) {
|
if !dswp.podPreviouslyProcessed(podName) {
|
||||||
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
||||||
@ -212,7 +213,7 @@ func TestFindAndAddNewPods_WithReprocessPodAndVolumeRetrievalError(t *testing.T)
|
|||||||
pluginPVOmittingClient(dswp)
|
pluginPVOmittingClient(dswp)
|
||||||
|
|
||||||
dswp.ReprocessPod(podName)
|
dswp.ReprocessPod(podName)
|
||||||
dswp.findAndAddNewPods()
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
if !dswp.podPreviouslyProcessed(podName) {
|
if !dswp.podPreviouslyProcessed(podName) {
|
||||||
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
||||||
@ -243,7 +244,8 @@ func TestFindAndAddNewPods_WithVolumeRetrievalError(t *testing.T) {
|
|||||||
|
|
||||||
podName := util.GetUniquePodName(pod)
|
podName := util.GetUniquePodName(pod)
|
||||||
|
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
if dswp.podPreviouslyProcessed(podName) {
|
if dswp.podPreviouslyProcessed(podName) {
|
||||||
t.Fatalf("The volumes for the specified pod: %s should not have been processed by the populator", podName)
|
t.Fatalf("The volumes for the specified pod: %s should not have been processed by the populator", podName)
|
||||||
@ -485,7 +487,8 @@ func prepareDSWPWithPodPV(t *testing.T) (*desiredStateOfWorldPopulator, *fakePod
|
|||||||
|
|
||||||
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name
|
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name
|
||||||
|
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
if !dswp.pods.processedPods[podName] {
|
if !dswp.pods.processedPods[podName] {
|
||||||
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
||||||
@ -535,7 +538,7 @@ func TestFindAndRemoveNonattachableVolumes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fakeVolumePluginMgr, fakeVolumePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
fakeVolumePluginMgr, fakeVolumePlugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
||||||
dswp, fakePodManager, fakesDSW, _, _ := createDswpWithVolumeWithCustomPluginMgr(t, pv, pvc, fakeVolumePluginMgr)
|
dswp, fakePodManager, fakesDSW, _, _ := createDswpWithVolumeWithCustomPluginMgr(pv, pvc, fakeVolumePluginMgr)
|
||||||
|
|
||||||
// create pod
|
// create pod
|
||||||
containers := []v1.Container{
|
containers := []v1.Container{
|
||||||
@ -556,7 +559,8 @@ func TestFindAndRemoveNonattachableVolumes(t *testing.T) {
|
|||||||
|
|
||||||
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name
|
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name
|
||||||
|
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
if !dswp.pods.processedPods[podName] {
|
if !dswp.pods.processedPods[podName] {
|
||||||
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
||||||
@ -602,7 +606,8 @@ func TestEphemeralVolumeOwnerCheck(t *testing.T) {
|
|||||||
|
|
||||||
podName := util.GetUniquePodName(pod)
|
podName := util.GetUniquePodName(pod)
|
||||||
|
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
if dswp.pods.processedPods[podName] {
|
if dswp.pods.processedPods[podName] {
|
||||||
t.Fatalf("%s should not have been processed by the populator", podName)
|
t.Fatalf("%s should not have been processed by the populator", podName)
|
||||||
}
|
}
|
||||||
@ -656,7 +661,8 @@ func TestFindAndAddNewPods_FindAndRemoveDeletedPods_Valid_Block_VolumeDevices(t
|
|||||||
|
|
||||||
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name
|
generatedVolumeName := "fake-plugin/" + pod.Spec.Volumes[0].Name
|
||||||
|
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
if !dswp.pods.processedPods[podName] {
|
if !dswp.pods.processedPods[podName] {
|
||||||
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
t.Fatalf("Failed to record that the volumes for the specified pod: %s have been processed by the populator", podName)
|
||||||
@ -758,10 +764,11 @@ func TestCreateVolumeSpec_Valid_File_VolumeMounts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers)
|
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers)
|
||||||
|
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
fakePodManager.AddPod(pod)
|
fakePodManager.AddPod(pod)
|
||||||
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
||||||
_, volumeSpec, _, err :=
|
_, volumeSpec, _, err :=
|
||||||
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
dswp.createVolumeSpec(logger, pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
if volumeSpec == nil || err != nil {
|
if volumeSpec == nil || err != nil {
|
||||||
@ -804,10 +811,11 @@ func TestCreateVolumeSpec_Valid_Nil_VolumeMounts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers)
|
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers)
|
||||||
|
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
fakePodManager.AddPod(pod)
|
fakePodManager.AddPod(pod)
|
||||||
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
||||||
_, volumeSpec, _, err :=
|
_, volumeSpec, _, err :=
|
||||||
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
dswp.createVolumeSpec(logger, pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
if volumeSpec == nil || err != nil {
|
if volumeSpec == nil || err != nil {
|
||||||
@ -850,10 +858,11 @@ func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "block-bound", containers)
|
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "block-bound", containers)
|
||||||
|
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
fakePodManager.AddPod(pod)
|
fakePodManager.AddPod(pod)
|
||||||
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
||||||
_, volumeSpec, _, err :=
|
_, volumeSpec, _, err :=
|
||||||
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
dswp.createVolumeSpec(logger, pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
if volumeSpec == nil || err != nil {
|
if volumeSpec == nil || err != nil {
|
||||||
@ -896,10 +905,11 @@ func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers)
|
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", containers)
|
||||||
|
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
fakePodManager.AddPod(pod)
|
fakePodManager.AddPod(pod)
|
||||||
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
||||||
_, volumeSpec, _, err :=
|
_, volumeSpec, _, err :=
|
||||||
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
dswp.createVolumeSpec(logger, pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
if volumeSpec != nil || err == nil {
|
if volumeSpec != nil || err == nil {
|
||||||
@ -942,10 +952,11 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "block-bound", containers)
|
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "block-bound", containers)
|
||||||
|
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
fakePodManager.AddPod(pod)
|
fakePodManager.AddPod(pod)
|
||||||
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
mountsMap, devicesMap, _ := util.GetPodVolumeNames(pod)
|
||||||
_, volumeSpec, _, err :=
|
_, volumeSpec, _, err :=
|
||||||
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
dswp.createVolumeSpec(logger, pod.Spec.Volumes[0], pod, mountsMap, devicesMap)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
if volumeSpec != nil || err == nil {
|
if volumeSpec != nil || err == nil {
|
||||||
@ -1104,13 +1115,14 @@ func TestCheckVolumeFSResize(t *testing.T) {
|
|||||||
|
|
||||||
fakePodManager.AddPod(pod)
|
fakePodManager.AddPod(pod)
|
||||||
// Fill the dsw to contains volumes and pods.
|
// Fill the dsw to contains volumes and pods.
|
||||||
dswp.findAndAddNewPods()
|
tCtx := ktesting.Init(t)
|
||||||
|
dswp.findAndAddNewPods(tCtx)
|
||||||
reconcileASW(fakeASW, fakeDSW, t)
|
reconcileASW(fakeASW, fakeDSW, t)
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
tc.resize(t, pv, pvc, dswp)
|
tc.resize(t, pv, pvc, dswp)
|
||||||
|
|
||||||
resizeRequiredVolumes := reprocess(dswp, uniquePodName, fakeDSW, fakeASW, *pv.Spec.Capacity.Storage())
|
resizeRequiredVolumes := reprocess(tCtx, dswp, uniquePodName, fakeDSW, fakeASW, *pv.Spec.Capacity.Storage())
|
||||||
|
|
||||||
tc.verify(t, resizeRequiredVolumes, uniqueVolumeName)
|
tc.verify(t, resizeRequiredVolumes, uniqueVolumeName)
|
||||||
}()
|
}()
|
||||||
@ -1279,8 +1291,9 @@ func TestCheckVolumeSELinux(t *testing.T) {
|
|||||||
|
|
||||||
fakeVolumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
fakeVolumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
||||||
plugin.SupportsSELinux = tc.pluginSupportsSELinux
|
plugin.SupportsSELinux = tc.pluginSupportsSELinux
|
||||||
dswp, fakePodManager, fakeDSW, _, _ := createDswpWithVolumeWithCustomPluginMgr(t, pv, pvc, fakeVolumePluginMgr)
|
dswp, fakePodManager, fakeDSW, _, _ := createDswpWithVolumeWithCustomPluginMgr(pv, pvc, fakeVolumePluginMgr)
|
||||||
|
|
||||||
|
tCtx := ktesting.Init(t)
|
||||||
var existingPod *v1.Pod
|
var existingPod *v1.Pod
|
||||||
if tc.existingContainerSELinuxOpts != nil {
|
if tc.existingContainerSELinuxOpts != nil {
|
||||||
// Add existing pod + volume
|
// Add existing pod + volume
|
||||||
@ -1288,7 +1301,7 @@ func TestCheckVolumeSELinux(t *testing.T) {
|
|||||||
existingContainer.SecurityContext.SELinuxOptions = tc.existingContainerSELinuxOpts
|
existingContainer.SecurityContext.SELinuxOptions = tc.existingContainerSELinuxOpts
|
||||||
existingPod = createPodWithVolume("dswp-old-pod", "dswp-test-volume-name", "file-bound", []v1.Container{existingContainer})
|
existingPod = createPodWithVolume("dswp-old-pod", "dswp-test-volume-name", "file-bound", []v1.Container{existingContainer})
|
||||||
fakePodManager.AddPod(existingPod)
|
fakePodManager.AddPod(existingPod)
|
||||||
dswp.findAndAddNewPods()
|
dswp.findAndAddNewPods(tCtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
newContainer := container
|
newContainer := container
|
||||||
@ -1297,7 +1310,7 @@ func TestCheckVolumeSELinux(t *testing.T) {
|
|||||||
|
|
||||||
// Act - add the new Pod
|
// Act - add the new Pod
|
||||||
fakePodManager.AddPod(newPod)
|
fakePodManager.AddPod(newPod)
|
||||||
dswp.findAndAddNewPods()
|
dswp.findAndAddNewPods(tCtx)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
||||||
@ -1402,10 +1415,10 @@ func clearASW(asw cache.ActualStateOfWorld, dsw cache.DesiredStateOfWorld, t *te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func reprocess(dswp *desiredStateOfWorldPopulator, uniquePodName types.UniquePodName,
|
func reprocess(ctx context.Context, dswp *desiredStateOfWorldPopulator, uniquePodName types.UniquePodName,
|
||||||
dsw cache.DesiredStateOfWorld, asw cache.ActualStateOfWorld, newSize resource.Quantity) []v1.UniqueVolumeName {
|
dsw cache.DesiredStateOfWorld, asw cache.ActualStateOfWorld, newSize resource.Quantity) []v1.UniqueVolumeName {
|
||||||
dswp.ReprocessPod(uniquePodName)
|
dswp.ReprocessPod(uniquePodName)
|
||||||
dswp.findAndAddNewPods()
|
dswp.findAndAddNewPods(ctx)
|
||||||
return getResizeRequiredVolumes(dsw, asw, newSize)
|
return getResizeRequiredVolumes(dsw, asw, newSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1544,7 +1557,7 @@ func createEphemeralVolumeObjects(podName, volumeName string, owned bool, volume
|
|||||||
|
|
||||||
func createDswpWithVolume(t *testing.T, pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) (*desiredStateOfWorldPopulator, kubepod.Manager, cache.DesiredStateOfWorld, *containertest.FakeRuntime, *fakePodStateProvider) {
|
func createDswpWithVolume(t *testing.T, pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) (*desiredStateOfWorldPopulator, kubepod.Manager, cache.DesiredStateOfWorld, *containertest.FakeRuntime, *fakePodStateProvider) {
|
||||||
fakeVolumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
fakeVolumePluginMgr, _ := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
||||||
dswp, fakePodManager, fakesDSW, fakeRuntime, fakeStateProvider := createDswpWithVolumeWithCustomPluginMgr(t, pv, pvc, fakeVolumePluginMgr)
|
dswp, fakePodManager, fakesDSW, fakeRuntime, fakeStateProvider := createDswpWithVolumeWithCustomPluginMgr(pv, pvc, fakeVolumePluginMgr)
|
||||||
return dswp, fakePodManager, fakesDSW, fakeRuntime, fakeStateProvider
|
return dswp, fakePodManager, fakesDSW, fakeRuntime, fakeStateProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1567,7 +1580,7 @@ func (p *fakePodStateProvider) ShouldPodRuntimeBeRemoved(uid kubetypes.UID) bool
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func createDswpWithVolumeWithCustomPluginMgr(t *testing.T, pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim,
|
func createDswpWithVolumeWithCustomPluginMgr(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim,
|
||||||
fakeVolumePluginMgr *volume.VolumePluginMgr) (*desiredStateOfWorldPopulator, kubepod.Manager, cache.DesiredStateOfWorld, *containertest.FakeRuntime, *fakePodStateProvider) {
|
fakeVolumePluginMgr *volume.VolumePluginMgr) (*desiredStateOfWorldPopulator, kubepod.Manager, cache.DesiredStateOfWorld, *containertest.FakeRuntime, *fakePodStateProvider) {
|
||||||
fakeClient := &fake.Clientset{}
|
fakeClient := &fake.Clientset{}
|
||||||
fakeClient.AddReactor("get", "persistentvolumeclaims", func(action core.Action) (bool, runtime.Object, error) {
|
fakeClient.AddReactor("get", "persistentvolumeclaims", func(action core.Action) (bool, runtime.Object, error) {
|
||||||
|
@ -39,6 +39,8 @@ import (
|
|||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/volumemanager/cache"
|
"k8s.io/kubernetes/pkg/kubelet/volumemanager/cache"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
@ -188,6 +190,7 @@ func Test_Run_Positive_VolumeAttachAndMount(t *testing.T) {
|
|||||||
// Verifies there is are attach/mount/etc calls and no detach/unmount calls.
|
// Verifies there is are attach/mount/etc calls and no detach/unmount calls.
|
||||||
func Test_Run_Positive_VolumeAttachAndMountMigrationEnabled(t *testing.T) {
|
func Test_Run_Positive_VolumeAttachAndMountMigrationEnabled(t *testing.T) {
|
||||||
// Arrange
|
// Arrange
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
intreeToCSITranslator := csitrans.New()
|
intreeToCSITranslator := csitrans.New()
|
||||||
node := &v1.Node{
|
node := &v1.Node{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -254,7 +257,7 @@ func Test_Run_Positive_VolumeAttachAndMountMigrationEnabled(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
|
volumeSpec := &volume.Spec{Volume: &pod.Spec.Volumes[0]}
|
||||||
migratedSpec, err := csimigration.TranslateInTreeSpecToCSI(volumeSpec, pod.Namespace, intreeToCSITranslator)
|
migratedSpec, err := csimigration.TranslateInTreeSpecToCSI(logger, volumeSpec, pod.Namespace, intreeToCSITranslator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error while translating spec %v: %v", volumeSpec, err)
|
t.Fatalf("unexpected error while translating spec %v: %v", volumeSpec, err)
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ const (
|
|||||||
// this node and makes it so.
|
// this node and makes it so.
|
||||||
type VolumeManager interface {
|
type VolumeManager interface {
|
||||||
// Starts the volume manager and all the asynchronous loops that it controls
|
// Starts the volume manager and all the asynchronous loops that it controls
|
||||||
Run(sourcesReady config.SourcesReady, stopCh <-chan struct{})
|
Run(ctx context.Context, sourcesReady config.SourcesReady)
|
||||||
|
|
||||||
// WaitForAttachAndMount processes the volumes referenced in the specified
|
// WaitForAttachAndMount processes the volumes referenced in the specified
|
||||||
// pod and blocks until they are all attached and mounted (reflected in
|
// pod and blocks until they are all attached and mounted (reflected in
|
||||||
@ -275,23 +275,23 @@ type volumeManager struct {
|
|||||||
intreeToCSITranslator csimigration.InTreeToCSITranslator
|
intreeToCSITranslator csimigration.InTreeToCSITranslator
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *volumeManager) Run(sourcesReady config.SourcesReady, stopCh <-chan struct{}) {
|
func (vm *volumeManager) Run(ctx context.Context, sourcesReady config.SourcesReady) {
|
||||||
defer runtime.HandleCrash()
|
defer runtime.HandleCrash()
|
||||||
|
|
||||||
if vm.kubeClient != nil {
|
if vm.kubeClient != nil {
|
||||||
// start informer for CSIDriver
|
// start informer for CSIDriver
|
||||||
go vm.volumePluginMgr.Run(stopCh)
|
go vm.volumePluginMgr.Run(ctx.Done())
|
||||||
}
|
}
|
||||||
|
|
||||||
go vm.desiredStateOfWorldPopulator.Run(sourcesReady, stopCh)
|
go vm.desiredStateOfWorldPopulator.Run(ctx, sourcesReady)
|
||||||
klog.V(2).InfoS("The desired_state_of_world populator starts")
|
klog.V(2).InfoS("The desired_state_of_world populator starts")
|
||||||
|
|
||||||
klog.InfoS("Starting Kubelet Volume Manager")
|
klog.InfoS("Starting Kubelet Volume Manager")
|
||||||
go vm.reconciler.Run(stopCh)
|
go vm.reconciler.Run(ctx.Done())
|
||||||
|
|
||||||
metrics.Register(vm.actualStateOfWorld, vm.desiredStateOfWorld, vm.volumePluginMgr)
|
metrics.Register(vm.actualStateOfWorld, vm.desiredStateOfWorld, vm.volumePluginMgr)
|
||||||
|
|
||||||
<-stopCh
|
<-ctx.Done()
|
||||||
klog.InfoS("Shutting down Kubelet Volume Manager")
|
klog.InfoS("Shutting down Kubelet Volume Manager")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ func NewFakeVolumeManager(initialVolumes []v1.UniqueVolumeName) *FakeVolumeManag
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run is not implemented
|
// Run is not implemented
|
||||||
func (f *FakeVolumeManager) Run(sourcesReady config.SourcesReady, stopCh <-chan struct{}) {
|
func (f *FakeVolumeManager) Run(ctx context.Context, sourcesReady config.SourcesReady) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WaitForAttachAndMount is not implemented
|
// WaitForAttachAndMount is not implemented
|
||||||
|
@ -25,8 +25,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/mount-utils"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
kubetypes "k8s.io/apimachinery/pkg/types"
|
kubetypes "k8s.io/apimachinery/pkg/types"
|
||||||
@ -44,6 +42,8 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
|
"k8s.io/kubernetes/test/utils/ktesting"
|
||||||
|
"k8s.io/mount-utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -94,15 +94,17 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
|
|
||||||
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, node)
|
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, node)
|
||||||
|
|
||||||
stopCh := runVolumeManager(manager)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
sourcesReady := config.NewSourcesReady(func(_ sets.Set[string]) bool { return true })
|
||||||
|
go manager.Run(tCtx, sourcesReady)
|
||||||
|
|
||||||
podManager.SetPods([]*v1.Pod{pod})
|
podManager.SetPods([]*v1.Pod{pod})
|
||||||
|
|
||||||
// Fake node status update
|
// Fake node status update
|
||||||
go simulateVolumeInUseUpdate(
|
go simulateVolumeInUseUpdate(
|
||||||
v1.UniqueVolumeName(node.Status.VolumesAttached[0].Name),
|
v1.UniqueVolumeName(node.Status.VolumesAttached[0].Name),
|
||||||
stopCh,
|
tCtx.Done(),
|
||||||
manager)
|
manager)
|
||||||
|
|
||||||
err = manager.WaitForAttachAndMount(context.Background(), pod)
|
err = manager.WaitForAttachAndMount(context.Background(), pod)
|
||||||
@ -218,8 +220,10 @@ func TestWaitForAttachAndMountError(t *testing.T) {
|
|||||||
|
|
||||||
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, nil)
|
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, nil)
|
||||||
|
|
||||||
stopCh := runVolumeManager(manager)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
sourcesReady := config.NewSourcesReady(func(_ sets.Set[string]) bool { return true })
|
||||||
|
go manager.Run(tCtx, sourcesReady)
|
||||||
|
|
||||||
podManager.SetPods([]*v1.Pod{pod})
|
podManager.SetPods([]*v1.Pod{pod})
|
||||||
|
|
||||||
@ -250,15 +254,17 @@ func TestInitialPendingVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
|
|
||||||
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, node)
|
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, node)
|
||||||
|
|
||||||
stopCh := runVolumeManager(manager)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
sourcesReady := config.NewSourcesReady(func(_ sets.Set[string]) bool { return true })
|
||||||
|
go manager.Run(tCtx, sourcesReady)
|
||||||
|
|
||||||
podManager.SetPods([]*v1.Pod{pod})
|
podManager.SetPods([]*v1.Pod{pod})
|
||||||
|
|
||||||
// Fake node status update
|
// Fake node status update
|
||||||
go simulateVolumeInUseUpdate(
|
go simulateVolumeInUseUpdate(
|
||||||
v1.UniqueVolumeName(node.Status.VolumesAttached[0].Name),
|
v1.UniqueVolumeName(node.Status.VolumesAttached[0].Name),
|
||||||
stopCh,
|
tCtx.Done(),
|
||||||
manager)
|
manager)
|
||||||
|
|
||||||
// delayed claim binding
|
// delayed claim binding
|
||||||
@ -338,15 +344,17 @@ func TestGetExtraSupplementalGroupsForPod(t *testing.T) {
|
|||||||
|
|
||||||
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, node)
|
manager := newTestVolumeManager(t, tmpDir, podManager, kubeClient, node)
|
||||||
|
|
||||||
stopCh := runVolumeManager(manager)
|
tCtx := ktesting.Init(t)
|
||||||
defer close(stopCh)
|
defer tCtx.Cancel("test has completed")
|
||||||
|
sourcesReady := config.NewSourcesReady(func(_ sets.Set[string]) bool { return true })
|
||||||
|
go manager.Run(tCtx, sourcesReady)
|
||||||
|
|
||||||
podManager.SetPods([]*v1.Pod{pod})
|
podManager.SetPods([]*v1.Pod{pod})
|
||||||
|
|
||||||
// Fake node status update
|
// Fake node status update
|
||||||
go simulateVolumeInUseUpdate(
|
go simulateVolumeInUseUpdate(
|
||||||
v1.UniqueVolumeName(node.Status.VolumesAttached[0].Name),
|
v1.UniqueVolumeName(node.Status.VolumesAttached[0].Name),
|
||||||
stopCh,
|
tCtx.Done(),
|
||||||
manager)
|
manager)
|
||||||
|
|
||||||
err = manager.WaitForAttachAndMount(context.Background(), pod)
|
err = manager.WaitForAttachAndMount(context.Background(), pod)
|
||||||
@ -537,12 +545,3 @@ func delayClaimBecomesBound(
|
|||||||
}
|
}
|
||||||
kubeClient.CoreV1().PersistentVolumeClaims(namespace).Update(context.TODO(), volumeClaim, metav1.UpdateOptions{})
|
kubeClient.CoreV1().PersistentVolumeClaims(namespace).Update(context.TODO(), volumeClaim, metav1.UpdateOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func runVolumeManager(manager VolumeManager) chan struct{} {
|
|
||||||
stopCh := make(chan struct{})
|
|
||||||
//readyCh := make(chan bool, 1)
|
|
||||||
//readyCh <- true
|
|
||||||
sourcesReady := config.NewSourcesReady(func(_ sets.Set[string]) bool { return true })
|
|
||||||
go manager.Run(sourcesReady, stopCh)
|
|
||||||
return stopCh
|
|
||||||
}
|
|
||||||
|
@ -46,8 +46,8 @@ type InTreeToCSITranslator interface {
|
|||||||
IsMigratableIntreePluginByName(inTreePluginName string) bool
|
IsMigratableIntreePluginByName(inTreePluginName string) bool
|
||||||
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
||||||
GetCSINameFromInTreeName(pluginName string) (string, error)
|
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||||
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSILimits is a plugin that checks node volume limits.
|
// CSILimits is a plugin that checks node volume limits.
|
||||||
@ -293,7 +293,7 @@ func (pl *CSILimits) checkAttachableInlineVolume(logger klog.Logger, vol *v1.Vol
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// Do translation for the in-tree volume.
|
// Do translation for the in-tree volume.
|
||||||
translatedPV, err := pl.translator.TranslateInTreeInlineVolumeToCSI(vol, pod.Namespace)
|
translatedPV, err := pl.translator.TranslateInTreeInlineVolumeToCSI(logger, vol, pod.Namespace)
|
||||||
if err != nil || translatedPV == nil {
|
if err != nil || translatedPV == nil {
|
||||||
return fmt.Errorf("converting volume(%s) from inline to csi: %w", vol.Name, err)
|
return fmt.Errorf("converting volume(%s) from inline to csi: %w", vol.Name, err)
|
||||||
}
|
}
|
||||||
@ -350,7 +350,7 @@ func (pl *CSILimits) getCSIDriverInfo(logger klog.Logger, csiNode *storagev1.CSI
|
|||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
csiPV, err := pl.translator.TranslateInTreePVToCSI(pv)
|
csiPV, err := pl.translator.TranslateInTreePVToCSI(logger, pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.V(5).Info("Unable to translate in-tree volume to CSI", "err", err)
|
logger.V(5).Info("Unable to translate in-tree volume to CSI", "err", err)
|
||||||
return "", ""
|
return "", ""
|
||||||
|
@ -117,7 +117,7 @@ type PodVolumes struct {
|
|||||||
type InTreeToCSITranslator interface {
|
type InTreeToCSITranslator interface {
|
||||||
IsPVMigratable(pv *v1.PersistentVolume) bool
|
IsPVMigratable(pv *v1.PersistentVolume) bool
|
||||||
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
||||||
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SchedulerVolumeBinder is used by the scheduler VolumeBinding plugin to
|
// SchedulerVolumeBinder is used by the scheduler VolumeBinding plugin to
|
||||||
@ -673,7 +673,7 @@ func (b *volumeBinder) checkBindings(logger klog.Logger, pod *v1.Pod, bindings [
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pv, err = b.tryTranslatePVToCSI(pv, csiNode)
|
pv, err = b.tryTranslatePVToCSI(logger, pv, csiNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("failed to translate pv to csi: %w", err)
|
return false, fmt.Errorf("failed to translate pv to csi: %w", err)
|
||||||
}
|
}
|
||||||
@ -732,7 +732,7 @@ func (b *volumeBinder) checkBindings(logger klog.Logger, pod *v1.Pod, bindings [
|
|||||||
return false, fmt.Errorf("failed to get pv %q from cache: %w", pvc.Spec.VolumeName, err)
|
return false, fmt.Errorf("failed to get pv %q from cache: %w", pvc.Spec.VolumeName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pv, err = b.tryTranslatePVToCSI(pv, csiNode)
|
pv, err = b.tryTranslatePVToCSI(logger, pv, csiNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -881,7 +881,7 @@ func (b *volumeBinder) checkBoundClaims(logger klog.Logger, claims []*v1.Persist
|
|||||||
return true, false, err
|
return true, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pv, err = b.tryTranslatePVToCSI(pv, csiNode)
|
pv, err = b.tryTranslatePVToCSI(logger, pv, csiNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, true, err
|
return false, true, err
|
||||||
}
|
}
|
||||||
@ -1128,7 +1128,7 @@ func isPluginMigratedToCSIOnNode(pluginName string, csiNode *storagev1.CSINode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tryTranslatePVToCSI will translate the in-tree PV to CSI if it meets the criteria. If not, it returns the unmodified in-tree PV.
|
// tryTranslatePVToCSI will translate the in-tree PV to CSI if it meets the criteria. If not, it returns the unmodified in-tree PV.
|
||||||
func (b *volumeBinder) tryTranslatePVToCSI(pv *v1.PersistentVolume, csiNode *storagev1.CSINode) (*v1.PersistentVolume, error) {
|
func (b *volumeBinder) tryTranslatePVToCSI(logger klog.Logger, pv *v1.PersistentVolume, csiNode *storagev1.CSINode) (*v1.PersistentVolume, error) {
|
||||||
if !b.translator.IsPVMigratable(pv) {
|
if !b.translator.IsPVMigratable(pv) {
|
||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
@ -1146,7 +1146,7 @@ func (b *volumeBinder) tryTranslatePVToCSI(pv *v1.PersistentVolume, csiNode *sto
|
|||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
transPV, err := b.translator.TranslateInTreePVToCSI(pv)
|
transPV, err := b.translator.TranslateInTreePVToCSI(logger, pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not translate pv: %v", err)
|
return nil, fmt.Errorf("could not translate pv: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
csilibplugins "k8s.io/csi-translation-lib/plugins"
|
csilibplugins "k8s.io/csi-translation-lib/plugins"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
)
|
)
|
||||||
@ -123,20 +124,20 @@ func (pm PluginManager) IsMigratable(spec *volume.Spec) (bool, error) {
|
|||||||
// InTreeToCSITranslator performs translation of Volume sources for PV and Volume objects
|
// InTreeToCSITranslator performs translation of Volume sources for PV and Volume objects
|
||||||
// from references to in-tree plugins to migrated CSI plugins
|
// from references to in-tree plugins to migrated CSI plugins
|
||||||
type InTreeToCSITranslator interface {
|
type InTreeToCSITranslator interface {
|
||||||
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeSpecToCSI translates a volume spec (either PV or inline volume)
|
// TranslateInTreeSpecToCSI translates a volume spec (either PV or inline volume)
|
||||||
// supported by an in-tree plugin to CSI
|
// supported by an in-tree plugin to CSI
|
||||||
func TranslateInTreeSpecToCSI(spec *volume.Spec, podNamespace string, translator InTreeToCSITranslator) (*volume.Spec, error) {
|
func TranslateInTreeSpecToCSI(logger klog.Logger, spec *volume.Spec, podNamespace string, translator InTreeToCSITranslator) (*volume.Spec, error) {
|
||||||
var csiPV *v1.PersistentVolume
|
var csiPV *v1.PersistentVolume
|
||||||
var err error
|
var err error
|
||||||
inlineVolume := false
|
inlineVolume := false
|
||||||
if spec.PersistentVolume != nil {
|
if spec.PersistentVolume != nil {
|
||||||
csiPV, err = translator.TranslateInTreePVToCSI(spec.PersistentVolume)
|
csiPV, err = translator.TranslateInTreePVToCSI(logger, spec.PersistentVolume)
|
||||||
} else if spec.Volume != nil {
|
} else if spec.Volume != nil {
|
||||||
csiPV, err = translator.TranslateInTreeInlineVolumeToCSI(spec.Volume, podNamespace)
|
csiPV, err = translator.TranslateInTreeInlineVolumeToCSI(logger, spec.Volume, podNamespace)
|
||||||
inlineVolume = true
|
inlineVolume = true
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("not a valid volume spec")
|
err = errors.New("not a valid volume spec")
|
||||||
|
@ -63,8 +63,8 @@ type InTreeToCSITranslator interface {
|
|||||||
IsMigratableIntreePluginByName(inTreePluginName string) bool
|
IsMigratableIntreePluginByName(inTreePluginName string) bool
|
||||||
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error)
|
||||||
GetCSINameFromInTreeName(pluginName string) (string, error)
|
GetCSINameFromInTreeName(pluginName string) (string, error)
|
||||||
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ OperationGenerator = &operationGenerator{}
|
var _ OperationGenerator = &operationGenerator{}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
storage "k8s.io/api/storage/v1"
|
storage "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/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -57,7 +58,7 @@ func NewAWSElasticBlockStoreCSITranslator() InTreePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI translates InTree EBS storage class parameters to CSI storage class
|
// TranslateInTreeStorageClassToCSI translates InTree EBS storage class parameters to CSI storage class
|
||||||
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
var (
|
var (
|
||||||
generatedTopologies []v1.TopologySelectorTerm
|
generatedTopologies []v1.TopologySelectorTerm
|
||||||
params = map[string]string{}
|
params = map[string]string{}
|
||||||
@ -100,7 +101,7 @@ func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeStorageClassToCSI(sc
|
|||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a Volume with AWSElasticBlockStore set from in-tree
|
// TranslateInTreeInlineVolumeToCSI takes a Volume with AWSElasticBlockStore set from in-tree
|
||||||
// and converts the AWSElasticBlockStore source to a CSIPersistentVolumeSource
|
// and converts the AWSElasticBlockStore source to a CSIPersistentVolumeSource
|
||||||
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.AWSElasticBlockStore == nil {
|
if volume == nil || volume.AWSElasticBlockStore == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or AWS EBS not defined on volume")
|
return nil, fmt.Errorf("volume is nil or AWS EBS not defined on volume")
|
||||||
}
|
}
|
||||||
@ -135,7 +136,7 @@ func (t *awsElasticBlockStoreCSITranslator) TranslateInTreeInlineVolumeToCSI(vol
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a PV with AWSElasticBlockStore set from in-tree
|
// TranslateInTreePVToCSI takes a PV with AWSElasticBlockStore set from in-tree
|
||||||
// and converts the AWSElasticBlockStore source to a CSIPersistentVolumeSource
|
// and converts the AWSElasticBlockStore source to a CSIPersistentVolumeSource
|
||||||
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (t *awsElasticBlockStoreCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.AWSElasticBlockStore == nil {
|
if pv == nil || pv.Spec.AWSElasticBlockStore == nil {
|
||||||
return nil, fmt.Errorf("pv is nil or AWS EBS not defined on pv")
|
return nil, fmt.Errorf("pv is nil or AWS EBS not defined on pv")
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,9 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -79,6 +82,7 @@ func TestKubernetesVolumeIDToEBSVolumeID(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateEBSInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslateEBSInTreeStorageClassToCSI(t *testing.T) {
|
||||||
translator := NewAWSElasticBlockStoreCSITranslator()
|
translator := NewAWSElasticBlockStoreCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -111,7 +115,7 @@ func TestTranslateEBSInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeStorageClassToCSI(tc.sc)
|
got, err := translator.TranslateInTreeStorageClassToCSI(logger, tc.sc)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -129,6 +133,7 @@ func TestTranslateEBSInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateInTreeInlineVolumeToCSI(t *testing.T) {
|
func TestTranslateInTreeInlineVolumeToCSI(t *testing.T) {
|
||||||
translator := NewAWSElasticBlockStoreCSITranslator()
|
translator := NewAWSElasticBlockStoreCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -182,7 +187,7 @@ func TestTranslateInTreeInlineVolumeToCSI(t *testing.T) {
|
|||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeInlineVolumeToCSI(&v1.Volume{Name: "volume", VolumeSource: tc.volumeSource}, "")
|
got, err := translator.TranslateInTreeInlineVolumeToCSI(logger, &v1.Volume{Name: "volume", VolumeSource: tc.volumeSource}, "")
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Fatalf("Did not expect error but got: %v", err)
|
t.Fatalf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -60,7 +61,7 @@ func NewAzureDiskCSITranslator() InTreePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI translates InTree Azure Disk storage class parameters to CSI storage class
|
// TranslateInTreeStorageClassToCSI translates InTree Azure Disk storage class parameters to CSI storage class
|
||||||
func (t *azureDiskCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (t *azureDiskCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
var (
|
var (
|
||||||
generatedTopologies []v1.TopologySelectorTerm
|
generatedTopologies []v1.TopologySelectorTerm
|
||||||
params = map[string]string{}
|
params = map[string]string{}
|
||||||
@ -96,7 +97,7 @@ func (t *azureDiskCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.St
|
|||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a Volume with AzureDisk set from in-tree
|
// TranslateInTreeInlineVolumeToCSI takes a Volume with AzureDisk set from in-tree
|
||||||
// and converts the AzureDisk source to a CSIPersistentVolumeSource
|
// and converts the AzureDisk source to a CSIPersistentVolumeSource
|
||||||
func (t *azureDiskCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (t *azureDiskCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.AzureDisk == nil {
|
if volume == nil || volume.AzureDisk == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or Azure Disk not defined on volume")
|
return nil, fmt.Errorf("volume is nil or Azure Disk not defined on volume")
|
||||||
}
|
}
|
||||||
@ -140,7 +141,7 @@ func (t *azureDiskCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Vol
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a PV with AzureDisk set from in-tree
|
// TranslateInTreePVToCSI takes a PV with AzureDisk set from in-tree
|
||||||
// and converts the AzureDisk source to a CSIPersistentVolumeSource
|
// and converts the AzureDisk source to a CSIPersistentVolumeSource
|
||||||
func (t *azureDiskCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (t *azureDiskCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.AzureDisk == nil {
|
if pv == nil || pv.Spec.AzureDisk == nil {
|
||||||
return nil, fmt.Errorf("pv is nil or Azure Disk source not defined on pv")
|
return nil, fmt.Errorf("pv is nil or Azure Disk source not defined on pv")
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ import (
|
|||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIsManagedDisk(t *testing.T) {
|
func TestIsManagedDisk(t *testing.T) {
|
||||||
@ -99,6 +101,7 @@ func TestGetDiskName(t *testing.T) {
|
|||||||
func TestTranslateAzureDiskInTreeInlineVolumeToCSI(t *testing.T) {
|
func TestTranslateAzureDiskInTreeInlineVolumeToCSI(t *testing.T) {
|
||||||
sharedBlobDiskKind := corev1.AzureDedicatedBlobDisk
|
sharedBlobDiskKind := corev1.AzureDedicatedBlobDisk
|
||||||
translator := NewAzureDiskCSITranslator()
|
translator := NewAzureDiskCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -158,7 +161,7 @@ func TestTranslateAzureDiskInTreeInlineVolumeToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeInlineVolumeToCSI(tc.volume, "")
|
got, err := translator.TranslateInTreeInlineVolumeToCSI(logger, tc.volume, "")
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -175,6 +178,7 @@ func TestTranslateAzureDiskInTreeInlineVolumeToCSI(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateAzureDiskInTreePVToCSI(t *testing.T) {
|
func TestTranslateAzureDiskInTreePVToCSI(t *testing.T) {
|
||||||
translator := NewAzureDiskCSITranslator()
|
translator := NewAzureDiskCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
sharedBlobDiskKind := corev1.AzureDedicatedBlobDisk
|
sharedBlobDiskKind := corev1.AzureDedicatedBlobDisk
|
||||||
cachingMode := corev1.AzureDataDiskCachingMode("cachingmode")
|
cachingMode := corev1.AzureDataDiskCachingMode("cachingmode")
|
||||||
@ -250,7 +254,7 @@ func TestTranslateAzureDiskInTreePVToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreePVToCSI(tc.volume)
|
got, err := translator.TranslateInTreePVToCSI(logger, tc.volume)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -447,6 +451,7 @@ func TestTranslateTranslateCSIPVToInTree(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslateInTreeStorageClassToCSI(t *testing.T) {
|
||||||
translator := NewAzureDiskCSITranslator()
|
translator := NewAzureDiskCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
name string
|
name string
|
||||||
@ -513,7 +518,7 @@ func TestTranslateInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
gotOptions, err := translator.TranslateInTreeStorageClassToCSI(tc.options)
|
gotOptions, err := translator.TranslateInTreeStorageClassToCSI(logger, tc.options)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -59,13 +59,13 @@ func NewAzureFileCSITranslator() InTreePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI translates InTree Azure File storage class parameters to CSI storage class
|
// TranslateInTreeStorageClassToCSI translates InTree Azure File storage class parameters to CSI storage class
|
||||||
func (t *azureFileCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (t *azureFileCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
return sc, nil
|
return sc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a Volume with AzureFile set from in-tree
|
// TranslateInTreeInlineVolumeToCSI takes a Volume with AzureFile set from in-tree
|
||||||
// and converts the AzureFile source to a CSIPersistentVolumeSource
|
// and converts the AzureFile source to a CSIPersistentVolumeSource
|
||||||
func (t *azureFileCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (t *azureFileCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.AzureFile == nil {
|
if volume == nil || volume.AzureFile == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or Azure File not defined on volume")
|
return nil, fmt.Errorf("volume is nil or Azure File not defined on volume")
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ func (t *azureFileCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Vol
|
|||||||
azureSource := volume.AzureFile
|
azureSource := volume.AzureFile
|
||||||
accountName, err := getStorageAccountName(azureSource.SecretName)
|
accountName, err := getStorageAccountName(azureSource.SecretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(5).Infof("getStorageAccountName(%s) returned with error: %v", azureSource.SecretName, err)
|
logger.V(5).Info("getStorageAccountName returned with error", "secretName", azureSource.SecretName, "err", err)
|
||||||
accountName = azureSource.SecretName
|
accountName = azureSource.SecretName
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ func (t *azureFileCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Vol
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a PV with AzureFile set from in-tree
|
// TranslateInTreePVToCSI takes a PV with AzureFile set from in-tree
|
||||||
// and converts the AzureFile source to a CSIPersistentVolumeSource
|
// and converts the AzureFile source to a CSIPersistentVolumeSource
|
||||||
func (t *azureFileCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (t *azureFileCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.AzureFile == nil {
|
if pv == nil || pv.Spec.AzureFile == nil {
|
||||||
return nil, fmt.Errorf("pv is nil or Azure File source not defined on pv")
|
return nil, fmt.Errorf("pv is nil or Azure File source not defined on pv")
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ func (t *azureFileCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume)
|
|||||||
azureSource := pv.Spec.PersistentVolumeSource.AzureFile
|
azureSource := pv.Spec.PersistentVolumeSource.AzureFile
|
||||||
accountName, err := getStorageAccountName(azureSource.SecretName)
|
accountName, err := getStorageAccountName(azureSource.SecretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.V(5).Infof("getStorageAccountName(%s) returned with error: %v", azureSource.SecretName, err)
|
logger.V(5).Info("getStorageAccountName returned with error", "secretName", azureSource.SecretName, "err", err)
|
||||||
accountName = azureSource.SecretName
|
accountName = azureSource.SecretName
|
||||||
}
|
}
|
||||||
resourceGroup := ""
|
resourceGroup := ""
|
||||||
|
@ -23,6 +23,8 @@ import (
|
|||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -100,6 +102,7 @@ func TestGetFileShareInfo(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateAzureFileInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslateAzureFileInTreeStorageClassToCSI(t *testing.T) {
|
||||||
translator := NewAzureFileCSITranslator()
|
translator := NewAzureFileCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -188,7 +191,7 @@ func TestTranslateAzureFileInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeInlineVolumeToCSI(tc.volume, tc.podNamespace)
|
got, err := translator.TranslateInTreeInlineVolumeToCSI(logger, tc.volume, tc.podNamespace)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -205,6 +208,7 @@ func TestTranslateAzureFileInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateAzureFileInTreePVToCSI(t *testing.T) {
|
func TestTranslateAzureFileInTreePVToCSI(t *testing.T) {
|
||||||
translator := NewAzureFileCSITranslator()
|
translator := NewAzureFileCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
secretNamespace := "secretnamespace"
|
secretNamespace := "secretnamespace"
|
||||||
|
|
||||||
@ -367,7 +371,7 @@ func TestTranslateAzureFileInTreePVToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreePVToCSI(tc.volume)
|
got, err := translator.TranslateInTreePVToCSI(logger, tc.volume)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
storage "k8s.io/api/storage/v1"
|
storage "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/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -78,7 +79,7 @@ func generateToplogySelectors(key string, values []string) []v1.TopologySelector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI translates InTree GCE storage class parameters to CSI storage class
|
// TranslateInTreeStorageClassToCSI translates InTree GCE storage class parameters to CSI storage class
|
||||||
func (g *gcePersistentDiskCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (g *gcePersistentDiskCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
var generatedTopologies []v1.TopologySelectorTerm
|
var generatedTopologies []v1.TopologySelectorTerm
|
||||||
|
|
||||||
np := map[string]string{}
|
np := map[string]string{}
|
||||||
@ -162,7 +163,7 @@ func backwardCompatibleAccessModes(ams []v1.PersistentVolumeAccessMode) []v1.Per
|
|||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a Volume with GCEPersistentDisk set from in-tree
|
// TranslateInTreeInlineVolumeToCSI takes a Volume with GCEPersistentDisk set from in-tree
|
||||||
// and converts the GCEPersistentDisk source to a CSIPersistentVolumeSource
|
// and converts the GCEPersistentDisk source to a CSIPersistentVolumeSource
|
||||||
func (g *gcePersistentDiskCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (g *gcePersistentDiskCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.GCEPersistentDisk == nil {
|
if volume == nil || volume.GCEPersistentDisk == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or GCE PD not defined on volume")
|
return nil, fmt.Errorf("volume is nil or GCE PD not defined on volume")
|
||||||
}
|
}
|
||||||
@ -208,7 +209,7 @@ func (g *gcePersistentDiskCSITranslator) TranslateInTreeInlineVolumeToCSI(volume
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a PV with GCEPersistentDisk set from in-tree
|
// TranslateInTreePVToCSI takes a PV with GCEPersistentDisk set from in-tree
|
||||||
// and converts the GCEPersistentDisk source to a CSIPersistentVolumeSource
|
// and converts the GCEPersistentDisk source to a CSIPersistentVolumeSource
|
||||||
func (g *gcePersistentDiskCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (g *gcePersistentDiskCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
var volID string
|
var volID string
|
||||||
|
|
||||||
if pv == nil || pv.Spec.GCEPersistentDisk == nil {
|
if pv == nil || pv.Spec.GCEPersistentDisk == nil {
|
||||||
|
@ -24,6 +24,8 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewStorageClass(params map[string]string, allowedTopologies []v1.TopologySelectorTerm) *storage.StorageClass {
|
func NewStorageClass(params map[string]string, allowedTopologies []v1.TopologySelectorTerm) *storage.StorageClass {
|
||||||
@ -35,6 +37,7 @@ func NewStorageClass(params map[string]string, allowedTopologies []v1.TopologySe
|
|||||||
|
|
||||||
func TestTranslatePDInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslatePDInTreeStorageClassToCSI(t *testing.T) {
|
||||||
g := NewGCEPersistentDiskCSITranslator()
|
g := NewGCEPersistentDiskCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
name string
|
name string
|
||||||
@ -86,7 +89,7 @@ func TestTranslatePDInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
gotOptions, err := g.TranslateInTreeStorageClassToCSI(tc.options)
|
gotOptions, err := g.TranslateInTreeStorageClassToCSI(logger, tc.options)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -266,7 +269,8 @@ func TestBackwardCompatibleAccessModes(t *testing.T) {
|
|||||||
|
|
||||||
func TestInlineReadOnly(t *testing.T) {
|
func TestInlineReadOnly(t *testing.T) {
|
||||||
g := NewGCEPersistentDiskCSITranslator()
|
g := NewGCEPersistentDiskCSITranslator()
|
||||||
pv, err := g.TranslateInTreeInlineVolumeToCSI(&v1.Volume{
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
pv, err := g.TranslateInTreeInlineVolumeToCSI(logger, &v1.Volume{
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
|
||||||
PDName: "foo",
|
PDName: "foo",
|
||||||
@ -298,6 +302,7 @@ func TestInlineReadOnly(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateInTreePVToCSIVolIDFmt(t *testing.T) {
|
func TestTranslateInTreePVToCSIVolIDFmt(t *testing.T) {
|
||||||
g := NewGCEPersistentDiskCSITranslator()
|
g := NewGCEPersistentDiskCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
pdName := "pd-name"
|
pdName := "pd-name"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
desc string
|
desc string
|
||||||
@ -332,7 +337,7 @@ func TestTranslateInTreePVToCSIVolIDFmt(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.desc, func(t *testing.T) {
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
translatedPV, err := g.TranslateInTreePVToCSI(&v1.PersistentVolume{
|
translatedPV, err := g.TranslateInTreePVToCSI(logger, &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Labels: map[string]string{tc.topologyLabelKey: tc.topologyLabelValue},
|
Labels: map[string]string{tc.topologyLabelKey: tc.topologyLabelValue},
|
||||||
},
|
},
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InTreePlugin handles translations between CSI and in-tree sources in a PV
|
// InTreePlugin handles translations between CSI and in-tree sources in a PV
|
||||||
@ -32,17 +33,17 @@ type InTreePlugin interface {
|
|||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI takes in-tree volume options
|
// TranslateInTreeStorageClassToCSI takes in-tree volume options
|
||||||
// and translates them to a volume options consumable by CSI plugin
|
// and translates them to a volume options consumable by CSI plugin
|
||||||
TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error)
|
TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error)
|
||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
||||||
// the in-tree inline volume source to a CSIPersistentVolumeSource
|
// the in-tree inline volume source to a CSIPersistentVolumeSource
|
||||||
// A PV object containing the CSIPersistentVolumeSource in it's spec is returned
|
// A PV object containing the CSIPersistentVolumeSource in it's spec is returned
|
||||||
// podNamespace is only needed for azurefile to fetch secret namespace, no need to be set for other plugins.
|
// podNamespace is only needed for azurefile to fetch secret namespace, no need to be set for other plugins.
|
||||||
TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error)
|
||||||
|
|
||||||
// TranslateInTreePVToCSI takes a persistent volume and will translate
|
// TranslateInTreePVToCSI takes a persistent volume and will translate
|
||||||
// the in-tree pv source to a CSI Source. The input persistent volume can be modified
|
// the in-tree pv source to a CSI Source. The input persistent volume can be modified
|
||||||
TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error)
|
||||||
|
|
||||||
// TranslateCSIPVToInTree takes a PV with a CSI PersistentVolume Source and will translate
|
// TranslateCSIPVToInTree takes a PV with a CSI PersistentVolume Source and will translate
|
||||||
// it to a in-tree Persistent Volume Source for the in-tree volume
|
// it to a in-tree Persistent Volume Source for the in-tree volume
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -45,7 +46,7 @@ func NewOpenStackCinderCSITranslator() InTreePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI translates InTree Cinder storage class parameters to CSI storage class
|
// TranslateInTreeStorageClassToCSI translates InTree Cinder storage class parameters to CSI storage class
|
||||||
func (t *osCinderCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (t *osCinderCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
var (
|
var (
|
||||||
params = map[string]string{}
|
params = map[string]string{}
|
||||||
)
|
)
|
||||||
@ -75,7 +76,7 @@ func (t *osCinderCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.Sto
|
|||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a Volume with Cinder set from in-tree
|
// TranslateInTreeInlineVolumeToCSI takes a Volume with Cinder set from in-tree
|
||||||
// and converts the Cinder source to a CSIPersistentVolumeSource
|
// and converts the Cinder source to a CSIPersistentVolumeSource
|
||||||
func (t *osCinderCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (t *osCinderCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.Cinder == nil {
|
if volume == nil || volume.Cinder == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or Cinder not defined on volume")
|
return nil, fmt.Errorf("volume is nil or Cinder not defined on volume")
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ func (t *osCinderCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volu
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a PV with Cinder set from in-tree
|
// TranslateInTreePVToCSI takes a PV with Cinder set from in-tree
|
||||||
// and converts the Cinder source to a CSIPersistentVolumeSource
|
// and converts the Cinder source to a CSIPersistentVolumeSource
|
||||||
func (t *osCinderCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (t *osCinderCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.Cinder == nil {
|
if pv == nil || pv.Spec.Cinder == nil {
|
||||||
return nil, fmt.Errorf("pv is nil or Cinder not defined on pv")
|
return nil, fmt.Errorf("pv is nil or Cinder not defined on pv")
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,13 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTranslateCinderInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslateCinderInTreeStorageClassToCSI(t *testing.T) {
|
||||||
translator := NewOpenStackCinderCSITranslator()
|
translator := NewOpenStackCinderCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -63,7 +66,7 @@ func TestTranslateCinderInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeStorageClassToCSI(tc.sc)
|
got, err := translator.TranslateInTreeStorageClassToCSI(logger, tc.sc)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,10 @@ package plugins
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storagev1 "k8s.io/api/storage/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/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -39,7 +40,7 @@ func NewPortworxCSITranslator() InTreePlugin {
|
|||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI takes in-tree storage class used by in-tree plugin
|
// TranslateInTreeStorageClassToCSI takes in-tree storage class used by in-tree plugin
|
||||||
// and translates them to a storageclass consumable by CSI plugin
|
// and translates them to a storageclass consumable by CSI plugin
|
||||||
func (p portworxCSITranslator) TranslateInTreeStorageClassToCSI(sc *storagev1.StorageClass) (*storagev1.StorageClass, error) {
|
func (p portworxCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storagev1.StorageClass) (*storagev1.StorageClass, error) {
|
||||||
if sc == nil {
|
if sc == nil {
|
||||||
return nil, fmt.Errorf("sc is nil")
|
return nil, fmt.Errorf("sc is nil")
|
||||||
}
|
}
|
||||||
@ -49,7 +50,7 @@ func (p portworxCSITranslator) TranslateInTreeStorageClassToCSI(sc *storagev1.St
|
|||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
||||||
// the in-tree inline volume source to a CSIPersistentVolumeSource
|
// the in-tree inline volume source to a CSIPersistentVolumeSource
|
||||||
func (p portworxCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (p portworxCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.PortworxVolume == nil {
|
if volume == nil || volume.PortworxVolume == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or PortworxVolume not defined on volume")
|
return nil, fmt.Errorf("volume is nil or PortworxVolume not defined on volume")
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ func (p portworxCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volum
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a Portworx persistent volume and will translate
|
// TranslateInTreePVToCSI takes a Portworx persistent volume and will translate
|
||||||
// the in-tree pv source to a CSI Source
|
// the in-tree pv source to a CSI Source
|
||||||
func (p portworxCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (p portworxCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.PortworxVolume == nil {
|
if pv == nil || pv.Spec.PortworxVolume == nil {
|
||||||
return nil, fmt.Errorf("pv is nil or PortworxVolume not defined on pv")
|
return nil, fmt.Errorf("pv is nil or PortworxVolume not defined on pv")
|
||||||
}
|
}
|
||||||
|
@ -17,15 +17,19 @@ limitations under the License.
|
|||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"reflect"
|
"k8s.io/klog/v2/ktesting"
|
||||||
"testing"
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTranslatePortworxInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslatePortworxInTreeStorageClassToCSI(t *testing.T) {
|
||||||
translator := NewPortworxCSITranslator()
|
translator := NewPortworxCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
inTreeSC *storage.StorageClass
|
inTreeSC *storage.StorageClass
|
||||||
@ -71,7 +75,7 @@ func TestTranslatePortworxInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
result, err := translator.TranslateInTreeStorageClassToCSI(tc.inTreeSC)
|
result, err := translator.TranslateInTreeStorageClassToCSI(logger, tc.inTreeSC)
|
||||||
if err != nil && !tc.errorExp {
|
if err != nil && !tc.errorExp {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -86,6 +90,8 @@ func TestTranslatePortworxInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslatePortworxInTreeInlineVolumeToCSI(t *testing.T) {
|
func TestTranslatePortworxInTreeInlineVolumeToCSI(t *testing.T) {
|
||||||
translator := NewPortworxCSITranslator()
|
translator := NewPortworxCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
inLine *v1.Volume
|
inLine *v1.Volume
|
||||||
@ -136,7 +142,7 @@ func TestTranslatePortworxInTreeInlineVolumeToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
result, err := translator.TranslateInTreeInlineVolumeToCSI(tc.inLine, "ns")
|
result, err := translator.TranslateInTreeInlineVolumeToCSI(logger, tc.inLine, "ns")
|
||||||
if err != nil && !tc.errExpected {
|
if err != nil && !tc.errExpected {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -151,6 +157,7 @@ func TestTranslatePortworxInTreeInlineVolumeToCSI(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslatePortworxInTreePVToCSI(t *testing.T) {
|
func TestTranslatePortworxInTreePVToCSI(t *testing.T) {
|
||||||
translator := NewPortworxCSITranslator()
|
translator := NewPortworxCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -234,7 +241,7 @@ func TestTranslatePortworxInTreePVToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
result, err := translator.TranslateInTreePVToCSI(tc.inTree)
|
result, err := translator.TranslateInTreePVToCSI(logger, tc.inTree)
|
||||||
if err != nil && !tc.errExpected {
|
if err != nil && !tc.errExpected {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ func NewvSphereCSITranslator() InTreePlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI translates InTree vSphere storage class parameters to CSI storage class
|
// TranslateInTreeStorageClassToCSI translates InTree vSphere storage class parameters to CSI storage class
|
||||||
func (t *vSphereCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (t *vSphereCSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
if sc == nil {
|
if sc == nil {
|
||||||
return nil, fmt.Errorf("sc is nil")
|
return nil, fmt.Errorf("sc is nil")
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ func (t *vSphereCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.Stor
|
|||||||
case "iopslimit":
|
case "iopslimit":
|
||||||
params[paramIopslimit] = v
|
params[paramIopslimit] = v
|
||||||
default:
|
default:
|
||||||
klog.V(2).Infof("StorageClass parameter [name:%q, value:%q] is not supported", k, v)
|
logger.V(2).Info("StorageClass parameter is not supported", "name", k, "value", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ func (t *vSphereCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.Stor
|
|||||||
|
|
||||||
// TranslateInTreeInlineVolumeToCSI takes a Volume with VsphereVolume set from in-tree
|
// TranslateInTreeInlineVolumeToCSI takes a Volume with VsphereVolume set from in-tree
|
||||||
// and converts the VsphereVolume source to a CSIPersistentVolumeSource
|
// and converts the VsphereVolume source to a CSIPersistentVolumeSource
|
||||||
func (t *vSphereCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (t *vSphereCSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil || volume.VsphereVolume == nil {
|
if volume == nil || volume.VsphereVolume == nil {
|
||||||
return nil, fmt.Errorf("volume is nil or VsphereVolume not defined on volume")
|
return nil, fmt.Errorf("volume is nil or VsphereVolume not defined on volume")
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ func (t *vSphereCSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volum
|
|||||||
|
|
||||||
// TranslateInTreePVToCSI takes a PV with VsphereVolume set from in-tree
|
// TranslateInTreePVToCSI takes a PV with VsphereVolume set from in-tree
|
||||||
// and converts the VsphereVolume source to a CSIPersistentVolumeSource
|
// and converts the VsphereVolume source to a CSIPersistentVolumeSource
|
||||||
func (t *vSphereCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (t *vSphereCSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil || pv.Spec.VsphereVolume == nil {
|
if pv == nil || pv.Spec.VsphereVolume == nil {
|
||||||
return nil, fmt.Errorf("pv is nil or VsphereVolume not defined on pv")
|
return nil, fmt.Errorf("pv is nil or VsphereVolume not defined on pv")
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,13 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTranslatevSphereInTreeStorageClassToCSI(t *testing.T) {
|
func TestTranslatevSphereInTreeStorageClassToCSI(t *testing.T) {
|
||||||
translator := NewvSphereCSITranslator()
|
translator := NewvSphereCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
topologySelectorTerm := v1.TopologySelectorTerm{MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
topologySelectorTerm := v1.TopologySelectorTerm{MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||||
{
|
{
|
||||||
Key: v1.LabelTopologyZone,
|
Key: v1.LabelTopologyZone,
|
||||||
@ -111,7 +114,7 @@ func TestTranslatevSphereInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeStorageClassToCSI(tc.sc)
|
got, err := translator.TranslateInTreeStorageClassToCSI(logger, tc.sc)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -291,6 +294,7 @@ func TestTranslateVSphereCSIPVToInTree(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslateVSphereInTreePVToCSI(t *testing.T) {
|
func TestTranslateVSphereInTreePVToCSI(t *testing.T) {
|
||||||
translator := NewvSphereCSITranslator()
|
translator := NewvSphereCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
intreePV *v1.PersistentVolume
|
intreePV *v1.PersistentVolume
|
||||||
@ -462,7 +466,7 @@ func TestTranslateVSphereInTreePVToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreePVToCSI(tc.intreePV)
|
got, err := translator.TranslateInTreePVToCSI(logger, tc.intreePV)
|
||||||
if err != nil && !tc.expErr {
|
if err != nil && !tc.expErr {
|
||||||
t.Errorf("Did not expect error but got: %v", err)
|
t.Errorf("Did not expect error but got: %v", err)
|
||||||
}
|
}
|
||||||
@ -479,6 +483,7 @@ func TestTranslateVSphereInTreePVToCSI(t *testing.T) {
|
|||||||
|
|
||||||
func TestTranslatevSphereInTreeInlineVolumeToCSI(t *testing.T) {
|
func TestTranslatevSphereInTreeInlineVolumeToCSI(t *testing.T) {
|
||||||
translator := NewvSphereCSITranslator()
|
translator := NewvSphereCSITranslator()
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
inlinevolume *v1.Volume
|
inlinevolume *v1.Volume
|
||||||
@ -523,7 +528,7 @@ func TestTranslatevSphereInTreeInlineVolumeToCSI(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Logf("Testing %v", tc.name)
|
t.Logf("Testing %v", tc.name)
|
||||||
got, err := translator.TranslateInTreeInlineVolumeToCSI(tc.inlinevolume, "")
|
got, err := translator.TranslateInTreeInlineVolumeToCSI(logger, tc.inlinevolume, "")
|
||||||
if err == nil && tc.expErr {
|
if err == nil && tc.expErr {
|
||||||
t.Errorf("Expected error, but did not get one.")
|
t.Errorf("Expected error, but did not get one.")
|
||||||
continue
|
continue
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
"k8s.io/csi-translation-lib/plugins"
|
"k8s.io/csi-translation-lib/plugins"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -50,11 +51,11 @@ func New() CSITranslator {
|
|||||||
|
|
||||||
// TranslateInTreeStorageClassToCSI takes in-tree Storage Class
|
// TranslateInTreeStorageClassToCSI takes in-tree Storage Class
|
||||||
// and translates it to a set of parameters consumable by CSI plugin
|
// and translates it to a set of parameters consumable by CSI plugin
|
||||||
func (CSITranslator) TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
func (CSITranslator) TranslateInTreeStorageClassToCSI(logger klog.Logger, inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) {
|
||||||
newSC := sc.DeepCopy()
|
newSC := sc.DeepCopy()
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if inTreePluginName == curPlugin.GetInTreePluginName() {
|
if inTreePluginName == curPlugin.GetInTreePluginName() {
|
||||||
return curPlugin.TranslateInTreeStorageClassToCSI(newSC)
|
return curPlugin.TranslateInTreeStorageClassToCSI(logger, newSC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("could not find in-tree storage class parameter translation logic for %#v", inTreePluginName)
|
return nil, fmt.Errorf("could not find in-tree storage class parameter translation logic for %#v", inTreePluginName)
|
||||||
@ -63,13 +64,13 @@ func (CSITranslator) TranslateInTreeStorageClassToCSI(inTreePluginName string, s
|
|||||||
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
|
||||||
// the in-tree volume source to a CSIPersistentVolumeSource (wrapped in a PV)
|
// the in-tree volume source to a CSIPersistentVolumeSource (wrapped in a PV)
|
||||||
// if the translation logic has been implemented.
|
// if the translation logic has been implemented.
|
||||||
func (CSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
func (CSITranslator) TranslateInTreeInlineVolumeToCSI(logger klog.Logger, volume *v1.Volume, podNamespace string) (*v1.PersistentVolume, error) {
|
||||||
if volume == nil {
|
if volume == nil {
|
||||||
return nil, fmt.Errorf("persistent volume was nil")
|
return nil, fmt.Errorf("persistent volume was nil")
|
||||||
}
|
}
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.CanSupportInline(volume) {
|
if curPlugin.CanSupportInline(volume) {
|
||||||
pv, err := curPlugin.TranslateInTreeInlineVolumeToCSI(volume, podNamespace)
|
pv, err := curPlugin.TranslateInTreeInlineVolumeToCSI(logger, volume, podNamespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -92,14 +93,14 @@ func (CSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume, podName
|
|||||||
// the in-tree source to a CSI Source if the translation logic
|
// the in-tree source to a CSI Source if the translation logic
|
||||||
// has been implemented. The input persistent volume will not
|
// has been implemented. The input persistent volume will not
|
||||||
// be modified
|
// be modified
|
||||||
func (CSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
func (CSITranslator) TranslateInTreePVToCSI(logger klog.Logger, pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
|
||||||
if pv == nil {
|
if pv == nil {
|
||||||
return nil, errors.New("persistent volume was nil")
|
return nil, errors.New("persistent volume was nil")
|
||||||
}
|
}
|
||||||
copiedPV := pv.DeepCopy()
|
copiedPV := pv.DeepCopy()
|
||||||
for _, curPlugin := range inTreePlugins {
|
for _, curPlugin := range inTreePlugins {
|
||||||
if curPlugin.CanSupport(copiedPV) {
|
if curPlugin.CanSupport(copiedPV) {
|
||||||
return curPlugin.TranslateInTreePVToCSI(copiedPV)
|
return curPlugin.TranslateInTreePVToCSI(logger, copiedPV)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("could not find in-tree plugin translation logic for %#v", copiedPV.Name)
|
return nil, fmt.Errorf("could not find in-tree plugin translation logic for %#v", copiedPV.Name)
|
||||||
|
@ -25,6 +25,8 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/csi-translation-lib/plugins"
|
"k8s.io/csi-translation-lib/plugins"
|
||||||
|
"k8s.io/klog/v2/ktesting"
|
||||||
|
_ "k8s.io/klog/v2/ktesting/init"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -45,6 +47,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestTranslationStability(t *testing.T) {
|
func TestTranslationStability(t *testing.T) {
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
pv *v1.PersistentVolume
|
pv *v1.PersistentVolume
|
||||||
@ -84,7 +87,7 @@ func TestTranslationStability(t *testing.T) {
|
|||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
ctl := New()
|
ctl := New()
|
||||||
t.Logf("Testing %v", test.name)
|
t.Logf("Testing %v", test.name)
|
||||||
csiSource, err := ctl.TranslateInTreePVToCSI(test.pv)
|
csiSource, err := ctl.TranslateInTreePVToCSI(logger, test.pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error when translating to CSI: %v", err)
|
t.Errorf("Error when translating to CSI: %v", err)
|
||||||
}
|
}
|
||||||
@ -99,6 +102,7 @@ func TestTranslationStability(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTopologyTranslation(t *testing.T) {
|
func TestTopologyTranslation(t *testing.T) {
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
key string
|
key string
|
||||||
@ -207,7 +211,7 @@ func TestTopologyTranslation(t *testing.T) {
|
|||||||
t.Logf("Testing %v", test.name)
|
t.Logf("Testing %v", test.name)
|
||||||
|
|
||||||
// Translate to CSI PV and check translated node affinity
|
// Translate to CSI PV and check translated node affinity
|
||||||
newCSIPV, err := ctl.TranslateInTreePVToCSI(test.pv)
|
newCSIPV, err := ctl.TranslateInTreePVToCSI(logger, test.pv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error when translating to CSI: %v", err)
|
t.Errorf("Error when translating to CSI: %v", err)
|
||||||
}
|
}
|
||||||
@ -365,12 +369,13 @@ func makeTopology(key string, values ...string) *v1.NodeSelectorRequirement {
|
|||||||
func TestTranslateInTreeInlineVolumeToCSINameUniqueness(t *testing.T) {
|
func TestTranslateInTreeInlineVolumeToCSINameUniqueness(t *testing.T) {
|
||||||
for driverName := range inTreePlugins {
|
for driverName := range inTreePlugins {
|
||||||
t.Run(driverName, func(t *testing.T) {
|
t.Run(driverName, func(t *testing.T) {
|
||||||
|
logger, _ := ktesting.NewTestContext(t)
|
||||||
ctl := New()
|
ctl := New()
|
||||||
vs1, err := generateUniqueVolumeSource(driverName)
|
vs1, err := generateUniqueVolumeSource(driverName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Couldn't generate random source: %v", err)
|
t.Fatalf("Couldn't generate random source: %v", err)
|
||||||
}
|
}
|
||||||
pv1, err := ctl.TranslateInTreeInlineVolumeToCSI(&v1.Volume{
|
pv1, err := ctl.TranslateInTreeInlineVolumeToCSI(logger, &v1.Volume{
|
||||||
VolumeSource: vs1,
|
VolumeSource: vs1,
|
||||||
}, "")
|
}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -380,7 +385,7 @@ func TestTranslateInTreeInlineVolumeToCSINameUniqueness(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Couldn't generate random source: %v", err)
|
t.Fatalf("Couldn't generate random source: %v", err)
|
||||||
}
|
}
|
||||||
pv2, err := ctl.TranslateInTreeInlineVolumeToCSI(&v1.Volume{
|
pv2, err := ctl.TranslateInTreeInlineVolumeToCSI(logger, &v1.Volume{
|
||||||
VolumeSource: vs2,
|
VolumeSource: vs2,
|
||||||
}, "")
|
}, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user