Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make StartCmd more customizable #16209

Merged
merged 6 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (core) [#14860](https://github.com/cosmos/cosmos-sdk/pull/14860) Add `Precommit` and `PrepareCheckState` AppModule callbacks.
* (tx) [#15992](https://github.com/cosmos/cosmos-sdk/pull/15992) Add `WithExtensionOptions` in tx Factory to allow `SetExtensionOptions` with given extension options.
* (types/simulation) [#16074](https://github.com/cosmos/cosmos-sdk/pull/16074) Add generic SimulationStoreDecoder for modules using collections.
* (cli) [#16209](https://github.com/cosmos/cosmos-sdk/pull/16209) Make `StartCmd` more customizable.

### Improvements

Expand Down Expand Up @@ -212,6 +213,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
* `simulation.NewOperationMsg` now marshals the operation msg as proto bytes instead of legacy amino JSON bytes.
* `simulation.NewOperationMsg` is now 2-arity instead of 3-arity with the obsolete argument `codec.ProtoCodec` removed.
* The field `OperationMsg.Msg` is now of type `[]byte` instead of `json.RawMessage`.
* (cli) [#16209](https://github.com/cosmos/cosmos-sdk/pull/16209) `StartCmd` now accepts struct `StartCmdOptions` as
parameter.


### Client Breaking Changes
Expand Down
49 changes: 39 additions & 10 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/cometbft/cometbft/proxy"
"github.com/cometbft/cometbft/rpc/client/local"
cmttypes "github.com/cometbft/cometbft/types"
dbm "github.com/cosmos/cosmos-db"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -88,9 +89,27 @@ const (
FlagMempoolMaxTxs = "mempool.max-txs"
)

// StartCmdOptions defines options that can be customized in `StartCmd`,
// only `AppCreator` and `DefaultNodeHome` are required, the other fields are optional.
type StartCmdOptions struct {
AppCreator types.AppCreator
DefaultNodeHome string
// DBOpener can be used to customize db opening, for example customize db options or support different db backends.
DBOpener func(rootDir string, backendType dbm.BackendType) (dbm.DB, error)
// PostSetup can be used to setup extra services under the same cancellable context,
// it's not called in stand-alone mode, only for in-process mode.
PostSetup func(svrCtx *Context, clientCtx client.Context, ctx context.Context, g *errgroup.Group) error
// AddFlags add custom flags to start cmd
AddFlags func(cmd *cobra.Command)
}

// StartCmd runs the service passed in, either stand-alone or in-process with
// CometBFT.
func StartCmd(appCreator types.AppCreator, defaultNodeHome string) *cobra.Command {
func StartCmd(opts StartCmdOptions) *cobra.Command {
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
if opts.DBOpener == nil {
opts.DBOpener = openDB
}

cmd := &cobra.Command{
Use: "start",
Short: "Run the full node",
Expand Down Expand Up @@ -145,17 +164,17 @@ is performed. Note, when enabled, gRPC will also be automatically enabled.
serverCtx.Logger.Info("starting ABCI without CometBFT")

return wrapCPUProfile(serverCtx, func() error {
return startStandAlone(serverCtx, appCreator)
return startStandAlone(serverCtx, opts)
})
}

return wrapCPUProfile(serverCtx, func() error {
return startInProcess(serverCtx, clientCtx, appCreator)
return startInProcess(serverCtx, clientCtx, opts)
})
},
}

cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
cmd.Flags().String(flags.FlagHome, opts.DefaultNodeHome, "The application home directory")
cmd.Flags().Bool(flagWithComet, true, "Run abci app embedded in-process with CometBFT")
cmd.Flags().String(flagAddress, "tcp://0.0.0.0:26658", "Listen address")
cmd.Flags().String(flagTransport, "socket", "Transport protocol: socket, grpc")
Expand Down Expand Up @@ -200,15 +219,19 @@ is performed. Note, when enabled, gRPC will also be automatically enabled.

// add support for all CometBFT-specific command line options
cmtcmd.AddNodeFlags(cmd)

if opts.AddFlags != nil {
opts.AddFlags(cmd)
}
return cmd
}

func startStandAlone(svrCtx *Context, appCreator types.AppCreator) error {
func startStandAlone(svrCtx *Context, opts StartCmdOptions) error {
addr := svrCtx.Viper.GetString(flagAddress)
transport := svrCtx.Viper.GetString(flagTransport)
home := svrCtx.Viper.GetString(flags.FlagHome)

db, err := openDB(home, GetAppDBBackend(svrCtx.Viper))
db, err := opts.DBOpener(home, GetAppDBBackend(svrCtx.Viper))
if err != nil {
return err
}
Expand All @@ -221,7 +244,7 @@ func startStandAlone(svrCtx *Context, appCreator types.AppCreator) error {
return err
}

app := appCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper)
app := opts.AppCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper)

config, err := serverconfig.GetConfig(svrCtx.Viper)
if err != nil {
Expand Down Expand Up @@ -267,11 +290,11 @@ func startStandAlone(svrCtx *Context, appCreator types.AppCreator) error {
return g.Wait()
}

func startInProcess(svrCtx *Context, clientCtx client.Context, appCreator types.AppCreator) error {
func startInProcess(svrCtx *Context, clientCtx client.Context, opts StartCmdOptions) error {
cmtCfg := svrCtx.Config
home := cmtCfg.RootDir

db, err := openDB(home, GetAppDBBackend(svrCtx.Viper))
db, err := opts.DBOpener(home, GetAppDBBackend(svrCtx.Viper))
if err != nil {
return err
}
Expand All @@ -286,7 +309,7 @@ func startInProcess(svrCtx *Context, clientCtx client.Context, appCreator types.
return err
}

app := appCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper)
app := opts.AppCreator(svrCtx.Logger, db, traceWriter, svrCtx.Viper)

// TODO: Move this to only be done if were launching the node. (So not in GRPC-only mode)
nodeKey, err := p2p.LoadOrGenNodeKey(cmtCfg.NodeKeyFile())
Expand Down Expand Up @@ -346,6 +369,12 @@ func startInProcess(svrCtx *Context, clientCtx client.Context, appCreator types.
return err
}

if opts.PostSetup != nil {
if err := opts.PostSetup(svrCtx, clientCtx, ctx, g); err != nil {
return err
}
}

// At this point it is safe to block the process if we're in gRPC-only mode as
// we do not need to handle any CometBFT related processes.
if gRPCOnly {
Expand Down
5 changes: 4 additions & 1 deletion server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,10 @@ func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator type
BootstrapStateCmd(appCreator),
)

startCmd := StartCmd(appCreator, defaultNodeHome)
startCmd := StartCmd(StartCmdOptions{
AppCreator: appCreator,
DefaultNodeHome: defaultNodeHome,
})
addStartFlags(startCmd)

rootCmd.AddCommand(
Expand Down
16 changes: 8 additions & 8 deletions server/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func preRunETestImpl(cmd *cobra.Command, args []string) error {

func TestInterceptConfigsPreRunHandlerCreatesConfigFilesWhenMissing(t *testing.T) {
tempDir := t.TempDir()
cmd := server.StartCmd(nil, "/foobar")
cmd := server.StartCmd(server.StartCmdOptions{AppCreator: nil, DefaultNodeHome: "/foobar"})
if err := cmd.Flags().Set(flags.FlagHome, tempDir); err != nil {
t.Fatalf("Could not set home flag [%T] %v", err, err)
}
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestInterceptConfigsPreRunHandlerReadsConfigToml(t *testing.T) {
t.Fatalf("Failed closing config.toml: %v", err)
}

cmd := server.StartCmd(nil, "/foobar")
cmd := server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: "/foobar"})
if err := cmd.Flags().Set(flags.FlagHome, tempDir); err != nil {
t.Fatalf("Could not set home flag [%T] %v", err, err)
}
Expand Down Expand Up @@ -155,7 +155,7 @@ func TestInterceptConfigsPreRunHandlerReadsAppToml(t *testing.T) {
if err := writer.Close(); err != nil {
t.Fatalf("Failed closing app.toml: %v", err)
}
cmd := server.StartCmd(nil, tempDir)
cmd := server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: tempDir})

cmd.PreRunE = preRunETestImpl

Expand All @@ -174,7 +174,7 @@ func TestInterceptConfigsPreRunHandlerReadsAppToml(t *testing.T) {
func TestInterceptConfigsPreRunHandlerReadsFlags(t *testing.T) {
const testAddr = "tcp://127.1.2.3:12345"
tempDir := t.TempDir()
cmd := server.StartCmd(nil, "/foobar")
cmd := server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: "/foobar"})

if err := cmd.Flags().Set(flags.FlagHome, tempDir); err != nil {
t.Fatalf("Could not set home flag [%T] %v", err, err)
Expand Down Expand Up @@ -202,7 +202,7 @@ func TestInterceptConfigsPreRunHandlerReadsFlags(t *testing.T) {
func TestInterceptConfigsPreRunHandlerReadsEnvVars(t *testing.T) {
const testAddr = "tcp://127.1.2.3:12345"
tempDir := t.TempDir()
cmd := server.StartCmd(nil, "/foobar")
cmd := server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: "/foobar"})
if err := cmd.Flags().Set(flags.FlagHome, tempDir); err != nil {
t.Fatalf("Could not set home flag [%T] %v", err, err)
}
Expand Down Expand Up @@ -288,7 +288,7 @@ func newPrecedenceCommon(t *testing.T) precedenceCommon {
})

// Set up the command object that is used in this test
retval.cmd = server.StartCmd(nil, tempDir)
retval.cmd = server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: tempDir})
retval.cmd.PreRunE = preRunETestImpl

return retval
Expand Down Expand Up @@ -395,7 +395,7 @@ func TestInterceptConfigsWithBadPermissions(t *testing.T) {
if err := os.Mkdir(subDir, 0o600); err != nil {
t.Fatalf("Failed to create sub directory: %v", err)
}
cmd := server.StartCmd(nil, "/foobar")
cmd := server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: "/foobar"})
if err := cmd.Flags().Set(flags.FlagHome, subDir); err != nil {
t.Fatalf("Could not set home flag [%T] %v", err, err)
}
Expand Down Expand Up @@ -432,7 +432,7 @@ func TestEmptyMinGasPrices(t *testing.T) {
config.WriteConfigFile(appCfgTempFilePath, appConf)

// Run StartCmd.
cmd = server.StartCmd(nil, tempDir)
cmd = server.StartCmd(StartCmdOptions{AppCreator: nil, DefaultNodeHome: tempDir})
cmd.PreRunE = func(cmd *cobra.Command, _ []string) error {
ctx, err := server.InterceptConfigsAndCreateContext(cmd, "", nil, cmtcfg.DefaultConfig())
if err != nil {
Expand Down