trmcli: add cli and command for close recommendations

This commit is contained in:
carla 2020-01-16 11:06:42 +02:00
parent a3cdc4bdb6
commit a13d473950
No known key found for this signature in database
GPG key ID: 4CA7FE54A6213C91
6 changed files with 216 additions and 0 deletions

View file

@ -58,6 +58,7 @@ $(GOACC_BIN):
build:
@$(call print, "Building terminator.")
$(GOBUILD) $(PKG)/cmd/terminator
$(GOBUILD) $(PKG)/cmd/trmcli
install:
@$(call print, "Installing terminator.")
@ -125,4 +126,5 @@ list:
clean:
@$(call print, "Cleaning source.$(NC)")
$(RM) ./terminator
$(RM) ./trmcli
$(RM) coverage.txt

View file

@ -0,0 +1,79 @@
package main
import (
"context"
"time"
"github.com/lightninglabs/terminator/trmrpc"
"github.com/urfave/cli"
)
var (
defaultMinMonitored = time.Hour * 24 * 7 * 4 // four weeks in hours
defaultOutlierMultiplier = 3
)
var closeRecommendationCommand = cli.Command{
Name: "closerecs",
Category: "channel",
Usage: "Get close recommendations for currently open channels.",
Flags: []cli.Flag{
cli.Int64Flag{
Name: "min_monitored",
Usage: "amount of time in seconds a channel should " +
"be monitored for to be eligible for close",
Value: int64(defaultMinMonitored.Seconds()),
},
cli.StringFlag{
Name: "outlier_mult",
Usage: "(optional with outlier strategy) Number of " +
"inter quartile ranges a channel should be " +
"from quartiles to be considered an outlier. " +
"Recommended values are 1.5 for aggressive " +
"recommendations and 3 for conservative ones.",
},
cli.StringFlag{
Name: "uptime_threshold",
Usage: "(optional) Uptime percentage threshold " +
"underneath which a channel will be recommended " +
"for close.",
},
},
Action: queryCloseRecommendations,
}
func queryCloseRecommendations(ctx *cli.Context) error {
client, cleanup := getClient(ctx)
defer cleanup()
// Set monitored value from cli and default outlier multiplier. The
// outlier multiplier will be overwritten if the user provided it.
req := &trmrpc.CloseRecommendationsRequest{
MinimumMonitored: ctx.Int64("min_monitored"),
OutlierMultiplier: float32(defaultOutlierMultiplier),
}
// If an a custom outlier multiple was set, use it.
if ctx.IsSet("outlier_mult") {
req.OutlierMultiplier = float32(ctx.Float64("outlier_mult"))
}
// If an uptime threshold was set, use it.
if ctx.IsSet("uptime_threshold") {
uptimeThreshold := float32(ctx.Float64("uptime_threshold"))
req.Threshold =
&trmrpc.CloseRecommendationsRequest_UptimeThreshold{
UptimeThreshold: uptimeThreshold,
}
}
rpcCtx := context.Background()
recs, err := client.CloseRecommendations(rpcCtx, req)
if err != nil {
return err
}
printRespJSON(recs)
return nil
}

32
cmd/trmcli/main.go Normal file
View file

@ -0,0 +1,32 @@
package main
import (
"os"
"github.com/urfave/cli"
)
var (
defaultRPCPort = "8419"
defaultRPCHostPort = "localhost:" + defaultRPCPort
)
func main() {
app := cli.NewApp()
app.Name = "trmcli"
app.Usage = "command line tool for terminator"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "rpcserver",
Value: defaultRPCHostPort,
Usage: "host:port of terminator",
},
}
app.Commands = []cli.Command{
closeRecommendationCommand,
}
if err := app.Run(os.Args); err != nil {
fatal(err)
}
}

97
cmd/trmcli/utils.go Normal file
View file

