181 lines
4.2 KiB
Go
181 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
"github.com/kr/pretty"
|
|
"github.com/urfave/cli/v2"
|
|
|
|
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
|
"github.com/filecoin-project/lotus/node/config"
|
|
)
|
|
|
|
var configCmd = &cli.Command{
|
|
Name: "config",
|
|
Usage: "Manage node config by layers. The layer 'base' will always be applied. ",
|
|
Subcommands: []*cli.Command{
|
|
configDefaultCmd,
|
|
configSetCmd,
|
|
configGetCmd,
|
|
configListCmd,
|
|
configViewCmd,
|
|
},
|
|
}
|
|
|
|
var configDefaultCmd = &cli.Command{
|
|
Name: "default",
|
|
Usage: "Print default node config",
|
|
Flags: []cli.Flag{
|
|
&cli.BoolFlag{
|
|
Name: "no-comment",
|
|
Usage: "don't comment default values",
|
|
},
|
|
},
|
|
Action: func(cctx *cli.Context) error {
|
|
c := config.DefaultLotusProvider()
|
|
|
|
cb, err := config.ConfigUpdate(c, nil, config.Commented(!cctx.Bool("no-comment")), config.DefaultKeepUncommented())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println(string(cb))
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var configSetCmd = &cli.Command{
|
|
Name: "set",
|
|
Usage: "Set a config layer or the base",
|
|
ArgsUsage: "a layer's name",
|
|
Action: func(cctx *cli.Context) error {
|
|
args := cctx.Args()
|
|
if args.Len() != 1 {
|
|
return errors.New("must have exactly 1 arg for the file name")
|
|
}
|
|
db, err := makeDB(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fn := args.First()
|
|
bytes, err := os.ReadFile(fn)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot read file %w", err)
|
|
}
|
|
|
|
lp := config.DefaultLotusProvider() // ensure it's toml
|
|
_, err = toml.Decode(string(bytes), lp)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot decode file: %w", err)
|
|
}
|
|
_ = lp
|
|
|
|
name := strings.Split(fn, ".")[0]
|
|
_, err = db.Exec(context.Background(),
|
|
`INSERT INTO harmony_config (title, config) VALUES (?,?)
|
|
ON CONFLICT (title) DO UPDATE SET config = excluded.config`, name, string(bytes))
|
|
if err != nil {
|
|
return fmt.Errorf("unable to save config layer: %w", err)
|
|
}
|
|
|
|
fmt.Println("Layer " + name + " created/updated")
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var configGetCmd = &cli.Command{
|
|
Name: "get",
|
|
Usage: "Get a config layer by name. You may want to pipe the output to a file, or use 'less'",
|
|
ArgsUsage: "layer name",
|
|
Action: func(cctx *cli.Context) error {
|
|
args := cctx.Args()
|
|
if args.Len() != 1 {
|
|
return fmt.Errorf("want 1 layer arg, got %d", args.Len())
|
|
}
|
|
db, err := makeDB(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var cfg string
|
|
err = db.QueryRow(context.Background(), `SELECT config FROM harmony_config WHERE title=?`, args.First()).Scan(&cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println(cfg)
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var configListCmd = &cli.Command{
|
|
Name: "list",
|
|
Usage: "List config layers you can get.",
|
|
Flags: []cli.Flag{},
|
|
Action: func(cctx *cli.Context) error {
|
|
db, err := makeDB(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var res []string
|
|
err = db.Select(context.Background(), &res, `SELECT title FROM harmony_confg ORDER BY title`)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to read from db: %w", err)
|
|
}
|
|
for _, r := range res {
|
|
fmt.Println(r)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var configViewCmd = &cli.Command{
|
|
Name: "view",
|
|
Usage: "View stacked config layers as it will be interpreted.",
|
|
ArgsUsage: "a list of layers to be interpreted as the final config",
|
|
Action: func(cctx *cli.Context) error {
|
|
db, err := makeDB(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
lp, err := getConfig(cctx, db)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println(pretty.Sprint(lp))
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
func getConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig, error) {
|
|
lp := config.DefaultLotusProvider()
|
|
have := []string{}
|
|
for _, layer := range regexp.MustCompile("[ |,]").Split(cctx.String("layers"), -1) {
|
|
text := ""
|
|
err := db.QueryRow(cctx.Context, `SELECT config FROM harmony_config WHERE title=?`, layer).Scan(&text)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not read layer %s: %w", layer, err)
|
|
}
|
|
meta, err := toml.Decode(text, &lp)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not read layer, bad toml %s: %w", layer, err)
|
|
}
|
|
for _, k := range meta.Keys() {
|
|
have = append(have, strings.Join(k, " "))
|
|
}
|
|
}
|
|
_ = have // TODO: verify that required fields are here.
|
|
return lp, nil
|
|
}
|