Merge pull request #9214 from dmcgowan/generalize-plugin-library

Generalize plugin library
This commit is contained in:
Akihiro Suda 2023-10-13 14:50:38 +09:00 committed by GitHub
commit 0cd7bdd4a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
115 changed files with 836 additions and 3308 deletions

View File

@ -21,7 +21,6 @@ import (
"context"
"encoding/json"
"fmt"
"runtime"
"strconv"
"strings"
"sync"
@ -52,7 +51,7 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/dialer"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
@ -185,7 +184,7 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) {
c := &Client{
defaultns: copts.defaultns,
conn: conn,
runtime: plugin.RuntimePlugin.String() + "." + runtime.GOOS,
runtime: defaults.DefaultRuntime,
}
if copts.defaultPlatform != nil {
@ -826,7 +825,7 @@ func (c *Client) getSnapshotter(ctx context.Context, name string) (snapshots.Sna
// GetSnapshotterSupportedPlatforms returns a platform matchers which represents the
// supported platforms for the given snapshotters
func (c *Client) GetSnapshotterSupportedPlatforms(ctx context.Context, snapshotterName string) (platforms.MatchComparer, error) {
filters := []string{fmt.Sprintf("type==%s, id==%s", plugin.SnapshotPlugin, snapshotterName)}
filters := []string{fmt.Sprintf("type==%s, id==%s", plugins.SnapshotPlugin, snapshotterName)}
in := c.IntrospectionService()
resp, err := in.Plugins(ctx, filters)
@ -857,7 +856,7 @@ func toPlatforms(pt []*apitypes.Platform) []ocispec.Platform {
// GetSnapshotterCapabilities returns the capabilities of a snapshotter.
func (c *Client) GetSnapshotterCapabilities(ctx context.Context, snapshotterName string) ([]string, error) {
filters := []string{fmt.Sprintf("type==%s, id==%s", plugin.SnapshotPlugin, snapshotterName)}
filters := []string{fmt.Sprintf("type==%s, id==%s", plugins.SnapshotPlugin, snapshotterName)}
in := c.IntrospectionService()
resp, err := in.Plugins(ctx, filters)

View File

@ -31,7 +31,7 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/integration/remote"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/log"
metrics "github.com/docker/go-metrics"
"github.com/urfave/cli"
@ -167,7 +167,7 @@ func main() {
cli.StringFlag{
Name: "runtime",
Usage: "Set the runtime to stress test",
Value: plugin.RuntimeRuncV2,
Value: plugins.RuntimeRuncV2,
},
cli.StringFlag{
Name: "snapshotter",

View File

@ -16,4 +16,6 @@
package builtins
import _ "github.com/containerd/zfs/plugin"
// Temporarily removed while plugin package is moved, to be added back
// before 2.0.
//import _ "github.com/containerd/zfs/plugin"

View File

@ -18,4 +18,8 @@
package builtins
import _ "github.com/containerd/zfs/plugin"
// zfs snapshotter is temporarily removed until it is updated to use the
// new plugin package. In the future, the external plugin package will
// make it easier to update zfs and containerd independently without
// the dependency loop. Add back before 2.0 release.
//import _ "github.com/containerd/zfs/plugin"

View File

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

View File

@ -36,6 +36,8 @@ import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/log"
digest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -47,14 +49,14 @@ const (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.DiffPlugin,
registry.Register(&plugin.Registration{
Type: plugins.DiffPlugin,
ID: "windows-lcow",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
md, err := ic.Get(plugin.MetadataPlugin)
md, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}

View File

@ -23,17 +23,19 @@ import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.DiffPlugin,
registry.Register(&plugin.Registration{
Type: plugins.DiffPlugin,
ID: "walking",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
md, err := ic.Get(plugin.MetadataPlugin)
md, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}

View File

@ -39,20 +39,22 @@ import (
"github.com/containerd/containerd/pkg/epoch"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/log"
"github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.DiffPlugin,
registry.Register(&plugin.Registration{
Type: plugins.DiffPlugin,
ID: "windows",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
md, err := ic.Get(plugin.MetadataPlugin)
md, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}

View File

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

View File

@ -25,6 +25,8 @@ import (
"github.com/containerd/containerd/gc"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/log"
)
@ -96,11 +98,11 @@ func (d duration) MarshalText() (text []byte, err error) {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GCPlugin,
ID: "scheduler",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
Config: &config{
PauseThreshold: 0.02,
@ -110,14 +112,14 @@ func init() {
StartupDelay: duration(100 * time.Millisecond),
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
md, err := ic.Get(plugin.MetadataPlugin)
md, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
mdCollector, ok := md.(collector)
if !ok {
return nil, fmt.Errorf("%s %T must implement collector", plugin.MetadataPlugin, md)
return nil, fmt.Errorf("%s %T must implement collector", plugins.MetadataPlugin, md)
}
m := newScheduler(mdCollector, ic.Config.(*config))

2
go.mod
View File

@ -21,7 +21,6 @@ require (
github.com/containerd/nri v0.5.0
github.com/containerd/ttrpc v1.2.2
github.com/containerd/typeurl/v2 v2.1.1
github.com/containerd/zfs v1.2.0
github.com/containernetworking/cni v1.1.2
github.com/containernetworking/plugins v1.3.0
github.com/coreos/go-systemd/v22 v22.5.0
@ -103,7 +102,6 @@ require (
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect

4
go.sum
View File

@ -295,8 +295,6 @@ github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQ
github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
github.com/containerd/zfs v1.2.0 h1:AtAkI6CIAtBV1Pu5/06r4fsHv9JQwZOt/NoKdhSi4qA=
github.com/containerd/zfs v1.2.0/go.mod h1:NinsnukMVY2SnwkJzrEhXzDDPdJ3Ok5LnGjblu1nfmI=
github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY=
@ -693,8 +691,6 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=

View File

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

View File

@ -38,7 +38,7 @@ import (
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/runc/options"
"github.com/containerd/containerd/sys"
@ -1028,7 +1028,7 @@ func TestContainerRuntimeOptionsv2(t *testing.T) {
ctx, id,
WithNewSnapshot(id, image),
WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)),
WithRuntime(plugin.RuntimeRuncV2, &options.Options{BinaryName: "no-runc"}),
WithRuntime(plugins.RuntimeRuncV2, &options.Options{BinaryName: "no-runc"}),
)
if err != nil {
t.Fatal(err)

View File

@ -39,7 +39,7 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
gogotypes "github.com/containerd/containerd/protobuf/types"
_ "github.com/containerd/containerd/runtime"
"github.com/containerd/containerd/runtime/v2/runc/options"
@ -172,7 +172,7 @@ func TestContainerStart(t *testing.T) {
}
func readShimPath(taskID string) (string, error) {
runtime := plugin.RuntimePluginV2.String() + ".task"
runtime := plugins.RuntimePluginV2.String() + ".task"
shimBinaryNamePath := filepath.Join(defaultState, runtime, testNamespace, taskID, "shim-binary-path")
shimPath, err := os.ReadFile(shimBinaryNamePath)

View File

@ -29,7 +29,7 @@ import (
"github.com/containerd/cgroups/v3"
. "github.com/containerd/containerd"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/runc/options"
)
@ -55,7 +55,7 @@ version = 2
}
id := t.Name()
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("top")), WithRuntime(plugin.RuntimeRuncV2, &options.Options{
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("top")), WithRuntime(plugins.RuntimeRuncV2, &options.Options{
Root: runtimeRoot,
}))
if err != nil {

View File

@ -760,7 +760,6 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.9.9/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.12.0-rc.0 h1:wX/F5huJxH9APBkhKSEAqaiZsuBvbbDnyBROZAqsSaY=
github.com/Microsoft/hcsshim v0.12.0-rc.0/go.mod h1:rvOnw3YlfoNnEp45wReUngvsXbwRW+AFQ10GVjG1kMU=
@ -873,7 +872,6 @@ github.com/container-orchestrated-devices/container-device-interface v0.6.1/go.m
github.com/containerd/btrfs/v2 v2.0.0/go.mod h1:swkD/7j9HApWpzl8OHfrHNxppPd9l44DFZdF94BUj9k=
github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo=
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
@ -882,7 +880,6 @@ github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4q
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
@ -911,7 +908,6 @@ github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izU
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/containerd/zfs v1.2.0/go.mod h1:NinsnukMVY2SnwkJzrEhXzDDPdJ3Ok5LnGjblu1nfmI=
github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0=
@ -1195,7 +1191,6 @@ github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JV
github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -1366,7 +1361,6 @@ github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WT
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@ -1454,7 +1448,6 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0=
github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
@ -2068,7 +2061,6 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -2572,7 +2564,6 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -28,6 +28,8 @@ import (
"github.com/containerd/containerd/pkg/failpoint"
"github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/runc/task"
"github.com/containerd/containerd/runtime/v2/shim"
"github.com/containerd/ttrpc"
@ -38,19 +40,19 @@ const (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.TTRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin,
ID: "task",
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.InternalPlugin,
plugins.EventPlugin,
plugins.InternalPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
pp, err := ic.GetByID(plugin.EventPlugin, "publisher")
pp, err := ic.GetByID(plugins.EventPlugin, "publisher")
if err != nil {
return nil, err
}
ss, err := ic.GetByID(plugin.InternalPlugin, "shutdown")
ss, err := ic.GetByID(plugins.InternalPlugin, "shutdown")
if err != nil {
return nil, err
}

View File

@ -23,22 +23,24 @@ import (
"github.com/containerd/containerd/leases"
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.LeasePlugin,
registry.Register(&plugin.Registration{
Type: plugins.LeasePlugin,
ID: "manager",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugin.GCPlugin,
plugins.MetadataPlugin,
plugins.GCPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
g, err := ic.Get(plugin.GCPlugin)
g, err := ic.Get(plugins.GCPlugin)
if err != nil {
return nil, err
}

View File

@ -28,6 +28,8 @@ import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/log"
@ -81,27 +83,28 @@ func (bc *BoltConfig) Validate() error {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.MetadataPlugin,
registry.Register(&plugin.Registration{
Type: plugins.MetadataPlugin,
ID: "bolt",
Requires: []plugin.Type{
plugin.ContentPlugin,
plugin.EventPlugin,
plugin.SnapshotPlugin,
plugins.ContentPlugin,
plugins.EventPlugin,
plugins.SnapshotPlugin,
},
Config: &BoltConfig{
ContentSharingPolicy: SharingPolicyShared,
},
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
}
cs, err := ic.Get(plugin.ContentPlugin)
cs, err := ic.Get(plugins.ContentPlugin)
if err != nil {
return nil, err
}
snapshottersRaw, err := ic.GetByType(plugin.SnapshotPlugin)
snapshottersRaw, err := ic.GetByType(plugins.SnapshotPlugin)
if err != nil {
return nil, err
}
@ -119,7 +122,7 @@ func init() {
snapshotters[name] = sn.(snapshots.Snapshotter)
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}
@ -140,7 +143,7 @@ func init() {
}
}
path := filepath.Join(ic.Root, "meta.db")
path := filepath.Join(root, "meta.db")
ic.Meta.Exports["path"] = path
options := *bolt.DefaultOptions

View File

@ -25,6 +25,8 @@ import (
v2 "github.com/containerd/containerd/metrics/cgroups/v2"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime"
metrics "github.com/docker/go-metrics"
)
@ -35,12 +37,12 @@ type Config struct {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.TaskMonitorPlugin,
registry.Register(&plugin.Registration{
Type: plugins.TaskMonitorPlugin,
ID: "cgroups",
InitFn: New,
Requires: []plugin.Type{
plugin.EventPlugin,
plugins.EventPlugin,
},
Config: &Config{},
})
@ -58,7 +60,7 @@ func New(ic *plugin.InitContext) (interface{}, error) {
err error
)
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}

View File

@ -27,6 +27,8 @@ import (
nriservice "github.com/containerd/containerd/pkg/nri"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/log"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
"k8s.io/klog/v2"
@ -38,14 +40,14 @@ import (
// Register CRI service plugin
func init() {
config := criconfig.DefaultConfig()
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "cri",
Config: &config,
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.ServicePlugin,
plugin.NRIApiPlugin,
plugins.EventPlugin,
plugins.ServicePlugin,
plugins.NRIApiPlugin,
},
InitFn: initCRIService,
})
@ -62,10 +64,10 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
c := criconfig.Config{
PluginConfig: *pluginConfig,
ContainerdRootDir: filepath.Dir(ic.Root),
ContainerdEndpoint: ic.Address,
RootDir: ic.Root,
StateDir: ic.State,
ContainerdRootDir: filepath.Dir(ic.Properties[plugins.PropertyRootDir]),
ContainerdEndpoint: ic.Properties[plugins.PropertyGRPCAddress],
RootDir: ic.Properties[plugins.PropertyRootDir],
StateDir: ic.Properties[plugins.PropertyStateDir],
}
log.G(ctx).Infof("Start cri plugin with config %+v", c)
@ -125,7 +127,7 @@ func setGLogLevel() error {
// Get the NRI plugin, and set up our NRI API for it.
func getNRIAPI(ic *plugin.InitContext) *nri.API {
const (
pluginType = plugin.NRIApiPlugin
pluginType = plugins.NRIApiPlugin
pluginName = "nri"
)

View File

@ -41,7 +41,7 @@ import (
containerstore "github.com/containerd/containerd/pkg/cri/store/container"
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
runtimeoptions "github.com/containerd/containerd/pkg/runtimeoptions/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
"github.com/containerd/log"
)
@ -289,7 +289,7 @@ func generateRuntimeOptions(r criconfig.Runtime) (interface{}, error) {
// getRuntimeOptionsType gets empty runtime options by the runtime type name.
func getRuntimeOptionsType(t string) interface{} {
switch t {
case plugin.RuntimeRuncV2:
case plugins.RuntimeRuncV2:
return &runcoptions.Options{}
case runtimeRunhcsV1:
return &runhcsoptions.Options{}

View File

@ -30,7 +30,7 @@ import (
"github.com/containerd/containerd/oci"
criconfig "github.com/containerd/containerd/pkg/cri/config"
containerstore "github.com/containerd/containerd/pkg/cri/store/container"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf/types"
runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
"github.com/containerd/typeurl/v2"
@ -119,7 +119,7 @@ systemd_cgroup = true
no_pivot = true
default_runtime_name = "default"
[containerd.runtimes.runcv2]
runtime_type = "` + plugin.RuntimeRuncV2 + `"
runtime_type = "` + plugins.RuntimeRuncV2 + `"
`
nonNilOpts := `
systemd_cgroup = true
@ -134,7 +134,7 @@ systemd_cgroup = true
Root = "/runc"
NoNewKeyring = true
[containerd.runtimes.runcv2]
runtime_type = "` + plugin.RuntimeRuncV2 + `"
runtime_type = "` + plugins.RuntimeRuncV2 + `"
[containerd.runtimes.runcv2.options]
BinaryName = "runc"
Root = "/runcv2"

View File

@ -22,7 +22,7 @@ import (
criconfig "github.com/containerd/containerd/pkg/cri/config"
"github.com/containerd/containerd/pkg/systemd"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/stretchr/testify/assert"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
)
@ -30,7 +30,7 @@ import (
func newFakeRuntimeConfig(runcV2, systemdCgroup bool) criconfig.Runtime {
r := criconfig.Runtime{Type: "default", Options: map[string]interface{}{}}
if runcV2 {
r.Type = plugin.RuntimeRuncV2
r.Type = plugins.RuntimeRuncV2
if systemdCgroup {
r.Options["SystemdCgroup"] = true
}

View File

@ -36,7 +36,7 @@ import (
imagestore "github.com/containerd/containerd/pkg/cri/store/image"
snapshotstore "github.com/containerd/containerd/pkg/cri/store/snapshot"
"github.com/containerd/containerd/pkg/cri/streaming"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/sandbox"
"github.com/containerd/go-cni"
"github.com/containerd/log"
@ -350,7 +350,7 @@ func (c *criService) register(s *grpc.Server) error {
// imageFSPath returns containerd image filesystem path.
// Note that if containerd changes directory layout, we also needs to change this.
func imageFSPath(rootDir, snapshotter string) string {
return filepath.Join(rootDir, plugin.SnapshotPlugin.String()+"."+snapshotter)
return filepath.Join(rootDir, plugins.SnapshotPlugin.String()+"."+snapshotter)
}
func loadOCISpec(filename string) (*oci.Spec, error) {

View File

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

View File

@ -19,20 +19,15 @@ package plugin
import (
"context"
"fmt"
"path/filepath"
"github.com/containerd/containerd/errdefs"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
)
// InitContext is used for plugin initialization
type InitContext struct {
Context context.Context
Root string
State string
Properties map[string]string
Config interface{}
Address string
TTRPCAddress string
RegisterReadiness func() func()
// Meta is metadata plugins can fill in at init
@ -42,11 +37,13 @@ type InitContext struct {
}
// 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{
Context: ctx,
Root: filepath.Join(root, r.URI()),
State: filepath.Join(state, r.URI()),
Context: ctx,
Properties: properties,
Meta: &Meta{
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
// process.
type Meta struct {
Platforms []ocispec.Platform // platforms supported by plugin
Exports map[string]string // values exported by plugin
Capabilities []string // feature switches for plugin
Platforms []imagespec.Platform // platforms supported by plugin
Exports map[string]string // values exported by plugin
Capabilities []string // feature switches for plugin
}
// Plugin represents an initialized plugin, used with an init context.
type Plugin struct {
Registration *Registration // registration, as initialized
Config interface{} // config, as initialized
Meta *Meta
Registration Registration // registration, as initialized
Config interface{} // config, as initialized
Meta Meta
instance interface{}
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 {
byID[p.Registration.ID] = p
} 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)
@ -127,7 +124,7 @@ func (ps *Set) Get(t Type) (interface{}, error) {
for _, v := range ps.byTypeAndID[t] {
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
@ -153,7 +150,7 @@ func (i *InitContext) GetByID(t Type, id string) (interface{}, error) {
}
p, ok := ps[id]
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()
}
@ -162,7 +159,7 @@ func (i *InitContext) GetByID(t Type, id string) (interface{}, error) {
func (i *InitContext) GetByType(t Type) (map[string]*Plugin, error) {
p, ok := i.plugins.byTypeAndID[t]
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

37
plugin/dynamic/dynamic.go Normal file
View File

@ -0,0 +1,37 @@
/*
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 dynamic
import "fmt"
// Load loads all plugins at the provided path into containerd.
//
// Load is currently only implemented on non-static, non-gccgo builds for amd64
// and arm64, and plugins must be built with the exact same version of Go as
// containerd itself.
func Load(path string) (err error) {
defer func() {
if v := recover(); v != nil {
rerr, ok := v.(error)
if !ok {
rerr = fmt.Errorf("%s", v)
}
err = rerr
}
}()
return loadPlugins(path)
}

View File

@ -16,7 +16,7 @@
limitations under the License.
*/
package plugin
package dynamic
import (
"fmt"

View File

@ -16,7 +16,7 @@
limitations under the License.
*/
package plugin
package dynamic
// loadPlugins is not supported;
//

View File

@ -20,7 +20,6 @@ import (
"context"
"errors"
"fmt"
"sync"
)
var (
@ -34,6 +33,10 @@ var (
// this allows the plugin loader differentiate between a plugin which is configured
// not to load and one that fails to load.
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
// defined in an invalid manner.
@ -50,56 +53,6 @@ type Type string
func (t Type) String() string { return string(t) }
const (
// InternalPlugin implements an internal plugin to containerd
InternalPlugin Type = "io.containerd.internal.v1"
// RuntimePlugin implements a runtime
RuntimePlugin Type = "io.containerd.runtime.v1"
// RuntimePluginV2 implements a runtime v2
RuntimePluginV2 Type = "io.containerd.runtime.v2"
// ServicePlugin implements a internal service
ServicePlugin Type = "io.containerd.service.v1"
// GRPCPlugin implements a grpc service
GRPCPlugin Type = "io.containerd.grpc.v1"
// TTRPCPlugin implements a ttrpc shim service
TTRPCPlugin Type = "io.containerd.ttrpc.v1"
// SnapshotPlugin implements a snapshotter
SnapshotPlugin Type = "io.containerd.snapshotter.v1"
// TaskMonitorPlugin implements a task monitor
TaskMonitorPlugin Type = "io.containerd.monitor.v1"
// DiffPlugin implements a differ
DiffPlugin Type = "io.containerd.differ.v1"
// MetadataPlugin implements a metadata store
MetadataPlugin Type = "io.containerd.metadata.v1"
// ContentPlugin implements a content store
ContentPlugin Type = "io.containerd.content.v1"
// GCPlugin implements garbage collection policy
GCPlugin Type = "io.containerd.gc.v1"
// EventPlugin implements event handling
EventPlugin Type = "io.containerd.event.v1"
// LeasePlugin implements lease manager
LeasePlugin Type = "io.containerd.lease.v1"
// StreamingPlugin implements a stream manager
StreamingPlugin Type = "io.containerd.streaming.v1"
// TracingProcessorPlugin implements a open telemetry span processor
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
// NRIApiPlugin implements the NRI adaptation interface for containerd.
NRIApiPlugin Type = "io.containerd.nri.v1"
// TransferPlugin implements a transfer service
TransferPlugin Type = "io.containerd.transfer.v1"
// SandboxStorePlugin implements a sandbox store
SandboxStorePlugin Type = "io.containerd.sandbox.store.v1"
// SandboxControllerPlugin implements a sandbox controller
SandboxControllerPlugin Type = "io.containerd.sandbox.controller.v1"
// ImageVerifierPlugin implements an image verifier service
ImageVerifierPlugin Type = "io.containerd.image-verifier.v1"
)
const (
// RuntimeRuncV2 is the runc runtime that supports multiple containers per shim
RuntimeRuncV2 = "io.containerd.runc.v2"
)
// Registration contains information for registering a plugin
type Registration struct {
// Type of the plugin
@ -115,8 +68,6 @@ type Registration struct {
// context are passed in. The init function may modify the registration to
// add exports, capabilities and platform support declarations.
InitFn func(*InitContext) (interface{}, error)
// Disable the plugin from loading
Disable bool
// ConfigMigration allows a plugin to migrate configurations from an older
// version to handle plugin renames or moving of features from one plugin
@ -129,12 +80,12 @@ type Registration struct {
}
// Init the registered plugin
func (r *Registration) Init(ic *InitContext) *Plugin {
func (r Registration) Init(ic *InitContext) *Plugin {
p, err := r.InitFn(ic)
return &Plugin{
Registration: r,
Config: ic.Config,
Meta: ic.Meta,
Meta: *ic.Meta,
instance: p,
err: err,
}
@ -145,41 +96,64 @@ func (r *Registration) URI() string {
return r.Type.String() + "." + r.ID
}
var register = struct {
sync.RWMutex
r []*Registration
}{}
// DisableFilter filters out disabled plugins
type DisableFilter func(r *Registration) bool
// Load loads all plugins at the provided path into containerd.
//
// Load is currently only implemented on non-static, non-gccgo builds for amd64
// and arm64, and plugins must be built with the exact same version of Go as
// containerd itself.
func Load(path string) (err error) {
defer func() {
if v := recover(); v != nil {
rerr, ok := v.(error)
if !ok {
rerr = fmt.Errorf("%s", v)
}
err = rerr
// 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
}
}()
return loadPlugins(path)
}
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
}
// Register allows plugins to register
func Register(r *Registration) {
register.Lock()
defer register.Unlock()
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 == "" {
panic(ErrNoType)
}
if r.ID == "" {
panic(ErrNoPluginID)
}
if err := checkUnique(r); err != nil {
if err := checkUnique(registry, r); err != nil {
panic(err)
}
@ -189,66 +163,14 @@ func Register(r *Registration) {
}
}
register.r = append(register.r, r)
return append(registry, r)
}
// Reset removes all global registrations
func Reset() {
register.Lock()
defer register.Unlock()
register.r = nil
}
func checkUnique(r *Registration) error {
for _, registered := range register.r {
func checkUnique(registry Registry, r *Registration) error {
for _, registered := range registry {
if r.URI() == registered.URI() {
return fmt.Errorf("%s: %w", r.URI(), ErrIDRegistered)
}
}
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,227 +22,201 @@ import (
"github.com/containerd/containerd/services"
)
func registerClear() {
register.Lock()
defer register.Unlock()
register.r = nil
}
func mockPluginFilter(*Registration) bool {
return false
}
var tasksServiceRequires = []Type{
RuntimePlugin,
RuntimePluginV2,
MetadataPlugin,
TaskMonitorPlugin,
}
// TestContainerdPlugin tests the logic of Graph, use the containerd's plugin
func TestContainerdPlugin(t *testing.T) {
registerClear()
Register(&Registration{
// Plugin types commonly used by containerd
const (
InternalPlugin Type = "io.containerd.internal.v1"
RuntimePlugin Type = "io.containerd.runtime.v1"
RuntimePluginV2 Type = "io.containerd.runtime.v2"
ServicePlugin Type = "io.containerd.service.v1"
GRPCPlugin Type = "io.containerd.grpc.v1"
SnapshotPlugin Type = "io.containerd.snapshotter.v1"
TaskMonitorPlugin Type = "io.containerd.monitor.v1"
DiffPlugin Type = "io.containerd.differ.v1"
MetadataPlugin Type = "io.containerd.metadata.v1"
ContentPlugin Type = "io.containerd.content.v1"
GCPlugin Type = "io.containerd.gc.v1"
LeasePlugin Type = "io.containerd.lease.v1"
TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1"
)
var register Registry
register = register.Register(&Registration{
Type: TaskMonitorPlugin,
ID: "cgroups",
})
Register(&Registration{
Type: ServicePlugin,
ID: services.TasksService,
Requires: tasksServiceRequires,
})
Register(&Registration{
}).Register(&Registration{
Type: ServicePlugin,
ID: services.TasksService,
Requires: []Type{
RuntimePlugin,
RuntimePluginV2,
MetadataPlugin,
TaskMonitorPlugin,
},
}).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{
@ -250,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",
@ -290,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))
}
@ -306,6 +280,7 @@ func TestPluginGraph(t *testing.T) {
for _, testcase := range []struct {
input []*Registration
expectedURI []string
filter DisableFilter
}{
// test requires *
{
@ -380,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)
}
}

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,14 @@ import (
"github.com/containerd/containerd/pkg/imageverifier/bindir"
"github.com/containerd/containerd/pkg/tomlext"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
)
// Register default image verifier service plugin
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ImageVerifierPlugin,
registry.Register(&plugin.Registration{
Type: plugins.ImageVerifierPlugin,
ID: "bindir",
Config: defaultConfig(),
InitFn: func(ic *plugin.InitContext) (interface{}, error) {

View File

@ -29,6 +29,8 @@ import (
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime"
v2 "github.com/containerd/containerd/runtime/v2"
"github.com/containerd/containerd/sandbox"
@ -38,26 +40,26 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.SandboxControllerPlugin,
registry.Register(&plugin.Registration{
Type: plugins.SandboxControllerPlugin,
ID: "local",
Requires: []plugin.Type{
plugin.RuntimePluginV2,
plugin.EventPlugin,
plugin.SandboxStorePlugin,
plugins.RuntimePluginV2,
plugins.EventPlugin,
plugins.SandboxStorePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
shimPlugin, err := ic.GetByID(plugin.RuntimePluginV2, "shim")
shimPlugin, err := ic.GetByID(plugins.RuntimePluginV2, "shim")
if err != nil {
return nil, err
}
exchangePlugin, err := ic.GetByID(plugin.EventPlugin, "exchange")
exchangePlugin, err := ic.GetByID(plugins.EventPlugin, "exchange")
if err != nil {
return nil, err
}
sbPlugin, err := ic.GetByID(plugin.SandboxStorePlugin, "local")
sbPlugin, err := ic.GetByID(plugins.SandboxStorePlugin, "local")
if err != nil {
return nil, err
}

View File

@ -19,17 +19,19 @@ package sandbox
import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.SandboxStorePlugin,
registry.Register(&plugin.Registration{
Type: plugins.SandboxStorePlugin,
ID: "local",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}

View File

@ -28,17 +28,19 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/streaming"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.StreamingPlugin,
registry.Register(&plugin.Registration{
Type: plugins.StreamingPlugin,
ID: "manager",
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
md, err := ic.Get(plugin.MetadataPlugin)
md, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}

View File

@ -29,6 +29,8 @@ import (
"github.com/containerd/containerd/pkg/unpack"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/log"
// Load packages with type registrations
@ -39,30 +41,30 @@ import (
// Register local transfer service plugin
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.TransferPlugin,
registry.Register(&plugin.Registration{
Type: plugins.TransferPlugin,
ID: "local",
Requires: []plugin.Type{
plugin.LeasePlugin,
plugin.MetadataPlugin,
plugin.DiffPlugin,
plugin.ImageVerifierPlugin,
plugins.LeasePlugin,
plugins.MetadataPlugin,
plugins.DiffPlugin,
plugins.ImageVerifierPlugin,
},
Config: defaultConfig(),
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
config := ic.Config.(*transferConfig)
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
ms := m.(*metadata.DB)
l, err := ic.Get(plugin.LeasePlugin)
l, err := ic.Get(plugins.LeasePlugin)
if err != nil {
return nil, err
}
vfs := make(map[string]imageverifier.ImageVerifier)
vps, err := ic.GetByType(plugin.ImageVerifierPlugin)
vps, err := ic.GetByType(plugins.ImageVerifierPlugin)
if err != nil {
return nil, err
}
@ -82,7 +84,7 @@ func init() {
for _, uc := range config.UnpackConfiguration {
p, err := platforms.Parse(uc.Platform)
if err != nil {
return nil, fmt.Errorf("%s: platform configuration %v invalid", plugin.TransferPlugin, uc.Platform)
return nil, fmt.Errorf("%s: platform configuration %v invalid", plugins.TransferPlugin, uc.Platform)
}
sn := ms.Snapshotter(uc.Snapshotter)
@ -90,7 +92,7 @@ func init() {
return nil, fmt.Errorf("snapshotter %q not found: %w", uc.Snapshotter, errdefs.ErrNotFound)
}
diffPlugins, err := ic.GetByType(plugin.DiffPlugin)
diffPlugins, err := ic.GetByType(plugins.DiffPlugin)
if err != nil {
return nil, fmt.Errorf("error loading diff plugins: %w", err)
}

84
plugins/types.go Normal file
View File

@ -0,0 +1,84 @@
/*
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.
*/
// plugins package stores all the plugin types used by containerd internally.
//
// External plugins should copy from these types and avoid importing this
// package.
package plugins
import "github.com/containerd/containerd/plugin"
const (
// InternalPlugin implements an internal plugin to containerd
InternalPlugin plugin.Type = "io.containerd.internal.v1"
// RuntimePlugin implements a runtime
RuntimePlugin plugin.Type = "io.containerd.runtime.v1"
// RuntimePluginV2 implements a runtime v2
RuntimePluginV2 plugin.Type = "io.containerd.runtime.v2"
// ServicePlugin implements a internal service
ServicePlugin plugin.Type = "io.containerd.service.v1"
// GRPCPlugin implements a grpc service
GRPCPlugin plugin.Type = "io.containerd.grpc.v1"
// TTRPCPlugin implements a ttrpc shim service
TTRPCPlugin plugin.Type = "io.containerd.ttrpc.v1"
// SnapshotPlugin implements a snapshotter
SnapshotPlugin plugin.Type = "io.containerd.snapshotter.v1"
// TaskMonitorPlugin implements a task monitor
TaskMonitorPlugin plugin.Type = "io.containerd.monitor.v1"
// DiffPlugin implements a differ
DiffPlugin plugin.Type = "io.containerd.differ.v1"
// MetadataPlugin implements a metadata store
MetadataPlugin plugin.Type = "io.containerd.metadata.v1"
// ContentPlugin implements a content store
ContentPlugin plugin.Type = "io.containerd.content.v1"
// GCPlugin implements garbage collection policy
GCPlugin plugin.Type = "io.containerd.gc.v1"
// EventPlugin implements event handling
EventPlugin plugin.Type = "io.containerd.event.v1"
// LeasePlugin implements lease manager
LeasePlugin plugin.Type = "io.containerd.lease.v1"
// StreamingPlugin implements a stream manager
StreamingPlugin plugin.Type = "io.containerd.streaming.v1"
// TracingProcessorPlugin implements a open telemetry span processor
TracingProcessorPlugin plugin.Type = "io.containerd.tracing.processor.v1"
// NRIApiPlugin implements the NRI adaptation interface for containerd.
NRIApiPlugin plugin.Type = "io.containerd.nri.v1"
// TransferPlugin implements a transfer service
TransferPlugin plugin.Type = "io.containerd.transfer.v1"
// SandboxStorePlugin implements a sandbox store
SandboxStorePlugin plugin.Type = "io.containerd.sandbox.store.v1"
// SandboxControllerPlugin implements a sandbox controller
SandboxControllerPlugin plugin.Type = "io.containerd.sandbox.controller.v1"
// ImageVerifierPlugin implements an image verifier service
ImageVerifierPlugin plugin.Type = "io.containerd.image-verifier.v1"
)
const (
// RuntimeRuncV2 is the runc runtime that supports multiple containers per shim
RuntimeRuncV2 = "io.containerd.runc.v2"
)
const (
// PropertyRootDir sets the root directory property for a plugin
PropertyRootDir = "io.containerd.plugin.root"
// PropertyStateDir sets the state directory property for a plugin
PropertyStateDir = "io.containerd.plugin.state"
// PropertyGRPCAddress is the grpc address used for client connections to containerd
PropertyGRPCAddress = "io.containerd.plugin.grpc.address"
// PropertyGRPCAddress is the ttrpc address used for client connections to containerd
PropertyTTRPCAddress = "io.containerd.plugin.ttrpc.address"
)

View File

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

View File

@ -24,25 +24,27 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/runtime/v2/shim"
"github.com/containerd/ttrpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.TTRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin,
ID: "task",
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.InternalPlugin,
plugins.EventPlugin,
plugins.InternalPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
pp, err := ic.GetByID(plugin.EventPlugin, "publisher")
pp, err := ic.GetByID(plugins.EventPlugin, "publisher")
if err != nil {
return nil, err
}
ss, err := ic.GetByID(plugin.InternalPlugin, "shutdown")
ss, err := ic.GetByID(plugins.InternalPlugin, "shutdown")
if err != nil {
return nil, err
}

View File

@ -34,6 +34,8 @@ import (
"github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/runtime"
shimbinary "github.com/containerd/containerd/runtime/v2/shim"
@ -50,12 +52,12 @@ type Config struct {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.RuntimePluginV2,
registry.Register(&plugin.Registration{
Type: plugins.RuntimePluginV2,
ID: "task",
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.MetadataPlugin,
plugins.EventPlugin,
plugins.MetadataPlugin,
},
Config: &Config{
Platforms: defaultPlatforms(),
@ -69,11 +71,11 @@ func init() {
ic.Meta.Platforms = supportedPlatforms
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
ep, err := ic.GetByID(plugin.EventPlugin, "exchange")
ep, err := ic.GetByID(plugins.EventPlugin, "exchange")
if err != nil {
return nil, err
}
@ -82,10 +84,10 @@ func init() {
events := ep.(*exchange.Exchange)
shimManager, err := NewShimManager(ic.Context, &ManagerConfig{
Root: ic.Root,
State: ic.State,
Address: ic.Address,
TTRPCAddress: ic.TTRPCAddress,
Root: ic.Properties[plugins.PropertyRootDir],
State: ic.Properties[plugins.PropertyStateDir],
Address: ic.Properties[plugins.PropertyGRPCAddress],
TTRPCAddress: ic.Properties[plugins.PropertyTTRPCAddress],
Events: events,
Store: cs,
SchedCore: config.SchedCore,
@ -103,11 +105,11 @@ func init() {
// However, due to time limits and to avoid migration steps in 1.6 release,
// use the following workaround.
// This expected to be removed in 1.7.
plugin.Register(&plugin.Registration{
Type: plugin.RuntimePluginV2,
registry.Register(&plugin.Registration{
Type: plugins.RuntimePluginV2,
ID: "shim",
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
taskManagerI, err := ic.GetByID(plugin.RuntimePluginV2, "task")
taskManagerI, err := ic.GetByID(plugins.RuntimePluginV2, "task")
if err != nil {
return nil, err
}
@ -176,7 +178,7 @@ type ShimManager struct {
// ID of the shim manager
func (m *ShimManager) ID() string {
return plugin.RuntimePluginV2.String() + ".shim"
return plugins.RuntimePluginV2.String() + ".shim"
}
// Start launches a new shim instance
@ -400,7 +402,7 @@ func NewTaskManager(shims *ShimManager) *TaskManager {
// ID of the task manager
func (m *TaskManager) ID() string {
return plugin.RuntimePluginV2.String() + ".task"
return plugins.RuntimePluginV2.String() + ".task"
}
// Create launches new shim instance and creates new task

View File

@ -24,6 +24,8 @@ import (
"github.com/containerd/containerd/api/types"
"github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/shim"
"github.com/containerd/log"
"github.com/containerd/ttrpc"
@ -33,14 +35,14 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.TTRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin,
ID: "pause",
Requires: []plugin.Type{
plugin.InternalPlugin,
plugins.InternalPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ss, err := ic.GetByID(plugin.InternalPlugin, "shutdown")
ss, err := ic.GetByID(plugins.InternalPlugin, "shutdown")
if err != nil {
return nil, err
}

View File

@ -19,24 +19,26 @@ package plugin
import (
"github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/runtime/v2/runc/task"
"github.com/containerd/containerd/runtime/v2/shim"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.TTRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin,
ID: "task",
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.InternalPlugin,
plugins.EventPlugin,
plugins.InternalPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
pp, err := ic.GetByID(plugin.EventPlugin, "publisher")
pp, err := ic.GetByID(plugins.EventPlugin, "publisher")
if err != nil {
return nil, err
}
ss, err := ic.GetByID(plugin.InternalPlugin, "shutdown")
ss, err := ic.GetByID(plugins.InternalPlugin, "shutdown")
if err != nil {
return nil, err
}

View File

@ -34,6 +34,8 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/shutdown"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/protobuf/proto"
"github.com/containerd/containerd/version"
@ -283,8 +285,8 @@ func run(ctx context.Context, manager Manager, name string, config Config) error
}
}
plugin.Register(&plugin.Registration{
Type: plugin.InternalPlugin,
registry.Register(&plugin.Registration{
Type: plugins.InternalPlugin,
ID: "shutdown",
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
return sd, nil
@ -292,8 +294,8 @@ func run(ctx context.Context, manager Manager, name string, config Config) error
})
// Register event plugin
plugin.Register(&plugin.Registration{
Type: plugin.EventPlugin,
registry.Register(&plugin.Registration{
Type: plugins.EventPlugin,
ID: "publisher",
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
return publisher, nil
@ -306,24 +308,24 @@ func run(ctx context.Context, manager Manager, name string, config Config) error
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()
log.G(ctx).WithField("type", p.Type).Infof("loading plugin %q...", id)
initContext := plugin.NewContext(
ctx,
p,
initialized,
// NOTE: Root is empty since the shim does not support persistent storage,
// 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
// on reboot
"",
bundlePath,
map[string]string{
// NOTE: Root is empty since the shim does not support persistent storage,
// 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
// on reboot
plugins.PropertyStateDir: filepath.Join(bundlePath, p.URI()),
plugins.PropertyGRPCAddress: addressFlag,
plugins.PropertyTTRPCAddress: ttrpcAddress,
},
)
initContext.Address = addressFlag
initContext.TTRPCAddress = ttrpcAddress
// load the plugin specific configuration if it is provided
// TODO: Read configuration passed into shim, or from state directory?

View File

@ -31,6 +31,7 @@ import (
"github.com/containerd/containerd/leases"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/sandbox"
srv "github.com/containerd/containerd/services"
"github.com/containerd/containerd/services/introspection"
@ -183,16 +184,16 @@ func WithInMemoryServices(ic *plugin.InitContext) ClientOpt {
return func(c *clientOpts) error {
var opts []ServicesOpt
for t, fn := range map[plugin.Type]func(interface{}) ServicesOpt{
plugin.EventPlugin: func(i interface{}) ServicesOpt {
plugins.EventPlugin: func(i interface{}) ServicesOpt {
return WithEventService(i.(EventService))
},
plugin.LeasePlugin: func(i interface{}) ServicesOpt {
plugins.LeasePlugin: func(i interface{}) ServicesOpt {
return WithLeasesService(i.(leases.Manager))
},
plugin.SandboxStorePlugin: func(i interface{}) ServicesOpt {
plugins.SandboxStorePlugin: func(i interface{}) ServicesOpt {
return WithSandboxStore(i.(sandbox.Store))
},
plugin.SandboxControllerPlugin: func(i interface{}) ServicesOpt {
plugins.SandboxControllerPlugin: func(i interface{}) ServicesOpt {
return WithSandboxController(i.(sandbox.Controller))
},
} {
@ -203,7 +204,7 @@ func WithInMemoryServices(ic *plugin.InitContext) ClientOpt {
opts = append(opts, fn(i))
}
plugins, err := ic.GetByType(plugin.ServicePlugin)
plugins, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return fmt.Errorf("failed to get service plugin: %w", err)
}

View File

@ -27,6 +27,8 @@ import (
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
bolt "go.etcd.io/bbolt"
@ -37,19 +39,19 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.ContainersService,
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.MetadataPlugin,
plugins.EventPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}

View File

@ -23,24 +23,26 @@ import (
api "github.com/containerd/containerd/api/services/containers/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"google.golang.org/grpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "containers",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.ContainersService]
p, ok := sps[services.ContainersService]
if !ok {
return nil, errors.New("containers service not found")
}

View File

@ -21,19 +21,21 @@ import (
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services"
"github.com/containerd/containerd/services/content/contentserver"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "content",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
plugins, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}

View File

@ -24,6 +24,8 @@ import (
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services"
digest "github.com/opencontainers/go-digest"
)
@ -35,19 +37,19 @@ type store struct {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.ContentService,
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.MetadataPlugin,
plugins.EventPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}

View File

@ -26,6 +26,8 @@ import (
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services"
"github.com/containerd/typeurl/v2"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@ -48,15 +50,15 @@ type differ interface {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.DiffService,
Requires: []plugin.Type{
plugin.DiffPlugin,
plugins.DiffPlugin,
},
Config: defaultDifferConfig,
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
differs, err := ic.GetByType(plugin.DiffPlugin)
differs, err := ic.GetByType(plugins.DiffPlugin)
if err != nil {
return nil, err
}

View File

@ -22,23 +22,25 @@ import (
diffapi "github.com/containerd/containerd/api/services/diff/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services"
"google.golang.org/grpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "diff",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.DiffService]
p, ok := sps[services.DiffService]
if !ok {
return nil, errors.New("diff service not found")
}

View File

@ -26,6 +26,8 @@ import (
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/events/exchange"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/ttrpc"
@ -33,14 +35,14 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "events",
Requires: []plugin.Type{
plugin.EventPlugin,
plugins.EventPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ep, err := ic.GetByID(plugin.EventPlugin, "exchange")
ep, err := ic.GetByID(plugins.EventPlugin, "exchange")
if err != nil {
return nil, err
}

View File

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

View File

@ -28,6 +28,8 @@ import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/pkg/epoch"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"github.com/containerd/log"
@ -37,25 +39,25 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.ImagesService,
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.MetadataPlugin,
plugin.GCPlugin,
plugins.EventPlugin,
plugins.MetadataPlugin,
plugins.GCPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
g, err := ic.Get(plugin.GCPlugin)
g, err := ic.Get(plugins.GCPlugin)
if err != nil {
return nil, err
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}

View File

@ -22,24 +22,26 @@ import (
imagesapi "github.com/containerd/containerd/api/services/images/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"google.golang.org/grpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "images",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.ImagesService]
p, ok := sps[services.ImagesService]
if !ok {
return nil, errors.New("images service not found")
}

View File

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

View File

@ -22,22 +22,24 @@ import (
api "github.com/containerd/containerd/api/services/introspection/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"google.golang.org/grpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "introspection",
Requires: []plugin.Type{plugin.ServicePlugin},
Requires: []plugin.Type{plugins.ServicePlugin},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.IntrospectionService]
p, ok := sps[services.IntrospectionService]
if !ok {
return nil, errors.New("introspection service not found")
}
@ -51,7 +53,7 @@ func init() {
if !ok {
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{
local: localClient,

View File

@ -23,20 +23,22 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/leases"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
ptypes "github.com/containerd/containerd/protobuf/types"
"google.golang.org/grpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "leases",
Requires: []plugin.Type{
plugin.LeasePlugin,
plugins.LeasePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
i, err := ic.GetByID(plugin.LeasePlugin, "manager")
i, err := ic.GetByID(plugins.LeasePlugin, "manager")
if err != nil {
return nil, err
}

View File

@ -27,6 +27,8 @@ import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
bolt "go.etcd.io/bbolt"
@ -36,19 +38,19 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.NamespacesService,
Requires: []plugin.Type{
plugin.EventPlugin,
plugin.MetadataPlugin,
plugins.EventPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}

View File

@ -22,24 +22,26 @@ import (
api "github.com/containerd/containerd/api/services/namespaces/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"google.golang.org/grpc"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "namespaces",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.NamespacesService]
p, ok := sps[services.NamespacesService]
if !ok {
return nil, errors.New("namespaces service not found")
}

View File

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

View File

@ -27,26 +27,28 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/sandbox"
"github.com/containerd/log"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "sandbox-controllers",
Requires: []plugin.Type{
plugin.SandboxControllerPlugin,
plugin.EventPlugin,
plugins.SandboxControllerPlugin,
plugins.EventPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
sc, err := ic.GetByID(plugin.SandboxControllerPlugin, "local")
sc, err := ic.GetByID(plugins.SandboxControllerPlugin, "local")
if err != nil {
return nil, err
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}

View File

@ -25,19 +25,21 @@ import (
"github.com/containerd/containerd/api/types"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/sandbox"
"github.com/containerd/log"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "sandboxes",
Requires: []plugin.Type{
plugin.SandboxStorePlugin,
plugins.SandboxStorePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
sp, err := ic.GetByID(plugin.SandboxStorePlugin, "local")
sp, err := ic.GetByID(plugins.SandboxStorePlugin, "local")
if err != nil {
return nil, err
}

View File

@ -239,11 +239,10 @@ type ProxyPlugin struct {
}
// Decode unmarshals a plugin specific configuration by plugin id
func (c *Config) Decode(ctx context.Context, p *plugin.Registration) (interface{}, error) {
id := p.URI()
func (c *Config) Decode(ctx context.Context, id string, config interface{}) (interface{}, error) {
data, ok := c.Plugins[id]
if !ok {
return p.Config, nil
return config, nil
}
b, err := toml.Marshal(data)
@ -251,7 +250,7 @@ func (c *Config) Decode(ctx context.Context, p *plugin.Registration) (interface{
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
if errors.As(err, &serr) {
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(), " "),
}).WithError(err).Warn("Ignoring unknown key in TOML for plugin")
}
err = toml.Unmarshal(b, p.Config)
err = toml.Unmarshal(b, config)
}
if err != nil {
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

View File

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

View File

@ -46,6 +46,9 @@ import (
"github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/dynamic"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
srvconfig "github.com/containerd/containerd/services/server/config"
ssproxy "github.com/containerd/containerd/snapshots/proxy"
"github.com/containerd/containerd/sys"
@ -127,7 +130,7 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
}
timeout.Set(key, d)
}
plugins, err := LoadPlugins(ctx, config)
loaded, err := LoadPlugins(ctx, config)
if err != nil {
return nil, err
}
@ -223,7 +226,7 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
// Run each plugin migration for each version to ensure that migration logic is simple and
// focused on upgrading from one version at a time.
for v := version; v < srvconfig.CurrentConfigVersion; v++ {
for _, p := range plugins {
for _, p := range loaded {
if p.ConfigMigration != nil {
if err := p.ConfigMigration(ctx, v, config.Plugins); err != nil {
return nil, err
@ -237,20 +240,21 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
log.G(ctx).WithField("t", migrationT).Warnf("Configuration migrated from version %d, use `containerd config migrate` to avoid migration", version)
}
for _, p := range plugins {
for _, p := range loaded {
id := p.URI()
log.G(ctx).WithField("type", p.Type).Infof("loading plugin %q...", id)
var mustSucceed int32
initContext := plugin.NewContext(
ctx,
p,
initialized,
config.Root,
config.State,
map[string]string{
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() {
atomic.StoreInt32(&mustSucceed, 1)
return s.RegisterReadiness()
@ -258,7 +262,7 @@ func New(ctx context.Context, config *srvconfig.Config) (*Server, error) {
// load the plugin specific configuration if it is provided
if p.Config != nil {
pc, err := config.Decode(ctx, p)
pc, err := config.Decode(ctx, id, p.Config)
if err != nil {
return nil, err
}
@ -425,22 +429,23 @@ func (s *Server) Wait() {
// LoadPlugins loads all plugins into containerd and generates an ordered graph
// 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
path := config.PluginDir
if path == "" {
path = filepath.Join(config.Root, "plugins")
}
if err := plugin.Load(path); err != nil {
if err := dynamic.Load(path); err != nil {
return nil, err
}
// load additional plugins that don't automatically register themselves
plugin.Register(&plugin.Registration{
Type: plugin.ContentPlugin,
registry.Register(&plugin.Registration{
Type: plugins.ContentPlugin,
ID: "content",
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Exports["root"] = ic.Root
return local.NewStore(ic.Root)
root := ic.Properties[plugins.PropertyRootDir]
ic.Meta.Exports["root"] = root
return local.NewStore(root)
},
})
@ -456,20 +461,20 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
)
switch pp.Type {
case string(plugin.SnapshotPlugin), "snapshot":
t = plugin.SnapshotPlugin
case string(plugins.SnapshotPlugin), "snapshot":
t = plugins.SnapshotPlugin
ssname := name
f = func(conn *grpc.ClientConn) interface{} {
return ssproxy.NewSnapshotter(ssapi.NewSnapshotsClient(conn), ssname)
}
case string(plugin.ContentPlugin), "content":
t = plugin.ContentPlugin
case string(plugins.ContentPlugin), "content":
t = plugins.ContentPlugin
f = func(conn *grpc.ClientConn) interface{} {
return csproxy.NewContentStore(csapi.NewContentClient(conn))
}
case string(plugin.DiffPlugin), "diff":
t = plugin.DiffPlugin
case string(plugins.DiffPlugin), "diff":
t = plugins.DiffPlugin
f = func(conn *grpc.ClientConn) interface{} {
return diffproxy.NewDiffApplier(diffapi.NewDiffClient(conn))
}
@ -485,7 +490,7 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
p = platforms.DefaultSpec()
}
plugin.Register(&plugin.Registration{
registry.Register(&plugin.Registration{
Type: t,
ID: name,
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
@ -503,7 +508,7 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
filter := srvconfig.V2DisabledFilter
// return the ordered graph for plugins
return plugin.Graph(filter(config.DisabledPlugins)), nil
return registry.Graph(filter(config.DisabledPlugins)), nil
}
type proxyClients struct {

View File

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

View File

@ -24,6 +24,8 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"github.com/containerd/containerd/snapshots"
@ -32,11 +34,11 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "snapshots",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: newService,
})
@ -50,11 +52,11 @@ type service struct {
}
func newService(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.SnapshotsService]
p, ok := sps[services.SnapshotsService]
if !ok {
return nil, errors.New("snapshots service not found")
}

View File

@ -19,18 +19,20 @@ package snapshots
import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/services"
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.SnapshotsService,
Requires: []plugin.Type{
plugin.MetadataPlugin,
plugins.MetadataPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}

View File

@ -24,6 +24,8 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/streaming"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/log"
@ -41,14 +43,14 @@ func init() {
panic(err)
}
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "streaming",
Requires: []plugin.Type{
plugin.StreamingPlugin,
plugins.StreamingPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
i, err := ic.GetByID(plugin.StreamingPlugin, "manager")
i, err := ic.GetByID(plugins.StreamingPlugin, "manager")
if err != nil {
return nil, err
}

View File

@ -19,6 +19,7 @@ package tasks
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"os"
@ -41,6 +42,8 @@ import (
"github.com/containerd/containerd/pkg/rdt"
"github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
"github.com/containerd/containerd/protobuf/proto"
ptypes "github.com/containerd/containerd/protobuf/types"
@ -74,8 +77,8 @@ type Config struct {
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.ServicePlugin,
registry.Register(&plugin.Registration{
Type: plugins.ServicePlugin,
ID: services.TasksService,
Requires: tasksServiceRequires,
Config: &Config{},
@ -88,24 +91,24 @@ func init() {
func initFunc(ic *plugin.InitContext) (interface{}, error) {
config := ic.Config.(*Config)
v2r, err := ic.GetByID(plugin.RuntimePluginV2, "task")
v2r, err := ic.GetByID(plugins.RuntimePluginV2, "task")
if err != nil {
return nil, err
}
m, err := ic.Get(plugin.MetadataPlugin)
m, err := ic.Get(plugins.MetadataPlugin)
if err != nil {
return nil, err
}
ep, err := ic.Get(plugin.EventPlugin)
ep, err := ic.Get(plugins.EventPlugin)
if err != nil {
return nil, err
}
monitor, err := ic.Get(plugin.TaskMonitorPlugin)
monitor, err := ic.Get(plugins.TaskMonitorPlugin)
if err != nil {
if !errdefs.IsNotFound(err) {
if !errors.Is(err, plugin.ErrPluginNotFound) {
return nil, err
}
monitor = runtime.NewNoopMonitor()

View File

@ -20,10 +20,11 @@ package tasks
import (
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
)
var tasksServiceRequires = []plugin.Type{
plugin.RuntimePluginV2,
plugin.MetadataPlugin,
plugin.TaskMonitorPlugin,
plugins.RuntimePluginV2,
plugins.MetadataPlugin,
plugins.TaskMonitorPlugin,
}

View File

@ -18,11 +18,12 @@ package tasks
import (
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
)
var tasksServiceRequires = []plugin.Type{
plugin.EventPlugin,
plugin.RuntimePluginV2,
plugin.MetadataPlugin,
plugin.TaskMonitorPlugin,
plugins.EventPlugin,
plugins.RuntimePluginV2,
plugins.MetadataPlugin,
plugins.TaskMonitorPlugin,
}

View File

@ -20,12 +20,12 @@ package tasks
import (
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
)
var tasksServiceRequires = []plugin.Type{
plugin.EventPlugin,
plugin.RuntimePlugin,
plugin.RuntimePluginV2,
plugin.MetadataPlugin,
plugin.TaskMonitorPlugin,
plugins.EventPlugin,
plugins.RuntimePluginV2,
plugins.MetadataPlugin,
plugins.TaskMonitorPlugin,
}

View File

@ -18,11 +18,12 @@ package tasks
import (
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
)
var tasksServiceRequires = []plugin.Type{
plugin.EventPlugin,
plugin.RuntimePluginV2,
plugin.MetadataPlugin,
plugin.TaskMonitorPlugin,
plugins.EventPlugin,
plugins.RuntimePluginV2,
plugins.MetadataPlugin,
plugins.TaskMonitorPlugin,
}

View File

@ -22,6 +22,8 @@ import (
api "github.com/containerd/containerd/api/services/tasks/v1"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/services"
"google.golang.org/grpc"
@ -32,18 +34,18 @@ var (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "tasks",
Requires: []plugin.Type{
plugin.ServicePlugin,
plugins.ServicePlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.ServicePlugin)
sps, err := ic.GetByType(plugins.ServicePlugin)
if err != nil {
return nil, err
}
p, ok := plugins[services.TasksService]
p, ok := sps[services.TasksService]
if !ok {
return nil, errors.New("tasks service not found")
}

View File

@ -24,8 +24,10 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/pkg/streaming"
"github.com/containerd/containerd/pkg/transfer"
"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/registry"
"github.com/containerd/containerd/plugins"
ptypes "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/log"
"github.com/containerd/typeurl/v2"
@ -36,12 +38,12 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.GRPCPlugin,
registry.Register(&plugin.Registration{
Type: plugins.GRPCPlugin,
ID: "transfer",
Requires: []plugin.Type{
plugin.TransferPlugin,
plugin.StreamingPlugin,
plugins.TransferPlugin,
plugins.StreamingPlugin,
},
InitFn: newService,
})
@ -54,21 +56,21 @@ type service struct {
}
func newService(ic *plugin.InitContext) (interface{}, error) {
plugins, err := ic.GetByType(plugin.TransferPlugin)
sps, err := ic.GetByType(plugins.TransferPlugin)
if err != nil {
return nil, err
}
// TODO: how to determine order?
t := make([]transfer.Transferrer, 0, len(plugins))
for _, p := range plugins {
t := make([]transfer.Transferrer, 0, len(sps))
for _, p := range sps {
i, err := p.Instance()
if err != nil {
return nil, err
}
t = append(t, i.(transfer.Transferrer))
}
sp, err := ic.GetByID(plugin.StreamingPlugin, "manager")
sp, err := ic.GetByID(plugins.StreamingPlugin, "manager")
if err != nil {
return nil, err
}
@ -134,7 +136,7 @@ func (s *service) Transfer(ctx context.Context, req *transferapi.TransferRequest
}
func (s *service) convertAny(ctx context.Context, a typeurl.Any) (interface{}, error) {
obj, err := plugins.ResolveType(a)
obj, err := tplugins.ResolveType(a)
if err != nil {
if errdefs.IsNotFound(err) {
return typeurl.UnmarshalAny(a)

View File

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

View File

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

View File

@ -25,6 +25,8 @@ import (
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots/btrfs"
)
@ -35,9 +37,9 @@ type Config struct {
}
func init() {
plugin.Register(&plugin.Registration{
registry.Register(&plugin.Registration{
ID: "btrfs",
Type: plugin.SnapshotPlugin,
Type: plugins.SnapshotPlugin,
Config: &Config{},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Platforms = []ocispec.Platform{platforms.DefaultSpec()}
@ -47,7 +49,7 @@ func init() {
return nil, errors.New("invalid btrfs configuration")
}
root := ic.Root
root := ic.Properties[plugins.PropertyRootDir]
if len(config.RootPath) != 0 {
root = config.RootPath
}

View File

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

View File

@ -37,6 +37,8 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/containerd/snapshots/storage"
"github.com/containerd/continuity/fs"
@ -45,15 +47,15 @@ import (
)
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.SnapshotPlugin,
registry.Register(&plugin.Registration{
Type: plugins.SnapshotPlugin,
ID: "windows-lcow",
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Platforms = append(ic.Meta.Platforms, ocispec.Platform{
OS: "linux",
Architecture: runtime.GOARCH,
})
return NewSnapshotter(ic.Root)
return NewSnapshotter(ic.Properties[plugins.PropertyRootDir])
},
})
}

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@ import (
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/protobuf"
google_protobuf "github.com/containerd/containerd/protobuf/types"
"github.com/containerd/containerd/rootfs"
@ -309,7 +309,7 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat
switch status.Status {
case Stopped, Unknown, "":
case Created:
if t.client.runtime == plugin.RuntimePlugin.String()+".windows" {
if t.client.runtime == plugins.RuntimePlugin.String()+".windows" {
// On windows Created is akin to Stopped
break
}
@ -326,7 +326,7 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat
// io.Wait locks for restored tasks on Windows unless we call
// io.Close first (https://github.com/containerd/containerd/issues/5621)
// in other cases, preserve the contract and let IO finish before closing
if t.client.runtime == plugin.RuntimePlugin.String()+".windows" {
if t.client.runtime == plugins.RuntimePlugin.String()+".windows" {
t.io.Close()
}
// io.Cancel is used to cancel the io goroutine while it is in
@ -690,7 +690,7 @@ func isCheckpointPathExist(runtime string, v interface{}) bool {
}
switch runtime {
case plugin.RuntimeRuncV2:
case plugins.RuntimeRuncV2:
if opts, ok := v.(*options.CheckpointOptions); ok && opts.ImagePath != "" {
return true
}

View File

@ -25,6 +25,8 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/plugin/registry"
"github.com/containerd/containerd/plugins"
"github.com/containerd/containerd/tracing"
"github.com/containerd/log"
"github.com/sirupsen/logrus"
@ -41,9 +43,9 @@ import (
const exporterPlugin = "otlp"
func init() {
plugin.Register(&plugin.Registration{
registry.Register(&plugin.Registration{
ID: exporterPlugin,
Type: plugin.TracingProcessorPlugin,
Type: plugins.TracingProcessorPlugin,
Config: &OTLPConfig{},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
cfg := ic.Config.(*OTLPConfig)
@ -54,14 +56,19 @@ func init() {
return trace.NewBatchSpanProcessor(exp), nil
},
})
plugin.Register(&plugin.Registration{
ID: "tracing",
Type: plugin.InternalPlugin,
Requires: []plugin.Type{plugin.TracingProcessorPlugin},
Config: &TraceConfig{ServiceName: "containerd", TraceSamplingRatio: 1.0},
registry.Register(&plugin.Registration{
ID: "tracing",
Type: plugins.InternalPlugin,
Requires: []plugin.Type{
plugins.TracingProcessorPlugin,
},
Config: &TraceConfig{
ServiceName: "containerd",
TraceSamplingRatio: 1.0,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
//get TracingProcessorPlugin which is a dependency
plugins, err := ic.GetByType(plugin.TracingProcessorPlugin)
plugins, err := ic.GetByType(plugins.TracingProcessorPlugin)
if err != nil {
return nil, fmt.Errorf("failed to get tracing processors: %w", err)
}

View File

@ -1,4 +0,0 @@
*.test
# Support running go modules in vendor mode for local development
/vendor/

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -1,35 +0,0 @@
# [containerd](https://github.com/containerd/containerd) ZFS snapshotter plugin
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/zfs)](https://pkg.go.dev/github.com/containerd/zfs)
[![Build Status](https://github.com/containerd/zfs/actions/workflows/ci.yml/badge.svg)](https://github.com/containerd/zfs/actions/workflows/ci.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/zfs)](https://goreportcard.com/report/github.com/containerd/zfs)
[![codecov](https://codecov.io/gh/containerd/zfs/branch/main/graph/badge.svg)](https://codecov.io/gh/containerd/zfs)
ZFS snapshotter plugin for containerd.
This plugin is tested on Linux with Ubuntu. It should be compatible with FreeBSD.
## Usage
The plugin is built-in by default since containerd 1.1.
No need to recompile containerd or execute a proxy snapshotter process.
1. Set up a ZFS filesystem.
The ZFS filesystem name is arbitrary but the mount point needs to be `/var/lib/containerd/io.containerd.snapshotter.v1.zfs`, when the containerd root is set to `/var/lib/containerd`.
```console
$ zfs create -o mountpoint=/var/lib/containerd/io.containerd.snapshotter.v1.zfs your-zpool/containerd
```
2. Start containerd.
3. e.g. `ctr pull --snapshotter=zfs ...`
## Project details
The zfs plugin is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
As a containerd sub-project, you will find the:
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
information in our [`containerd/project`](https://github.com/containerd/project) repository.

View File

@ -1 +0,0 @@
comment: false

View File

@ -1,62 +0,0 @@
//go:build linux || freebsd
/*
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 plugin
import (
"errors"
"fmt"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/zfs"
)
// Config represents configuration for the zfs plugin
type Config struct {
// Root directory for the plugin
RootPath string `toml:"root_path"`
}
func init() {
plugin.Register(&plugin.Registration{
Type: plugin.SnapshotPlugin,
ID: "zfs",
Config: &Config{},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Platforms = append(ic.Meta.Platforms, platforms.DefaultSpec())
// get config
config, ok := ic.Config.(*Config)
if !ok {
return nil, errors.New("invalid zfs configuration")
}
// use default ic.Root as root path if config doesn't have a valid root path
root := ic.Root
if len(config.RootPath) != 0 {
root = config.RootPath
}
ic.Meta.Exports["root"] = root
snapshotter, err := zfs.NewSnapshotter(root)
if err != nil {
return nil, fmt.Errorf("%s: %w", err.Error(), plugin.ErrSkipPlugin)
}
return snapshotter, nil
},
})
}

View File

@ -1,368 +0,0 @@
//go:build linux || freebsd
/*
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 zfs
import (
"context"
"fmt"
"math"
"path/filepath"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/containerd/snapshots/storage"
"github.com/containerd/log"
"github.com/mistifyio/go-zfs/v3"
)
const (
// snapshotSuffix is used as follows:
// active := filepath.Join(dataset.Name, id)
// committed := active + "@" + snapshotSuffix
snapshotSuffix = "snapshot"
// Using this typed MaxInt64 to prevent integer overlow on 32bit
maxSnapshotSize int64 = math.MaxInt64
)
type snapshotter struct {
dataset *zfs.Dataset
ms *storage.MetaStore
}
// NewSnapshotter returns a Snapshotter using zfs. Uses the provided
// root directory for snapshots and stores the metadata in
// a file in the provided root.
// root needs to be a mount point of zfs.
func NewSnapshotter(root string) (snapshots.Snapshotter, error) {
m, err := mount.Lookup(root)
if err != nil {
return nil, err
}
if m.FSType != "zfs" {
return nil, fmt.Errorf("path %s must be a zfs filesystem to be used with the zfs snapshotter", root)
}
dataset, err := zfs.GetDataset(m.Source)
if err != nil {
return nil, err
}
ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db"))
if err != nil {
return nil, err
}
b := &snapshotter{
dataset: dataset,
ms: ms,
}
return b, nil
}
var zfsCreateProperties = map[string]string{
"mountpoint": "legacy",
}
// createFilesystem creates but not mount.
func createFilesystem(datasetName string) (*zfs.Dataset, error) {
return zfs.CreateFilesystem(datasetName, zfsCreateProperties)
}
// cloneFilesystem clones but not mount.
func cloneFilesystem(datasetName string, snapshot *zfs.Dataset) (*zfs.Dataset, error) {
return snapshot.Clone(datasetName, zfsCreateProperties)
}
func destroy(dataset *zfs.Dataset) error {
return dataset.Destroy(zfs.DestroyDefault)
}
func destroySnapshot(dataset *zfs.Dataset) error {
return dataset.Destroy(zfs.DestroyDeferDeletion)
}
// Stat returns the info for an active or committed snapshot by name or
// key.
//
// Should be used for parent resolution, existence checks and to discern
// the kind of snapshot.
func (z *snapshotter) Stat(ctx context.Context, key string) (snapshots.Info, error) {
ctx, t, err := z.ms.TransactionContext(ctx, false)
if err != nil {
return snapshots.Info{}, err
}
defer t.Rollback() //nolint:errcheck
_, info, _, err := storage.GetInfo(ctx, key)
if err != nil {
return snapshots.Info{}, err
}
return info, nil
}
// Usage retrieves the disk usage of the top-level snapshot.
func (z *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) {
return z.usage(ctx, key)
}
func (z *snapshotter) usage(ctx context.Context, key string) (snapshots.Usage, error) {
ctx, t, err := z.ms.TransactionContext(ctx, false)
if err != nil {
return snapshots.Usage{}, err
}
id, info, usage, err := storage.GetInfo(ctx, key)
t.Rollback() //nolint:errcheck
if err != nil {
return snapshots.Usage{}, err
}
if info.Kind == snapshots.KindActive {
activeName := filepath.Join(z.dataset.Name, id)
sDataset, err := zfs.GetDataset(activeName)
if err != nil {
return snapshots.Usage{}, err
}
if int64(sDataset.Used) > maxSnapshotSize {
return snapshots.Usage{}, fmt.Errorf("Dataset size exceeds maximum snapshot size of %d bytes", maxSnapshotSize)
}
usage = snapshots.Usage{
Size: int64(sDataset.Used),
Inodes: -1,
}
}
return usage, nil
}
// Walk the committed snapshots.
func (z *snapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, filters ...string) error {
ctx, t, err := z.ms.TransactionContext(ctx, false)
if err != nil {
return err
}
defer t.Rollback() //nolint:errcheck
return storage.WalkInfo(ctx, fn, filters...)
}
func (z *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
return z.createSnapshot(ctx, snapshots.KindActive, key, parent, opts...)
}
func (z *snapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
return z.createSnapshot(ctx, snapshots.KindView, key, parent, opts...)
}
func (z *snapshotter) createSnapshot(ctx context.Context, kind snapshots.Kind, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
ctx, t, err := z.ms.TransactionContext(ctx, true)
if err != nil {
return nil, err
}
defer func() {
if err != nil && t != nil {
if rerr := t.Rollback(); rerr != nil {
log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction")
}
}
}()
a, err := storage.CreateSnapshot(ctx, kind, key, parent, opts...)
if err != nil {
return nil, err
}
targetName := filepath.Join(z.dataset.Name, a.ID)
var target *zfs.Dataset
if len(a.ParentIDs) == 0 {
target, err = createFilesystem(targetName)
if err != nil {
return nil, err
}
} else {
parent0Name := filepath.Join(z.dataset.Name, a.ParentIDs[0]) + "@" + snapshotSuffix
parent0, err := zfs.GetDataset(parent0Name)
if err != nil {
return nil, err
}
target, err = cloneFilesystem(targetName, parent0)
if err != nil {
return nil, err
}
}
err = t.Commit()
t = nil
if err != nil {
if derr := destroy(target); derr != nil {
log.G(ctx).WithError(derr).WithField("targetName", targetName).Error("failed to delete dataset")
}
return nil, err
}
readonly := kind == snapshots.KindView
return z.mounts(target, readonly)
}
func (z *snapshotter) mounts(dataset *zfs.Dataset, readonly bool) ([]mount.Mount, error) {
var options []string
if readonly {
options = append(options, "ro")
}
return []mount.Mount{
{
Type: "zfs",
Source: dataset.Name,
Options: options,
},
}, nil
}
func (z *snapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) (err error) {
usage, err := z.usage(ctx, key)
if err != nil {
return fmt.Errorf("failed to compute usage: %w", err)
}
ctx, t, err := z.ms.TransactionContext(ctx, true)
if err != nil {
return err
}
defer func() {
if err != nil && t != nil {
if rerr := t.Rollback(); rerr != nil {
log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction")
}
}
}()
id, err := storage.CommitActive(ctx, key, name, usage, opts...)
if err != nil {
return fmt.Errorf("failed to commit: %w", err)
}
activeName := filepath.Join(z.dataset.Name, id)
active, err := zfs.GetDataset(activeName)
if err != nil {
return err
}
snapshot, err := active.Snapshot(snapshotSuffix, false)
if err != nil {
return err
}
err = t.Commit()
t = nil
if err != nil {
snapshotName := activeName + "@" + snapshotSuffix
if derr := destroySnapshot(snapshot); derr != nil {
log.G(ctx).WithError(derr).WithField("snapshotName", snapshotName).Error("failed to delete dataset")
}
return err
}
return nil
}
// Mounts returns the mounts for the transaction identified by key. Can be
// called on an read-write or readonly transaction.
//
// This can be used to recover mounts after calling View or Prepare.
func (z *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
ctx, t, err := z.ms.TransactionContext(ctx, false)
if err != nil {
return nil, err
}
s, err := storage.GetSnapshot(ctx, key)
t.Rollback() //nolint:errcheck
if err != nil {
return nil, fmt.Errorf("failed to get active snapshot: %w", err)
}
sName := filepath.Join(z.dataset.Name, s.ID)
sDataset, err := zfs.GetDataset(sName)
if err != nil {
return nil, err
}
return z.mounts(sDataset, false)
}
// Remove abandons the transaction identified by key. All resources
// associated with the key will be removed.
func (z *snapshotter) Remove(ctx context.Context, key string) (err error) {
ctx, t, err := z.ms.TransactionContext(ctx, true)
if err != nil {
return err
}
defer func() {
if err != nil && t != nil {
if rerr := t.Rollback(); rerr != nil {
log.G(ctx).WithError(rerr).Warn("Failure rolling back transaction")
}
}
// FIXME: rolling back the removed ZFS dataset is unsupported yet
}()
id, k, err := storage.Remove(ctx, key)
if err != nil {
return fmt.Errorf("failed to remove snapshot: %w", err)
}
datasetName := filepath.Join(z.dataset.Name, id)
if k == snapshots.KindCommitted {
snapshotName := datasetName + "@" + snapshotSuffix
snapshot, err := zfs.GetDataset(snapshotName)
if err != nil {
return err
}
if err = destroySnapshot(snapshot); err != nil {
return err
}
}
dataset, err := zfs.GetDataset(datasetName)
if err != nil {
return err
}
if err = destroy(dataset); err != nil {
return err
}
err = t.Commit()
t = nil
return err
}
func (o *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) {
ctx, t, err := o.ms.TransactionContext(ctx, true)
if err != nil {
return snapshots.Info{}, err
}
info, err = storage.UpdateInfo(ctx, info, fieldpaths...)
if err != nil {
t.Rollback() //nolint:errcheck
return snapshots.Info{}, err
}
if err := t.Commit(); err != nil {
return snapshots.Info{}, err
}
return info, nil
}
func (o *snapshotter) Close() error {
return o.ms.Close()
}

View File

@ -1,4 +0,0 @@
has nix && use nix
dotenv_if_exists
PATH_add bin
path_add GOBIN bin

View File

@ -1,6 +0,0 @@
bin
go-zfs.test
.vagrant
# added by lint-install
out/

View File

@ -1,207 +0,0 @@
run:
# The default runtime timeout is 1m, which doesn't work well on Github Actions.
timeout: 4m
# NOTE: This file is populated by the lint-install tool. Local adjustments may be overwritten.
linters-settings:
cyclop:
# NOTE: This is a very high transitional threshold
max-complexity: 37
package-average: 34.0
skip-tests: true
gocognit:
# NOTE: This is a very high transitional threshold
min-complexity: 98
dupl:
threshold: 200
goconst:
min-len: 4
min-occurrences: 5
ignore-tests: true
gosec:
excludes:
- G107 # Potential HTTP request made with variable url
- G204 # Subprocess launched with function call as argument or cmd arguments
- G404 # Use of weak random number generator (math/rand instead of crypto/rand
errorlint:
# these are still common in Go: for instance, exit errors.
asserts: false
exhaustive:
default-signifies-exhaustive: true
nestif:
min-complexity: 8
nolintlint:
require-explanation: true
allow-unused: false
require-specific: true
revive:
ignore-generated-header: true
severity: warning
rules:
- name: atomic
- name: blank-imports
- name: bool-literal-in-expr
- name: confusing-naming
- name: constant-logical-expr
- name: context-as-argument
- name: context-keys-type
- name: deep-exit
- name: defer
- name: range-val-in-closure
- name: range-val-address
- name: dot-imports
- name: error-naming
- name: error-return
- name: error-strings
- name: errorf
- name: exported
- name: identical-branches
- name: if-return
- name: import-shadowing
- name: increment-decrement
- name: indent-error-flow
- name: indent-error-flow
- name: package-comments
- name: range
- name: receiver-naming
- name: redefines-builtin-id
- name: superfluous-else
- name: struct-tag
- name: time-naming
- name: unexported-naming
- name: unexported-return
- name: unnecessary-stmt
- name: unreachable-code
- name: unused-parameter
- name: var-declaration
- name: var-naming
- name: unconditional-recursion
- name: waitgroup-by-value
staticcheck:
go: "1.16"
unused:
go: "1.16"
output:
sort-results: true
linters:
disable-all: true
enable:
- asciicheck
- bodyclose
- cyclop
- deadcode
- dogsled
- dupl
- durationcheck
- errcheck
- errname
- errorlint
- exhaustive
- exportloopref
- forcetypeassert
- gocognit
- goconst
- gocritic
- godot
- gofmt
- gofumpt
- gosec
- goheader
- goimports
- goprintffuncname
- gosimple
- govet
- ifshort
- importas
- ineffassign
- makezero
- misspell
- nakedret
- nestif
- nilerr
- noctx
- nolintlint
- predeclared
# disabling for the initial iteration of the linting tool
# - promlinter
- revive
- rowserrcheck
- sqlclosecheck
- staticcheck
- structcheck
- stylecheck
- thelper
- tparallel
- typecheck
- unconvert
- unparam
- unused
- varcheck
- wastedassign
- whitespace
# Disabled linters, due to being misaligned with Go practices
# - exhaustivestruct
# - gochecknoglobals
# - gochecknoinits
# - goconst
# - godox
# - goerr113
# - gomnd
# - lll
# - nlreturn
# - testpackage
# - wsl
# Disabled linters, due to not being relevant to our code base:
# - maligned
# - prealloc "For most programs usage of prealloc will be a premature optimization."
# Disabled linters due to bad error messages or bugs
# - tagliatelle
issues:
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
- path: _test\.go
linters:
- dupl
- errcheck
- forcetypeassert
- gocyclo
- gosec
- noctx
- path: .*cmd.*
linters:
- noctx
- path: main\.go
linters:
- noctx
- path: .*cmd.*
text: "deep-exit"
- path: main\.go
text: "deep-exit"
# This check is of questionable value
- linters:
- tparallel
text: "call t.Parallel on the top level as well as its subtests"
# Don't hide lint issues just because there are many of them
max-same-issues: 0
max-issues-per-linter: 0

View File

@ -1,16 +0,0 @@
---
extends: default
rules:
braces:
max-spaces-inside: 1
brackets:
max-spaces-inside: 1
comments: disable
comments-indentation: disable
document-start: disable
line-length:
level: warning
max: 160
allow-non-breakable-inline-mappings: true
truthy: disable

View File

@ -1,250 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
This change log follows the advice of [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog).
## [Unreleased]
## [3.0.0] - 2022-03-30
### Added
- Rename, Mount and Unmount methods
- Parse more fields into Zpool type:
- dedupratio
- fragmentation
- freeing
- leaked
- readonly
- Parse more fields into Dataset type:
- referenced
- Incremental Send
- Parse numbers in exact format
- Support for Solaris (non-blockint, best-effort status)
- Debug logging for command invocation
- Use GitHub Actions for CI
- Nix shell for dev env reproducibility
- Direnv file for ease of dev
- Formatting/lint checks (enforced by CI)
- Go Module
- FreeBSD based vagrant machine
### Changed
- Temporarily adjust TestDiff expected strings depending on ZFS version
- Use one `zfs list`/`zpool list` call instead of many `zfs get`/`zpool get`
- ZFS docs links now point to OpenZFS pages
- Ubuntu vagrant box changed to generic/ubuntu2004
### Fixed
- `GetProperty` returning `VALUE` instead of the actual value
### Shortlog
Amit Krishnan (1):
Issue #39 and Issue #40 - Enable Solaris support for go-zfs Switch from zfs/zpool get to zfs/zpool list for better performance Signed-off-by: Amit Krishnan <krish.amit@gmail.com>
Anand Patil (3):
Added Rename
Small fix to rename.
Added mount and umount methods
Brian Akins (1):
Add 'referenced' to zfs properties
Brian Bickerton (3):
Add debug logging before and after running external zfs command
Don't export the default no-op logger
Update uuid package repo url
Dmitry Teselkin (1):
Issue #52 - fix parseLine for fragmentation field
Edward Betts (1):
correct spelling mistake
Justin Cormack (1):
Switch to google/uuid which is the maintained version of pborman/uuid
Manuel Mendez (40):
rename Umount -> Unmount to follow zfs command name
add missing Unmount/Mount docs
always allocate largest Mount slice
add travis config
travis: update to go 1.7
travis: get go deps first
test: add nok helper to verify an error occurred
test: add test for Dataset.GetProperty
ci: swap #cerana on freenode for slack
ci: install new deps for 0.7 relases
ci: bump zol versions
ci: bump go versions
ci: use better gometalinter invocations
ci: add ccache
ci: set env earlier in before_install
fix test nok error printing
test: restructure TestDiff to deal with different order of changes
test: better unicode path handling in TestDiff
travis: bump zfs and go versions
cache zfs artifacts
Add nix-shell and direnv goodness
prettierify all the files
Add go based tools
Add Makefile and rules.mk files
gofumptize the code base
Use tinkerbell/lint-install to setup linters
make golangci-lint happy
Update CONTRIBUTING.md with make based approach
Add GitHub Actions
Drop Travis CI
One sentence per line
Update documentation links to openzfs-docs pages
Format Vagrantfile using rufo
Add go-zfs.test to .gitignore
test: Avoid reptitive/duplicate error logging and quitting
test: Use t.Logf instead of fmt.Printf
test: Better cleanup and error handling in zpoolTest
test: Do not mark TestDatasets as a t.Helper.
test: Change zpoolTest to a pure helper that returns a clean up function
test: Move helpers to a different file
vagrant: Add set -euxo pipefail to provision script
vagrant: Update to generic/ubuntu2004
vagrant: Minor fixes to Vagrantfile
vagrant: Update to go 1.17.8
vagrant: Run go tests as part of provision script
vagrant: Indent heredoc script
vagrant: Add freebsd machine
Matt Layher (1):
Parse more fields into Zpool type
Michael Crosby (1):
Add incremental send
Rikard Gynnerstedt (1):
remove command name from joined args
Sebastiaan van Stijn (1):
Add go.mod and rename to github.com/mistifyio/go-zfs/v3 (v3.0.0)
mikudeko (1):
Fix GetProperty always returning 'VALUE'
## [2.1.1] - 2015-05-29
### Fixed
- Ignoring first pool listed
- Incorrect `zfs get` argument ordering
### Shortlog
Alexey Guskov (1):
zfs command uses different order of arguments on freebsd
Brian Akins (4):
test that ListZpools returns expected zpool
test error first
test error first
fix test to check correct return value
James Cunningham (1):
Fix Truncating First Zpool
Pat Norton (2):
Added Use of Go Tools
Update CONTRIBUTING.md
## [2.1.0] - 2014-12-08
### Added
- Parse hardlink modification count returned from `zfs diff`
### Fixed
- Continuing instead of erroring when rolling back a non-snapshot
### Shortlog
Brian Akins (2):
need to return the error here
use named struct fields
Jörg Thalheim (1):
zfs diff handle hardlinks modification now
## [2.0.0] - 2014-12-02
### Added
- Flags for Destroy:
- DESTROY_DEFAULT
- DESTROY_DEFER_DELETION (`zfs destroy ... -d`)
- DESTROY_FORCE (`zfs destroy ... -f`)
- DESTROY_RECURSIVE_CLONES (`zfs destroy ... -R`)
- DESTROY_RECURSIVE (`zfs destroy ... -r`)
- etc
- Diff method (`zfs diff`)
- LogicalUsed and Origin properties to Dataset
- Type constants for Dataset
- State constants for Zpool
- Logger interface
- Improve documentation
### Shortlog
Brian Akins (8):
remove reflection
style change for switches
need to check for error
keep in scope
go 1.3.3
golint cleanup
Just test if logical used is greater than 0, as this appears to be implementation specific
add docs to satisfy golint
Jörg Thalheim (8):
Add deferred flag to zfs.Destroy()
add Logicalused property
Add Origin property
gofmt
Add zfs.Diff
Add Logger
add recursive destroy with clones
use CamelCase-style constants
Matt Layher (4):
Improve documentation, document common ZFS operations, provide more references
Add zpool state constants, for easier health checking
Add dataset type constants, for easier type checking
Fix string split in command.Run(), use strings.Fields() instead of strings.Split()
## [1.0.0] - 2014-11-12
### Shortlog
Brian Akins (7):
add godoc badge
Add example
add information about zpool to struct and parser
Add Quota
add Children call
add Children call
fix snapshot tests
Brian Bickerton (3):
MIST-150 Change Snapshot second paramater from properties map[string][string] to recursive bool
MIST-150 Add Rollback method and related tests
MIST-160 Add SendSnapshot streaming method and tests
Matt Layher (1):
Add Error struct type and tests, enabling easier error return checking
[3.0.0]: https://github.com/mistifyio/go-zfs/compare/v2.1.1...v3.0.0
[2.1.1]: https://github.com/mistifyio/go-zfs/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/mistifyio/go-zfs/compare/v2.0.0...v2.1.0
[2.0.0]: https://github.com/mistifyio/go-zfs/compare/v1.0.0...v2.0.0
[1.0.0]: https://github.com/mistifyio/go-zfs/compare/v0.0.0...v1.0.0

Some files were not shown because too many files have changed in this diff Show More