Setup plugin ids and dependencies
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
36
plugin/context.go
Normal file
36
plugin/context.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func NewContext(plugins map[PluginType][]interface{}) *InitContext {
|
||||
return &InitContext{
|
||||
plugins: plugins,
|
||||
}
|
||||
}
|
||||
|
||||
type InitContext struct {
|
||||
Root string
|
||||
Context context.Context
|
||||
Config interface{}
|
||||
|
||||
plugins map[PluginType][]interface{}
|
||||
}
|
||||
|
||||
func (i *InitContext) Get(t PluginType) (interface{}, error) {
|
||||
p := i.plugins[t]
|
||||
if len(p) == 0 {
|
||||
return nil, fmt.Errorf("no plugins registered for %s", t)
|
||||
}
|
||||
return p[0], nil
|
||||
}
|
||||
|
||||
func (i *InitContext) GetAll(t PluginType) ([]interface{}, error) {
|
||||
p, ok := i.plugins[t]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no plugins registered for %s", t)
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package plugin
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrUnknownRuntime = errors.New("unknown runtime")
|
||||
ErrContainerExists = errors.New("container with id already exists")
|
||||
ErrContainerNotExist = errors.New("container does not exist")
|
||||
ErrRuntimeNotExist = errors.New("runtime does not exist")
|
||||
|
||||
@@ -1,45 +1,42 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/snapshot"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type PluginType int
|
||||
var (
|
||||
ErrNoPluginType = errors.New("plugin: no type")
|
||||
ErrNoPluginID = errors.New("plugin: no id")
|
||||
)
|
||||
|
||||
type PluginType string
|
||||
|
||||
const (
|
||||
RuntimePlugin PluginType = iota + 1
|
||||
GRPCPlugin
|
||||
SnapshotPlugin
|
||||
TaskMonitorPlugin
|
||||
DiffPlugin
|
||||
RuntimePlugin PluginType = "io.containerd.runtime.v1"
|
||||
GRPCPlugin PluginType = "io.containerd.grpc.v1"
|
||||
SnapshotPlugin PluginType = "io.containerd.snapshotter.v1"
|
||||
TaskMonitorPlugin PluginType = "io.containerd.monitor.v1"
|
||||
DiffPlugin PluginType = "io.containerd.differ.v1"
|
||||
MetadataPlugin PluginType = "io.containerd.metadata.v1"
|
||||
ContentPlugin PluginType = "io.containerd.content.v1"
|
||||
)
|
||||
|
||||
type Registration struct {
|
||||
Type PluginType
|
||||
Config interface{}
|
||||
Init func(*InitContext) (interface{}, error)
|
||||
Type PluginType
|
||||
ID string
|
||||
Config interface{}
|
||||
Requires []PluginType
|
||||
Init func(*InitContext) (interface{}, error)
|
||||
|
||||
added bool
|
||||
}
|
||||
|
||||
// TODO(@crosbymichael): how do we keep this struct from growing but support dependency injection for loaded plugins?
|
||||
type InitContext struct {
|
||||
Root string
|
||||
State string
|
||||
Runtimes map[string]Runtime
|
||||
Content content.Store
|
||||
Meta *bolt.DB
|
||||
Snapshotter snapshot.Snapshotter
|
||||
Differ Differ
|
||||
Config interface{}
|
||||
Context context.Context
|
||||
Monitor TaskMonitor
|
||||
func (r *Registration) URI() string {
|
||||
return fmt.Sprintf("%s.%s", r.Type, r.ID)
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
@@ -48,10 +45,8 @@ type Service interface {
|
||||
|
||||
var register = struct {
|
||||
sync.Mutex
|
||||
r map[string]*Registration
|
||||
}{
|
||||
r: make(map[string]*Registration),
|
||||
}
|
||||
r []*Registration
|
||||
}{}
|
||||
|
||||
// Load loads all plugins at the provided path into containerd
|
||||
func Load(path string) (err error) {
|
||||
@@ -67,16 +62,39 @@ func Load(path string) (err error) {
|
||||
return loadPlugins(path)
|
||||
}
|
||||
|
||||
func Register(name string, r *Registration) error {
|
||||
func Register(r *Registration) {
|
||||
register.Lock()
|
||||
defer register.Unlock()
|
||||
if _, ok := register.r[name]; ok {
|
||||
return fmt.Errorf("plugin already registered as %q", name)
|
||||
if r.Type == "" {
|
||||
panic(ErrNoPluginType)
|
||||
}
|
||||
register.r[name] = r
|
||||
return nil
|
||||
if r.ID == "" {
|
||||
panic(ErrNoPluginID)
|
||||
}
|
||||
register.r = append(register.r, r)
|
||||
}
|
||||
|
||||
func Registrations() map[string]*Registration {
|
||||
return register.r
|
||||
func Graph() (ordered []*Registration) {
|
||||
for _, r := range register.r {
|
||||
children(r.Requires, &ordered)
|
||||
if !r.added {
|
||||
ordered = append(ordered, r)
|
||||
r.added = true
|
||||
}
|
||||
}
|
||||
return ordered
|
||||
}
|
||||
|
||||
func children(types []PluginType, ordered *[]*Registration) {
|
||||
for _, t := range types {
|
||||
for _, r := range register.r {
|
||||
if r.Type == t {
|
||||
children(r.Requires, ordered)
|
||||
if !r.added {
|
||||
*ordered = append(*ordered, r)
|
||||
r.added = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ type Exit struct {
|
||||
// Runtime is responsible for the creation of containers for a certain platform,
|
||||
// arch, or custom usage.
|
||||
type Runtime interface {
|
||||
// ID of the runtime
|
||||
ID() string
|
||||
// Create creates a container with the provided id and options
|
||||
Create(ctx context.Context, id string, opts CreateOpts) (Task, error)
|
||||
// Get returns a container
|
||||
|
||||
Reference in New Issue
Block a user