5a0bcd39d1
Allow for faster updates to plugin status when allocations become terminal by listening for register/deregister events from the dynamic plugin registry (which in turn are triggered by the plugin supervisor hook). The deregistration function closures that we pass up to the CSI plugin manager don't properly close over the name and type of the registration, causing monolith-type plugins to deregister only one of their two plugins on alloc shutdown. Rebind plugin supervisor deregistration targets to fix that. Includes log message and comment improvements
162 lines
3.9 KiB
Go
162 lines
3.9 KiB
Go
package csimanager
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/nomad/client/dynamicplugins"
|
|
"github.com/hashicorp/nomad/client/pluginmanager"
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
var _ pluginmanager.PluginManager = (*csiManager)(nil)
|
|
|
|
var fakePlugin = &dynamicplugins.PluginInfo{
|
|
Name: "my-plugin",
|
|
Type: "csi-controller",
|
|
ConnectionInfo: &dynamicplugins.PluginConnectionInfo{},
|
|
}
|
|
|
|
func setupRegistry() dynamicplugins.Registry {
|
|
return dynamicplugins.NewRegistry(
|
|
nil,
|
|
map[string]dynamicplugins.PluginDispenser{
|
|
"csi-controller": func(*dynamicplugins.PluginInfo) (interface{}, error) {
|
|
return nil, nil
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestManager_Setup_Shutdown(t *testing.T) {
|
|
r := setupRegistry()
|
|
defer r.Shutdown()
|
|
|
|
cfg := &Config{
|
|
Logger: testlog.HCLogger(t),
|
|
DynamicRegistry: r,
|
|
UpdateNodeCSIInfoFunc: func(string, *structs.CSIInfo) {},
|
|
}
|
|
pm := New(cfg).(*csiManager)
|
|
pm.Run()
|
|
pm.Shutdown()
|
|
}
|
|
|
|
func TestManager_RegisterPlugin(t *testing.T) {
|
|
registry := setupRegistry()
|
|
defer registry.Shutdown()
|
|
|
|
require.NotNil(t, registry)
|
|
|
|
cfg := &Config{
|
|
Logger: testlog.HCLogger(t),
|
|
DynamicRegistry: registry,
|
|
UpdateNodeCSIInfoFunc: func(string, *structs.CSIInfo) {},
|
|
}
|
|
pm := New(cfg).(*csiManager)
|
|
defer pm.Shutdown()
|
|
|
|
require.NotNil(t, pm.registry)
|
|
|
|
err := registry.RegisterPlugin(fakePlugin)
|
|
require.Nil(t, err)
|
|
|
|
pm.Run()
|
|
|
|
require.Eventually(t, func() bool {
|
|
pmap, ok := pm.instances[fakePlugin.Type]
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
_, ok = pmap[fakePlugin.Name]
|
|
return ok
|
|
}, 5*time.Second, 10*time.Millisecond)
|
|
}
|
|
|
|
func TestManager_DeregisterPlugin(t *testing.T) {
|
|
registry := setupRegistry()
|
|
defer registry.Shutdown()
|
|
|
|
require.NotNil(t, registry)
|
|
|
|
cfg := &Config{
|
|
Logger: testlog.HCLogger(t),
|
|
DynamicRegistry: registry,
|
|
UpdateNodeCSIInfoFunc: func(string, *structs.CSIInfo) {},
|
|
PluginResyncPeriod: 500 * time.Millisecond,
|
|
}
|
|
pm := New(cfg).(*csiManager)
|
|
defer pm.Shutdown()
|
|
|
|
require.NotNil(t, pm.registry)
|
|
|
|
err := registry.RegisterPlugin(fakePlugin)
|
|
require.Nil(t, err)
|
|
|
|
pm.Run()
|
|
|
|
require.Eventually(t, func() bool {
|
|
_, ok := pm.instances[fakePlugin.Type][fakePlugin.Name]
|
|
return ok
|
|
}, 5*time.Second, 10*time.Millisecond)
|
|
|
|
err = registry.DeregisterPlugin(fakePlugin.Type, fakePlugin.Name)
|
|
require.Nil(t, err)
|
|
|
|
require.Eventually(t, func() bool {
|
|
_, ok := pm.instances[fakePlugin.Type][fakePlugin.Name]
|
|
return !ok
|
|
}, 5*time.Second, 10*time.Millisecond)
|
|
}
|
|
|
|
// TestManager_MultiplePlugins ensures that multiple plugins with the same
|
|
// name but different types (as found with monolith plugins) don't interfere
|
|
// with each other.
|
|
func TestManager_MultiplePlugins(t *testing.T) {
|
|
registry := setupRegistry()
|
|
defer registry.Shutdown()
|
|
|
|
require.NotNil(t, registry)
|
|
|
|
cfg := &Config{
|
|
Logger: testlog.HCLogger(t),
|
|
DynamicRegistry: registry,
|
|
UpdateNodeCSIInfoFunc: func(string, *structs.CSIInfo) {},
|
|
PluginResyncPeriod: 500 * time.Millisecond,
|
|
}
|
|
pm := New(cfg).(*csiManager)
|
|
defer pm.Shutdown()
|
|
|
|
require.NotNil(t, pm.registry)
|
|
|
|
err := registry.RegisterPlugin(fakePlugin)
|
|
require.Nil(t, err)
|
|
|
|
fakeNodePlugin := *fakePlugin
|
|
fakeNodePlugin.Type = "csi-node"
|
|
err = registry.RegisterPlugin(&fakeNodePlugin)
|
|
require.Nil(t, err)
|
|
|
|
pm.Run()
|
|
|
|
require.Eventually(t, func() bool {
|
|
_, ok := pm.instances[fakePlugin.Type][fakePlugin.Name]
|
|
return ok
|
|
}, 5*time.Second, 10*time.Millisecond)
|
|
|
|
require.Eventually(t, func() bool {
|
|
_, ok := pm.instances[fakeNodePlugin.Type][fakeNodePlugin.Name]
|
|
return ok
|
|
}, 5*time.Second, 10*time.Millisecond)
|
|
|
|
err = registry.DeregisterPlugin(fakePlugin.Type, fakePlugin.Name)
|
|
require.Nil(t, err)
|
|
|
|
require.Eventually(t, func() bool {
|
|
_, ok := pm.instances[fakePlugin.Type][fakePlugin.Name]
|
|
return !ok
|
|
}, 5*time.Second, 10*time.Millisecond)
|
|
}
|