diff --git a/etcdctlv3/README.md b/etcdctlv3/README.md index 1a6a5e0ce..7853035c4 100644 --- a/etcdctlv3/README.md +++ b/etcdctlv3/README.md @@ -13,13 +13,15 @@ PUT assigns the specified value with the specified key. If key already holds a v #### Return value -Simple reply +##### Simple reply - OK if PUT executed correctly. Exit code is zero. - Error string if PUT failed. Exit code is non-zero. -TODO: probably json and binary encoded proto +##### JSON reply + +The JSON encoding of the PUT [RPC response][etcdrpc]. #### Examples @@ -60,13 +62,15 @@ TODO: add consistency, from, prefix #### Return value -Simple reply +##### Simple reply - \\n\\n\\n\... - Error string if GET failed. Exit code is non-zero. -TODO: probably json and binary encoded proto +##### JSON reply + +The JSON encoding of the [RPC message][etcdrpc] for a key-value pair for each fetched key-value. #### Examples @@ -78,7 +82,7 @@ bar #### Notes -If any key or value contains non-printable characters or control characters, the output in text format (e.g. simple reply or JSON reply) might be ambiguous. +If any key or value contains non-printable characters or control characters, the output in text format (e.g. simple reply) might be ambiguous. Adding `--hex` to print key or value as hex encode string in text format can resolve this issue. ### DEL [options] \ [range_end] @@ -91,13 +95,15 @@ TODO: --prefix, --from #### Return value -Simple reply +##### Simple reply - The number of keys that were removed in decimal if DEL executed correctly. Exit code is zero. - Error string if DEL failed. Exit code is non-zero. -TODO: probably json and binary encoded proto +##### JSON reply + +The JSON encoding of the DeleteRange [RPC response][etcdrpc]. #### Examples @@ -142,7 +148,7 @@ TODO: non-interactive mode #### Return value -Simple reply +##### Simple reply - SUCCESS if etcd processed the transaction success list, FAILURE if etcd processed the transaction failure list. @@ -150,7 +156,9 @@ Simple reply - Additional error string if TXN failed. Exit code is non-zero. -TODO: probably json and binary encoded proto +##### JSON reply + +The JSON encoding of the Txn [RPC response][etcdrpc]. #### Examples @@ -205,7 +213,9 @@ watch [options] \n - Additional error string if WATCH failed. Exit code is non-zero. -TODO: probably json and binary encoded proto +##### JSON reply + +The JSON encoding of the [RPC message][storagerpc] for each received Event. #### Examples @@ -265,3 +275,12 @@ Simple reply ``` [mirror]: ./doc/mirror_maker.md + + +## Notes + +- JSON encoding for keys and values uses base64 since they are byte strings. + + +[etcdrpc]: ../etcdserver/etcdserverpb/rpc.proto +[storagerpc]: ../storage/storagepb/kv.proto diff --git a/etcdctlv3/command/global.go b/etcdctlv3/command/global.go index 4278997a7..e93510647 100644 --- a/etcdctlv3/command/global.go +++ b/etcdctlv3/command/global.go @@ -63,7 +63,11 @@ func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client { } isHex, _ := cmd.Flags().GetBool("hex") - display = &simplePrinter{isHex: isHex} + outputType, _ := cmd.Flags().GetString("write-out") + if display = NewPrinter(outputType, isHex); display == nil { + ExitWithError(ExitBadFeature, errors.New("unsupported output format")) + } + return mustClient(endpoint, cert, key, cacert) } diff --git a/etcdctlv3/command/printer.go b/etcdctlv3/command/printer.go index 9c77c92b8..091ef2eba 100644 --- a/etcdctlv3/command/printer.go +++ b/etcdctlv3/command/printer.go @@ -15,7 +15,9 @@ package command import ( + "encoding/json" "fmt" + "os" v3 "github.com/coreos/etcd/clientv3" pb "github.com/coreos/etcd/etcdserver/etcdserverpb" @@ -29,6 +31,16 @@ type printer interface { Watch(v3.WatchResponse) } +func NewPrinter(printerType string, isHex bool) printer { + switch printerType { + case "simple": + return &simplePrinter{isHex: isHex} + case "json": + return &jsonPrinter{} + } + return nil +} + type simplePrinter struct { isHex bool } @@ -75,3 +87,24 @@ func (s *simplePrinter) Watch(resp v3.WatchResponse) { printKV(s.isHex, e.Kv) } } + +type jsonPrinter struct{} + +func (p *jsonPrinter) Del(r v3.DeleteResponse) { printJSON(r) } +func (p *jsonPrinter) Get(r v3.GetResponse) { + for _, kv := range r.Kvs { + printJSON(kv) + } +} +func (p *jsonPrinter) Put(r v3.PutResponse) { printJSON(r) } +func (p *jsonPrinter) Txn(r v3.TxnResponse) { printJSON(r) } +func (p *jsonPrinter) Watch(r v3.WatchResponse) { printJSON(r) } + +func printJSON(v interface{}) { + b, err := json.Marshal(v) + if err != nil { + fmt.Fprintf(os.Stderr, "%v\n", err) + return + } + fmt.Println(string(b)) +}