plugins: Move GlobalSpecPaths into LocalRegistry

Signed-off-by: Jan Garcia <github-public@n-garcia.com>
This commit is contained in:
Jan Garcia 2023-01-10 21:33:49 +01:00
parent 62296f9281
commit 1e1d326b50
8 changed files with 41 additions and 46 deletions

View file

@ -19,15 +19,19 @@ var (
socketsPath = "/run/docker/plugins" socketsPath = "/run/docker/plugins"
) )
// localRegistry defines a registry that is local (using unix socket). // LocalRegistry defines a registry that is local (using unix socket).
type localRegistry struct{} type LocalRegistry struct {
SpecsPaths func() []string
}
func newLocalRegistry() localRegistry { func NewLocalRegistry() LocalRegistry {
return localRegistry{} return LocalRegistry{
SpecsPaths,
}
} }
// Scan scans all the plugin paths and returns all the names it found // 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 var names []string
dirEntries, err := os.ReadDir(socketsPath) dirEntries, err := os.ReadDir(socketsPath)
if err != nil && !os.IsNotExist(err) { 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) dirEntries, err := os.ReadDir(p)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return nil, errors.Wrap(err, "error reading dir entries") 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). // 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") socketpaths := pluginPaths(socketsPath, name, ".sock")
for _, p := range socketpaths { for _, p := range socketpaths {
@ -93,7 +97,7 @@ func (l *localRegistry) Plugin(name string) (*Plugin, error) {
} }
var txtspecpaths []string 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, ".spec")...)
txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".json")...) txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".json")...)
} }

View file

