confix: convert tx-index.indexer from string to array (#8342)

The format of this config value was changed in v0.35.

- Move plan to its own file (for ease of reading).
- Convert indexer string to an array if not already done.
This commit is contained in:
M. J. Fromberger
2022-04-14 06:20:49 -07:00
committed by GitHub
parent 68c9efdb82
commit 69874c2050
2 changed files with 225 additions and 182 deletions

View File

@@ -12,11 +12,9 @@ import (
"log"
"os"
"path/filepath"
"strings"
"github.com/creachadair/atomicfile"
"github.com/creachadair/tomledit"
"github.com/creachadair/tomledit/parser"
"github.com/creachadair/tomledit/transform"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/config"
@@ -78,186 +76,6 @@ func main() {
}
}
var plan = transform.Plan{
{
// Since https://github.com/tendermint/tendermint/pull/5777.
Desc: "Rename everything from snake_case to kebab-case",
T: transform.SnakeToKebab(),
},
{
// [fastsync] renamed in https://github.com/tendermint/tendermint/pull/6896.
// [blocksync] removed in https://github.com/tendermint/tendermint/pull/7159.
Desc: "Remove [fastsync] and [blocksync] sections",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
doc.First("fast-sync").Remove()
transform.FindTable(doc, "fastsync").Remove()
transform.FindTable(doc, "blocksync").Remove()
return nil
}),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/6241.
Desc: `Add top-level mode setting (default "full")`,
T: transform.EnsureKey(nil, &parser.KeyValue{
Block: parser.Comments{"Mode of Node: full | validator | seed"},
Name: parser.Key{"mode"},
Value: parser.MustValue(`"full"`),
}),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/7121.
Desc: "Remove gRPC settings from the [rpc] section",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
doc.First("rpc", "grpc-laddr").Remove()
doc.First("rpc", "grpc-max-open-connections").Remove()
return nil
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/8217.
Desc: "Remove per-node consensus timeouts (converted to consensus parameters)",
T: transform.Remove(
parser.Key{"consensus", "skip-timeout-commit"},
parser.Key{"consensus", "timeout-commit"},
parser.Key{"consensus", "timeout-precommit"},
parser.Key{"consensus", "timeout-precommit-delta"},
parser.Key{"consensus", "timeout-prevote"},
parser.Key{"consensus", "timeout-prevote-delta"},
parser.Key{"consensus", "timeout-propose"},
parser.Key{"consensus", "timeout-propose-delta"},
),
ErrorOK: true,
},
{
// Removed wal-dir: https://github.com/tendermint/tendermint/pull/6396.
// Removed version: https://github.com/tendermint/tendermint/pull/7171.
Desc: "Remove vestigial mempool.wal-dir settings",
T: transform.Remove(
parser.Key{"mempool", "wal-dir"},
parser.Key{"mempool", "version"},
),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/6323.
Desc: "Add new [p2p] queue-type setting",
T: transform.EnsureKey(parser.Key{"p2p"}, &parser.KeyValue{
Block: parser.Comments{"Select the p2p internal queue"},
Name: parser.Key{"queue-type"},
Value: parser.MustValue(`"priority"`),
}),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/6353.
Desc: "Add [p2p] connection count and rate limit settings",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
tab := transform.FindTable(doc, "p2p")
if tab == nil {
return errors.New("p2p table not found")
}
transform.InsertMapping(tab.Section, &parser.KeyValue{
Block: parser.Comments{"Maximum number of connections (inbound and outbound)."},
Name: parser.Key{"max-connections"},
Value: parser.MustValue("64"),
}, false)
transform.InsertMapping(tab.Section, &parser.KeyValue{
Block: parser.Comments{
"Rate limits the number of incoming connection attempts per IP address.",
},
Name: parser.Key{"max-incoming-connection-attempts"},
Value: parser.MustValue("100"),
}, false)
return nil
}),
},
{
// Added "chunk-fetchers" https://github.com/tendermint/tendermint/pull/6566.
// This value was backported into v0.34.11 (modulo casing).
// Renamed to "fetchers" https://github.com/tendermint/tendermint/pull/6587.
Desc: "Rename statesync.chunk-fetchers to statesync.fetchers",
T: transform.Func(func(ctx context.Context, doc *tomledit.Document) error {
// If the key already exists, rename it preserving its value.
if found := doc.First("statesync", "chunk-fetchers"); found != nil {
found.KeyValue.Name = parser.Key{"fetchers"}
return nil
}
// Otherwise, add it.
return transform.EnsureKey(parser.Key{"statesync"}, &parser.KeyValue{
Block: parser.Comments{
"The number of concurrent chunk and block fetchers to run (default: 4).",
},
Name: parser.Key{"fetchers"},
Value: parser.MustValue("4"),
})(ctx, doc)
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/6807.
// Backported into v0.34.13 (modulo casing).
Desc: "Add statesync.use-p2p setting",
T: transform.EnsureKey(parser.Key{"statesync"}, &parser.KeyValue{
Block: parser.Comments{
"# State sync uses light client verification to verify state. This can be done either through the",
"# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer",
"# will be used.",
},
Name: parser.Key{"use-p2p"},
Value: parser.MustValue("false"),
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/6462.
Desc: "Move priv-validator settings under [priv-validator]",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
const pvPrefix = "priv-validator-"
var found []*tomledit.Entry
doc.Scan(func(key parser.Key, e *tomledit.Entry) bool {
if e.IsSection() && !e.IsGlobal() {
return false // no more candidates
} else if len(key) == 1 && strings.HasPrefix(key[0], pvPrefix) {
found = append(found, e)
}
return true
})
if len(found) == 0 {
return nil // nothing to do
}
// Now that we know we have work to do, find the target table.
var sec *tomledit.Section
if dst := transform.FindTable(doc, "priv-validator"); dst == nil {
// If the table doesn't exist, create it. Old config files
// probably will not have it, so plug in the comment too.
sec = &tomledit.Section{
Heading: &parser.Heading{
Block: parser.Comments{
"#######################################################",
"### Priv Validator Configuration ###",
"#######################################################",
},
Name: parser.Key{"priv-validator"},
},
}
doc.Sections = append(doc.Sections, sec)
} else {
sec = dst.Section
}
for _, e := range found {
e.Remove()
e.Name = parser.Key{strings.TrimPrefix(e.Name[0], pvPrefix)}
sec.Items = append(sec.Items, e.KeyValue)
}
return nil
}),
},
}
// ApplyFixes transforms doc and reports whether it succeeded.
func ApplyFixes(ctx context.Context, doc *tomledit.Document) error {
// Check what version of Tendermint might have created this config file, as

225
scripts/confix/plan.go Normal file
View File

@@ -0,0 +1,225 @@
package main
import (
"context"
"errors"
"fmt"
"strings"
"github.com/creachadair/tomledit"
"github.com/creachadair/tomledit/parser"
"github.com/creachadair/tomledit/transform"
)
// The plan is the sequence of transformation steps that should be applied, in
// the given order, to convert a configuration file to be compatible with the
// current version of the config grammar.
//
// Transformation steps are specific to the target config version. For this
// reason, you must exercise caution when backporting changes to this script
// into older releases.
var plan = transform.Plan{
{
// Since https://github.com/tendermint/tendermint/pull/5777.
Desc: "Rename everything from snake_case to kebab-case",
T: transform.SnakeToKebab(),
},
{
// [fastsync] renamed in https://github.com/tendermint/tendermint/pull/6896.
// [blocksync] removed in https://github.com/tendermint/tendermint/pull/7159.
Desc: "Remove [fastsync] and [blocksync] sections",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
doc.First("fast-sync").Remove()
transform.FindTable(doc, "fastsync").Remove()
transform.FindTable(doc, "blocksync").Remove()
return nil
}),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/6241.
Desc: `Add top-level mode setting (default "full")`,
T: transform.EnsureKey(nil, &parser.KeyValue{
Block: parser.Comments{"Mode of Node: full | validator | seed"},
Name: parser.Key{"mode"},
Value: parser.MustValue(`"full"`),
}),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/7121.
Desc: "Remove gRPC settings from the [rpc] section",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
doc.First("rpc", "grpc-laddr").Remove()
doc.First("rpc", "grpc-max-open-connections").Remove()
return nil
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/8217.
Desc: "Remove per-node consensus timeouts (converted to consensus parameters)",
T: transform.Remove(
parser.Key{"consensus", "skip-timeout-commit"},
parser.Key{"consensus", "timeout-commit"},
parser.Key{"consensus", "timeout-precommit"},
parser.Key{"consensus", "timeout-precommit-delta"},
parser.Key{"consensus", "timeout-prevote"},
parser.Key{"consensus", "timeout-prevote-delta"},
parser.Key{"consensus", "timeout-propose"},
parser.Key{"consensus", "timeout-propose-delta"},
),
ErrorOK: true,
},
{
// Removed wal-dir: https://github.com/tendermint/tendermint/pull/6396.
// Removed version: https://github.com/tendermint/tendermint/pull/7171.
Desc: "Remove vestigial mempool.wal-dir settings",
T: transform.Remove(
parser.Key{"mempool", "wal-dir"},
parser.Key{"mempool", "version"},
),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/6323.
Desc: "Add new [p2p] queue-type setting",
T: transform.EnsureKey(parser.Key{"p2p"}, &parser.KeyValue{
Block: parser.Comments{"Select the p2p internal queue"},
Name: parser.Key{"queue-type"},
Value: parser.MustValue(`"priority"`),
}),
ErrorOK: true,
},
{
// Since https://github.com/tendermint/tendermint/pull/6353.
Desc: "Add [p2p] connection count and rate limit settings",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
tab := transform.FindTable(doc, "p2p")
if tab == nil {
return errors.New("p2p table not found")
}
transform.InsertMapping(tab.Section, &parser.KeyValue{
Block: parser.Comments{"Maximum number of connections (inbound and outbound)."},
Name: parser.Key{"max-connections"},
Value: parser.MustValue("64"),
}, false)
transform.InsertMapping(tab.Section, &parser.KeyValue{
Block: parser.Comments{
"Rate limits the number of incoming connection attempts per IP address.",
},
Name: parser.Key{"max-incoming-connection-attempts"},
Value: parser.MustValue("100"),
}, false)
return nil
}),
},
{
// Added "chunk-fetchers" https://github.com/tendermint/tendermint/pull/6566.
// This value was backported into v0.34.11 (modulo casing).
// Renamed to "fetchers" https://github.com/tendermint/tendermint/pull/6587.
Desc: "Rename statesync.chunk-fetchers to statesync.fetchers",
T: transform.Func(func(ctx context.Context, doc *tomledit.Document) error {
// If the key already exists, rename it preserving its value.
if found := doc.First("statesync", "chunk-fetchers"); found != nil {
found.KeyValue.Name = parser.Key{"fetchers"}
return nil
}
// Otherwise, add it.
return transform.EnsureKey(parser.Key{"statesync"}, &parser.KeyValue{
Block: parser.Comments{
"The number of concurrent chunk and block fetchers to run (default: 4).",
},
Name: parser.Key{"fetchers"},
Value: parser.MustValue("4"),
})(ctx, doc)
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/6807.
// Backported into v0.34.13 (modulo casing).
Desc: "Add statesync.use-p2p setting",
T: transform.EnsureKey(parser.Key{"statesync"}, &parser.KeyValue{
Block: parser.Comments{
"# State sync uses light client verification to verify state. This can be done either through the",
"# P2P layer or RPC layer. Set this to true to use the P2P layer. If false (default), RPC layer",
"# will be used.",
},
Name: parser.Key{"use-p2p"},
Value: parser.MustValue("false"),
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/6462.
Desc: "Move priv-validator settings under [priv-validator]",
T: transform.Func(func(_ context.Context, doc *tomledit.Document) error {
const pvPrefix = "priv-validator-"
var found []*tomledit.Entry
doc.Global.Scan(func(key parser.Key, e *tomledit.Entry) bool {
if len(key) == 1 && strings.HasPrefix(key[0], pvPrefix) {
found = append(found, e)
}
return true
})
if len(found) == 0 {
return nil // nothing to do
}
// Now that we know we have work to do, find the target table.
var sec *tomledit.Section
if dst := transform.FindTable(doc, "priv-validator"); dst == nil {
// If the table doesn't exist, create it. Old config files
// probably will not have it, so plug in the comment too.
sec = &tomledit.Section{
Heading: &parser.Heading{
Block: parser.Comments{
"#######################################################",
"### Priv Validator Configuration ###",
"#######################################################",
},
Name: parser.Key{"priv-validator"},
},
}
doc.Sections = append(doc.Sections, sec)
} else {
sec = dst.Section
}
for _, e := range found {
e.Remove()
e.Name = parser.Key{strings.TrimPrefix(e.Name[0], pvPrefix)}
sec.Items = append(sec.Items, e.KeyValue)
}
return nil
}),
},
{
// Since https://github.com/tendermint/tendermint/pull/6411.
Desc: "Convert tx-index.indexer from a string to a list of strings",
T: transform.Func(func(ctx context.Context, doc *tomledit.Document) error {
idx := doc.First("tx-index", "indexer")
if idx == nil {
// No previous indexer setting: Default to ["null"] per #8222.
return transform.EnsureKey(parser.Key{"tx-index"}, &parser.KeyValue{
Block: parser.Comments{"The backend database list to back the indexer."},
Name: parser.Key{"indexer"},
Value: parser.MustValue(`["null"]`),
})(ctx, doc)
}
// Versions prior to v0.35 had a string value here, v0.35 and onward
// use an array of strings.
switch idx.KeyValue.Value.X.(type) {
case parser.Array:
// OK, this is already up-to-date.
return nil
case parser.Token:
// Wrap the value in a single-element array.
idx.KeyValue.Value.X = parser.Array{idx.KeyValue.Value}
return nil
}
return fmt.Errorf("unrecognized value: %v", idx.KeyValue)
}),
},
}