Generalize the plugin package

Remove containerd specific parts of the plugin package to prepare its
move out of the main repository. Separate the plugin registration
singleton into a separate package.

Separating out the plugin package and registration makes it easier to
implement external plugins without creating a dependency loop.

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2023-10-12 15:36:02 -07:00
parent a80606bc2d
commit 7b2a918213
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB
65 changed files with 363 additions and 299 deletions

View File

@ -24,7 +24,7 @@ import (
"github.com/containerd/containerd/defaults" "github.com/containerd/containerd/defaults"
"github.com/containerd/containerd/images" "github.com/containerd/containerd/images"
"github.com/containerd/containerd/pkg/timeout" "github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/services/server" "github.com/containerd/containerd/services/server"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -46,7 +46,7 @@ func outputConfig(ctx gocontext.Context, config *srvconfig.Config) error {
continue continue
} }
pc, err := config.Decode(ctx, p) pc, err := config.Decode(ctx, p.URI(), p.Config)
if err != nil { if err != nil {
return err return err
} }
@ -113,7 +113,7 @@ var configCommand = cli.Command{
} }
if config.Version < srvconfig.CurrentConfigVersion { if config.Version < srvconfig.CurrentConfigVersion {
plugins := plugin.Graph(srvconfig.V2DisabledFilter(config.DisabledPlugins)) plugins := registry.Graph(srvconfig.V2DisabledFilter(config.DisabledPlugins))
for _, p := range plugins { for _, p := range plugins {
if p.ConfigMigration != nil { if p.ConfigMigration != nil {
if err := p.ConfigMigration(ctx, config.Version, config.Plugins); err != nil { if err := p.ConfigMigration(ctx, config.Version, config.Plugins); err != nil {

View File

@ -36,6 +36,7 @@ import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/log" "github.com/containerd/log"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
@ -48,7 +49,7 @@ const (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.DiffPlugin, Type: plugins.DiffPlugin,
ID: "windows-lcow", ID: "windows-lcow",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -23,11 +23,12 @@ import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.DiffPlugin, Type: plugins.DiffPlugin,
ID: "walking", ID: "walking",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -39,6 +39,7 @@ import (
"github.com/containerd/containerd/pkg/epoch" "github.com/containerd/containerd/pkg/epoch"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/log" "github.com/containerd/log"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
@ -46,7 +47,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.DiffPlugin, Type: plugins.DiffPlugin,
ID: "windows", ID: "windows",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -19,11 +19,12 @@ package plugin
import ( import (
"github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/events/exchange"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.EventPlugin, Type: plugins.EventPlugin,
ID: "exchange", ID: "exchange",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {

View File

@ -25,6 +25,7 @@ import (
"github.com/containerd/containerd/gc" "github.com/containerd/containerd/gc"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/log" "github.com/containerd/log"
) )
@ -97,7 +98,7 @@ func (d duration) MarshalText() (text []byte, err error) {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GCPlugin, Type: plugins.GCPlugin,
ID: "scheduler", ID: "scheduler",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -26,6 +26,7 @@ import (
"github.com/containerd/containerd/pkg/cri/constants" "github.com/containerd/containerd/pkg/cri/constants"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
ctrdsrv "github.com/containerd/containerd/services/server" ctrdsrv "github.com/containerd/containerd/services/server"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
"github.com/containerd/log/logtest" "github.com/containerd/log/logtest"
@ -54,7 +55,7 @@ import (
var ( var (
loadPluginOnce sync.Once loadPluginOnce sync.Once
loadedPlugins []*plugin.Registration loadedPlugins []plugin.Registration
loadedPluginsErr error loadedPluginsErr error
) )
@ -88,15 +89,16 @@ func buildLocalContainerdClient(t *testing.T, tmpDir string) *containerd.Client
for _, p := range loadedPlugins { for _, p := range loadedPlugins {
initContext := plugin.NewContext( initContext := plugin.NewContext(
ctx, ctx,
p,
initialized, initialized,
config.Root, map[string]string{
config.State, plugins.PropertyRootDir: filepath.Join(config.Root, p.URI()),
plugins.PropertyStateDir: filepath.Join(config.State, p.URI()),
},
) )
// load the plugin specific configuration if it is provided // load the plugin specific configuration if it is provided
if p.Config != nil { if p.Config != nil {
pc, err := config.Decode(ctx, p) pc, err := config.Decode(ctx, p.URI(), p.Config)
assert.NoError(t, err) assert.NoError(t, err)
initContext.Config = pc initContext.Config = pc

View File

@ -28,6 +28,7 @@ import (
"github.com/containerd/containerd/pkg/failpoint" "github.com/containerd/containerd/pkg/failpoint"
"github.com/containerd/containerd/pkg/shutdown" "github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/runc/task" "github.com/containerd/containerd/runtime/v2/runc/task"
"github.com/containerd/containerd/runtime/v2/shim" "github.com/containerd/containerd/runtime/v2/shim"
@ -39,7 +40,7 @@ const (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin, Type: plugins.TTRPCPlugin,
ID: "task", ID: "task",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -23,11 +23,12 @@ import (
"github.com/containerd/containerd/leases" "github.com/containerd/containerd/leases"
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.LeasePlugin, Type: plugins.LeasePlugin,
ID: "manager", ID: "manager",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -28,6 +28,7 @@ import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/pkg/timeout" "github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots" "github.com/containerd/containerd/snapshots"
"github.com/containerd/log" "github.com/containerd/log"
@ -82,7 +83,7 @@ func (bc *BoltConfig) Validate() error {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.MetadataPlugin, Type: plugins.MetadataPlugin,
ID: "bolt", ID: "bolt",
Requires: []plugin.Type{ Requires: []plugin.Type{
@ -94,7 +95,8 @@ func init() {
ContentSharingPolicy: SharingPolicyShared, ContentSharingPolicy: SharingPolicyShared,
}, },
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
if err := os.MkdirAll(ic.Root, 0711); err != nil { root := ic.Properties[plugins.PropertyRootDir]
if err := os.MkdirAll(root, 0711); err != nil {
return nil, err return nil, err
} }
cs, err := ic.Get(plugins.ContentPlugin) cs, err := ic.Get(plugins.ContentPlugin)
@ -141,7 +143,7 @@ func init() {
} }
} }
path := filepath.Join(ic.Root, "meta.db") path := filepath.Join(root, "meta.db")
ic.Meta.Exports["path"] = path ic.Meta.Exports["path"] = path
options := *bolt.DefaultOptions options := *bolt.DefaultOptions

View File

@ -25,6 +25,7 @@ import (
v2 "github.com/containerd/containerd/metrics/cgroups/v2" v2 "github.com/containerd/containerd/metrics/cgroups/v2"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime" "github.com/containerd/containerd/runtime"
metrics "github.com/docker/go-metrics" metrics "github.com/docker/go-metrics"
@ -36,7 +37,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.TaskMonitorPlugin, Type: plugins.TaskMonitorPlugin,
ID: "cgroups", ID: "cgroups",
InitFn: New, InitFn: New,

View File

@ -27,6 +27,7 @@ import (
nriservice "github.com/containerd/containerd/pkg/nri" nriservice "github.com/containerd/containerd/pkg/nri"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/log" "github.com/containerd/log"
imagespec "github.com/opencontainers/image-spec/specs-go/v1" imagespec "github.com/opencontainers/image-spec/specs-go/v1"
@ -39,7 +40,7 @@ import (
// Register CRI service plugin // Register CRI service plugin
func init() { func init() {
config := criconfig.DefaultConfig() config := criconfig.DefaultConfig()
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "cri", ID: "cri",
Config: &config, Config: &config,
@ -63,10 +64,10 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
c := criconfig.Config{ c := criconfig.Config{
PluginConfig: *pluginConfig, PluginConfig: *pluginConfig,
ContainerdRootDir: filepath.Dir(ic.Root), ContainerdRootDir: filepath.Dir(ic.Properties[plugins.PropertyRootDir]),
ContainerdEndpoint: ic.Address, ContainerdEndpoint: ic.Properties[plugins.PropertyGRPCAddress],
RootDir: ic.Root, RootDir: ic.Properties[plugins.PropertyRootDir],
StateDir: ic.State, StateDir: ic.Properties[plugins.PropertyStateDir],
} }
log.G(ctx).Infof("Start cri plugin with config %+v", c) log.G(ctx).Infof("Start cri plugin with config %+v", c)

View File

@ -19,11 +19,12 @@ package plugin
import ( import (
"github.com/containerd/containerd/pkg/nri" "github.com/containerd/containerd/pkg/nri"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.NRIApiPlugin, Type: plugins.NRIApiPlugin,
ID: "nri", ID: "nri",
Config: nri.DefaultConfig(), Config: nri.DefaultConfig(),

View File

@ -19,20 +19,15 @@ package plugin
import ( import (
"context" "context"
"fmt" "fmt"
"path/filepath"
"github.com/containerd/containerd/errdefs" imagespec "github.com/opencontainers/image-spec/specs-go/v1"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
// InitContext is used for plugin initialization // InitContext is used for plugin initialization
type InitContext struct { type InitContext struct {
Context context.Context Context context.Context
Root string Properties map[string]string
State string
Config interface{} Config interface{}
Address string
TTRPCAddress string
RegisterReadiness func() func() RegisterReadiness func() func()
// Meta is metadata plugins can fill in at init // Meta is metadata plugins can fill in at init
@ -42,11 +37,13 @@ type InitContext struct {
} }
// NewContext returns a new plugin InitContext // NewContext returns a new plugin InitContext
func NewContext(ctx context.Context, r *Registration, plugins *Set, root, state string) *InitContext { func NewContext(ctx context.Context, plugins *Set, properties map[string]string) *InitContext {
if properties == nil {
properties = map[string]string{}
}
return &InitContext{ return &InitContext{
Context: ctx, Context: ctx,
Root: filepath.Join(root, r.URI()), Properties: properties,
State: filepath.Join(state, r.URI()),
Meta: &Meta{ Meta: &Meta{
Exports: map[string]string{}, Exports: map[string]string{},
}, },
@ -62,16 +59,16 @@ func (i *InitContext) Get(t Type) (interface{}, error) {
// Meta contains information gathered from the registration and initialization // Meta contains information gathered from the registration and initialization
// process. // process.
type Meta struct { type Meta struct {
Platforms []ocispec.Platform // platforms supported by plugin Platforms []imagespec.Platform // platforms supported by plugin
Exports map[string]string // values exported by plugin Exports map[string]string // values exported by plugin
Capabilities []string // feature switches for plugin Capabilities []string // feature switches for plugin
} }
// Plugin represents an initialized plugin, used with an init context. // Plugin represents an initialized plugin, used with an init context.
type Plugin struct { type Plugin struct {
Registration *Registration // registration, as initialized Registration Registration // registration, as initialized
Config interface{} // config, as initialized Config interface{} // config, as initialized
Meta *Meta Meta Meta
instance interface{} instance interface{}
err error // will be set if there was an error initializing the plugin err error // will be set if there was an error initializing the plugin
@ -115,7 +112,7 @@ func (ps *Set) Add(p *Plugin) error {
} else if _, idok := byID[p.Registration.ID]; !idok { } else if _, idok := byID[p.Registration.ID]; !idok {
byID[p.Registration.ID] = p byID[p.Registration.ID] = p
} else { } else {
return fmt.Errorf("plugin %v already initialized: %w", p.Registration.URI(), errdefs.ErrAlreadyExists) return fmt.Errorf("plugin add failed for %s: %w", p.Registration.URI(), ErrPluginInitialized)
} }
ps.ordered = append(ps.ordered, p) ps.ordered = append(ps.ordered, p)
@ -127,7 +124,7 @@ func (ps *Set) Get(t Type) (interface{}, error) {
for _, v := range ps.byTypeAndID[t] { for _, v := range ps.byTypeAndID[t] {
return v.Instance() return v.Instance()
} }
return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
} }
// GetAll returns all initialized plugins // GetAll returns all initialized plugins
@ -153,7 +150,7 @@ func (i *InitContext) GetByID(t Type, id string) (interface{}, error) {
} }
p, ok := ps[id] p, ok := ps[id]
if !ok { if !ok {
return nil, fmt.Errorf("no %s plugins with id %s: %w", t, id, errdefs.ErrNotFound) return nil, fmt.Errorf("no %s plugins with id %s: %w", t, id, ErrPluginNotFound)
} }
return p.Instance() return p.Instance()
} }
@ -162,7 +159,7 @@ func (i *InitContext) GetByID(t Type, id string) (interface{}, error) {
func (i *InitContext) GetByType(t Type) (map[string]*Plugin, error) { func (i *InitContext) GetByType(t Type) (map[string]*Plugin, error) {
p, ok := i.plugins.byTypeAndID[t] p, ok := i.plugins.byTypeAndID[t]
if !ok { if !ok {
return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
} }
return p, nil return p, nil

View File

@ -20,7 +20,6 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"sync"
) )
var ( var (
@ -34,6 +33,10 @@ var (
// this allows the plugin loader differentiate between a plugin which is configured // this allows the plugin loader differentiate between a plugin which is configured
// not to load and one that fails to load. // not to load and one that fails to load.
ErrSkipPlugin = errors.New("skip plugin") ErrSkipPlugin = errors.New("skip plugin")
// ErrPluginInitialized is used when a plugin is already initialized
ErrPluginInitialized = errors.New("plugin: already initialized")
// ErrPluginNotFound is used when a plugin is looked up but not found
ErrPluginNotFound = errors.New("plugin: not found")
// ErrInvalidRequires will be thrown if the requirements for a plugin are // ErrInvalidRequires will be thrown if the requirements for a plugin are
// defined in an invalid manner. // defined in an invalid manner.
@ -65,8 +68,6 @@ type Registration struct {
// context are passed in. The init function may modify the registration to // context are passed in. The init function may modify the registration to
// add exports, capabilities and platform support declarations. // add exports, capabilities and platform support declarations.
InitFn func(*InitContext) (interface{}, error) InitFn func(*InitContext) (interface{}, error)
// Disable the plugin from loading
Disable bool
// ConfigMigration allows a plugin to migrate configurations from an older // ConfigMigration allows a plugin to migrate configurations from an older
// version to handle plugin renames or moving of features from one plugin // version to handle plugin renames or moving of features from one plugin
@ -79,12 +80,12 @@ type Registration struct {
} }
// Init the registered plugin // Init the registered plugin
func (r *Registration) Init(ic *InitContext) *Plugin { func (r Registration) Init(ic *InitContext) *Plugin {
p, err := r.InitFn(ic) p, err := r.InitFn(ic)
return &Plugin{ return &Plugin{
Registration: r, Registration: r,
Config: ic.Config, Config: ic.Config,
Meta: ic.Meta, Meta: *ic.Meta,
instance: p, instance: p,
err: err, err: err,
} }
@ -95,11 +96,6 @@ func (r *Registration) URI() string {
return r.Type.String() + "." + r.ID return r.Type.String() + "." + r.ID
} }
var register = struct {
sync.RWMutex
r []*Registration
}{}
// Load loads all plugins at the provided path into containerd. // Load loads all plugins at the provided path into containerd.
// //
// Load is currently only implemented on non-static, non-gccgo builds for amd64 // Load is currently only implemented on non-static, non-gccgo builds for amd64
@ -118,18 +114,64 @@ func Load(path string) (err error) {
return loadPlugins(path) return loadPlugins(path)
} }
// Register allows plugins to register // DisableFilter filters out disabled plugins
func Register(r *Registration) { type DisableFilter func(r *Registration) bool
register.Lock()
defer register.Unlock()
// Registry is list of registrations which can be registered to and
// produce a filtered and ordered output.
// The Registry itself is immutable and the list will be copied
// and appeneded to a new registry when new items are registered.
type Registry []*Registration
// Graph computes the ordered list of registrations based on their dependencies,
// filtering out any plugins which match the provided filter.
func (registry Registry) Graph(filter DisableFilter) []Registration {
disabled := map[*Registration]bool{}
for _, r := range registry {
if filter(r) {
disabled[r] = true
}
}
ordered := make([]Registration, 0, len(registry)-len(disabled))
added := map[*Registration]bool{}
for _, r := range registry {
if disabled[r] {
continue
}
children(r, registry, added, disabled, &ordered)
if !added[r] {
ordered = append(ordered, *r)
added[r] = true
}
}
return ordered
}
func children(reg *Registration, registry []*Registration, added, disabled map[*Registration]bool, ordered *[]Registration) {
for _, t := range reg.Requires {
for _, r := range registry {
if !disabled[r] && r.URI() != reg.URI() && (t == "*" || r.Type == t) {
children(r, registry, added, disabled, ordered)
if !added[r] {
*ordered = append(*ordered, *r)
added[r] = true
}
}
}
}
}
// Register adds the registration to a Registry and returns the
// updated Registry, panicking if registration could not succeed.
func (registry Registry) Register(r *Registration) Registry {
if r.Type == "" { if r.Type == "" {
panic(ErrNoType) panic(ErrNoType)
} }
if r.ID == "" { if r.ID == "" {
panic(ErrNoPluginID) panic(ErrNoPluginID)
} }
if err := checkUnique(r); err != nil { if err := checkUnique(registry, r); err != nil {
panic(err) panic(err)
} }
@ -139,66 +181,14 @@ func Register(r *Registration) {
} }
} }
register.r = append(register.r, r) return append(registry, r)
} }
// Reset removes all global registrations func checkUnique(registry Registry, r *Registration) error {
func Reset() { for _, registered := range registry {
register.Lock()
defer register.Unlock()
register.r = nil
}
func checkUnique(r *Registration) error {
for _, registered := range register.r {
if r.URI() == registered.URI() { if r.URI() == registered.URI() {
return fmt.Errorf("%s: %w", r.URI(), ErrIDRegistered) return fmt.Errorf("%s: %w", r.URI(), ErrIDRegistered)
} }
} }
return nil return nil
} }
// DisableFilter filters out disabled plugins
type DisableFilter func(r *Registration) bool
// Graph returns an ordered list of registered plugins for initialization.
// Plugins in disableList specified by id will be disabled.
func Graph(filter DisableFilter) (ordered []*Registration) {
register.RLock()
defer register.RUnlock()
for _, r := range register.r {
if filter(r) {
r.Disable = true
}
}
added := map[*Registration]bool{}
for _, r := range register.r {
if r.Disable {
continue
}
children(r, added, &ordered)
if !added[r] {
ordered = append(ordered, r)
added[r] = true
}
}
return ordered
}
func children(reg *Registration, added map[*Registration]bool, ordered *[]*Registration) {
for _, t := range reg.Requires {
for _, r := range register.r {
if !r.Disable &&
r.URI() != reg.URI() &&
(t == "*" || r.Type == t) {
children(r, added, ordered)
if !added[r] {
*ordered = append(*ordered, r)
added[r] = true
}
}
}
}
}

View File

@ -22,19 +22,12 @@ import (
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
) )
func registerClear() {
register.Lock()
defer register.Unlock()
register.r = nil
}
func mockPluginFilter(*Registration) bool { func mockPluginFilter(*Registration) bool {
return false return false
} }
// TestContainerdPlugin tests the logic of Graph, use the containerd's plugin // TestContainerdPlugin tests the logic of Graph, use the containerd's plugin
func TestContainerdPlugin(t *testing.T) { func TestContainerdPlugin(t *testing.T) {
registerClear()
// Plugin types commonly used by containerd // Plugin types commonly used by containerd
const ( const (
InternalPlugin Type = "io.containerd.internal.v1" InternalPlugin Type = "io.containerd.internal.v1"
@ -52,11 +45,11 @@ func TestContainerdPlugin(t *testing.T) {
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1" TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
) )
Register(&Registration{ var register Registry
register = register.Register(&Registration{
Type: TaskMonitorPlugin, Type: TaskMonitorPlugin,
ID: "cgroups", ID: "cgroups",
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.TasksService, ID: services.TasksService,
Requires: []Type{ Requires: []Type{
@ -65,199 +58,165 @@ func TestContainerdPlugin(t *testing.T) {
MetadataPlugin, MetadataPlugin,
TaskMonitorPlugin, TaskMonitorPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.IntrospectionService, ID: services.IntrospectionService,
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.NamespacesService, ID: services.NamespacesService,
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "namespaces", ID: "namespaces",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "content", ID: "content",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "containers", ID: "containers",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.ContainersService, ID: services.ContainersService,
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "events", ID: "events",
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "leases", ID: "leases",
Requires: []Type{ Requires: []Type{
LeasePlugin, LeasePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: LeasePlugin, Type: LeasePlugin,
ID: "manager", ID: "manager",
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "diff", ID: "diff",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.DiffService, ID: services.DiffService,
Requires: []Type{ Requires: []Type{
DiffPlugin, DiffPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.SnapshotsService, ID: services.SnapshotsService,
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "snapshots", ID: "snapshots",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "version", ID: "version",
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "images", ID: "images",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GCPlugin, Type: GCPlugin,
ID: "scheduler", ID: "scheduler",
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: RuntimePluginV2, Type: RuntimePluginV2,
ID: "task", ID: "task",
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "tasks", ID: "tasks",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "introspection", ID: "introspection",
Requires: []Type{"*"}, Requires: []Type{"*"},
}) }).Register(&Registration{
Register(&Registration{
Type: ServicePlugin, Type: ServicePlugin,
ID: services.ContentService, ID: services.ContentService,
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "healthcheck", ID: "healthcheck",
}) }).Register(&Registration{
Register(&Registration{
Type: InternalPlugin, Type: InternalPlugin,
ID: "opt", ID: "opt",
}) }).Register(&Registration{
Register(&Registration{
Type: GRPCPlugin, Type: GRPCPlugin,
ID: "cri", ID: "cri",
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: RuntimePlugin, Type: RuntimePlugin,
ID: "linux", ID: "linux",
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: InternalPlugin, Type: InternalPlugin,
Requires: []Type{ Requires: []Type{
ServicePlugin, ServicePlugin,
}, },
ID: "restart", ID: "restart",
}) }).Register(&Registration{
Register(&Registration{
Type: DiffPlugin, Type: DiffPlugin,
ID: "walking", ID: "walking",
Requires: []Type{ Requires: []Type{
MetadataPlugin, MetadataPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: SnapshotPlugin, Type: SnapshotPlugin,
ID: "native", ID: "native",
}) }).Register(&Registration{
Register(&Registration{
Type: SnapshotPlugin, Type: SnapshotPlugin,
ID: "overlayfs", ID: "overlayfs",
}) }).Register(&Registration{
Register(&Registration{
Type: ContentPlugin, Type: ContentPlugin,
ID: "content", ID: "content",
}) }).Register(&Registration{
Register(&Registration{
Type: MetadataPlugin, Type: MetadataPlugin,
ID: "bolt", ID: "bolt",
Requires: []Type{ Requires: []Type{
ContentPlugin, ContentPlugin,
SnapshotPlugin, SnapshotPlugin,
}, },
}) }).Register(&Registration{
Register(&Registration{
Type: TracingProcessorPlugin, Type: TracingProcessorPlugin,
ID: "otlp", ID: "otlp",
}) }).Register(&Registration{
Register(&Registration{
Type: InternalPlugin, Type: InternalPlugin,
ID: "tracing", ID: "tracing",
Requires: []Type{ Requires: []Type{
@ -265,7 +224,7 @@ func TestContainerdPlugin(t *testing.T) {
}, },
}) })
ordered := Graph(mockPluginFilter) ordered := register.Graph(mockPluginFilter)
expectedURI := []string{ expectedURI := []string{
"io.containerd.monitor.v1.cgroups", "io.containerd.monitor.v1.cgroups",
"io.containerd.content.v1.content", "io.containerd.content.v1.content",
@ -305,7 +264,7 @@ func TestContainerdPlugin(t *testing.T) {
cmpOrdered(t, ordered, expectedURI) cmpOrdered(t, ordered, expectedURI)
} }
func cmpOrdered(t *testing.T, ordered []*Registration, expectedURI []string) { func cmpOrdered(t *testing.T, ordered []Registration, expectedURI []string) {
if len(ordered) != len(expectedURI) { if len(ordered) != len(expectedURI) {
t.Fatalf("ordered compare failed, %d != %d", len(ordered), len(expectedURI)) t.Fatalf("ordered compare failed, %d != %d", len(ordered), len(expectedURI))
} }
@ -321,6 +280,7 @@ func TestPluginGraph(t *testing.T) {
for _, testcase := range []struct { for _, testcase := range []struct {
input []*Registration input []*Registration
expectedURI []string expectedURI []string
filter DisableFilter
}{ }{
// test requires * // test requires *
{ {
@ -397,19 +357,25 @@ func TestPluginGraph(t *testing.T) {
{ {
Type: "disable", Type: "disable",
ID: "disable", ID: "disable",
Disable: true,
}, },
}, },
expectedURI: []string{ expectedURI: []string{
"content.content", "content.content",
}, },
filter: func(r *Registration) bool {
return r.Type == "disable"
},
}, },
} { } {
registerClear() var register Registry
for _, in := range testcase.input { for _, in := range testcase.input {
Register(in) register = register.Register(in)
} }
ordered := Graph(mockPluginFilter) var filter DisableFilter = mockPluginFilter
if testcase.filter != nil {
filter = testcase.filter
}
ordered := register.Graph(filter)
cmpOrdered(t, ordered, testcase.expectedURI) cmpOrdered(t, ordered, testcase.expectedURI)
} }
} }

View File

@ -0,0 +1,50 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package registry
import (
"sync"
"github.com/containerd/containerd/plugin"
)
var register = struct {
sync.RWMutex
r plugin.Registry
}{}
// Register allows plugins to register
func Register(r *plugin.Registration) {
register.Lock()
defer register.Unlock()
register.r = register.r.Register(r)
}
// Reset removes all global registrations
func Reset() {
register.Lock()
defer register.Unlock()
register.r = nil
}
// Graph returns an ordered list of registered plugins for initialization.
// Plugins in disableList specified by id will be disabled.
func Graph(filter plugin.DisableFilter) []plugin.Registration {
register.RLock()
defer register.RUnlock()
return register.r.Graph(filter)
}

View File

@ -22,12 +22,13 @@ import (
"github.com/containerd/containerd/pkg/imageverifier/bindir" "github.com/containerd/containerd/pkg/imageverifier/bindir"
"github.com/containerd/containerd/pkg/tomlext" "github.com/containerd/containerd/pkg/tomlext"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
// Register default image verifier service plugin // Register default image verifier service plugin
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ImageVerifierPlugin, Type: plugins.ImageVerifierPlugin,
ID: "bindir", ID: "bindir",
Config: defaultConfig(), Config: defaultConfig(),

View File

@ -29,6 +29,7 @@ import (
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime" "github.com/containerd/containerd/runtime"
v2 "github.com/containerd/containerd/runtime/v2" v2 "github.com/containerd/containerd/runtime/v2"
@ -39,7 +40,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SandboxControllerPlugin, Type: plugins.SandboxControllerPlugin,
ID: "local", ID: "local",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -19,11 +19,12 @@ package sandbox
import ( import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SandboxStorePlugin, Type: plugins.SandboxStorePlugin,
ID: "local", ID: "local",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -28,11 +28,12 @@ import (
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/streaming" "github.com/containerd/containerd/pkg/streaming"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.StreamingPlugin, Type: plugins.StreamingPlugin,
ID: "manager", ID: "manager",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -29,6 +29,7 @@ import (
"github.com/containerd/containerd/pkg/unpack" "github.com/containerd/containerd/pkg/unpack"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/log" "github.com/containerd/log"
@ -40,7 +41,7 @@ import (
// Register local transfer service plugin // Register local transfer service plugin
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.TransferPlugin, Type: plugins.TransferPlugin,
ID: "local", ID: "local",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -26,6 +26,7 @@ import (
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/restart" "github.com/containerd/containerd/runtime/restart"
"github.com/containerd/log" "github.com/containerd/log"
@ -52,7 +53,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.InternalPlugin, Type: plugins.InternalPlugin,
Requires: []plugin.Type{ Requires: []plugin.Type{
plugins.EventPlugin, plugins.EventPlugin,

View File

@ -24,6 +24,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/shutdown" "github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/runtime/v2/shim" "github.com/containerd/containerd/runtime/v2/shim"
@ -31,7 +32,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin, Type: plugins.TTRPCPlugin,
ID: "task", ID: "task",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -34,6 +34,7 @@ import (
"github.com/containerd/containerd/pkg/timeout" "github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/runtime" "github.com/containerd/containerd/runtime"
@ -51,7 +52,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.RuntimePluginV2, Type: plugins.RuntimePluginV2,
ID: "task", ID: "task",
Requires: []plugin.Type{ Requires: []plugin.Type{
@ -83,10 +84,10 @@ func init() {
events := ep.(*exchange.Exchange) events := ep.(*exchange.Exchange)
shimManager, err := NewShimManager(ic.Context, &ManagerConfig{ shimManager, err := NewShimManager(ic.Context, &ManagerConfig{
Root: ic.Root, Root: ic.Properties[plugins.PropertyRootDir],
State: ic.State, State: ic.Properties[plugins.PropertyStateDir],
Address: ic.Address, Address: ic.Properties[plugins.PropertyGRPCAddress],
TTRPCAddress: ic.TTRPCAddress, TTRPCAddress: ic.Properties[plugins.PropertyTTRPCAddress],
Events: events, Events: events,
Store: cs, Store: cs,
SchedCore: config.SchedCore, SchedCore: config.SchedCore,
@ -104,7 +105,7 @@ func init() {
// However, due to time limits and to avoid migration steps in 1.6 release, // However, due to time limits and to avoid migration steps in 1.6 release,
// use the following workaround. // use the following workaround.
// This expected to be removed in 1.7. // This expected to be removed in 1.7.
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.RuntimePluginV2, Type: plugins.RuntimePluginV2,
ID: "shim", ID: "shim",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {

View File

@ -24,6 +24,7 @@ import (
"github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types"
"github.com/containerd/containerd/pkg/shutdown" "github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/shim" "github.com/containerd/containerd/runtime/v2/shim"
"github.com/containerd/log" "github.com/containerd/log"
@ -34,7 +35,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin, Type: plugins.TTRPCPlugin,
ID: "pause", ID: "pause",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -19,13 +19,14 @@ package plugin
import ( import (
"github.com/containerd/containerd/pkg/shutdown" "github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/runc/task" "github.com/containerd/containerd/runtime/v2/runc/task"
"github.com/containerd/containerd/runtime/v2/shim" "github.com/containerd/containerd/runtime/v2/shim"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin, Type: plugins.TTRPCPlugin,
ID: "task", ID: "task",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -34,6 +34,7 @@ import (
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/shutdown" "github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/protobuf/proto" "github.com/containerd/containerd/protobuf/proto"
@ -284,7 +285,7 @@ func run(ctx context.Context, manager Manager, name string, config Config) error
} }
} }
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.InternalPlugin, Type: plugins.InternalPlugin,
ID: "shutdown", ID: "shutdown",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
@ -293,7 +294,7 @@ func run(ctx context.Context, manager Manager, name string, config Config) error
}) })
// Register event plugin // Register event plugin
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.EventPlugin, Type: plugins.EventPlugin,
ID: "publisher", ID: "publisher",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
@ -307,24 +308,24 @@ func run(ctx context.Context, manager Manager, name string, config Config) error
ttrpcUnaryInterceptors = []ttrpc.UnaryServerInterceptor{} ttrpcUnaryInterceptors = []ttrpc.UnaryServerInterceptor{}
) )
plugins := plugin.Graph(func(*plugin.Registration) bool { return false })
for _, p := range plugins { for _, p := range registry.Graph(func(*plugin.Registration) bool { return false }) {
id := p.URI() id := p.URI()
log.G(ctx).WithField("type", p.Type).Infof("loading plugin %q...", id) log.G(ctx).WithField("type", p.Type).Infof("loading plugin %q...", id)
initContext := plugin.NewContext( initContext := plugin.NewContext(
ctx, ctx,
p,
initialized, initialized,
map[string]string{
// NOTE: Root is empty since the shim does not support persistent storage, // NOTE: Root is empty since the shim does not support persistent storage,
// shim plugins should make use state directory for writing files to disk. // shim plugins should make use state directory for writing files to disk.
// The state directory will be destroyed when the shim if cleaned up or // The state directory will be destroyed when the shim if cleaned up or
// on reboot // on reboot
"", plugins.PropertyStateDir: filepath.Join(bundlePath, p.URI()),
bundlePath, plugins.PropertyGRPCAddress: addressFlag,
plugins.PropertyTTRPCAddress: ttrpcAddress,
},
) )
initContext.Address = addressFlag
initContext.TTRPCAddress = ttrpcAddress
// load the plugin specific configuration if it is provided // load the plugin specific configuration if it is provided
// TODO: Read configuration passed into shim, or from state directory? // TODO: Read configuration passed into shim, or from state directory?

View File

@ -27,6 +27,7 @@ import (
"github.com/containerd/containerd/events" "github.com/containerd/containerd/events"
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -38,7 +39,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.ContainersService, ID: services.ContainersService,
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -23,6 +23,7 @@ import (
api "github.com/containerd/containerd/api/services/containers/v1" api "github.com/containerd/containerd/api/services/containers/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -30,7 +31,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "containers", ID: "containers",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -21,13 +21,14 @@ import (
"github.com/containerd/containerd/content" "github.com/containerd/containerd/content"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
"github.com/containerd/containerd/services/content/contentserver" "github.com/containerd/containerd/services/content/contentserver"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "content", ID: "content",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -24,6 +24,7 @@ import (
"github.com/containerd/containerd/events" "github.com/containerd/containerd/events"
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
@ -36,7 +37,7 @@ type store struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.ContentService, ID: services.ContentService,
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -26,6 +26,7 @@ import (
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/oci" "github.com/containerd/containerd/oci"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
"github.com/containerd/typeurl/v2" "github.com/containerd/typeurl/v2"
@ -49,7 +50,7 @@ type differ interface {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.DiffService, ID: services.DiffService,
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -22,13 +22,14 @@ import (
diffapi "github.com/containerd/containerd/api/services/diff/v1" diffapi "github.com/containerd/containerd/api/services/diff/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "diff", ID: "diff",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -26,6 +26,7 @@ import (
"github.com/containerd/containerd/events" "github.com/containerd/containerd/events"
"github.com/containerd/containerd/events/exchange" "github.com/containerd/containerd/events/exchange"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
@ -34,7 +35,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "events", ID: "events",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -18,6 +18,7 @@ package healthcheck
import ( import (
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -30,7 +31,7 @@ type service struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "healthcheck", ID: "healthcheck",
InitFn: func(*plugin.InitContext) (interface{}, error) { InitFn: func(*plugin.InitContext) (interface{}, error) {

View File

@ -28,6 +28,7 @@ import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/pkg/epoch" "github.com/containerd/containerd/pkg/epoch"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -38,7 +39,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.ImagesService, ID: services.ImagesService,
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -22,6 +22,7 @@ import (
imagesapi "github.com/containerd/containerd/api/services/images/v1" imagesapi "github.com/containerd/containerd/api/services/images/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -29,7 +30,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "images", ID: "images",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -28,6 +28,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/filters" "github.com/containerd/containerd/filters"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -39,7 +40,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.IntrospectionService, ID: services.IntrospectionService,
Requires: []plugin.Type{}, Requires: []plugin.Type{},
@ -47,7 +48,7 @@ func init() {
// this service fetches all plugins through the plugin set of the plugin context // this service fetches all plugins through the plugin set of the plugin context
return &Local{ return &Local{
plugins: ic.Plugins(), plugins: ic.Plugins(),
root: ic.Root, root: ic.Properties[plugins.PropertyRootDir],
}, nil }, nil
}, },
}) })

View File

@ -22,6 +22,7 @@ import (
api "github.com/containerd/containerd/api/services/introspection/v1" api "github.com/containerd/containerd/api/services/introspection/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -29,7 +30,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "introspection", ID: "introspection",
Requires: []plugin.Type{plugins.ServicePlugin}, Requires: []plugin.Type{plugins.ServicePlugin},
@ -52,7 +53,7 @@ func init() {
if !ok { if !ok {
return nil, errors.New("could not create a local client for introspection service") return nil, errors.New("could not create a local client for introspection service")
} }
localClient.UpdateLocal(ic.Root) localClient.UpdateLocal(ic.Properties[plugins.PropertyRootDir])
return &server{ return &server{
local: localClient, local: localClient,

View File

@ -23,6 +23,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/leases" "github.com/containerd/containerd/leases"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
@ -30,7 +31,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "leases", ID: "leases",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -27,6 +27,7 @@ import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -37,7 +38,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.NamespacesService, ID: services.NamespacesService,
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -22,6 +22,7 @@ import (
api "github.com/containerd/containerd/api/services/namespaces/v1" api "github.com/containerd/containerd/api/services/namespaces/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -29,7 +30,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "namespaces", ID: "namespaces",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -22,6 +22,7 @@ import (
"path/filepath" "path/filepath"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
) )
@ -32,7 +33,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.InternalPlugin, Type: plugins.InternalPlugin,
ID: "opt", ID: "opt",
Config: &Config{ Config: &Config{

View File

@ -27,6 +27,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events" "github.com/containerd/containerd/events"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/sandbox" "github.com/containerd/containerd/sandbox"
@ -34,7 +35,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "sandbox-controllers", ID: "sandbox-controllers",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -25,13 +25,14 @@ import (
"github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/sandbox" "github.com/containerd/containerd/sandbox"
"github.com/containerd/log" "github.com/containerd/log"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "sandboxes", ID: "sandboxes",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -239,11 +239,10 @@ type ProxyPlugin struct {
} }
// Decode unmarshals a plugin specific configuration by plugin id // Decode unmarshals a plugin specific configuration by plugin id
func (c *Config) Decode(ctx context.Context, p *plugin.Registration) (interface{}, error) { func (c *Config) Decode(ctx context.Context, id string, config interface{}) (interface{}, error) {
id := p.URI()
data, ok := c.Plugins[id] data, ok := c.Plugins[id]
if !ok { if !ok {
return p.Config, nil return config, nil
} }
b, err := toml.Marshal(data) b, err := toml.Marshal(data)
@ -251,7 +250,7 @@ func (c *Config) Decode(ctx context.Context, p *plugin.Registration) (interface{
return nil, err return nil, err
} }
if err := toml.NewDecoder(bytes.NewReader(b)).DisallowUnknownFields().Decode(p.Config); err != nil { if err := toml.NewDecoder(bytes.NewReader(b)).DisallowUnknownFields().Decode(config); err != nil {
var serr *toml.StrictMissingError var serr *toml.StrictMissingError
if errors.As(err, &serr) { if errors.As(err, &serr) {
for _, derr := range serr.Errors { for _, derr := range serr.Errors {
@ -260,7 +259,7 @@ func (c *Config) Decode(ctx context.Context, p *plugin.Registration) (interface{
"key": strings.Join(derr.Key(), " "), "key": strings.Join(derr.Key(), " "),
}).WithError(err).Warn("Ignoring unknown key in TOML for plugin") }).WithError(err).Warn("Ignoring unknown key in TOML for plugin")
} }
err = toml.Unmarshal(b, p.Config) err = toml.Unmarshal(b, config)
} }
if err != nil { if err != nil {
return nil, err return nil, err
@ -268,7 +267,7 @@ func (c *Config) Decode(ctx context.Context, p *plugin.Registration) (interface{
} }
return p.Config, nil return config, nil
} }
// LoadConfig loads the containerd server config from the provided path // LoadConfig loads the containerd server config from the provided path

View File

@ -25,7 +25,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/containerd/containerd/plugin"
"github.com/containerd/log/logtest" "github.com/containerd/log/logtest"
) )
@ -201,7 +200,7 @@ func TestDecodePlugin(t *testing.T) {
ctx := logtest.WithT(context.Background(), t) ctx := logtest.WithT(context.Background(), t)
data := ` data := `
version = 2 version = 2
[plugins."io.containerd.runtime.v1.linux"] [plugins."io.containerd.runtime.v2.task"]
shim_debug = true shim_debug = true
` `
@ -216,7 +215,7 @@ version = 2
assert.NoError(t, err) assert.NoError(t, err)
pluginConfig := map[string]interface{}{} pluginConfig := map[string]interface{}{}
_, err = out.Decode(ctx, &plugin.Registration{Type: "io.containerd.runtime.v1", ID: "linux", Config: &pluginConfig}) _, err = out.Decode(ctx, "io.containerd.runtime.v2.task", &pluginConfig)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, true, pluginConfig["shim_debug"]) assert.Equal(t, true, pluginConfig["shim_debug"])
} }
@ -226,7 +225,7 @@ version = 2
func TestDecodePluginInV1Config(t *testing.T) { func TestDecodePluginInV1Config(t *testing.T) {
ctx := logtest.WithT(context.Background(), t) ctx := logtest.WithT(context.Background(), t)
data := ` data := `
[plugins.linux] [plugins.task]
shim_debug = true shim_debug = true
` `
@ -244,7 +243,7 @@ func TestDecodePluginInV1Config(t *testing.T) {
assert.Equal(t, 3, out.Version) assert.Equal(t, 3, out.Version)
pluginConfig := map[string]interface{}{} pluginConfig := map[string]interface{}{}
_, err = out.Decode(ctx, &plugin.Registration{Type: "io.containerd.runtime.v1", ID: "linux", Config: &pluginConfig}) _, err = out.Decode(ctx, "io.containerd.runtime.v2.task", &pluginConfig)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, true, pluginConfig["shim_debug"]) assert.Equal(t, true, pluginConfig["shim_debug"])
} }

View File

@ -46,6 +46,7 @@ import (
"github.com/containerd/containerd/pkg/timeout" "github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
ssproxy "github.com/containerd/containerd/snapshots/proxy" ssproxy "github.com/containerd/containerd/snapshots/proxy"
@ -245,13 +246,14 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
initContext := plugin.NewContext( initContext := plugin.NewContext(
ctx, ctx,
p,
initialized, initialized,
config.Root, map[string]string{
config.State, plugins.PropertyRootDir: filepath.Join(config.Root, id),
plugins.PropertyStateDir: filepath.Join(config.State, id),
plugins.PropertyGRPCAddress: config.GRPC.Address,
plugins.PropertyTTRPCAddress: config.TTRPC.Address,
},
) )
initContext.Address = config.GRPC.Address
initContext.TTRPCAddress = config.TTRPC.Address
initContext.RegisterReadiness = func() func() { initContext.RegisterReadiness = func() func() {
atomic.StoreInt32(&mustSucceed, 1) atomic.StoreInt32(&mustSucceed, 1)
return s.RegisterReadiness() return s.RegisterReadiness()
@ -259,7 +261,7 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
// load the plugin specific configuration if it is provided // load the plugin specific configuration if it is provided
if p.Config != nil { if p.Config != nil {
pc, err := config.Decode(ctx, p) pc, err := config.Decode(ctx, id, p.Config)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -426,7 +428,7 @@ func (s *Server) Wait() {
// LoadPlugins loads all plugins into containerd and generates an ordered graph // LoadPlugins loads all plugins into containerd and generates an ordered graph
// of all plugins. // of all plugins.
func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Registration, error) { func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]plugin.Registration, error) {
// load all plugins into containerd // load all plugins into containerd
path := config.PluginDir path := config.PluginDir
if path == "" { if path == "" {
@ -436,12 +438,13 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
return nil, err return nil, err
} }
// load additional plugins that don't automatically register themselves // load additional plugins that don't automatically register themselves
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ContentPlugin, Type: plugins.ContentPlugin,
ID: "content", ID: "content",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Exports["root"] = ic.Root root := ic.Properties[plugins.PropertyRootDir]
return local.NewStore(ic.Root) ic.Meta.Exports["root"] = root
return local.NewStore(root)
}, },
}) })
@ -486,7 +489,7 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
p = platforms.DefaultSpec() p = platforms.DefaultSpec()
} }
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: t, Type: t,
ID: name, ID: name,
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
@ -504,7 +507,7 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
filter := srvconfig.V2DisabledFilter filter := srvconfig.V2DisabledFilter
// return the ordered graph for plugins // return the ordered graph for plugins
return plugin.Graph(filter(config.DisabledPlugins)), nil return registry.Graph(filter(config.DisabledPlugins)), nil
} }
type proxyClients struct { type proxyClients struct {

View File

@ -21,6 +21,7 @@ import (
"testing" "testing"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
srvconfig "github.com/containerd/containerd/services/server/config" srvconfig "github.com/containerd/containerd/services/server/config"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -57,8 +58,8 @@ func TestCreateTopLevelDirectoriesWithEmptyRootPath(t *testing.T) {
} }
func TestMigration(t *testing.T) { func TestMigration(t *testing.T) {
plugin.Reset() registry.Reset()
defer plugin.Reset() defer registry.Reset()
version := srvconfig.CurrentConfigVersion - 1 version := srvconfig.CurrentConfigVersion - 1
@ -67,7 +68,7 @@ func TestMigration(t *testing.T) {
NotMigrated string `toml:"notmigrated"` NotMigrated string `toml:"notmigrated"`
} }
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: "io.containerd.test", Type: "io.containerd.test",
ID: "t1", ID: "t1",
Config: &testConfig{}, Config: &testConfig{},
@ -86,7 +87,7 @@ func TestMigration(t *testing.T) {
return nil, nil return nil, nil
}, },
}) })
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: "io.containerd.new", Type: "io.containerd.new",
Requires: []plugin.Type{ Requires: []plugin.Type{
"io.containerd.test", // Ensure this test runs second "io.containerd.test", // Ensure this test runs second

View File

@ -24,6 +24,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -33,7 +34,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "snapshots", ID: "snapshots",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -19,12 +19,13 @@ package snapshots
import ( import (
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.SnapshotsService, ID: services.SnapshotsService,
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -24,6 +24,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/streaming" "github.com/containerd/containerd/pkg/streaming"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
@ -42,7 +43,7 @@ func init() {
panic(err) panic(err)
} }
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "streaming", ID: "streaming",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -19,6 +19,7 @@ package tasks
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -41,6 +42,7 @@ import (
"github.com/containerd/containerd/pkg/rdt" "github.com/containerd/containerd/pkg/rdt"
"github.com/containerd/containerd/pkg/timeout" "github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf" "github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/protobuf/proto" "github.com/containerd/containerd/protobuf/proto"
@ -75,7 +77,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin, Type: plugins.ServicePlugin,
ID: services.TasksService, ID: services.TasksService,
Requires: tasksServiceRequires, Requires: tasksServiceRequires,
@ -106,7 +108,7 @@ func initFunc(ic *plugin.InitContext) (interface{}, error) {
monitor, err := ic.Get(plugins.TaskMonitorPlugin) monitor, err := ic.Get(plugins.TaskMonitorPlugin)
if err != nil { if err != nil {
if !errdefs.IsNotFound(err) { if !errors.Is(err, plugin.ErrPluginNotFound) {
return nil, err return nil, err
} }
monitor = runtime.NewNoopMonitor() monitor = runtime.NewNoopMonitor()

View File

@ -22,6 +22,7 @@ import (
api "github.com/containerd/containerd/api/services/tasks/v1" api "github.com/containerd/containerd/api/services/tasks/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -33,7 +34,7 @@ var (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "tasks", ID: "tasks",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -26,6 +26,7 @@ import (
"github.com/containerd/containerd/pkg/transfer" "github.com/containerd/containerd/pkg/transfer"
tplugins "github.com/containerd/containerd/pkg/transfer/plugins" tplugins "github.com/containerd/containerd/pkg/transfer/plugins"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/log" "github.com/containerd/log"
@ -37,7 +38,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "transfer", ID: "transfer",
Requires: []plugin.Type{ Requires: []plugin.Type{

View File

@ -21,6 +21,7 @@ import (
api "github.com/containerd/containerd/api/services/version/v1" api "github.com/containerd/containerd/api/services/version/v1"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types" ptypes "github.com/containerd/containerd/protobuf/types"
ctrdversion "github.com/containerd/containerd/version" ctrdversion "github.com/containerd/containerd/version"
@ -30,7 +31,7 @@ import (
var _ api.VersionServer = &service{} var _ api.VersionServer = &service{}
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin, Type: plugins.GRPCPlugin,
ID: "version", ID: "version",
InitFn: initFunc, InitFn: initFunc,

View File

@ -21,6 +21,7 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots/blockfile" "github.com/containerd/containerd/snapshots/blockfile"
) )
@ -45,7 +46,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
ID: "blockfile", ID: "blockfile",
Config: &Config{}, Config: &Config{},
@ -58,7 +59,7 @@ func init() {
} }
var opts []blockfile.Opt var opts []blockfile.Opt
root := ic.Root root := ic.Properties[plugins.PropertyRootDir]
if len(config.RootPath) != 0 { if len(config.RootPath) != 0 {
root = config.RootPath root = config.RootPath
} }

View File

@ -25,6 +25,7 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots/btrfs" "github.com/containerd/containerd/snapshots/btrfs"
) )
@ -36,7 +37,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
ID: "btrfs", ID: "btrfs",
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
Config: &Config{}, Config: &Config{},
@ -48,7 +49,7 @@ func init() {
return nil, errors.New("invalid btrfs configuration") return nil, errors.New("invalid btrfs configuration")
} }
root := ic.Root root := ic.Properties[plugins.PropertyRootDir]
if len(config.RootPath) != 0 { if len(config.RootPath) != 0 {
root = config.RootPath root = config.RootPath
} }

View File

@ -24,12 +24,13 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots/devmapper" "github.com/containerd/containerd/snapshots/devmapper"
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
ID: "devmapper", ID: "devmapper",
Config: &devmapper.Config{}, Config: &devmapper.Config{},
@ -46,7 +47,7 @@ func init() {
} }
if config.RootPath == "" { if config.RootPath == "" {
config.RootPath = ic.Root config.RootPath = ic.Properties[plugins.PropertyRootDir]
} }
return devmapper.NewSnapshotter(ic.Context, config) return devmapper.NewSnapshotter(ic.Context, config)

View File

@ -37,6 +37,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots" "github.com/containerd/containerd/snapshots"
"github.com/containerd/containerd/snapshots/storage" "github.com/containerd/containerd/snapshots/storage"
@ -46,7 +47,7 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
ID: "windows-lcow", ID: "windows-lcow",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
@ -54,7 +55,7 @@ func init() {
OS: "linux", OS: "linux",
Architecture: runtime.GOARCH, Architecture: runtime.GOARCH,
}) })
return NewSnapshotter(ic.Root) return NewSnapshotter(ic.Properties[plugins.PropertyRootDir])
}, },
}) })
} }

View File

@ -21,6 +21,7 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots/native" "github.com/containerd/containerd/snapshots/native"
) )
@ -32,7 +33,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
ID: "native", ID: "native",
Config: &Config{}, Config: &Config{},
@ -44,7 +45,7 @@ func init() {
return nil, errors.New("invalid native configuration") return nil, errors.New("invalid native configuration")
} }
root := ic.Root root := ic.Properties[plugins.PropertyRootDir]
if len(config.RootPath) != 0 { if len(config.RootPath) != 0 {
root = config.RootPath root = config.RootPath
} }

View File

@ -23,6 +23,7 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots/overlay" "github.com/containerd/containerd/snapshots/overlay"
"github.com/containerd/containerd/snapshots/overlay/overlayutils" "github.com/containerd/containerd/snapshots/overlay/overlayutils"
@ -50,7 +51,7 @@ type Config struct {
} }
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
ID: "overlayfs", ID: "overlayfs",
Config: &Config{}, Config: &Config{},
@ -62,7 +63,7 @@ func init() {
return nil, errors.New("invalid overlay configuration") return nil, errors.New("invalid overlay configuration")
} }
root := ic.Root root := ic.Properties[plugins.PropertyRootDir]
if config.RootPath != "" { if config.RootPath != "" {
root = config.RootPath root = config.RootPath
} }

View File

@ -38,6 +38,7 @@ import (
"github.com/containerd/containerd/mount" "github.com/containerd/containerd/mount"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots" "github.com/containerd/containerd/snapshots"
"github.com/containerd/containerd/snapshots/storage" "github.com/containerd/containerd/snapshots/storage"
@ -47,12 +48,12 @@ import (
) )
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin, Type: plugins.SnapshotPlugin,
ID: "windows", ID: "windows",
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Platforms = []ocispec.Platform{platforms.DefaultSpec()} ic.Meta.Platforms = []ocispec.Platform{platforms.DefaultSpec()}
return NewSnapshotter(ic.Root) return NewSnapshotter(ic.Properties[plugins.PropertyRootDir])
}, },
}) })
} }

View File

@ -25,6 +25,7 @@ import (
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins" "github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/tracing" "github.com/containerd/containerd/tracing"
"github.com/containerd/log" "github.com/containerd/log"
@ -42,7 +43,7 @@ import (
const exporterPlugin = "otlp" const exporterPlugin = "otlp"
func init() { func init() {
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
ID: exporterPlugin, ID: exporterPlugin,
Type: plugins.TracingProcessorPlugin, Type: plugins.TracingProcessorPlugin,
Config: &OTLPConfig{}, Config: &OTLPConfig{},
@ -55,7 +56,7 @@ func init() {
return trace.NewBatchSpanProcessor(exp), nil return trace.NewBatchSpanProcessor(exp), nil
}, },
}) })
plugin.Register(&plugin.Registration{ registry.Register(&plugin.Registration{
ID: "tracing", ID: "tracing",
Type: plugins.InternalPlugin, Type: plugins.InternalPlugin,
Requires: []plugin.Type{ Requires: []plugin.Type{