Skip to content

Commit 8aca169

Browse files
committed
cli: add hex option to debug keys
This was used in #29252 and I imagine I'll want to use it again whenever we see the consistency checker fail in the future. Release note: None
1 parent 9d69acb commit 8aca169

File tree

5 files changed

+69
-9
lines changed

5 files changed

+69
-9
lines changed

pkg/cli/cli_debug_test.go

+45
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@
1414

1515
package cli
1616

17+
import (
18+
"path/filepath"
19+
"strings"
20+
"testing"
21+
22+
"github.com/cockroachdb/cockroach/pkg/testutils"
23+
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
24+
)
25+
1726
func Example_debug_decode_key_value() {
1827
cliTest{}.RunWithArgs([]string{"debug", "decode-value", "016b12bd8980c0b6c2e211ba5182000172647363", "884d186d03089b09120bbd8980c0b6c2e211ba51821a0bbd8980c0b9e7c5c610e99622060801100118012206080410041802220608021002180428053004"})
1928

@@ -25,3 +34,39 @@ func Example_debug_decode_key_value() {
2534
// 0.987654321,0 /Local/Range/Table/53/1/-4560243296450227838/RangeDescriptor: [/Table/53/1/-4560243296450227838, /Table/53/1/-4559358311118345834)
2635
// Raw:r1179:/Table/53/1/-45{60243296450227838-59358311118345834} [(n1,s1):1, (n4,s4):2, (n2,s2):4, next=5, gen=4]
2736
}
37+
38+
func TestDebugKeysHex(t *testing.T) {
39+
defer leaktest.AfterTest(t)()
40+
41+
baseDir, dirCleanupFn := testutils.TempDir(t)
42+
defer dirCleanupFn()
43+
44+
storePath := filepath.Join(baseDir, "store")
45+
createStore(t, storePath)
46+
47+
{
48+
out, err := cliTest{}.RunWithCapture("debug keys " + storePath +
49+
" --from hex:016b12bd898090d79e52e79b0144000174786e2d733fb094e9aa4d67974c71486b9823b900" +
50+
" --to hex:016b12bd898090d79e52e79b0144000174786e2d733fb094e9aa4d67974c71486b9823b900")
51+
if err != nil {
52+
t.Fatal(err)
53+
}
54+
// Should just output the command invocation and no results.
55+
if !strings.HasSuffix(strings.TrimSpace(out), "b900") {
56+
t.Fatalf("%q", out)
57+
}
58+
}
59+
60+
// Test invalid key, verify we get a good suggestion back.
61+
out, err := cliTest{}.RunWithCapture("debug keys " + storePath +
62+
" --to hex:01")
63+
if err != nil {
64+
t.Fatal(err)
65+
}
66+
expOut := `invalid argument "hex:01" for "--to" flag: perhaps this is just a hex-encoded key; ` +
67+
`you need an encoded MVCCKey (i.e. with a timestamp component); here's one with a zero timestamp: ` +
68+
`0100: invalid encoded mvcc key: 01`
69+
if !strings.Contains(out, expOut) {
70+
t.Fatalf("%q", out)
71+
}
72+
}

pkg/cli/cliflags/flags.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -678,17 +678,17 @@ database, insecure, certs).`,
678678
From = FlagInfo{
679679
Name: "from",
680680
Description: `
681-
Start key and format as [<format>:]<key>. Supported formats: raw, human,
681+
Start key and format as [<format>:]<key>. Supported formats: raw, hex, human,
682682
rangeID. The raw format supports escaped text. For example, "raw:\x01k" is the
683-
prefix for range local keys.`,
683+
prefix for range local keys. The hex format takes an encoded MVCCKey.`,
684684
}
685685

686686
To = FlagInfo{
687687
Name: "to",
688688
Description: `
689-
Exclusive end key and format as [<format>:]<key>. Supported formats: raw,
689+
Exclusive end key and format as [<format>:]<key>. Supported formats: raw, hex,
690690
human, rangeID. The raw format supports escaped text. For example, "raw:\x01k"
691-
is the prefix for range local keys.`}
691+
is the prefix for range local keys. The hex format takes an encoded MVCCKey.`}
692692

693693
Values = FlagInfo{
694694
Name: "values",

pkg/cli/debug.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
"bufio"
2020
"bytes"
2121
"context"
22-
"encoding/hex"
22+
gohex "encoding/hex"
2323
"fmt"
2424
"io"
2525
"math"
@@ -337,7 +337,7 @@ Decode a hexadecimal-encoded key and pretty-print it. For example:
337337
Args: cobra.ArbitraryArgs,
338338
RunE: func(cmd *cobra.Command, args []string) error {
339339
for _, arg := range args {
340-
b, err := hex.DecodeString(arg)
340+
b, err := gohex.DecodeString(arg)
341341
if err != nil {
342342
return err
343343
}
@@ -364,7 +364,7 @@ Decode and print a hexadecimal-encoded key-value pair.
364364
RunE: func(cmd *cobra.Command, args []string) error {
365365
var bs [][]byte
366366
for _, arg := range args {
367-
b, err := hex.DecodeString(arg)
367+
b, err := gohex.DecodeString(arg)
368368
if err != nil {
369369
return err
370370
}

pkg/cli/flags_util.go

+15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package cli
1616

1717
import (
1818
"context"
19+
gohex "encoding/hex"
1920
"fmt"
2021
"math"
2122
"regexp"
@@ -166,6 +167,19 @@ func (k *mvccKey) Set(value string) error {
166167
}
167168

168169
switch typ {
170+
case hex:
171+
b, err := gohex.DecodeString(keyStr)
172+
if err != nil {
173+
return err
174+
}
175+
newK, err := engine.DecodeKey(b)
176+
if err != nil {
177+
encoded := gohex.EncodeToString(engine.EncodeKey(engine.MakeMVCCMetadataKey(roachpb.Key(b))))
178+
return errors.Wrapf(err, "perhaps this is just a hex-encoded key; you need an "+
179+
"encoded MVCCKey (i.e. with a timestamp component); here's one with a zero timestamp: %s",
180+
encoded)
181+
}
182+
*k = mvccKey(newK)
169183
case raw:
170184
unquoted, err := unquoteArg(keyStr)
171185
if err != nil {
@@ -208,6 +222,7 @@ const (
208222
raw keyType = iota
209223
human
210224
rangeID
225+
hex
211226
)
212227

213228
// _keyTypes stores the names of all the possible key types.

pkg/cli/keytype_string.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)