mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #5301 from gyuho/simple_member
etcdctl/ctlv3: make 'table' printer configurable
This commit is contained in:
commit
efcba23d21
@ -423,6 +423,18 @@ On success, prints a JSON listing of the member IDs, statuses, names, peer addre
|
||||
|
||||
```bash
|
||||
./etcdctl member list
|
||||
8211f1d0f64f3269, started, infra1, http://127.0.0.1:12380, http://127.0.0.1:2379
|
||||
91bc3c398fb3c146, started, infra2, http://127.0.0.1:22380, http://127.0.0.1:22379
|
||||
fd422379fda50e48, started, infra3, http://127.0.0.1:32380, http://127.0.0.1:32379
|
||||
```
|
||||
|
||||
```bash
|
||||
./etcdctl -w json member list
|
||||
{"header":{"cluster_id":17237436991929493444,"member_id":9372538179322589801,"raft_term":2},"members":[{"ID":9372538179322589801,"name":"infra1","peerURLs":["http://127.0.0.1:12380"],"clientURLs":["http://127.0.0.1:2379"]},{"ID":10501334649042878790,"name":"infra2","peerURLs":["http://127.0.0.1:22380"],"clientURLs":["http://127.0.0.1:22379"]},{"ID":18249187646912138824,"name":"infra3","peerURLs":["http://127.0.0.1:32380"],"clientURLs":["http://127.0.0.1:32379"]}]}
|
||||
```
|
||||
|
||||
```bash
|
||||
./etcdctl -w table member list
|
||||
+------------------+---------+--------+------------------------+------------------------+
|
||||
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS |
|
||||
+------------------+---------+--------+------------------------+------------------------+
|
||||
@ -432,11 +444,6 @@ On success, prints a JSON listing of the member IDs, statuses, names, peer addre
|
||||
+------------------+---------+--------+------------------------+------------------------+
|
||||
```
|
||||
|
||||
```bash
|
||||
./etcdctl -w json member list
|
||||
{"header":{"cluster_id":17237436991929493444,"member_id":9372538179322589801,"raft_term":2},"members":[{"ID":9372538179322589801,"name":"infra1","peerURLs":["http://127.0.0.1:12380"],"clientURLs":["http://127.0.0.1:2379"]},{"ID":10501334649042878790,"name":"infra2","peerURLs":["http://127.0.0.1:22380"],"clientURLs":["http://127.0.0.1:22379"]},{"ID":18249187646912138824,"name":"infra3","peerURLs":["http://127.0.0.1:32380"],"clientURLs":["http://127.0.0.1:32379"]}]}
|
||||
```
|
||||
|
||||
## Utility Commands
|
||||
|
||||
### ENDPOINT \<subcommand\>
|
||||
@ -481,13 +488,9 @@ On success, prints a line of JSON encoding each endpoint URL, ID, version, datab
|
||||
|
||||
```bash
|
||||
./etcdctl endpoint status
|
||||
+-----------------+------------------+-----------+---------+-----------+-----------+------------+
|
||||
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
|
||||
+-----------------+------------------+-----------+---------+-----------+-----------+------------+
|
||||
| 127.0.0.1:2379 | 8211f1d0f64f3269 | 2.3.0+git | 25 kB | false | 2 | 31563 |
|
||||
| 127.0.0.1:22379 | 91bc3c398fb3c146 | 2.3.0+git | 25 kB | false | 2 | 31563 |
|
||||
| 127.0.0.1:32379 | fd422379fda50e48 | 2.3.0+git | 25 kB | true | 2 | 31563 |
|
||||
+-----------------+------------------+-----------+---------+-----------+-----------+------------+
|
||||
127.0.0.1:2379, 8211f1d0f64f3269, 3.0.0-beta.0+git, 25 kB, false, 2, 63
|
||||
127.0.0.1:22379, 91bc3c398fb3c146, 3.0.0-beta.0+git, 25 kB, false, 2, 63
|
||||
127.0.0.1:32379, fd422379fda50e48, 3.0.0-beta.0+git, 25 kB, true, 2, 63
|
||||
```
|
||||
|
||||
```bash
|
||||
@ -495,6 +498,16 @@ On success, prints a line of JSON encoding each endpoint URL, ID, version, datab
|
||||
[{"Endpoint":"127.0.0.1:2379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":9372538179322589801,"revision":2,"raft_term":2},"version":"2.3.0+git","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}},{"Endpoint":"127.0.0.1:22379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":10501334649042878790,"revision":2,"raft_term":2},"version":"2.3.0+git","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}},{"Endpoint":"127.0.0.1:32379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":18249187646912138824,"revision":2,"raft_term":2},"version":"2.3.0+git","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}}]
|
||||
```
|
||||
|
||||
```bash
|
||||
./etcdctl -w table endpoint status
|
||||
+-----------------+------------------+------------------+---------+-----------+-----------+------------+
|
||||
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
|
||||
+-----------------+------------------+------------------+---------+-----------+-----------+------------+
|
||||
| 127.0.0.1:2379 | 8211f1d0f64f3269 | 3.0.0-beta.0+git | 25 kB | false | 2 | 52 |
|
||||
| 127.0.0.1:22379 | 91bc3c398fb3c146 | 3.0.0-beta.0+git | 25 kB | false | 2 | 52 |
|
||||
| 127.0.0.1:32379 | fd422379fda50e48 | 3.0.0-beta.0+git | 25 kB | true | 2 | 52 |
|
||||
+-----------------+------------------+------------------+---------+-----------+-----------+------------+
|
||||
```
|
||||
|
||||
### LOCK \<lockname\>
|
||||
|
||||
@ -705,11 +718,7 @@ On success, prints a line of JSON encoding the database hash, revision, total ke
|
||||
#### Examples
|
||||
```bash
|
||||
./etcdctl snapshot status file.db
|
||||
+----------+----------+------------+------------+
|
||||
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
|
||||
+----------+----------+------------+------------+
|
||||
| cf1550fb | 3 | 3 | 25 kB |
|
||||
+----------+----------+------------+------------+
|
||||
cf1550fb, 3, 3, 25 kB
|
||||
```
|
||||
|
||||
```bash
|
||||
@ -717,6 +726,15 @@ On success, prints a line of JSON encoding the database hash, revision, total ke
|
||||
{"hash":3474280699,"revision":3,"totalKey":3,"totalSize":24576}
|
||||
```
|
||||
|
||||
```bash
|
||||
./etcdctl -write-out=table snapshot status file.db
|
||||
+----------+----------+------------+------------+
|
||||
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
|
||||
+----------+----------+------------+------------+
|
||||
| cf1550fb | 3 | 3 | 25 kB |
|
||||
+----------+----------+------------+------------+
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- JSON encoding for keys and values uses base64 since they are byte strings.
|
||||
|
@ -51,7 +51,10 @@ func newEpStatusCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "status",
|
||||
Short: "status prints out the status of endpoints specified in `--endpoints` flag",
|
||||
Run: epStatusCommandFunc,
|
||||
Long: `When --write-out is set to simple, this command prints out comma-separated status lists for each endpoint.
|
||||
The items in the lists are endpoint, ID, version, db size, is leader, raft term, raft index.
|
||||
`,
|
||||
Run: epStatusCommandFunc,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,9 @@ func NewMemberListCommand() *cobra.Command {
|
||||
cc := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "list is used to list all members in the cluster",
|
||||
Long: `When --write-out is set to simple, this command prints out comma-separated member lists for each endpoint.
|
||||
The items in the lists are ID, Status, Name, Peer Addrs, Client Addrs.
|
||||
`,
|
||||
|
||||
Run: memberListCommandFunc,
|
||||
}
|
||||
|
@ -51,10 +51,57 @@ func NewPrinter(printerType string, isHex bool) printer {
|
||||
return &jsonPrinter{}
|
||||
case "protobuf":
|
||||
return &pbPrinter{}
|
||||
case "table":
|
||||
return &tablePrinter{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeMemberListTable(r v3.MemberListResponse) (hdr []string, rows [][]string) {
|
||||
hdr = []string{"ID", "Status", "Name", "Peer Addrs", "Client Addrs"}
|
||||
for _, m := range r.Members {
|
||||
status := "started"
|
||||
if len(m.Name) == 0 {
|
||||
status = "unstarted"
|
||||
}
|
||||
rows = append(rows, []string{
|
||||
fmt.Sprintf("%x", m.ID),
|
||||
status,
|
||||
m.Name,
|
||||
strings.Join(m.PeerURLs, ","),
|
||||
strings.Join(m.ClientURLs, ","),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]string) {
|
||||
hdr = []string{"endpoint", "ID", "version", "db size", "is leader", "raft term", "raft index"}
|
||||
for _, status := range statusList {
|
||||
rows = append(rows, []string{
|
||||
fmt.Sprint(status.Ep),
|
||||
fmt.Sprintf("%x", status.Resp.Header.MemberId),
|
||||
fmt.Sprint(status.Resp.Version),
|
||||
fmt.Sprint(humanize.Bytes(uint64(status.Resp.DbSize))),
|
||||
fmt.Sprint(status.Resp.Leader == status.Resp.Header.MemberId),
|
||||
fmt.Sprint(status.Resp.RaftTerm),
|
||||
fmt.Sprint(status.Resp.RaftIndex),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func makeDBStatusTable(ds dbstatus) (hdr []string, rows [][]string) {
|
||||
hdr = []string{"hash", "revision", "total keys", "total size"}
|
||||
rows = append(rows, []string{
|
||||
fmt.Sprintf("%x", ds.Hash),
|
||||
fmt.Sprint(ds.Revision),
|
||||
fmt.Sprint(ds.TotalKey),
|
||||
humanize.Bytes(uint64(ds.TotalSize)),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
type simplePrinter struct {
|
||||
isHex bool
|
||||
}
|
||||
@ -107,57 +154,71 @@ func (s *simplePrinter) Alarm(resp v3.AlarmResponse) {
|
||||
}
|
||||
|
||||
func (s *simplePrinter) MemberList(resp v3.MemberListResponse) {
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"ID", "Status", "Name", "Peer Addrs", "Client Addrs"})
|
||||
|
||||
for _, m := range resp.Members {
|
||||
status := "started"
|
||||
if len(m.Name) == 0 {
|
||||
status = "unstarted"
|
||||
}
|
||||
|
||||
table.Append([]string{
|
||||
fmt.Sprintf("%x", m.ID),
|
||||
status,
|
||||
m.Name,
|
||||
strings.Join(m.PeerURLs, ","),
|
||||
strings.Join(m.ClientURLs, ","),
|
||||
})
|
||||
_, rows := makeMemberListTable(resp)
|
||||
for _, row := range rows {
|
||||
fmt.Println(strings.Join(row, ", "))
|
||||
}
|
||||
|
||||
table.Render()
|
||||
}
|
||||
|
||||
func (s *simplePrinter) EndpointStatus(statusList []epStatus) {
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"endpoint", "ID", "version", "db size", "is leader", "raft term", "raft index"})
|
||||
|
||||
for _, status := range statusList {
|
||||
table.Append([]string{
|
||||
fmt.Sprint(status.Ep),
|
||||
fmt.Sprintf("%x", status.Resp.Header.MemberId),
|
||||
fmt.Sprint(status.Resp.Version),
|
||||
fmt.Sprint(humanize.Bytes(uint64(status.Resp.DbSize))),
|
||||
fmt.Sprint(status.Resp.Leader == status.Resp.Header.MemberId),
|
||||
fmt.Sprint(status.Resp.RaftTerm),
|
||||
fmt.Sprint(status.Resp.RaftIndex),
|
||||
})
|
||||
_, rows := makeEndpointStatusTable(statusList)
|
||||
for _, row := range rows {
|
||||
fmt.Println(strings.Join(row, ", "))
|
||||
}
|
||||
|
||||
table.Render()
|
||||
}
|
||||
|
||||
func (s *simplePrinter) DBStatus(ds dbstatus) {
|
||||
_, rows := makeDBStatusTable(ds)
|
||||
for _, row := range rows {
|
||||
fmt.Println(strings.Join(row, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
type tablePrinter struct{}
|
||||
|
||||
func (tp *tablePrinter) Del(r v3.DeleteResponse) {
|
||||
ExitWithError(ExitBadFeature, errors.New("table is not supported as output format"))
|
||||
}
|
||||
func (tp *tablePrinter) Get(r v3.GetResponse) {
|
||||
ExitWithError(ExitBadFeature, errors.New("table is not supported as output format"))
|
||||
}
|
||||
func (tp *tablePrinter) Put(r v3.PutResponse) {
|
||||
ExitWithError(ExitBadFeature, errors.New("table is not supported as output format"))
|
||||
}
|
||||
func (tp *tablePrinter) Txn(r v3.TxnResponse) {
|
||||
ExitWithError(ExitBadFeature, errors.New("table is not supported as output format"))
|
||||
}
|
||||
func (tp *tablePrinter) Watch(r v3.WatchResponse) {
|
||||
ExitWithError(ExitBadFeature, errors.New("table is not supported as output format"))
|
||||
}
|
||||
func (tp *tablePrinter) Alarm(r v3.AlarmResponse) {
|
||||
ExitWithError(ExitBadFeature, errors.New("table is not supported as output format"))
|
||||
}
|
||||
func (tp *tablePrinter) MemberList(r v3.MemberListResponse) {
|
||||
hdr, rows := makeMemberListTable(r)
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"hash", "revision", "total keys", "total size"})
|
||||
|
||||
table.Append([]string{
|
||||
fmt.Sprintf("%x", ds.Hash),
|
||||
fmt.Sprint(ds.Revision),
|
||||
fmt.Sprint(ds.TotalKey),
|
||||
humanize.Bytes(uint64(ds.TotalSize)),
|
||||
})
|
||||
|
||||
table.SetHeader(hdr)
|
||||
for _, row := range rows {
|
||||
table.Append(row)
|
||||
}
|
||||
table.Render()
|
||||
}
|
||||
func (tp *tablePrinter) EndpointStatus(r []epStatus) {
|
||||
hdr, rows := makeEndpointStatusTable(r)
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader(hdr)
|
||||
for _, row := range rows {
|
||||
table.Append(row)
|
||||
}
|
||||
table.Render()
|
||||
}
|
||||
func (tp *tablePrinter) DBStatus(r dbstatus) {
|
||||
hdr, rows := makeDBStatusTable(r)
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader(hdr)
|
||||
for _, row := range rows {
|
||||
table.Append(row)
|
||||
}
|
||||
table.Render()
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,10 @@ func newSnapshotStatusCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "status <filename>",
|
||||
Short: "status gets backend snapshot status of a given file.",
|
||||
Run: snapshotStatusCommandFunc,
|
||||
Long: `When --write-out is set to simple, this command prints out comma-separated status lists for each endpoint.
|
||||
The items in the lists are hash, revision, total keys, total size.
|
||||
`,
|
||||
Run: snapshotStatusCommandFunc,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ var (
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringSliceVar(&globalFlags.Endpoints, "endpoints", []string{"127.0.0.1:2379", "127.0.0.1:22379", "127.0.0.1:32379"}, "gRPC endpoints")
|
||||
|
||||
rootCmd.PersistentFlags().StringVarP(&globalFlags.OutputFormat, "write-out", "w", "simple", "set the output format (simple, json, protobuf)")
|
||||
rootCmd.PersistentFlags().StringVarP(&globalFlags.OutputFormat, "write-out", "w", "simple", "set the output format (simple, json, protobuf, table)")
|
||||
rootCmd.PersistentFlags().BoolVar(&globalFlags.IsHex, "hex", false, "print byte strings as hex encoded strings")
|
||||
|
||||
rootCmd.PersistentFlags().DurationVar(&globalFlags.DialTimeout, "dial-timeout", defaultDialTimeout, "dial timeout for client connections")
|
||||
|
Loading…
x
Reference in New Issue
Block a user