Add configuration diff tool. (#8298)

* Add diff outputs as testdata.
* Normalize all samples to kebabs.
This commit is contained in:
M. J. Fromberger
2022-04-11 12:41:27 -07:00
committed by GitHub
parent 0e32ad9e5c
commit 9ec30ecc0c
8 changed files with 244 additions and 3 deletions

2
go.mod
View File

@@ -73,7 +73,7 @@ require (
github.com/charithe/durationcheck v0.0.9 // indirect
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect
github.com/containerd/continuity v0.2.1 // indirect
github.com/creachadair/tomledit v0.0.13
github.com/creachadair/tomledit v0.0.15
github.com/daixiang0/gci v0.3.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denis-tingaikin/go-header v0.4.3 // indirect

4
go.sum
View File

@@ -225,8 +225,8 @@ github.com/creachadair/atomicfile v0.2.4 h1:GRjpQLmz/78I4+nBQpGMFrRa9yrL157AUTrA
github.com/creachadair/atomicfile v0.2.4/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.13 h1:UKsFVZbCKH/8vIh50cDEtRu2KuBync5v1WXMYb+HSJ0=
github.com/creachadair/tomledit v0.0.13/go.mod h1:gvtfnSZLa+YNQD28vaPq0Nk12bRxEhmUdBzAWn+EGF4=
github.com/creachadair/tomledit v0.0.15 h1:g/qlpwSFIXEngyz8gcTEGZtvdGBLHODwV+Z0BFILVxw=
github.com/creachadair/tomledit v0.0.15/go.mod h1:gvtfnSZLa+YNQD28vaPq0Nk12bRxEhmUdBzAWn+EGF4=
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/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=

View File

@@ -0,0 +1,152 @@
// Program condiff performs a keyspace diff on two TOML documents.
package main
import (
"context"
"flag"
"fmt"
"io"
"log"
"os"
"path/filepath"
"sort"
"strings"
"github.com/creachadair/tomledit"
"github.com/creachadair/tomledit/parser"
"github.com/creachadair/tomledit/transform"
)
var (
doDesnake = flag.Bool("desnake", false, "Convert snake_case to kebab-case before comparing")
)
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, `Usage: %[1]s [options] f1 f2
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.
Options:
`, filepath.Base(os.Args[0]))
flag.PrintDefaults()
}
}
func main() {
flag.Parse()
if flag.NArg() != 2 {
log.Fatalf("Usage: %[1]s <lhs> <rhs>", filepath.Base(os.Args[0]))
}
lhs := mustParse(flag.Arg(0))
rhs := mustParse(flag.Arg(1))
if *doDesnake {
log.Printf("Converting all names from snake_case to kebab-case")
fix := transform.SnakeToKebab()
_ = fix(context.Background(), lhs)
_ = fix(context.Background(), rhs)
}
diffDocs(os.Stdout, lhs, rhs)
}
func mustParse(path string) *tomledit.Document {
f, err := os.Open(path)
if err != nil {
log.Fatalf("Opening TOML input: %v", err)
}
defer f.Close()
doc, err := tomledit.Parse(f)
if err != nil {
log.Fatalf("Parsing %q: %v", path, err)
}
return doc
}
func allKeys(s *tomledit.Section) []string {
var keys []string
s.Scan(func(key parser.Key, _ *tomledit.Entry) bool {
keys = append(keys, key.String())
return true
})
return keys
}
const (
delSection = "-S"
delMapping = "-M"
addSection = "+S"
addMapping = "+M"
delMapSep = "\n" + delMapping + " "
addMapSep = "\n" + addMapping + " "
)
func diffDocs(w io.Writer, lhs, rhs *tomledit.Document) {
diffSections(w, 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) {
fmt.Fprintln(w, delSection, lsec[i].Name)
fmt.Fprintln(w, delMapping, strings.Join(allKeys(lsec[i]), delMapSep))
i++
} else if rsec[j].Name.Before(lsec[i].Name) {
fmt.Fprintln(w, addSection, rsec[j].Name)
fmt.Fprintln(w, addMapping, strings.Join(allKeys(rsec[j]), addMapSep))
j++
} else {
diffSections(w, lsec[i], rsec[j])
i++
j++
}
}
for ; i < len(lsec); i++ {
fmt.Fprintln(w, delSection, lsec[i].Name)
fmt.Fprintln(w, delMapping, strings.Join(allKeys(lsec[i]), delMapSep))
}
for ; j < len(rsec); j++ {
fmt.Fprintln(w, addSection, rsec[j].Name)
fmt.Fprintln(w, addMapping, strings.Join(allKeys(rsec[j]), addMapSep))
}
}
func diffSections(w io.Writer, lhs, rhs *tomledit.Section) {
diffKeys(w, allKeys(lhs), allKeys(rhs))
}
func diffKeys(w io.Writer, lhs, rhs []string) {
sort.Strings(lhs)
sort.Strings(rhs)
i, j := 0, 0
for i < len(lhs) && j < len(rhs) {
if lhs[i] < rhs[j] {
fmt.Fprintln(w, delMapping, lhs[i])
i++
} else if lhs[i] > rhs[j] {
fmt.Fprintln(w, addMapping, rhs[j])
j++
} else {
i++
j++
}
}
for ; i < len(lhs); i++ {
fmt.Fprintln(w, delMapping, lhs[i])
}
for ; j < len(rhs); j++ {
fmt.Fprintln(w, addMapping, rhs[j])
}
}