@ -6,23 +6,26 @@ import (
"testing" "testing"
) )
func Setup(t *testing.T) (string, func()) { func Setup(t *testing.T) (string, func(), LocalRegistry) {
tmpdir, err := os.MkdirTemp("", "docker-test") tmpdir, err := os.MkdirTemp("", "docker-test")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
backup := socketsPath backup := socketsPath
socketsPath = tmpdir socketsPath = tmpdir
globalSpecsPaths = []string{tmpdir}
return tmpdir, func() { return tmpdir, func() {
socketsPath = backup socketsPath = backup
os.RemoveAll(tmpdir) os.RemoveAll(tmpdir)
} }, LocalRegistry{
func() []string {
return []string{tmpdir}
},
}
} }
func TestFileSpecPlugin(t *testing.T) { func TestFileSpecPlugin(t *testing.T) {
tmpdir, unregister := Setup(t) tmpdir, unregister, r := Setup(t)
defer unregister() defer unregister()
cases := []struct { cases := []struct {
@ -47,7 +50,6 @@ func TestFileSpecPlugin(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := newLocalRegistry()
p, err := r.Plugin(c.name) p, err := r.Plugin(c.name)
if c.fail && err == nil { if c.fail && err == nil {
continue continue
@ -72,7 +74,7 @@ func TestFileSpecPlugin(t *testing.T) {
} }
func TestFileJSONSpecPlugin(t *testing.T) { func TestFileJSONSpecPlugin(t *testing.T) {
tmpdir, unregister := Setup(t) tmpdir, unregister, r := Setup(t)
defer unregister() defer unregister()
p := filepath.Join(tmpdir, "example.json") p := filepath.Join(tmpdir, "example.json")
@ -90,7 +92,6 @@ func TestFileJSONSpecPlugin(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := newLocalRegistry()
plugin, err := r.Plugin("example") plugin, err := r.Plugin("example")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -118,7 +119,7 @@ func TestFileJSONSpecPlugin(t *testing.T) {
} }
func TestFileJSONSpecPluginWithoutTLSConfig(t *testing.T) { func TestFileJSONSpecPluginWithoutTLSConfig(t *testing.T) {
tmpdir, unregister := Setup(t) tmpdir, unregister, r := Setup(t)
defer unregister() defer unregister()
p := filepath.Join(tmpdir, "example.json") p := filepath.Join(tmpdir, "example.json")
@ -131,7 +132,6 @@ func TestFileJSONSpecPluginWithoutTLSConfig(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := newLocalRegistry()
plugin, err := r.Plugin("example") plugin, err := r.Plugin("example")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

View file

@ -9,18 +9,13 @@ import (
"github.com/docker/docker/pkg/rootless" "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 { func rootlessConfigPluginsPath() string {
configHome, err := homedir.GetConfigHome() configHome, err := homedir.GetConfigHome()
if err == nil { if err == nil {
return filepath.Join(configHome, "docker/plugins") return filepath.Join(configHome, "docker/plugins")
} }
return globalConfigPluginsPath return "/etc/docker/plugins"
} }
func rootlessLibPluginsPath() string { func rootlessLibPluginsPath() string {
@ -29,7 +24,7 @@ func rootlessLibPluginsPath() string {
return filepath.Join(libHome, "docker/plugins") return filepath.Join(libHome, "docker/plugins")
} }
return globalLibPluginsPath return "/usr/lib/docker/plugins"
} }
// SpecsPaths returns // SpecsPaths returns
@ -42,5 +37,5 @@ func SpecsPaths() []string {
return []string{rootlessConfigPluginsPath(), rootlessLibPluginsPath()} return []string{rootlessConfigPluginsPath(), rootlessLibPluginsPath()}
} }
return globalSpecsPaths return []string{"/etc/docker/plugins", "/usr/lib/docker/plugins"}
} }

View file

@ -16,7 +16,7 @@ import (
func TestLocalSocket(t *testing.T) { func TestLocalSocket(t *testing.T) {
// TODO Windows: Enable a similar version for Windows named pipes // TODO Windows: Enable a similar version for Windows named pipes
tmpdir, unregister := Setup(t) tmpdir, unregister, r := Setup(t)
defer unregister() defer unregister()
cases := []string{ cases := []string{
@ -34,7 +34,6 @@ func TestLocalSocket(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := newLocalRegistry()
p, err := r.Plugin("echo") p, err := r.Plugin("echo")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -64,10 +63,10 @@ func TestLocalSocket(t *testing.T) {
} }
func TestScan(t *testing.T) { func TestScan(t *testing.T) {
tmpdir, unregister := Setup(t) tmpdir, unregister, r := Setup(t)
defer unregister() defer unregister()
pluginNames, err := Scan() pluginNames, err := r.Scan()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -89,11 +88,10 @@ func TestScan(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := newLocalRegistry()
p, err := r.Plugin(name) p, err := r.Plugin(name)
assert.NilError(t, err) assert.NilError(t, err)
pluginNamesNotEmpty, err := Scan() pluginNamesNotEmpty, err := r.Scan()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -106,7 +104,7 @@ func TestScan(t *testing.T) {
} }
func TestScanNotPlugins(t *testing.T) { func TestScanNotPlugins(t *testing.T) {
tmpdir, unregister := Setup(t) tmpdir, unregister, localRegistry := Setup(t)
defer unregister() defer unregister()
// not that `Setup()` above sets the sockets path and spec path dirs, which // 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() defer f.Close()
names, err := Scan() names, err := localRegistry.Scan()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -146,7 +144,7 @@ func TestScanNotPlugins(t *testing.T) {
} }
defer f.Close() defer f.Close()
names, err = Scan() names, err = localRegistry.Scan()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -5,13 +5,11 @@ import (
"path/filepath" "path/filepath"
) )
var globalSpecsPaths = []string{filepath.Join(os.Getenv("programdata"), "docker", "plugins")}
// SpecsPaths returns // SpecsPaths returns
// { "%programdata%\docker\plugins" } on Windows, // { "%programdata%\docker\plugins" } on Windows,
// { "/etc/docker/plugins", "/usr/lib/docker/plugins" } on Unix in non-rootless mode, // { "/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 // { "$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. // with fallback to the corresponding path in non-rootless mode if $XDG_CONFIG_HOME or $HOME is not set.
func SpecsPaths() []string { func SpecsPaths() []string {
return globalSpecsPaths return []string{filepath.Join(os.Getenv("programdata"), "docker", "plugins")}
} }

View file

@ -123,7 +123,7 @@ func TestPluginWithNoManifest(t *testing.T) {
} }
func TestGetAll(t *testing.T) { func TestGetAll(t *testing.T) {
tmpdir, unregister := Setup(t) tmpdir, unregister, r := Setup(t)
defer unregister() defer unregister()
p := filepath.Join(tmpdir, "example.json") p := filepath.Join(tmpdir, "example.json")
@ -136,7 +136,6 @@ func TestGetAll(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
r := newLocalRegistry()
plugin, err := r.Plugin("example") plugin, err := r.Plugin("example")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -144,7 +143,7 @@ func TestGetAll(t *testing.T) {
plugin.Manifest = &Manifest{Implements: []string{"apple"}} plugin.Manifest = &Manifest{Implements: []string{"apple"}}
storage.plugins["example"] = plugin storage.plugins["example"] = plugin
fetchedPlugins, err := GetAll("apple") fetchedPlugins, err := r.GetAll("apple")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -201,7 +201,7 @@ func load(name string) (*Plugin, error) {
} }
func loadWithRetry(name string, retry bool) (*Plugin, error) { func loadWithRetry(name string, retry bool) (*Plugin, error) {
registry := newLocalRegistry() registry := NewLocalRegistry()
start := time.Now() start := time.Now()
var retries int var retries int
@ -293,8 +293,8 @@ func Handle(iface string, fn func(string, *Client)) {
} }
// GetAll returns all the plugins for the specified implementation // GetAll returns all the plugins for the specified implementation
func GetAll(imp string) ([]*Plugin, error) { func (l *LocalRegistry) GetAll(imp string) ([]*Plugin, error) {
pluginNames, err := Scan() pluginNames, err := l.Scan()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -192,7 +192,8 @@ func (ps *Store) GetAllByCap(capability string) ([]plugingetter.CompatPlugin, er
// Lookup with legacy model // Lookup with legacy model
if allowV1PluginsFallback { if allowV1PluginsFallback {
pl, err := plugins.GetAll(capability) l := plugins.NewLocalRegistry()
pl, err := l.GetAll(capability)
if err != nil { if err != nil {
return nil, errors.Wrap(errdefs.System(err), "legacy plugin") return nil, errors.Wrap(errdefs.System(err), "legacy plugin")
} }