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: Allow app developers to override default appConfig template #9550

Merged
merged 22 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from 13 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
16 changes: 13 additions & 3 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
tmos "github.com/tendermint/tendermint/libs/os"
)

const defaultConfigTemplate = `# This is a TOML config file.
const DefaultConfigTemplate = `# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml

###############################################################################
Expand Down Expand Up @@ -210,7 +210,7 @@ func init() {

tmpl := template.New("appConfigFileTemplate")

if configTemplate, err = tmpl.Parse(defaultConfigTemplate); err != nil {
if configTemplate, err = tmpl.Parse(DefaultConfigTemplate); err != nil {
panic(err)
}
}
Expand All @@ -224,9 +224,19 @@ func ParseConfig(v *viper.Viper) (*Config, error) {
return conf, err
}

func SetConfigTemplate(customTemplate string) {
anilcse marked this conversation as resolved.
Show resolved Hide resolved
var err error

tmpl := template.New("appConfigFileTemplate")

if configTemplate, err = tmpl.Parse(customTemplate); err != nil {
panic(err)
}
}

// WriteConfigFile renders config using the template and writes it to
// configFilePath.
func WriteConfigFile(configFilePath string, config *Config) {
func WriteConfigFile(configFilePath string, config interface{}) {
var buffer bytes.Buffer

if err := configTemplate.Execute(&buffer, config); err != nil {
Expand Down
27 changes: 19 additions & 8 deletions server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error)
// the Tendermint configuration. The Viper literal is used to read and parse
// the application configuration. Command handlers can fetch the server Context
// to get the Tendermint configuration or to get access to Viper.
func InterceptConfigsPreRunHandler(cmd *cobra.Command) error {
func InterceptConfigsPreRunHandler(cmd *cobra.Command, customAppConfigTemplate string, customAppConfig interface{}) error {
serverCtx := NewDefaultContext()

// Get the executable name and configure the viper instance so that environmental
Expand All @@ -123,7 +123,7 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command) error {
serverCtx.Viper.AutomaticEnv()

// intercept configuration files, using both Viper instances separately
config, err := interceptConfigs(serverCtx.Viper)
config, err := interceptConfigs(serverCtx.Viper, customAppConfigTemplate, customAppConfig)
if err != nil {
return err
}
Expand Down Expand Up @@ -181,7 +181,7 @@ func SetCmdServerContext(cmd *cobra.Command, serverCtx *Context) error {
// configuration file. The Tendermint 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) (*tmcfg.Config, error) {
func interceptConfigs(rootViper *viper.Viper, customAppTemplate string, customConfig interface{}) (*tmcfg.Config, error) {
rootDir := rootViper.GetString(flags.FlagHome)
configPath := filepath.Join(rootDir, "config")
tmCfgFile := filepath.Join(configPath, "config.toml")
Expand Down Expand Up @@ -226,12 +226,23 @@ func interceptConfigs(rootViper *viper.Viper) (*tmcfg.Config, error) {

appCfgFilePath := filepath.Join(configPath, "app.toml")
if _, err := os.Stat(appCfgFilePath); os.IsNotExist(err) {
appConf, err := config.ParseConfig(rootViper)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err)
}
if customAppTemplate != "" {
config.SetConfigTemplate(customAppTemplate)

err = rootViper.Unmarshal(customConfig)
if err != nil {
anilcse marked this conversation as resolved.
Show resolved Hide resolved
return nil, fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err)
}

config.WriteConfigFile(appCfgFilePath, appConf)
config.WriteConfigFile(appCfgFilePath, customConfig)
} else {
appConf, err := config.ParseConfig(rootViper)
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err)
}

config.WriteConfigFile(appCfgFilePath, appConf)
}
}

rootViper.SetConfigType("toml")
Expand Down
2 changes: 1 addition & 1 deletion server/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var CancelledInPreRun = errors.New("Canelled in prerun")
// Used in each test to run the function under test via Cobra
// but to always halt the command
func preRunETestImpl(cmd *cobra.Command, args []string) error {
err := InterceptConfigsPreRunHandler(cmd)
err := InterceptConfigsPreRunHandler(cmd, "", nil)
if err != nil {
return err
}
Expand Down
45 changes: 43 additions & 2 deletions simapp/simd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"

serverconfig "github.com/cosmos/cosmos-sdk/server/config"
"github.com/spf13/cast"
"github.com/spf13/cobra"
tmcli "github.com/tendermint/tendermint/libs/cli"
Expand All @@ -14,7 +15,7 @@ import (

"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
config "github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/keys"
Expand Down Expand Up @@ -66,7 +67,10 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
return err
}

return server.InterceptConfigsPreRunHandler(cmd)
// this is optional
customAppTemplate, customAppConfig := initConfig()

return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig)
},
}

Expand All @@ -75,6 +79,43 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
return rootCmd, encodingConfig
}

// initConfig helps to override default appConfig template and settings.
// return; if no custom configuration is required for the application.
func initConfig() (string, interface{}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add a few short sentences in the docs about this please.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh sorry, meant the docs/ directory. I see you added in the doc.go.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find a relavant place to add it actually. There are no docs explaining server configs. May be I will add a new file or a new section under node docs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated rootCmd section docs

// WASMConfig defines configuration for the wasm module.
type WASMConfig struct {
// This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries
QueryGasLimit uint64 `mapstructure:"query_gas_limit"`

// Address defines the gRPC-web server to listen on
LruSize uint64 `mapstructure:"lru_size"`
}

type CustomAppConfig struct {
serverconfig.Config

WASM WASMConfig `mapstructure:"wasm"`
}

customAppConfig := CustomAppConfig{
Config: *serverconfig.DefaultConfig(),
WASM: WASMConfig{
LruSize: 1,
QueryGasLimit: 300000,
},
}

customAppTemplate := serverconfig.DefaultConfigTemplate + `
[wasm]
# This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries
query_gas_limit = 300000
# This is the number of wasm vm instances we keep cached in memory for speed-up
# Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally
lru_size = 0`

return customAppTemplate, customAppConfig
}

func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
cfg := sdk.GetConfig()
cfg.Seal()
Expand Down