-
Notifications
You must be signed in to change notification settings - Fork 8
/
command.go
135 lines (114 loc) · 2.77 KB
/
command.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"errors"
"fmt"
"strings"
cli "github.com/urfave/cli/v2"
)
var flags []cli.Flag = []cli.Flag{
&cli.IntFlag{
Name: "service-port",
Aliases: []string{"p"},
Usage: "grpc service port; e.g. -p 2379",
Required: true,
},
&cli.StringFlag{
Name: "interface",
Aliases: []string{"i"},
Usage: "listen on interface; e.g. -i eth0",
Required: false,
},
&cli.StringFlag{
Name: "read-file",
Aliases: []string{"r"},
Usage: "pcap file to parse, incompatible with -i; e.g. -r packet.pcap",
Required: false,
},
&cli.StringSliceFlag{
Name: "proto-file",
Aliases: []string{"f"},
Usage: "proto file to parse http2 frame, can use multiple times; e.g. -f rpc1.proto -f rpc2.proto",
Required: true,
},
&cli.StringFlag{
Name: "guess-path",
Aliases: []string{"m"},
Usage: "e.g. -m /pb.CoreRPC/WatchServiceStatus,/pb.CoreRPC/SetWorkloadsStatus or -m AUTO",
Required: false,
},
&cli.StringFlag{
Name: "output-format",
Aliases: []string{"o"},
DefaultText: "text",
Usage: "output format including 'text', 'json'",
Required: false,
},
&cli.BoolFlag{
Name: "grpcurl",
Usage: "output request data with corresponding grpcurl",
},
}
type ProvideMethod int
const (
UnknownMethod ProvideMethod = iota
BySniff
ByPcapFile
)
type OutputFormat int
const (
UnknownFormat OutputFormat = iota
Text
Json
Grpcurl
)
type Args struct {
// provider
ProvideMethod
Source string
// parser
ServicePort int
ProtoFilenames []string
GuessPaths []string
// outputter
OutputFormat
WithGrpcurl bool
}
func newArgs(ctx *cli.Context) (args *Args, err error) {
args = &Args{}
args.ServicePort = ctx.Int("service-port")
if iface := ctx.String("interface"); iface != "" {
args.ProvideMethod = BySniff
args.Source = fmt.Sprintf("%s:%d", iface, args.ServicePort)
}
if pcapFilename := ctx.String("read-file"); pcapFilename != "" {
if args.ProvideMethod != UnknownMethod {
return nil, errors.New("sniff-target and read-file cannot be used together")
}
args.ProvideMethod = ByPcapFile
args.Source = pcapFilename
}
args.ProtoFilenames = ctx.StringSlice("proto-file")
args.GuessPaths = strings.Split(ctx.String("guess-path"), ",")
if args.GuessPaths[0] == "" {
args.GuessPaths = []string{}
}
switch ctx.String("output-format") {
case "text":
args.OutputFormat = Text
case "json":
args.OutputFormat = Json
default:
args.OutputFormat = Text
}
args.WithGrpcurl = ctx.Bool("grpcurl")
return args, args.Validate()
}
func (a *Args) Validate() (err error) {
if a.ProvideMethod == UnknownMethod {
return errors.New("either sniff-target or read-file must be set")
}
if a.OutputFormat == UnknownFormat {
return errors.New("output-format must be set")
}
return nil
}