2015-05-14 17:05:39 +00:00
|
|
|
package plugins
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
2015-05-27 22:21:18 +00:00
|
|
|
"github.com/docker/docker/pkg/tlsconfig"
|
2015-05-14 17:05:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrNotImplements = errors.New("Plugin does not implement the requested driver")
|
|
|
|
)
|
|
|
|
|
|
|
|
type plugins struct {
|
|
|
|
sync.Mutex
|
|
|
|
plugins map[string]*Plugin
|
|
|
|
}
|
|
|
|
|
2015-05-15 11:07:59 +00:00
|
|
|
var (
|
|
|
|
storage = plugins{plugins: make(map[string]*Plugin)}
|
|
|
|
extpointHandlers = make(map[string]func(string, *Client))
|
|
|
|
)
|
2015-05-14 17:05:39 +00:00
|
|
|
|
|
|
|
type Manifest struct {
|
|
|
|
Implements []string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Plugin struct {
|
2015-05-27 22:21:18 +00:00
|
|
|
Name string `json:"-"`
|
|
|
|
Addr string
|
|
|
|
TLSConfig tlsconfig.Options
|
|
|
|
Client *Client `json:"-"`
|
|
|
|
Manifest *Manifest `json:"-"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func newLocalPlugin(name, addr string) *Plugin {
|
|
|
|
return &Plugin{
|
|
|
|
Name: name,
|
|
|
|
Addr: addr,
|
|
|
|
TLSConfig: tlsconfig.Options{InsecureSkipVerify: true},
|
|
|
|
}
|
2015-05-14 17:05:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Plugin) activate() error {
|
2015-05-27 22:21:18 +00:00
|
|
|
c, err := NewClient(p.Addr, p.TLSConfig)
|
2015-05-14 17:05:39 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-05-27 22:21:18 +00:00
|
|
|
p.Client = c
|
|
|
|
|
|
|
|
m := new(Manifest)
|
|
|
|
if err = p.Client.Call("Plugin.Activate", nil, m); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-05-14 17:05:39 +00:00
|
|
|
|
|
|
|
logrus.Debugf("%s's manifest: %v", p.Name, m)
|
|
|
|
p.Manifest = m
|
2015-05-27 22:21:18 +00:00
|
|
|
|
2015-05-15 11:07:59 +00:00
|
|
|
for _, iface := range m.Implements {
|
|
|
|
handler, handled := extpointHandlers[iface]
|
|
|
|
if !handled {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
handler(p.Name, p.Client)
|
|
|
|
}
|
2015-05-14 17:05:39 +00:00
|
|
|
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
|
|
|
|
}
|
2015-05-15 11:07:59 +00:00
|
|
|
|
|
|
|
func Handle(iface string, fn func(string, *Client)) {
|
|
|
|
extpointHandlers[iface] = fn
|
|
|
|
}
|