Created
March 22, 2019 19:40
-
-
Save dasl-/4b475f3adb4b693172b29c96ed5d6a0c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/go/vt/vtctl/topo.go b/go/vt/vtctl/topo.go | |
index 547a84baa..f03ab709d 100644 | |
--- a/go/vt/vtctl/topo.go | |
+++ b/go/vt/vtctl/topo.go | |
@@ -17,8 +17,10 @@ limitations under the License. | |
package vtctl | |
import ( | |
+ "encoding/json" | |
"flag" | |
"fmt" | |
+ "github.com/golang/protobuf/jsonpb" | |
"io/ioutil" | |
"path" | |
@@ -42,7 +44,7 @@ func init() { | |
addCommand(topoGroupName, command{ | |
"TopoCat", | |
commandTopoCat, | |
- "[-cell <cell>] [-decode_proto] [-long] <path> [<path>...]", | |
+ "[-cell <cell>] [-decode_proto] [-long] [-json] <path> [<path>...]", | |
"Retrieves the file(s) at <path> from the topo service, and displays it. It can resolve wildcards, and decode the proto-encoded data."}) | |
addCommand(topoGroupName, command{ | |
@@ -54,40 +56,70 @@ func init() { | |
// DecodeContent uses the filename to imply a type, and proto-decodes | |
// the right object, then echoes it as a string. | |
-func DecodeContent(filename string, data []byte) (string, error) { | |
+func DecodeContent(filename string, data []byte, json bool) (string, error) { | |
+ message, err := decodeContentAsMessage(filename, data) | |
+ if message == nil || err != nil { | |
+ return string(data), err | |
+ } | |
+ | |
+ return proto.MarshalTextString(message), nil | |
+} | |
+ | |
+func decodeContentAsInterface(filename string, data []byte) (interface{}, error) { | |
+ message, err := decodeContentAsMessage(filename, data) | |
+ if message == nil || err != nil { | |
+ return data, err | |
+ } | |
+ | |
+ jsonText, err := new(jsonpb.Marshaler).MarshalToString(message) | |
+ if err != nil { | |
+ return data, err | |
+ } | |
+ | |
+ var obj interface{} | |
+ if err := json.Unmarshal([]byte(jsonString), &obj); err != nil { | |
+ return data, err | |
+ } | |
+ | |
+ | |
+} | |
+ | |
+func decodeContentAsMessage(filename string, data []byte) (proto.Message, error) { | |
name := path.Base(filename) | |
- var p proto.Message | |
+ var message proto.Message | |
switch name { | |
case topo.CellInfoFile: | |
- p = new(topodatapb.CellInfo) | |
+ message = new(topodatapb.CellInfo) | |
case topo.KeyspaceFile: | |
- p = new(topodatapb.Keyspace) | |
+ message = new(topodatapb.Keyspace) | |
case topo.ShardFile: | |
- p = new(topodatapb.Shard) | |
+ message = new(topodatapb.Shard) | |
case topo.VSchemaFile: | |
- p = new(vschemapb.Keyspace) | |
+ message = new(vschemapb.Keyspace) | |
case topo.ShardReplicationFile: | |
- p = new(topodatapb.ShardReplication) | |
+ message = new(topodatapb.ShardReplication) | |
case topo.TabletFile: | |
- p = new(topodatapb.Tablet) | |
+ message = new(topodatapb.Tablet) | |
case topo.SrvVSchemaFile: | |
- p = new(vschemapb.SrvVSchema) | |
+ message = new(vschemapb.SrvVSchema) | |
case topo.SrvKeyspaceFile: | |
- p = new(topodatapb.SrvKeyspace) | |
+ message = new(topodatapb.SrvKeyspace) | |
default: | |
- return string(data), nil | |
+ return nil, nil | |
} | |
- if err := proto.Unmarshal(data, p); err != nil { | |
- return string(data), err | |
+ if err := proto.Unmarshal(data, message); err != nil { | |
+ return nil, err | |
} | |
- return proto.MarshalTextString(p), nil | |
+ | |
+ return message, nil | |
} | |
func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { | |
cell := subFlags.String("cell", topo.GlobalCell, "topology cell to cat the file from. Defaults to global cell.") | |
long := subFlags.Bool("long", false, "long listing.") | |
+ json := subFlags.Bool("json", false, "json output") | |
decodeProto := subFlags.Bool("decode_proto", false, "decode proto files and display them as text") | |
subFlags.Parse(args) | |
if subFlags.NArg() == 0 { | |
@@ -107,6 +139,7 @@ func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.F | |
return err | |
} | |
hasError := false | |
+ wr.Logger().Printf("[") | |
for _, arg := range resolved { | |
data, version, err := conn.Get(ctx, arg) | |
if err != nil { | |
@@ -120,7 +153,7 @@ func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.F | |
} | |
decoded := "" | |
if *decodeProto { | |
- decoded, err = DecodeContent(arg, data) | |
+ decoded, err = DecodeContent(arg, data, json) | |
if err != nil { | |
wr.Logger().Warningf("TopoCat: cannot proto decode %v: %v", arg, err) | |
decoded = string(data) | |
@@ -128,11 +161,12 @@ func commandTopoCat(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.F | |
} else { | |
decoded = string(data) | |
} | |
- wr.Logger().Printf(decoded) | |
+ wr.Logger().Printf(decoded + ",") | |
if len(decoded) > 0 && decoded[len(decoded)-1] != '\n' && *long { | |
wr.Logger().Printf("\n") | |
} | |
} | |
+ wr.Logger().Printf("]") | |
if hasError { | |
return fmt.Errorf("TopoCat: some paths had errors") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment