/
loader.go
87 lines (68 loc) · 2.12 KB
/
loader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package plugin
import (
"errors"
"fmt"
"io/ioutil"
"path/filepath"
sys_plugin "plugin"
"github.com/steven-zou/go-plugin/pkg"
"github.com/steven-zou/go-plugin/pkg/context"
"github.com/steven-zou/go-plugin/pkg/spec"
)
//Loader defines the plugin load flow
type Loader interface {
//Scan the plugin base dir and get the plugin candidates
Scan(pluginBaseDir string) ([]string, error)
//Parse the plugin metadata
Parse(pluginPath string) (*spec.Plugin, error)
//Load the plugin executor
Load(plugin *spec.Plugin) (spec.PluginExecutor, error)
}
//BaseLoader is an default implementation of Loader interface
type BaseLoader struct{}
//Scan implements same method of Loader interface
func (bl *BaseLoader) Scan(pluginBaseDir string) ([]string, error) {
if len(pluginBaseDir) == 0 {
return nil, errors.New("plugin base dir path is empty")
}
if !pkg.FileExists(pluginBaseDir) {
return nil, fmt.Errorf("plugin base dir '%s' is not existing", pluginBaseDir)
}
files, err := ioutil.ReadDir(pluginBaseDir)
if err != nil {
return nil, err
}
candidates := make([]string, 0)
for _, f := range files {
if f.IsDir() {
candidates = append(candidates, filepath.Join(pluginBaseDir, f.Name()))
}
}
return candidates, nil
}
//Parse implements same method of Loader interface
func (bl *BaseLoader) Parse(pluginPath string) (*spec.Plugin, error) {
return nil, errors.New("not implemented in BaseLoader, leverage the validator to get the plugin spec")
}
//Load implements same method of Loader interface
func (bl *BaseLoader) Load(plugin *spec.Plugin) (spec.PluginExecutor, error) {
if plugin == nil {
return nil, errors.New("nil plugin spec")
}
if !pkg.FileExists(plugin.Source.Path) {
return nil, fmt.Errorf("plugin so file '%s' is not existsing", plugin.Source.Path)
}
p, err := sys_plugin.Open(plugin.Source.Path)
if err != nil {
return nil, err
}
exec, err := p.Lookup("Execute")
if err != nil {
return nil, err
}
pExec, ok := exec.(func(ctx context.PluginContext) error)
if !ok {
return nil, fmt.Errorf("failed to lookup entry function 'Execute' in plugin so file '%s'", plugin.Source.Path)
}
return pExec, nil
}