mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-09-19 20:26:26 +08:00
feat: Implement plugin architecture with gRPC support
- 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.
This commit is contained in:
11
buf.gen.yaml
Normal file
11
buf.gen.yaml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
version: v1
|
||||||
|
plugins:
|
||||||
|
- plugin: buf.build/protocolbuffers/go:v1.36.7
|
||||||
|
out: .
|
||||||
|
opt:
|
||||||
|
- paths=source_relative
|
||||||
|
- plugin: buf.build/grpc/go:v1.5.1
|
||||||
|
out: .
|
||||||
|
opt:
|
||||||
|
- paths=source_relative
|
||||||
|
- require_unimplemented_servers=false
|
@ -14,6 +14,7 @@ func Init(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
initLogrus()
|
initLogrus()
|
||||||
bootstrap.InitConfig()
|
bootstrap.InitConfig()
|
||||||
|
bootstrap.InitDriverPlugins()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Release() {
|
func Release() {
|
||||||
|
13
go.mod
13
go.mod
@ -1,33 +1,42 @@
|
|||||||
module github.com/OpenListTeam/OpenList/v5
|
module github.com/OpenListTeam/OpenList/v5
|
||||||
|
|
||||||
go 1.23.4
|
go 1.24
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-contrib/cors v1.7.6
|
github.com/gin-contrib/cors v1.7.6
|
||||||
github.com/gin-gonic/gin v1.10.1
|
github.com/gin-gonic/gin v1.10.1
|
||||||
|
github.com/hashicorp/go-plugin v1.7.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
golang.org/x/net v0.43.0
|
golang.org/x/net v0.43.0
|
||||||
|
google.golang.org/grpc v1.74.2
|
||||||
|
google.golang.org/protobuf v1.36.7
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bytedance/sonic v1.14.0 // indirect
|
github.com/bytedance/sonic v1.14.0 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
|
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||||
|
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/oklog/run v1.2.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/spf13/pflag v1.0.7 // indirect
|
github.com/spf13/pflag v1.0.7 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
@ -36,6 +45,6 @@ require (
|
|||||||
golang.org/x/crypto v0.41.0 // indirect
|
golang.org/x/crypto v0.41.0 // indirect
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/sys v0.35.0 // indirect
|
||||||
golang.org/x/text v0.28.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.7 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
51
go.sum
51
go.sum
@ -1,3 +1,5 @@
|
|||||||
|
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
|
||||||
|
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
|
||||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||||
@ -9,6 +11,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||||
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
|
github.com/gin-contrib/cors v1.7.6 h1:3gQ8GMzs1Ylpf70y8bMw4fVpycXIeX1ZemuSQIsnQQY=
|
||||||
@ -17,6 +22,10 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w
|
|||||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||||
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
||||||
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
@ -27,11 +36,23 @@ github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHO
|
|||||||
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||||
|
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||||
|
github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA=
|
||||||
|
github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8=
|
||||||
|
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||||
|
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
|
||||||
|
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
@ -42,6 +63,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@ -49,6 +76,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E=
|
||||||
|
github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
@ -69,6 +98,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
@ -77,18 +107,39 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a h1:tPE/Kp+x9dMSwUm/uM0JKK0IfdiJkwAbSMSeZBXXJXc=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
|
||||||
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
13
internal/bootstrap/driver.go
Normal file
13
internal/bootstrap/driver.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package bootstrap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/internal/driver"
|
||||||
|
driverS "github.com/OpenListTeam/OpenList/v5/shared/driver"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitDriverPlugins() {
|
||||||
|
driver.PluginMap = map[string]plugin.Plugin{
|
||||||
|
"grpc": &driverS.Plugin{},
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package conf
|
package conf
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Conf *Config
|
Conf *Config
|
||||||
SitePath string
|
SitePath string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var PrivacyReg []*regexp.Regexp
|
||||||
|
9
internal/driver/var.go
Normal file
9
internal/driver/var.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
PluginMap map[string]plugin.Plugin
|
||||||
|
)
|
141
proto/driver/config.pb.go
Normal file
141
proto/driver/config.pb.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.7
|
||||||
|
// protoc (unknown)
|
||||||
|
// source: proto/driver/config.proto
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
|
DefaultRoot string `protobuf:"bytes,3,opt,name=default_root,json=defaultRoot,proto3" json:"default_root,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
mi := &file_proto_driver_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_driver_config_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_driver_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetVersion() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Version
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetDefaultRoot() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DefaultRoot
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_proto_driver_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_proto_driver_config_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"\x19proto/driver/config.proto\x12\x06driver\"Y\n" +
|
||||||
|
"\x06Config\x12\x12\n" +
|
||||||
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x18\n" +
|
||||||
|
"\aversion\x18\x02 \x01(\tR\aversion\x12!\n" +
|
||||||
|
"\fdefault_root\x18\x03 \x01(\tR\vdefaultRootB\n" +
|
||||||
|
"Z\b./driverb\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_proto_driver_config_proto_rawDescOnce sync.Once
|
||||||
|
file_proto_driver_config_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_proto_driver_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_proto_driver_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_proto_driver_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_driver_config_proto_rawDesc), len(file_proto_driver_config_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_proto_driver_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_proto_driver_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
|
var file_proto_driver_config_proto_goTypes = []any{
|
||||||
|
(*Config)(nil), // 0: driver.Config
|
||||||
|
}
|
||||||
|
var file_proto_driver_config_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_proto_driver_config_proto_init() }
|
||||||
|
func file_proto_driver_config_proto_init() {
|
||||||
|
if File_proto_driver_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_driver_config_proto_rawDesc), len(file_proto_driver_config_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 1,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_proto_driver_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_proto_driver_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_proto_driver_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_proto_driver_config_proto = out.File
|
||||||
|
file_proto_driver_config_proto_goTypes = nil
|
||||||
|
file_proto_driver_config_proto_depIdxs = nil
|
||||||
|
}
|
10
proto/driver/config.proto
Normal file
10
proto/driver/config.proto
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package driver;
|
||||||
|
option go_package = "./driver";
|
||||||
|
|
||||||
|
message Config {
|
||||||
|
string name = 1;
|
||||||
|
string version = 2;
|
||||||
|
string default_root = 3;
|
||||||
|
}
|
69
proto/driver/driver.pb.go
Normal file
69
proto/driver/driver.pb.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.7
|
||||||
|
// protoc (unknown)
|
||||||
|
// source: proto/driver/driver.proto
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||||
|
reflect "reflect"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
var File_proto_driver_driver_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_proto_driver_driver_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"\x19proto/driver/driver.proto\x12\x06driver\x1a\x1bgoogle/protobuf/empty.proto\x1a\x19proto/driver/config.proto2:\n" +
|
||||||
|
"\x06Driver\x120\n" +
|
||||||
|
"\x06Config\x12\x16.google.protobuf.Empty\x1a\x0e.driver.ConfigB\n" +
|
||||||
|
"Z\b./driverb\x06proto3"
|
||||||
|
|
||||||
|
var file_proto_driver_driver_proto_goTypes = []any{
|
||||||
|
(*emptypb.Empty)(nil), // 0: google.protobuf.Empty
|
||||||
|
(*Config)(nil), // 1: driver.Config
|
||||||
|
}
|
||||||
|
var file_proto_driver_driver_proto_depIdxs = []int32{
|
||||||
|
0, // 0: driver.Driver.Config:input_type -> google.protobuf.Empty
|
||||||
|
1, // 1: driver.Driver.Config:output_type -> driver.Config
|
||||||
|
1, // [1:2] is the sub-list for method output_type
|
||||||
|
0, // [0:1] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_proto_driver_driver_proto_init() }
|
||||||
|
func file_proto_driver_driver_proto_init() {
|
||||||
|
if File_proto_driver_driver_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file_proto_driver_config_proto_init()
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_driver_driver_proto_rawDesc), len(file_proto_driver_driver_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 0,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_proto_driver_driver_proto_goTypes,
|
||||||
|
DependencyIndexes: file_proto_driver_driver_proto_depIdxs,
|
||||||
|
}.Build()
|
||||||
|
File_proto_driver_driver_proto = out.File
|
||||||
|
file_proto_driver_driver_proto_goTypes = nil
|
||||||
|
file_proto_driver_driver_proto_depIdxs = nil
|
||||||
|
}
|
11
proto/driver/driver.proto
Normal file
11
proto/driver/driver.proto
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package driver;
|
||||||
|
option go_package = "./driver";
|
||||||
|
|
||||||
|
import "google/protobuf/empty.proto";
|
||||||
|
import "proto/driver/config.proto";
|
||||||
|
|
||||||
|
service Driver {
|
||||||
|
rpc Config(google.protobuf.Empty) returns (driver.Config);
|
||||||
|
}
|
120
proto/driver/driver_grpc.pb.go
Normal file
120
proto/driver/driver_grpc.pb.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
|
// - protoc (unknown)
|
||||||
|
// source: proto/driver/driver.proto
|
||||||
|
|
||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.64.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
|
const (
|
||||||
|
Driver_Config_FullMethodName = "/driver.Driver/Config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DriverClient is the client API for Driver service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type DriverClient interface {
|
||||||
|
Config(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Config, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type driverClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDriverClient(cc grpc.ClientConnInterface) DriverClient {
|
||||||
|
return &driverClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *driverClient) Config(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Config, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(Config)
|
||||||
|
err := c.cc.Invoke(ctx, Driver_Config_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DriverServer is the server API for Driver service.
|
||||||
|
// All implementations should embed UnimplementedDriverServer
|
||||||
|
// for forward compatibility.
|
||||||
|
type DriverServer interface {
|
||||||
|
Config(context.Context, *emptypb.Empty) (*Config, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedDriverServer should be embedded to have
|
||||||
|
// forward compatible implementations.
|
||||||
|
//
|
||||||
|
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||||
|
// pointer dereference when methods are called.
|
||||||
|
type UnimplementedDriverServer struct{}
|
||||||
|
|
||||||
|
func (UnimplementedDriverServer) Config(context.Context, *emptypb.Empty) (*Config, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Config not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDriverServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
|
// UnsafeDriverServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to DriverServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeDriverServer interface {
|
||||||
|
mustEmbedUnimplementedDriverServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterDriverServer(s grpc.ServiceRegistrar, srv DriverServer) {
|
||||||
|
// If the following call pancis, it indicates UnimplementedDriverServer was
|
||||||
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||||
|
t.testEmbeddedByValue()
|
||||||
|
}
|
||||||
|
s.RegisterService(&Driver_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Driver_Config_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(emptypb.Empty)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DriverServer).Config(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Driver_Config_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DriverServer).Config(ctx, req.(*emptypb.Empty))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver_ServiceDesc is the grpc.ServiceDesc for Driver service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var Driver_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "driver.Driver",
|
||||||
|
HandlerType: (*DriverServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "Config",
|
||||||
|
Handler: _Driver_Config_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "proto/driver/driver.proto",
|
||||||
|
}
|
53
server/common/common.go
Normal file
53
server/common/common.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/cmd/flags"
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/internal/conf"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrorResp is used to return error response
|
||||||
|
// @param l: if true, log error
|
||||||
|
func ErrorResp(c *gin.Context, err error, code int, l ...bool) {
|
||||||
|
ErrorWithDataResp(c, err, code, nil, l...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrorWithDataResp(c *gin.Context, err error, code int, data any, l ...bool) {
|
||||||
|
if len(l) > 0 && l[0] {
|
||||||
|
if flags.Debug {
|
||||||
|
log.Errorf("%+v", err)
|
||||||
|
} else {
|
||||||
|
log.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(200, Resp[any]{
|
||||||
|
Code: code,
|
||||||
|
Message: hidePrivacy(err.Error()),
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrorStrResp(c *gin.Context, str string, code int, l ...bool) {
|
||||||
|
if len(l) != 0 && l[0] {
|
||||||
|
log.Error(str)
|
||||||
|
}
|
||||||
|
c.JSON(200, Resp[any]{
|
||||||
|
Code: code,
|
||||||
|
Message: hidePrivacy(str),
|
||||||
|
Data: nil,
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
func hidePrivacy(msg string) string {
|
||||||
|
for _, r := range conf.PrivacyReg {
|
||||||
|
msg = r.ReplaceAllStringFunc(msg, func(s string) string {
|
||||||
|
return strings.Repeat("*", len(s))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
12
server/common/resp.go
Normal file
12
server/common/resp.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
type Resp[T any] struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Data T `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PageResp struct {
|
||||||
|
Content interface{} `json:"content"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
}
|
131
server/handles/plugin.go
Normal file
131
server/handles/plugin.go
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
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
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/cmd/flags"
|
||||||
"github.com/OpenListTeam/OpenList/v5/internal/conf"
|
"github.com/OpenListTeam/OpenList/v5/internal/conf"
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/server/handles"
|
||||||
"github.com/gin-contrib/cors"
|
"github.com/gin-contrib/cors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@ -19,6 +21,9 @@ func Init(e *gin.Engine) {
|
|||||||
g.Any("/ping", func(c *gin.Context) {
|
g.Any("/ping", func(c *gin.Context) {
|
||||||
c.String(200, "pong")
|
c.String(200, "pong")
|
||||||
})
|
})
|
||||||
|
if flags.Dev {
|
||||||
|
g.POST("/plugin/register", handles.PluginRegister)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Cors(r *gin.Engine) {
|
func Cors(r *gin.Engine) {
|
||||||
|
7
shared/driver/config.go
Normal file
7
shared/driver/config.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package driver
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Name string
|
||||||
|
Version string
|
||||||
|
DefaultRoot string
|
||||||
|
}
|
41
shared/driver/grpc.go
Normal file
41
shared/driver/grpc.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/proto/driver"
|
||||||
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GRPCServer struct {
|
||||||
|
Impl PluginIF
|
||||||
|
}
|
||||||
|
type GRPCClient struct {
|
||||||
|
client driver.DriverClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *GRPCServer) Config(ctx context.Context, in *emptypb.Empty) (*driver.Config, error) {
|
||||||
|
config, err := s.Impl.Config(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &driver.Config{
|
||||||
|
Name: config.Name,
|
||||||
|
Version: config.Version,
|
||||||
|
DefaultRoot: config.DefaultRoot,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
func (p *GRPCClient) Config(ctx context.Context) (Config, error) {
|
||||||
|
resp, err := p.client.Config(ctx, &emptypb.Empty{})
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
return Config{
|
||||||
|
Name: resp.Name,
|
||||||
|
Version: resp.Version,
|
||||||
|
DefaultRoot: resp.DefaultRoot,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.DriverServer = (*GRPCServer)(nil)
|
||||||
|
var _ PluginIF = (*GRPCClient)(nil)
|
37
shared/driver/interface.go
Normal file
37
shared/driver/interface.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/OpenListTeam/OpenList/v5/proto/driver"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetHandshakeConfig() plugin.HandshakeConfig {
|
||||||
|
return plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 2,
|
||||||
|
MagicCookieKey: "OpenListTeam",
|
||||||
|
MagicCookieValue: "openlist",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginIF interface {
|
||||||
|
Config(ctx context.Context) (Config, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin struct {
|
||||||
|
plugin.Plugin
|
||||||
|
Impl PluginIF
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
driver.RegisterDriverServer(s, &GRPCServer{Impl: p.Impl})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (any, error) {
|
||||||
|
return &GRPCClient{client: driver.NewDriverClient(c)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ plugin.GRPCPlugin = (*Plugin)(nil)
|
129
shared/driver/plugin_test.go
Normal file
129
shared/driver/plugin_test.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package driver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGrpcPlugin(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
c := plugin.NewClient(&plugin.ClientConfig{
|
||||||
|
Cmd: helperProcess("grpc"),
|
||||||
|
HandshakeConfig: GetHandshakeConfig(),
|
||||||
|
Plugins: plugin.PluginSet{
|
||||||
|
"grpc": &Plugin{},
|
||||||
|
},
|
||||||
|
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
|
||||||
|
SyncStdout: os.Stdout,
|
||||||
|
SyncStderr: os.Stderr,
|
||||||
|
})
|
||||||
|
client, err := c.Client()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pinging should work
|
||||||
|
if err := client.Ping(); err != nil {
|
||||||
|
t.Fatalf("should not err: %s", err)
|
||||||
|
}
|
||||||
|
// Grab the impl
|
||||||
|
raw, err := client.Dispense("grpc")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err should be nil, got %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
storage, ok := raw.(PluginIF)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad: %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
conf, err := storage.Config(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should not err: %s", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("config: %+v\n", conf)
|
||||||
|
|
||||||
|
<-time.After(100 * time.Millisecond)
|
||||||
|
c.Kill()
|
||||||
|
cancel()
|
||||||
|
if err := client.Ping(); err == nil {
|
||||||
|
t.Fatal("should error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try logging, this should show out in tests. We have to manually verify.
|
||||||
|
t.Logf("HELLO")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not a real test. This is just a helper process kicked off by
|
||||||
|
// tests.
|
||||||
|
func TestHelperProcess(*testing.T) {
|
||||||
|
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer os.Exit(0)
|
||||||
|
|
||||||
|
args := os.Args
|
||||||
|
for len(args) > 0 {
|
||||||
|
if args[0] == "--" {
|
||||||
|
args = args[1:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args = args[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) == 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "No command\n")
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
cmd := args[0]
|
||||||
|
// args = args[1:]
|
||||||
|
switch cmd {
|
||||||
|
case "grpc":
|
||||||
|
plugin.Serve(&plugin.ServeConfig{
|
||||||
|
HandshakeConfig: GetHandshakeConfig(),
|
||||||
|
Plugins: plugin.PluginSet{
|
||||||
|
"grpc": &Plugin{
|
||||||
|
Impl: &TestServer{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
GRPCServer: plugin.DefaultGRPCServer,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func helperProcess(s ...string) *exec.Cmd {
|
||||||
|
cs := []string{"-test.run=TestHelperProcess", "--"}
|
||||||
|
cs = append(cs, s...)
|
||||||
|
env := []string{
|
||||||
|
"GO_WANT_HELPER_PROCESS=1",
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(os.Args[0], cs...)
|
||||||
|
cmd.Env = append(env, os.Environ()...)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestServer struct{}
|
||||||
|
|
||||||
|
func (s *TestServer) Config(ctx context.Context) (Config, error) {
|
||||||
|
fmt.Println("TestServer Config called")
|
||||||
|
return Config{
|
||||||
|
Name: "TestPlugin",
|
||||||
|
Version: "v0.0.1",
|
||||||
|
DefaultRoot: "/",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ PluginIF = (*TestServer)(nil)
|
8
shared/model/plugin.go
Normal file
8
shared/model/plugin.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type PluginReattachConfig struct {
|
||||||
|
Protocol string `json:"protocol,omitempty"` // Protocol type (e.g., "grpc", "netrpc")
|
||||||
|
Version int `json:"version,omitempty"` // Protocol version
|
||||||
|
Network string `json:"network,omitempty"` // Network type (e.g., "tcp", "unix")
|
||||||
|
Address string `json:"address,omitempty"` // Address
|
||||||
|
}
|
Reference in New Issue
Block a user