mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 12:18:16 +00:00 
			
		
		
		
	Merge pull request #76151 from vladimirvivien/plugin-CanAttach-return-error
Ability for volume AttachablePlugin.CanAttach() to return both bool and error
This commit is contained in:
		@@ -308,8 +308,8 @@ func (plugin *TestPlugin) NewDetacher() (volume.Detacher, error) {
 | 
			
		||||
	return &detacher, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *TestPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *TestPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *TestPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -277,8 +277,8 @@ func (detacher *awsElasticBlockStoreDetacher) UnmountDevice(deviceMountPath stri
 | 
			
		||||
	return mount.CleanupMountPoint(deviceMountPath, detacher.mounter, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *awsElasticBlockStorePlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *awsElasticBlockStorePlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *awsElasticBlockStorePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -238,8 +238,8 @@ func (plugin *azureDataDiskPlugin) NewDetacher() (volume.Detacher, error) {
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *azureDataDiskPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *azureDataDiskPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *azureDataDiskPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -406,8 +406,8 @@ func (detacher *cinderDiskDetacher) UnmountDevice(deviceMountPath string) error
 | 
			
		||||
	return mount.CleanupMountPoint(deviceMountPath, detacher.mounter, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *cinderPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *cinderPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *cinderPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -348,7 +348,10 @@ func TestAttacherWithCSIDriver(t *testing.T) {
 | 
			
		||||
			csiAttacher := attacher.(*csiAttacher)
 | 
			
		||||
			spec := volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 10, test.driver, "test-vol"), false)
 | 
			
		||||
 | 
			
		||||
			pluginCanAttach := plug.CanAttach(spec)
 | 
			
		||||
			pluginCanAttach, err := plug.CanAttach(spec)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("attacher.CanAttach failed: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
			if pluginCanAttach != test.expectVolumeAttachment {
 | 
			
		||||
				t.Errorf("attacher.CanAttach does not match expected attachment status %t", test.expectVolumeAttachment)
 | 
			
		||||
			}
 | 
			
		||||
@@ -429,7 +432,10 @@ func TestAttacherWaitForVolumeAttachmentWithCSIDriver(t *testing.T) {
 | 
			
		||||
			csiAttacher := attacher.(*csiAttacher)
 | 
			
		||||
			spec := volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 10, test.driver, "test-vol"), false)
 | 
			
		||||
 | 
			
		||||
			pluginCanAttach := plug.CanAttach(spec)
 | 
			
		||||
			pluginCanAttach, err := plug.CanAttach(spec)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("plugin.CanAttach test failed: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
			if !pluginCanAttach {
 | 
			
		||||
				t.Log("plugin is not attachable")
 | 
			
		||||
				return
 | 
			
		||||
 
 | 
			
		||||
@@ -581,34 +581,30 @@ func (p *csiPlugin) NewDetacher() (volume.Detacher, error) {
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO change CanAttach to return error to propagate ability
 | 
			
		||||
// to support Attachment or an error - see https://github.com/kubernetes/kubernetes/issues/74810
 | 
			
		||||
func (p *csiPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
func (p *csiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	driverMode, err := p.getDriverMode(spec)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if driverMode == ephemeralDriverMode {
 | 
			
		||||
		klog.V(4).Info(log("driver ephemeral mode detected for spec %v", spec.Name))
 | 
			
		||||
		return false
 | 
			
		||||
		klog.V(5).Info(log("plugin.CanAttach = false, ephemeral mode detected for spec %v", spec.Name()))
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pvSrc, err := getCSISourceFromSpec(spec)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		klog.Error(log("plugin.CanAttach failed to get info from spec: %s", err))
 | 
			
		||||
		return false
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	driverName := pvSrc.Driver
 | 
			
		||||
 | 
			
		||||
	skipAttach, err := p.skipAttach(driverName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		klog.Error(log("plugin.CanAttach error when calling plugin.skipAttach for driver %s: %s", driverName, err))
 | 
			
		||||
		return false
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return !skipAttach
 | 
			
		||||
	return !skipAttach, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO (#75352) add proper logic to determine device moutability by inspecting the spec.
 | 
			
		||||
 
 | 
			
		||||
@@ -880,6 +880,7 @@ func TestPluginCanAttach(t *testing.T) {
 | 
			
		||||
		driverName string
 | 
			
		||||
		spec       *volume.Spec
 | 
			
		||||
		canAttach  bool
 | 
			
		||||
		shouldFail bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:       "non-attachable inline",
 | 
			
		||||
@@ -893,6 +894,19 @@ func TestPluginCanAttach(t *testing.T) {
 | 
			
		||||
			spec:       volume.NewSpecFromPersistentVolume(makeTestPV("test-vol", 20, "attachable-pv", testVol), true),
 | 
			
		||||
			canAttach:  true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:       "incomplete spec",
 | 
			
		||||
			driverName: "attachable-pv",
 | 
			
		||||
			spec:       &volume.Spec{ReadOnly: true},
 | 
			
		||||
			canAttach:  false,
 | 
			
		||||
			shouldFail: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:       "nil spec",
 | 
			
		||||
			driverName: "attachable-pv",
 | 
			
		||||
			canAttach:  false,
 | 
			
		||||
			shouldFail: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
@@ -902,10 +916,80 @@ func TestPluginCanAttach(t *testing.T) {
 | 
			
		||||
			plug, tmpDir := newTestPlugin(t, fakeCSIClient)
 | 
			
		||||
			defer os.RemoveAll(tmpDir)
 | 
			
		||||
 | 
			
		||||
			pluginCanAttach := plug.CanAttach(test.spec)
 | 
			
		||||
			pluginCanAttach, err := plug.CanAttach(test.spec)
 | 
			
		||||
			if err != nil && !test.shouldFail {
 | 
			
		||||
				t.Fatalf("unexected plugin.CanAttach error: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
			if pluginCanAttach != test.canAttach {
 | 
			
		||||
				t.Fatalf("expecting plugin.CanAttach %t got %t", test.canAttach, pluginCanAttach)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestPluginFindAttachablePlugin(t *testing.T) {
 | 
			
		||||
	defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name       string
 | 
			
		||||
		driverName string
 | 
			
		||||
		spec       *volume.Spec
 | 
			
		||||
		canAttach  bool
 | 
			
		||||
		shouldFail bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:       "non-attachable inline",
 | 
			
		||||
			driverName: "attachable-inline",
 | 
			
		||||
			spec:       volume.NewSpecFromVolume(makeTestVol("test-vol", "attachable-inline")),
 | 
			
		||||
			canAttach:  false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:       "attachable PV",
 | 
			
		||||
			driverName: "attachable-pv",
 | 
			
		||||
			spec:       volume.NewSpecFromPersistentVolume(makeTestPV("test-vol", 20, "attachable-pv", testVol), true),
 | 
			
		||||
			canAttach:  true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:       "incomplete spec",
 | 
			
		||||
			driverName: "attachable-pv",
 | 
			
		||||
			spec:       &volume.Spec{ReadOnly: true},
 | 
			
		||||
			canAttach:  false,
 | 
			
		||||
			shouldFail: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:       "nil spec",
 | 
			
		||||
			driverName: "attachable-pv",
 | 
			
		||||
			canAttach:  false,
 | 
			
		||||
			shouldFail: true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			tmpDir, err := utiltesting.MkTmpdir("csi-test")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("can't create temp dir: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			defer os.RemoveAll(tmpDir)
 | 
			
		||||
 | 
			
		||||
			client := fakeclient.NewSimpleClientset(getCSIDriver(test.driverName, nil, &test.canAttach))
 | 
			
		||||
			factory := informers.NewSharedInformerFactory(client, csiResyncPeriod)
 | 
			
		||||
			host := volumetest.NewFakeVolumeHostWithCSINodeName(
 | 
			
		||||
				tmpDir,
 | 
			
		||||
				client,
 | 
			
		||||
				nil,
 | 
			
		||||
				"fakeNode",
 | 
			
		||||
				factory.Storage().V1beta1().CSIDrivers().Lister(),
 | 
			
		||||
			)
 | 
			
		||||
 | 
			
		||||
			plugMgr := &volume.VolumePluginMgr{}
 | 
			
		||||
			plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
 | 
			
		||||
 | 
			
		||||
			plugin, err := plugMgr.FindAttachablePluginBySpec(test.spec)
 | 
			
		||||
			if err != nil && !test.shouldFail {
 | 
			
		||||
				t.Fatalf("unexected error calling pluginMgr.FindAttachablePluginBySpec: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
			if (plugin != nil) != test.canAttach {
 | 
			
		||||
				t.Fatal("expecting attachable plugin, but got nil")
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -175,8 +175,8 @@ func (detacher *fcDetacher) UnmountDevice(deviceMountPath string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *fcPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *fcPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *fcPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -256,8 +256,8 @@ func (plugin *flexVolumeAttachablePlugin) NewDeviceUnmounter() (volume.DeviceUnm
 | 
			
		||||
	return plugin.NewDetacher()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *flexVolumeAttachablePlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *flexVolumeAttachablePlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *flexVolumeAttachablePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -350,8 +350,8 @@ func (detacher *gcePersistentDiskDetacher) UnmountDevice(deviceMountPath string)
 | 
			
		||||
	return mount.CleanupMountPoint(deviceMountPath, detacher.host.GetMounter(gcePersistentDiskPluginName), false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *gcePersistentDiskPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *gcePersistentDiskPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *gcePersistentDiskPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -176,8 +176,8 @@ func (detacher *iscsiDetacher) UnmountDevice(deviceMountPath string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *iscsiPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *iscsiPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *iscsiPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -308,8 +308,8 @@ func (detacher *photonPersistentDiskDetacher) UnmountDevice(deviceMountPath stri
 | 
			
		||||
	return mount.CleanupMountPoint(deviceMountPath, detacher.mounter, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *photonPersistentDiskPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *photonPersistentDiskPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *photonPersistentDiskPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -235,7 +235,7 @@ type AttachableVolumePlugin interface {
 | 
			
		||||
	NewAttacher() (Attacher, error)
 | 
			
		||||
	NewDetacher() (Detacher, error)
 | 
			
		||||
	// CanAttach tests if provided volume spec is attachable
 | 
			
		||||
	CanAttach(spec *Spec) bool
 | 
			
		||||
	CanAttach(spec *Spec) (bool, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeviceMountableVolumePlugin is an extended interface of VolumePlugin and is used
 | 
			
		||||
@@ -891,7 +891,9 @@ func (pm *VolumePluginMgr) FindAttachablePluginBySpec(spec *Spec) (AttachableVol
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if attachableVolumePlugin, ok := volumePlugin.(AttachableVolumePlugin); ok {
 | 
			
		||||
		if attachableVolumePlugin.CanAttach(spec) {
 | 
			
		||||
		if canAttach, err := attachableVolumePlugin.CanAttach(spec); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		} else if canAttach {
 | 
			
		||||
			return attachableVolumePlugin, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -71,8 +71,8 @@ func (plugin *rbdPlugin) GetDeviceMountRefs(deviceMountPath string) ([]string, e
 | 
			
		||||
	return mounter.GetMountRefs(deviceMountPath)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *rbdPlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *rbdPlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *rbdPlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -492,8 +492,8 @@ func (plugin *FakeVolumePlugin) GetNewDetacherCallCount() int {
 | 
			
		||||
	return plugin.NewDetacherCallCount
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *FakeVolumePlugin) CanAttach(spec *Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *FakeVolumePlugin) CanAttach(spec *Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *FakeVolumePlugin) CanDeviceMount(spec *Spec) (bool, error) {
 | 
			
		||||
@@ -654,8 +654,8 @@ func (f *FakeAttachableVolumePlugin) NewDetacher() (Detacher, error) {
 | 
			
		||||
	return f.Plugin.NewDetacher()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FakeAttachableVolumePlugin) CanAttach(spec *Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (f *FakeAttachableVolumePlugin) CanAttach(spec *Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ VolumePlugin = &FakeAttachableVolumePlugin{}
 | 
			
		||||
 
 | 
			
		||||
@@ -295,8 +295,8 @@ func (detacher *vsphereVMDKDetacher) UnmountDevice(deviceMountPath string) error
 | 
			
		||||
	return mount.CleanupMountPoint(deviceMountPath, detacher.mounter, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *vsphereVolumePlugin) CanAttach(spec *volume.Spec) bool {
 | 
			
		||||
	return true
 | 
			
		||||
func (plugin *vsphereVolumePlugin) CanAttach(spec *volume.Spec) (bool, error) {
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (plugin *vsphereVolumePlugin) CanDeviceMount(spec *volume.Spec) (bool, error) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user