@ -0,0 +1,97 @@
package main
import (
"context"
"fmt"
"net"
"os"
"github.com/lightninglabs/protobuf-hex-display/jsonpb"
"github.com/lightninglabs/protobuf-hex-display/proto"
"github.com/lightninglabs/terminator/trmrpc"
"github.com/lightningnetwork/lnd/lncfg"
"github.com/urfave/cli"
"google.golang.org/grpc"
)
var (
// maxMsgRecvSize is the largest message our client will receive. We
// set this to 200MiB atm.
maxMsgRecvSize = grpc.MaxCallRecvMsgSize(1 * 1024 * 1024 * 200)
)
// fatal logs and error and exits.
func fatal(err error) {
_, _ = fmt.Fprintf(os.Stderr, "[trmcli] %v\n", err)
os.Exit(1)
}
// printRespJSON prints a proto message as json.
func printRespJSON(resp proto.Message) {
jsonMarshaler := &jsonpb.Marshaler{
EmitDefaults: true,
Indent: " ",
}
jsonStr, err := jsonMarshaler.MarshalToString(resp)
if err != nil {
fmt.Println("unable to decode response: ", err)
return
}
fmt.Println(jsonStr)
}
// getClient returns a terminator client.
func getClient(ctx *cli.Context) (trmrpc.TerminatorServerClient, func()) {
conn := getClientConn(ctx)
cleanUp := func() {
if err := conn.Close(); err != nil {
fatal(err)
}
}
return trmrpc.NewTerminatorServerClient(conn), cleanUp
}
// getClientConn gets a client connection to the address provided by the
// rpcserver flag.
func getClientConn(ctx *cli.Context) *grpc.ClientConn {
// We need to use a custom dialer so we can also connect to unix sockets
// and not just TCP addresses.
genericDialer := clientAddressDialer(defaultRPCPort)
opts := []grpc.DialOption{
grpc.WithContextDialer(genericDialer),
grpc.WithDefaultCallOptions(maxMsgRecvSize),
// TODO(carla): add tls and remove this option.
grpc.WithInsecure(),
}
conn, err := grpc.Dial(ctx.GlobalString("rpcserver"), opts...)
if err != nil {
fatal(fmt.Errorf("unable to connect to RPC server: %v", err))
}
return conn
}
// ClientAddressDialer parsed client address and returns a dialer.
func clientAddressDialer(defaultPort string) func(context.Context,
string) (net.Conn, error) {
return func(ctx context.Context, addr string) (net.Conn, error) {
parsedAddr, err := lncfg.ParseAddressString(
addr, defaultPort, net.ResolveTCPAddr,
)
if err != nil {
return nil, err
}
d := net.Dialer{}
return d.DialContext(
ctx, parsedAddr.Network(), parsedAddr.String(),
)
}
}

2
go.mod
View file

@ -6,7 +6,9 @@ require (
github.com/golang/protobuf v1.3.3
github.com/jessevdk/go-flags v1.4.0
github.com/lightninglabs/loop v0.2.4-alpha
github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d
github.com/lightningnetwork/lnd v0.8.0-beta-rc3.0.20191025122959-1a0ab538d53c
github.com/urfave/cli v1.20.0
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55
google.golang.org/grpc v1.27.0
)

4
go.sum
View file

@ -75,6 +75,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -137,6 +138,8 @@ github.com/lightninglabs/loop v0.2.4-alpha/go.mod h1:n/8uTYPcWrU12xAQmUvjvfxKTFW
github.com/lightninglabs/neutrino v0.0.0-20190906012717-f087198de655/go.mod h1:awTrhbCWjWNH4yVwZ4IE7nZbvpQ27e7OyD+jao7wRxA=
github.com/lightninglabs/neutrino v0.10.0 h1:yWVy2cOCCXbKFdpYCE9vD1fWRJDd9FtGXhUws4l9RkU=
github.com/lightninglabs/neutrino v0.10.0/go.mod h1:C3KhCMk1Mcx3j8v0qRVWM1Ow6rIJSvSPnUAq00ZNAfk=
github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d h1:QWD/5MPnaZfUVP7P8wLa4M8Td2DI7XXHXt2vhVtUgGI=
github.com/lightninglabs/protobuf-hex-display v1.3.3-0.20191212020323-b444784ce75d/go.mod h1:KDb67YMzoh4eudnzClmvs2FbiLG9vxISmLApUkCa4uI=
github.com/lightningnetwork/lightning-onion v0.0.0-20190909101754-850081b08b6a h1:GoWPN4i4jTKRxhVNh9a2vvBBO1Y2seiJB+SopUYoKyo=
github.com/lightningnetwork/lightning-onion v0.0.0-20190909101754-850081b08b6a/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4=
github.com/lightningnetwork/lnd v0.7.1-beta-rc2.0.20190914085956-35027e52fc22/go.mod h1:VaY0b5o38keUN3Ga6GVb/Mgta4B/CcCXwNvPAvhbv/A=
@ -181,6 +184,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY=
github.com/urfave/cli v1.18.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=