Browse Source

etcdctlv3: json formatting

Anthony Romano 9 years ago
parent
commit
355896b00a
3 changed files with 67 additions and 11 deletions
  1. 29 10
      etcdctlv3/README.md
  2. 5 1
      etcdctlv3/command/global.go
  3. 33 0
      etcdctlv3/command/printer.go

+ 29 - 10
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
 
 - \<key\>\n\<value\>\n\<next_key\>\n\<next_value\>...
 
 - 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] \<key\> [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] <key or prefix>\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

+ 5 - 1
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)
 }
 

+ 33 - 0
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))
+}