2019-06-25 11:42:17 +00:00
|
|
|
package cli
|
|
|
|
|
|
|
|
import (
|
2019-07-09 12:08:43 +00:00
|
|
|
"context"
|
2019-07-23 18:49:09 +00:00
|
|
|
"net/http"
|
2019-07-09 12:08:43 +00:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
|
|
|
|
2019-07-23 18:49:09 +00:00
|
|
|
logging "github.com/ipfs/go-log"
|
2019-07-10 17:28:49 +00:00
|
|
|
manet "github.com/multiformats/go-multiaddr-net"
|
2019-07-26 11:45:25 +00:00
|
|
|
"golang.org/x/xerrors"
|
2019-06-25 11:42:17 +00:00
|
|
|
"gopkg.in/urfave/cli.v2"
|
2019-07-10 17:28:49 +00:00
|
|
|
|
|
|
|
"github.com/filecoin-project/go-lotus/api"
|
|
|
|
"github.com/filecoin-project/go-lotus/api/client"
|
|
|
|
"github.com/filecoin-project/go-lotus/node/repo"
|
2019-06-25 11:42:17 +00:00
|
|
|
)
|
|
|
|
|
2019-07-23 18:49:09 +00:00
|
|
|
var log = logging.Logger("cli")
|
|
|
|
|
2019-07-09 12:08:43 +00:00
|
|
|
const (
|
2019-07-25 20:19:43 +00:00
|
|
|
metadataTraceConetxt = "traceContext"
|
|
|
|
metadataContext = "context"
|
2019-07-09 12:08:43 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ApiConnector returns API instance
|
2019-07-24 00:09:34 +00:00
|
|
|
type ApiConnector func() api.FullNode
|
2019-07-08 19:07:16 +00:00
|
|
|
|
2019-07-27 12:18:36 +00:00
|
|
|
func getAPI(ctx *cli.Context, repoFlag string) (string, http.Header, error) {
|
|
|
|
r, err := repo.NewFS(ctx.String(repoFlag))
|
2019-07-10 17:28:49 +00:00
|
|
|
if err != nil {
|
2019-07-27 12:18:36 +00:00
|
|
|
return "", nil, err
|
2019-07-10 17:28:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ma, err := r.APIEndpoint()
|
|
|
|
if err != nil {
|
2019-07-27 12:18:36 +00:00
|
|
|
return "", nil, xerrors.Errorf("failed to get api endpoint: %w", err)
|
2019-07-10 17:28:49 +00:00
|
|
|
}
|
|
|
|
_, addr, err := manet.DialArgs(ma)
|
2019-07-11 11:52:07 +00:00
|
|
|
if err != nil {
|
2019-07-27 12:18:36 +00:00
|
|
|
return "", nil, err
|
2019-07-11 11:52:07 +00:00
|
|
|
}
|
2019-07-23 18:49:09 +00:00
|
|
|
var headers http.Header
|
|
|
|
token, err := r.APIToken()
|
|
|
|
if err != nil {
|
|
|
|
log.Warnf("Couldn't load CLI token, capabilities may be limited: %w", err)
|
|
|
|
} else {
|
2019-07-23 20:05:44 +00:00
|
|
|
headers = http.Header{}
|
2019-07-23 18:49:09 +00:00
|
|
|
headers.Add("Authorization", "Bearer "+string(token))
|
|
|
|
}
|
|
|
|
|
2019-07-27 12:18:36 +00:00
|
|
|
return "ws://" + addr + "/rpc/v0", headers, nil
|
|
|
|
}
|
|
|
|
|
2019-08-02 16:18:44 +00:00
|
|
|
func GetAPI(ctx *cli.Context) (api.Common, error) {
|
|
|
|
f := "repo"
|
|
|
|
if ctx.String("storagerepo") != "" {
|
|
|
|
f = "storagerepo"
|
|
|
|
}
|
|
|
|
|
|
|
|
addr, headers, err := getAPI(ctx, f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return client.NewCommonRPC(addr, headers)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetFullNodeAPI(ctx *cli.Context) (api.FullNode, error) {
|
2019-07-27 12:18:36 +00:00
|
|
|
addr, headers, err := getAPI(ctx, "repo")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return client.NewFullNodeRPC(addr, headers)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetStorageMinerAPI(ctx *cli.Context) (api.StorageMiner, error) {
|
|
|
|
addr, headers, err := getAPI(ctx, "storagerepo")
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return client.NewStorageMinerRPC(addr, headers)
|
2019-07-09 12:08:43 +00:00
|
|
|
}
|
|
|
|
|
2019-07-18 23:16:23 +00:00
|
|
|
// ReqContext returns context for cli execution. Calling it for the first time
|
2019-07-09 12:08:43 +00:00
|
|
|
// installs SIGTERM handler that will close returned context.
|
|
|
|
// Not safe for concurrent execution.
|
2019-07-18 23:16:23 +00:00
|
|
|
func ReqContext(cctx *cli.Context) context.Context {
|
2019-07-09 12:08:43 +00:00
|
|
|
if uctx, ok := cctx.App.Metadata[metadataContext]; ok {
|
2019-07-09 12:46:06 +00:00
|
|
|
// unchecked cast as if something else is in there
|
2019-07-09 12:08:43 +00:00
|
|
|
// it is crash worthy either way
|
|
|
|
return uctx.(context.Context)
|
|
|
|
}
|
2019-07-25 20:19:43 +00:00
|
|
|
var tCtx context.Context
|
|
|
|
|
|
|
|
if mtCtx, ok := cctx.App.Metadata[metadataTraceConetxt]; ok {
|
|
|
|
tCtx = mtCtx.(context.Context)
|
|
|
|
} else {
|
|
|
|
tCtx = context.Background()
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx, done := context.WithCancel(tCtx)
|
2019-07-09 12:08:43 +00:00
|
|
|
sigChan := make(chan os.Signal, 2)
|
|
|
|
go func() {
|
|
|
|
<-sigChan
|
|
|
|
done()
|
|
|
|
}()
|
|
|
|
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
|
|
|
|
|
|
|
|
return ctx
|
2019-07-08 19:07:16 +00:00
|
|
|
}
|
|
|
|
|
2019-06-25 11:42:17 +00:00
|
|
|
var Commands = []*cli.Command{
|
2019-07-09 15:19:27 +00:00
|
|
|
chainCmd,
|
2019-07-20 21:55:51 +00:00
|
|
|
clientCmd,
|
2019-08-13 04:27:54 +00:00
|
|
|
createMinerCmd,
|
2019-07-20 21:55:51 +00:00
|
|
|
minerCmd,
|
|
|
|
mpoolCmd,
|
2019-07-08 19:07:16 +00:00
|
|
|
netCmd,
|
2019-08-13 04:27:54 +00:00
|
|
|
paychCmd,
|
|
|
|
sendCmd,
|
|
|
|
stateCmd,
|
2019-06-25 11:42:17 +00:00
|
|
|
versionCmd,
|
2019-07-13 00:41:32 +00:00
|
|
|
walletCmd,
|
2019-06-28 09:03:28 +00:00
|
|
|
}
|