From b67f39db1faf5ab962dd3cd1d25554c29d5c5f1c Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Fri, 26 Jul 2024 16:02:27 -0400 Subject: [PATCH 1/8] refactor --- mod/cli/pkg/builder/builder.go | 14 +- mod/cli/pkg/config/app.go | 108 ++++++ mod/cli/pkg/config/client.go | 10 +- mod/cli/pkg/config/comet.go | 104 ++++++ mod/cli/pkg/config/server.go | 142 ++++++++ mod/cli/pkg/utils/context/interceptors.go | 321 ------------------ .../context/{cmd.go => server_context.go} | 22 +- 7 files changed, 385 insertions(+), 336 deletions(-) create mode 100644 mod/cli/pkg/config/app.go create mode 100644 mod/cli/pkg/config/comet.go create mode 100644 mod/cli/pkg/config/server.go delete mode 100644 mod/cli/pkg/utils/context/interceptors.go rename mod/cli/pkg/utils/context/{cmd.go => server_context.go} (71%) diff --git a/mod/cli/pkg/builder/builder.go b/mod/cli/pkg/builder/builder.go index 65be2aa62f..d7a0d0d439 100644 --- a/mod/cli/pkg/builder/builder.go +++ b/mod/cli/pkg/builder/builder.go @@ -27,7 +27,7 @@ import ( "cosmossdk.io/depinject" sdklog "cosmossdk.io/log" cmdlib "github.com/berachain/beacon-kit/mod/cli/pkg/commands" - "github.com/berachain/beacon-kit/mod/cli/pkg/utils/context" + "github.com/berachain/beacon-kit/mod/cli/pkg/config" "github.com/berachain/beacon-kit/mod/log" "github.com/berachain/beacon-kit/mod/node-core/pkg/components" "github.com/berachain/beacon-kit/mod/node-core/pkg/types" @@ -153,9 +153,6 @@ func (cb *CLIBuilder[T, ExecutionPayloadT]) defaultRunHandler( } } -// InterceptConfigsPreRunHandler is identical to -// InterceptConfigsAndCreateContext except it also sets the server context on -// the command and the server logger. func (cb *CLIBuilder[T, ExecutionPayloadT]) InterceptConfigsPreRunHandler( cmd *cobra.Command, logger log.AdvancedLogger[any, sdklog.Logger], @@ -163,8 +160,13 @@ func (cb *CLIBuilder[T, ExecutionPayloadT]) InterceptConfigsPreRunHandler( customAppConfig interface{}, cmtConfig *cmtcfg.Config, ) error { - serverCtx, err := context.InterceptConfigsAndCreateContext( - cmd, customAppConfigTemplate, customAppConfig, cmtConfig, logger) + serverCtx, err := config.SetupConfigAndContext( + cmd, + customAppConfigTemplate, + customAppConfig, + cmtConfig, + logger, + ) if err != nil { return err } diff --git a/mod/cli/pkg/config/app.go b/mod/cli/pkg/config/app.go new file mode 100644 index 0000000000..2d4044eee4 --- /dev/null +++ b/mod/cli/pkg/config/app.go @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package config + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "github.com/cosmos/cosmos-sdk/server/config" + "github.com/spf13/viper" +) + +// handleAppConfig writes the provided to the file at +// /app.toml, or reads it into the provided instance +// if it exists. +func handleAppConfig( + viper *viper.Viper, + configDirPath string, + customAppTemplate string, + appConfig any, +) error { + // if the app.toml file does not exist, populate it with the values from + // + appCfgFilePath := filepath.Join(configDirPath, "app.toml") + if _, err := os.Stat(appCfgFilePath); os.IsNotExist(err) { + return writeAppConfig( + viper, + appCfgFilePath, + customAppTemplate, + appConfig, + ) + } + + // merge the app.toml file into the viper instance + viper.SetConfigType("toml") + viper.SetConfigName("app") + viper.AddConfigPath(configDirPath) + if err := viper.MergeInConfig(); err != nil { + return fmt.Errorf("failed to merge configuration: %w", err) + } + + return nil +} + +// writeAppConfig creates a new configuration file with default +// values at the specified file path . +func writeAppConfig( + rootViper *viper.Viper, + appConfigFilePath string, + appTemplate string, + appConfig any, +) error { + // customAppTemplate == nil ⊕ customConfig == nil + if (appTemplate != "" && appConfig == nil) || + (appTemplate == "" && appConfig != nil) { + return errors.New("customAppTemplate and customConfig " + + "should be both nil or not nil") + } + //nolint:nestif // not overly complex + if appTemplate != "" { + // set the config template + if err := config.SetConfigTemplate(appTemplate); err != nil { + return fmt.Errorf("failed to set config template: %w", err) + } + // populate appConfig with the values from the viper instance + err := rootViper.Unmarshal(&appConfig) + if err != nil { + return fmt.Errorf("failed to unmarshal app config: %w", err) + } + // write the appConfig to the file at appConfigFilePath + err = config.WriteConfigFile(appConfigFilePath, appConfig) + if err != nil { + return fmt.Errorf("failed to write %s: %w", appConfigFilePath, err) + } + } else { + appConf, err := config.ParseConfig(rootViper) + if err != nil { + return fmt.Errorf("failed to parse %s: %w", appConfigFilePath, err) + } + + err = config.WriteConfigFile(appConfigFilePath, appConf) + if err != nil { + return fmt.Errorf("failed to write %s: %w", appConfigFilePath, err) + } + } + + return nil +} diff --git a/mod/cli/pkg/config/client.go b/mod/cli/pkg/config/client.go index 20066b5040..ef999aff9d 100644 --- a/mod/cli/pkg/config/client.go +++ b/mod/cli/pkg/config/client.go @@ -20,12 +20,12 @@ package config -import "github.com/cosmos/cosmos-sdk/client/config" +import client "github.com/cosmos/cosmos-sdk/client/config" // InitClientConfig sets up the default client configuration, allowing for // overrides. -func InitClientConfig() (string, interface{}) { - clientCfg := config.DefaultConfig() - clientCfg.KeyringBackend = "test" - return config.DefaultClientConfigTemplate, clientCfg +func InitClientConfig() (string, any) { + clientConfig := client.DefaultConfig() + clientConfig.KeyringBackend = "test" + return client.DefaultClientConfigTemplate, clientConfig } diff --git a/mod/cli/pkg/config/comet.go b/mod/cli/pkg/config/comet.go new file mode 100644 index 0000000000..3761f86aee --- /dev/null +++ b/mod/cli/pkg/config/comet.go @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package config + +import ( + "fmt" + "os" + "time" + + cmtcfg "github.com/cometbft/cometbft/config" + "github.com/spf13/viper" +) + +// handleCometConfig reads the comet config at into the +// provided instance. If the file does not exist, it will be populated +// with the values from . +// will then be updated with the latest values from . +func handleCometConfig( + viper *viper.Viper, + cometConfigFile string, + cometConfig *cmtcfg.Config, + rootDir string, + configDirPath string, +) error { + _, err := os.Stat(cometConfigFile) + if os.IsNotExist(err) { + if err = writeCometConfig( + cometConfigFile, + cometConfig, + rootDir, + ); err != nil { + return fmt.Errorf("failed to write comet config: %w", err) + } + } else if err != nil { + return err + } + + // read the config.toml file into the viper instance + viper.SetConfigType("toml") + viper.SetConfigName("config") + viper.AddConfigPath(configDirPath) + + if err = viper.ReadInConfig(); err != nil { + return fmt.Errorf("failed to read in %s: %w", cometConfigFile, err) + } + + // update the comet config with the latest values from viper + if err = viper.Unmarshal(cometConfig); err != nil { + return err + } + + cometConfig.SetRoot(rootDir) + return nil +} + +// writeCometConfig creates a new comet config file one with default values. +// If the file exists, it reads and merges it into the provided Viper +// instance. +func writeCometConfig( + cometConfigFile string, + cometConfig *cmtcfg.Config, + rootDir string, +) error { + cmtcfg.EnsureRoot(rootDir) + + if err := cometConfig.ValidateBasic(); err != nil { + return fmt.Errorf("error in config file: %w", err) + } + + // the SDK is very opinionated about these values, so we override them + // if they aren't already set + defaultCometCfg := cmtcfg.DefaultConfig() + if cometConfig.Consensus.TimeoutCommit == + defaultCometCfg.Consensus.TimeoutCommit { + //nolint:mnd // 5 seconds + cometConfig.Consensus.TimeoutCommit = 5 * time.Second + } + if cometConfig.RPC.PprofListenAddress == + defaultCometCfg.RPC.PprofListenAddress { + cometConfig.RPC.PprofListenAddress = "localhost:6060" + } + + // write the comet config to the specified file path + cmtcfg.WriteConfigFile(cometConfigFile, cometConfig) + return nil +} diff --git a/mod/cli/pkg/config/server.go b/mod/cli/pkg/config/server.go new file mode 100644 index 0000000000..bfe7726dca --- /dev/null +++ b/mod/cli/pkg/config/server.go @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2024, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package config + +import ( + "fmt" + "os" + "path" + "path/filepath" + "strings" + + sdklog "cosmossdk.io/log" + "github.com/berachain/beacon-kit/mod/cli/pkg/utils/context" + "github.com/berachain/beacon-kit/mod/log" + cmtcfg "github.com/cometbft/cometbft/config" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/server" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func SetupConfigAndContext( + cmd *cobra.Command, + customAppConfigTemplate string, + customAppConfig interface{}, + cmtConfig *cmtcfg.Config, + logger log.AdvancedLogger[any, sdklog.Logger], +) (*server.Context, error) { + // initialize the server context + serverCtx, err := InitializeServerContext(cmd, logger) + if err != nil { + return nil, err + } + + // intercept the comet and app config files + cometConfig, err := handleConfigs( + serverCtx.Viper, customAppConfigTemplate, customAppConfig, cmtConfig) + if err != nil { + return nil, err + } + serverCtx.Config = cometConfig + return serverCtx, nil +} + +// InitializeServerContext returns a new server.Context object with the root +// viper instance. The comet config and app config are merged into the viper +// instance. If the app config is empty, the viper instance is populated with +// the app config values. +func InitializeServerContext( + cmd *cobra.Command, + logger log.AdvancedLogger[any, sdklog.Logger], +) (*server.Context, error) { + // Get the executable name and configure the viper instance so that + // environmental variables are checked based off that name. + baseName, err := baseName() + if err != nil { + return nil, err + } + viper := newPrefixedViper(baseName) + + // bind cobra flags to the viper instance + if err = bindFlags(cmd, viper); err != nil { + return nil, fmt.Errorf("error binding flags: %w", err) + } + + // create a new server.Context with the logger and viper instance + return context.CreateServerContext(logger, viper), nil +} + +// newPrefixedViper creates a new viper instance with the given environment +// prefix, and replaces all (.) and (-) with (_). +func newPrefixedViper(prefix string) *viper.Viper { + viper := viper.New() + viper.SetEnvPrefix(prefix) + viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_")) + viper.AutomaticEnv() + return viper +} + +// baseName returns the base name of the executable. +// ex: full path /usr/local/bin/myapp -> myapp +func baseName() (string, error) { + executableName, err := os.Executable() + if err != nil { + return "", fmt.Errorf("failed to fetch executable name: %w", err) + } + return path.Base(executableName), nil +} + +// bindFlags binds the command line flags to the viper instance. +func bindFlags(cmd *cobra.Command, viper *viper.Viper) error { + if err := viper.BindPFlags(cmd.Flags()); err != nil { + return err + } + if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { + return err + } + return nil +} + +// handleConfigs writes a new comet config file and app config file, and +// merges them into the provided viper instance. +func handleConfigs( + viper *viper.Viper, + customAppTemplate string, + customConfig any, + cometConfig *cmtcfg.Config, +) (*cmtcfg.Config, error) { + rootDir := viper.GetString(flags.FlagHome) + configDirPath := filepath.Join(rootDir, "config") + cmtCfgFile := filepath.Join(configDirPath, "config.toml") + + if err := handleCometConfig( + viper, cmtCfgFile, cometConfig, rootDir, configDirPath); err != nil { + return nil, err + } + + if err := handleAppConfig( + viper, configDirPath, customAppTemplate, customConfig); err != nil { + return nil, err + } + + return cometConfig, nil +} diff --git a/mod/cli/pkg/utils/context/interceptors.go b/mod/cli/pkg/utils/context/interceptors.go deleted file mode 100644 index 095e2b3386..0000000000 --- a/mod/cli/pkg/utils/context/interceptors.go +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -// -// Copyright (C) 2024, Berachain Foundation. All rights reserved. -// Use of this software is governed by the Business Source License included -// in the LICENSE file of this repository and at www.mariadb.com/bsl11. -// -// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY -// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER -// VERSIONS OF THE LICENSED WORK. -// -// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF -// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF -// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). -// -// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON -// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, -// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND -// TITLE. - -package context - -import ( - "errors" - "fmt" - "os" - "path" - "path/filepath" - "strings" - "time" - - sdklog "cosmossdk.io/log" - "github.com/berachain/beacon-kit/mod/log" - cmtcfg "github.com/cometbft/cometbft/config" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/server" - "github.com/cosmos/cosmos-sdk/server/config" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "github.com/spf13/viper" -) - -// InterceptConfigsAndCreateContext intercepts Comet and App Config files and -// creates a new server.Context object. It returns an error if the configuration -// files cannot be read or parsed. -func InterceptConfigsAndCreateContext( - cmd *cobra.Command, - customAppConfigTemplate string, - customAppConfig interface{}, - cmtConfig *cmtcfg.Config, - logger log.AdvancedLogger[any, sdklog.Logger], -) (*server.Context, error) { - serverCtx := newDefaultContextWithLogger(logger) - - // Get the executable name and configure the viper instance so that - // environmental variables are checked based off that name. - // The underscore character is used as a separator. - executableName, err := os.Executable() - if err != nil { - return nil, fmt.Errorf("failed to fetch executable name: %w", err) - } - - basename := path.Base(executableName) - - // configure the viper instance - if err = serverCtx.Viper.BindPFlags(cmd.Flags()); err != nil { - return nil, err - } - if err = serverCtx.Viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return nil, err - } - - serverCtx.Viper.SetEnvPrefix(basename) - serverCtx.Viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_")) - serverCtx.Viper.AutomaticEnv() - - // intercept configuration files, using both Viper instances separately - config, err := interceptConfigs( - serverCtx.Viper, customAppConfigTemplate, customAppConfig, cmtConfig) - if err != nil { - return nil, err - } - - // return value is a CometBFT configuration object - serverCtx.Config = config - if err = bindFlags(basename, cmd, serverCtx.Viper); err != nil { - return nil, fmt.Errorf("error binding flags for basename '%s': %w", - basename, err) - } - - return serverCtx, nil -} - -// newDefaultContextWithLogger returns a new server.Context with the default -// configuration. -func newDefaultContextWithLogger( - logger log.AdvancedLogger[any, sdklog.Logger], -) *server.Context { - return &server.Context{ - Viper: viper.New(), - Config: cmtcfg.DefaultConfig(), - Logger: logger, - } -} - -// TODO: Call this function from ProvideConfig to solve all our AppOpts problems -// This will allow us ingest ChainSpec into app.toml, and set logger config -// at build-time. - -// WriteAppConfig creates a new configuration file with default values if it -// does not exist, and write it to the specified file path. If the config file -// exists it skips. -// - -func WriteAppConfig( - rootViper *viper.Viper, - configPath string, - customAppTemplate string, - customConfig interface{}, -) error { - appCfgFilePath := filepath.Join(configPath, "app.toml") - // check if the application configuration file exists - if _, err := os.Stat(appCfgFilePath); os.IsNotExist(err) { - return populateConfigFileWithDefaults( - rootViper, - appCfgFilePath, - customAppTemplate, - customConfig, - err, - ) - } - return nil -} - -// populateConfigFileWithDefaults creates a new configuration file with default -// values at the specified file path . -func populateConfigFileWithDefaults( - rootViper *viper.Viper, - appCfgFilePath string, - customAppTemplate string, - customConfig interface{}, - statError error, -) error { - if (customAppTemplate != "" && customConfig == nil) || - (customAppTemplate == "" && customConfig != nil) { - return errors.New("customAppTemplate and customConfig " + - "should be both nil or not nil") - } - //nolint:nestif // not overly complex - if customAppTemplate != "" { - // set the configuration template - if config.SetConfigTemplate(customAppTemplate) != nil { - return fmt.Errorf("failed to set config template: %w", statError) - } - - if rootViper.Unmarshal(&customConfig) != nil { - return fmt.Errorf("failed to parse %s: %w", - appCfgFilePath, statError) - } - - if config.WriteConfigFile(appCfgFilePath, customConfig) != nil { - return fmt.Errorf("failed to write %s: %w", appCfgFilePath, - statError) - } - } else { - appConf, err := config.ParseConfig(rootViper) - if err != nil { - return fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err) - } - - if config.WriteConfigFile(appCfgFilePath, appConf) != nil { - return fmt.Errorf("failed to write %s: %w", appCfgFilePath, err) - } - } - return nil -} - -// interceptConfigs parses and updates a CometBFT configuration file or -// creates a new one and saves it. It also parses and saves the application -// configuration file. The CometBFT configuration file is parsed given a root -// Viper object, whereas the application is parsed with the private -// package-aware viperCfg object. -func interceptConfigs( - rootViper *viper.Viper, - customAppTemplate string, - customConfig interface{}, - cmtConfig *cmtcfg.Config, -) (*cmtcfg.Config, error) { - rootDir := rootViper.GetString(flags.FlagHome) - configPath := filepath.Join(rootDir, "config") - cmtCfgFile := filepath.Join(configPath, "config.toml") - - conf := cmtConfig - - if err := writeCometConfig( - rootViper, - cmtCfgFile, - conf, - rootDir, - configPath); err != nil { - return nil, err - } - - // Read into the configuration whatever data the viper instance has for it. - // This may come from the configuration file above but also any of the other - // sources viper uses. - if err := rootViper.Unmarshal(conf); err != nil { - return nil, err - } - - conf.SetRoot(rootDir) - - if err := WriteAppConfig( - rootViper, - configPath, - customAppTemplate, - customConfig); err != nil { - return nil, err - } - - rootViper.SetConfigType("toml") - rootViper.SetConfigName("app") - rootViper.AddConfigPath(configPath) - - if err := rootViper.MergeInConfig(); err != nil { - return nil, fmt.Errorf("failed to merge configuration: %w", err) - } - - return conf, nil -} - -// writeCometConfig creates a new comet config file one with default values. -// If the file exists, it reads and merges it into the provided Viper -// instance. -func writeCometConfig( - rootViper *viper.Viper, - cmtCfgFile string, - conf *cmtcfg.Config, - rootDir string, - configPath string, -) error { - // check if the configuration file exists - switch _, err := os.Stat(cmtCfgFile); { - case os.IsNotExist(err): - // create new config file with default values - cmtcfg.EnsureRoot(rootDir) - - if err = conf.ValidateBasic(); err != nil { - return fmt.Errorf("error in config file: %w", err) - } - - defaultCometCfg := cmtcfg.DefaultConfig() - // The SDK is opinionated about those comet values, so we set them here. - // We verify first that the user has not changed them for not overriding - // them. - if conf.Consensus.TimeoutCommit == - defaultCometCfg.Consensus.TimeoutCommit { - //nolint:mnd // 5 second timeout - conf.Consensus.TimeoutCommit = 5 * time.Second - } - if conf.RPC.PprofListenAddress == - defaultCometCfg.RPC.PprofListenAddress { - conf.RPC.PprofListenAddress = "localhost:6060" - } - // Write the configuration file to the config directory. - cmtcfg.WriteConfigFile(cmtCfgFile, conf) - - case err != nil: - return err - - default: - // read in the configuration file - rootViper.SetConfigType("toml") - rootViper.SetConfigName("config") - rootViper.AddConfigPath(configPath) - - if err = rootViper.ReadInConfig(); err != nil { - return fmt.Errorf("failed to read in %s: %w", cmtCfgFile, err) - } - } - return nil -} - -// bindFlags binds the command line flags to the viper instance. -func bindFlags( - basename string, cmd *cobra.Command, v *viper.Viper, -) (err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("bindFlags failed: %v", r) - } - }() - - cmd.Flags().VisitAll(func(f *pflag.Flag) { - // Environment variables can't have dashes in them, so bind them to - // their equivalent keys with underscores, e.g. --favorite-color to - // STING_FAVORITE_COLOR - err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper( - strings.ReplaceAll(f.Name, "-", "_")))) - if err != nil { - panic(err) - } - - err = v.BindPFlag(f.Name, f) - if err != nil { - panic(err) - } - - // Apply the viper config value to the flag when the flag is not set and - // viper has a value. - if !f.Changed && v.IsSet(f.Name) { - val := v.Get(f.Name) - err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) - if err != nil { - panic(err) - } - } - }) - - return err -} diff --git a/mod/cli/pkg/utils/context/cmd.go b/mod/cli/pkg/utils/context/server_context.go similarity index 71% rename from mod/cli/pkg/utils/context/cmd.go rename to mod/cli/pkg/utils/context/server_context.go index 13778cb98a..51913c0a3e 100644 --- a/mod/cli/pkg/utils/context/cmd.go +++ b/mod/cli/pkg/utils/context/server_context.go @@ -21,12 +21,28 @@ package context import ( - "cosmossdk.io/log" + sdklog "cosmossdk.io/log" + "github.com/berachain/beacon-kit/mod/log" "github.com/berachain/beacon-kit/mod/log/pkg/noop" + cmtcfg "github.com/cometbft/cometbft/config" "github.com/cosmos/cosmos-sdk/server" "github.com/spf13/cobra" + "github.com/spf13/viper" ) +// createServerContext initializes a new server.Context with the default comet +// config, and the provided logger and viper instances. +func CreateServerContext( + logger log.AdvancedLogger[any, sdklog.Logger], + viper *viper.Viper, +) *server.Context { + return &server.Context{ + Viper: viper, + Config: cmtcfg.DefaultConfig(), + Logger: logger, + } +} + // GetServerContextFromCmd returns a Context from a command or an empty Context // if it has not been set. func GetServerContextFromCmd(cmd *cobra.Command) *server.Context { @@ -35,7 +51,5 @@ func GetServerContextFromCmd(cmd *cobra.Command) *server.Context { return serverCtxPtr } - return newDefaultContextWithLogger( - &noop.Logger[any, log.Logger]{}, - ) + return CreateServerContext(&noop.Logger[any, sdklog.Logger]{}, viper.New()) } From 4b89297a1749bf3d04b6360b280a5f63474cae2d Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Fri, 26 Jul 2024 16:12:28 -0400 Subject: [PATCH 2/8] tidy sync --- mod/cli/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/cli/go.mod b/mod/cli/go.mod index 87414fc4fe..66b8e5957e 100644 --- a/mod/cli/go.mod +++ b/mod/cli/go.mod @@ -206,7 +206,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.12 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect From e7232d1009c0602098e3a6d792c52e3fa5cb87ef Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Fri, 26 Jul 2024 16:58:58 -0400 Subject: [PATCH 3/8] check if e2e passes, why blutgang broken --- mod/cli/pkg/config/server.go | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/mod/cli/pkg/config/server.go b/mod/cli/pkg/config/server.go index bfe7726dca..903c53c27a 100644 --- a/mod/cli/pkg/config/server.go +++ b/mod/cli/pkg/config/server.go @@ -34,6 +34,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" ) @@ -57,6 +58,15 @@ func SetupConfigAndContext( return nil, err } serverCtx.Config = cometConfig + + // not really sure why we have to bind this again here + if err = bindCommandLineFlags( + serverCtx.Viper.GetString(flags.FlagHome), + cmd, + serverCtx.Viper, + ); err != nil { + return nil, fmt.Errorf("error binding command line flags: %w", err) + } return serverCtx, nil } @@ -116,6 +126,41 @@ func bindFlags(cmd *cobra.Command, viper *viper.Viper) error { return nil } +// bindCommandLineFlags binds the command line flags to the viper instance. +func bindCommandLineFlags( + basename string, cmd *cobra.Command, v *viper.Viper, +) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("bindFlags failed: %v", r) + } + }() + + cmd.Flags().VisitAll(func(f *pflag.Flag) { + // this should be redundant + err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper( + strings.ReplaceAll(f.Name, "-", "_")))) + if err != nil { + panic(err) + } + + err = v.BindPFlag(f.Name, f) + if err != nil { + panic(err) + } + + if !f.Changed && v.IsSet(f.Name) { + val := v.Get(f.Name) + err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) + if err != nil { + panic(err) + } + } + }) + + return err +} + // handleConfigs writes a new comet config file and app config file, and // merges them into the provided viper instance. func handleConfigs( From 57bbb782f14a559ee7840c566494f3d8a6b822d4 Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Fri, 26 Jul 2024 17:11:39 -0400 Subject: [PATCH 4/8] ermset --- mod/cli/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/cli/go.mod b/mod/cli/go.mod index 63d4e10c2a..30fddaaca6 100644 --- a/mod/cli/go.mod +++ b/mod/cli/go.mod @@ -207,7 +207,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/pflag v1.0.5 github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.12 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect From 9d89f135b2da870f2c1df87fb6accf4a3158dbda Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Sun, 28 Jul 2024 19:40:32 -0400 Subject: [PATCH 5/8] revert second bind --- mod/cli/go.mod | 2 +- mod/cli/pkg/config/server.go | 45 ------------------------------------ 2 files changed, 1 insertion(+), 46 deletions(-) diff --git a/mod/cli/go.mod b/mod/cli/go.mod index a8721e02aa..0a3d0a2a90 100644 --- a/mod/cli/go.mod +++ b/mod/cli/go.mod @@ -207,7 +207,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.12 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect diff --git a/mod/cli/pkg/config/server.go b/mod/cli/pkg/config/server.go index 903c53c27a..bfe7726dca 100644 --- a/mod/cli/pkg/config/server.go +++ b/mod/cli/pkg/config/server.go @@ -34,7 +34,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" "github.com/spf13/cobra" - "github.com/spf13/pflag" "github.com/spf13/viper" ) @@ -58,15 +57,6 @@ func SetupConfigAndContext( return nil, err } serverCtx.Config = cometConfig - - // not really sure why we have to bind this again here - if err = bindCommandLineFlags( - serverCtx.Viper.GetString(flags.FlagHome), - cmd, - serverCtx.Viper, - ); err != nil { - return nil, fmt.Errorf("error binding command line flags: %w", err) - } return serverCtx, nil } @@ -126,41 +116,6 @@ func bindFlags(cmd *cobra.Command, viper *viper.Viper) error { return nil } -// bindCommandLineFlags binds the command line flags to the viper instance. -func bindCommandLineFlags( - basename string, cmd *cobra.Command, v *viper.Viper, -) (err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("bindFlags failed: %v", r) - } - }() - - cmd.Flags().VisitAll(func(f *pflag.Flag) { - // this should be redundant - err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper( - strings.ReplaceAll(f.Name, "-", "_")))) - if err != nil { - panic(err) - } - - err = v.BindPFlag(f.Name, f) - if err != nil { - panic(err) - } - - if !f.Changed && v.IsSet(f.Name) { - val := v.Get(f.Name) - err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) - if err != nil { - panic(err) - } - } - }) - - return err -} - // handleConfigs writes a new comet config file and app config file, and // merges them into the provided viper instance. func handleConfigs( From 209fa859e566a8bc9ca0450e11558d28d121928f Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Mon, 29 Jul 2024 12:42:49 -0400 Subject: [PATCH 6/8] e2e not working locally reeee --- mod/cli/go.mod | 2 +- mod/cli/pkg/config/server.go | 57 ++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/mod/cli/go.mod b/mod/cli/go.mod index 0a3d0a2a90..a8721e02aa 100644 --- a/mod/cli/go.mod +++ b/mod/cli/go.mod @@ -207,7 +207,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/pflag v1.0.5 github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.12 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect diff --git a/mod/cli/pkg/config/server.go b/mod/cli/pkg/config/server.go index bfe7726dca..0cf076b584 100644 --- a/mod/cli/pkg/config/server.go +++ b/mod/cli/pkg/config/server.go @@ -34,13 +34,20 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" ) +// SetupConfigAndContext returns a server.Context initialized with a viper +// instance configured with the provided command. If the files expected to +// contain the comet and app configs are empty, it will be populated with the +// values from and . +// In either case, the resulting values in these files will be merged with +// viper. func SetupConfigAndContext( cmd *cobra.Command, - customAppConfigTemplate string, - customAppConfig interface{}, + appTemplate string, + appConfig any, cmtConfig *cmtcfg.Config, logger log.AdvancedLogger[any, sdklog.Logger], ) (*server.Context, error) { @@ -52,10 +59,12 @@ func SetupConfigAndContext( // intercept the comet and app config files cometConfig, err := handleConfigs( - serverCtx.Viper, customAppConfigTemplate, customAppConfig, cmtConfig) + serverCtx.Viper, appTemplate, appConfig, cmtConfig) if err != nil { return nil, err } + + // set the cometbft config serverCtx.Config = cometConfig return serverCtx, nil } @@ -77,7 +86,7 @@ func InitializeServerContext( viper := newPrefixedViper(baseName) // bind cobra flags to the viper instance - if err = bindFlags(cmd, viper); err != nil { + if err = bindFlags(baseName, cmd, viper); err != nil { return nil, fmt.Errorf("error binding flags: %w", err) } @@ -106,14 +115,38 @@ func baseName() (string, error) { } // bindFlags binds the command line flags to the viper instance. -func bindFlags(cmd *cobra.Command, viper *viper.Viper) error { - if err := viper.BindPFlags(cmd.Flags()); err != nil { - return err - } - if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { - return err - } - return nil +func bindFlags( + basename string, cmd *cobra.Command, v *viper.Viper, +) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("bindFlags failed: %v", r) + } + }() + + cmd.Flags().VisitAll(func(f *pflag.Flag) { + // this should be redundant + err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper( + strings.ReplaceAll(f.Name, "-", "_")))) + if err != nil { + panic(err) + } + + err = v.BindPFlag(f.Name, f) + if err != nil { + panic(err) + } + + if !f.Changed && v.IsSet(f.Name) { + val := v.Get(f.Name) + err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) + if err != nil { + panic(err) + } + } + }) + + return err } // handleConfigs writes a new comet config file and app config file, and From 5ac98cc10f33210a97f56f9da6a00ffd68b09b38 Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Mon, 29 Jul 2024 13:04:35 -0400 Subject: [PATCH 7/8] small cleanup --- mod/cli/pkg/config/app.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/mod/cli/pkg/config/app.go b/mod/cli/pkg/config/app.go index 2d4044eee4..8dae04dcba 100644 --- a/mod/cli/pkg/config/app.go +++ b/mod/cli/pkg/config/app.go @@ -70,38 +70,38 @@ func writeAppConfig( appTemplate string, appConfig any, ) error { + var ( + appTemplatePopulated bool = appTemplate != "" + appConfigPopulated bool = appConfig != nil + err error + ) + // customAppTemplate == nil ⊕ customConfig == nil - if (appTemplate != "" && appConfig == nil) || - (appTemplate == "" && appConfig != nil) { + if (appTemplatePopulated && !appConfigPopulated) || + (!appTemplatePopulated && appConfigPopulated) { return errors.New("customAppTemplate and customConfig " + "should be both nil or not nil") } //nolint:nestif // not overly complex - if appTemplate != "" { + if appTemplatePopulated { // set the config template if err := config.SetConfigTemplate(appTemplate); err != nil { return fmt.Errorf("failed to set config template: %w", err) } // populate appConfig with the values from the viper instance - err := rootViper.Unmarshal(&appConfig) - if err != nil { + if err := rootViper.Unmarshal(&appConfig); err != nil { return fmt.Errorf("failed to unmarshal app config: %w", err) } - // write the appConfig to the file at appConfigFilePath - err = config.WriteConfigFile(appConfigFilePath, appConfig) - if err != nil { - return fmt.Errorf("failed to write %s: %w", appConfigFilePath, err) - } } else { - appConf, err := config.ParseConfig(rootViper) + // read the appConfig from the file at appConfigFilePath + appConfig, err = config.ParseConfig(rootViper) if err != nil { return fmt.Errorf("failed to parse %s: %w", appConfigFilePath, err) } - - err = config.WriteConfigFile(appConfigFilePath, appConf) - if err != nil { - return fmt.Errorf("failed to write %s: %w", appConfigFilePath, err) - } + } + // write the appConfig to the file at appConfigFilePath + if err := config.WriteConfigFile(appConfigFilePath, appConfig); err != nil { + return fmt.Errorf("failed to write %s: %w", appConfigFilePath, err) } return nil From 368550aeda045a25d8607bc3b5755ab6c5f58a2a Mon Sep 17 00:00:00 2001 From: ocnc-two Date: Mon, 29 Jul 2024 13:43:50 -0400 Subject: [PATCH 8/8] lint --- mod/cli/pkg/config/app.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/mod/cli/pkg/config/app.go b/mod/cli/pkg/config/app.go index 8dae04dcba..73442470e4 100644 --- a/mod/cli/pkg/config/app.go +++ b/mod/cli/pkg/config/app.go @@ -70,11 +70,9 @@ func writeAppConfig( appTemplate string, appConfig any, ) error { - var ( - appTemplatePopulated bool = appTemplate != "" - appConfigPopulated bool = appConfig != nil - err error - ) + var err error + appTemplatePopulated := appTemplate != "" + appConfigPopulated := appConfig != nil // customAppTemplate == nil ⊕ customConfig == nil if (appTemplatePopulated && !appConfigPopulated) || @@ -82,14 +80,14 @@ func writeAppConfig( return errors.New("customAppTemplate and customConfig " + "should be both nil or not nil") } - //nolint:nestif // not overly complex + if appTemplatePopulated { // set the config template - if err := config.SetConfigTemplate(appTemplate); err != nil { + if err = config.SetConfigTemplate(appTemplate); err != nil { return fmt.Errorf("failed to set config template: %w", err) } // populate appConfig with the values from the viper instance - if err := rootViper.Unmarshal(&appConfig); err != nil { + if err = rootViper.Unmarshal(&appConfig); err != nil { return fmt.Errorf("failed to unmarshal app config: %w", err) } } else { @@ -100,7 +98,7 @@ func writeAppConfig( } } // write the appConfig to the file at appConfigFilePath - if err := config.WriteConfigFile(appConfigFilePath, appConfig); err != nil { + if err = config.WriteConfigFile(appConfigFilePath, appConfig); err != nil { return fmt.Errorf("failed to write %s: %w", appConfigFilePath, err) }