From 9d40c45d2d3a1577f42cc0ac2ad80cee845fd297 Mon Sep 17 00:00:00 2001 From: Quanzheng Long Date: Tue, 16 Nov 2021 14:08:42 -0800 Subject: [PATCH] Add admin tool to decode any thrift binary into JOSN (#4634) --- tools/cli/admin.go | 14 +++++++ tools/cli/adminDBCleanCommand.go | 34 +++++++++++++++++ tools/cli/supportedDecodingTypes.go | 58 +++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 tools/cli/supportedDecodingTypes.go diff --git a/tools/cli/admin.go b/tools/cli/admin.go index 5bcd04a247f..a02e1692ad3 100644 --- a/tools/cli/admin.go +++ b/tools/cli/admin.go @@ -952,6 +952,20 @@ func newDBCommands() []cli.Command { AdminDBClean(c) }, }, + { + Name: "decode_thrift", + Usage: "decode thrift object of HEX, print into JSON if the HEX data is matching with any supported struct", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: FlagInputWithAlias, + EnvVar: "Input", + Usage: "HEX input of the binary data, you may get from database query like SELECT HEX(...) FROM ...", + }, + }, + Action: func(c *cli.Context) { + AdminDBDataDecodeThrift(c) + }, + }, } } diff --git a/tools/cli/adminDBCleanCommand.go b/tools/cli/adminDBCleanCommand.go index 3e01b06fe38..2a836e70c2a 100644 --- a/tools/cli/adminDBCleanCommand.go +++ b/tools/cli/adminDBCleanCommand.go @@ -23,6 +23,8 @@ package cli import ( + "bytes" + "encoding/hex" "encoding/json" "fmt" "io" @@ -31,6 +33,7 @@ import ( "github.com/urfave/cli" "github.com/uber/cadence/common" + "github.com/uber/cadence/common/codec" "github.com/uber/cadence/common/persistence" "github.com/uber/cadence/common/reconciliation/entity" "github.com/uber/cadence/common/reconciliation/invariant" @@ -38,6 +41,37 @@ import ( "github.com/uber/cadence/service/worker/scanner/executions" ) +// AdminDBDataDecodeThrift is the command to decode thrift binary into JSON +func AdminDBDataDecodeThrift(c *cli.Context) { + input := getRequiredOption(c, FlagInput) + + encoder := codec.NewThriftRWEncoder() + data, err := hex.DecodeString(input) + if err != nil { + ErrorAndExit("input is not a valid hex string", err) + } + found := false + for typeName, t := range decodingTypes { + err = encoder.Decode(data, t) + if err == nil { + // encoding back to confirm + data2, err := encoder.Encode(t) + if err != nil { + ErrorAndExit("cannot encode back to confirm", err) + } + if bytes.Compare(data, data2) == 0 { + fmt.Printf("=======Decode into type %v ========\n", typeName) + fmt.Println(anyToString(t, true, 0)) + found = true + } + } + } + if !found { + ErrorAndExit("input data cannot be decoded into any struct", nil) + } + +} + // AdminDBClean is the command to clean up unhealthy executions. // Input is a JSON stream provided via STDIN or a file. func AdminDBClean(c *cli.Context) { diff --git a/tools/cli/supportedDecodingTypes.go b/tools/cli/supportedDecodingTypes.go new file mode 100644 index 00000000000..1225ae5b341 --- /dev/null +++ b/tools/cli/supportedDecodingTypes.go @@ -0,0 +1,58 @@ +// The MIT License (MIT) +// +// Copyright (c) 2021 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package cli + +import ( + "github.com/uber/cadence/.gen/go/config" + "github.com/uber/cadence/.gen/go/history" + "github.com/uber/cadence/.gen/go/replicator" + "github.com/uber/cadence/.gen/go/shared" + "github.com/uber/cadence/.gen/go/sqlblobs" + "github.com/uber/cadence/common/codec" +) + +var decodingTypes = map[string]codec.ThriftObject{ + "shared.History": &shared.History{}, + "shared.HistoryEvent": &shared.HistoryEvent{}, + "shared.Memo": &shared.Memo{}, + "shared.ResetPoints": &shared.ResetPoints{}, + "shared.BadBinaries": &shared.BadBinaries{}, + "shared.VersionHistories": &shared.VersionHistories{}, + "replicator.FailoverMarkers": &replicator.FailoverMarkers{}, + "history.ProcessingQueueStates": &history.ProcessingQueueStates{}, + "config.DynamicConfigBlob": &config.DynamicConfigBlob{}, + "sqlblobs.ShardInfo": &sqlblobs.ShardInfo{}, + "sqlblobs.DomainInfo": &sqlblobs.DomainInfo{}, + "sqlblobs.HistoryTreeInfo": &sqlblobs.HistoryTreeInfo{}, + "sqlblobs.WorkflowExecutionInfo": &sqlblobs.WorkflowExecutionInfo{}, + "sqlblobs.ActivityInfo": &sqlblobs.ActivityInfo{}, + "sqlblobs.ChildExecutionInfo": &sqlblobs.ChildExecutionInfo{}, + "sqlblobs.SignalInfo": &sqlblobs.SignalInfo{}, + "sqlblobs.RequestCancelInfo": &sqlblobs.RequestCancelInfo{}, + "sqlblobs.TimerInfo": &sqlblobs.TimerInfo{}, + "sqlblobs.TaskInfo": &sqlblobs.TaskInfo{}, + "sqlblobs.TaskListInfo": &sqlblobs.TaskListInfo{}, + "sqlblobs.TransferTaskInfo": &sqlblobs.TransferTaskInfo{}, + "sqlblobs.TimerTaskInfo": &sqlblobs.TimerTaskInfo{}, + "sqlblobs.ReplicationTaskInfo": &sqlblobs.ReplicationTaskInfo{}, +} \ No newline at end of file