2018-05-01 02:15:06 -04:00
|
|
|
/*
|
|
|
|
|
Copyright 2018 The Kubernetes Authors.
|
|
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
|
limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package pluginwatcher
|
|
|
|
|
|
|
|
|
|
import (
|
2018-08-11 18:10:36 -04:00
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"os"
|
2022-06-06 03:51:42 -04:00
|
|
|
"path/filepath"
|
2018-05-01 02:15:06 -04:00
|
|
|
"sync"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
2019-03-11 08:05:07 -04:00
|
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
2020-04-17 15:25:06 -04:00
|
|
|
"k8s.io/klog/v2"
|
2019-10-06 15:24:24 -04:00
|
|
|
registerapi "k8s.io/kubelet/pkg/apis/pluginregistration/v1"
|
2019-03-09 08:25:08 -05:00
|
|
|
"k8s.io/kubernetes/pkg/kubelet/pluginmanager/cache"
|
2025-07-10 11:15:24 -04:00
|
|
|
"k8s.io/kubernetes/test/utils/ktesting"
|
2018-05-01 02:15:06 -04:00
|
|
|
)
|
|
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
var (
|
|
|
|
|
supportedVersions = []string{"v1beta1", "v1beta2"}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
var logLevel string
|
|
|
|
|
|
2025-07-10 11:15:24 -04:00
|
|
|
flags := &flag.FlagSet{}
|
|
|
|
|
klog.InitFlags(flags)
|
2018-08-11 18:10:36 -04:00
|
|
|
flag.Set("alsologtostderr", fmt.Sprintf("%t", true))
|
|
|
|
|
flag.StringVar(&logLevel, "logLevel", "6", "test")
|
|
|
|
|
flag.Lookup("v").Value.Set(logLevel)
|
2022-06-06 03:51:42 -04:00
|
|
|
}
|
2018-08-11 18:10:36 -04:00
|
|
|
|
2022-06-06 03:51:42 -04:00
|
|
|
func initTempDir(t *testing.T) string {
|
|
|
|
|
// Creating a different directory. os.RemoveAll is not atomic enough;
|
|
|
|
|
// os.MkdirAll can get into an "Access Denied" error on Windows.
|
2022-07-18 10:51:51 -04:00
|
|
|
d, err := os.MkdirTemp("", "plugin_test")
|
2018-08-11 18:10:36 -04:00
|
|
|
if err != nil {
|
2022-06-06 03:51:42 -04:00
|
|
|
t.Fatalf("Could not create a temp directory %s: %v", d, err)
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
}
|
2018-08-11 18:10:36 -04:00
|
|
|
|
2022-06-06 03:51:42 -04:00
|
|
|
return d
|
2018-08-11 18:10:36 -04:00
|
|
|
}
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
func waitForRegistration(
|
|
|
|
|
t *testing.T,
|
|
|
|
|
socketPath string,
|
|
|
|
|
dsw cache.DesiredStateOfWorld) {
|
|
|
|
|
err := retryWithExponentialBackOff(
|
|
|
|
|
time.Duration(500*time.Millisecond),
|
|
|
|
|
func() (bool, error) {
|
|
|
|
|
if dsw.PluginExists(socketPath) {
|
|
|
|
|
return true, nil
|
|
|
|
|
}
|
|
|
|
|
return false, nil
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("Timed out waiting for plugin to be added to desired state of world cache:\n%s.", socketPath)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func waitForUnregistration(
|
|
|
|
|
t *testing.T,
|
|
|
|
|
socketPath string,
|
|
|
|
|
dsw cache.DesiredStateOfWorld) {
|
|
|
|
|
err := retryWithExponentialBackOff(
|
|
|
|
|
time.Duration(500*time.Millisecond),
|
|
|
|
|
func() (bool, error) {
|
|
|
|
|
if !dsw.PluginExists(socketPath) {
|
|
|
|
|
return true, nil
|
|
|
|
|
}
|
|
|
|
|
return false, nil
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("Timed out waiting for plugin to be unregistered:\n%s.", socketPath)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func retryWithExponentialBackOff(initialDuration time.Duration, fn wait.ConditionFunc) error {
|
|
|
|
|
backoff := wait.Backoff{
|
|
|
|
|
Duration: initialDuration,
|
|
|
|
|
Factor: 3,
|
|
|
|
|
Jitter: 0,
|
|
|
|
|
Steps: 6,
|
|
|
|
|
}
|
|
|
|
|
return wait.ExponentialBackoff(backoff, fn)
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
func TestPluginRegistration(t *testing.T) {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketDir := initTempDir(t)
|
|
|
|
|
defer os.RemoveAll(socketDir)
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2025-07-10 11:15:24 -04:00
|
|
|
tCtx := ktesting.Init(t)
|
2019-03-09 08:25:08 -05:00
|
|
|
dsw := cache.NewDesiredStateOfWorld()
|
2022-06-06 03:51:42 -04:00
|
|
|
newWatcher(t, socketDir, dsw, wait.NeverStop)
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
for i := 0; i < 10; i++ {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketPath := filepath.Join(socketDir, fmt.Sprintf("plugin-%d.sock", i))
|
2018-08-11 18:10:36 -04:00
|
|
|
pluginName := fmt.Sprintf("example-plugin-%d", i)
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
p := NewTestExamplePlugin(pluginName, registerapi.DevicePlugin, socketPath, supportedVersions...)
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Serve(tCtx, "v1beta1", "v1beta2"))
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-11-11 14:42:58 -05:00
|
|
|
pluginInfo := GetPluginInfo(p)
|
2019-03-09 08:25:08 -05:00
|
|
|
waitForRegistration(t, pluginInfo.SocketPath, dsw)
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
// Check the desired state for plugins
|
|
|
|
|
dswPlugins := dsw.GetPluginsToRegister()
|
|
|
|
|
if len(dswPlugins) != 1 {
|
|
|
|
|
t.Fatalf("TestPluginRegistration: desired state of world length should be 1 but it's %d", len(dswPlugins))
|
|
|
|
|
}
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
// Stop the plugin; the plugin should be removed from the desired state of world cache
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Stop(tCtx))
|
2019-03-09 08:25:08 -05:00
|
|
|
// The following doesn't work when running the unit tests locally: event.Op of plugin watcher won't pick up the delete event
|
|
|
|
|
waitForUnregistration(t, pluginInfo.SocketPath, dsw)
|
|
|
|
|
dswPlugins = dsw.GetPluginsToRegister()
|
|
|
|
|
if len(dswPlugins) != 0 {
|
|
|
|
|
t.Fatalf("TestPluginRegistration: desired state of world length should be 0 but it's %d", len(dswPlugins))
|
|
|
|
|
}
|
2018-08-11 18:10:36 -04:00
|
|
|
}
|
|
|
|
|
}
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
func TestPluginRegistrationSameName(t *testing.T) {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketDir := initTempDir(t)
|
|
|
|
|
defer os.RemoveAll(socketDir)
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2025-07-10 11:15:24 -04:00
|
|
|
tCtx := ktesting.Init(t)
|
2019-03-09 08:25:08 -05:00
|
|
|
dsw := cache.NewDesiredStateOfWorld()
|
2022-06-06 03:51:42 -04:00
|
|
|
newWatcher(t, socketDir, dsw, wait.NeverStop)
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
// Make 10 plugins with the same name and same type but different socket path;
|
|
|
|
|
// all 10 should be in desired state of world cache
|
|
|
|
|
pluginName := "dep-example-plugin"
|
2018-08-11 18:10:36 -04:00
|
|
|
for i := 0; i < 10; i++ {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketPath := filepath.Join(socketDir, fmt.Sprintf("plugin-%d.sock", i))
|
2018-08-11 18:10:36 -04:00
|
|
|
p := NewTestExamplePlugin(pluginName, registerapi.DevicePlugin, socketPath, supportedVersions...)
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Serve(tCtx, "v1beta1", "v1beta2"))
|
2018-08-11 18:10:36 -04:00
|
|
|
|
2019-11-11 14:42:58 -05:00
|
|
|
pluginInfo := GetPluginInfo(p)
|
2019-03-09 08:25:08 -05:00
|
|
|
waitForRegistration(t, pluginInfo.SocketPath, dsw)
|
2018-08-11 18:10:36 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
// Check the desired state for plugins
|
|
|
|
|
dswPlugins := dsw.GetPluginsToRegister()
|
|
|
|
|
if len(dswPlugins) != i+1 {
|
|
|
|
|
t.Fatalf("TestPluginRegistrationSameName: desired state of world length should be %d but it's %d", i+1, len(dswPlugins))
|
|
|
|
|
}
|
2018-05-01 02:15:06 -04:00
|
|
|
}
|
2019-03-09 08:25:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestPluginReRegistration(t *testing.T) {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketDir := initTempDir(t)
|
|
|
|
|
defer os.RemoveAll(socketDir)
|
2019-03-09 08:25:08 -05:00
|
|
|
|
2025-07-10 11:15:24 -04:00
|
|
|
tCtx := ktesting.Init(t)
|
2019-03-09 08:25:08 -05:00
|
|
|
dsw := cache.NewDesiredStateOfWorld()
|
2022-06-06 03:51:42 -04:00
|
|
|
newWatcher(t, socketDir, dsw, wait.NeverStop)
|
2019-03-09 08:25:08 -05:00
|
|
|
|
|
|
|
|
// Create a plugin first, we are then going to remove the plugin, update the plugin with a different name
|
|
|
|
|
// and recreate it.
|
2022-06-06 03:51:42 -04:00
|
|
|
socketPath := filepath.Join(socketDir, "plugin-reregistration.sock")
|
2019-03-09 08:25:08 -05:00
|
|
|
pluginName := "reregister-plugin"
|
|
|
|
|
p := NewTestExamplePlugin(pluginName, registerapi.DevicePlugin, socketPath, supportedVersions...)
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Serve(tCtx, "v1beta1", "v1beta2"))
|
2019-11-11 14:42:58 -05:00
|
|
|
pluginInfo := GetPluginInfo(p)
|
2019-03-09 08:25:08 -05:00
|
|
|
lastTimestamp := time.Now()
|
|
|
|
|
waitForRegistration(t, pluginInfo.SocketPath, dsw)
|
|
|
|
|
|
|
|
|
|
// Remove this plugin, then recreate it again with a different name for 10 times
|
|
|
|
|
// The updated plugin should be in the desired state of world cache
|
|
|
|
|
for i := 0; i < 10; i++ {
|
|
|
|
|
// Stop the plugin; the plugin should be removed from the desired state of world cache
|
2023-08-04 02:56:50 -04:00
|
|
|
// The plugin removal doesn't work when running the unit tests locally: event.Op of plugin watcher won't pick up the delete event
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Stop(tCtx))
|
2019-03-09 08:25:08 -05:00
|
|
|
waitForUnregistration(t, pluginInfo.SocketPath, dsw)
|
2018-05-01 02:15:06 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
// Add the plugin again
|
|
|
|
|
pluginName := fmt.Sprintf("dep-example-plugin-%d", i)
|
|
|
|
|
p := NewTestExamplePlugin(pluginName, registerapi.DevicePlugin, socketPath, supportedVersions...)
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Serve(tCtx, "v1beta1", "v1beta2"))
|
2019-03-09 08:25:08 -05:00
|
|
|
waitForRegistration(t, pluginInfo.SocketPath, dsw)
|
2018-08-11 18:10:36 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
// Check the dsw cache. The updated plugin should be the only plugin in it
|
|
|
|
|
dswPlugins := dsw.GetPluginsToRegister()
|
|
|
|
|
if len(dswPlugins) != 1 {
|
|
|
|
|
t.Fatalf("TestPluginReRegistration: desired state of world length should be 1 but it's %d", len(dswPlugins))
|
|
|
|
|
}
|
|
|
|
|
if !dswPlugins[0].Timestamp.After(lastTimestamp) {
|
|
|
|
|
t.Fatalf("TestPluginReRegistration: for plugin %s timestamp of plugin is not updated", pluginName)
|
|
|
|
|
}
|
|
|
|
|
lastTimestamp = dswPlugins[0].Timestamp
|
2018-08-11 18:10:36 -04:00
|
|
|
}
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
}
|
|
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
func TestPluginRegistrationAtKubeletStart(t *testing.T) {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketDir := initTempDir(t)
|
|
|
|
|
defer os.RemoveAll(socketDir)
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2025-07-10 11:15:24 -04:00
|
|
|
tCtx := ktesting.Init(t)
|
2018-08-11 18:10:36 -04:00
|
|
|
plugins := make([]*examplePlugin, 10)
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
for i := 0; i < len(plugins); i++ {
|
2022-06-06 03:51:42 -04:00
|
|
|
socketPath := filepath.Join(socketDir, fmt.Sprintf("plugin-%d.sock", i))
|
2018-08-11 18:10:36 -04:00
|
|
|
pluginName := fmt.Sprintf("example-plugin-%d", i)
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
p := NewTestExamplePlugin(pluginName, registerapi.DevicePlugin, socketPath, supportedVersions...)
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Serve(tCtx, "v1beta1", "v1beta2"))
|
2019-03-09 08:25:08 -05:00
|
|
|
defer func(p *examplePlugin) {
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, p.Stop(tCtx))
|
2019-03-09 08:25:08 -05:00
|
|
|
}(p)
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
plugins[i] = p
|
|
|
|
|
}
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2019-03-09 08:25:08 -05:00
|
|
|
dsw := cache.NewDesiredStateOfWorld()
|
2022-06-06 03:51:42 -04:00
|
|
|
newWatcher(t, socketDir, dsw, wait.NeverStop)
|
2019-03-09 08:25:08 -05:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
for i := 0; i < len(plugins); i++ {
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go func(p *examplePlugin) {
|
|
|
|
|
defer wg.Done()
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2019-11-11 14:42:58 -05:00
|
|
|
pluginInfo := GetPluginInfo(p)
|
2019-03-09 08:25:08 -05:00
|
|
|
// Validate that the plugin is in the desired state cache
|
|
|
|
|
waitForRegistration(t, pluginInfo.SocketPath, dsw)
|
2018-08-11 18:10:36 -04:00
|
|
|
}(plugins[i])
|
|
|
|
|
}
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
c := make(chan struct{})
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
go func() {
|
2018-08-11 18:10:36 -04:00
|
|
|
defer close(c)
|
|
|
|
|
wg.Wait()
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
}()
|
|
|
|
|
|
2018-08-11 18:10:36 -04:00
|
|
|
select {
|
|
|
|
|
case <-c:
|
|
|
|
|
return
|
2019-03-11 08:05:07 -04:00
|
|
|
case <-time.After(wait.ForeverTestTimeout):
|
2018-08-11 18:10:36 -04:00
|
|
|
t.Fatalf("Timeout while waiting for the plugin registration status")
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
}
|
2018-08-11 18:10:36 -04:00
|
|
|
}
|
Add hierarchy support for plugin directory
it traverses and watch plugin directory and its sub directory recursively,
plugin socket file only need be unique within one directory,
- plugin socket directory
- |
- ---->sub directory 1
- | |
- | -----> socket1, socket2 ...
- ----->sub directory 2
- |
- ------> socket1, socket2 ...
the design itself allow sub directory be anything,
but in practical, each plugin type could just use one sub directory.
four bonus changes added as below
1. extract example handler out from test, it is easier to read the code
with the seperation.
2. there are two variables here: "Watcher" and "watcher".
"Watcher" is the plugin watcher, and "watcher" is the fsnotify watcher.
so rename the "watcher" to "fsWatcher" to make code easier to
understand.
3. change RegisterCallbackFn() return value order, it is
conventional to return error last, after this change,
the pkg/volume/csi is compliance with golint, so remove it
from hack/.golint_failures
4. refactor errors handling at invokeRegistrationCallbackAtHandler()
to make error message more clear.
2018-05-30 20:07:58 -04:00
|
|
|
|
2022-06-06 03:51:42 -04:00
|
|
|
func newWatcher(t *testing.T, socketDir string, desiredStateOfWorldCache cache.DesiredStateOfWorld, stopCh <-chan struct{}) *Watcher {
|
2025-07-10 11:15:24 -04:00
|
|
|
tCtx := ktesting.Init(t)
|
2019-11-11 14:42:58 -05:00
|
|
|
w := NewWatcher(socketDir, desiredStateOfWorldCache)
|
2025-07-10 11:15:24 -04:00
|
|
|
require.NoError(t, w.Start(tCtx, stopCh))
|
2018-08-11 18:10:36 -04:00
|
|
|
|
|
|
|
|
return w
|
|
|
|
|
}
|