diff --git a/plugins/discovery.go b/plugins/discovery.go index 5ea8db5..3f79661 100644 --- a/plugins/discovery.go +++ b/plugins/discovery.go @@ -25,6 +25,38 @@ func newLocalRegistry() localRegistry { return localRegistry{} } +// Scan scans all the plugin paths and returns all the names it found +func Scan() ([]string, error) { + var names []string + if err := filepath.Walk(socketsPath, func(path string, fi os.FileInfo, err error) error { + if err != nil { + return nil + } + + if fi.Mode()&os.ModeSocket != 0 { + name := strings.TrimSuffix(fi.Name(), filepath.Ext(fi.Name())) + names = append(names, name) + } + return nil + }); err != nil { + return nil, err + } + + for _, path := range specsPaths { + if err := filepath.Walk(path, func(p string, fi os.FileInfo, err error) error { + if err != nil || fi.IsDir() { + return nil + } + name := strings.TrimSuffix(fi.Name(), filepath.Ext(fi.Name())) + names = append(names, name) + return nil + }); err != nil { + return nil, err + } + } + return names, nil +} + // Plugin returns the plugin registered with the given name (or returns an error). func (l *localRegistry) Plugin(name string) (*Plugin, error) { socketpaths := pluginPaths(socketsPath, name, ".sock") diff --git a/plugins/plugins.go b/plugins/plugins.go index 6317e4f..7157107 100644 --- a/plugins/plugins.go +++ b/plugins/plugins.go @@ -108,6 +108,15 @@ func (p *Plugin) activateWithLock() error { return nil } +func (p *Plugin) implements(kind string) bool { + for _, driver := range p.Manifest.Implements { + if driver == kind { + return true + } + } + return false +} + func load(name string) (*Plugin, error) { return loadWithRetry(name, true) } @@ -166,11 +175,9 @@ func Get(name, imp string) (*Plugin, error) { if err != nil { return nil, err } - for _, driver := range pl.Manifest.Implements { - logrus.Debugf("%s implements: %s", name, driver) - if driver == imp { - return pl, nil - } + if pl.implements(imp) { + logrus.Debugf("%s implements: %s", name, imp) + return pl, nil } return nil, ErrNotImplements } @@ -179,3 +186,37 @@ func Get(name, imp string) (*Plugin, error) { func Handle(iface string, fn func(string, *Client)) { extpointHandlers[iface] = fn } + +// GetAll returns all the plugins for the specified implementation +func GetAll(imp string) ([]*Plugin, error) { + pluginNames, err := Scan() + if err != nil { + return nil, err + } + + type plLoad struct { + pl *Plugin + err error + } + + chPl := make(chan plLoad, len(pluginNames)) + for _, name := range pluginNames { + go func(name string) { + pl, err := loadWithRetry(name, false) + chPl <- plLoad{pl, err} + }(name) + } + + var out []*Plugin + for i := 0; i < len(pluginNames); i++ { + pl := <-chPl + if pl.err != nil { + logrus.Error(err) + continue + } + if pl.pl.implements(imp) { + out = append(out, pl.pl) + } + } + return out, nil +}