Skip to content

Commit

Permalink
plugin: wire in plugin loader for node creation
Browse files Browse the repository at this point in the history
License: MIT
Signed-off-by: Kacper Łukawski <[email protected]>
  • Loading branch information
PlayerWithoutName authored and Stebalien committed Dec 18, 2018
1 parent d0c2727 commit a1e654c
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 147 deletions.
48 changes: 33 additions & 15 deletions cmd/ipfs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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)
}

Expand Down
5 changes: 4 additions & 1 deletion commands/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -23,6 +24,8 @@ type Context struct {
ConfigRoot string
ReqLog *ReqLog

Plugins *loader.PluginLoader

config *config.Config
LoadConfig func(path string) (*config.Config, error)

Expand Down
63 changes: 0 additions & 63 deletions plugin/loader/initializer.go

This file was deleted.

67 changes: 0 additions & 67 deletions plugin/loader/load.go

This file was deleted.

125 changes: 125 additions & 0 deletions plugin/loader/loader.go
Original file line number Diff line number Diff line change
@@ -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
}
14 changes: 13 additions & 1 deletion repo/fsrepo/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit a1e654c

Please sign in to comment.