Files
httprunner/plugin/inner/hashicorp_plugin.go
2022-02-25 23:04:34 +08:00

96 lines
2.1 KiB
Go

package pluginInternal
import (
"os"
"os/exec"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin"
"github.com/rs/zerolog/log"
)
var client *plugin.Client
// HashicorpPlugin implements hashicorp/go-plugin
type HashicorpPlugin struct {
logOn bool // turn on plugin log
FuncCaller
cachedFunctions map[string]bool // cache loaded functions to improve performance
}
func (p *HashicorpPlugin) Init(path string) error {
loggerOptions := &hclog.LoggerOptions{
Name: PluginName,
Output: os.Stdout,
}
if p.logOn {
loggerOptions.Level = hclog.Debug
} else {
loggerOptions.Level = hclog.Info
}
// launch the plugin process
client = plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: HandshakeConfig,
Plugins: map[string]plugin.Plugin{
PluginName: &HRPPlugin{},
},
Cmd: exec.Command(path),
Logger: hclog.New(loggerOptions),
})
// Connect via RPC
rpcClient, err := client.Client()
if err != nil {
log.Error().Err(err).Msg("connect plugin via RPC failed")
return err
}
// Request the plugin
raw, err := rpcClient.Dispense(PluginName)
if err != nil {
log.Error().Err(err).Msg("request plugin failed")
return err
}
// We should have a Function now! This feels like a normal interface
// implementation but is in fact over an RPC connection.
p.FuncCaller = raw.(FuncCaller)
p.cachedFunctions = make(map[string]bool)
log.Info().Str("path", path).Msg("load hashicorp go plugin success")
return nil
}
func (p *HashicorpPlugin) Has(funcName string) bool {
flag, ok := p.cachedFunctions[funcName]
if ok {
return flag
}
funcNames, err := p.GetNames()
if err != nil {
return false
}
for _, name := range funcNames {
if name == funcName {
p.cachedFunctions[funcName] = true // cache as exists
return true
}
}
p.cachedFunctions[funcName] = false // cache as not exists
return false
}
func (p *HashicorpPlugin) Call(funcName string, args ...interface{}) (interface{}, error) {
return p.FuncCaller.Call(funcName, args...)
}
func (p *HashicorpPlugin) Quit() error {
// kill hashicorp plugin process
log.Info().Msg("quit hashicorp plugin process")
client.Kill()
return nil
}