// 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) }
// 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) }
// 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") } }
// 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)) } }
// 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) }
// 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, ",")) } } }
// 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) }
// 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) }
// 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) }
// 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)) } }
func getSubCommands(cmd *cobra.Command) []*cobra.Command { var subCommands []*cobra.Command for _, subCmd := range cmd.Commands() { subCommands = append(subCommands, subCmd) subCommands = append(subCommands, getSubCommands(subCmd)...) } return subCommands }
// 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 rangeFunc(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args) > 2 { fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } k := args[0] end := "" if len(args) == 2 { end = args[1] } if rangeConsistency == "l" { fmt.Println("bench with linearizable range") } else if rangeConsistency == "s" { fmt.Println("bench with serializable range") } else { fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } results = make(chan result) requests := make(chan v3.Op, totalClients) bar = pb.New(rangeTotal) clients := mustCreateClients(totalClients, totalConns) bar.Format("Bom !") bar.Start() for i := range clients { wg.Add(1) go doRange(clients[i].KV, requests) } pdoneC := printReport(results) go func() { for i := 0; i < rangeTotal; i++ { opts := []v3.OpOption{v3.WithRange(end)} if rangeConsistency == "s" { opts = append(opts, v3.WithSerializable()) } op := v3.OpGet(k, opts...) requests <- op } close(requests) }() wg.Wait() bar.Finish() close(results) <-pdoneC }
func rangeFunc(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args) > 2 { fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } k := []byte(args[0]) var end []byte if len(args) == 2 { end = []byte(args[1]) } if rangeConsistency == "l" { fmt.Println("bench with linearizable range") } else if rangeConsistency == "s" { fmt.Println("bench with serializable range") } else { fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } results = make(chan result) requests := make(chan etcdserverpb.RangeRequest, totalClients) bar = pb.New(rangeTotal) clients := mustCreateClients(totalClients, totalConns) bar.Format("Bom !") bar.Start() for i := range clients { wg.Add(1) go doRange(clients[i].KV, requests) } pdoneC := printReport(results) go func() { for i := 0; i < rangeTotal; i++ { r := etcdserverpb.RangeRequest{Key: k, RangeEnd: end} if rangeConsistency == "s" { r.Serializable = true } requests <- r } close(requests) }() wg.Wait() bar.Finish() close(results) <-pdoneC }
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 }
func rangeFunc(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args) > 2 { fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } k := []byte(args[0]) var end []byte if len(args) == 1 { end = []byte(args[1]) } results = make(chan *result, rangeTotal) requests := make(chan *etcdserverpb.RangeRequest, rangeTotal) bar = pb.New(rangeTotal) conns := make([]*grpc.ClientConn, totalConns) for i := range conns { conns[i] = mustCreateConn() } clients := make([]etcdserverpb.KVClient, totalClients) for i := range clients { clients[i] = etcdserverpb.NewKVClient(conns[i%int(totalConns)]) } bar.Format("Bom !") bar.Start() for i := range clients { wg.Add(1) go doRange(clients[i], requests) } start := time.Now() for i := 0; i < rangeTotal; i++ { r := &etcdserverpb.RangeRequest{ Key: k, RangeEnd: end, } requests <- r } close(requests) wg.Wait() bar.Finish() printReport(rangeTotal, results, time.Now().Sub(start)) }
func rangeFunc(cmd *cobra.Command, args []string) { if len(args) == 0 || len(args) > 2 { fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } k := []byte(args[0]) var end []byte if len(args) == 1 { end = []byte(args[1]) } results = make(chan result) requests := make(chan etcdserverpb.RangeRequest, totalClients) bar = pb.New(rangeTotal) clients := mustCreateClients(totalClients, totalConns) bar.Format("Bom !") bar.Start() for i := range clients { wg.Add(1) go doRange(clients[i].KV, requests) } pdoneC := printReport(results) go func() { for i := 0; i < rangeTotal; i++ { requests <- etcdserverpb.RangeRequest{ Key: k, RangeEnd: end} } close(requests) }() wg.Wait() bar.Finish() close(results) <-pdoneC }
func usageFunc(cmd *cobra.Command) error { subCommands := getSubCommands(cmd) tabOut := getTabOutWithWriter(os.Stdout) commandUsageTemplate.Execute(tabOut, struct { Cmd *cobra.Command LocalFlags string GlobalFlags string SubCommands []*cobra.Command Version string }{ cmd, etcdFlagUsages(cmd.LocalFlags()), etcdFlagUsages(cmd.InheritedFlags()), subCommands, version.Version, }) tabOut.Flush() return nil }
// 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 stmFunc(cmd *cobra.Command, args []string) { if stmKeyCount <= 0 { fmt.Fprintf(os.Stderr, "expected positive --keys, got (%v)", stmKeyCount) os.Exit(1) } if stmWritePercent < 0 || stmWritePercent > 100 { fmt.Fprintf(os.Stderr, "expected [0, 100] --txn-wr-percent, got (%v)", stmWritePercent) os.Exit(1) } if stmKeysPerTxn < 0 || stmKeysPerTxn > stmKeyCount { fmt.Fprintf(os.Stderr, "expected --keys-per-txn between 0 and %v, got (%v)", stmKeyCount, stmKeysPerTxn) os.Exit(1) } switch stmIsolation { case "r": mkSTM = v3sync.NewSTMRepeatable case "l": mkSTM = v3sync.NewSTMSerializable default: fmt.Fprintln(os.Stderr, cmd.Usage()) os.Exit(1) } results = make(chan result) requests := make(chan stmApply, totalClients) bar = pb.New(stmTotal) clients := mustCreateClients(totalClients, totalConns) bar.Format("Bom !") bar.Start() for i := range clients { wg.Add(1) go doSTM(context.Background(), clients[i], requests) } pdoneC := printReport(results) go func() { for i := 0; i < stmTotal; i++ { kset := make(map[string]struct{}) for len(kset) != stmKeysPerTxn { k := make([]byte, 16) binary.PutVarint(k, int64(rand.Intn(stmKeyCount))) s := string(k) kset[s] = struct{}{} } applyf := func(s v3sync.STM) error { wrs := int(float32(len(kset)*stmWritePercent) / 100.0) for k := range kset { s.Get(k) if wrs > 0 { s.Put(k, string(mustRandBytes(stmValSize))) wrs-- } } return nil } requests <- applyf } close(requests) }() wg.Wait() bar.Finish() close(results) <-pdoneC }
func CommandFunc(cmd *cobra.Command, args []string) { defer func() { fmt.Println("deleting...") os.RemoveAll("infra1.etcd") os.RemoveAll("infra2.etcd") os.RemoveAll("infra3.etcd") }() oldCmds := make([]*exec.Cmd, 3) oldOutputs := make([]io.ReadCloser, 3) newCmds := make([]*exec.Cmd, 3) newOutputs := make([]io.ReadCloser, 3) for i := range oldCmds { oldCmd := exec.Command(cmdFlag.EtcdOld, getInfraFlags(i+1)...) oldCmds[i] = oldCmd oldOutput, err := oldCmd.StderrPipe() if err != nil { fmt.Fprintln(os.Stderr, err) return } oldOutputs[i] = oldOutput newCmd := exec.Command(cmdFlag.EtcdNew, getInfraFlags(i+1)...) newCmds[i] = newCmd newOutput, err := newCmd.StderrPipe() if err != nil { fmt.Fprintln(os.Stderr, err) return } newOutputs[i] = newOutput } errChan := make(chan error) done := make(chan struct{}) for i := range oldCmds { cmd := oldCmds[i] go func(i int, cmd *exec.Cmd) { if err := cmd.Start(); err != nil { errChan <- err return } done <- struct{}{} }(i, cmd) } cn := 0 for cn != 3 { cn++ select { case err := <-errChan: fmt.Fprintln(os.Stderr, err) return case <-done: } } becameActiveCount := 0 for i, o := range oldOutputs { go func(i int, reader io.ReadCloser) { scanner := bufio.NewScanner(reader) for { for scanner.Scan() { txt := scanner.Text() fmt.Printf("[old infra%d] %s\n", i+1, txt) if strings.Contains(txt, memberStartReadyString) { mu.Lock() nodeStatus[fmt.Sprintf("infra%d", i+1)] = "LIVE" mu.Unlock() fmt.Printf("[old infra%d] %s READY!!!!!!!!!!!!!\n", i+1, txt) done <- struct{}{} } if strings.HasSuffix(txt, memberReStartReadySuffix) { fmt.Printf("[old infra%d] reconnected!\n", i+1) mu.Lock() nodeStatus[fmt.Sprintf("infra%d", i+1)] = "LIVE" mu.Unlock() becameActiveCount++ } } } if err := scanner.Err(); err != nil { errChan <- err return } }(i, o) } for i, o := range newOutputs { go func(i int, reader io.ReadCloser) { scanner := bufio.NewScanner(reader) for { for scanner.Scan() { txt := scanner.Text() fmt.Printf("[new infra%d] %s\n", i+1, txt) if strings.HasSuffix(txt, memberReStartReadySuffix) { fmt.Printf("[new infra%d] reconnected!\n", i+1) mu.Lock() nodeStatus[fmt.Sprintf("infra%d", i+1)] = "LIVE" mu.Unlock() becameActiveCount++ } } } if err := scanner.Err(); err != nil { errChan <- err return } }(i, o) } cn = 0 for cn != 3 { cn++ select { case err := <-errChan: fmt.Fprintln(os.Stderr, err) return case <-done: } } es := stress(10) if es != nil { log.Println(es) return } go func() { es := stress(50) if es != nil { log.Println(es) return } }() for i := 0; i < 3; i++ { fmt.Printf("[old infra%d] killing...\n", i+1) mu.Lock() nodeStatus[fmt.Sprintf("infra%d", i+1)] = "KILLED" mu.Unlock() if err := syscall.Kill(oldCmds[i].Process.Pid, syscall.SIGKILL); err != nil { fmt.Fprintln(os.Stderr, err) return } fmt.Printf("[old infra%d] killed!\n", i+1) time.Sleep(10 * time.Second) fmt.Printf("[new infra%d] restarting...\n", i+1) if err := newCmds[i].Start(); err != nil { fmt.Fprintln(os.Stderr, err) return } mu.Lock() nodeStatus[fmt.Sprintf("infra%d", i+1)] = "LIVE" mu.Unlock() fmt.Printf("[new infra%d] restarted!\n", i+1) time.Sleep(10 * time.Second) } // 6(2 per node) at the beginning of cluster + 12(4 per kill) during migration = 18 if becameActiveCount >= 18 { fmt.Printf("migration successful from %s to %s (node status %v)\n", cmdFlag.EtcdOld, cmdFlag.EtcdNew, nodeStatus) } else { fmt.Printf("migration failed from %s to %s (becameActiveCount %d, node status %v)\n", cmdFlag.EtcdOld, cmdFlag.EtcdNew, becameActiveCount, nodeStatus) } }
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) }