diff --git a/tools/confix/README.md b/tools/confix/README.md index f6badd49734f..d7867d5f4481 100644 --- a/tools/confix/README.md +++ b/tools/confix/README.md @@ -93,14 +93,20 @@ confix set ~/.simapp/config/client.toml chain-id "foo-1" # sets the value chain- ### Migrate -Migrate a configuration file to a new version, e.g.: +Migrate a configuration file to a new version, config type defaults to `app.toml`, if you want to change it to `client.toml`, please indicate it by adding the optional parameter, e.g.: ```shell -simd config migrate v0.47 # migrates defaultHome/config/app.toml to the latest v0.47 config +simd config migrate v0.50 # migrates defaultHome/config/app.toml to the latest v0.47 config ``` ```shell -confix migrate v0.47 ~/.simapp/config/app.toml # migrate ~/.simapp/config/app.toml to the latest v0.47 config +confix migrate v0.50 ~/.simapp/config/app.toml # migrate ~/.simapp/config/app.toml to the latest v0.47 config +``` + +or + +```shell +confix migrate v0.50 ~/.simapp/config/client.toml client # migrate ~/.simapp/config/client.toml to the latest v0.47 config ``` ### Diff diff --git a/tools/confix/cmd/diff.go b/tools/confix/cmd/diff.go index a30193376f53..263095a451fa 100644 --- a/tools/confix/cmd/diff.go +++ b/tools/confix/cmd/diff.go @@ -3,44 +3,46 @@ package cmd import ( "errors" "fmt" + "strings" + "github.com/cosmos/cosmos-sdk/client" "github.com/spf13/cobra" "golang.org/x/exp/maps" "cosmossdk.io/tools/confix" - - "github.com/cosmos/cosmos-sdk/client" ) +// DiffCommand creates a new command for comparing configuration files func DiffCommand() *cobra.Command { return &cobra.Command{ - Use: "diff [target-version] ", - Short: "Outputs all config values that are different from the app.toml defaults.", - Args: cobra.MinimumNArgs(1), + Use: "diff [target-version] [config-type]", + Short: "Outputs all config values that are different from the default.", + Long: "This command compares the specified configuration file (app.toml or client.toml) with the defaults and outputs any differences.", + Args: cobra.MinimumNArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - var filename string + targetVersion := args[0] + configPath := args[1] + configType := confix.AppConfigType // Default to app configuration clientCtx := client.GetClientContextFromCmd(cmd) - switch { - - case len(args) > 1: - filename = args[1] - case clientCtx.HomeDir != "": - filename = fmt.Sprintf("%s/config/app.toml", clientCtx.HomeDir) - default: - return errors.New("must provide a path to the app.toml file") + + if len(args) > 2 { + configType = strings.ToLower(args[2]) + } + + if configType != confix.AppConfigType && configType != confix.ClientConfigType { + return errors.New("config type must be 'app' or 'client'") } - targetVersion := args[0] if _, ok := confix.Migrations[targetVersion]; !ok { return fmt.Errorf("unknown version %q, supported versions are: %q", targetVersion, maps.Keys(confix.Migrations)) } - targetVersionFile, err := confix.LoadLocalConfig(targetVersion) + targetVersionFile, err := confix.LoadLocalConfig(targetVersion, configType) if err != nil { panic(fmt.Errorf("failed to load internal config: %w", err)) } - rawFile, err := confix.LoadConfig(filename) + rawFile, err := confix.LoadConfig(configPath) if err != nil { return fmt.Errorf("failed to load config: %w", err) } diff --git a/tools/confix/cmd/migrate.go b/tools/confix/cmd/migrate.go index 6377c254b0af..bdc410b78cef 100644 --- a/tools/confix/cmd/migrate.go +++ b/tools/confix/cmd/migrate.go @@ -4,15 +4,16 @@ import ( "context" "errors" "fmt" + "strings" + "github.com/cosmos/cosmos-sdk/client" "github.com/spf13/cobra" "golang.org/x/exp/maps" "cosmossdk.io/tools/confix" - - "github.com/cosmos/cosmos-sdk/client" ) + var ( FlagStdOut bool FlagVerbose bool @@ -21,31 +22,43 @@ var ( func MigrateCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "migrate [target-version] (options)", - Short: "Migrate Cosmos SDK app configuration file to the specified version", - Long: `Migrate the contents of the Cosmos SDK app configuration (app.toml) to the specified version. + Use: "migrate [target-version] [config-type]", + Short: "Migrate Cosmos SDK configuration file to the specified version", + Long: `Migrate the contents of the Cosmos SDK configuration (app.toml or client.toml) to the specified version. Configuration type is app by default. The output is written in-place unless --stdout is provided. In case of any error in updating the file, no output is written.`, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - var filename string + var configPath string + clientCtx := client.GetClientContextFromCmd(cmd) - switch { + targetVersion := args[0] + configType := confix.AppConfigType // Default to app configuration + + if len(args) > 2 { + configType = strings.ToLower(args[2]) + } + + if configType != confix.AppConfigType && configType != confix.ClientConfigType { + return errors.New("config type must be 'app' or 'client'") + } + + switch { case len(args) > 1: - filename = args[1] + configPath = args[1] case clientCtx.HomeDir != "": - filename = fmt.Sprintf("%s/config/app.toml", clientCtx.HomeDir) + configPath = fmt.Sprintf("%s/config/%s.toml",clientCtx.HomeDir, configType) default: - return errors.New("must provide a path to the app.toml file") + return errors.New("must provide a path to the config file") } - targetVersion := args[0] + plan, ok := confix.Migrations[targetVersion] if !ok { return fmt.Errorf("unknown version %q, supported versions are: %q", targetVersion, maps.Keys(confix.Migrations)) } - rawFile, err := confix.LoadConfig(filename) + rawFile, err := confix.LoadConfig(configPath) if err != nil { return fmt.Errorf("failed to load config: %w", err) } @@ -55,12 +68,12 @@ In case of any error in updating the file, no output is written.`, ctx = confix.WithLogWriter(ctx, cmd.ErrOrStderr()) } - outputPath := filename + outputPath := configPath if FlagStdOut { outputPath = "" } - if err := confix.Upgrade(ctx, plan(rawFile, targetVersion), filename, outputPath, FlagSkipValidate); err != nil { + if err := confix.Upgrade(ctx, plan(rawFile, targetVersion, configType), configPath, outputPath, FlagSkipValidate); err != nil { return fmt.Errorf("failed to migrate config: %w", err) } diff --git a/tools/confix/cmd/migrate_test.go b/tools/confix/cmd/migrate_test.go index e16134106f61..c2291f25b1a4 100644 --- a/tools/confix/cmd/migrate_test.go +++ b/tools/confix/cmd/migrate_test.go @@ -1,7 +1,7 @@ package cmd_test import ( - "fmt" + "path/filepath" "strings" "testing" @@ -9,30 +9,32 @@ import ( "cosmossdk.io/tools/confix/cmd" - "github.com/cosmos/cosmos-sdk/client" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" ) -func TestMigradeCmd(t *testing.T) { +func TestMigrateCmd(t *testing.T) { clientCtx, cleanup := initClientContext(t) defer cleanup() - _, err := clitestutil.ExecTestCLICmd(client.Context{}, cmd.MigrateCommand(), []string{"v0.0"}) - assert.ErrorContains(t, err, "must provide a path to the app.toml file") - - _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.0"}) + _, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.0","app"}) assert.ErrorContains(t, err, "unknown version") // clientCtx does not create app.toml, so this should fail - _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.45"}) + _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.45","app"}) assert.ErrorContains(t, err, "no such file or directory") // try to migrate from client.toml it should fail without --skip-validate - _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.46", fmt.Sprintf("%s/config/client.toml", clientCtx.HomeDir)}) + _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.46", filepath.Join(clientCtx.HomeDir, "config", "client.toml"), "app"}) assert.ErrorContains(t, err, "failed to migrate config") // try to migrate from client.toml - it should work and give us a big diff - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.46", fmt.Sprintf("%s/config/client.toml", clientCtx.HomeDir), "--skip-validate", "--verbose"}) + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.46", filepath.Join(clientCtx.HomeDir, "config", "client.toml"), "--skip-validate", "--verbose"}) assert.NilError(t, err) assert.Assert(t, strings.Contains(out.String(), "add app-db-backend key")) + + + // this should work + out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.MigrateCommand(), []string{"v0.51", filepath.Join(clientCtx.HomeDir, "config", "client.toml"),"client", "--verbose"}) + assert.NilError(t, err) + assert.Assert(t, strings.Contains(out.String(), "add keyring-default-keyname key")) } diff --git a/tools/confix/data/v0.47-client.toml b/tools/confix/data/v0.47-client.toml new file mode 100644 index 000000000000..d91250aebe78 --- /dev/null +++ b/tools/confix/data/v0.47-client.toml @@ -0,0 +1,17 @@ +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + +# The network chain ID +chain-id = "demo" +# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) +keyring-backend = "os" +# CLI output format (text|json) +output = "text" +# : to Tendermint RPC interface for this chain +node = "tcp://localhost:26657" +# Transaction broadcasting mode (sync|async|block) +broadcast-mode = "sync" \ No newline at end of file diff --git a/tools/confix/data/v0.50-client.toml b/tools/confix/data/v0.50-client.toml new file mode 100644 index 000000000000..d91250aebe78 --- /dev/null +++ b/tools/confix/data/v0.50-client.toml @@ -0,0 +1,17 @@ +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + +# The network chain ID +chain-id = "demo" +# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) +keyring-backend = "os" +# CLI output format (text|json) +output = "text" +# : to Tendermint RPC interface for this chain +node = "tcp://localhost:26657" +# Transaction broadcasting mode (sync|async|block) +broadcast-mode = "sync" \ No newline at end of file diff --git a/tools/confix/data/v0.51-client.toml b/tools/confix/data/v0.51-client.toml new file mode 100644 index 000000000000..a284426a8d04 --- /dev/null +++ b/tools/confix/data/v0.51-client.toml @@ -0,0 +1,19 @@ +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + +# The network chain ID +chain-id = "demo" +# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) +keyring-backend = "test" +# Default key name, if set, defines the default key to use for signing transaction when the --from flag is not specified +keyring-default-keyname = "" +# CLI output format (text|json) +output = "text" +# : to CometBFT RPC interface for this chain +node = "tcp://localhost:26657" +# Transaction broadcasting mode (sync|async) +broadcast-mode = "sync" diff --git a/tools/confix/file.go b/tools/confix/file.go index 2803c98fc92b..f6fd8dcad902 100644 --- a/tools/confix/file.go +++ b/tools/confix/file.go @@ -4,6 +4,8 @@ import ( "embed" "fmt" "os" + "path/filepath" + "strings" "github.com/creachadair/tomledit" ) @@ -11,11 +13,16 @@ import ( //go:embed data var data embed.FS -// LoadConfig loads and parses the TOML document from confix data -func LoadLocalConfig(name string) (*tomledit.Document, error) { - f, err := data.Open(fmt.Sprintf("data/%s-app.toml", name)) +// LoadLocalConfig loads and parses the TOML document from confix data +func LoadLocalConfig(name string, configType string) (*tomledit.Document, error) { + fileName, err := getFileName(name, configType) if err != nil { - panic(fmt.Errorf("failed to read file: %w. This file should have been included in confix", err)) + return nil, err + } + + f, err := data.Open(filepath.Join("data", fileName)) + if err != nil { + return nil, fmt.Errorf("failed to read file: %w. This file should have been included in confix", err) } defer f.Close() @@ -32,3 +39,15 @@ func LoadConfig(path string) (*tomledit.Document, error) { return tomledit.Parse(f) } + +// getFileName constructs the filename based on the type of configuration (app or client) +func getFileName(name string, configType string) (string, error) { + switch strings.ToLower(configType) { + case "app": + return fmt.Sprintf("%s-app.toml", name), nil + case "client": + return fmt.Sprintf("%s-client.toml", name), nil + default: + return "", fmt.Errorf("unsupported config type: %q", configType) + } +} diff --git a/tools/confix/migrations.go b/tools/confix/migrations.go index d5347c9bc301..91abd61fc626 100644 --- a/tools/confix/migrations.go +++ b/tools/confix/migrations.go @@ -11,28 +11,31 @@ import ( ) const ( - AppConfig = "app.toml" - ClientConfig = "client.toml" - CMTConfig = "config.toml" + AppConfig = "app.toml" + AppConfigType = "app" + ClientConfig = "client.toml" + ClientConfigType = "client" + CMTConfig = "config.toml" ) // MigrationMap defines a mapping from a version to a transformation plan. -type MigrationMap map[string]func(from *tomledit.Document, to string) transform.Plan +type MigrationMap map[string]func(from *tomledit.Document, to string, planType string) transform.Plan var Migrations = MigrationMap{ "v0.45": NoPlan, // Confix supports only the current supported SDK version. So we do not support v0.44 -> v0.45. "v0.46": PlanBuilder, "v0.47": PlanBuilder, "v0.50": PlanBuilder, + "v0.51": PlanBuilder, // "v0.xx.x": PlanBuilder, // add specific migration in case of configuration changes in minor versions } // PlanBuilder is a function that returns a transformation plan for a given diff between two files. -func PlanBuilder(from *tomledit.Document, to string) transform.Plan { +func PlanBuilder(from *tomledit.Document, to string, planType string) transform.Plan { plan := transform.Plan{} deletedSections := map[string]bool{} - target, err := LoadLocalConfig(to) + target, err := LoadLocalConfig(to, planType) if err != nil { panic(fmt.Errorf("failed to parse file: %w. This file should have been valid", err)) } @@ -115,7 +118,7 @@ func PlanBuilder(from *tomledit.Document, to string) transform.Plan { } // NoPlan returns a no-op plan. -func NoPlan(_ *tomledit.Document, to string) transform.Plan { +func NoPlan(_ *tomledit.Document, to string, planType string) transform.Plan { fmt.Printf("no migration needed to %s\n", to) return transform.Plan{} }