// memberUpdateCommandFunc executes the "member update" command. func memberUpdateCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("member ID is not provided")) } id, err := strconv.ParseUint(args[0], 16, 64) if err != nil { ExitWithError(ExitBadArgs, fmt.Errorf("bad member ID arg (%v), expecting ID in Hex", err)) } if len(memberPeerURLs) == 0 { ExitWithError(ExitBadArgs, fmt.Errorf("member peer urls not provided.")) } urls := strings.Split(memberPeerURLs, ",") endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } mc := pb.NewClusterClient(conn) resp, err := mc.MemberUpdate(context.TODO(), &pb.MemberUpdateRequest{ID: uint64(id), PeerURLs: urls}) if err != nil { ExitWithError(ExitError, err) } fmt.Printf("Member %16x updated in cluster %16x\n", id, resp.Header.ClusterId) }
// memberListCommandFunc executes the "member list" command. func memberListCommandFunc(cmd *cobra.Command, args []string) { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } mc := pb.NewClusterClient(conn) resp, err := mc.MemberList(context.TODO(), &pb.MemberListRequest{}) if err != nil { ExitWithError(ExitError, err) } // use https://github.com/olekukonko/tablewriter to print out a pretty table? for _, m := range resp.Members { if len(m.Name) == 0 { fmt.Printf("%16x[unstarted]: peerURLs=%s\n", m.ID, strings.Join(m.PeerURLs, ",")) } else { fmt.Printf("%16x: name=%s peerURLs=%s clientURLs=%s\n", m.ID, m.Name, strings.Join(m.PeerURLs, ","), strings.Join(m.ClientURLs, ",")) } } }
// memberRemoveCommandFunc executes the "member remove" command. func memberRemoveCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("member ID is not provided")) } id, err := strconv.ParseUint(args[0], 16, 64) if err != nil { ExitWithError(ExitBadArgs, fmt.Errorf("bad member ID arg (%v), expecting ID in Hex", err)) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } mc := pb.NewClusterClient(conn) resp, err := mc.MemberRemove(context.TODO(), &pb.MemberRemoveRequest{ID: uint64(id)}) if err != nil { ExitWithError(ExitError, err) } fmt.Printf("Member %16x removed from cluster %16x\n", id, resp.Header.ClusterId) }
// deleteRangeCommandFunc executes the "deleteRange" command. func deleteRangeCommandFunc(cmd *cobra.Command, args []string) { if len(args) == 0 { ExitWithError(ExitBadArgs, fmt.Errorf("delete-range command needs arguments.")) } var rangeEnd []byte key := []byte(args[0]) if len(args) > 1 { rangeEnd = []byte(args[1]) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } kv := pb.NewKVClient(conn) req := &pb.DeleteRangeRequest{Key: key, RangeEnd: rangeEnd} kv.DeleteRange(context.Background(), req) if rangeEnd != nil { fmt.Printf("range [%s, %s) is deleted\n", string(key), string(rangeEnd)) } else { fmt.Printf("key %s is deleted\n", string(key)) } }
// rangeCommandFunc executes the "range" command. func rangeCommandFunc(cmd *cobra.Command, args []string) { if len(args) == 0 { ExitWithError(ExitBadArgs, fmt.Errorf("range command needs arguments.")) } var rangeEnd []byte key := []byte(args[0]) if len(args) > 1 { rangeEnd = []byte(args[1]) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } kv := pb.NewKVClient(conn) req := &pb.RangeRequest{Key: key, RangeEnd: rangeEnd} resp, err := kv.Range(context.Background(), req) for _, kv := range resp.Kvs { fmt.Printf("%s %s\n", string(kv.Key), string(kv.Value)) } }
// txnCommandFunc executes the "txn" command. func txnCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 0 { ExitWithError(ExitBadArgs, fmt.Errorf("txn command does not accept argument.")) } reader := bufio.NewReader(os.Stdin) next := compareState txn := &pb.TxnRequest{} for next != nil { next = next(txn, reader) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } kv := pb.NewKVClient(conn) resp, err := kv.Txn(context.Background(), txn) if err != nil { ExitWithError(ExitError, err) } if resp.Succeeded { fmt.Println("executed success request list") } else { fmt.Println("executed failure request list") } }
// putCommandFunc executes the "put" command. func putCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 2 { ExitWithError(ExitBadArgs, fmt.Errorf("put command needs 2 arguments.")) } id, err := strconv.ParseInt(leaseStr, 16, 64) if err != nil { ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err)) } key := []byte(args[0]) value := []byte(args[1]) endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } kv := pb.NewKVClient(conn) req := &pb.PutRequest{Key: key, Value: value, Lease: id} kv.Put(context.Background(), req) fmt.Printf("%s %s\n", key, value) }
// memberAddCommandFunc executes the "member add" command. func memberAddCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("member name not provided.")) } if len(memberPeerURLs) == 0 { ExitWithError(ExitBadArgs, fmt.Errorf("member peer urls not provided.")) } urls := strings.Split(memberPeerURLs, ",") endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } mc := pb.NewClusterClient(conn) resp, err := mc.MemberAdd(context.TODO(), &pb.MemberAddRequest{PeerURLs: urls}) if err != nil { ExitWithError(ExitError, err) } fmt.Printf("Member %16x added to cluster %16x\n", args[0], resp.Member.ID, resp.Header.ClusterId) }
// leaseRevokeCommandFunc executes the "lease create" command. func leaseRevokeCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("lease revoke command needs 1 argument")) } id, err := strconv.ParseInt(args[0], 16, 64) if err != nil { ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err)) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } lease := pb.NewLeaseClient(conn) req := &pb.LeaseRevokeRequest{ID: id} _, err = lease.LeaseRevoke(context.Background(), req) if err != nil { fmt.Fprintf(os.Stderr, "failed to revoke lease (%v)\n", err) return } fmt.Printf("lease %016x revoked\n", id) }
// leaseCreateCommandFunc executes the "lease create" command. func leaseCreateCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("lease create command needs TTL argument.")) } ttl, err := strconv.ParseInt(args[0], 10, 64) if err != nil { ExitWithError(ExitBadArgs, fmt.Errorf("bad TTL (%v)", err)) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } lease := pb.NewLeaseClient(conn) req := &pb.LeaseCreateRequest{TTL: ttl} resp, err := lease.LeaseCreate(context.Background(), req) if err != nil { fmt.Fprintf(os.Stderr, "failed to create lease (%v)\n", err) return } fmt.Printf("lease %016x created with TTL(%ds)\n", resp.ID, resp.TTL) }
// watchCommandFunc executes the "watch" command. func watchCommandFunc(cmd *cobra.Command, args []string) { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitInvalidInput, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } wAPI := pb.NewWatchClient(conn) wStream, err := wAPI.Watch(context.TODO()) if err != nil { ExitWithError(ExitBadConnection, err) } go recvLoop(wStream) reader := bufio.NewReader(os.Stdin) for { l, err := reader.ReadString('\n') if err != nil { ExitWithError(ExitInvalidInput, fmt.Errorf("Error reading watch request line: %v", err)) } l = strings.TrimSuffix(l, "\n") // TODO: support start and end revision segs := strings.Split(l, " ") if len(segs) != 2 { fmt.Fprintf(os.Stderr, "Invalid watch request format: use \"watch [key]\", \"watchprefix [prefix]\" or \"cancel [watcher ID]\"\n") continue } var r *pb.WatchRequest switch segs[0] { case "watch": r = &pb.WatchRequest{CreateRequest: &pb.WatchCreateRequest{Key: []byte(segs[1])}} case "watchprefix": r = &pb.WatchRequest{CreateRequest: &pb.WatchCreateRequest{Prefix: []byte(segs[1])}} case "cancel": id, perr := strconv.ParseInt(segs[1], 10, 64) if perr != nil { fmt.Fprintf(os.Stderr, "Invalid cancel ID (%v)\n", perr) continue } r = &pb.WatchRequest{CancelRequest: &pb.WatchCancelRequest{WatchId: id}} default: fmt.Fprintf(os.Stderr, "Invalid watch request type: use watch, watchprefix or cancel\n") continue } err = wStream.Send(r) if err != nil { fmt.Fprintf(os.Stderr, "Error sending request to server: %v\n", err) } } }
func mustClient(cmd *cobra.Command) *clientv3.Client { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } client, err := clientv3.NewFromURL(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } return client }
// watchCommandFunc executes the "watch" command. func watchCommandFunc(cmd *cobra.Command, args []string) { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitInvalidInput, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } wAPI := pb.NewWatchClient(conn) wStream, err := wAPI.Watch(context.TODO()) if err != nil { ExitWithError(ExitBadConnection, err) } go recvLoop(wStream) reader := bufio.NewReader(os.Stdin) for { l, err := reader.ReadString('\n') if err != nil { ExitWithError(ExitInvalidInput, fmt.Errorf("Error reading watch request line: %v", err)) } l = strings.TrimSuffix(l, "\n") // TODO: support start and end revision segs := strings.Split(l, " ") if len(segs) != 2 { fmt.Fprintf(os.Stderr, "Invalid watch request format: use watch key or watchprefix prefix\n") continue } var r *pb.WatchRequest switch segs[0] { case "watch": r = &pb.WatchRequest{Key: []byte(segs[1])} case "watchprefix": r = &pb.WatchRequest{Prefix: []byte(segs[1])} default: fmt.Fprintf(os.Stderr, "Invalid watch request format: use watch key or watchprefix prefix\n") continue } err = wStream.Send(r) if err != nil { fmt.Fprintf(os.Stderr, "Error sending request to server: %v\n", err) } } }
func mustClient(cmd *cobra.Command) *clientv3.Client { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } // set tls if any one tls option set var cfgtls *transport.TLSInfo tls := transport.TLSInfo{} if tls.CertFile, err = cmd.Flags().GetString("cert"); err == nil { cfgtls = &tls } if tls.KeyFile, err = cmd.Flags().GetString("key"); err == nil { cfgtls = &tls } if tls.CAFile, err = cmd.Flags().GetString("cacert"); err == nil { cfgtls = &tls } cfg := clientv3.Config{ Endpoints: []string{endpoint}, TLS: cfgtls, } client, err := clientv3.New(cfg) if err != nil { ExitWithError(ExitBadConnection, err) } return client }
// compactionCommandFunc executes the "compaction" command. func compactionCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("compaction command needs 1 argument.")) } rev, err := strconv.ParseInt(args[0], 10, 64) if err != nil { ExitWithError(ExitError, err) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } kv := pb.NewKVClient(conn) req := &pb.CompactionRequest{Revision: rev} kv.Compact(context.Background(), req) }
// leaseKeepAliveCommandFunc executes the "lease keep-alive" command. func leaseKeepAliveCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { ExitWithError(ExitBadArgs, fmt.Errorf("lease keep-alive command needs lease ID as argument")) } id, err := strconv.ParseInt(args[0], 16, 64) if err != nil { ExitWithError(ExitBadArgs, fmt.Errorf("bad lease ID arg (%v), expecting ID in Hex", err)) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } lease := pb.NewLeaseClient(conn) kStream, err := lease.LeaseKeepAlive(context.TODO()) if err != nil { ExitWithError(ExitBadConnection, err) } nextC := make(chan int64, 1) go leaseKeepAliveRecvLoop(kStream, nextC) req := &pb.LeaseKeepAliveRequest{ID: id} for { err := kStream.Send(req) if err != nil { ExitWithError(ExitError, fmt.Errorf("failed to keep-alive lease (%v)", err)) } next := <-nextC time.Sleep(time.Duration(next/2) * time.Second) } }
// rangeCommandFunc executes the "range" command. func rangeCommandFunc(cmd *cobra.Command, args []string) { if len(args) == 0 { ExitWithError(ExitBadArgs, fmt.Errorf("range command needs arguments.")) } var rangeEnd []byte key := []byte(args[0]) if len(args) > 1 { rangeEnd = []byte(args[1]) } endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } sortByOrder := pb.RangeRequest_NONE sortOrder := strings.ToUpper(rangeSortOrder) switch { case sortOrder == "ASCEND": sortByOrder = pb.RangeRequest_ASCEND case sortOrder == "DESCEND": sortByOrder = pb.RangeRequest_DESCEND case sortOrder == "": sortByOrder = pb.RangeRequest_NONE default: ExitWithError(ExitBadFeature, fmt.Errorf("bad sort order %v", rangeSortOrder)) } sortByTarget := pb.RangeRequest_KEY sortTarget := strings.ToUpper(rangeSortTarget) switch { case sortTarget == "CREATE": sortByTarget = pb.RangeRequest_CREATE case sortTarget == "KEY": sortByTarget = pb.RangeRequest_KEY case sortTarget == "MODIFY": sortByTarget = pb.RangeRequest_MOD case sortTarget == "VALUE": sortByTarget = pb.RangeRequest_VALUE case sortTarget == "VERSION": sortByTarget = pb.RangeRequest_VERSION case sortTarget == "": sortByTarget = pb.RangeRequest_KEY default: ExitWithError(ExitBadFeature, fmt.Errorf("bad sort target %v", rangeSortTarget)) } conn, err := grpc.Dial(endpoint) if err != nil { ExitWithError(ExitBadConnection, err) } kv := pb.NewKVClient(conn) req := &pb.RangeRequest{ Key: key, RangeEnd: rangeEnd, SortOrder: sortByOrder, SortTarget: sortByTarget, Limit: int64(rangeLimit), } resp, err := kv.Range(context.Background(), req) for _, kv := range resp.Kvs { fmt.Printf("%s %s\n", string(kv.Key), string(kv.Value)) } }
func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } var cert, key, cacert string if cert, err = cmd.Flags().GetString("cert"); err != nil { ExitWithError(ExitBadArgs, err) } else if cert == "" && cmd.Flags().Changed("cert") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --cert option")) } if key, err = cmd.Flags().GetString("key"); err != nil { ExitWithError(ExitBadArgs, err) } else if key == "" && cmd.Flags().Changed("key") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --key option")) } if cacert, err = cmd.Flags().GetString("cacert"); err != nil { ExitWithError(ExitBadArgs, err) } else if cacert == "" && cmd.Flags().Changed("cacert") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --cacert option")) } isHex, _ := cmd.Flags().GetBool("hex") 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) }
func mustClient(cmd *cobra.Command) *clientv3.Client { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } // set tls if any one tls option set var cfgtls *transport.TLSInfo tls := transport.TLSInfo{} var file string if file, err = cmd.Flags().GetString("cert"); err == nil && file != "" { tls.CertFile = file cfgtls = &tls } else if cmd.Flags().Changed("cert") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --cert option")) } if file, err = cmd.Flags().GetString("key"); err == nil && file != "" { tls.KeyFile = file cfgtls = &tls } else if cmd.Flags().Changed("key") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --key option")) } if file, err = cmd.Flags().GetString("cacert"); err == nil && file != "" { tls.CAFile = file cfgtls = &tls } else if cmd.Flags().Changed("cacert") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --cacert option")) } cfg := clientv3.Config{ Endpoints: []string{endpoint}, TLS: cfgtls, DialTimeout: 20 * time.Second, } client, err := clientv3.New(cfg) if err != nil { ExitWithError(ExitBadConnection, err) } return client }
func mustClientFromCmd(cmd *cobra.Command) *clientv3.Client { endpoint, err := cmd.Flags().GetString("endpoint") if err != nil { ExitWithError(ExitError, err) } var cert, key, cacert string if cert, err = cmd.Flags().GetString("cert"); err != nil { ExitWithError(ExitBadArgs, err) } else if cert == "" && cmd.Flags().Changed("cert") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --cert option")) } if key, err = cmd.Flags().GetString("key"); err != nil { ExitWithError(ExitBadArgs, err) } else if key == "" && cmd.Flags().Changed("key") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --key option")) } if cacert, err = cmd.Flags().GetString("cacert"); err != nil { ExitWithError(ExitBadArgs, err) } else if cacert == "" && cmd.Flags().Changed("cacert") { ExitWithError(ExitBadArgs, errors.New("empty string is passed to --cacert option")) } return mustClient(endpoint, cert, key, cacert) }