-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiscover.go
84 lines (70 loc) · 2.24 KB
/
discover.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package main
import (
"context"
"errors"
"strings"
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/grpcreflect"
gr "github.com/jhump/protoreflect/grpcreflect"
"google.golang.org/grpc"
rpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
"google.golang.org/grpc/status"
)
// this file is used to retrieve information,
// such as services list, proto- files
// from grpc client connections
// code was taken from evans sources
// https://github.com/ktr0731/evans/blob/master/grpc/grpcreflection/reflection.go
var ErrTLSHandshakeFailed = errors.New("TLS handshake failed")
func ListPackages(c *gr.Client) ([]*desc.FileDescriptor, error) {
ssvcs, err := c.ListServices()
if err != nil {
msg := status.Convert(err).Message()
// Check whether the error message contains TLS related error.
// If the server didn't enable TLS, the error message contains the first string.
// If Evans didn't enable TLS against to the TLS enabled server, the error message contains
// the second string.
if strings.Contains(msg, "tls: first record does not look like a TLS handshake") ||
strings.Contains(msg, "latest connection error: <nil>") {
return nil, ErrTLSHandshakeFailed
}
return nil, err
}
fds := make([]*desc.FileDescriptor, 0, len(ssvcs))
for _, s := range ssvcs {
svc, err := c.ResolveService(s)
if err != nil {
if gr.IsElementNotFoundError(err) {
// Service doesn't expose the ServiceDescriptor, skip.
continue
}
return nil, err
}
f := svc.GetFile()
fds = append(fds, f)
}
return fds, nil
}
func DiscoverServices(conn *grpc.ClientConn) (error, []string, []*desc.FileDescriptor) {
stub := rpb.NewServerReflectionClient(conn)
rclient := grpcreflect.NewClient(context.Background(), stub)
fds, err := ListPackages(rclient)
if err != nil {
return err, []string{}, []*desc.FileDescriptor{}
}
services, err := rclient.ListServices()
if err != nil {
return err, []string{}, []*desc.FileDescriptor{}
}
var methods []string
for _, srv := range services {
sdes, err := rclient.ResolveService(srv)
if err == nil {
for _, m := range sdes.GetMethods() {
fullMethodName := "/" + srv + "/" + m.GetName()
methods = append(methods, fullMethodName)
}
}
}
return nil, methods, fds
}