Merge pull request #106703 from scottnice/patch-1

Fixed skipping valid volume plugins when another plugin has an error
This commit is contained in:
Kubernetes Prow Robot 2021-12-15 09:53:50 -08:00 committed by GitHub
commit 66931c9b8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 9 deletions

View File

@ -30,8 +30,9 @@ import (
) )
const ( const (
pluginDir = "/flexvolume" pluginDir = "/flexvolume"
driverName = "fake-driver" driverName = "fake-driver"
errorDriverName = "error-driver"
) )
func assertPathSuffix(t *testing.T, dir1 string, dir2 string) { func assertPathSuffix(t *testing.T, dir1 string, dir2 string) {
@ -185,7 +186,7 @@ func TestEmptyPluginDir(t *testing.T) {
pluginDir: pluginDir, pluginDir: pluginDir,
watcher: watcher, watcher: watcher,
fs: fs, fs: fs,
factory: fakePluginFactory{error: false}, factory: fakePluginFactory{},
} }
prober.Init() prober.Init()
@ -279,7 +280,7 @@ func TestProberError(t *testing.T) {
pluginDir: pluginDir, pluginDir: pluginDir,
watcher: watcher, watcher: watcher,
fs: fs, fs: fs,
factory: fakePluginFactory{error: true}, factory: fakePluginFactory{errorDriver: driverName},
} }
installDriver(driverName, fs) installDriver(driverName, fs)
prober.Init() prober.Init()
@ -288,6 +289,34 @@ func TestProberError(t *testing.T) {
assert.Error(t, err) assert.Error(t, err)
} }
func TestProberSuccessAndError(t *testing.T) {
// Arrange
fs := utilfs.NewTempFs()
watcher := newFakeWatcher()
prober := &flexVolumeProber{
pluginDir: pluginDir,
watcher: watcher,
fs: fs,
factory: fakePluginFactory{errorDriver: errorDriverName},
}
installDriver(driverName, fs)
prober.Init()
installDriver(errorDriverName, fs)
driverPath := filepath.Join(pluginDir, errorDriverName)
watcher.TriggerEvent(fsnotify.Create, filepath.Join(driverPath, errorDriverName))
// Act
events, err := prober.Probe()
// Assert
assert.Equal(t, 1, len(events))
assert.Equal(t, volume.ProbeAddOrUpdate, events[0].Op)
assert.Equal(t, driverName, events[0].PluginName)
assert.Error(t, err)
}
// Installs a mock driver (an empty file) in the mock fs. // Installs a mock driver (an empty file) in the mock fs.
func installDriver(driverName string, fs utilfs.Filesystem) { func installDriver(driverName string, fs utilfs.Filesystem) {
driverPath := filepath.Join(pluginDir, driverName) driverPath := filepath.Join(pluginDir, driverName)
@ -307,7 +336,7 @@ func initTestEnvironment(t *testing.T) (
pluginDir: pluginDir, pluginDir: pluginDir,
watcher: watcher, watcher: watcher,
fs: fs, fs: fs,
factory: fakePluginFactory{error: false}, factory: fakePluginFactory{},
} }
driverPath = filepath.Join(pluginDir, driverName) driverPath = filepath.Join(pluginDir, driverName)
installDriver(driverName, fs) installDriver(driverName, fs)
@ -320,13 +349,13 @@ func initTestEnvironment(t *testing.T) (
// Fake Flexvolume plugin // Fake Flexvolume plugin
type fakePluginFactory struct { type fakePluginFactory struct {
error bool // Indicates whether an error should be returned. errorDriver string // the name of the driver in error
} }
var _ PluginFactory = fakePluginFactory{} var _ PluginFactory = fakePluginFactory{}
func (m fakePluginFactory) NewFlexVolumePlugin(_, driverName string, _ exec.Interface) (volume.VolumePlugin, error) { func (m fakePluginFactory) NewFlexVolumePlugin(_, driverName string, _ exec.Interface) (volume.VolumePlugin, error) {
if m.error { if driverName == m.errorDriver {
return nil, fmt.Errorf("Flexvolume plugin error") return nil, fmt.Errorf("Flexvolume plugin error")
} }
// Dummy Flexvolume plugin. Prober never interacts with the plugin. // Dummy Flexvolume plugin. Prober never interacts with the plugin.

View File

@ -132,7 +132,7 @@ type NodeResizeOptions struct {
type DynamicPluginProber interface { type DynamicPluginProber interface {
Init() error Init() error
// If an error occurs, events are undefined. // aggregates events for successful drivers and errors for failed drivers
Probe() (events []ProbeEvent, err error) Probe() (events []ProbeEvent, err error)
} }
@ -746,11 +746,14 @@ func (pm *VolumePluginMgr) logDeprecation(plugin string) {
// If it is, initialize all probed plugins and replace the cache with them. // If it is, initialize all probed plugins and replace the cache with them.
func (pm *VolumePluginMgr) refreshProbedPlugins() { func (pm *VolumePluginMgr) refreshProbedPlugins() {
events, err := pm.prober.Probe() events, err := pm.prober.Probe()
if err != nil { if err != nil {
klog.ErrorS(err, "Error dynamically probing plugins") klog.ErrorS(err, "Error dynamically probing plugins")
return // Use cached plugins upon failure.
} }
// because the probe function can return a list of valid plugins
// even when an error is present we still must add the plugins
// or they will be skipped because each event only fires once
for _, event := range events { for _, event := range events {
if event.Op == ProbeAddOrUpdate { if event.Op == ProbeAddOrUpdate {
if err := pm.initProbedPlugin(event.Plugin); err != nil { if err := pm.initProbedPlugin(event.Plugin); err != nil {