mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-09-19 20:26:26 +08:00

- Added driver initialization for gRPC plugins in internal/bootstrap/driver.go. - Introduced configuration structures and protobuf definitions for driver plugins in proto/driver/config.proto and proto/driver/driver.proto. - Implemented gRPC server and client interfaces for driver plugins in shared/driver/grpc.go. - Created common response handling utilities in server/common/common.go and server/common/resp.go. - Developed plugin registration endpoint in server/handles/plugin.go. - Added test cases for plugin functionality in shared/driver/plugin_test.go. - Defined plugin reattachment configuration model in shared/model/plugin.go.
132 lines
3.3 KiB
Go
132 lines
3.3 KiB
Go
package handles
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/OpenListTeam/OpenList/v5/internal/driver"
|
|
"github.com/OpenListTeam/OpenList/v5/server/common"
|
|
driverS "github.com/OpenListTeam/OpenList/v5/shared/driver"
|
|
"github.com/OpenListTeam/OpenList/v5/shared/model"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/hashicorp/go-plugin"
|
|
"github.com/hashicorp/go-plugin/runner"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func PluginRegister(c *gin.Context) {
|
|
var config model.PluginReattachConfig
|
|
err := c.ShouldBind(&config)
|
|
if err != nil {
|
|
common.ErrorStrResp(c, "Invalid request: "+err.Error(), 400, true)
|
|
return
|
|
}
|
|
|
|
protocol := plugin.Protocol(config.Protocol)
|
|
if protocol != plugin.ProtocolGRPC {
|
|
common.ErrorStrResp(c, "Unsupported protocol: "+config.Protocol, 400, true)
|
|
return
|
|
}
|
|
|
|
var addr net.Addr
|
|
switch config.Network {
|
|
case "tcp":
|
|
addr, err = net.ResolveTCPAddr("tcp", config.Address)
|
|
case "unix":
|
|
addr, err = net.ResolveUnixAddr("unix", config.Address)
|
|
default:
|
|
common.ErrorStrResp(c, "Unknown network type: "+config.Network, 400, true)
|
|
return
|
|
}
|
|
if err != nil {
|
|
common.ErrorStrResp(c, "Failed to resolve address: "+err.Error(), 400, true)
|
|
return
|
|
}
|
|
reattach := &plugin.ReattachConfig{
|
|
Protocol: protocol,
|
|
ProtocolVersion: config.Version,
|
|
Addr: addr,
|
|
Test: true,
|
|
ReattachFunc: func() (runner.AttachedRunner, error) {
|
|
conn, err := net.Dial(addr.Network(), addr.String())
|
|
if err != nil {
|
|
return nil, plugin.ErrProcessNotFound
|
|
}
|
|
_ = conn.Close()
|
|
|
|
return &attachedRunner{
|
|
id: addr.String(),
|
|
ctx: c.Request.Context(),
|
|
}, nil
|
|
|
|
},
|
|
}
|
|
storage, err := client(reattach)
|
|
if err != nil {
|
|
common.ErrorStrResp(c, "Failed to connect to plugin: "+err.Error(), 500, true)
|
|
return
|
|
}
|
|
|
|
driverConf, err := storage.Config(c.Request.Context())
|
|
if err != nil {
|
|
common.ErrorStrResp(c, "Failed to get plugin config: "+err.Error(), 500, true)
|
|
return
|
|
}
|
|
logrus.Infof("Plugin config: %+v", driverConf)
|
|
<-c.Request.Context().Done()
|
|
}
|
|
|
|
func client(reattach *plugin.ReattachConfig) (driverS.PluginIF, error) {
|
|
client := plugin.NewClient(&plugin.ClientConfig{
|
|
HandshakeConfig: driverS.GetHandshakeConfig(),
|
|
Plugins: driver.PluginMap,
|
|
Reattach: reattach,
|
|
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
|
|
SyncStdout: logrus.StandardLogger().Out,
|
|
SyncStderr: logrus.StandardLogger().Out,
|
|
})
|
|
clientProtocol, err := client.Client()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create plugin client: %w", err)
|
|
}
|
|
rawIF, err := clientProtocol.Dispense("grpc")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("dispense plugin interface: %w", err)
|
|
}
|
|
driverIF, ok := rawIF.(driverS.PluginIF)
|
|
if !ok {
|
|
return nil, fmt.Errorf("invalid plugin interface type: %T", rawIF)
|
|
}
|
|
return driverIF, nil
|
|
}
|
|
|
|
type attachedRunner struct {
|
|
id string
|
|
ctx context.Context
|
|
addrTranslator
|
|
}
|
|
|
|
func (c *attachedRunner) Wait(_ context.Context) error {
|
|
<-c.ctx.Done()
|
|
return nil
|
|
}
|
|
|
|
func (c *attachedRunner) Kill(_ context.Context) error {
|
|
return nil
|
|
}
|
|
|
|
func (c *attachedRunner) ID() string {
|
|
return c.id
|
|
}
|
|
|
|
type addrTranslator struct{}
|
|
|
|
func (*addrTranslator) PluginToHost(pluginNet, pluginAddr string) (string, string, error) {
|
|
return pluginNet, pluginAddr, nil
|
|
}
|
|
|
|
func (*addrTranslator) HostToPlugin(hostNet, hostAddr string) (string, string, error) {
|
|
return hostNet, hostAddr, nil
|
|
}
|