1501e01cae
Signed-off-by: Madhu Venugopal <madhu@docker.com>
100 lines
1.7 KiB
Go
100 lines
1.7 KiB
Go
package plugins
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
)
|
|
|
|
var (
|
|
ErrNotImplements = errors.New("Plugin does not implement the requested driver")
|
|
)
|
|
|
|
type plugins struct {
|
|
sync.Mutex
|
|
plugins map[string]*Plugin
|
|
}
|
|
|
|
var (
|
|
storage = plugins{plugins: make(map[string]*Plugin)}
|
|
extpointHandlers = make(map[string]func(string, *Client))
|
|
)
|
|
|
|
type Manifest struct {
|
|
Implements []string
|
|
}
|
|
|
|
type Plugin struct {
|
|
Name string
|
|
Addr string
|
|
Client *Client
|
|
Manifest *Manifest
|
|
}
|
|
|
|
func (p *Plugin) activate() error {
|
|
m := new(Manifest)
|
|
p.Client = NewClient(p.Addr)
|
|
err := p.Client.Call("Plugin.Activate", nil, m)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
logrus.Debugf("%s's manifest: %v", p.Name, m)
|
|
p.Manifest = m
|
|
for _, iface := range m.Implements {
|
|
handler, handled := extpointHandlers[iface]
|
|
if !handled {
|
|
continue
|
|
}
|
|
handler(p.Name, p.Client)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func load(name string) (*Plugin, error) {
|
|
registry := newLocalRegistry("")
|
|
pl, err := registry.Plugin(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := pl.activate(); err != nil {
|
|
return nil, err
|
|
}
|
|
return pl, nil
|
|
}
|
|
|
|
func get(name string) (*Plugin, error) {
|
|
storage.Lock()
|
|
defer storage.Unlock()
|
|
pl, ok := storage.plugins[name]
|
|
if ok {
|
|
return pl, nil
|
|
}
|
|
pl, err := load(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
logrus.Debugf("Plugin: %v", pl)
|
|
storage.plugins[name] = pl
|
|
return pl, nil
|
|
}
|
|
|
|
func Get(name, imp string) (*Plugin, error) {
|
|
pl, err := get(name)
|
|
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
|
|
}
|
|
}
|
|
return nil, ErrNotImplements
|
|
}
|
|
|
|
func Handle(iface string, fn func(string, *Client)) {
|
|
extpointHandlers[iface] = fn
|
|
}
|