mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
plugin: wire in plugin loader for node creation
License: MIT Signed-off-by: Kacper Łukawski <kacluk98@gmail.com>
This commit is contained in:
parent
d0c27272ad
commit
a1e654cd38
@ -51,6 +51,33 @@ const (
|
||||
heapProfile = "ipfs.memprof"
|
||||
)
|
||||
|
||||
func loadPlugins(repoPath string) (*loader.PluginLoader, error) {
|
||||
pluginpath := filepath.Join(repoPath, "plugins")
|
||||
|
||||
// check if repo is accessible before loading plugins
|
||||
var plugins *loader.PluginLoader
|
||||
ok, err := checkPermissions(repoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
pluginpath = ""
|
||||
}
|
||||
plugins, err = loader.NewPluginLoader(pluginpath)
|
||||
if err != nil {
|
||||
log.Error("error loading plugins: ", err)
|
||||
}
|
||||
|
||||
if err := plugins.Initialize(); err != nil {
|
||||
log.Error("error initializing plugins: ", err)
|
||||
}
|
||||
|
||||
if err := plugins.Run(); err != nil {
|
||||
log.Error("error running plugins: ", err)
|
||||
}
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
// main roadmap:
|
||||
// - parse the commandline to get a cmdInvocation
|
||||
// - if user requests help, print it and exit.
|
||||
@ -116,12 +143,18 @@ func mainRet() int {
|
||||
}
|
||||
log.Debugf("config path is %s", repoPath)
|
||||
|
||||
plugins, err := loadPlugins(repoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// this sets up the function that will initialize the node
|
||||
// this is so that we can construct the node lazily.
|
||||
return &oldcmds.Context{
|
||||
ConfigRoot: repoPath,
|
||||
LoadConfig: loadConfig,
|
||||
ReqLog: &oldcmds.ReqLog{},
|
||||
Plugins: plugins,
|
||||
ConstructNode: func() (n *core.IpfsNode, err error) {
|
||||
if req == nil {
|
||||
return nil, errors.New("constructing node without a request")
|
||||
@ -179,21 +212,6 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
|
||||
if client != nil && !req.Command.External {
|
||||
exctr = client.(cmds.Executor)
|
||||
} else {
|
||||
cctx := env.(*oldcmds.Context)
|
||||
pluginpath := filepath.Join(cctx.ConfigRoot, "plugins")
|
||||
|
||||
// check if repo is accessible before loading plugins
|
||||
ok, err := checkPermissions(cctx.ConfigRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
pluginpath = ""
|
||||
}
|
||||
if _, err := loader.LoadPlugins(pluginpath); err != nil {
|
||||
log.Error("error loading plugins: ", err)
|
||||
}
|
||||
|
||||
exctr = cmds.NewExecutor(req.Root)
|
||||
}
|
||||
|
||||
|
||||
@ -6,9 +6,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/go-ipfs/core"
|
||||
core "github.com/ipfs/go-ipfs/core"
|
||||
coreapi "github.com/ipfs/go-ipfs/core/coreapi"
|
||||
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
|
||||
loader "github.com/ipfs/go-ipfs/plugin/loader"
|
||||
|
||||
"gx/ipfs/QmPdvMtgpnMuU68mWhGtzCxnddXJoV96tT9aPcNbQsqPaM/go-ipfs-cmds"
|
||||
config "gx/ipfs/QmYyzmMnhNTtoXx5ttgUaRdHHckYnQWjPL98hgLAR2QLDD/go-ipfs-config"
|
||||
@ -23,6 +24,8 @@ type Context struct {
|
||||
ConfigRoot string
|
||||
ReqLog *ReqLog
|
||||
|
||||
Plugins *loader.PluginLoader
|
||||
|
||||
config *config.Config
|
||||
LoadConfig func(path string) (*config.Config, error)
|
||||
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-ipfs/core/coredag"
|
||||
"github.com/ipfs/go-ipfs/plugin"
|
||||
"github.com/ipfs/go-ipfs/repo/fsrepo"
|
||||
|
||||
"gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go"
|
||||
ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
|
||||
)
|
||||
|
||||
func initialize(plugins []plugin.Plugin) error {
|
||||
for _, p := range plugins {
|
||||
err := p.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func run(plugins []plugin.Plugin) error {
|
||||
for _, pl := range plugins {
|
||||
switch pl := pl.(type) {
|
||||
case plugin.PluginIPLD:
|
||||
err := runIPLDPlugin(pl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case plugin.PluginTracer:
|
||||
err := runTracerPlugin(pl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case plugin.PluginDatastore:
|
||||
err := fsrepo.AddDatastoreConfigHandler(pl.DatastoreTypeName(), pl.DatastoreConfigParser())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
panic(pl)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runIPLDPlugin(pl plugin.PluginIPLD) error {
|
||||
err := pl.RegisterBlockDecoders(ipld.DefaultBlockDecoder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pl.RegisterInputEncParsers(coredag.DefaultInputEncParsers)
|
||||
}
|
||||
|
||||
func runTracerPlugin(pl plugin.PluginTracer) error {
|
||||
tracer, err := pl.InitTracer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opentracing.SetGlobalTracer(tracer)
|
||||
return nil
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ipfs/go-ipfs/plugin"
|
||||
|
||||
logging "gx/ipfs/QmcuXC5cxs79ro2cUuHs4HQ2bkDLJUYokwL8aivcX6HW3C/go-log"
|
||||
)
|
||||
|
||||
var log = logging.Logger("plugin/loader")
|
||||
|
||||
var loadPluginsFunc = func(string) ([]plugin.Plugin, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// LoadPlugins loads and initializes plugins.
|
||||
func LoadPlugins(pluginDir string) ([]plugin.Plugin, error) {
|
||||
plMap := make(map[string]plugin.Plugin)
|
||||
for _, v := range preloadPlugins {
|
||||
plMap[v.Name()] = v
|
||||
}
|
||||
|
||||
if pluginDir != "" {
|
||||
newPls, err := loadDynamicPlugins(pluginDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pl := range newPls {
|
||||
if ppl, ok := plMap[pl.Name()]; ok {
|
||||
// plugin is already preloaded
|
||||
return nil, fmt.Errorf(
|
||||
"plugin: %s, is duplicated in version: %s, "+
|
||||
"while trying to load dynamically: %s",
|
||||
ppl.Name(), ppl.Version(), pl.Version())
|
||||
}
|
||||
plMap[pl.Name()] = pl
|
||||
}
|
||||
}
|
||||
|
||||
pls := make([]plugin.Plugin, 0, len(plMap))
|
||||
for _, v := range plMap {
|
||||
pls = append(pls, v)
|
||||
}
|
||||
|
||||
err := initialize(pls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = run(pls)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) {
|
||||
_, err := os.Stat(pluginDir)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return loadPluginsFunc(pluginDir)
|
||||
}
|
||||
125
plugin/loader/loader.go
Normal file
125
plugin/loader/loader.go
Normal file
@ -0,0 +1,125 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ipfs/go-ipfs/core/coredag"
|
||||
"github.com/ipfs/go-ipfs/plugin"
|
||||
"github.com/ipfs/go-ipfs/repo/fsrepo"
|
||||
"os"
|
||||
|
||||
opentracing "gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go"
|
||||
ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
|
||||
logging "gx/ipfs/QmcuXC5cxs79ro2cUuHs4HQ2bkDLJUYokwL8aivcX6HW3C/go-log"
|
||||
)
|
||||
|
||||
var log = logging.Logger("plugin/loader")
|
||||
|
||||
var loadPluginsFunc = func(string) ([]plugin.Plugin, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// PluginLoader keeps track of loaded plugins
|
||||
type PluginLoader struct {
|
||||
plugins []plugin.Plugin
|
||||
}
|
||||
|
||||
// NewPluginLoader creates new plugin loader
|
||||
func NewPluginLoader(pluginDir string) (*PluginLoader, error) {
|
||||
plMap := make(map[string]plugin.Plugin)
|
||||
for _, v := range preloadPlugins {
|
||||
plMap[v.Name()] = v
|
||||
}
|
||||
|
||||
if pluginDir != "" {
|
||||
newPls, err := loadDynamicPlugins(pluginDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, pl := range newPls {
|
||||
if ppl, ok := plMap[pl.Name()]; ok {
|
||||
// plugin is already preloaded
|
||||
return nil, fmt.Errorf(
|
||||
"plugin: %s, is duplicated in version: %s, "+
|
||||
"while trying to load dynamically: %s",
|
||||
ppl.Name(), ppl.Version(), pl.Version())
|
||||
}
|
||||
plMap[pl.Name()] = pl
|
||||
}
|
||||
}
|
||||
|
||||
loader := &PluginLoader{plugins: make([]plugin.Plugin, 0, len(plMap))}
|
||||
|
||||
for _, v := range plMap {
|
||||
loader.plugins = append(loader.plugins, v)
|
||||
}
|
||||
|
||||
return loader, nil
|
||||
}
|
||||
|
||||
func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) {
|
||||
_, err := os.Stat(pluginDir)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return loadPluginsFunc(pluginDir)
|
||||
}
|
||||
|
||||
//Initialize all loaded plugins
|
||||
func (loader *PluginLoader) Initialize() error {
|
||||
for _, p := range loader.plugins {
|
||||
err := p.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Run the plugins
|
||||
func (loader *PluginLoader) Run() error {
|
||||
for _, pl := range loader.plugins {
|
||||
switch pl := pl.(type) {
|
||||
case plugin.PluginIPLD:
|
||||
err := runIPLDPlugin(pl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case plugin.PluginTracer:
|
||||
err := runTracerPlugin(pl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case plugin.PluginDatastore:
|
||||
err := fsrepo.AddDatastoreConfigHandler(pl.DatastoreTypeName(), pl.DatastoreConfigParser())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
panic(pl)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runIPLDPlugin(pl plugin.PluginIPLD) error {
|
||||
err := pl.RegisterBlockDecoders(ipld.DefaultBlockDecoder)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pl.RegisterInputEncParsers(coredag.DefaultInputEncParsers)
|
||||
}
|
||||
|
||||
func runTracerPlugin(pl plugin.PluginTracer) error {
|
||||
tracer, err := pl.InitTracer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opentracing.SetGlobalTracer(tracer)
|
||||
return nil
|
||||
}
|
||||
@ -75,7 +75,19 @@ var measureConfig = []byte(`{
|
||||
}`)
|
||||
|
||||
func TestDefaultDatastoreConfig(t *testing.T) {
|
||||
loader.LoadPlugins("")
|
||||
loader, err := loader.NewPluginLoader("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = loader.Initialize()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = loader.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "ipfs-datastore-config-test")
|
||||
if err != nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user