forked from cloudquery/cloudquery
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin.go
More file actions
124 lines (105 loc) · 2.83 KB
/
plugin.go
File metadata and controls
124 lines (105 loc) · 2.83 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package plugin
import (
"fmt"
"github.com/cloudquery/cloudquery/logging"
"github.com/hashicorp/go-plugin"
"github.com/rs/zerolog/log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
const defaultOrganization = "cloudquery"
type managedPlugin interface {
Name() string
Version() string
Provider() CQProvider
Close()
}
type remotePlugin struct {
name string
version string
client *plugin.Client
provider CQProvider
}
// NewRemotePlugin creates a new remoted plugin using go_plugin
func newRemotePlugin(providerName, version string) (*remotePlugin, error) {
pluginPath, _ := GetProviderPath(providerName, version)
client := plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: Handshake,
VersionedPlugins: map[int]plugin.PluginSet{
1: PluginMap,
},
Cmd: exec.Command(pluginPath),
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
SyncStderr: os.Stderr,
SyncStdout: os.Stdout,
Logger: logging.NewZHcLog(&log.Logger, ""),
})
rpcClient, err := client.Client()
if err != nil {
client.Kill()
return nil, err
}
raw, err := rpcClient.Dispense("provider")
if err != nil {
client.Kill()
return nil, err
}
provider, ok := raw.(CQProvider)
if !ok {
client.Kill()
return nil, fmt.Errorf("failed to cast plugin")
}
return &remotePlugin{
name: providerName,
version: version,
client: client,
provider: provider,
}, nil
}
func (r remotePlugin) Name() string { return r.name }
func (r remotePlugin) Version() string { return r.version }
func (r remotePlugin) Provider() CQProvider { return r.provider }
func (r remotePlugin) Close() {
if r.client == nil {
return
}
r.client.Kill()
}
type embeddedPlugin struct {
name string
version string
provider CQProvider
}
// NewEmbeddedPlugin is a managed plugin that is created in-process, usually used for debugging purposes
func newEmbeddedPlugin(providerName, version string, p CQProvider) *embeddedPlugin {
return &embeddedPlugin{
name: providerName,
version: version,
provider: p,
}
}
func (e embeddedPlugin) Name() string { return e.name }
func (e embeddedPlugin) Version() string { return e.version }
func (e embeddedPlugin) Provider() CQProvider { return e.provider }
func (e embeddedPlugin) Close() { return }
// GetProviderPath returns expected path of provider on file system from name and version of plugin
func GetProviderPath(name string, version string) (string, error) {
org := defaultOrganization
split := strings.Split(name, "/")
if len(split) == 2 {
org = split[0]
name = split[1]
}
workingDir, err := os.Getwd()
if err != nil {
return "", err
}
extension := ""
if runtime.GOOS == "windows" {
extension = ".exe"
}
return filepath.Join(workingDir, ".cq", "providers", org, name, fmt.Sprintf("%s-%s-%s%s", version, runtime.GOOS, runtime.GOARCH, extension)), nil
}