From a1e654cd38ce63a108b0f110e4f88222a3dd073b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20=C5=81ukawski?= Date: Sat, 10 Mar 2018 21:40:46 +0100 Subject: [PATCH] plugin: wire in plugin loader for node creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Kacper Ɓukawski --- cmd/ipfs/main.go | 48 +++++++++----- commands/context.go | 5 +- plugin/loader/initializer.go | 63 ------------------ plugin/loader/load.go | 67 ------------------- plugin/loader/loader.go | 125 +++++++++++++++++++++++++++++++++++ repo/fsrepo/config_test.go | 14 +++- 6 files changed, 175 insertions(+), 147 deletions(-) delete mode 100644 plugin/loader/initializer.go delete mode 100644 plugin/loader/load.go create mode 100644 plugin/loader/loader.go diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index d1c7ba83764..9c8b1262a08 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -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) } diff --git a/commands/context.go b/commands/context.go index 34904ae8108..8d14e3b2a29 100644 --- a/commands/context.go +++ b/commands/context.go @@ -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) diff --git a/plugin/loader/initializer.go b/plugin/loader/initializer.go deleted file mode 100644 index 95068cd70fc..00000000000 --- a/plugin/loader/initializer.go +++ /dev/null @@ -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 -} diff --git a/plugin/loader/load.go b/plugin/loader/load.go deleted file mode 100644 index bce3e42c4fb..00000000000 --- a/plugin/loader/load.go +++ /dev/null @@ -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) -} diff --git a/plugin/loader/loader.go b/plugin/loader/loader.go new file mode 100644 index 00000000000..c58335d9e15 --- /dev/null +++ b/plugin/loader/loader.go @@ -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 +} diff --git a/repo/fsrepo/config_test.go b/repo/fsrepo/config_test.go index bd402bf28e1..6221d087822 100644 --- a/repo/fsrepo/config_test.go +++ b/repo/fsrepo/config_test.go @@ -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 {