#1 #5
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,3 +25,4 @@ config.yaml
|
|||||||
servicechecker
|
servicechecker
|
||||||
*.protoset
|
*.protoset
|
||||||
authn.yaml
|
authn.yaml
|
||||||
|
.idea
|
@ -29,11 +29,8 @@ import (
|
|||||||
"go.unistack.org/servicechecker/pkg/config"
|
"go.unistack.org/servicechecker/pkg/config"
|
||||||
"go.unistack.org/servicechecker/pkg/grpcconn"
|
"go.unistack.org/servicechecker/pkg/grpcconn"
|
||||||
"go.unistack.org/servicechecker/pkg/httpconn"
|
"go.unistack.org/servicechecker/pkg/httpconn"
|
||||||
|
"go.unistack.org/servicechecker/pkg/protoset"
|
||||||
"go.unistack.org/servicechecker/pkg/scheduler"
|
"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 (
|
var (
|
||||||
@ -131,7 +128,7 @@ func main() {
|
|||||||
client.Codec("application/grpc+json", jsonpbcodec.NewCodec()),
|
client.Codec("application/grpc+json", jsonpbcodec.NewCodec()),
|
||||||
client.ContentType("application/grpc"),
|
client.ContentType("application/grpc"),
|
||||||
client.Retries(0),
|
client.Retries(0),
|
||||||
// client.TLSConfig(&tls.Config{InsecureSkipVerify: true}),
|
// client.TLSConfig(&tls.Config{InsecureSkipVerify: true}),
|
||||||
)
|
)
|
||||||
if err = gcli.Init(); err != nil {
|
if err = gcli.Init(); err != nil {
|
||||||
l.Fatal(ctx, "failed to init grpc client", err)
|
l.Fatal(ctx, "failed to init grpc client", err)
|
||||||
@ -144,7 +141,7 @@ func main() {
|
|||||||
client.Codec("application/json", jsonpbcodec.NewCodec()),
|
client.Codec("application/json", jsonpbcodec.NewCodec()),
|
||||||
client.ContentType("application/json"),
|
client.ContentType("application/json"),
|
||||||
client.Retries(0),
|
client.Retries(0),
|
||||||
// client.TLSConfig(&tls.Config{InsecureSkipVerify: true}),
|
// client.TLSConfig(&tls.Config{InsecureSkipVerify: true}),
|
||||||
)
|
)
|
||||||
if err = hcli.Init(); err != nil {
|
if err = hcli.Init(); err != nil {
|
||||||
l.Fatal(ctx, "failed to init http client", err)
|
l.Fatal(ctx, "failed to init http client", err)
|
||||||
@ -307,51 +304,28 @@ func newGRPCTask(ctx context.Context, l logger.Logger, m meter.Meter, check stri
|
|||||||
var rsp interface{}
|
var rsp interface{}
|
||||||
var treq client.Request
|
var treq client.Request
|
||||||
var labels []string
|
var labels []string
|
||||||
|
p := protoset.NewProtoSet()
|
||||||
|
|
||||||
if task.GRPC.Protoset != "" {
|
if task.GRPC.Protoset != "" {
|
||||||
|
pkg, svc, mth := grpcconn.ServiceMethod(task.GRPC.Endpoint)
|
||||||
|
|
||||||
protosetBuf, err := os.ReadFile(task.GRPC.Protoset)
|
protosetBuf, err := os.ReadFile(task.GRPC.Protoset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Error(ctx, "failed to unmarshal protoset file", err)
|
l.Error(ctx, "failed to unmarshal protoset file", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fdset := &descriptorpb.FileDescriptorSet{}
|
if err = p.AddProtoset(task.GRPC.Addr, svc, protosetBuf); err != nil {
|
||||||
if err = protocodec.NewCodec().Unmarshal(protosetBuf, fdset); err != nil {
|
l.Error(ctx, "failed add protoset", err)
|
||||||
l.Error(ctx, "failed to unmarshal protoset file", err)
|
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pfileoptions := protodesc.FileOptions{AllowUnresolvable: true}
|
req, rsp, err = p.GetMessage(task.GRPC.Addr, pkg, svc, mth)
|
||||||
pfiles, err := pfileoptions.NewFiles(fdset)
|
|
||||||
if err != nil {
|
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
|
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 {
|
if err = jsonpbcodec.NewCodec().Unmarshal([]byte(task.GRPC.Data), req); err != nil {
|
||||||
l.Error(ctx, "failed to unmarshal", err)
|
l.Error(ctx, "failed to unmarshal", err)
|
||||||
return nil, nil, 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/go-co-op/gocron/v2 v2.12.3
|
||||||
github.com/google/gnostic v0.7.0
|
github.com/google/gnostic v0.7.0
|
||||||
github.com/google/uuid v1.6.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-grpc/v3 v3.11.10
|
||||||
go.unistack.org/micro-client-http/v3 v3.9.14
|
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-json/v3 v3.10.1
|
||||||
go.unistack.org/micro-codec-jsonpb/v3 v3.10.3
|
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-proto/v3 v3.10.2
|
||||||
go.unistack.org/micro-codec-yaml/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-meter-victoriametrics/v3 v3.8.9
|
||||||
go.unistack.org/micro-proto/v3 v3.4.1
|
go.unistack.org/micro-proto/v3 v3.4.1
|
||||||
go.unistack.org/micro-server-http/v3 v3.11.34
|
go.unistack.org/micro-server-http/v3 v3.11.34
|
||||||
@ -21,9 +21,10 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
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/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
|
||||||
github.com/jonboulle/clockwork v0.4.0 // 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/robfig/cron/v3 v3.0.1 // indirect
|
||||||
github.com/valyala/fastrand v1.1.0 // indirect
|
github.com/valyala/fastrand v1.1.0 // indirect
|
||||||
github.com/valyala/histogram v1.2.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.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
|
||||||
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
|
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.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=
|
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=
|
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=
|
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-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 h1:02I9XzhaBHqZU8Vd5e2zhf8j4foJ4muPT/x4gdR6E4c=
|
||||||
go.unistack.org/micro-codec-yaml/v3 v3.10.2/go.mod h1:A/tYj7x9CRhuin7WxeIvnuo8bMDrZYcJkogVYN8X7rU=
|
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 h1:ZXCS0eFiSdvcFYxpxV2Q77gfwAjpIRydwAEI1QBrwuQ=
|
||||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9/go.mod h1:xODJQ0Nu/F8k34D/z2ITL91OskI/C674XCkugAxmc3Q=
|
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=
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|||||||
|
|
||||||
|
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
вот этоу лучше на testify