feat: support switch hashicorp plugin with environment HRP_PLUGIN_TYPE

This commit is contained in:
debugtalk
2022-03-04 20:34:24 +08:00
parent 1ca1ef446c
commit 0f9628e373
8 changed files with 73 additions and 21 deletions

View File

@@ -1,6 +1,11 @@
package pluginInternal
import "github.com/hashicorp/go-plugin"
import (
"os"
"strings"
"github.com/hashicorp/go-plugin"
)
const PluginName = "debugtalk"
const RPCPluginName = PluginName + "_rpc"
@@ -15,3 +20,18 @@ var HandshakeConfig = plugin.HandshakeConfig{
MagicCookieKey: "HttpRunnerPlus",
MagicCookieValue: PluginName,
}
const hrpPluginTypeEnvName = "HRP_PLUGIN_TYPE"
var hrpPluginType string
func init() {
hrpPluginType = strings.ToLower(os.Getenv(hrpPluginTypeEnvName))
if hrpPluginType == "" {
hrpPluginType = "grpc" // default
}
}
func IsRPCPluginType() bool {
return hrpPluginType == "rpc"
}

View File

@@ -30,14 +30,14 @@ func (m *functionGRPCClient) GetNames() ([]string, error) {
func (m *functionGRPCClient) Call(funcName string, funcArgs ...interface{}) (interface{}, error) {
log.Info().Str("funcName", funcName).Interface("funcArgs", funcArgs).Msg("call function via gRPC")
req := &proto.CallRequest{
Name: funcName,
}
funcArgBytes, err := json.Marshal(funcArgs)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal Call() funcArgs")
}
req.Args = funcArgBytes
req := &proto.CallRequest{
Name: funcName,
Args: funcArgBytes,
}
response, err := m.client.Call(context.Background(), req)
if err != nil {
@@ -65,7 +65,7 @@ func (m *functionGRPCServer) GetNames(ctx context.Context, req *proto.Empty) (*p
log.Info().Interface("req", req).Msg("gRPC GetNames() called on plugin side")
v, err := m.Impl.GetNames()
if err != nil {
log.Error().Err(err).Msg("gRPC GetNames execution failed")
log.Error().Err(err).Msg("gRPC GetNames() execution failed")
return nil, err
}
return &proto.GetNamesResponse{Names: v}, err

View File

@@ -1,11 +1,13 @@
package pluginInternal
import (
"fmt"
"os"
"os/exec"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
@@ -19,7 +21,14 @@ type HashicorpPlugin struct {
}
func (p *HashicorpPlugin) Init(path string) error {
pluginName := GRPCPluginName
var pluginName string
if IsRPCPluginType() {
pluginName = RPCPluginName
} else {
pluginName = GRPCPluginName
}
// logger
loggerOptions := &hclog.LoggerOptions{
Name: pluginName,
Output: os.Stdout,
@@ -29,6 +38,11 @@ func (p *HashicorpPlugin) Init(path string) error {
} else {
loggerOptions.Level = hclog.Info
}
// cmd
cmd := exec.Command(path)
cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", hrpPluginTypeEnvName, hrpPluginType))
// launch the plugin process
client = plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: HandshakeConfig,
@@ -36,7 +50,7 @@ func (p *HashicorpPlugin) Init(path string) error {
RPCPluginName: &RPCPlugin{},
GRPCPluginName: &GRPCPlugin{},
},
Cmd: exec.Command(path),
Cmd: cmd,
Logger: hclog.New(loggerOptions),
AllowedProtocols: []plugin.Protocol{
plugin.ProtocolNetRPC,
@@ -44,18 +58,16 @@ func (p *HashicorpPlugin) Init(path string) error {
},
})
// Connect via RPC
// Connect via RPC/gRPC
rpcClient, err := client.Client()
if err != nil {
log.Error().Err(err).Msg("connect plugin via RPC failed")
return err
return errors.Wrap(err, fmt.Sprintf("connect %s plugin failed", hrpPluginType))
}
// Request the plugin
raw, err := rpcClient.Dispense(pluginName)
if err != nil {
log.Error().Err(err).Msg("request plugin failed")
return err
return errors.Wrap(err, fmt.Sprintf("request %s plugin failed", hrpPluginType))
}
// We should have a Function now! This feels like a normal interface