View File

@@ -0,0 +1,5 @@
+S fastsync
+M fastsync.version
+M mempool.max-tx-bytes
+M rpc.max-body-bytes
+M rpc.max-header-bytes

View File

@@ -0,0 +1,6 @@
+M p2p.persistent-peers-max-dial-period
+M p2p.unconditional-peer-ids
+M tx-index.index-all-keys
-M tx-index.index-all-tags
+M tx-index.index-keys
-M tx-index.index-tags

20
scripts/confix/testdata/diff-33-34.txt vendored Normal file
View File

@@ -0,0 +1,20 @@
-M prof-laddr
+M consensus.double-sign-check-height
+M mempool.keep-invalid-txs-in-cache
+M mempool.max-batch-bytes
+M rpc.experimental-close-on-slow-client
+M rpc.experimental-subscription-buffer-size
+M rpc.experimental-websocket-write-buffer-size
+M rpc.pprof-laddr
+S statesync
+M statesync.enable
+M statesync.rpc-servers
+M statesync.trust-height
+M statesync.trust-hash
+M statesync.trust-period
+M statesync.discovery-time
+M statesync.temp-dir
+M statesync.chunk-request-timeout
+M statesync.chunk-fetchers
-M tx-index.index-all-keys
-M tx-index.index-keys

31
scripts/confix/testdata/diff-34-35.txt vendored Normal file
View File

@@ -0,0 +1,31 @@
-M fast-sync
+M mode
-M priv-validator-key-file
-M priv-validator-laddr
-M priv-validator-state-file
+S blocksync
+M blocksync.enable
+M blocksync.version
-S fastsync
-M fastsync.version
+M mempool.ttl-duration
+M mempool.ttl-num-blocks
+M mempool.version
-M mempool.wal-dir
+M p2p.bootstrap-peers
+M p2p.max-connections
+M p2p.max-incoming-connection-attempts
+M p2p.queue-type
-M p2p.seed-mode
+M p2p.use-legacy
+S priv-validator
+M priv-validator.key-file
+M priv-validator.state-file
+M priv-validator.laddr
+M priv-validator.client-certificate-file
+M priv-validator.client-key-file
+M priv-validator.root-ca-file
-M statesync.chunk-fetchers
+M statesync.fetchers
+M statesync.use-p2p
+M tx-index.psql-conn

27
scripts/confix/testdata/diff-35-36.txt vendored Normal file
View File

@@ -0,0 +1,27 @@
-S blocksync
-M blocksync.enable
-M blocksync.version
-M consensus.skip-timeout-commit
-M consensus.timeout-commit
-M consensus.timeout-precommit
-M consensus.timeout-precommit-delta
-M consensus.timeout-prevote
-M consensus.timeout-prevote-delta
-M consensus.timeout-propose
-M consensus.timeout-propose-delta
-M mempool.version
-M p2p.addr-book-file
-M p2p.addr-book-strict
-M p2p.max-num-inbound-peers
-M p2p.max-num-outbound-peers
-M p2p.persistent-peers-max-dial-period
-M p2p.unconditional-peer-ids
-M p2p.use-legacy
+M rpc.event-log-max-items
+M rpc.event-log-window-size
-M rpc.experimental-close-on-slow-client
+M rpc.experimental-disable-websocket
-M rpc.experimental-subscription-buffer-size
-M rpc.experimental-websocket-write-buffer-size
-M rpc.grpc-laddr
-M rpc.grpc-max-open-connections