#1 #5
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,3 +25,4 @@ config.yaml
|
||||
servicechecker
|
||||
*.protoset
|
||||
authn.yaml
|
||||
.idea
|
@ -29,11 +29,8 @@ import (
|
||||
"go.unistack.org/servicechecker/pkg/config"
|
||||
"go.unistack.org/servicechecker/pkg/grpcconn"
|
||||
"go.unistack.org/servicechecker/pkg/httpconn"
|
||||
"go.unistack.org/servicechecker/pkg/protoset"
|
||||
"go.unistack.org/servicechecker/pkg/scheduler"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/dynamicpb"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -307,51 +304,28 @@ func newGRPCTask(ctx context.Context, l logger.Logger, m meter.Meter, check stri
|
||||
var rsp interface{}
|
||||
var treq client.Request
|
||||
var labels []string
|
||||
p := protoset.NewProtoSet()
|
||||
|
||||
if task.GRPC.Protoset != "" {
|
||||
pkg, svc, mth := grpcconn.ServiceMethod(task.GRPC.Endpoint)
|
||||
|
||||
protosetBuf, err := os.ReadFile(task.GRPC.Protoset)
|
||||
if err != nil {
|
||||
l.Error(ctx, "failed to unmarshal protoset file", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
fdset := &descriptorpb.FileDescriptorSet{}
|
||||
if err = protocodec.NewCodec().Unmarshal(protosetBuf, fdset); err != nil {
|
||||
l.Error(ctx, "failed to unmarshal protoset file", err)
|
||||
if err = p.AddProtoset(task.GRPC.Addr, svc, protosetBuf); err != nil {
|
||||
l.Error(ctx, "failed add protoset", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pfileoptions := protodesc.FileOptions{AllowUnresolvable: true}
|
||||
pfiles, err := pfileoptions.NewFiles(fdset)
|
||||
req, rsp, err = p.GetMessage(task.GRPC.Addr, pkg, svc, mth)
|
||||
if err != nil {
|
||||
l.Error(ctx, "failed to use protoset file", err)
|
||||
l.Error(ctx, "failed get req, rsp from protoset", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pkg, svc, mth := grpcconn.ServiceMethod(task.GRPC.Endpoint)
|
||||
pdesc, err := pfiles.FindDescriptorByName(protoreflect.FullName(pkg + "." + svc))
|
||||
if err != nil {
|
||||
l.Error(ctx, "failed to find service "+pkg+"."+svc)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sdesc, ok := pdesc.(protoreflect.ServiceDescriptor)
|
||||
if !ok {
|
||||
err = fmt.Errorf("failed to find service " + pkg + "." + svc)
|
||||
l.Error(ctx, "unable to find service in protoset", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
mdesc := sdesc.Methods().ByName(protoreflect.Name(mth))
|
||||
if mdesc == nil {
|
||||
err = fmt.Errorf("unknown method " + mth)
|
||||
l.Error(ctx, "failed to find method", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
req = dynamicpb.NewMessageType(mdesc.Input()).New()
|
||||
rsp = dynamicpb.NewMessageType(mdesc.Output()).New()
|
||||
|
||||
if err = jsonpbcodec.NewCodec().Unmarshal([]byte(task.GRPC.Data), req); err != nil {
|
||||
l.Error(ctx, "failed to unmarshal", err)
|
||||
return nil, nil, err
|
||||
|
5
go.mod
5
go.mod
@ -6,13 +6,13 @@ require (
|
||||
github.com/go-co-op/gocron/v2 v2.12.3
|
||||
github.com/google/gnostic v0.7.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.unistack.org/micro-client-grpc/v3 v3.11.10
|
||||
go.unistack.org/micro-client-http/v3 v3.9.14
|
||||
go.unistack.org/micro-codec-json/v3 v3.10.1
|
||||
go.unistack.org/micro-codec-jsonpb/v3 v3.10.3
|
||||
go.unistack.org/micro-codec-proto/v3 v3.10.2
|
||||
go.unistack.org/micro-codec-yaml/v3 v3.10.2
|
||||
go.unistack.org/micro-config-file/v3 v3.8.10
|
||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9
|
||||
go.unistack.org/micro-proto/v3 v3.4.1
|
||||
go.unistack.org/micro-server-http/v3 v3.11.34
|
||||
@ -21,9 +21,10 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/valyala/fastrand v1.1.0 // indirect
|
||||
github.com/valyala/histogram v1.2.0 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -593,8 +593,6 @@ cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vf
|
||||
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
|
||||
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
|
||||
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
|
||||
@ -910,8 +908,6 @@ go.unistack.org/micro-codec-proto/v3 v3.10.2 h1:9iUQjBjTsd/RgIqB5rAQMZE0CYWngoW9
|
||||
go.unistack.org/micro-codec-proto/v3 v3.10.2/go.mod h1:54e1jb6aLL9obJUwJjtVupE5zY4PugTcMSqWDhz9aC4=
|
||||
go.unistack.org/micro-codec-yaml/v3 v3.10.2 h1:02I9XzhaBHqZU8Vd5e2zhf8j4foJ4muPT/x4gdR6E4c=
|
||||
go.unistack.org/micro-codec-yaml/v3 v3.10.2/go.mod h1:A/tYj7x9CRhuin7WxeIvnuo8bMDrZYcJkogVYN8X7rU=
|
||||
go.unistack.org/micro-config-file/v3 v3.8.10 h1:/IyD/i6I7Ic8jCNq7ZsTpWT8sToNG14gIFkSVPxbNpY=
|
||||
go.unistack.org/micro-config-file/v3 v3.8.10/go.mod h1:w7uw5KxK3H2OrZwX4p0hQHbp9UzwDODYqJvdofySgxY=
|
||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9 h1:ZXCS0eFiSdvcFYxpxV2Q77gfwAjpIRydwAEI1QBrwuQ=
|
||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9/go.mod h1:xODJQ0Nu/F8k34D/z2ITL91OskI/C674XCkugAxmc3Q=
|
||||
go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
|
||||
|
84
pkg/protoset/protoset.go
Normal file
84
pkg/protoset/protoset.go
Normal file
@ -0,0 +1,84 @@
|
||||
package protoset
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
protocodec "go.unistack.org/micro-codec-proto/v3"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/dynamicpb"
|
||||
)
|
||||
|
||||
var errNotFound = errors.New("file descriptor not found")
|
||||
|
||||
type ProtoSet struct {
|
||||
mu sync.Mutex
|
||||
files map[string]*protoregistry.Files
|
||||
}
|
||||
|
||||
func NewProtoSet() *ProtoSet {
|
||||
return &ProtoSet{
|
||||
mu: sync.Mutex{},
|
||||
files: make(map[string]*protoregistry.Files, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProtoSet) GetMessage(addr, pkg, svc, mth string) (protoreflect.Message, protoreflect.Message, error) {
|
||||
if addr == "" || svc == "" || mth == "" || pkg == "" {
|
||||
|
||||
return nil, nil, errors.New("addr or service name is empty")
|
||||
}
|
||||
p.mu.Lock()
|
||||
pfile, ok := p.files[addr+"|"+svc]
|
||||
p.mu.Unlock()
|
||||
if !ok || pfile == nil {
|
||||
return nil, nil, errNotFound
|
||||
}
|
||||
|
||||
pdesc, err := pfile.FindDescriptorByName(protoreflect.FullName(pkg + "." + svc))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to find service %s.%s, err: %w", pkg, svc, err)
|
||||
}
|
||||
|
||||
sdesc, ok := pdesc.(protoreflect.ServiceDescriptor)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("failed to find service " + pkg + "." + svc)
|
||||
}
|
||||
|
||||
mdesc := sdesc.Methods().ByName(protoreflect.Name(mth))
|
||||
if mdesc == nil {
|
||||
return nil, nil, fmt.Errorf("unknown method " + mth)
|
||||
}
|
||||
|
||||
req := dynamicpb.NewMessageType(mdesc.Input()).New()
|
||||
rsp := dynamicpb.NewMessageType(mdesc.Output()).New()
|
||||
|
||||
return req, rsp, nil
|
||||
}
|
||||
|
||||
func (p *ProtoSet) AddProtoset(addr, svc string, data []byte) error {
|
||||
fdset := &descriptorpb.FileDescriptorSet{}
|
||||
if err := protocodec.NewCodec().Unmarshal(data, fdset); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal protoset file: %w", err)
|
||||
vtolstov
commented
такие штуки fmt.Errorf("failed to unmarshal protoset file: %s", err) лучше через такие штуки fmt.Errorf("failed to unmarshal protoset file: %s", err) лучше через
fmt.Errorf("failed to unmarshal protoset file: %w", err) делать, чтобы оно врапало исходную ошибку.
|
||||
}
|
||||
|
||||
pfileoptions := protodesc.FileOptions{AllowUnresolvable: true}
|
||||
pfiles, err := pfileoptions.NewFiles(fdset)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to use protoset file, err: %w", err)
|
||||
}
|
||||
|
||||
p.mu.Lock()
|
||||
p.files[addr+"|"+svc] = pfiles
|
||||
p.mu.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProtoSet) AddReflection(ctx context.Context, service string, addr string) error {
|
||||
return nil
|
||||
}
|
49
pkg/protoset/protoset_test.go
Normal file
49
pkg/protoset/protoset_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package protoset
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
vtolstov
commented
вот этоу лучше на testify вот этоу лучше на [testify](https://github.com/stretchr/testify)
|
||||
|
||||
func TestProtoSet_1(t *testing.T) {
|
||||
p := NewProtoSet()
|
||||
data, err := os.ReadFile("path to .protoset")
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = p.AddProtoset("localhost:9090", "CardService", data)
|
||||
assert.Nil(t, err)
|
||||
|
||||
req, rsp, err := p.GetMessage("localhost:9090", "card_proto", "CardService", "GetCardList")
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, req)
|
||||
assert.NotNil(t, rsp)
|
||||
fmt.Printf("req: %v, rsp: %v \n", req, rsp)
|
||||
}
|
||||
|
||||
func TestProtoSet_2_bad(t *testing.T) {
|
||||
p := NewProtoSet()
|
||||
data, err := os.ReadFile("path to .protoset")
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = p.AddProtoset("localhost:9090", "CardService", data)
|
||||
assert.Nil(t, err)
|
||||
|
||||
req, rsp, err := p.GetMessage("localhost:9090", "card_proto", "Card", "GetCardList")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, req)
|
||||
assert.Nil(t, rsp)
|
||||
fmt.Printf("req: %v, rsp: %v \n", req, rsp)
|
||||
}
|
||||
|
||||
func TestProtoSet_3_not_found(t *testing.T) {
|
||||
p := NewProtoSet()
|
||||
|
||||
req, rsp, err := p.GetMessage("localhost:9090", "card_proto", "CardService", "GetCardList")
|
||||
assert.ErrorIs(t, err, errNotFound)
|
||||
assert.Nil(t, req)
|
||||
assert.Nil(t, rsp)
|
||||
fmt.Printf("req: %v, rsp: %v \n", req, rsp)
|
||||
}
|
Loading…
Reference in New Issue
Block a user
проверку pkg пропустил, по факту все 4 параметра тут обязательные.