plugin: wire in plugin loader for node creation
License: MIT Signed-off-by: Kacper Łukawski <kacluk98@gmail.com>
Kacper Łukawski committed
Mar 10, 2018 at 21:40 UTC
a1e654cd38ce63a108b0f110e4f88222a3dd073b
6 files changed
+175
-147
cmd/ipfs/main.go
+33
-15
@@ -51,6 +51,33 @@ const (
51
heapProfile = "ipfs.memprof"
52
)
53
54
+func loadPlugins(repoPath string) (*loader.PluginLoader, error) {
55
+ pluginpath := filepath.Join(repoPath, "plugins")
56
+
57
+ // check if repo is accessible before loading plugins
58
+ var plugins *loader.PluginLoader
59
+ ok, err := checkPermissions(repoPath)
60
+ if err != nil {
61
+ return nil, err
62
+ }
63
+ if !ok {
64
+ pluginpath = ""
65
+ }
66
+ plugins, err = loader.NewPluginLoader(pluginpath)
67
+ if err != nil {
68
+ log.Error("error loading plugins: ", err)
69
+ }
70
+
71
+ if err := plugins.Initialize(); err != nil {
72
+ log.Error("error initializing plugins: ", err)
73
+ }
74
+
75
+ if err := plugins.Run(); err != nil {
76
+ log.Error("error running plugins: ", err)
77
+ }
78
+ return plugins, nil
79
+}
80
+
81
// main roadmap:
82
// - parse the commandline to get a cmdInvocation
83
// - if user requests help, print it and exit.
@@ -116,12 +143,18 @@ func mainRet() int {
143
}
144
log.Debugf("config path is %s", repoPath)
145
146
+ plugins, err := loadPlugins(repoPath)
147
+ if err != nil {
148
+ return nil, err
149
+ }
150
+
151
// this sets up the function that will initialize the node
152
// this is so that we can construct the node lazily.
153
return &oldcmds.Context{
154
ConfigRoot: repoPath,
155
LoadConfig: loadConfig,
156
ReqLog: &oldcmds.ReqLog{},
157
+ Plugins: plugins,
158
ConstructNode: func() (n *core.IpfsNode, err error) {
159
if req == nil {
160
return nil, errors.New("constructing node without a request")
@@ -179,21 +212,6 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
212
if client != nil && !req.Command.External {
213
exctr = client.(cmds.Executor)
214
} else {
182
- cctx := env.(*oldcmds.Context)
183
- pluginpath := filepath.Join(cctx.ConfigRoot, "plugins")
184
-
185
- // check if repo is accessible before loading plugins
186
- ok, err := checkPermissions(cctx.ConfigRoot)
187
- if err != nil {
188
- return nil, err
189
- }
190
- if !ok {
191
- pluginpath = ""
192
- }
193
- if _, err := loader.LoadPlugins(pluginpath); err != nil {
194
- log.Error("error loading plugins: ", err)
195
- }
196
-
215
exctr = cmds.NewExecutor(req.Root)
216
}
217
commands/context.go
+4
-1
@@ -6,9 +6,10 @@ import (
6
"strings"
7
"time"
8
9
- "github.com/ipfs/go-ipfs/core"
9
+ core "github.com/ipfs/go-ipfs/core"
10
coreapi "github.com/ipfs/go-ipfs/core/coreapi"
11
coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
12
+ loader "github.com/ipfs/go-ipfs/plugin/loader"
13
14
"gx/ipfs/QmPdvMtgpnMuU68mWhGtzCxnddXJoV96tT9aPcNbQsqPaM/go-ipfs-cmds"
15
config "gx/ipfs/QmYyzmMnhNTtoXx5ttgUaRdHHckYnQWjPL98hgLAR2QLDD/go-ipfs-config"
@@ -23,6 +24,8 @@ type Context struct {
24
ConfigRoot string
25
ReqLog *ReqLog
26
27
+ Plugins *loader.PluginLoader
28
+
29
config *config.Config
30
LoadConfig func(path string) (*config.Config, error)
31
plugin/loader/initializer.go
deleted
-63
@@ -1,63 +0,0 @@
1
-package loader
2
-
3
-import (
4
- "github.com/ipfs/go-ipfs/core/coredag"
5
- "github.com/ipfs/go-ipfs/plugin"
6
- "github.com/ipfs/go-ipfs/repo/fsrepo"
7
-
8
- "gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go"
9
- ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
10
-)
11
-
12
-func initialize(plugins []plugin.Plugin) error {
13
- for _, p := range plugins {
14
- err := p.Init()
15
- if err != nil {
16
- return err
17
- }
18
- }
19
-
20
- return nil
21
-}
22
-
23
-func run(plugins []plugin.Plugin) error {
24
- for _, pl := range plugins {
25
- switch pl := pl.(type) {
26
- case plugin.PluginIPLD:
27
- err := runIPLDPlugin(pl)
28
- if err != nil {
29
- return err
30
- }
31
- case plugin.PluginTracer:
32
- err := runTracerPlugin(pl)
33
- if err != nil {
34
- return err
35
- }
36
- case plugin.PluginDatastore:
37
- err := fsrepo.AddDatastoreConfigHandler(pl.DatastoreTypeName(), pl.DatastoreConfigParser())
38
- if err != nil {
39
- return err
40
- }
41
- default:
42
- panic(pl)
43
- }
44
- }
45
- return nil
46
-}
47
-
48
-func runIPLDPlugin(pl plugin.PluginIPLD) error {
49
- err := pl.RegisterBlockDecoders(ipld.DefaultBlockDecoder)
50
- if err != nil {
51
- return err
52
- }
53
- return pl.RegisterInputEncParsers(coredag.DefaultInputEncParsers)
54
-}
55
-
56
-func runTracerPlugin(pl plugin.PluginTracer) error {
57
- tracer, err := pl.InitTracer()
58
- if err != nil {
59
- return err
60
- }
61
- opentracing.SetGlobalTracer(tracer)
62
- return nil
63
-}
plugin/loader/load.go
deleted
-67
@@ -1,67 +0,0 @@
1
-package loader
2
-
3
-import (
4
- "fmt"
5
- "os"
6
-
7
- "github.com/ipfs/go-ipfs/plugin"
8
-
9
- logging "gx/ipfs/QmcuXC5cxs79ro2cUuHs4HQ2bkDLJUYokwL8aivcX6HW3C/go-log"
10
-)
11
-
12
-var log = logging.Logger("plugin/loader")
13
-
14
-var loadPluginsFunc = func(string) ([]plugin.Plugin, error) {
15
- return nil, nil
16
-}
17
-
18
-// LoadPlugins loads and initializes plugins.
19
-func LoadPlugins(pluginDir string) ([]plugin.Plugin, error) {
20
- plMap := make(map[string]plugin.Plugin)
21
- for _, v := range preloadPlugins {
22
- plMap[v.Name()] = v
23
- }
24
-
25
- if pluginDir != "" {
26
- newPls, err := loadDynamicPlugins(pluginDir)
27
- if err != nil {
28
- return nil, err
29
- }
30
-
31
- for _, pl := range newPls {
32
- if ppl, ok := plMap[pl.Name()]; ok {
33
- // plugin is already preloaded
34
- return nil, fmt.Errorf(
35
- "plugin: %s, is duplicated in version: %s, "+
36
- "while trying to load dynamically: %s",
37
- ppl.Name(), ppl.Version(), pl.Version())
38
- }
39
- plMap[pl.Name()] = pl
40
- }
41
- }
42
-
43
- pls := make([]plugin.Plugin, 0, len(plMap))
44
- for _, v := range plMap {
45
- pls = append(pls, v)
46
- }
47
-
48
- err := initialize(pls)
49
- if err != nil {
50
- return nil, err
51
- }
52
-
53
- err = run(pls)
54
- return nil, err
55
-}
56
-
57
-func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) {
58
- _, err := os.Stat(pluginDir)
59
- if os.IsNotExist(err) {
60
- return nil, nil
61
- }
62
- if err != nil {
63
- return nil, err
64
- }
65
-
66
- return loadPluginsFunc(pluginDir)
67
-}
plugin/loader/loader.go
new
+125
@@ -0,0 +1,125 @@
1
+package loader
2
+
3
+import (
4
+ "fmt"
5
+ "github.com/ipfs/go-ipfs/core/coredag"
6
+ "github.com/ipfs/go-ipfs/plugin"
7
+ "github.com/ipfs/go-ipfs/repo/fsrepo"
8
+ "os"
9
+
10
+ opentracing "gx/ipfs/QmWLWmRVSiagqP15jczsGME1qpob6HDbtbHAY2he9W5iUo/opentracing-go"
11
+ ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
12
+ logging "gx/ipfs/QmcuXC5cxs79ro2cUuHs4HQ2bkDLJUYokwL8aivcX6HW3C/go-log"
13
+)
14
+
15
+var log = logging.Logger("plugin/loader")
16
+
17
+var loadPluginsFunc = func(string) ([]plugin.Plugin, error) {
18
+ return nil, nil
19
+}
20
+
21
+// PluginLoader keeps track of loaded plugins
22
+type PluginLoader struct {
23
+ plugins []plugin.Plugin
24
+}
25
+
26
+// NewPluginLoader creates new plugin loader
27
+func NewPluginLoader(pluginDir string) (*PluginLoader, error) {
28
+ plMap := make(map[string]plugin.Plugin)
29
+ for _, v := range preloadPlugins {
30
+ plMap[v.Name()] = v
31
+ }
32
+
33
+ if pluginDir != "" {
34
+ newPls, err := loadDynamicPlugins(pluginDir)
35
+ if err != nil {
36
+ return nil, err
37
+ }
38
+
39
+ for _, pl := range newPls {
40
+ if ppl, ok := plMap[pl.Name()]; ok {
41
+ // plugin is already preloaded
42
+ return nil, fmt.Errorf(
43
+ "plugin: %s, is duplicated in version: %s, "+
44
+ "while trying to load dynamically: %s",
45
+ ppl.Name(), ppl.Version(), pl.Version())
46
+ }
47
+ plMap[pl.Name()] = pl
48
+ }
49
+ }
50
+
51
+ loader := &PluginLoader{plugins: make([]plugin.Plugin, 0, len(plMap))}
52
+
53
+ for _, v := range plMap {
54
+ loader.plugins = append(loader.plugins, v)
55
+ }
56
+
57
+ return loader, nil
58
+}
59
+
60
+func loadDynamicPlugins(pluginDir string) ([]plugin.Plugin, error) {
61
+ _, err := os.Stat(pluginDir)
62
+ if os.IsNotExist(err) {
63
+ return nil, nil
64
+ }
65
+ if err != nil {
66
+ return nil, err
67
+ }
68
+
69
+ return loadPluginsFunc(pluginDir)
70
+}
71
+
72
+//Initialize all loaded plugins
73
+func (loader *PluginLoader) Initialize() error {
74
+ for _, p := range loader.plugins {
75
+ err := p.Init()
76
+ if err != nil {
77
+ return err
78
+ }
79
+ }
80
+
81
+ return nil
82
+}
83
+
84
+//Run the plugins
85
+func (loader *PluginLoader) Run() error {
86
+ for _, pl := range loader.plugins {
87
+ switch pl := pl.(type) {
88
+ case plugin.PluginIPLD:
89
+ err := runIPLDPlugin(pl)
90
+ if err != nil {
91
+ return err
92
+ }
93
+ case plugin.PluginTracer:
94
+ err := runTracerPlugin(pl)
95
+ if err != nil {
96
+ return err
97
+ }
98
+ case plugin.PluginDatastore:
99
+ err := fsrepo.AddDatastoreConfigHandler(pl.DatastoreTypeName(), pl.DatastoreConfigParser())
100
+ if err != nil {
101
+ return err
102
+ }
103
+ default:
104
+ panic(pl)
105
+ }
106
+ }
107
+ return nil
108
+}
109
+
110
+func runIPLDPlugin(pl plugin.PluginIPLD) error {
111
+ err := pl.RegisterBlockDecoders(ipld.DefaultBlockDecoder)
112
+ if err != nil {
113
+ return err
114
+ }
115
+ return pl.RegisterInputEncParsers(coredag.DefaultInputEncParsers)
116
+}
117
+
118
+func runTracerPlugin(pl plugin.PluginTracer) error {
119
+ tracer, err := pl.InitTracer()
120
+ if err != nil {
121
+ return err
122
+ }
123
+ opentracing.SetGlobalTracer(tracer)
124
+ return nil
125
+}
repo/fsrepo/config_test.go
+13
-1
@@ -75,7 +75,19 @@ var measureConfig = []byte(`{
75
}`)
76
77
func TestDefaultDatastoreConfig(t *testing.T) {
78
- loader.LoadPlugins("")
78
+ loader, err := loader.NewPluginLoader("")
79
+ if err != nil {
80
+ t.Fatal(err)
81
+ }
82
+ err = loader.Initialize()
83
+ if err != nil {
84
+ t.Fatal(err)
85
+ }
86
+
87
+ err = loader.Run()
88
+ if err != nil {
89
+ t.Fatal(err)
90
+ }
91
92
dir, err := ioutil.TempDir("", "ipfs-datastore-config-test")
93
if err != nil {