diff --git a/pkg/plugins/discovery.go b/pkg/plugins/discovery.go index 61a58980cb..04c3779df9 100644 --- a/pkg/plugins/discovery.go +++ b/pkg/plugins/discovery.go @@ -19,15 +19,19 @@ var ( socketsPath = "/run/docker/plugins" ) -// localRegistry defines a registry that is local (using unix socket). -type localRegistry struct{} +// LocalRegistry defines a registry that is local (using unix socket). +type LocalRegistry struct { + SpecsPaths func() []string +} -func newLocalRegistry() localRegistry { - return localRegistry{} +func NewLocalRegistry() LocalRegistry { + return LocalRegistry{ + SpecsPaths, + } } // Scan scans all the plugin paths and returns all the names it found -func Scan() ([]string, error) { +func (l *LocalRegistry) Scan() ([]string, error) { var names []string dirEntries, err := os.ReadDir(socketsPath) if err != nil && !os.IsNotExist(err) { @@ -49,7 +53,7 @@ func Scan() ([]string, error) { } } - for _, p := range SpecsPaths() { + for _, p := range l.SpecsPaths() { dirEntries, err := os.ReadDir(p) if err != nil && !os.IsNotExist(err) { return nil, errors.Wrap(err, "error reading dir entries") @@ -83,7 +87,7 @@ func Scan() ([]string, error) { } // Plugin returns the plugin registered with the given name (or returns an error). -func (l *localRegistry) Plugin(name string) (*Plugin, error) { +func (l *LocalRegistry) Plugin(name string) (*Plugin, error) { socketpaths := pluginPaths(socketsPath, name, ".sock") for _, p := range socketpaths { @@ -93,7 +97,7 @@ func (l *localRegistry) Plugin(name string) (*Plugin, error) { } var txtspecpaths []string - for _, p := range SpecsPaths() { + for _, p := range l.SpecsPaths() { txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".spec")...) txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".json")...) } diff --git a/pkg/plugins/discovery_test.go b/pkg/plugins/discovery_test.go index 544b1f8cb5..60440443cc 100644 --- a/pkg/plugins/discovery_test.go +++ b/pkg/plugins/discovery_test.go @@ -6,23 +6,26 @@ import ( "testing" ) -func Setup(t *testing.T) (string, func()) { +func Setup(t *testing.T) (string, func(), LocalRegistry) { tmpdir, err := os.MkdirTemp("", "docker-test") if err != nil { t.Fatal(err) } backup := socketsPath socketsPath = tmpdir - globalSpecsPaths = []string{tmpdir} return tmpdir, func() { - socketsPath = backup - os.RemoveAll(tmpdir) - } + socketsPath = backup + os.RemoveAll(tmpdir) + }, LocalRegistry{ + func() []string { + return []string{tmpdir} + }, + } } func TestFileSpecPlugin(t *testing.T) { - tmpdir, unregister := Setup(t) + tmpdir, unregister, r := Setup(t) defer unregister() cases := []struct { @@ -47,7 +50,6 @@ func TestFileSpecPlugin(t *testing.T) { t.Fatal(err) } - r := newLocalRegistry() p, err := r.Plugin(c.name) if c.fail && err == nil { continue @@ -72,7 +74,7 @@ func TestFileSpecPlugin(t *testing.T) { } func TestFileJSONSpecPlugin(t *testing.T) { - tmpdir, unregister := Setup(t) + tmpdir, unregister, r := Setup(t) defer unregister() p := filepath.Join(tmpdir, "example.json") @@ -90,7 +92,6 @@ func TestFileJSONSpecPlugin(t *testing.T) { t.Fatal(err) } - r := newLocalRegistry() plugin, err := r.Plugin("example") if err != nil { t.Fatal(err) @@ -118,7 +119,7 @@ func TestFileJSONSpecPlugin(t *testing.T) { } func TestFileJSONSpecPluginWithoutTLSConfig(t *testing.T) { - tmpdir, unregister := Setup(t) + tmpdir, unregister, r := Setup(t) defer unregister() p := filepath.Join(tmpdir, "example.json") @@ -131,7 +132,6 @@ func TestFileJSONSpecPluginWithoutTLSConfig(t *testing.T) { t.Fatal(err) } - r := newLocalRegistry() plugin, err := r.Plugin("example") if err != nil { t.Fatal(err) diff --git a/pkg/plugins/discovery_unix.go b/pkg/plugins/discovery_unix.go index 46d57d31e7..2c1b2a3193 100644 --- a/pkg/plugins/discovery_unix.go +++ b/pkg/plugins/discovery_unix.go @@ -9,18 +9,13 @@ import ( "github.com/docker/docker/pkg/rootless" ) -const globalConfigPluginsPath = "/etc/docker/plugins" -const globalLibPluginsPath = "/usr/lib/docker/plugins" - -var globalSpecsPaths = []string{globalConfigPluginsPath, globalLibPluginsPath} - func rootlessConfigPluginsPath() string { configHome, err := homedir.GetConfigHome() if err == nil { return filepath.Join(configHome, "docker/plugins") } - return globalConfigPluginsPath + return "/etc/docker/plugins" } func rootlessLibPluginsPath() string { @@ -29,7 +24,7 @@ func rootlessLibPluginsPath() string { return filepath.Join(libHome, "docker/plugins") } - return globalLibPluginsPath + return "/usr/lib/docker/plugins" } // SpecsPaths returns @@ -42,5 +37,5 @@ func SpecsPaths() []string { return []string{rootlessConfigPluginsPath(), rootlessLibPluginsPath()} } - return globalSpecsPaths + return []string{"/etc/docker/plugins", "/usr/lib/docker/plugins"} } diff --git a/pkg/plugins/discovery_unix_test.go b/pkg/plugins/discovery_unix_test.go index cb1f204f91..18174da1d7 100644 --- a/pkg/plugins/discovery_unix_test.go +++ b/pkg/plugins/discovery_unix_test.go @@ -16,7 +16,7 @@ import ( func TestLocalSocket(t *testing.T) { // TODO Windows: Enable a similar version for Windows named pipes - tmpdir, unregister := Setup(t) + tmpdir, unregister, r := Setup(t) defer unregister() cases := []string{ @@ -34,7 +34,6 @@ func TestLocalSocket(t *testing.T) { t.Fatal(err) } - r := newLocalRegistry() p, err := r.Plugin("echo") if err != nil { t.Fatal(err) @@ -64,10 +63,10 @@ func TestLocalSocket(t *testing.T) { } func TestScan(t *testing.T) { - tmpdir, unregister := Setup(t) + tmpdir, unregister, r := Setup(t) defer unregister() - pluginNames, err := Scan() + pluginNames, err := r.Scan() if err != nil { t.Fatal(err) } @@ -89,11 +88,10 @@ func TestScan(t *testing.T) { t.Fatal(err) } - r := newLocalRegistry() p, err := r.Plugin(name) assert.NilError(t, err) - pluginNamesNotEmpty, err := Scan() + pluginNamesNotEmpty, err := r.Scan() if err != nil { t.Fatal(err) } @@ -106,7 +104,7 @@ func TestScan(t *testing.T) { } func TestScanNotPlugins(t *testing.T) { - tmpdir, unregister := Setup(t) + tmpdir, unregister, localRegistry := Setup(t) defer unregister() // not that `Setup()` above sets the sockets path and spec path dirs, which @@ -131,7 +129,7 @@ func TestScanNotPlugins(t *testing.T) { } defer f.Close() - names, err := Scan() + names, err := localRegistry.Scan() if err != nil { t.Fatal(err) } @@ -146,7 +144,7 @@ func TestScanNotPlugins(t *testing.T) { } defer f.Close() - names, err = Scan() + names, err = localRegistry.Scan() if err != nil { t.Fatal(err) } diff --git a/pkg/plugins/discovery_windows.go b/pkg/plugins/discovery_windows.go index 6e978c94fa..ea5d4be375 100644 --- a/pkg/plugins/discovery_windows.go +++ b/pkg/plugins/discovery_windows.go @@ -5,13 +5,11 @@ import ( "path/filepath" ) -var globalSpecsPaths = []string{filepath.Join(os.Getenv("programdata"), "docker", "plugins")} - // SpecsPaths returns // { "%programdata%\docker\plugins" } on Windows, // { "/etc/docker/plugins", "/usr/lib/docker/plugins" } on Unix in non-rootless mode, // { "$XDG_CONFIG_HOME/docker/plugins", "$HOME/.local/lib/docker/plugins" } on Unix in rootless mode // with fallback to the corresponding path in non-rootless mode if $XDG_CONFIG_HOME or $HOME is not set. func SpecsPaths() []string { - return globalSpecsPaths + return []string{filepath.Join(os.Getenv("programdata"), "docker", "plugins")} } diff --git a/pkg/plugins/plugin_test.go b/pkg/plugins/plugin_test.go index 1252dd17b2..c4df5d455c 100644 --- a/pkg/plugins/plugin_test.go +++ b/pkg/plugins/plugin_test.go @@ -123,7 +123,7 @@ func TestPluginWithNoManifest(t *testing.T) { } func TestGetAll(t *testing.T) { - tmpdir, unregister := Setup(t) + tmpdir, unregister, r := Setup(t) defer unregister() p := filepath.Join(tmpdir, "example.json") @@ -136,7 +136,6 @@ func TestGetAll(t *testing.T) { t.Fatal(err) } - r := newLocalRegistry() plugin, err := r.Plugin("example") if err != nil { t.Fatal(err) @@ -144,7 +143,7 @@ func TestGetAll(t *testing.T) { plugin.Manifest = &Manifest{Implements: []string{"apple"}} storage.plugins["example"] = plugin - fetchedPlugins, err := GetAll("apple") + fetchedPlugins, err := r.GetAll("apple") if err != nil { t.Fatal(err) } diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 6f21665e90..7d9c5eac22 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -201,7 +201,7 @@ func load(name string) (*Plugin, error) { } func loadWithRetry(name string, retry bool) (*Plugin, error) { - registry := newLocalRegistry() + registry := NewLocalRegistry() start := time.Now() var retries int @@ -293,8 +293,8 @@ func Handle(iface string, fn func(string, *Client)) { } // GetAll returns all the plugins for the specified implementation -func GetAll(imp string) ([]*Plugin, error) { - pluginNames, err := Scan() +func (l *LocalRegistry) GetAll(imp string) ([]*Plugin, error) { + pluginNames, err := l.Scan() if err != nil { return nil, err } diff --git a/plugin/store.go b/plugin/store.go index 76d9acbfd6..b1acfc22db 100644 --- a/plugin/store.go +++ b/plugin/store.go @@ -192,7 +192,8 @@ func (ps *Store) GetAllByCap(capability string) ([]plugingetter.CompatPlugin, er // Lookup with legacy model if allowV1PluginsFallback { - pl, err := plugins.GetAll(capability) + l := plugins.NewLocalRegistry() + pl, err := l.GetAll(capability) if err != nil { return nil, errors.Wrap(errdefs.System(err), "legacy plugin") }