feat: create config fix tool (#14342)
This commit is contained in:
parent
edae9b99ab
commit
9742029158
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@ -44,6 +44,8 @@
|
||||
"C:Rosetta":
|
||||
- contrib/rosetta/**/*
|
||||
- tools/rosetta/**/*
|
||||
"C:Confix":
|
||||
- tools/confix/**/*
|
||||
"C:Keys":
|
||||
- client/keys/**/*
|
||||
"Type: Build":
|
||||
|
||||
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@ -35,15 +35,24 @@ jobs:
|
||||
**/go.sum
|
||||
**/Makefile
|
||||
Makefile
|
||||
###################
|
||||
#### Build App ####
|
||||
###################
|
||||
- name: Build
|
||||
if: env.GIT_DIFF
|
||||
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make build
|
||||
- name: Build Legacy
|
||||
if: env.GIT_DIFF
|
||||
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false COSMOS_BUILD_OPTIONS=legacy make build
|
||||
###################
|
||||
## Build Tooling ##
|
||||
###################
|
||||
- name: Build Cosmovisor
|
||||
if: env.GIT_DIFF
|
||||
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make cosmovisor
|
||||
- name: Build Rosetta
|
||||
if: env.GIT_DIFF
|
||||
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make rosetta
|
||||
- name: Build Confix
|
||||
if: env.GIT_DIFF
|
||||
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make confix
|
||||
|
||||
38
.github/workflows/release-confix.yml
vendored
Normal file
38
.github/workflows/release-confix.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
name: Release Confix
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "tools/confix/v*.*.*"
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
goreleaser:
|
||||
permissions:
|
||||
contents: write # for goreleaser/goreleaser-action to create a GitHub release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19.4
|
||||
# get 'v*.*.*' part from 'confix/v*.*.*' and save to $GITHUB_ENV
|
||||
- name: Set env
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/confix/}" >> $GITHUB_ENV
|
||||
# remove the possible pre-existing same tag for cosmos-sdk related tags instead of confix tags
|
||||
# Because goreleaser enforces semantic versioning and will error on non compliant tags.(https://goreleaser.com/limitations/semver/)
|
||||
- name: Tag without prefix locally to avoid error in goreleaser
|
||||
run: |-
|
||||
git tag -d ${{ env.RELEASE_VERSION }} || echo "No such a tag exists before"
|
||||
git tag ${{ env.RELEASE_VERSION }} HEAD
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
with:
|
||||
# stick to version v0.179.0(https://github.com/cosmos/cosmos-sdk/issues/11125)
|
||||
version: v0.179.0
|
||||
args: release --rm-dist --skip-validate --release-notes ./RELEASE_NOTES.md
|
||||
workdir: tools/confix
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GORELEASER_CURRENT_TAG: confix/${{ env.RELEASE_VERSION }}
|
||||
30
.github/workflows/test.yml
vendored
30
.github/workflows/test.yml
vendored
@ -581,3 +581,33 @@ jobs:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_X_NFT }}
|
||||
with:
|
||||
projectBaseDir: x/nft/
|
||||
|
||||
test-confix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19.4
|
||||
cache: true
|
||||
cache-dependency-path: tools/confix/go.sum
|
||||
- uses: technote-space/get-diff-action@v6.1.2
|
||||
id: git_diff
|
||||
with:
|
||||
PATTERNS: |
|
||||
tools/confix/**/*.go
|
||||
tools/confix/go.mod
|
||||
tools/confix/go.sum
|
||||
- name: tests
|
||||
if: env.GIT_DIFF
|
||||
run: |
|
||||
cd tools/confix
|
||||
go test -mod=readonly -timeout 30m -coverprofile=coverage.out -covermode=atomic -tags='norace ledger test_ledger_mock rocksdb_build' ./...
|
||||
- name: sonarcloud
|
||||
if: env.GIT_DIFF
|
||||
uses: SonarSource/sonarcloud-github-action@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_CONFIX }}
|
||||
with:
|
||||
projectBaseDir: tools/confix/
|
||||
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Features
|
||||
|
||||
* (client) [#14342](https://github.com/cosmos/cosmos-sdk/pull/14342) Add `simd config` command is now a sub-command, for setting, getting and migrating Cosmos SDK configuration files.
|
||||
* (query) [#14468](https://github.com/cosmos/cosmos-sdk/pull/14468) Implement pagination for collections.
|
||||
* (x/bank) [#14045](https://github.com/cosmos/cosmos-sdk/pull/14045) Add CLI command `spendable-balances`, which also accepts the flag `--denom`.
|
||||
* (x/slashing, x/staking) [#14363](https://github.com/cosmos/cosmos-sdk/pull/14363) Add the infraction a validator commited type as an argument to a `SlashWithInfractionReason` keeper method.
|
||||
@ -117,10 +118,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* [#13881](https://github.com/cosmos/cosmos-sdk/pull/13881) Optimize iteration on nested cached KV stores and other operations in general.
|
||||
* (x/gov) [#14347](https://github.com/cosmos/cosmos-sdk/pull/14347) Support `v1.Proposal` message in `v1beta1.Proposal.Content`.
|
||||
* (x/gov) [#14390](https://github.com/cosmos/cosmos-sdk/pull/14390) Add title, proposer and summary to proposal struct
|
||||
* (baseapp) [#14417](https://github.com/cosmos/cosmos-sdk/pull/14417) `SetStreamingService` accepts appOptions, AppCodec and Storekeys needed to set streamers.
|
||||
* Store pacakge no longer has a dependency on baseapp.
|
||||
* (store) [#14438](https://github.com/cosmos/cosmos-sdk/pull/14438) Pass logger from baseapp to store.
|
||||
* (store) [#14439](https://github.com/cosmos/cosmos-sdk/pull/14439) Remove global metric gatherer from store.
|
||||
* (baseapp) [#14417](https://github.com/cosmos/cosmos-sdk/pull/14417) `SetStreamingService` accepts appOptions, AppCodec and Storekeys needed to set streamers.
|
||||
* Store pacakge no longer has a dependency on baseapp.
|
||||
* (store) [#14438](https://github.com/cosmos/cosmos-sdk/pull/14438) Pass logger from baseapp to store.
|
||||
* (store) [#14439](https://github.com/cosmos/cosmos-sdk/pull/14439) Remove global metric gatherer from store.
|
||||
* By default store has a no op metric gatherer, the application developer must set another metric gatherer or us the provided one in `store/metrics`.
|
||||
|
||||
### State Machine Breaking
|
||||
@ -212,6 +213,7 @@ extension interfaces. `module.Manager.Modules` is now of type `map[string]interf
|
||||
|
||||
### CLI Breaking Changes
|
||||
|
||||
* (client) [#14342](https://github.com/cosmos/cosmos-sdk/pull/14342) `simd config` command is now a sub-command. Use `simd config --help` to learn more.
|
||||
* (x/genutil) [#13535](https://github.com/cosmos/cosmos-sdk/pull/13535) Replace in `simd init`, the `--staking-bond-denom` flag with `--default-denom` which is used for all default denomination in the genesis, instead of only staking.
|
||||
* (tx) [#12659](https://github.com/cosmos/cosmos-sdk/pull/12659) Remove broadcast mode `block`.
|
||||
* (genesis) [#14149](https://github.com/cosmos/cosmos-sdk/pull/14149) Add `simd genesis` command, which contains all genesis-related sub-commands.
|
||||
|
||||
5
Makefile
5
Makefile
@ -140,7 +140,10 @@ cosmovisor:
|
||||
rosetta:
|
||||
$(MAKE) -C tools/rosetta rosetta
|
||||
|
||||
.PHONY: build build-linux-amd64 build-linux-arm64 cosmovisor rosetta
|
||||
confix:
|
||||
$(MAKE) -C tools/confix confix
|
||||
|
||||
.PHONY: build build-linux-amd64 build-linux-arm64 cosmovisor rosetta confix
|
||||
|
||||
|
||||
mocks: $(MOCKS_DIR)
|
||||
|
||||
@ -1,97 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
)
|
||||
|
||||
// Cmd returns a CLI command to interactively create an application CLI
|
||||
// config file.
|
||||
func Cmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "config <key> [value]",
|
||||
Short: "Create or query an application CLI configuration file",
|
||||
RunE: runConfigCmd,
|
||||
Args: cobra.RangeArgs(0, 2),
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runConfigCmd(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
configPath := filepath.Join(clientCtx.HomeDir, "config")
|
||||
|
||||
conf, err := getClientConfig(configPath, clientCtx.Viper)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't get client config: %v", err)
|
||||
}
|
||||
|
||||
switch len(args) {
|
||||
case 0:
|
||||
// print all client config fields to stdout
|
||||
s, err := json.MarshalIndent(conf, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Println(string(s))
|
||||
|
||||
case 1:
|
||||
// it's a get
|
||||
key := args[0]
|
||||
|
||||
switch key {
|
||||
case flags.FlagChainID:
|
||||
cmd.Println(conf.ChainID)
|
||||
case flags.FlagKeyringBackend:
|
||||
cmd.Println(conf.KeyringBackend)
|
||||
case flags.FlagOutput:
|
||||
cmd.Println(conf.Output)
|
||||
case flags.FlagNode:
|
||||
cmd.Println(conf.Node)
|
||||
case flags.FlagBroadcastMode:
|
||||
cmd.Println(conf.BroadcastMode)
|
||||
default:
|
||||
err := errUnknownConfigKey(key)
|
||||
return fmt.Errorf("couldn't get the value for the key: %v, error: %v", key, err)
|
||||
}
|
||||
|
||||
case 2:
|
||||
// it's set
|
||||
key, value := args[0], args[1]
|
||||
|
||||
switch key {
|
||||
case flags.FlagChainID:
|
||||
conf.SetChainID(value)
|
||||
case flags.FlagKeyringBackend:
|
||||
conf.SetKeyringBackend(value)
|
||||
case flags.FlagOutput:
|
||||
conf.SetOutput(value)
|
||||
case flags.FlagNode:
|
||||
conf.SetNode(value)
|
||||
case flags.FlagBroadcastMode:
|
||||
conf.SetBroadcastMode(value)
|
||||
default:
|
||||
return errUnknownConfigKey(key)
|
||||
}
|
||||
|
||||
confFile := filepath.Join(configPath, "client.toml")
|
||||
if err := writeConfigToFile(confFile, conf); err != nil {
|
||||
return fmt.Errorf("could not write client config to the file: %v", err)
|
||||
}
|
||||
|
||||
default:
|
||||
panic("cound not execute config command")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func errUnknownConfigKey(key string) error {
|
||||
return fmt.Errorf("unknown configuration key: %q", key)
|
||||
}
|
||||
@ -8,14 +8,15 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// Default constants
|
||||
const (
|
||||
chainID = ""
|
||||
keyringBackend = "os"
|
||||
output = "text"
|
||||
node = "tcp://localhost:26657"
|
||||
broadcastMode = "sync"
|
||||
)
|
||||
func DefaultConfig() *ClientConfig {
|
||||
return &ClientConfig{
|
||||
ChainID: "",
|
||||
KeyringBackend: "os",
|
||||
Output: "text",
|
||||
Node: "tcp://localhost:26657",
|
||||
BroadcastMode: "sync",
|
||||
}
|
||||
}
|
||||
|
||||
type ClientConfig struct {
|
||||
ChainID string `mapstructure:"chain-id" json:"chain-id"`
|
||||
@ -25,11 +26,6 @@ type ClientConfig struct {
|
||||
BroadcastMode string `mapstructure:"broadcast-mode" json:"broadcast-mode"`
|
||||
}
|
||||
|
||||
// defaultClientConfig returns the reference to ClientConfig with default values.
|
||||
func defaultClientConfig() *ClientConfig {
|
||||
return &ClientConfig{chainID, keyringBackend, output, node, broadcastMode}
|
||||
}
|
||||
|
||||
func (c *ClientConfig) SetChainID(chainID string) {
|
||||
c.ChainID = chainID
|
||||
}
|
||||
@ -54,11 +50,11 @@ func (c *ClientConfig) SetBroadcastMode(broadcastMode string) {
|
||||
func ReadFromClientConfig(ctx client.Context) (client.Context, error) {
|
||||
configPath := filepath.Join(ctx.HomeDir, "config")
|
||||
configFilePath := filepath.Join(configPath, "client.toml")
|
||||
conf := defaultClientConfig()
|
||||
conf := DefaultConfig()
|
||||
|
||||
// if config.toml file does not exist we create it and write default ClientConfig values into it.
|
||||
// when config.toml does not exist create and init with default values
|
||||
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
|
||||
if err := ensureConfigPath(configPath); err != nil {
|
||||
if err := os.MkdirAll(configPath, os.ModePerm); err != nil {
|
||||
return ctx, fmt.Errorf("couldn't make client config: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
@ -13,7 +11,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking/client/cli"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -45,68 +43,52 @@ func initClientContext(t *testing.T, envVar string) (client.Context, func()) {
|
||||
return clientCtx, func() { _ = os.RemoveAll(home) }
|
||||
}
|
||||
|
||||
func TestConfigCmd(t *testing.T) {
|
||||
clientCtx, cleanup := initClientContext(t, testNode1)
|
||||
defer func() {
|
||||
_ = os.Unsetenv(nodeEnv)
|
||||
cleanup()
|
||||
}()
|
||||
|
||||
// NODE=http://localhost:1 ./build/simd config node http://localhost:2
|
||||
cmd := config.Cmd()
|
||||
args := []string{"node", testNode2}
|
||||
_, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// ./build/simd config node //http://localhost:1
|
||||
b := bytes.NewBufferString("")
|
||||
cmd.SetOut(b)
|
||||
cmd.SetArgs([]string{"node"})
|
||||
require.NoError(t, cmd.Execute())
|
||||
out, err := io.ReadAll(b)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, string(out), testNode1+"\n")
|
||||
}
|
||||
|
||||
func TestConfigCmdEnvFlag(t *testing.T) {
|
||||
const (
|
||||
defaultNode = "http://localhost:26657"
|
||||
)
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
envVar string
|
||||
args []string
|
||||
expNode string
|
||||
}{
|
||||
{"env var is set with no flag", testNode1, []string{"validators"}, testNode1},
|
||||
{"env var is set with a flag", testNode1, []string{"validators", fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2},
|
||||
{"env var is not set with no flag", "", []string{"validators"}, defaultNode},
|
||||
{"env var is not set with a flag", "", []string{"validators", fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2},
|
||||
{"env var is set with no flag", testNode1, []string{}, testNode1},
|
||||
{"env var is set with a flag", testNode1, []string{fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2},
|
||||
{"env var is not set with no flag", "", []string{}, "tcp://localhost:26657"},
|
||||
{"env var is not set with a flag", "", []string{fmt.Sprintf("--%s=%s", flags.FlagNode, testNode2)}, testNode2},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testCmd := &cobra.Command{
|
||||
Use: "test",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s", clientCtx.NodeURI)
|
||||
},
|
||||
}
|
||||
flags.AddQueryFlagsToCmd(testCmd)
|
||||
|
||||
clientCtx, cleanup := initClientContext(t, tc.envVar)
|
||||
defer func() {
|
||||
if tc.envVar != "" {
|
||||
_ = os.Unsetenv(nodeEnv)
|
||||
}
|
||||
cleanup()
|
||||
_ = os.Unsetenv(nodeEnv)
|
||||
}()
|
||||
/*
|
||||
env var is set with a flag
|
||||
|
||||
NODE=http://localhost:1 ./build/simd q staking validators --node http://localhost:2
|
||||
Error: post failed: Post "http://localhost:2": dial tcp 127.0.0.1:2: connect: connection refused
|
||||
NODE=http://localhost:1 test-cmd --node http://localhost:2
|
||||
Prints "http://localhost:2"
|
||||
|
||||
We dial http://localhost:2 cause a flag has the higher priority than env variable.
|
||||
It prints http://localhost:2 cause a flag has the higher priority than env variable.
|
||||
*/
|
||||
cmd := cli.GetQueryCmd()
|
||||
_, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
|
||||
|
||||
_, err := clitestutil.ExecTestCLICmd(clientCtx, testCmd, tc.args)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expNode, "Output does not contain expected Node")
|
||||
require.Contains(t, err.Error(), tc.expNode)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,11 +45,6 @@ func writeConfigToFile(configFilePath string, config *ClientConfig) error {
|
||||
return os.WriteFile(configFilePath, buffer.Bytes(), 0o600)
|
||||
}
|
||||
|
||||
// ensureConfigPath creates a directory configPath if it does not exist
|
||||
func ensureConfigPath(configPath string) error {
|
||||
return os.MkdirAll(configPath, os.ModePerm)
|
||||
}
|
||||
|
||||
// getClientConfig reads values from client.toml file and unmarshalls them into ClientConfig
|
||||
func getClientConfig(configPath string, v *viper.Viper) (*ClientConfig, error) {
|
||||
v.AddConfigPath(configPath)
|
||||
@ -60,7 +55,7 @@ func getClientConfig(configPath string, v *viper.Viper) (*ClientConfig, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conf := new(ClientConfig)
|
||||
conf := DefaultConfig()
|
||||
if err := v.Unmarshal(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
1
docs/.gitignore
vendored
1
docs/.gitignore
vendored
@ -15,6 +15,7 @@ docs/docs/spec
|
||||
docs/docs/architecture
|
||||
docs/docs/tooling/01-cosmovisor.md
|
||||
docs/docs/tooling/02-depinject.md
|
||||
docs/docs/tooling/03-confix.md
|
||||
docs/run-node/04-rosetta.md
|
||||
|
||||
# Misc
|
||||
|
||||
@ -9,3 +9,4 @@ This section provides documentation on various tooling used in development of a
|
||||
* [Protocol Buffers](./00-protobuf.md)
|
||||
* [Cosmovisor](./01-cosmovisor.md)
|
||||
* [Depinject](./02-depinject.md)
|
||||
* [Confix](./03-confix.md)
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
find docs/modules ! -name '_category_.json' -type f -exec rm -rf {} +
|
||||
rm -rf docs/tooling/01-cosmovisor.md
|
||||
rm -rf docs/tooling/02-depinject.md
|
||||
rm -rf docs/tooling/03-confix.md
|
||||
rm -rf docs/run-node/04-rosetta.md
|
||||
rm -rf docs/architecture
|
||||
rm -rf docs/spec
|
||||
|
||||
@ -17,10 +17,9 @@ cp ../x/auth/tx/README.md ./docs/modules/auth/2-tx.md
|
||||
## Add modules page list
|
||||
cat ../x/README.md | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./docs/modules/README.md
|
||||
|
||||
## Add cosmovisor documentation
|
||||
## Add tooling documentation
|
||||
cp ../tools/cosmovisor/README.md ./docs/tooling/01-cosmovisor.md
|
||||
|
||||
## Add depinject documentation
|
||||
cp ../tools/confix/README.md ./docs/tooling/03-confix.md
|
||||
cp ../depinject/README.md ./docs/tooling/02-depinject.md
|
||||
|
||||
## Add rosetta documentation
|
||||
|
||||
@ -15,5 +15,6 @@ use (
|
||||
./tests
|
||||
./tools/rosetta
|
||||
./tools/cosmovisor
|
||||
./tools/confix
|
||||
./x/nft
|
||||
)
|
||||
|
||||
@ -8,10 +8,11 @@ require (
|
||||
cosmossdk.io/core v0.4.0
|
||||
cosmossdk.io/depinject v1.0.0-alpha.3
|
||||
cosmossdk.io/math v1.0.0-beta.4
|
||||
cosmossdk.io/tools/confix v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/tools/rosetta v0.2.0
|
||||
github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32
|
||||
// this version is not used as it is always replaced by the latest cosmos-sdk version
|
||||
github.com/cosmos/cosmos-sdk v0.47.0-alpha2.0.20221219231612-5ed4075ba219
|
||||
github.com/cosmos/cosmos-sdk v0.47.0-rc1
|
||||
github.com/cosmos/cosmos-sdk/x/nft v0.1.0-alpha1
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/spf13/cast v1.5.0
|
||||
@ -62,7 +63,9 @@ require (
|
||||
github.com/cosmos/iavl v0.20.0-alpha1 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect
|
||||
github.com/cosmos/rosetta-sdk-go v0.9.0 // indirect
|
||||
github.com/creachadair/atomicfile v0.2.7 // indirect
|
||||
github.com/creachadair/taskgroup v0.3.2 // indirect
|
||||
github.com/creachadair/tomledit v0.0.24 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
@ -181,6 +184,8 @@ require (
|
||||
)
|
||||
|
||||
replace (
|
||||
// todo remove at pseudo version of confix
|
||||
cosmossdk.io/tools/confix => ../tools/confix
|
||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
|
||||
// Simapp always use the latest version of the cosmos-sdk
|
||||
github.com/cosmos/cosmos-sdk => ../.
|
||||
|
||||
@ -218,8 +218,12 @@ github.com/cosmos/rosetta-sdk-go v0.9.0/go.mod h1:2v41yXL25xxAXrczVSnbDHcQH9Cgil
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creachadair/atomicfile v0.2.7 h1:LiL/QmAUO7ZDsjSJ6xj3PlsXaYXYKMS8g/Po5S9IIk4=
|
||||
github.com/creachadair/atomicfile v0.2.7/go.mod h1:BRq8Une6ckFneYXZQ+kO7p1ZZP3I2fzVzf28JxrIkBc=
|
||||
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
||||
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
|
||||
github.com/creachadair/tomledit v0.0.24 h1:5Xjr25R2esu1rKCbQEmjZYlrhFkDspoAbAKb6QKQDhQ=
|
||||
github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cucumber/common/gherkin/go/v22 v22.0.0 h1:4K8NqptbvdOrjL9DEea6HFjSpbdT9+Q5kgLpmmsHYl0=
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
|
||||
"cosmossdk.io/simapp"
|
||||
"cosmossdk.io/simapp/params"
|
||||
confixcmd "cosmossdk.io/tools/confix/cmd"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
@ -174,7 +175,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
|
||||
genutilcli.InitCmd(simapp.ModuleBasics, simapp.DefaultNodeHome),
|
||||
NewTestnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}),
|
||||
debug.Cmd(),
|
||||
config.Cmd(),
|
||||
confixcmd.ConfigCommand(),
|
||||
pruning.Cmd(newApp),
|
||||
)
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ require (
|
||||
cosmossdk.io/simapp v0.0.0-00010101000000-000000000000
|
||||
github.com/cosmos/cosmos-db v0.0.0-20221226095112-f3c38ecb5e32
|
||||
// this version is not used as it is always replaced by the latest cosmos-sdk version
|
||||
github.com/cosmos/cosmos-sdk v0.47.0-alpha2.0.20221219231612-5ed4075ba219
|
||||
github.com/cosmos/cosmos-sdk v0.47.0-rc1
|
||||
github.com/cosmos/cosmos-sdk/x/nft v0.1.0-alpha1
|
||||
github.com/cosmos/gogoproto v1.4.3
|
||||
github.com/golang/mock v1.6.0
|
||||
|
||||
2
tools/confix/.gitignore
vendored
Normal file
2
tools/confix/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/confix
|
||||
/condiff
|
||||
34
tools/confix/.goreleaser.yml
Normal file
34
tools/confix/.goreleaser.yml
Normal file
@ -0,0 +1,34 @@
|
||||
project_name: confix
|
||||
|
||||
release:
|
||||
disable: false
|
||||
name_template: "{{.Tag}}"
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- go mod tidy
|
||||
|
||||
builds:
|
||||
- main: ./cmd/confix
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
||||
archives:
|
||||
- name_template: '{{ replace .Version "confix/" "confix-" }}-{{ .Os }}-{{ .Arch }}'
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
|
||||
checksum:
|
||||
name_template: 'SHA256SUMS-{{ replace .Version "confix/" "confix-" }}.txt'
|
||||
algorithm: sha256
|
||||
|
||||
changelog:
|
||||
skip: false
|
||||
34
tools/confix/CHANGELOG.md
Normal file
34
tools/confix/CHANGELOG.md
Normal file
@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Guiding Principles:
|
||||
|
||||
Changelogs are for humans, not machines.
|
||||
There should be an entry for every single version.
|
||||
The same types of changes should be grouped.
|
||||
Versions and sections should be linkable.
|
||||
The latest version comes first.
|
||||
The release date of each version is displayed.
|
||||
Mention whether you follow Semantic Versioning.
|
||||
|
||||
Usage:
|
||||
|
||||
Change log entries are to be added to the Unreleased section under the
|
||||
appropriate stanza (see below). Each entry should ideally include a tag and
|
||||
the Github issue reference in the following format:
|
||||
|
||||
* (<tag>) [#<issue-number>] Changelog message.
|
||||
|
||||
Types of changes (Stanzas):
|
||||
|
||||
"Features" for new features.
|
||||
"Improvements" for changes in existing functionality.
|
||||
"Deprecated" for soon-to-be removed features.
|
||||
"Bug Fixes" for any bug fixes.
|
||||
"API Breaking" for breaking exported APIs used by developers building on SDK.
|
||||
Ref: https://keepachangelog.com/en/1.0.0/
|
||||
-->
|
||||
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
* [#14342](https://github.com/cosmos/cosmos-sdk/pull/14342) Add `confix` tool to manage configuration files.
|
||||
14
tools/confix/Makefile
Normal file
14
tools/confix/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
all: confix condiff test
|
||||
|
||||
confix:
|
||||
go build -mod=readonly ./cmd/confix
|
||||
|
||||
condiff:
|
||||
go build -mod=readonly ./cmd/condiff
|
||||
|
||||
test:
|
||||
go test -mod=readonly -race ./...
|
||||
|
||||
.PHONY: all confix condiff test
|
||||
74
tools/confix/README.md
Normal file
74
tools/confix/README.md
Normal file
@ -0,0 +1,74 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# Confix
|
||||
|
||||
`Confix` is a configuration management tool that allows you to manage your configuration via CLI.
|
||||
|
||||
It is based on the [Tendermint RFC 019](https://github.com/tendermint/tendermint/blob/5013bc3f4a6d64dcc2bf02ccc002ebc9881c62e4/docs/rfc/rfc-019-config-version.md).
|
||||
|
||||
## Installation
|
||||
|
||||
## Usage
|
||||
|
||||
Use standalone:
|
||||
|
||||
```shell
|
||||
confix --help
|
||||
```
|
||||
|
||||
Use in simd:
|
||||
|
||||
```shell
|
||||
simd config fix --help
|
||||
```
|
||||
|
||||
### Get
|
||||
|
||||
Get a configuration value, e.g.:
|
||||
|
||||
```shell
|
||||
simd config get app pruning # gets the value pruning from app.toml
|
||||
simd config get client chain-id # gets the value chain-id from client.toml
|
||||
```
|
||||
|
||||
```shell
|
||||
confix get ~/.simapp/config/app.toml pruning # gets the value pruning from app.toml
|
||||
confix get ~/.simapp/config/client.toml chain-id # gets the value chain-id from client.toml
|
||||
```
|
||||
|
||||
### Set
|
||||
|
||||
Set a configuration value, e.g.:
|
||||
|
||||
```shell
|
||||
simd config set app pruning "enabled" # sets the value pruning from app.toml
|
||||
simd config set client chain-id "foo-1" # sets the value chain-id from client.toml
|
||||
```
|
||||
|
||||
```shell
|
||||
confix set ~/.simapp/config/app.toml pruning "enabled" # sets the value pruning from app.toml
|
||||
confix set ~/.simapp/config/client.toml chain-id "foo-1" # sets the value chain-id from client.toml
|
||||
```
|
||||
|
||||
### Migrate
|
||||
|
||||
Migrate a configuration file to a new version, e.g.:
|
||||
|
||||
```shell
|
||||
simd config migrate v0.47 # 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
|
||||
```
|
||||
|
||||
### Maintainer
|
||||
|
||||
At each SDK modification of the default configuration, add the default SDK config under `data/v0.XX-app.toml`.
|
||||
This allows users to use the tool standalone.
|
||||
|
||||
## Credits
|
||||
|
||||
This project is based on the [Tendermint RFC 019](https://github.com/tendermint/tendermint/blob/5013bc3f4a6d64dcc2bf02ccc002ebc9881c62e4/docs/rfc/rfc-019-config-version.md) and their own implementation of [confix](https://github.com/tendermint/tendermint/blob/v0.36.x/scripts/confix/confix.go).
|
||||
43
tools/confix/cmd/condiff/main.go
Normal file
43
tools/confix/cmd/condiff/main.go
Normal file
@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/tools/confix"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd := &cobra.Command{
|
||||
Use: "condiff f1 f2",
|
||||
Short: "Diff the keyspaces of the TOML documents in files f1 and f2",
|
||||
Long: `Diff the keyspaces of the TOML documents in files f1 and f2.
|
||||
The output prints one line per key that differs:
|
||||
|
||||
-S name -- section exists in f1 but not f2
|
||||
+S name -- section exists in f2 but not f1
|
||||
-M name -- mapping exists in f1 but not f2
|
||||
+M name -- mapping exists in f2 but not f1
|
||||
|
||||
Comments, order, and values are ignored for comparison purposes.`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
lhs, err := confix.LoadConfig(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rhs, err := confix.LoadConfig(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
confix.PrintDiff(cmd.OutOrStdout(), confix.DiffKeys(lhs, rhs))
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
23
tools/confix/cmd/config.go
Normal file
23
tools/confix/cmd/config.go
Normal file
@ -0,0 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// ConfigComamnd contains all the confix commands
|
||||
// These command can be used to interactively update an application config value.
|
||||
func ConfigCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Utilities for managing application configuration",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
MigrateCommand(),
|
||||
DiffCommand(),
|
||||
GetCommand(),
|
||||
SetCommand(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
13
tools/confix/cmd/confix/main.go
Normal file
13
tools/confix/cmd/confix/main.go
Normal file
@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
confixcmd "cosmossdk.io/tools/confix/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := confixcmd.ConfigCommand().Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
17
tools/confix/cmd/diff.go
Normal file
17
tools/confix/cmd/diff.go
Normal file
@ -0,0 +1,17 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func DiffCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "diff [config]",
|
||||
Short: "Display the diff between the current config and the SDK default config",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// TODO to implement in the next PR
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
73
tools/confix/cmd/migrate.go
Normal file
73
tools/confix/cmd/migrate.go
Normal file
@ -0,0 +1,73 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/tools/confix"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
var (
|
||||
FlagStdOut bool
|
||||
FlagVerbose bool
|
||||
FlagSkipValidate bool
|
||||
)
|
||||
|
||||
func MigrateCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "migrate [target-version] <app-toml-path> (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.
|
||||
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
|
||||
targetVersion := args[0]
|
||||
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
if len(args) > 1 {
|
||||
filename = args[1]
|
||||
} else if clientCtx.HomeDir != "" {
|
||||
filename = fmt.Sprintf("%s/config/app.toml", clientCtx.HomeDir)
|
||||
} else {
|
||||
return fmt.Errorf("must provide a path to the app.toml file")
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load config: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
if FlagVerbose {
|
||||
ctx = confix.WithLogWriter(ctx, cmd.ErrOrStderr())
|
||||
}
|
||||
|
||||
outputPath := filename
|
||||
if FlagStdOut {
|
||||
outputPath = ""
|
||||
}
|
||||
|
||||
if err := confix.Upgrade(ctx, plan(rawFile, targetVersion), filename, outputPath, FlagSkipValidate); err != nil {
|
||||
return fmt.Errorf("failed to migrate config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&FlagStdOut, "stdout", false, "print the updated config to stdout")
|
||||
cmd.Flags().BoolVar(&FlagVerbose, "verbose", false, "log changes to stderr")
|
||||
cmd.Flags().BoolVar(&FlagSkipValidate, "skip-validate", false, "skip configuration validation (allows to migrate unknown configurations)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
36
tools/confix/cmd/migrate_test.go
Normal file
36
tools/confix/cmd/migrate_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package cmd_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/tools/confix/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestMigradeCmd(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"})
|
||||
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"})
|
||||
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)})
|
||||
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"})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, strings.Contains(out.String(), "add app-db-backend key"))
|
||||
}
|
||||
119
tools/confix/cmd/mutate.go
Normal file
119
tools/confix/cmd/mutate.go
Normal file
@ -0,0 +1,119 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"cosmossdk.io/tools/confix"
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/creachadair/tomledit/parser"
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// SetCommand returns a CLI command to interactively update an application config value.
|
||||
func SetCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "set [config] [key] [value]",
|
||||
Short: "Set an application config value",
|
||||
Long: "Set an application config value. The [config] argument must be the path of the file when using the too standalone, otherwise it must be the name of the config file without the .toml extension.",
|
||||
Args: cobra.ExactArgs(3),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
filename, inputValue := args[0], args[2]
|
||||
// parse key e.g mempool.size -> [mempool, size]
|
||||
key := strings.Split(args[1], ".")
|
||||
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
if clientCtx.HomeDir != "" {
|
||||
filename = fmt.Sprintf("%s/config/%s.toml", clientCtx.HomeDir, filename)
|
||||
}
|
||||
|
||||
plan := transform.Plan{
|
||||
{
|
||||
Desc: fmt.Sprintf("update %q=%q in %s", key, inputValue, filename),
|
||||
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
|
||||
results := doc.Find(key...)
|
||||
if len(results) == 0 {
|
||||
return fmt.Errorf("key %q not found", key)
|
||||
} else if len(results) > 1 {
|
||||
return fmt.Errorf("key %q is ambiguous", key)
|
||||
}
|
||||
|
||||
value, err := parser.ParseValue(inputValue)
|
||||
if err != nil {
|
||||
value = parser.MustValue(`"` + inputValue + `"`)
|
||||
}
|
||||
|
||||
if ok := transform.InsertMapping(results[0].Section, &parser.KeyValue{
|
||||
Block: results[0].Block,
|
||||
Name: key,
|
||||
Value: value,
|
||||
}, true); !ok {
|
||||
return errors.New("failed to set value")
|
||||
}
|
||||
|
||||
return nil
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
outputPath := filename
|
||||
if FlagStdOut {
|
||||
outputPath = ""
|
||||
}
|
||||
|
||||
ctx := cmd.Context()
|
||||
if FlagVerbose {
|
||||
ctx = confix.WithLogWriter(ctx, cmd.ErrOrStderr())
|
||||
}
|
||||
|
||||
return confix.Upgrade(ctx, plan, filename, outputPath, FlagSkipValidate)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&FlagStdOut, "stdout", false, "print the updated config to stdout")
|
||||
cmd.Flags().BoolVar(&FlagVerbose, "verbose", false, "log changes to stderr")
|
||||
cmd.Flags().BoolVar(&FlagSkipValidate, "skip-validate", false, "skip configuration validation (allows to mutate unknown configurations)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetCommand returns a CLI command to interactively get an application config value.
|
||||
func GetCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "get [config] [key]",
|
||||
Short: "Get an application config value",
|
||||
Long: "Get an application config value. The [config] argument must be the path of the file when using the too standalone, otherwise it must be the name of the config file without the .toml extension.",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
filename, key := args[0], args[1]
|
||||
// parse key e.g mempool.size -> [mempool, size]
|
||||
keys := strings.Split(key, ".")
|
||||
|
||||
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||
if clientCtx.HomeDir != "" {
|
||||
filename = fmt.Sprintf("%s/config/%s.toml", clientCtx.HomeDir, filename)
|
||||
}
|
||||
|
||||
doc, err := confix.LoadConfig(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load config: %w", err)
|
||||
}
|
||||
|
||||
results := doc.Find(keys...)
|
||||
if len(results) == 0 {
|
||||
return fmt.Errorf("key %q not found", key)
|
||||
} else if len(results) > 1 {
|
||||
return fmt.Errorf("key %q is ambiguous", key)
|
||||
}
|
||||
|
||||
return clientCtx.PrintString(fmt.Sprintf("%s\n", results[0].Value.String()))
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
63
tools/confix/cmd/mutate_test.go
Normal file
63
tools/confix/cmd/mutate_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package cmd_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/tools/confix/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
// initClientContext initiates client Context for tests
|
||||
func initClientContext(t *testing.T) (client.Context, func()) {
|
||||
home := t.TempDir()
|
||||
chainId := "test-chain" //nolint:revive
|
||||
clientCtx := client.Context{}.
|
||||
WithHomeDir(home).
|
||||
WithViper("").
|
||||
WithChainID(chainId)
|
||||
clientCtx, err := config.ReadFromClientConfig(clientCtx)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, clientCtx.ChainID, chainId)
|
||||
return clientCtx, func() { _ = os.RemoveAll(home) }
|
||||
}
|
||||
|
||||
func TestSetCmd(t *testing.T) {
|
||||
clientCtx, cleanup := initClientContext(t)
|
||||
defer cleanup()
|
||||
|
||||
_, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.SetCommand(), []string{"unexisting", "foo", "foo"})
|
||||
assert.ErrorContains(t, err, "no such file or directory")
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.GetCommand(), []string{"client", "chain-id"})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(out.String()), `"test-chain"`)
|
||||
|
||||
newValue := "new-chain"
|
||||
_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.SetCommand(), []string{"client", "chain-id", newValue})
|
||||
assert.NilError(t, err)
|
||||
|
||||
out, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.GetCommand(), []string{"client", "chain-id"})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(out.String()), fmt.Sprintf(`"%s"`, newValue))
|
||||
}
|
||||
|
||||
func TestGetCmd(t *testing.T) {
|
||||
clientCtx, cleanup := initClientContext(t)
|
||||
defer cleanup()
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd.GetCommand(), []string{"client", "chain-id"})
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(out.String()), `"test-chain"`)
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.GetCommand(), []string{"client", "foo"})
|
||||
assert.Error(t, err, `key "foo" not found`)
|
||||
|
||||
_, err = clitestutil.ExecTestCLICmd(clientCtx, cmd.GetCommand(), []string{"unexisting", "foo"})
|
||||
assert.ErrorContains(t, err, "no such file or directory")
|
||||
}
|
||||
230
tools/confix/data/v0.45-app.toml
Normal file
230
tools/confix/data/v0.45-app.toml
Normal file
@ -0,0 +1,230 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
###############################################################################
|
||||
### Base Configuration ###
|
||||
###############################################################################
|
||||
|
||||
# The minimum gas prices a validator is willing to accept for processing a
|
||||
# transaction. A transaction's fees must meet the minimum of any denomination
|
||||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "0stake"
|
||||
|
||||
# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
|
||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
# everything: all saved states will be deleted, storing only the current and previous state; pruning at 10 block intervals
|
||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
|
||||
pruning = "default"
|
||||
|
||||
# These are applied if and only if the pruning strategy is custom.
|
||||
pruning-keep-recent = "0"
|
||||
pruning-keep-every = "0"
|
||||
pruning-interval = "0"
|
||||
|
||||
# HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
# halt and shutdown that can be used to assist upgrades and testing.
|
||||
#
|
||||
# Note: Commitment of state will be attempted on the corresponding block.
|
||||
halt-height = 0
|
||||
|
||||
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
|
||||
# a node will gracefully halt and shutdown that can be used to assist upgrades
|
||||
# and testing.
|
||||
#
|
||||
# Note: Commitment of state will be attempted on the corresponding block.
|
||||
halt-time = 0
|
||||
|
||||
# MinRetainBlocks defines the minimum block height offset from the current
|
||||
# block being committed, such that all blocks past this offset are pruned
|
||||
# from Tendermint. It is used as part of the process of determining the
|
||||
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
|
||||
# that no blocks should be pruned.
|
||||
#
|
||||
# This configuration value is only responsible for pruning Tendermint blocks.
|
||||
# It has no bearing on application state pruning which is determined by the
|
||||
# "pruning-*" configurations.
|
||||
#
|
||||
# Note: Tendermint block pruning is dependant on this parameter in conunction
|
||||
# with the unbonding (safety threshold) period, state pruning and state sync
|
||||
# snapshot parameters to determine the correct minimum value of
|
||||
# ResponseCommit.RetainHeight.
|
||||
min-retain-blocks = 0
|
||||
|
||||
# InterBlockCache enables inter-block caching.
|
||||
inter-block-cache = true
|
||||
|
||||
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
|
||||
# which informs Tendermint what to index. If empty, all events will be indexed.
|
||||
#
|
||||
# Example:
|
||||
# ["message.sender", "message.recipient"]
|
||||
index-events = []
|
||||
|
||||
# IavlCacheSize set the size of the iavl tree cache.
|
||||
# Default cache size is 50mb.
|
||||
iavl-cache-size = 781250
|
||||
|
||||
# IAVLDisableFastNode enables or disables the fast node feature of IAVL.
|
||||
# Default is true.
|
||||
iavl-disable-fastnode = true
|
||||
|
||||
###############################################################################
|
||||
### Telemetry Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[telemetry]
|
||||
|
||||
# Prefixed with keys to separate services.
|
||||
service-name = ""
|
||||
|
||||
# Enabled enables the application telemetry functionality. When enabled,
|
||||
# an in-memory sink is also enabled by default. Operators may also enabled
|
||||
# other sinks such as Prometheus.
|
||||
enabled = false
|
||||
|
||||
# Enable prefixing gauge values with hostname.
|
||||
enable-hostname = false
|
||||
|
||||
# Enable adding hostname to labels.
|
||||
enable-hostname-label = false
|
||||
|
||||
# Enable adding service to labels.
|
||||
enable-service-label = false
|
||||
|
||||
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
|
||||
prometheus-retention-time = 0
|
||||
|
||||
# GlobalLabels defines a global set of name/value label tuples applied to all
|
||||
# metrics emitted using the wrapper functions defined in telemetry package.
|
||||
#
|
||||
# Example:
|
||||
# [["chain_id", "cosmoshub-1"]]
|
||||
global-labels = [
|
||||
]
|
||||
|
||||
###############################################################################
|
||||
### API Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[api]
|
||||
|
||||
# Enable defines if the API server should be enabled.
|
||||
enable = false
|
||||
|
||||
# Swagger defines if swagger documentation should automatically be registered.
|
||||
swagger = false
|
||||
|
||||
# Address defines the API server to listen on.
|
||||
address = "tcp://0.0.0.0:1317"
|
||||
|
||||
# MaxOpenConnections defines the number of maximum open connections.
|
||||
max-open-connections = 1000
|
||||
|
||||
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
|
||||
rpc-read-timeout = 10
|
||||
|
||||
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
|
||||
rpc-write-timeout = 0
|
||||
|
||||
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
|
||||
rpc-max-body-bytes = 1000000
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||
enabled-unsafe-cors = false
|
||||
|
||||
###############################################################################
|
||||
### Rosetta Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[rosetta]
|
||||
|
||||
# Enable defines if the Rosetta API server should be enabled.
|
||||
enable = false
|
||||
|
||||
# Address defines the Rosetta API server to listen on.
|
||||
address = ":8080"
|
||||
|
||||
# Network defines the name of the blockchain that will be returned by Rosetta.
|
||||
blockchain = "app"
|
||||
|
||||
# Network defines the name of the network that will be returned by Rosetta.
|
||||
network = "network"
|
||||
|
||||
# Retries defines the number of retries when connecting to the node before failing.
|
||||
retries = 3
|
||||
|
||||
# Offline defines if Rosetta server should run in offline mode.
|
||||
offline = false
|
||||
|
||||
###############################################################################
|
||||
### gRPC Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[grpc]
|
||||
|
||||
# Enable defines if the gRPC server should be enabled.
|
||||
enable = true
|
||||
|
||||
# Address defines the gRPC server address to bind to.
|
||||
address = "0.0.0.0:9090"
|
||||
|
||||
###############################################################################
|
||||
### gRPC Web Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[grpc-web]
|
||||
|
||||
# GRPCWebEnable defines if the gRPC-web should be enabled.
|
||||
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
|
||||
enable = true
|
||||
|
||||
# Address defines the gRPC-web server address to bind to.
|
||||
address = "0.0.0.0:9091"
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||
enable-unsafe-cors = false
|
||||
|
||||
###############################################################################
|
||||
### State Sync Configuration ###
|
||||
###############################################################################
|
||||
|
||||
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
|
||||
# blocks, instead downloading and applying a snapshot of the application state at a given height.
|
||||
[state-sync]
|
||||
|
||||
# snapshot-interval specifies the block interval at which local state sync snapshots are
|
||||
# taken (0 to disable). Must be a multiple of pruning-keep-every.
|
||||
snapshot-interval = 0
|
||||
|
||||
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
|
||||
snapshot-keep-recent = 2
|
||||
|
||||
###############################################################################
|
||||
### Store / State Streaming ###
|
||||
###############################################################################
|
||||
|
||||
[store]
|
||||
streamers = []
|
||||
|
||||
[streamers]
|
||||
[streamers.file]
|
||||
keys = ["*", ]
|
||||
write_dir = ""
|
||||
prefix = ""
|
||||
|
||||
# output-metadata specifies if output the metadata file which includes the abci request/responses
|
||||
# during processing the block.
|
||||
output-metadata = "true"
|
||||
|
||||
# stop-node-on-error specifies if propagate the file streamer errors to consensus state machine.
|
||||
stop-node-on-error = "true"
|
||||
|
||||
# fsync specifies if call fsync after writing the files.
|
||||
fsync = "false"
|
||||
|
||||
[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
|
||||
255
tools/confix/data/v0.46-app.toml
Normal file
255
tools/confix/data/v0.46-app.toml
Normal file
@ -0,0 +1,255 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
###############################################################################
|
||||
### Base Configuration ###
|
||||
###############################################################################
|
||||
|
||||
# The minimum gas prices a validator is willing to accept for processing a
|
||||
# transaction. A transaction's fees must meet the minimum of any denomination
|
||||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "0stake"
|
||||
|
||||
# default: the last 362880 states are kept, pruning at 10 block intervals
|
||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
# everything: 2 latest states will be kept; pruning at 10 block intervals.
|
||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval'
|
||||
pruning = "default"
|
||||
|
||||
# These are applied if and only if the pruning strategy is custom.
|
||||
pruning-keep-recent = "0"
|
||||
pruning-interval = "0"
|
||||
|
||||
# HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
# halt and shutdown that can be used to assist upgrades and testing.
|
||||
#
|
||||
# Note: Commitment of state will be attempted on the corresponding block.
|
||||
halt-height = 0
|
||||
|
||||
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
|
||||
# a node will gracefully halt and shutdown that can be used to assist upgrades
|
||||
# and testing.
|
||||
#
|
||||
# Note: Commitment of state will be attempted on the corresponding block.
|
||||
halt-time = 0
|
||||
|
||||
# MinRetainBlocks defines the minimum block height offset from the current
|
||||
# block being committed, such that all blocks past this offset are pruned
|
||||
# from Tendermint. It is used as part of the process of determining the
|
||||
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
|
||||
# that no blocks should be pruned.
|
||||
#
|
||||
# This configuration value is only responsible for pruning Tendermint blocks.
|
||||
# It has no bearing on application state pruning which is determined by the
|
||||
# "pruning-*" configurations.
|
||||
#
|
||||
# Note: Tendermint block pruning is dependant on this parameter in conunction
|
||||
# with the unbonding (safety threshold) period, state pruning and state sync
|
||||
# snapshot parameters to determine the correct minimum value of
|
||||
# ResponseCommit.RetainHeight.
|
||||
min-retain-blocks = 0
|
||||
|
||||
# InterBlockCache enables inter-block caching.
|
||||
inter-block-cache = true
|
||||
|
||||
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
|
||||
# which informs Tendermint what to index. If empty, all events will be indexed.
|
||||
#
|
||||
# Example:
|
||||
# ["message.sender", "message.recipient"]
|
||||
index-events = []
|
||||
|
||||
# IavlCacheSize set the size of the iavl tree cache.
|
||||
# Default cache size is 50mb.
|
||||
iavl-cache-size = 781250
|
||||
|
||||
# IavlDisableFastNode enables or disables the fast node feature of IAVL.
|
||||
# Default is false.
|
||||
iavl-disable-fastnode = false
|
||||
|
||||
# AppDBBackend defines the database backend type to use for the application and snapshots DBs.
|
||||
# An empty string indicates that a fallback will be used.
|
||||
# First fallback is the deprecated compile-time types.DBBackend value.
|
||||
# Second fallback (if the types.DBBackend also isn't set), is the db-backend value set in Tendermint's config.toml.
|
||||
app-db-backend = ""
|
||||
|
||||
###############################################################################
|
||||
### Telemetry Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[telemetry]
|
||||
|
||||
# Prefixed with keys to separate services.
|
||||
service-name = ""
|
||||
|
||||
# Enabled enables the application telemetry functionality. When enabled,
|
||||
# an in-memory sink is also enabled by default. Operators may also enabled
|
||||
# other sinks such as Prometheus.
|
||||
enabled = false
|
||||
|
||||
# Enable prefixing gauge values with hostname.
|
||||
enable-hostname = false
|
||||
|
||||
# Enable adding hostname to labels.
|
||||
enable-hostname-label = false
|
||||
|
||||
# Enable adding service to labels.
|
||||
enable-service-label = false
|
||||
|
||||
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
|
||||
prometheus-retention-time = 0
|
||||
|
||||
# GlobalLabels defines a global set of name/value label tuples applied to all
|
||||
# metrics emitted using the wrapper functions defined in telemetry package.
|
||||
#
|
||||
# Example:
|
||||
# [["chain_id", "cosmoshub-1"]]
|
||||
global-labels = [
|
||||
]
|
||||
|
||||
###############################################################################
|
||||
### API Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[api]
|
||||
|
||||
# Enable defines if the API server should be enabled.
|
||||
enable = false
|
||||
|
||||
# Swagger defines if swagger documentation should automatically be registered.
|
||||
swagger = false
|
||||
|
||||
# Address defines the API server to listen on.
|
||||
address = "tcp://0.0.0.0:1317"
|
||||
|
||||
# MaxOpenConnections defines the number of maximum open connections.
|
||||
max-open-connections = 1000
|
||||
|
||||
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
|
||||
rpc-read-timeout = 10
|
||||
|
||||
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
|
||||
rpc-write-timeout = 0
|
||||
|
||||
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
|
||||
rpc-max-body-bytes = 1000000
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||
enabled-unsafe-cors = false
|
||||
|
||||
###############################################################################
|
||||
### Rosetta Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[rosetta]
|
||||
|
||||
# Enable defines if the Rosetta API server should be enabled.
|
||||
enable = false
|
||||
|
||||
# Address defines the Rosetta API server to listen on.
|
||||
address = ":8080"
|
||||
|
||||
# Network defines the name of the blockchain that will be returned by Rosetta.
|
||||
blockchain = "app"
|
||||
|
||||
# Network defines the name of the network that will be returned by Rosetta.
|
||||
network = "network"
|
||||
|
||||
# Retries defines the number of retries when connecting to the node before failing.
|
||||
retries = 3
|
||||
|
||||
# Offline defines if Rosetta server should run in offline mode.
|
||||
offline = false
|
||||
|
||||
# EnableDefaultSuggestedFee defines if the server should suggest fee by default.
|
||||
# If 'construction/medata' is called without gas limit and gas price,
|
||||
# suggested fee based on gas-to-suggest and denom-to-suggest will be given.
|
||||
enable-fee-suggestion = false
|
||||
|
||||
# GasToSuggest defines gas limit when calculating the fee
|
||||
gas-to-suggest = 200000
|
||||
|
||||
# DenomToSuggest defines the defult denom for fee suggestion.
|
||||
# Price must be in minimum-gas-prices.
|
||||
denom-to-suggest = "uatom"
|
||||
|
||||
###############################################################################
|
||||
### gRPC Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[grpc]
|
||||
|
||||
# Enable defines if the gRPC server should be enabled.
|
||||
enable = true
|
||||
|
||||
# Address defines the gRPC server address to bind to.
|
||||
address = "0.0.0.0:9090"
|
||||
|
||||
# MaxRecvMsgSize defines the max message size in bytes the server can receive.
|
||||
# The default value is 10MB.
|
||||
max-recv-msg-size = "10485760"
|
||||
|
||||
# MaxSendMsgSize defines the max message size in bytes the server can send.
|
||||
# The default value is math.MaxInt32.
|
||||
max-send-msg-size = "2147483647"
|
||||
|
||||
###############################################################################
|
||||
### gRPC Web Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[grpc-web]
|
||||
|
||||
# GRPCWebEnable defines if the gRPC-web should be enabled.
|
||||
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
|
||||
enable = true
|
||||
|
||||
# Address defines the gRPC-web server address to bind to.
|
||||
address = "0.0.0.0:9091"
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||
enable-unsafe-cors = false
|
||||
|
||||
###############################################################################
|
||||
### State Sync Configuration ###
|
||||
###############################################################################
|
||||
|
||||
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
|
||||
# blocks, instead downloading and applying a snapshot of the application state at a given height.
|
||||
[state-sync]
|
||||
|
||||
# snapshot-interval specifies the block interval at which local state sync snapshots are
|
||||
# taken (0 to disable).
|
||||
snapshot-interval = 0
|
||||
|
||||
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
|
||||
snapshot-keep-recent = 2
|
||||
|
||||
###############################################################################
|
||||
### Store / State Streaming ###
|
||||
###############################################################################
|
||||
|
||||
[store]
|
||||
streamers = []
|
||||
|
||||
[streamers]
|
||||
[streamers.file]
|
||||
keys = ["*", ]
|
||||
write_dir = ""
|
||||
prefix = ""
|
||||
|
||||
# output-metadata specifies if output the metadata file which includes the abci request/responses
|
||||
# during processing the block.
|
||||
output-metadata = "true"
|
||||
|
||||
# stop-node-on-error specifies if propagate the file streamer errors to consensus state machine.
|
||||
stop-node-on-error = "true"
|
||||
|
||||
# fsync specifies if call fsync after writing the files.
|
||||
fsync = "false"
|
||||
|
||||
[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
|
||||
232
tools/confix/data/v0.47-app.toml
Normal file
232
tools/confix/data/v0.47-app.toml
Normal file
@ -0,0 +1,232 @@
|
||||
# This is a TOML config file.
|
||||
# For more information, see https://github.com/toml-lang/toml
|
||||
|
||||
###############################################################################
|
||||
### Base Configuration ###
|
||||
###############################################################################
|
||||
|
||||
# The minimum gas prices a validator is willing to accept for processing a
|
||||
# transaction. A transaction's fees must meet the minimum of any denomination
|
||||
# specified in this config (e.g. 0.25token1;0.0001token2).
|
||||
minimum-gas-prices = "0stake"
|
||||
|
||||
# default: the last 362880 states are kept, pruning at 10 block intervals
|
||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
|
||||
# everything: 2 latest states will be kept; pruning at 10 block intervals.
|
||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', and 'pruning-interval'
|
||||
pruning = "default"
|
||||
|
||||
# These are applied if and only if the pruning strategy is custom.
|
||||
pruning-keep-recent = "0"
|
||||
pruning-interval = "0"
|
||||
|
||||
# HaltHeight contains a non-zero block height at which a node will gracefully
|
||||
# halt and shutdown that can be used to assist upgrades and testing.
|
||||
#
|
||||
# Note: Commitment of state will be attempted on the corresponding block.
|
||||
halt-height = 0
|
||||
|
||||
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
|
||||
# a node will gracefully halt and shutdown that can be used to assist upgrades
|
||||
# and testing.
|
||||
#
|
||||
# Note: Commitment of state will be attempted on the corresponding block.
|
||||
halt-time = 0
|
||||
|
||||
# MinRetainBlocks defines the minimum block height offset from the current
|
||||
# block being committed, such that all blocks past this offset are pruned
|
||||
# from Tendermint. It is used as part of the process of determining the
|
||||
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
|
||||
# that no blocks should be pruned.
|
||||
#
|
||||
# This configuration value is only responsible for pruning Tendermint blocks.
|
||||
# It has no bearing on application state pruning which is determined by the
|
||||
# "pruning-*" configurations.
|
||||
#
|
||||
# Note: Tendermint block pruning is dependant on this parameter in conunction
|
||||
# with the unbonding (safety threshold) period, state pruning and state sync
|
||||
# snapshot parameters to determine the correct minimum value of
|
||||
# ResponseCommit.RetainHeight.
|
||||
min-retain-blocks = 0
|
||||
|
||||
# InterBlockCache enables inter-block caching.
|
||||
inter-block-cache = true
|
||||
|
||||
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
|
||||
# which informs Tendermint what to index. If empty, all events will be indexed.
|
||||
#
|
||||
# Example:
|
||||
# ["message.sender", "message.recipient"]
|
||||
index-events = []
|
||||
|
||||
# IavlCacheSize set the size of the iavl tree cache.
|
||||
# Default cache size is 50mb.
|
||||
iavl-cache-size = 781250
|
||||
|
||||
# IAVLDisableFastNode enables or disables the fast node feature of IAVL.
|
||||
# Default is false.
|
||||
iavl-disable-fastnode = false
|
||||
|
||||
# AppDBBackend defines the database backend type to use for the application and snapshots DBs.
|
||||
# An empty string indicates that a fallback will be used.
|
||||
# First fallback is the deprecated compile-time types.DBBackend value.
|
||||
# Second fallback (if the types.DBBackend also isn't set), is the db-backend value set in Tendermint's config.toml.
|
||||
app-db-backend = ""
|
||||
|
||||
###############################################################################
|
||||
### Telemetry Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[telemetry]
|
||||
|
||||
# Prefixed with keys to separate services.
|
||||
service-name = ""
|
||||
|
||||
# Enabled enables the application telemetry functionality. When enabled,
|
||||
# an in-memory sink is also enabled by default. Operators may also enabled
|
||||
# other sinks such as Prometheus.
|
||||
enabled = false
|
||||
|
||||
# Enable prefixing gauge values with hostname.
|
||||
enable-hostname = false
|
||||
|
||||
# Enable adding hostname to labels.
|
||||
enable-hostname-label = false
|
||||
|
||||
# Enable adding service to labels.
|
||||
enable-service-label = false
|
||||
|
||||
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
|
||||
prometheus-retention-time = 0
|
||||
|
||||
# GlobalLabels defines a global set of name/value label tuples applied to all
|
||||
# metrics emitted using the wrapper functions defined in telemetry package.
|
||||
#
|
||||
# Example:
|
||||
# [["chain_id", "cosmoshub-1"]]
|
||||
global-labels = [
|
||||
]
|
||||
|
||||
###############################################################################
|
||||
### API Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[api]
|
||||
|
||||
# Enable defines if the API server should be enabled.
|
||||
enable = false
|
||||
|
||||
# Swagger defines if swagger documentation should automatically be registered.
|
||||
swagger = false
|
||||
|
||||
# Address defines the API server to listen on.
|
||||
address = "tcp://localhost:1317"
|
||||
|
||||
# MaxOpenConnections defines the number of maximum open connections.
|
||||
max-open-connections = 1000
|
||||
|
||||
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
|
||||
rpc-read-timeout = 10
|
||||
|
||||
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
|
||||
rpc-write-timeout = 0
|
||||
|
||||
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
|
||||
rpc-max-body-bytes = 1000000
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||
enabled-unsafe-cors = false
|
||||
|
||||
###############################################################################
|
||||
### gRPC Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[grpc]
|
||||
|
||||
# Enable defines if the gRPC server should be enabled.
|
||||
enable = true
|
||||
|
||||
# Address defines the gRPC server address to bind to.
|
||||
address = "localhost:9090"
|
||||
|
||||
# MaxRecvMsgSize defines the max message size in bytes the server can receive.
|
||||
# The default value is 10MB.
|
||||
max-recv-msg-size = "10485760"
|
||||
|
||||
# MaxSendMsgSize defines the max message size in bytes the server can send.
|
||||
# The default value is math.MaxInt32.
|
||||
max-send-msg-size = "2147483647"
|
||||
|
||||
###############################################################################
|
||||
### gRPC Web Configuration ###
|
||||
###############################################################################
|
||||
|
||||
[grpc-web]
|
||||
|
||||
# GRPCWebEnable defines if the gRPC-web should be enabled.
|
||||
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
|
||||
enable = true
|
||||
|
||||
# Address defines the gRPC-web server address to bind to.
|
||||
address = "localhost:9091"
|
||||
|
||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
|
||||
enable-unsafe-cors = false
|
||||
|
||||
###############################################################################
|
||||
### State Sync Configuration ###
|
||||
###############################################################################
|
||||
|
||||
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
|
||||
# blocks, instead downloading and applying a snapshot of the application state at a given height.
|
||||
[state-sync]
|
||||
|
||||
# snapshot-interval specifies the block interval at which local state sync snapshots are
|
||||
# taken (0 to disable).
|
||||
snapshot-interval = 0
|
||||
|
||||
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
|
||||
snapshot-keep-recent = 2
|
||||
|
||||
###############################################################################
|
||||
### Store / State Streaming ###
|
||||
###############################################################################
|
||||
|
||||
[store]
|
||||
streamers = []
|
||||
|
||||
[streamers]
|
||||
[streamers.file]
|
||||
keys = ["*", ]
|
||||
write_dir = ""
|
||||
prefix = ""
|
||||
|
||||
# output-metadata specifies if output the metadata file which includes the abci request/responses
|
||||
# during processing the block.
|
||||
output-metadata = "true"
|
||||
|
||||
# stop-node-on-error specifies if propagate the file streamer errors to consensus state machine.
|
||||
stop-node-on-error = "true"
|
||||
|
||||
# fsync specifies if call fsync after writing the files.
|
||||
fsync = "false"
|
||||
|
||||
###############################################################################
|
||||
### Mempool ###
|
||||
###############################################################################
|
||||
|
||||
[mempool]
|
||||
# Setting max-txs to 0 will allow for a unbounded amount of transactions in the mempool.
|
||||
# Setting max_txs to negative 1 (-1) will disable transactions from being inserted into the mempool.
|
||||
# Setting max_txs to a positive number (> 0) will limit the number of transactions in the mempool, by the specified amount.
|
||||
#
|
||||
# Note, this configuration only applies to SDK built-in app-side mempool
|
||||
# implementations.
|
||||
max-txs = "5000"
|
||||
|
||||
[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
|
||||
140
tools/confix/diff.go
Normal file
140
tools/confix/diff.go
Normal file
@ -0,0 +1,140 @@
|
||||
package confix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/creachadair/tomledit/parser"
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
)
|
||||
|
||||
const (
|
||||
Section = "S"
|
||||
Mapping = "M"
|
||||
)
|
||||
|
||||
type KV struct {
|
||||
Key string
|
||||
Value string
|
||||
Block []string // comment block
|
||||
}
|
||||
|
||||
type Diff struct {
|
||||
Type string // "section" or "mapping"
|
||||
Deleted bool
|
||||
|
||||
KV KV
|
||||
}
|
||||
|
||||
// DiffKeys diffs the keyspaces of the TOML documents in files lhs and rhs.
|
||||
// Comments, order, and values are ignored for comparison purposes.
|
||||
func DiffKeys(lhs, rhs *tomledit.Document) []Diff {
|
||||
diff := diffSections(lhs.Global, rhs.Global)
|
||||
|
||||
lsec, rsec := lhs.Sections, rhs.Sections
|
||||
transform.SortSectionsByName(lsec)
|
||||
transform.SortSectionsByName(rsec)
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(lsec) && j < len(rsec) {
|
||||
if lsec[i].Name.Before(rsec[j].Name) {
|
||||
diff = append(diff, Diff{Type: Section, Deleted: true, KV: KV{Key: lsec[i].Name.String()}})
|
||||
for _, kv := range allKVs(lsec[i]) {
|
||||
diff = append(diff, Diff{Type: Mapping, Deleted: true, KV: kv})
|
||||
}
|
||||
i++
|
||||
} else if rsec[j].Name.Before(lsec[i].Name) {
|
||||
diff = append(diff, Diff{Type: Section, KV: KV{Key: rsec[j].Name.String()}})
|
||||
for _, kv := range allKVs(rsec[j]) {
|
||||
diff = append(diff, Diff{Type: Mapping, KV: kv})
|
||||
}
|
||||
j++
|
||||
} else {
|
||||
diff = append(diff, diffSections(lsec[i], rsec[j])...)
|
||||
i++
|
||||
j++
|
||||
}
|
||||
}
|
||||
for ; i < len(lsec); i++ {
|
||||
diff = append(diff, Diff{Type: Section, Deleted: true, KV: KV{Key: lsec[i].Name.String()}})
|
||||
for _, kv := range allKVs(lsec[i]) {
|
||||
diff = append(diff, Diff{Type: Mapping, Deleted: true, KV: kv})
|
||||
}
|
||||
}
|
||||
for ; j < len(rsec); j++ {
|
||||
diff = append(diff, Diff{Type: Section, KV: KV{Key: rsec[j].Name.String()}})
|
||||
for _, kv := range allKVs(rsec[j]) {
|
||||
diff = append(diff, Diff{Type: Mapping, KV: kv})
|
||||
}
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
||||
|
||||
func allKVs(s *tomledit.Section) []KV {
|
||||
keys := []KV{}
|
||||
s.Scan(func(key parser.Key, entry *tomledit.Entry) bool {
|
||||
keys = append(keys, KV{
|
||||
Key: key.String(),
|
||||
Value: entry.Value.String(),
|
||||
Block: entry.Block,
|
||||
})
|
||||
|
||||
return true
|
||||
})
|
||||
return keys
|
||||
}
|
||||
|
||||
func diffSections(lhs, rhs *tomledit.Section) []Diff {
|
||||
return diffKeys(allKVs(lhs), allKVs(rhs))
|
||||
}
|
||||
|
||||
func diffKeys(lhs, rhs []KV) []Diff {
|
||||
diff := []Diff{}
|
||||
|
||||
sort.Slice(lhs, func(i, j int) bool {
|
||||
return lhs[i].Key < lhs[j].Key
|
||||
})
|
||||
sort.Slice(rhs, func(i, j int) bool {
|
||||
return rhs[i].Key < rhs[j].Key
|
||||
})
|
||||
|
||||
i, j := 0, 0
|
||||
for i < len(lhs) && j < len(rhs) {
|
||||
if lhs[i].Key < rhs[j].Key {
|
||||
diff = append(diff, Diff{Type: Mapping, Deleted: true, KV: lhs[i]})
|
||||
i++
|
||||
} else if lhs[i].Key > rhs[j].Key {
|
||||
diff = append(diff, Diff{Type: Mapping, KV: rhs[j]})
|
||||
j++
|
||||
} else {
|
||||
i++
|
||||
j++
|
||||
}
|
||||
}
|
||||
for ; i < len(lhs); i++ {
|
||||
diff = append(diff, Diff{Type: Mapping, Deleted: true, KV: lhs[i]})
|
||||
}
|
||||
for ; j < len(rhs); j++ {
|
||||
diff = append(diff, Diff{Type: Mapping, KV: rhs[j]})
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
||||
|
||||
// PrintDiff output prints one line per key that differs:
|
||||
// -S name -- section exists in f1 but not f2
|
||||
// +S name -- section exists in f2 but not f1
|
||||
// -M name -- mapping exists in f1 but not f2
|
||||
// +M name -- mapping exists in f2 but not f1
|
||||
func PrintDiff(w io.Writer, diffs []Diff) {
|
||||
for _, diff := range diffs {
|
||||
if diff.Deleted {
|
||||
fmt.Fprintln(w, fmt.Sprintf("-%s", diff.Type), fmt.Sprintf("%s=%s", diff.KV.Key, diff.KV.Value))
|
||||
} else {
|
||||
fmt.Fprintln(w, fmt.Sprintf("+%s", diff.Type), fmt.Sprintf("%s=%s", diff.KV.Key, diff.KV.Value))
|
||||
}
|
||||
}
|
||||
}
|
||||
4
tools/confix/doc.go
Normal file
4
tools/confix/doc.go
Normal file
@ -0,0 +1,4 @@
|
||||
// Package confix applies changes to a Cosmos SDK TOML configuration file, to
|
||||
// update configurations created with an older version of Cosmos SDK to a
|
||||
// compatible format for a newer version.
|
||||
package confix
|
||||
144
tools/confix/go.mod
Normal file
144
tools/confix/go.mod
Normal file
@ -0,0 +1,144 @@
|
||||
module cosmossdk.io/tools/confix
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/cosmos/cosmos-sdk v0.47.0-rc1
|
||||
github.com/creachadair/atomicfile v0.2.7
|
||||
github.com/creachadair/tomledit v0.0.24
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.14.0
|
||||
golang.org/x/exp v0.0.0-20221019170559-20944726eadf
|
||||
gotest.tools/v3 v3.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
cosmossdk.io/api v0.2.6 // indirect
|
||||
cosmossdk.io/core v0.3.2 // indirect
|
||||
cosmossdk.io/depinject v1.0.0-alpha.3 // indirect
|
||||
cosmossdk.io/errors v1.0.0-beta.7 // indirect
|
||||
cosmossdk.io/math v1.0.0-beta.4 // indirect
|
||||
cosmossdk.io/tools/rosetta v0.2.0 // indirect
|
||||
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/confio/ics23/go v0.9.0 // indirect
|
||||
github.com/cosmos/btcutil v1.0.5 // indirect
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.1 // indirect
|
||||
github.com/cosmos/go-bip39 v1.0.0 // indirect
|
||||
github.com/cosmos/gogogateway v1.2.0 // indirect
|
||||
github.com/cosmos/gogoproto v1.4.3 // indirect
|
||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||
github.com/cosmos/iavl v0.19.4 // indirect
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect
|
||||
github.com/cosmos/rosetta-sdk-go v0.9.0 // indirect
|
||||
github.com/creachadair/taskgroup v0.3.2 // indirect
|
||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.1 // indirect
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-kit/kit v0.12.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
|
||||
github.com/huandu/skiplist v1.2.0 // indirect
|
||||
github.com/improbable-eng/grpc-web v0.15.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.15.12 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.14.0 // indirect
|
||||
github.com/prometheus/client_model v0.3.0 // indirect
|
||||
github.com/prometheus/common v0.37.0 // indirect
|
||||
github.com/prometheus/procfs v0.8.0 // indirect
|
||||
github.com/rakyll/statik v0.1.7 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rs/cors v1.8.2 // indirect
|
||||
github.com/rs/zerolog v1.28.0 // indirect
|
||||
github.com/sasha-s/go-deadlock v0.3.1 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.8.1 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||
github.com/tendermint/btcd v0.1.1 // indirect
|
||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tendermint/tendermint v0.37.0-rc2 // indirect
|
||||
github.com/tendermint/tm-db v0.6.7 // indirect
|
||||
github.com/tidwall/btree v1.5.2 // indirect
|
||||
github.com/zondax/hid v0.9.1 // indirect
|
||||
github.com/zondax/ledger-go v0.14.0 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
golang.org/x/net v0.3.0 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/term v0.3.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect
|
||||
google.golang.org/grpc v1.51.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
pgregory.net/rapid v0.5.3 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
|
||||
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
|
||||
// TODO investigate if we can outright delete this dependency, otherwise go install won't work :(
|
||||
replace github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1
|
||||
1210
tools/confix/go.sum
Normal file
1210
tools/confix/go.sum
Normal file
File diff suppressed because it is too large
Load Diff
14
tools/confix/log.go
Normal file
14
tools/confix/log.go
Normal file
@ -0,0 +1,14 @@
|
||||
package confix
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
)
|
||||
|
||||
// WithLogWriter returns a child of ctx with a logger attached that sends
|
||||
// output to w. This is a convenience wrapper for transform.WithLogWriter.
|
||||
func WithLogWriter(ctx context.Context, w io.Writer) context.Context {
|
||||
return transform.WithLogWriter(ctx, w)
|
||||
}
|
||||
125
tools/confix/migrations.go
Normal file
125
tools/confix/migrations.go
Normal file
@ -0,0 +1,125 @@
|
||||
package confix
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/creachadair/tomledit/parser"
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
)
|
||||
|
||||
const (
|
||||
AppConfig = "app.toml"
|
||||
ClientConfig = "client.toml"
|
||||
TMConfig = "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
|
||||
|
||||
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.47.x": PlanBuilder, // add specific migration in case of configuration changes in minor versions
|
||||
// "v0.48": PlanBuilder,
|
||||
}
|
||||
|
||||
//go:embed data
|
||||
data embed.FS
|
||||
)
|
||||
|
||||
// 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 {
|
||||
plan := transform.Plan{}
|
||||
|
||||
file, err := data.Open(fmt.Sprintf("data/%s-app.toml", to))
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to read file: %w. This file should have been included in confix", err))
|
||||
}
|
||||
|
||||
target, err := tomledit.Parse(file)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to parse file: %w. This file should have been valid", err))
|
||||
}
|
||||
|
||||
deletedSections := map[string]bool{}
|
||||
|
||||
diffs := DiffKeys(from, target)
|
||||
for _, diff := range diffs {
|
||||
diff := diff
|
||||
kv := diff.KV
|
||||
|
||||
var step transform.Step
|
||||
keys := strings.Split(kv.Key, ".")
|
||||
|
||||
if !diff.Deleted {
|
||||
switch diff.Type {
|
||||
case Section:
|
||||
step = transform.Step{
|
||||
Desc: fmt.Sprintf("add %s section", kv.Key),
|
||||
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
|
||||
doc.Sections = append(doc.Sections, &tomledit.Section{
|
||||
Heading: &parser.Heading{
|
||||
Block: parser.Comments{
|
||||
"###############################################################################",
|
||||
fmt.Sprintf("### %s Configuration ###", strings.Title(kv.Key)),
|
||||
"###############################################################################"},
|
||||
Name: keys,
|
||||
},
|
||||
})
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
case Mapping:
|
||||
if len(keys) == 1 { // top-level key
|
||||
step = transform.Step{
|
||||
Desc: fmt.Sprintf("add %s key", kv.Key),
|
||||
T: transform.EnsureKey(nil, &parser.KeyValue{
|
||||
Block: kv.Block,
|
||||
Name: parser.Key{keys[0]},
|
||||
Value: parser.MustValue(kv.Value),
|
||||
})}
|
||||
} else if len(keys) > 1 {
|
||||
step = transform.Step{
|
||||
Desc: fmt.Sprintf("add %s key", kv.Key),
|
||||
T: transform.EnsureKey(parser.Key{keys[0]}, &parser.KeyValue{
|
||||
Block: kv.Block,
|
||||
Name: parser.Key{keys[1]},
|
||||
Value: parser.MustValue(kv.Value),
|
||||
})}
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("unknown diff type: %s", diff.Type))
|
||||
}
|
||||
} else {
|
||||
if diff.Type == Section {
|
||||
deletedSections[kv.Key] = true
|
||||
}
|
||||
|
||||
// when the whole section is deleted we don't need to remove the keys
|
||||
if len(keys) > 1 && deletedSections[keys[0]] {
|
||||
continue
|
||||
}
|
||||
|
||||
step = transform.Step{
|
||||
Desc: fmt.Sprintf("remove %s key", kv.Key),
|
||||
T: transform.Remove(keys),
|
||||
}
|
||||
}
|
||||
|
||||
plan = append(plan, step)
|
||||
}
|
||||
|
||||
return plan
|
||||
}
|
||||
|
||||
// NoPlan returns a no-op plan.
|
||||
func NoPlan(_ *tomledit.Document, to string) transform.Plan {
|
||||
fmt.Printf("no migration needed to %s\n", to)
|
||||
return transform.Plan{}
|
||||
}
|
||||
15
tools/confix/sonar-project.properties
Normal file
15
tools/confix/sonar-project.properties
Normal file
@ -0,0 +1,15 @@
|
||||
sonar.projectKey=cosmos-sdk-tools-confix
|
||||
sonar.organization=cosmos
|
||||
|
||||
sonar.projectName=Cosmos SDK - Confix
|
||||
sonar.project.monorepo.enabled=true
|
||||
|
||||
sonar.sources=.
|
||||
sonar.exclusions=**/*_test.go
|
||||
sonar.tests=.
|
||||
sonar.test.inclusions=**/*_test.go
|
||||
sonar.go.coverage.reportPaths=coverage.out
|
||||
|
||||
sonar.sourceEncoding=UTF-8
|
||||
sonar.scm.provider=git
|
||||
sonar.pullrequest.github.summary_comment=true
|
||||
43
tools/confix/testdata/README.md
vendored
Normal file
43
tools/confix/testdata/README.md
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# Test data for `confix` and `condiff`
|
||||
|
||||
The files in this directory are stock Cosmos SDK configuration files generated
|
||||
by the last point release of each version series from v0.45 to present, along
|
||||
with diffs between consecutive versions.
|
||||
|
||||
## Config Samples
|
||||
|
||||
The files named `vXX-app.toml` were generated by checking out and building
|
||||
the corresponding version of Cosmos SDK v0.xx.y and initializing a new node in
|
||||
an empty home directory. The resulting `app.toml` file was copied here.
|
||||
The exact build instructions vary a bit, but a general repro looks like:
|
||||
|
||||
```shell
|
||||
# This example uses v0.47, substitute the version of your choice.
|
||||
git checkout release/v0.47.x
|
||||
|
||||
# Install dependencies
|
||||
make install
|
||||
|
||||
# Confirm you go the version you expected, and generate the file.
|
||||
simd version
|
||||
simd init test --chain-id test
|
||||
|
||||
# Copy the file out.
|
||||
cp ./.simapp/config/app.toml v47-app.toml
|
||||
```
|
||||
|
||||
## Version Diffs
|
||||
|
||||
The files named `diff-XX-YY.txt` were generated by using the `condiff` tool on
|
||||
the config samples for versions v0.XX and v0.YY:
|
||||
|
||||
```shell
|
||||
condiff vXX-app.toml data/vYY-app.toml > testdata/diff-XX-YY.txt
|
||||
```
|
||||
|
||||
The `baseline.txt` was computed in the same way, but using an empty starting
|
||||
file so that we capture all the settings in the target:
|
||||
|
||||
```shell
|
||||
condiff /dev/null data/v45-app.toml > testdata/baseline.txt
|
||||
```
|
||||
60
tools/confix/testdata/baseline.txt
vendored
Normal file
60
tools/confix/testdata/baseline.txt
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
+M halt-height
|
||||
+M halt-time
|
||||
+M iavl-cache-size
|
||||
+M iavl-disable-fastnode
|
||||
+M index-events
|
||||
+M inter-block-cache
|
||||
+M min-retain-blocks
|
||||
+M minimum-gas-prices
|
||||
+M pruning
|
||||
+M pruning-interval
|
||||
+M pruning-keep-every
|
||||
+M pruning-keep-recent
|
||||
+S api
|
||||
+M api.enable
|
||||
+M api.swagger
|
||||
+M api.address
|
||||
+M api.max-open-connections
|
||||
+M api.rpc-read-timeout
|
||||
+M api.rpc-write-timeout
|
||||
+M api.rpc-max-body-bytes
|
||||
+M api.enabled-unsafe-cors
|
||||
+S grpc
|
||||
+M grpc.enable
|
||||
+M grpc.address
|
||||
+S grpc-web
|
||||
+M grpc-web.enable
|
||||
+M grpc-web.address
|
||||
+M grpc-web.enable-unsafe-cors
|
||||
+S rosetta
|
||||
+M rosetta.enable
|
||||
+M rosetta.address
|
||||
+M rosetta.blockchain
|
||||
+M rosetta.network
|
||||
+M rosetta.retries
|
||||
+M rosetta.offline
|
||||
+S state-sync
|
||||
+M state-sync.snapshot-interval
|
||||
+M state-sync.snapshot-keep-recent
|
||||
+S store
|
||||
+M store.streamers
|
||||
+S streamers
|
||||
+M
|
||||
+S streamers.file
|
||||
+M streamers.file.keys
|
||||
+M streamers.file.write_dir
|
||||
+M streamers.file.prefix
|
||||
+M streamers.file.output-metadata
|
||||
+M streamers.file.stop-node-on-error
|
||||
+M streamers.file.fsync
|
||||
+S telemetry
|
||||
+M telemetry.service-name
|
||||
+M telemetry.enabled
|
||||
+M telemetry.enable-hostname
|
||||
+M telemetry.enable-hostname-label
|
||||
+M telemetry.enable-service-label
|
||||
+M telemetry.prometheus-retention-time
|
||||
+M telemetry.global-labels
|
||||
+S wasm
|
||||
+M wasm.query_gas_limit
|
||||
+M wasm.lru_size
|
||||
17
tools/confix/testdata/client.toml
vendored
Normal file
17
tools/confix/testdata/client.toml
vendored
Normal file
@ -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 = "test"
|
||||
# CLI output format (text|json)
|
||||
output = "text"
|
||||
# <host>:<port> to Tendermint RPC interface for this chain
|
||||
node = "tcp://localhost:26657"
|
||||
# Transaction broadcasting mode (sync|async)
|
||||
broadcast-mode = "sync"
|
||||
7
tools/confix/testdata/diff-45-46.txt
vendored
Normal file
7
tools/confix/testdata/diff-45-46.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
+M app-db-backend
|
||||
-M pruning-keep-every
|
||||
+M grpc.max-recv-msg-size
|
||||
+M grpc.max-send-msg-size
|
||||
+M rosetta.denom-to-suggest
|
||||
+M rosetta.enable-fee-suggestion
|
||||
+M rosetta.gas-to-suggest
|
||||
12
tools/confix/testdata/diff-46-47.txt
vendored
Normal file
12
tools/confix/testdata/diff-46-47.txt
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
+S mempool
|
||||
+M mempool.max-txs
|
||||
-S rosetta
|
||||
-M rosetta.enable
|
||||
-M rosetta.address
|
||||
-M rosetta.blockchain
|
||||
-M rosetta.network
|
||||
-M rosetta.retries
|
||||
-M rosetta.offline
|
||||
-M rosetta.enable-fee-suggestion
|
||||
-M rosetta.gas-to-suggest
|
||||
-M rosetta.denom-to-suggest
|
||||
116
tools/confix/upgrade.go
Normal file
116
tools/confix/upgrade.go
Normal file
@ -0,0 +1,116 @@
|
||||
package confix
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/creachadair/atomicfile"
|
||||
"github.com/creachadair/tomledit"
|
||||
"github.com/creachadair/tomledit/transform"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
clientcfg "github.com/cosmos/cosmos-sdk/client/config"
|
||||
srvcfg "github.com/cosmos/cosmos-sdk/server/config"
|
||||
)
|
||||
|
||||
// Upgrade reads the configuration file at configPath and applies any
|
||||
// transformations necessary to Upgrade it to the current version. If this
|
||||
// succeeds, the transformed output is written to outputPath. As a special
|
||||
// case, if outputPath == "" the output is written to stdout.
|
||||
//
|
||||
// It is safe if outputPath == inputPath. If a regular file outputPath already
|
||||
// exists, it is overwritten. In case of error, the output is not written.
|
||||
//
|
||||
// Upgrade is a convenience wrapper for calls to LoadConfig, ApplyFixes, and
|
||||
// CheckValid. If the caller requires more control over the behavior of the
|
||||
// Upgrade, call those functions directly.
|
||||
func Upgrade(ctx context.Context, plan transform.Plan, configPath, outputPath string, skipValidate bool) error {
|
||||
if configPath == "" {
|
||||
return errors.New("empty input configuration path")
|
||||
}
|
||||
|
||||
doc, err := LoadConfig(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("loading config: %v", err)
|
||||
}
|
||||
|
||||
// transforms doc and reports whether it succeeded.
|
||||
if err := plan.Apply(ctx, doc); err != nil {
|
||||
return fmt.Errorf("updating %q: %v", configPath, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := tomledit.Format(&buf, doc); err != nil {
|
||||
return fmt.Errorf("formatting config: %v", err)
|
||||
}
|
||||
|
||||
// allow to skip validation
|
||||
if !skipValidate {
|
||||
// verify that file is valid after applying fixes
|
||||
if err := CheckValid(configPath, buf.Bytes()); err != nil {
|
||||
return fmt.Errorf("updated config is invalid: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if outputPath == "" {
|
||||
_, err = os.Stdout.Write(buf.Bytes())
|
||||
} else {
|
||||
err = atomicfile.WriteData(outputPath, buf.Bytes(), 0600)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadConfig loads and parses the TOML document from path.
|
||||
func LoadConfig(path string) (*tomledit.Document, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open %q: %v", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return tomledit.Parse(f)
|
||||
}
|
||||
|
||||
// CheckValid checks whether the specified config appears to be a valid Cosmos SDK config file.
|
||||
// It tries to unmarshal the config into both the server and client config structs.
|
||||
func CheckValid(fileName string, data []byte) error {
|
||||
v := viper.New()
|
||||
v.SetConfigType("toml")
|
||||
|
||||
if err := v.ReadConfig(bytes.NewReader(data)); err != nil {
|
||||
return fmt.Errorf("reading config: %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.HasSuffix(fileName, AppConfig):
|
||||
var cfg srvcfg.Config
|
||||
if err := v.Unmarshal(&cfg); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal as server config: %w", err)
|
||||
}
|
||||
|
||||
if err := cfg.ValidateBasic(); err != nil {
|
||||
return fmt.Errorf("server config invalid : %w", err)
|
||||
}
|
||||
case strings.HasSuffix(fileName, ClientConfig):
|
||||
var cfg clientcfg.ClientConfig
|
||||
if err := v.Unmarshal(&cfg); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal as client config: %w", err)
|
||||
}
|
||||
|
||||
if cfg.ChainID == "" {
|
||||
return errors.New("client config invalid: chain-id is empty")
|
||||
}
|
||||
case strings.HasSuffix(fileName, TMConfig):
|
||||
return errors.New("tendermint config is not supported")
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown config: %s", fileName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
48
tools/confix/upgrade_test.go
Normal file
48
tools/confix/upgrade_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
package confix_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/tools/confix"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func mustReadConfig(t *testing.T, path string) []byte {
|
||||
f, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open file: %v", err)
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func TestUpgrade(t *testing.T) {
|
||||
// TODO: add more test cases
|
||||
}
|
||||
|
||||
func TestCheckValid(t *testing.T) {
|
||||
err := confix.CheckValid("foo", []byte{})
|
||||
assert.ErrorContains(t, err, "unknown config")
|
||||
|
||||
err = confix.CheckValid("client", mustReadConfig(t, "data/v0.45-app.toml"))
|
||||
assert.ErrorContains(t, err, "unknown config")
|
||||
|
||||
err = confix.CheckValid("config.toml", mustReadConfig(t, "data/v0.45-app.toml"))
|
||||
assert.Error(t, err, "tendermint config is not supported")
|
||||
|
||||
err = confix.CheckValid("client.toml", mustReadConfig(t, "data/v0.45-app.toml"))
|
||||
assert.Error(t, err, "client config invalid: chain-id is empty")
|
||||
|
||||
err = confix.CheckValid("client.toml", []byte{})
|
||||
assert.Error(t, err, "client config invalid: chain-id is empty")
|
||||
|
||||
err = confix.CheckValid("app.toml", []byte{})
|
||||
assert.ErrorContains(t, err, "server config invalid")
|
||||
|
||||
err = confix.CheckValid("app.toml", mustReadConfig(t, "data/v0.45-app.toml"))
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = confix.CheckValid("client.toml", mustReadConfig(t, "testdata/client.toml"))
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user