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
65 changed files with 363 additions and 299 deletions

View File

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