Merge pull request #14812 from ahrtr/add_hash_revision_etcdctl_20221121

Display hash_revision for `etcdctl endpoint hash`
This commit is contained in:
Benjamin Wang 2022-11-25 19:36:27 +08:00 committed by GitHub
commit 488e5413d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 18 deletions

View File

@ -32,6 +32,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0).
- [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13711) when displaying member list in json. - [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13711) when displaying member list in json.
- [Add one more field `storageVersion`](https://github.com/etcd-io/etcd/pull/13773) into the response of command `etcdctl endpoint status`. - [Add one more field `storageVersion`](https://github.com/etcd-io/etcd/pull/13773) into the response of command `etcdctl endpoint status`.
- Add [`--max-txn-ops`](https://github.com/etcd-io/etcd/pull/14340) flag to make-mirror command. - Add [`--max-txn-ops`](https://github.com/etcd-io/etcd/pull/14340) flag to make-mirror command.
- Display [field `hash_revision`](https://github.com/etcd-io/etcd/pull/14812) for `etcdctl endpoint hash` command.
### etcdutl v3 ### etcdutl v3
@ -64,6 +65,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0).
- Add [`etcd --experimental-compact-hash-check-enabled --experimental-compact-hash-check-time`](https://github.com/etcd-io/etcd/issues/14039) flags to support enabling reliable corruption detection on compacted revisions. - Add [`etcd --experimental-compact-hash-check-enabled --experimental-compact-hash-check-time`](https://github.com/etcd-io/etcd/issues/14039) flags to support enabling reliable corruption detection on compacted revisions.
- Add [Protection on maintenance request when auth is enabled](https://github.com/etcd-io/etcd/pull/14663). - Add [Protection on maintenance request when auth is enabled](https://github.com/etcd-io/etcd/pull/14663).
- Graduated [`--experimental-warning-unary-request-duration` to `--warning-unary-request-duration`](https://github.com/etcd-io/etcd/pull/14414). Note the experimental flag is deprecated and will be decommissioned in v3.7. - Graduated [`--experimental-warning-unary-request-duration` to `--warning-unary-request-duration`](https://github.com/etcd-io/etcd/pull/14414). Note the experimental flag is deprecated and will be decommissioned in v3.7.
- Add [field `hash_revision` into `HashKVResponse`](https://github.com/etcd-io/etcd/pull/14537).
### etcd grpc-proxy ### etcd grpc-proxy

View File

@ -837,28 +837,73 @@ Prints a line of JSON encoding each endpoint URL and KV history hash.
Get the hash for the default endpoint: Get the hash for the default endpoint:
```bash ```bash
./etcdctl endpoint hashkv ./etcdctl endpoint hashkv --cluster
# 127.0.0.1:2379, 1084519789 http://127.0.0.1:2379, 2064120424, 13
http://127.0.0.1:22379, 2064120424, 13
http://127.0.0.1:32379, 2064120424, 13
``` ```
Get the status for the default endpoint as JSON: Get the status for the default endpoint as JSON:
```bash ```bash
./etcdctl -w json endpoint hashkv ./etcdctl endpoint hash --cluster -w json | jq
# [{"Endpoint":"127.0.0.1:2379","Hash":{"header":{"cluster_id":14841639068965178418,"member_id":10276657743932975437,"revision":1,"raft_term":3},"hash":1084519789,"compact_revision":-1}}] [
{
"Endpoint": "http://127.0.0.1:2379",
"HashKV": {
"header": {
"cluster_id": 17237436991929494000,
"member_id": 9372538179322590000,
"revision": 13,
"raft_term": 2
},
"hash": 2064120424,
"compact_revision": -1,
"hash_revision": 13
}
},
{
"Endpoint": "http://127.0.0.1:22379",
"HashKV": {
"header": {
"cluster_id": 17237436991929494000,
"member_id": 10501334649042878000,
"revision": 13,
"raft_term": 2
},
"hash": 2064120424,
"compact_revision": -1,
"hash_revision": 13
}
},
{
"Endpoint": "http://127.0.0.1:32379",
"HashKV": {
"header": {
"cluster_id": 17237436991929494000,
"member_id": 18249187646912140000,
"revision": 13,
"raft_term": 2
},
"hash": 2064120424,
"compact_revision": -1,
"hash_revision": 13
}
}
]
``` ```
Get the status for all endpoints in the cluster associated with the default endpoint: Get the status for all endpoints in the cluster associated with the default endpoint:
```bash ```bash
./etcdctl -w table endpoint --cluster hashkv $ ./etcdctl endpoint hash --cluster -w table
+------------------------+------------+ +------------------------+-----------+---------------+
| ENDPOINT | HASH | | ENDPOINT | HASH | HASH REVISION |
+------------------------+------------+ +------------------------+-----------+---------------+
| http://127.0.0.1:2379 | 1084519789 | | http://127.0.0.1:2379 | 784522900 | 16 |
| http://127.0.0.1:22379 | 1084519789 | | http://127.0.0.1:22379 | 784522900 | 16 |
| http://127.0.0.1:32379 | 1084519789 | | http://127.0.0.1:32379 | 784522900 | 16 |
+------------------------+------------+ +------------------------+-----------+---------------+
``` ```
### ALARM \<subcommand\> ### ALARM \<subcommand\>

View File

@ -233,11 +233,12 @@ func makeEndpointStatusTable(statusList []epStatus) (hdr []string, rows [][]stri
} }
func makeEndpointHashKVTable(hashList []epHashKV) (hdr []string, rows [][]string) { func makeEndpointHashKVTable(hashList []epHashKV) (hdr []string, rows [][]string) {
hdr = []string{"endpoint", "hash"} hdr = []string{"endpoint", "hash", "hash_revision"}
for _, h := range hashList { for _, h := range hashList {
rows = append(rows, []string{ rows = append(rows, []string{
h.Ep, h.Ep,
fmt.Sprint(h.Resp.Hash), fmt.Sprint(h.Resp.Hash),
fmt.Sprint(h.Resp.HashRevision),
}) })
} }
return hdr, rows return hdr, rows

View File

@ -212,6 +212,7 @@ func (p *fieldsPrinter) EndpointHashKV(hs []epHashKV) {
p.hdr(h.Resp.Header) p.hdr(h.Resp.Header)
fmt.Printf("\"Endpoint\" : %q\n", h.Ep) fmt.Printf("\"Endpoint\" : %q\n", h.Ep)
fmt.Println(`"Hash" :`, h.Resp.Hash) fmt.Println(`"Hash" :`, h.Resp.Hash)
fmt.Println(`"HashRevision" :`, h.Resp.HashRevision)
fmt.Println() fmt.Println()
} }
} }

View File

@ -16,9 +16,12 @@ package common
import ( import (
"context" "context"
"fmt"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/require"
"go.etcd.io/etcd/tests/v3/framework/config"
"go.etcd.io/etcd/tests/v3/framework/testutils" "go.etcd.io/etcd/tests/v3/framework/testutils"
) )
@ -44,12 +47,30 @@ func TestEndpointHashKV(t *testing.T) {
clus := testRunner.NewCluster(ctx, t) clus := testRunner.NewCluster(ctx, t)
defer clus.Close() defer clus.Close()
cc := testutils.MustClient(clus.Client()) cc := testutils.MustClient(clus.Client())
testutils.ExecuteUntil(ctx, t, func() {
_, err := cc.HashKV(ctx, 0) t.Log("Add some entries")
if err != nil { for i := 0; i < 10; i++ {
t.Fatalf("get endpoint hashkv error: %v", err) key := fmt.Sprintf("key-%d", i)
value := fmt.Sprintf("value-%d", i)
if err := cc.Put(ctx, key, value, config.PutOptions{}); err != nil {
t.Fatalf("count not put key %q, err: %s", key, err)
} }
}) }
t.Log("Check all members' Hash and HashRevision")
require.Eventually(t, func() bool {
resp, err := cc.HashKV(ctx, 0)
require.NoError(t, err, "failed to get endpoint hashkv: %v", err)
require.Equal(t, 3, len(resp))
if resp[0].HashRevision == resp[1].HashRevision && resp[0].HashRevision == resp[2].HashRevision {
require.Equal(t, resp[0].Hash, resp[1].Hash)
require.Equal(t, resp[0].Hash, resp[2].Hash)
return true
}
t.Logf("HashRevisions are not equal: [%d, %d, %d], retry...", resp[0].HashRevision, resp[1].HashRevision, resp[2].HashRevision)
return false
}, 5*time.Second, 200*time.Millisecond)
} }
func TestEndpointHealth(t *testing.T) { func TestEndpointHealth(t *testing.T) {