Require plugins to succeed after registering readiness

When readiness is registered on initialization, the plugin must not
fail. When such a plugin fails, containerd will hang on the readiness
condition.

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan 2023-09-26 17:10:55 -07:00
parent bcd658c76c
commit e7254406c9
No known key found for this signature in database
GPG Key ID: F58C5D0A4405ACDB

View File

@ -31,6 +31,7 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"sync" "sync"
"sync/atomic"
"time" "time"
csapi "github.com/containerd/containerd/api/services/content/v1" csapi "github.com/containerd/containerd/api/services/content/v1"
@ -205,6 +206,7 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
for _, p := range plugins { for _, p := range plugins {
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)
var mustSucceed int32
initContext := plugin.NewContext( initContext := plugin.NewContext(
ctx, ctx,
@ -215,7 +217,10 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
) )
initContext.Address = config.GRPC.Address initContext.Address = config.GRPC.Address
initContext.TTRPCAddress = config.TTRPC.Address initContext.TTRPCAddress = config.TTRPC.Address
initContext.RegisterReadiness = s.RegisterReadiness initContext.RegisterReadiness = func() func() {
atomic.StoreInt32(&mustSucceed, 1)
return s.RegisterReadiness()
}
// 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 {
@ -240,6 +245,10 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
if _, ok := required[id]; ok { if _, ok := required[id]; ok {
return nil, fmt.Errorf("load required plugin %s: %w", id, err) return nil, fmt.Errorf("load required plugin %s: %w", id, err)
} }
// If readiness was registered during initialization, the plugin cannot fail
if atomic.LoadInt32(&mustSucceed) != 0 {
return nil, fmt.Errorf("plugin failed after registering readiness %s: %w", id, err)
}
continue continue
} }