Compare commits

..

188 Commits

Author SHA1 Message Date
Ivan Valdes 5400cdc39b
version: bump up to 3.6.4
Signed-off-by: Ivan Valdes <iv@a.ki>
2025-07-25 11:14:45 -07:00
Benjamin Wang effaa79508
Merge pull request #20387 from ahrtr/20250722_learner_3.6
[release-3.6] Check promotion against v2store when updating v2store
2025-07-24 11:41:34 +01:00
Benjamin Wang e5f4311b71 Check promotion against v2store when updating v2store
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-07-24 09:30:03 +01:00
Benjamin Wang e59bb1fdd0 Add an e2e test to reproduce the issue 20340
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-07-24 09:28:00 +01:00
James Blair 1ed440dc2b
version: bump up to 3.6.3
Signed-off-by: James Blair <mail@jamesblair.net>
2025-07-23 06:45:14 +12:00
Benjamin Wang e3a33657f1
Merge pull request #20370 from k8s-infra-cherrypick-robot/cherry-pick-20368-to-release-3.6
[release-3.6] Fix v2store check returning wrong result even there isn't any auth data
2025-07-21 16:49:45 +01:00
Benjamin Wang 0655761d60 Fix v2store check returning wrong result even there isn't any auth data
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-07-21 14:17:03 +00:00
Benjamin Wang 68ddc0667e
Merge pull request #20352 from k8s-infra-cherrypick-robot/cherry-pick-20328-to-release-3.6
[release-3.6] Updated help for --quota-backend-bytes
2025-07-17 20:39:57 +01:00
Zechariah ad00289fa7 Updated help for --quota-backend-bytes
Signed-off-by: Zechariah <zechariahks@outlook.com>
2025-07-17 18:10:12 +00:00
Marek Siarkowicz fe698afe74
Merge pull request #20330 from kishen-v/cherrypick-TestWatchRestore
Prevent flakes with TestWatchRestore
2025-07-14 09:41:52 +02:00
Marek Siarkowicz 2a88ea2fa1 Prevent flakes with TestWatchRestore
Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
(cherry picked from commit 9671fb369c)
2025-07-14 11:33:11 +05:30
James Blair 6088ddf90a
version: bump up to 3.6.2
Signed-off-by: James Blair <mail@jamesblair.net>
2025-07-10 19:59:51 +12:00
Benjamin Wang e47582cdb5
Merge pull request #20314 from ivanvc/release-3.6-go-1.23.11
[release-3.6] Bump go to 1.23.11
2025-07-09 11:53:30 +01:00
Ivan Valdes ddda058123
Bump go to 1.23.11
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-07-08 22:10:35 -10:00
Fu Wei 438287a59d
Merge pull request #20286 from k8s-infra-cherrypick-robot/cherry-pick-20281-to-release-3.6
[release-3.6] Avoid lowering revision of watchers in the future after restore
2025-07-06 16:53:11 -04:00
Marek Siarkowicz 50c37266f5 Avoid lowering revision of watchers in the future after restore
Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
2025-07-06 04:50:08 +00:00
Fu Wei 61dae259e1
Merge pull request #20277 from k8s-infra-cherrypick-robot/cherry-pick-20225-to-release-3.6
[release-3.6] Add verification to verify the watch response have a bigger revision than startRev
2025-07-05 16:48:30 -04:00
Benjamin Wang ab13cb144c Add verification to verify the watch response have a bigger revision than minRev
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-07-04 09:01:30 +00:00
Benjamin Wang 5897bc4847
Merge pull request #20267 from ivanvc/release-3.6-bbolt-1.4.2
[release-3.6] Bump bbolt to v1.4.2
2025-07-03 10:44:28 +01:00
Ivan Valdes a0c087ff19
Bump bbolt to v1.4.2
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-07-02 21:08:45 -07:00
Fu Wei 95bae9d277
Merge pull request #20246 from serathius/robustness-progress-release-3.6
[release-3.6] Disable progress notify validation until we can guarantee response
2025-06-30 11:12:20 -04:00
Marek Siarkowicz be98254d07 Disable progress notify validation until we can guarantee response
Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
2025-06-30 15:36:51 +02:00
Marek Siarkowicz 68075c999f
Merge pull request #20241 from serathius/skip-future-progress-notification-release-3.6
[release-3.6] Skip sending progress notification for watch with starting revision in the future
2025-06-30 13:41:30 +02:00
Marek Siarkowicz 9fc770feac Skip sending progress notification for watch with starting revision in the future
Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
2025-06-30 10:46:05 +02:00
Benjamin Wang c093b79f42
Merge pull request #20154 from ahrtr/20250610_bbolt_1.4.1_3.6
[release-3.6] Bump bbolt to v1.4.1
2025-06-10 17:21:16 +01:00
Benjamin Wang 986fe08764 Bump bbolt to v1.4.1
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-06-10 15:12:05 +01:00
Ivan Valdes a4708beb0f
version: bump up to 3.6.1
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-06-06 13:11:06 -07:00
Benjamin Wang 7edcfc047c
Merge pull request #20128 from ivanvc/release-3.6-go-1.23.10-version-bump
[release-3.6] Bump Go to 1.23.9
2025-06-06 07:44:09 +01:00
Ivan Valdes 823f94a43f
Bump Go to 1.23.9
Part of #20126.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-06-05 13:12:18 -07:00
Benjamin Wang cfb60c8365
Merge pull request #20121 from k8s-infra-cherrypick-robot/cherry-pick-20120-to-release-3.6
[release-3.6] Update 'endpoint health' command to avoid calling `flags.SetPflagsFromEnv` multiple times
2025-06-05 14:18:07 +01:00
Benjamin Wang 4562eeceac Update 'endpoint health' command to avoid calling flags.SetPflagsFromEnv multiple times
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-06-05 11:47:32 +00:00
Benjamin Wang debb049667
Merge pull request #20113 from ahrtr/20250603_20250603_discovery_ep_3.6
[release-3.6] Add validation to ensure that there is NO empty discovery endpoint
2025-06-04 11:04:27 +01:00
Benjamin Wang 23bdcbbad6 Verify that the discovery endpoint isn't empty
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-06-03 15:21:28 +01:00
Benjamin Wang 856c3ddb25
Merge pull request #20071 from ahrtr/20250530_force_new_cluster_3.6
[release-3.6] Fix the issue that `--force-new-cluster` can't remove all other members in a corner case
2025-05-31 17:07:14 +01:00
Benjamin Wang 78e0e23369 Initialize Commit Index = max(consistent_index, CommitIndex) on bootstrap if --force-new-cluster set
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-05-30 22:51:02 +01:00
Benjamin Wang 9d53b145e5 Add an e2e test to reproduce the issue that --force-new-cluster can't remove all members in a corner case
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-05-30 22:50:55 +01:00
Benjamin Wang 322b79c2be
Merge pull request #20067 from kjgorman/cherry-pick-19600-to-release-3.6
[release-3.6] mvcc: avoid double decrement of watcher gauge on close/cancel race (3.6 backport)
2025-05-30 13:33:31 +01:00
Kieran Gorman 302c89ed7a mvcc: avoid double decrement of watcher gauge on close/cancel race
This occurs specifically when the watch is for a compacted revision, as there's
a possible interleaving of cancel/close that invokes the `cancelWatch` function
twice.

It's fairly difficult to provoke the race condition but it is possible to
observe on `main` the racing test can fail with a negative gauge:

```
$ go test ./...  -run TestNewWatcherCountGauge/compacted_watch,_close/cancel_race
--- FAIL: TestNewWatcherCountGauge (0.34s)
    watchable_store_test.go:86:  # HELP etcd_debugging_mvcc_watcher_total Total number of watchers.
         # TYPE etcd_debugging_mvcc_watcher_total gauge
        -etcd_debugging_mvcc_watcher_total -1
        +etcd_debugging_mvcc_watcher_total 0

FAIL
FAIL    go.etcd.io/etcd/server/v3/storage/mvcc  0.830s
?       go.etcd.io/etcd/server/v3/storage/mvcc/testutil [no test files]
FAIL
```

It seems as though it is partially expected for the cancel function to be
invoked multiple times and to handle that safely (i.e., the existing `ch == nil`
check) - the bug here is that in the `if/else if` branches it comes "too late",
and multiple invocations where `wa.compacted` is true will both decrement the
counter. Shifting the case up one ensures that we can't follow that decrement
branch multiple times.

In fact, it seems logically more sensible to put this `wa.ch == nil` case
_first_, as a guard for the function being invoked multiple times, but moving i
before the sync/unsynced watch set delete functions could have a greater
inadvertent functional impact (i.e., if we never deleted cancelled watches from
these sets it would presumably introduce a leak), so from an abundance of
caution I've made the smallest change I think will fix my issue.

Signed-off-by: Kieran Gorman <kieran@kjgorman.com>
2025-05-30 10:53:46 +01:00
Benjamin Wang 8767dfab53
Merge pull request #20051 from ahrtr/20250529_v2store_panic_3.6
[release-3.6] Add protection on `PromoteMember` and `UpdateRaftAttributes`
2025-05-29 16:59:41 +01:00
Benjamin Wang 091f6c8f32 Add protection on PromoteMember and UpdateRaftAttributes
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-05-29 12:29:53 +01:00
Benjamin Wang a5ff1caf71 Add an e2e test to reproduce the promote member panicking issue when forcibly create one-member cluster
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-05-29 08:45:23 +01:00
Benjamin Wang 9f19153dc7
Merge pull request #20043 from dims/automated-cherry-pick-of-#20017-upstream-release-3.6-take-2
Semi-Automated cherry pick of #20017 upstream release 3.6 ( was Update go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to work with v0.61.0 )
2025-05-28 21:31:28 +01:00
Davanum Srinivas 5baf45e52f
refactor to reuse a single harness for both unary and stream tests
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2025-05-28 08:34:37 -04:00
Davanum Srinivas dd9f9a983d
fix test
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2025-05-28 08:34:33 -04:00
Davanum Srinivas 7078a0747a
add a new test for tracing with Stream RPC calls
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2025-05-28 08:34:28 -04:00
Davanum Srinivas 1ec53d99ed
Drop usage of deprecated APIs
Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2025-05-28 08:34:14 -04:00
Benjamin Wang 7b3514218a
Merge pull request #19948 from k8s-infra-cherrypick-robot/cherry-pick-19947-to-release-3.6
[release-3.6] [Integration Test]: Add test for panic-free removal of non-existent members
2025-05-16 08:01:15 +01:00
Benjamin Wang f5d605a93a
Merge pull request #19951 from ahrtr/release_script_20250515
[release-3.6] Update release script to exactly match the target tag
2025-05-15 20:32:45 +01:00
Benjamin Wang a1bcdc7fcf Update release script to exactly match the target tag
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-05-15 20:25:21 +01:00
Benjamin Wang 7a7a77cd3a version: bump up to 3.6.0
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-05-15 11:42:36 -07:00
amosehiguese 6339219452 Add test for panic-free removal of non-existent members
This test verifies that etcd no longer panics when restarting after
removing a member that was already removed from the cluster.

addresses: issue #13715

Signed-off-by: amosehiguese <amosehiguese@gmail.com>
2025-05-15 12:42:43 +00:00
siyuanfoundation 115f15ed9b version: bump up to 3.6.0-rc.5
Signed-off-by: siyuanfoundation <sizhang@google.com>
2025-05-08 19:24:34 +00:00
Benjamin Wang 53b485a947
Merge pull request #19890 from k8s-infra-cherrypick-robot/cherry-pick-19862-to-release-3.6
[release-3.6] release: Fix the tar unzip command,  avoid permissions issues
2025-05-08 09:09:19 +01:00
hwdef c774d44f5a Fix the tar unzip command, adding the --no-same-owner option to avoid permissions issues
Signed-off-by: hwdef <hwdefcom@outlook.com>
2025-05-08 06:12:11 +00:00
Benjamin Wang 8d1d1a962a
Merge pull request #19867 from ivanvc/release-3.6-go-1.23.9-bump
[release-3.6] Bump Go to 1.23.9
2025-05-07 07:46:29 +01:00
Ivan Valdes cddc9bc949
Bump Go to 1.23.9
Part of #19866.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-05-06 13:11:20 -07:00
James Blair 1a1cc66b74
Merge pull request #19853 from k8s-infra-cherrypick-robot/cherry-pick-19848-to-release-3.6
[release-3.6] fix: test-release checks
2025-05-03 22:29:04 +12:00
joshjms 9f66823bc8 fix: test-release
Address reviews in #19815

Signed-off-by: joshjms <joshjms1607@gmail.com>
2025-05-02 17:13:49 +00:00
Benjamin Wang 9e9ed6b7c4
Merge pull request #19851 from k8s-infra-cherrypick-robot/cherry-pick-19843-to-release-3.6
[release-3.6] remove DistributedTracing from feature gate list.
2025-05-02 08:10:14 +01:00
Siyuan Zhang 1222c0adec remove DistributedTracing from feature gate list.
Because the feature is not feature gated.

Signed-off-by: Siyuan Zhang <sizhang@google.com>
2025-05-01 18:36:09 +00:00
Marek Siarkowicz d3f59bfa96
Merge pull request #19842 from k8s-infra-cherrypick-robot/cherry-pick-19825-to-release-3.6
[release-3.6] chore(client/v3/naming): deprecate Metadata field in Endpoint struct
2025-05-01 10:03:38 +02:00
James Blair c5036a0e00
Merge pull request #19844 from k8s-infra-cherrypick-robot/cherry-pick-19836-to-release-3.6
[release-3.6] make: upload partial coverage reports
2025-05-01 10:30:57 +12:00
James Blair 744b3ca93d
Merge pull request #19845 from k8s-infra-cherrypick-robot/cherry-pick-19815-to-release-3.6
[release-3.6] Add test-release-tests Makefile target
2025-05-01 10:21:34 +12:00
joshjms 77e5c6fd69 Add test-release-tests Makefile target
Signed-off-by: joshjms <joshjms1607@gmail.com>
2025-04-30 21:25:39 +00:00
Ivan Valdes b9d47ef313 make: upload partial coverage reports
In the case of workflow failures (i.e., flaky tests), we still should
upload a partial coverage report to avoid lagging reports on the stable
branches.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-04-30 21:11:23 +00:00
amosehiguese d1d265f45a chore(client/v3/naming): deprecate Metadata field in Endpoint struct
issue: #19706

Signed-off-by: amosehiguese <amosehiguese@gmail.com>
2025-04-30 19:35:52 +00:00
Benjamin Wang 5a9094c536
Merge pull request #19816 from k8s-infra-cherrypick-robot/cherry-pick-19803-to-release-3.6
[release-3.6] pkg/featuregate: Return MutableFeatureGate interface in New function
2025-04-28 21:58:18 +01:00
Ivan Valdes 2d8e7256f3 pkg/featuregate: Return MutableFeatureGate interface in New function
Avoid returning an unexported struct in the exported New function,
instead return the MutableFeatureGate interface.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-04-28 17:21:20 +00:00
Benjamin Wang 9e6394ed64
Merge pull request #19782 from k8s-infra-cherrypick-robot/cherry-pick-19780-to-release-3.6
[release-3.6] Replace `resolver.State.Addresses` with `resolver.State.Endpoint.Addresses`
2025-04-25 09:52:14 +01:00
Fu Wei ed968bdeed
Merge pull request #19770 from k8s-infra-cherrypick-robot/cherry-pick-19762-to-release-3.6
[release-3.6] emit compaction pause duration metric in every compaction batch
2025-04-24 10:24:15 -04:00
Benjamin Wang 9b6738c9c1 Bump google.golang.org/grpc to v1.71.1
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-04-23 10:55:24 +01:00
Benjamin Wang 50ac484a2b Replace resolver.State.Addresses with resolver.State.Endpoint.Addresses
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-04-23 09:11:31 +00:00
Miancheng Lin 0e5db4e283 emit compaction pause duration metric in every compaction batch
Previously, the compaction pause duration metric was skipped if the number
of keys was smaller than `batchNum`, leading to gaps in monitoring data.
This change ensures the metric is emitted for every batch, regardless of
key count.

Signed-off-by: Miancheng Lin <iml@amazon.com>
2025-04-21 08:21:41 +00:00
James Blair 52bddd0266
version: bump up to 3.6.0-rc.4
Signed-off-by: James Blair <mail@jamesblair.net>
2025-04-16 07:19:13 +12:00
Fu Wei d289b4cec5
Merge pull request #19730 from ahrtr/3.6_conf_verification_20250408
[release-3.6] add verification to check whether membership data is in sync between …
2025-04-08 10:52:04 -04:00
Benjamin Wang b4f7075a58 add verification to check whether membership data is in sync between v2store and v3store
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-04-08 11:11:44 +01:00
Fu Wei 4caf9fb079
Merge pull request #19724 from henrybear327/release36/go/1.23.8
[release-3.6] Bump Go to 1.23.8
2025-04-07 17:45:20 -04:00
Chun-Hung Tseng 9e9bef42fa [release-3.6] Bump Go to 1.23.8
Reference:
- https://github.com/etcd-io/etcd/issues/19713

Signed-off-by: Chun-Hung Tseng <henrytseng@google.com>
2025-04-07 22:17:40 +02:00
Benjamin Wang d7e679e1e7
Merge pull request #19703 from k8s-infra-cherrypick-robot/cherry-pick-19694-to-release-3.6
[release-3.6] Switch to validating v3 when v2 and v3 are synchronized
2025-04-04 06:43:20 +01:00
Marek Siarkowicz 6807e0f171 Switch to validating v3 when v2 and v3 are synchronized
Signed-off-by: Marek Siarkowicz <siarkowicz@google.com>
2025-04-03 10:02:53 +00:00
James Blair a0e30d5d0a
Merge pull request #19690 from joshjms/release-3.6
remove CHANGELOG directory
2025-03-28 23:17:30 +13:00
joshjms b827576434 remove CHANGELOG directory
Signed-off-by: joshjms <joshjms1607@gmail.com>
2025-03-28 14:40:32 +08:00
Ivan Valdes 3325414d87
version: bump up to 3.6.0-rc.3
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-27 16:07:31 -07:00
James Blair 257cdd1bda
Merge pull request #19687 from ivanvc/release-3.6-golang.org-x-net-to-v0.38.0
[release-3.6] dependency: bump golang.org/x/net from v0.37.0 to v0.38.0
2025-03-28 10:32:42 +13:00
Ivan Valdes ada25acc14
dependency: bump golang.org/x/net from v0.37.0 to v0.38.0
Addresses CVE-2025-22872.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-27 13:37:40 -07:00
Benjamin Wang b9ef6ae3f3
Merge pull request #19683 from ahrtr/net_20250327
[release-3.6] bump golang.org/x/net to v0.37.0 to address CVE-2025-22870
2025-03-27 16:13:53 +00:00
Benjamin Wang 1cf5df3912 bump golang.org/x/net to v0.37.0 to address CVE-2025-22870
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-27 15:09:30 +00:00
Fu Wei ce82e7597d
Merge pull request #19673 from ahrtr/clientv2_2_20250326
[release-3.6] Move client/internal/v2 into server/internal/clientv2
2025-03-26 17:44:44 -04:00
Benjamin Wang 91342c9c43 Remove v2 from release script
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-26 20:25:42 +00:00
Benjamin Wang 77d3af32d7 Move client/internal/v2 into server/internal/clientv2
Previously we moved client/v2 into client/internal/v2, but it
caused dependency problem, see issue 19670. Since client/v2
is only used by v2discovery in etcdserver, so moving it into
the server module.

Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-26 19:48:00 +00:00
Benjamin Wang c4252fa098
Merge pull request #19662 from fuweid/36-backport-test
[3.6] e2e: add upgrade test for clusters set up by promoted members
2025-03-24 20:30:29 +00:00
Wei Fu a1c9687003 e2e: add upgrade test for clusters set up by promoted members
Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-03-24 15:12:39 -04:00
Benjamin Wang 347ed91d48
Merge pull request #19647 from ivanvc/release-3.6-bump-github.com-golang-jwt-jwt-v5
[release-3.6] dependency: bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2
2025-03-24 15:49:01 +00:00
Benjamin Wang 3ae1151d1b
Merge pull request #19648 from k8s-infra-cherrypick-robot/cherry-pick-19424-to-release-3.6
[release-3.6] github/workflows: remove coverage workflow
2025-03-24 15:48:35 +00:00
Benjamin Wang b4d383f759
Merge pull request #19636 from ahrtr/3.6_learner_sync_20250321
[release-3.6] Auto sync members in v3store is IsLearner differs between v2 and v3 store
2025-03-24 12:49:02 +00:00
Benjamin Wang de774e7ec6 Auto sync members in v3store is IsLearner differs between v2 and v3 store
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-24 10:26:03 +00:00
Ivan Valdes 922dfbf943 Enable uploading coverage report from Prow
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-24 04:40:07 +00:00
Ivan Valdes c9b026c29f github/workflows: remove coverage workflow
This workflow has already been migrated to the Prow infrastructure.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-24 04:40:07 +00:00
Ivan Valdes c4a025ccdd
dependency: bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2
Addresses CVE-2025-30204.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-23 21:29:56 -07:00
Benjamin Wang bcfe983226
Merge pull request #19641 from ahrtr/cv_20250321_3.6
[release-3.6] Returns the string representation of the `ClusterVersion`
2025-03-22 08:04:06 +00:00
Benjamin Wang 10f68e2e66 Returns the string representation of the ClusterVersion
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-21 22:15:07 +00:00
Benjamin Wang f9df7c6ac9
Merge pull request #19638 from ahrtr/upgrade_refactor_20250321_3.6
[release-3.6] minor refactor DowngradeUpgradeMembersByID to not block on waiting fo…
2025-03-21 19:42:07 +00:00
Benjamin Wang 4a842d1a94 minor refactor DowngradeUpgradeMembersByID to not block on waiting for member to be ready
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-21 17:19:41 +00:00
Benjamin Wang abaa1f06b9
Merge pull request #19561 from k8s-infra-cherrypick-robot/cherry-pick-19554-to-release-3.6
[release-3.6] fix: grpcproxy can get stuck in and endless loop causing high cpu usage
2025-03-10 13:59:35 +00:00
Benjamin Wang d7860e1732
Merge pull request #19560 from k8s-infra-cherrypick-robot/cherry-pick-19555-to-release-3.6
[release-3.6] server: remove ExperimentalMaxLearners
2025-03-10 13:58:51 +00:00
Rafael da Fonseca db4d0309bc fix: grpcproxy can get stuck in and endless loop causing high cpu usage
Signed-off-by: Rafael da Fonseca <rafael.fonseca@wildlifestudios.com>
2025-03-10 09:21:18 +00:00
Ivan Valdes 1f889bcc0d server: remove ExperimentalMaxLearners
ExperimentalMaxLearners was introduced in v3.6, so there's no need to
worry about deprecating, it can be migrated straight into a FeatureGate.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-10 09:17:07 +00:00
Benjamin Wang 79dfce859e
Merge pull request #19551 from k8s-infra-cherrypick-robot/cherry-pick-19496-to-release-3.6
[release-3.6] github/workflows: delete grpcproxy workflow
2025-03-07 07:35:00 +00:00
Benjamin Wang e7691c4c15
Merge pull request #19550 from k8s-infra-cherrypick-robot/cherry-pick-19422-to-release-3.6
[release-3.6] github/workflows: remove fuzzing workflow.
2025-03-07 07:34:24 +00:00
Benjamin Wang 82e5b24af6
Merge pull request #19549 from k8s-infra-cherrypick-robot/cherry-pick-19421-to-release-3.6
[release-3.6] github/workflows: remove contrib workflow
2025-03-07 07:33:45 +00:00
Ivan Valdes ca9898fbd8 github/workflows: delete grpcproxy workflow
This job is already running on the Prow infrastructure.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-07 06:14:19 +00:00
Ivan Valdes bdd1774bec github/workflows: remove fuzzing workflow.
This job is already running in the Prow infrastructure.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-07 06:12:40 +00:00
Ivan Valdes 3ed4c4ef61 github/workflows: remove contrib workflow
This job is already running in the Prow infrastructure.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-07 06:09:15 +00:00
Benjamin Wang 3dfed3f47c
Merge pull request #19547 from ivanvc/release-3.6-remove-release-github-workflow
[release-3.6] github workflows: remove release tests
2025-03-06 09:16:42 +00:00
Benjamin Wang 90f607af01
Merge pull request #19541 from k8s-infra-cherrypick-robot/cherry-pick-19538-to-release-3.6
[release-3.6] deflakey: TestCompactionHash in integration
2025-03-06 08:00:26 +00:00
Ivan Valdes a71ca78e1f
github workflows: remove release tests
This workflow has already been migrated to the prow infrastructure as a
presubmit job.

Cherry-picks PR #19358/commit ed975c2677.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-05 22:52:48 -08:00
Ivan Valdes c2d963e467
version: bump up to 3.6.0-rc.2
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-05 11:16:25 -08:00
James Blair 30c6d2a42b
Merge pull request #19539 from k8s-infra-cherrypick-robot/cherry-pick-19520-to-release-3.6
[release-3.6] Add verify release assets GitHub workflow
2025-03-06 08:07:44 +13:00
Wei Fu 54f2635c2e deflakey: TestCompactionHash in integration
We should use WithCompactPhysical to wait for compaction to finish,
because 50ms sleep can't guarantee compaction is done.

Based on the log, the defragment is finished before compaction, which is
not expected. This patch is to make sure compaction should be finished
before assertation.

```
=========================== defragment ==============
    logger.go:146: 2025-02-27T07:57:18.652Z	INFO	m0	finished defragment	{"member": "m0"}
=====================================================

    logger.go:146: 2025-02-27T07:57:18.652Z	INFO	m0	grpc service status changed	{"member": "m0", "service": "", "status": "SERVING"}
    logger.go:146: 2025-02-27T07:57:18.653Z	INFO	grpc	[[core] [Channel #1457]Channel Connectivity change to SHUTDOWN]
    logger.go:146: 2025-02-27T07:57:18.653Z	INFO	grpc	[[core] [Channel #1457]Closing the name resolver]
    logger.go:146: 2025-02-27T07:57:18.653Z	INFO	grpc	[[core] [Channel #1457]ccBalancerWrapper: closing]
    logger.go:146: 2025-02-27T07:57:18.653Z	INFO	grpc	[[core] [Channel #1457 SubChannel #1458]Subchannel Connectivity change to SHUTDOWN]
    logger.go:146: 2025-02-27T07:57:18.653Z	INFO	grpc	[[core] [Channel #1457 SubChannel #1458]Subchannel deleted]
    logger.go:146: 2025-02-27T07:57:18.654Z	INFO	grpc	[[transport] [client-transport 0xc00237bd48] Closing: rpc error: code = Canceled desc = grpc: the client connection is closing]
    logger.go:146: 2025-02-27T07:57:18.654Z	INFO	grpc	[[transport] [client-transport 0xc00237bd48] loopyWriter exiting with error: rpc error: code = Canceled desc = grpc: the client connection is closing]
    logger.go:146: 2025-02-27T07:57:18.654Z	INFO	grpc	[[transport] [server-transport 0xc0006bb520] Closing: EOF]
    logger.go:146: 2025-02-27T07:57:18.654Z	INFO	grpc	[[core] [Channel #1457]Channel deleted]
    logger.go:146: 2025-02-27T07:57:18.654Z	INFO	grpc	[[transport] [server-transport 0xc0006bb520] loopyWriter exiting with error: transport closed by client]
    hash.go:82:
        	Error Trace:	/home/prow/go/src/github.com/etcd-io/etcd/server/storage/mvcc/testutil/hash.go:82
        	            				/home/prow/go/src/github.com/etcd-io/etcd/server/storage/mvcc/testutil/hash.go:44
        	Error:      	Not equal:
        	            	expected: testutil.KeyValueHash{Hash:0x94694091, CompactRevision:1278, Revision:2507}
        	            	actual  : testutil.KeyValueHash{Hash:0x58af47dc, CompactRevision:2488, Revision:2507}

        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1,4 +1,4 @@
        	            	 (testutil.KeyValueHash) {
        	            	- Hash: (uint32) 2489925777,
        	            	- CompactRevision: (int64) 1278,
        	            	+ Hash: (uint32) 1487882204,
        	            	+ CompactRevision: (int64) 2488,
        	            	  Revision: (int64) 2507
        	Test:       	TestCompactionHash
        	Messages:   	hashes do not match on rev 2488
    cluster.go:1423: ========= Cluster termination started =====================
    logger.go:146: 2025-02-27T07:57:18.655Z	INFO	grpc	[[core] [Channel #1377]Channel Connectivity change to SHUTDOWN]
    logger.go:146: 2025-02-27T07:57:18.655Z	INFO	grpc	[[core] [Channel #1377]Closing the name resolver]
    logger.go:146: 2025-02-27T07:57:18.655Z	INFO	grpc	[[core] [Channel #1377]ccBalancerWrapper: closing]
    logger.go:146: 2025-02-27T07:57:18.656Z	INFO	grpc	[[core] [Channel #1377 SubChannel #1378]Subchannel Connectivity change to SHUTDOWN]
    logger.go:146: 2025-02-27T07:57:18.656Z	INFO	grpc	[[core] [Channel #1377 SubChannel #1378]Subchannel deleted]
    logger.go:146: 2025-02-27T07:57:18.656Z	INFO	grpc	[[transport] [client-transport 0xc0025f2248] Closing: rpc error: code = Canceled desc = grpc: the client connection is closing]
    logger.go:146: 2025-02-27T07:57:18.656Z	INFO	grpc	[[transport] [client-transport 0xc0025f2248] loopyWriter exiting with error: rpc error: code = Canceled desc = grpc: the client connection is closing]
    logger.go:146: 2025-02-27T07:57:18.656Z	INFO	grpc	[[transport] [server-transport 0xc000b56ea0] Closing: EOF]

=========================== compaction ==============
    logger.go:146: 2025-02-27T07:57:18.656Z	INFO	m0	finished scheduled compaction	{"member": "m0", "compact-revision": 2488, "took": "129.590742ms", "hash": 2489925777, "current-db-size-bytes": 40960, "current-db-size": "41 kB", "current-db-size-in-use-bytes": 40960, "current-db-size-in-use": "41 kB"}
=====================================================
```

Fixes: #19497

Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-03-05 18:56:52 +00:00
Ivan Valdes 1fb0f68762 Add verify released binary assets GitHub workflow
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-05 17:13:55 +00:00
Benjamin Wang 7850ff5fc1
Merge pull request #19531 from ivanvc/release-3.6-bump-golang.org-x-net-to-v0.36.0
[release-3.6] dependency: bump golang.org/x/net from v0.34.0 to v0.36.0
2025-03-05 07:19:07 +00:00
Benjamin Wang 2629a463b0
Merge pull request #19527 from ivanvc/release-3.6-bump-go-to-1.23.7
[release-3.6] Bump go toolchain to 1.23.7
2025-03-05 07:18:32 +00:00
Ivan Valdes 0cad8942be
Bump go toolchain to 1.23.7
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-04 17:15:56 -08:00
Ivan Valdes 78dd7eeea2
dependency: bump golang.org/x/net from v0.35.0 to v0.36.0
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-03-04 17:09:09 -08:00
Benjamin Wang 6f02e59f4f
Merge pull request #19522 from ahrtr/3.6_curl_watch_20250304
[3.6] Fix the issue of etcdserver crashing on receiving REST watch stream requests
2025-03-04 21:25:02 +00:00
Benjamin Wang 84fefb1e95 ensure the version of golang.org/x/net consistent
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-04 20:31:42 +00:00
Benjamin Wang 8fd8f8011b ensure the version consistent of google.golang.org/genproto/googleapis/rpc
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-04 20:19:47 +00:00
Benjamin Wang 325fd876ad re-generate api/etcdserverpb/gw/rpc.pb.gw.go
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-04 20:05:32 +00:00
Benjamin Wang d2116e82cf Bump grpc-gateway/v2 to v2.26.3
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-04 20:00:54 +00:00
Benjamin Wang a6660bee68 Create an e2e test to reproduce the issue of etcdserver crashing on receiving watch request
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-03-04 19:58:26 +00:00
Benjamin Wang 321948727a
Merge pull request #19507 from k8s-infra-cherrypick-robot/cherry-pick-19504-to-release-3.6
[release-3.6] tests: deflakey TestLeaseGrantKeepAliveOnce
2025-03-03 10:32:40 +00:00
tcchawla a7319eb3f0 tests: deflakey TestLeaseGrantKeepAliveOnce
Signed-off-by: tcchawla <tc.chawla2000@gmail.com>
2025-03-03 09:37:07 +00:00
Benjamin Wang 161e2b122d
Merge pull request #19501 from k8s-infra-cherrypick-robot/cherry-pick-19498-to-release-3.6
[release-3.6] etcdserver: Fixing minor typos in v3election.proto and rpc.proto
2025-02-27 16:53:46 +00:00
Ashik J M 9d6ec6a1ad etcdserver: Fixing minor typos in v3election.proto and rpc.proto
Signed-off-by: Ashik J M <ashikjm@gmail.com>
2025-02-27 15:48:17 +00:00
Benjamin Wang 733bd9e000
Merge pull request #19495 from k8s-infra-cherrypick-robot/cherry-pick-19452-to-release-3.6
[release-3.6] Add prometheus metric for server feature gate
2025-02-27 07:44:51 +00:00
Gang Li 27e3863975 add prometheus metric
Signed-off-by: Gang Li <ganglica@google.com>
Signed-off-by: Gang Li <gangligit@gmail.com>
2025-02-26 21:34:57 +00:00
Ivan Valdes 12ac41a87e
version: bump up to 3.6.0-rc.1
Signed-off-by: Ivan Valdes <iv@a.ki>
2025-02-25 11:33:52 -08:00
Benjamin Wang b9d33a23ba
Merge pull request #19483 from k8s-infra-cherrypick-robot/cherry-pick-19473-to-release-3.6
[release-3.6] Fix flaky `TestLeaseKeepAliveOneSecond`
2025-02-25 19:16:59 +00:00
Benjamin Wang 692198378d Fix flaky TestLeaseKeepAliveSeconds
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-02-25 18:23:56 +00:00
Benjamin Wang 22f450af10
Merge pull request #19481 from ahrtr/3.6_lease_20250225
[3.6] Fix TestLeaseGrantTimeToLiveExpired flaky due to leader change
2025-02-25 17:59:02 +00:00
Benjamin Wang 6662b3ce6b Fix TestLeaseGrantTimeToLiveExpired flaky due to leader change
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-02-25 09:46:24 +00:00
Benjamin Wang efcf06a326
Merge pull request #19480 from ivanvc/release-3.6-golang-x-crypto-bump-to-v0.35.0
[release-3.6] depedency: bump golang.org/x/crypto from v0.32.0 to v0.35.0
2025-02-25 09:29:01 +00:00
Benjamin Wang ddfc34f7ee
Merge pull request #19443 from k8s-infra-cherrypick-robot/cherry-pick-19432-to-release-3.6
[release-3.6] Use RLock in Demoted method for read-only access to expiry
2025-02-25 07:58:24 +00:00
Ivan Valdes 60b46a3e56
depedency: bump golang.org/x/crypto from v0.32.0 to v0.35.0
To address CVE-2025-22869.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-24 23:22:22 -08:00
Benjamin Wang 3c83cd9be6
Merge pull request #19468 from k8s-infra-cherrypick-robot/cherry-pick-19446-to-release-3.6
[release-3.6] etcdserver: Update description for count field in the RangeResponse message
2025-02-24 21:28:00 +00:00
Benjamin Wang 935f0c030f
Merge pull request #19471 from fuweid/backport-DowngradeInfo-3.6
[3.6] Backport DowngradeInfo proto change
2025-02-23 16:38:03 +00:00
Wei Fu a743e47970 deflake: TestDowngradeCancellationAfterDowngrading1InClusterOf3
Fixes: 65159a2b96 (*: Update cases related to Downgrade)

Signed-off-by: Wei Fu <fuweid89@gmail.com>
(cherry picked from commit 2de17bd396)
Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-02-23 10:41:50 -05:00
Wei Fu d758a64121 *: Update cases related to Downgrade
1. Update DowngradeUpgradeMembersByID

If it's downgrading process, the desire version of cluster should be
target one.
If it's upgrading process, the desire version of cluster should be
determined by mininum binary version of members.

2. Remove AssertProcessLogs from DowngradeEnable

The log message "The server is ready to downgrade" appears only when the storage
version monitor detects a mismatch between the cluster and storage versions.

If traffic is insufficient to trigger a commit or if an auto-commit occurs right
after reading the storage version, the monitor may fail to update it, leading
to errors like:

```bash
"msg":"failed to update storage version","cluster-version":"3.6.0",
"error":"cannot detect storage schema version: missing confstate information"
```

Given this, we should remove the AssertProcessLogs statement.

Similar to #19313

Signed-off-by: Wei Fu <fuweid89@gmail.com>
(cherry picked from commit 65159a2b96)
Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-02-23 10:41:39 -05:00
Wei Fu d3c835e780 etcdctl: support downgrade info in endpoint command
Signed-off-by: Wei Fu <fuweid89@gmail.com>
(cherry picked from commit 091b6ed718)
Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-02-23 10:41:34 -05:00
Wei Fu ae8c00209d v3rpc: add DowngradeInfo in status API
Signed-off-by: Wei Fu <fuweid89@gmail.com>
(cherry picked from commit 8575de3bab)
Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-02-23 10:41:29 -05:00
Wei Fu 586291e445 proto: add DowngradeProcessInfo in statusResponse
Signed-off-by: Wei Fu <fuweid89@gmail.com>
(cherry picked from commit 9d57554c4c)
Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-02-23 10:41:22 -05:00
Ashik J M ec0aa63cf2 etcdserver: Update description for count field in the RangeResponse message
To highlight that it doesn't honour the limit and filters (Min or Max, Create or Modify, Revisions)

Signed-off-by: Ashik J M <ashikjm@gmail.com>
2025-02-23 10:48:19 +00:00
Benjamin Wang 0f89474554
Merge pull request #19455 from k8s-infra-cherrypick-robot/cherry-pick-19342-to-release-3.6
[release-3.6] Move interface `AlarmBackend` from `server/etcdserver/api/v3alarm` to `server/storage/schema` to fix the `unexported-return` lint error
2025-02-21 10:03:43 +00:00
adeyemi 1fd8887a6f Move AlarmBackend interface to fix unexported-return
Signed-off-by: adeyemi <adeyemi.aladesawe@gmail.com>
2025-02-20 23:19:03 +00:00
Benjamin Wang fd47d1b6d6
Merge pull request #19447 from k8s-infra-cherrypick-robot/cherry-pick-19364-to-release-3.6
[release-3.6] codecov: improve coverage upload
2025-02-18 20:27:40 +00:00
Ivan Valdes db62c7c4fc codecov: improve coverage upload
Align running the code coverage upload with other workflows by
executing it from a Makefile target.

Update the current GitHub workflow to call this new target.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-18 18:13:16 +00:00
huangzw d057562fc5 perf: use RLock in Demoted method for read-only access to expiry
Signed-off-by: huangzw <huangzw@2345.com>
2025-02-18 10:29:27 +00:00
Benjamin Wang 0e40f37fbe
Merge pull request #19420 from k8s-infra-cherrypick-robot/cherry-pick-19418-to-release-3.6
[release-3.6] Fix release script prerelease GitHub template release
2025-02-15 08:12:10 +00:00
Ivan Valdes a46f0094e7 scripts/release: fix typo in "flag"
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-14 20:36:22 +00:00
Ivan Valdes b06c1ec120 scripts/release: fix getting version minor for prereleases
The GitHub release templates had the wrong version minor when there's a
prerelease part in the version (i.e., v3.6.0-rc.0). It cut until the
last dot, leaving a wrong minor version (i.e., v3.6.0-rc).

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-14 20:36:22 +00:00
Ivan Valdes bea21855ba
version: bump up to 3.6.0-rc.0
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-13 12:10:38 -08:00
Benjamin Wang 8e75018e3a
Merge pull request #19414 from k8s-infra-cherrypick-robot/cherry-pick-19413-to-release-3.6
[release-3.6] Migrate --experimental-set-member-localaddr to using feature flag
2025-02-13 18:14:06 +00:00
Chun-Hung Tseng 4b94ddcda1 Migrate --experimental-set-member-localaddr to using feature flag
Signed-off-by: Chun-Hung Tseng <henrytseng@google.com>
Co-authored-by: Benjamin Wang <benjamin.wang@broadcom.com>
2025-02-13 17:08:53 +00:00
Marek Siarkowicz 73c75b3d16
Merge pull request #19411 from k8s-infra-cherrypick-robot/cherry-pick-19410-to-release-3.6
[release-3.6] Fix a performance regression due to uncertain compaction sleep interval
2025-02-13 13:26:10 +01:00
Benjamin Wang 61ca4093b0 Fix a peformance regression due to uncertain compaction sleep interval
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-02-13 10:37:43 +00:00
Benjamin Wang 302f21d50c
Merge pull request #19409 from k8s-infra-cherrypick-robot/cherry-pick-19408-to-release-3.6
[release-3.6] Fix more v3.6 deprecation comments
2025-02-13 09:41:25 +00:00
Ivan Valdes ef3f1162c6 Standardize help deprecated messages
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-13 07:52:19 +00:00
Ivan Valdes 904e05d0e7 Properly deprecate ExperimentalInitialCorruptCheck
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-13 07:52:19 +00:00
Ivan Valdes 48b338eba1 Properly deprecate ExperimentalStopGRPCServiceOnDefrag
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-13 07:52:19 +00:00
Ivan Valdes e2de4ce2de Properly deprecate ExperimentalTxnModeWriteWithSharedBuffer
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-13 07:52:19 +00:00
Benjamin Wang 34afaca6f7
Merge pull request #19404 from k8s-infra-cherrypick-robot/cherry-pick-19403-to-release-3.6
[release-3.6] server: Remove deprecated NewZapCoreLoggerBuilder
2025-02-13 07:46:43 +00:00
Ivan Valdes f1095ba473 server/embed: Remove deprecated NewZapCoreLoggerBuilder
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-12 21:23:41 +00:00
Benjamin Wang 2feb5a22dc
Merge pull request #19402 from k8s-infra-cherrypick-robot/cherry-pick-19401-to-release-3.6
[release-3.6] Fix v3.6 deprecation notices
2025-02-12 20:30:37 +00:00
Ivan Valdes a0c541b1b1 Fix deprecation comments in server/features
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-12 19:11:37 +00:00
Ivan Valdes 66c533df61 Fix deprecation comments in server/embed
Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-12 19:11:37 +00:00
Ivan Valdes dddcdb5321 Fix rpctypes.ErrClusterIdMismatch deprecation comment
It was pointing to ErrGRPCClusterIDMismatch rather than
ErrClusterIDMismatch.

Signed-off-by: Ivan Valdes <ivan@vald.es>
2025-02-12 19:11:37 +00:00
Benjamin Wang ff8d7a8d7b
Merge pull request #19400 from k8s-infra-cherrypick-robot/cherry-pick-19398-to-release-3.6
[release-3.6] [test] Correct the expected version in downgrade test case
2025-02-12 18:58:17 +00:00
Benjamin Wang bfc38cf92e Correct the expected version in downgrade test case
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-02-12 15:57:45 +00:00
Marek Siarkowicz 71cdab469e
Merge pull request #19392 from k8s-infra-cherrypick-robot/cherry-pick-19388-to-release-3.6
[release-3.6] Minor refacotr on the e2e test framework
2025-02-12 10:45:53 +01:00
Benjamin Wang 5078428404
Merge pull request #19390 from k8s-infra-cherrypick-robot/cherry-pick-19367-to-release-3.6
[release-3.6] Fix a log formatting bug in the e2e downgrade tests
2025-02-12 07:49:28 +00:00
Benjamin Wang 06092f822b Minor refacotr on the e2e test framework
Also resolved the review comment in https://github.com/etcd-io/etcd/pull/19352

Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-02-11 22:01:01 +00:00
Chun-Hung Tseng abbf79f995 Fix a log formatting bug in the e2e downgrade tests
Signed-off-by: Chun-Hung Tseng <henrytseng@google.com>
Co-authored-by: Benjamin Wang <benjamin.wang@broadcom.com>
2025-02-11 21:33:10 +00:00
Benjamin Wang bf1f9985bd
Merge pull request #19389 from k8s-infra-cherrypick-robot/cherry-pick-19352-to-release-3.6
[release-3.6] migrate experimental-snapshot-catchup-entries flag to snapshot-catchup-entries
2025-02-11 21:12:48 +00:00
Ajay Sundar Karuppasamy eee08ed06a migrate experimental-snapshot-catchup-entries flag to snapshot-catchup-entries
Signed-off-by: Ajay Sundar Karuppasamy <ajaysundar@google.com>
2025-02-11 20:17:58 +00:00
Benjamin Wang 47aa45285e
Merge pull request #19387 from k8s-infra-cherrypick-robot/cherry-pick-19385-to-release-3.6
[release-3.6] Migrate experimental distributed tracing flags to non-experimental flags
2025-02-11 19:44:40 +00:00
Benjamin Wang 164f8cff2b Migrate experimental distributed tracing flags to non-experimental flags
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
2025-02-11 18:05:16 +00:00
Benjamin Wang 092fff42b9
Merge pull request #19382 from k8s-infra-cherrypick-robot/cherry-pick-19350-to-release-3.6
[release-3.6] Migrate WALVersion to fix unexported-return of walVersion
2025-02-11 07:49:14 +00:00
adeyemi 37520d4cf1 Migrate WALVersion, and reuse in schema.go
Signed-off-by: adeyemi <adeyemi.aladesawe@gmail.com>
2025-02-10 21:51:01 +00:00
476 changed files with 15402 additions and 20992 deletions

View File

@ -3,7 +3,7 @@
{ {
"name": "Go", "name": "Go",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm", "image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
// Features to add to the dev container. More info: https://containers.dev/features. // Features to add to the dev container. More info: https://containers.dev/features.
"features": { "features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}, "ghcr.io/devcontainers/features/docker-in-docker:2": {},

View File

@ -10,7 +10,7 @@ body:
label: Bug report criteria label: Bug report criteria
description: Please confirm this bug report meets the following criteria. description: Please confirm this bug report meets the following criteria.
options: options:
- label: This bug report is not security related, security issues should be disclosed privately via security@etcd.io. - label: This bug report is not security related, security issues should be disclosed privately via [etcd maintainers](mailto:etcd-maintainers@googlegroups.com).
- label: This is not a support request or question, support requests or questions should be raised in the etcd [discussion forums](https://github.com/etcd-io/etcd/discussions). - label: This is not a support request or question, support requests or questions should be raised in the etcd [discussion forums](https://github.com/etcd-io/etcd/discussions).
- label: You have read the etcd [bug reporting guidelines](https://github.com/etcd-io/etcd/blob/main/Documentation/contributor-guide/reporting_bugs.md). - label: You have read the etcd [bug reporting guidelines](https://github.com/etcd-io/etcd/blob/main/Documentation/contributor-guide/reporting_bugs.md).
- label: Existing open issues along with etcd [frequently asked questions](https://etcd.io/docs/latest/faq) have been checked and this is not a duplicate. - label: Existing open issues along with etcd [frequently asked questions](https://etcd.io/docs/latest/faq) have been checked and this is not a duplicate.

56
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,56 @@
---
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 90
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 21
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- "stage/tracked"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@ -1,99 +0,0 @@
---
name: Build and trigger Antithesis exploration
on:
# pull_request:
# branches: [main]
schedule:
- cron: "0 0 * * *" # run every day at midnight
workflow_dispatch:
inputs:
test:
description: 'Test name'
required: false
type: string
duration:
description: 'Duration (exploration hours)'
required: true
type: int
description:
description: 'Description (avoid quotes, please!)'
required: true
type: string
etcd_ref:
description: 'etcd version to build etcd-server from'
required: false
type: string
email:
description: 'Additional email notification recipient (separate with ;)'
required: true
type: string
cfg_node_count:
description: 'Number of nodes in the etcd cluster'
required: false
type: int
# Declare default permissions as read only.
permissions: read-all
env:
REGISTRY: us-central1-docker.pkg.dev
REPOSITORY: molten-verve-216720/linuxfoundation-repository
jobs:
build-and-push-and-test:
runs-on: ubuntu-latest
environment: Antithesis
env:
CFG_NODE_COUNT: ${{ inputs.cfg_node_count || 3 }}
steps:
- name: Checkout the code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Login to Antithesis Docker Registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ${{ env.REGISTRY }}
username: _json_key
password: ${{ secrets.ANTITHESIS_CONTAINER_REGISTRY_TOKEN }}
- name: Build and push config image
working-directory: ./tests/antithesis
run: |
make antithesis-build-config-image IMAGE_TAG=${{ inputs.etcd_ref || 'main' }}_${{ github.sha }}
export IMAGE="${{ env.REGISTRY }}/${{ env.REPOSITORY }}/etcd-config:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }}"
docker tag etcd-config:latest $IMAGE
docker push $IMAGE
- name: Build and push client image
working-directory: ./tests/antithesis
run: |
make antithesis-build-client-docker-image
export IMAGE="${{ env.REGISTRY }}/${{ env.REPOSITORY }}/etcd-client:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }}"
docker tag etcd-client:latest $IMAGE
docker push $IMAGE
- name: Build and push etcd image
working-directory: ./tests/antithesis
run: |
make antithesis-build-etcd-image REF=${{ inputs.etcd_ref || 'main' }}
export IMAGE="${{ env.REGISTRY }}/${{ env.REPOSITORY }}/etcd-server:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }}"
docker tag etcd-server:latest $IMAGE
docker push $IMAGE
- name: Run Antithesis Tests
uses: antithesishq/antithesis-trigger-action@6c0a27302c0a3cd97d87d40bd6704e673abed4bb # main commit on Mar 13, 2025
with:
notebook_name: etcd
tenant: linuxfoundation
username: ${{ secrets.ANTITHESIS_WEBHOOK_USERNAME }}
password: ${{ secrets.ANTITHESIS_WEBHOOK_PASSWORD }}
github_token: ${{ secrets.GH_PAT }}
config_image: us-central1-docker.pkg.dev/molten-verve-216720/linuxfoundation-repository/etcd-config:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }}
images: us-central1-docker.pkg.dev/molten-verve-216720/linuxfoundation-repository/etcd-client:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }};us-central1-docker.pkg.dev/molten-verve-216720/linuxfoundation-repository/etcd-server:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }};docker.io/library/ubuntu:latest;us-central1-docker.pkg.dev/molten-verve-216720/linuxfoundation-repository/etcd-config:${{ inputs.etcd_ref || 'main' }}_${{ github.sha }}
description: ${{ inputs.description || 'etcd nightly antithesis run' }}
email_recipients: ${{ inputs.email || 'siarkowicz@google.com' }}
test_name: ${{ inputs.test || 'etcd nightly antithesis run' }}
additional_parameters: |-
custom.duration = ${{ inputs.duration || 12 }}
antithesis.source = ${{ inputs.etcd_ref || 'main' }}

View File

@ -1,69 +0,0 @@
---
name: Verify Antithesis Docker Compose Pipeline
on:
push:
branches:
- main
paths:
- 'tests/antithesis/**'
- '.github/workflows/antithesis-verify.yml'
pull_request:
paths:
- 'tests/antithesis/**'
- '.github/workflows/antithesis-verify.yml'
jobs:
test-docker-compose:
strategy:
matrix:
node-count: [1, 3]
name: Test ${{ matrix.node-count }}-node cluster
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build etcd-server and etcd-client images
run: |
make -C tests/antithesis antithesis-build-etcd-image
make -C tests/antithesis antithesis-build-client-docker-image CFG_NODE_COUNT=${{ matrix.node-count }}
- name: Run docker-compose up
working-directory: ./tests/antithesis
run: |
make antithesis-docker-compose-up CFG_NODE_COUNT=${{ matrix.node-count }} &
- name: Check for healthy cluster
working-directory: ./tests/antithesis
run: |
timeout=120
interval=10
end_time=$(( $(date +%s) + timeout ))
while [ $(date +%s) -lt $end_time ]; do
# The client container might not be running yet, so ignore errors from docker compose logs
if docker compose -f config/docker-compose-${{ matrix.node-count }}-node.yml logs client 2>/dev/null | grep -q "Client \[entrypoint\]: cluster is healthy!"; then
echo "Cluster is healthy!"
exit 0
fi
echo "Waiting for cluster to become healthy..."
sleep $interval
done
echo "Cluster did not become healthy in ${timeout} seconds."
docker compose -f config/docker-compose-${{ matrix.node-count }}-node.yml logs
exit 1
- name: Run traffic
working-directory: ./tests/antithesis
run: make antithesis-run-container-traffic CFG_NODE_COUNT=${{ matrix.node-count }}
- name: Run validation
working-directory: ./tests/antithesis
run: make antithesis-run-container-validation CFG_NODE_COUNT=${{ matrix.node-count }}
- name: Clean up
if: always()
working-directory: ./tests/antithesis
run: make antithesis-clean CFG_NODE_COUNT=${{ matrix.node-count }}

View File

@ -40,7 +40,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
with: with:
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file. # By default, queries listed here will override any specified in a config file.
@ -50,6 +50,6 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 uses: github/codeql-action/autobuild@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8

View File

@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- id: goversion - id: goversion
run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT" run: echo "goversion=$(cat .go-version)" >> "$GITHUB_OUTPUT"
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with: with:
go-version: ${{ steps.goversion.outputs.goversion }} go-version: ${{ steps.goversion.outputs.goversion }}
- env: - env:

View File

@ -28,7 +28,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
@ -42,7 +42,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab. # format to the repository Actions tab.
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
@ -50,6 +50,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 uses: github/codeql-action/upload-sarif@dd746615b3b9d728a6a37ca2045b68ca76d4841a # v3.28.8
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@ -1,30 +0,0 @@
---
name: Mark and close stale issues and PRs
on:
schedule:
- cron: '0 0 * * *'
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 #v9.1.0
with:
days-until-stale: 90
days-until-close: 21
stale-issue-label: 'stale'
stale-pr-label: 'stale'
exempt-labels: 'stage/tracked,help wanted'
exempt-projects: false
exempt-milestones: false
exempt-assignees: false
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions.'
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed after 21 days if no further activity occurs. Thank you for your contributions.'
close-issue-message: ''
close-pr-message: ''
operations-per-run: 30

View File

@ -1 +1 @@
1.24.5 1.23.11

View File

@ -1,16 +0,0 @@
---
## [v2.3.8](https://github.com/etcd-io/etcd/releases/tag/v2.3.8) (2017-02-17)
See [code changes](https://github.com/etcd-io/etcd/compare/v2.3.7...v2.3.8).
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---

View File

@ -1,291 +0,0 @@
---
## [v3.0.16](https://github.com/etcd-io/etcd/releases/tag/v3.0.16) (2016-11-13)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.15...v3.0.16) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.4*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.15](https://github.com/etcd-io/etcd/releases/tag/v3.0.15) (2016-11-11)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.14...v3.0.15) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Fixed
- Fix cancel watch request with wrong range end.
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.14](https://github.com/etcd-io/etcd/releases/tag/v3.0.14) (2016-11-04)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.13...v3.0.14) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Added
- v3 `etcdctl migrate` command now supports `--no-ttl` flag to discard keys on transform.
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.13](https://github.com/etcd-io/etcd/releases/tag/v3.0.13) (2016-10-24)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.12...v3.0.13) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.12](https://github.com/etcd-io/etcd/releases/tag/v3.0.12) (2016-10-07)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.11...v3.0.12) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.11](https://github.com/etcd-io/etcd/releases/tag/v3.0.11) (2016-10-07)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.10...v3.0.11) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Added
- Server returns previous key-value (optional)
- `clientv3.WithPrevKV` option
- v3 etcdctl `put,watch,del --prev-kv` flag
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.10](https://github.com/etcd-io/etcd/releases/tag/v3.0.10) (2016-09-23)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.9...v3.0.10) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.9](https://github.com/etcd-io/etcd/releases/tag/v3.0.9) (2016-09-15)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.8...v3.0.9) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Added
- Warn on domain names on listen URLs (v3.2 will reject domain names).
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.8](https://github.com/etcd-io/etcd/releases/tag/v3.0.8) (2016-09-09)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.7...v3.0.8) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Other
- Allow only IP addresses in listen URLs (domain names are rejected).
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.7](https://github.com/etcd-io/etcd/releases/tag/v3.0.7) (2016-08-31)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.6...v3.0.7) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Other
- SRV records only allow A records (RFC 2052).
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.6](https://github.com/etcd-io/etcd/releases/tag/v3.0.6) (2016-08-19)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.5...v3.0.6) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.5](https://github.com/etcd-io/etcd/releases/tag/v3.0.5) (2016-08-19)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.4...v3.0.5) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Other
- SRV records (e.g., infra1.example.com) must match the discovery domain (i.e., example.com) if no custom certificate authority is given.
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.4](https://github.com/etcd-io/etcd/releases/tag/v3.0.4) (2016-07-27)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.3...v3.0.4) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Added
- v2 `etcdctl ls` command now supports `--output=json`.
- Add /var/lib/etcd directory to etcd official Docker image.
### Other
- v2 auth can now use common name from TLS certificate when `--client-cert-auth` is enabled.
### Go
- Compile with [*Go 1.6.3*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.3](https://github.com/etcd-io/etcd/releases/tag/v3.0.3) (2016-07-15)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.2...v3.0.3) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Other
- Revert Dockerfile to use `CMD`, instead of `ENTRYPOINT`, to support `etcdctl` run.
- Docker commands for v3.0.2 won't work without specifying executable binary paths.
- v3 etcdctl default endpoints are now `127.0.0.1:2379`.
### Go
- Compile with [*Go 1.6.2*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.2](https://github.com/etcd-io/etcd/releases/tag/v3.0.2) (2016-07-08)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.1...v3.0.2) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Other
- Dockerfile uses `ENTRYPOINT`, instead of `CMD`, to run etcd without binary path specified.
### Go
- Compile with [*Go 1.6.2*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.1](https://github.com/etcd-io/etcd/releases/tag/v3.0.1) (2016-07-01)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.0...v3.0.1) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.2*](https://golang.org/doc/devel/release.html#go1.6).
---
## [v3.0.0](https://github.com/etcd-io/etcd/releases/tag/v3.0.0) (2016-06-30)
See [code changes](https://github.com/etcd-io/etcd/compare/v2.3.0...v3.0.0) and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_0/).**
### Go
- Compile with [*Go 1.6.2*](https://golang.org/doc/devel/release.html#go1.6).
---

View File

@ -1,574 +0,0 @@
Previous change logs can be found at [CHANGELOG-3.0](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.0.md).
---
## [v3.1.21](https://github.com/etcd-io/etcd/releases/tag/v3.1.21) (2019-TBD)
### etcdctl v3
- [Strip out insecure endpoints from DNS SRV records when using discovery](https://github.com/etcd-io/etcd/pull/10443) with etcdctl v2
- Add [`etcdctl endpoint health --write-out` support](https://github.com/etcd-io/etcd/pull/9540).
- Previously, [`etcdctl endpoint health --write-out json` did not work](https://github.com/etcd-io/etcd/issues/9532).
- The command output is changed. Previously, if endpoint is unreachable, the command output is
"\<endpoint\> is unhealthy: failed to connect: \<error message\>". This change unified the error message, all error types
now have the same output "\<endpoint\> is unhealthy: failed to commit proposal: \<error message\>".
### Metrics, Monitoring
See [List of metrics](https://github.com/etcd-io/etcd/tree/main/Documentation/metrics) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Fix bug where [db_compaction_total_duration_milliseconds metric incorrectly measured duration as 0](https://github.com/etcd-io/etcd/pull/10646).
---
## [v3.1.20](https://github.com/etcd-io/etcd/releases/tag/v3.1.20) (2018-10-10)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.19...v3.1.20) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Improved
- Improve ["became inactive" warning log](https://github.com/etcd-io/etcd/pull/10024), which indicates message send to a peer failed.
- Improve [read index wait timeout warning log](https://github.com/etcd-io/etcd/pull/10026), which indicates that local node might have slow network.
- Add [gRPC interceptor for debugging logs](https://github.com/etcd-io/etcd/pull/9990); enable `etcd --debug` flag to see per-request debug information.
- Add [consistency check in snapshot status](https://github.com/etcd-io/etcd/pull/10109). If consistency check on snapshot file fails, `snapshot status` returns `"snapshot file integrity check failed..."` error.
### Metrics, Monitoring
See [List of metrics](https://github.com/etcd-io/etcd/tree/main/Documentation/metrics) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Improve [`etcd_network_peer_round_trip_time_seconds`](https://github.com/etcd-io/etcd/pull/10155) Prometheus metric to track leader heartbeats.
- Previously, it only samples the TCP connection for snapshot messages.
- Display all registered [gRPC metrics at start](https://github.com/etcd-io/etcd/pull/10034).
- Add [`etcd_snap_db_fsync_duration_seconds_count`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_snap_db_save_total_duration_seconds_bucket`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_network_snapshot_send_success`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_network_snapshot_send_failures`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_network_snapshot_send_total_duration_seconds`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_network_snapshot_receive_success`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_network_snapshot_receive_failures`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_network_snapshot_receive_total_duration_seconds`](https://github.com/etcd-io/etcd/pull/9997) Prometheus metric.
- Add [`etcd_server_id`](https://github.com/etcd-io/etcd/pull/9998) Prometheus metric.
- Add [`etcd_server_health_success`](https://github.com/etcd-io/etcd/pull/10156) Prometheus metric.
- Add [`etcd_server_health_failures`](https://github.com/etcd-io/etcd/pull/10156) Prometheus metric.
- Add [`etcd_server_read_indexes_failed_total`](https://github.com/etcd-io/etcd/pull/10094) Prometheus metric.
### client v3
- Fix logic on [release lock key if cancelled](https://github.com/etcd-io/etcd/pull/10153) in `clientv3/concurrency` package.
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.19](https://github.com/etcd-io/etcd/releases/tag/v3.1.19) (2018-07-24)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.18...v3.1.19) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Improved
- Improve [Raft Read Index timeout warning messages](https://github.com/etcd-io/etcd/pull/9897).
### Metrics, Monitoring
See [List of metrics](https://github.com/etcd-io/etcd/tree/main/Documentation/metrics) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Add [`etcd_server_go_version`](https://github.com/etcd-io/etcd/pull/9957) Prometheus metric.
- Add [`etcd_server_slow_read_indexes_total`](https://github.com/etcd-io/etcd/pull/9897) Prometheus metric.
- Add [`etcd_server_quota_backend_bytes`](https://github.com/etcd-io/etcd/pull/9820) Prometheus metric.
- Use it with `etcd_mvcc_db_total_size_in_bytes` and `etcd_mvcc_db_total_size_in_use_in_bytes`.
- `etcd_server_quota_backend_bytes 2.147483648e+09` means current quota size is 2 GB.
- `etcd_mvcc_db_total_size_in_bytes 20480` means current physically allocated DB size is 20 KB.
- `etcd_mvcc_db_total_size_in_use_in_bytes 16384` means future DB size if defragment operation is complete.
- `etcd_mvcc_db_total_size_in_bytes - etcd_mvcc_db_total_size_in_use_in_bytes` is the number of bytes that can be saved on disk with defragment operation.
- Add [`etcd_mvcc_db_total_size_in_bytes`](https://github.com/etcd-io/etcd/pull/9819) Prometheus metric.
- In addition to [`etcd_debugging_mvcc_db_total_size_in_bytes`](https://github.com/etcd-io/etcd/pull/9819).
- Add [`etcd_mvcc_db_total_size_in_use_in_bytes`](https://github.com/etcd-io/etcd/pull/9256) Prometheus metric.
- Use it with `etcd_mvcc_db_total_size_in_bytes` and `etcd_mvcc_db_total_size_in_use_in_bytes`.
- `etcd_server_quota_backend_bytes 2.147483648e+09` means current quota size is 2 GB.
- `etcd_mvcc_db_total_size_in_bytes 20480` means current physically allocated DB size is 20 KB.
- `etcd_mvcc_db_total_size_in_use_in_bytes 16384` means future DB size if defragment operation is complete.
- `etcd_mvcc_db_total_size_in_bytes - etcd_mvcc_db_total_size_in_use_in_bytes` is the number of bytes that can be saved on disk with defragment operation.
### client v3
- Fix [lease keepalive interval updates when response queue is full](https://github.com/etcd-io/etcd/pull/9952).
- If `<-chan *clientv3LeaseKeepAliveResponse` from `clientv3.Lease.KeepAlive` was never consumed or channel is full, client was [sending keepalive request every 500ms](https://github.com/etcd-io/etcd/issues/9911) instead of expected rate of every "TTL / 3" duration.
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.18](https://github.com/etcd-io/etcd/releases/tag/v3.1.18) (2018-06-15)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.17...v3.1.18) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Metrics, Monitoring
See [List of metrics](https://github.com/etcd-io/etcd/tree/main/Documentation/metrics) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Add [`etcd_server_version`](https://github.com/etcd-io/etcd/pull/8960) Prometheus metric.
- To replace [Kubernetes `etcd-version-monitor`](https://github.com/etcd-io/etcd/issues/8948).
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.17](https://github.com/etcd-io/etcd/releases/tag/v3.1.17) (2018-06-06)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.16...v3.1.17) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Fix [v3 snapshot recovery](https://github.com/etcd-io/etcd/issues/7628).
- A follower receives a leader snapshot to be persisted as a `[SNAPSHOT-INDEX].snap.db` file on disk.
- Now, server [ensures that the incoming snapshot be persisted on disk before loading it](https://github.com/etcd-io/etcd/pull/7876).
- Otherwise, index mismatch happens and triggers server-side panic (e.g. newer WAL entry with outdated snapshot index).
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.16](https://github.com/etcd-io/etcd/releases/tag/v3.1.16) (2018-05-31)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.15...v3.1.16) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Fix [`mvcc` server panic from restore operation](https://github.com/etcd-io/etcd/pull/9775).
- Let's assume that a watcher had been requested with a future revision X and sent to node A that became network-partitioned thereafter. Meanwhile, cluster makes progress. Then when the partition gets removed, the leader sends a snapshot to node A. Previously if the snapshot's latest revision is still lower than the watch revision X, **etcd server panicked** during snapshot restore operation.
- Now, this server-side panic has been fixed.
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.15](https://github.com/etcd-io/etcd/releases/tag/v3.1.15) (2018-05-09)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.14...v3.1.15) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Purge old [`*.snap.db` snapshot files](https://github.com/etcd-io/etcd/pull/7967).
- Previously, etcd did not respect `--max-snapshots` flag to purge old `*.snap.db` files.
- Now, etcd purges old `*.snap.db` files to keep maximum `--max-snapshots` number of files on disk.
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.14](https://github.com/etcd-io/etcd/releases/tag/v3.1.14) (2018-04-24)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.13...v3.1.14) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Metrics, Monitoring
See [List of metrics](https://github.com/etcd-io/etcd/tree/main/Documentation/metrics) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Add [`etcd_server_is_leader`](https://github.com/etcd-io/etcd/pull/9587) Prometheus metric.
### etcd server
- Add [`--initial-election-tick-advance`](https://github.com/etcd-io/etcd/pull/9591) flag to configure initial election tick fast-forward.
- By default, `--initial-election-tick-advance=true`, then local member fast-forwards election ticks to speed up "initial" leader election trigger.
- This benefits the case of larger election ticks. For instance, cross datacenter deployment may require longer election timeout of 10-second. If true, local node does not need wait up to 10-second. Instead, forwards its election ticks to 8-second, and have only 2-second left before leader election.
- Major assumptions are that: cluster has no active leader thus advancing ticks enables faster leader election. Or cluster already has an established leader, and rejoining follower is likely to receive heartbeats from the leader after tick advance and before election timeout.
- However, when network from leader to rejoining follower is congested, and the follower does not receive leader heartbeat within left election ticks, disruptive election has to happen thus affecting cluster availabilities.
- Now, this can be disabled by setting `--initial-election-tick-advance=false`.
- Disabling this would slow down initial bootstrap process for cross datacenter deployments. Make tradeoffs by configuring `--initial-election-tick-advance` at the cost of slow initial bootstrap.
- If single-node, it advances ticks regardless.
- Address [disruptive rejoining follower node](https://github.com/etcd-io/etcd/issues/9333).
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.13](https://github.com/etcd-io/etcd/releases/tag/v3.1.13) (2018-03-29)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.12...v3.1.13) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Improved
- Adjust [election timeout on server restart](https://github.com/etcd-io/etcd/pull/9415) to reduce [disruptive rejoining servers](https://github.com/etcd-io/etcd/issues/9333).
- Previously, etcd fast-forwards election ticks on server start, with only one tick left for leader election. This is to speed up start phase, without having to wait until all election ticks elapse. Advancing election ticks is useful for cross datacenter deployments with larger election timeouts. However, it was affecting cluster availability if the last tick elapses before leader contacts the restarted node.
- Now, when etcd restarts, it adjusts election ticks with more than one tick left, thus more time for leader to prevent disruptive restart.
### Metrics, Monitoring
See [List of metrics](https://github.com/etcd-io/etcd/tree/main/Documentation/metrics) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Add missing [`etcd_network_peer_sent_failures_total` count](https://github.com/etcd-io/etcd/pull/9437).
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.12](https://github.com/etcd-io/etcd/releases/tag/v3.1.12) (2018-03-08)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.11...v3.1.12) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Fix [`mvcc` "unsynced" watcher restore operation](https://github.com/etcd-io/etcd/pull/9297).
- "unsynced" watcher is watcher that needs to be in sync with events that have happened.
- That is, "unsynced" watcher is the slow watcher that was requested on old revision.
- "unsynced" watcher restore operation was not correctly populating its underlying watcher group.
- Which possibly causes [missing events from "unsynced" watchers](https://github.com/etcd-io/etcd/issues/9086).
- A node gets network partitioned with a watcher on a future revision, and falls behind receiving a leader snapshot after partition gets removed. When applying this snapshot, etcd watch storage moves current synced watchers to unsynced since sync watchers might have become stale during network partition. And reset synced watcher group to restart watcher routines. Previously, there was a bug when moving from synced watcher group to unsynced, thus client would miss events when the watcher was requested to the network-partitioned node.
### Go
- Compile with [*Go 1.8.7*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.11](https://github.com/etcd-io/etcd/releases/tag/v3.1.11) (2017-11-28)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.10...v3.1.11) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- [#8411](https://github.com/etcd-io/etcd/issues/8411),[#8806](https://github.com/etcd-io/etcd/pull/8806) backport "mvcc: sending events after restore"
- [#8009](https://github.com/etcd-io/etcd/issues/8009),[#8902](https://github.com/etcd-io/etcd/pull/8902) backport coreos/bbolt v1.3.1-coreos.5
### Go
- Compile with [*Go 1.8.5*](https://golang.org/doc/devel/release.html#go1.8).
---
## [v3.1.10](https://github.com/etcd-io/etcd/releases/tag/v3.1.10) (2017-07-14)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.9...v3.1.10) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Added
- Tag docker images with minor versions.
- e.g. `docker pull quay.io/coreos/etcd:v3.1` to fetch latest v3.1 versions.
### Go
- Compile with [*Go 1.8.3*](https://golang.org/doc/devel/release.html#go1.8).
- Fix panic on `net/http.CloseNotify`
---
## [v3.1.9](https://github.com/etcd-io/etcd/releases/tag/v3.1.9) (2017-06-09)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.8...v3.1.9) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Allow v2 snapshot over 512MB.
### Go
- Compile with [*Go 1.7.6*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.8](https://github.com/etcd-io/etcd/releases/tag/v3.1.8) (2017-05-19)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.7...v3.1.8) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.7](https://github.com/etcd-io/etcd/releases/tag/v3.1.7) (2017-04-28)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.6...v3.1.7) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.6](https://github.com/etcd-io/etcd/releases/tag/v3.1.6) (2017-04-19)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.5...v3.1.6) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Fill in Auth API response header.
- Remove auth check in Status API.
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.5](https://github.com/etcd-io/etcd/releases/tag/v3.1.5) (2017-03-27)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.4...v3.1.5) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd server
- Fix raft memory leak issue.
- Fix Windows file path issues.
### Other
- Add `/etc/nsswitch.conf` file to alpine-based Docker image.
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.4](https://github.com/etcd-io/etcd/releases/tag/v3.1.4) (2017-03-22)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.3...v3.1.4) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.3](https://github.com/etcd-io/etcd/releases/tag/v3.1.3) (2017-03-10)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.2...v3.1.3) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd gateway
- Fix `etcd gateway` schema handling in DNS discovery.
- Fix sd_notify behaviors in `gateway`, `grpc-proxy`.
### gRPC Proxy
- Fix sd_notify behaviors in `gateway`, `grpc-proxy`.
### Other
- Use machine default host when advertise URLs are default values(`localhost:2379,2380`) AND if listen URL is `0.0.0.0`.
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.2](https://github.com/etcd-io/etcd/releases/tag/v3.1.2) (2017-02-24)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.1...v3.1.2) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### etcd gateway
- Fix `etcd gateway` with multiple endpoints.
### Other
- Use IPv4 default host, by default (when IPv4 and IPv6 are available).
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.1](https://github.com/etcd-io/etcd/releases/tag/v3.1.1) (2017-02-17)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.1.0...v3.1.1) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Go
- Compile with [*Go 1.7.5*](https://golang.org/doc/devel/release.html#go1.7).
---
## [v3.1.0](https://github.com/etcd-io/etcd/releases/tag/v3.1.0) (2017-01-20)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.0.0...v3.1.0) and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.1 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_1/).**
### Improved
- Faster linearizable reads (implements Raft [read-index](https://github.com/etcd-io/etcd/pull/6212)).
- v3 authentication API is now stable.
### Breaking Changes
- Deprecated following gRPC metrics in favor of [go-grpc-prometheus](https://github.com/grpc-ecosystem/go-grpc-prometheus).
- `etcd_grpc_requests_total`
- `etcd_grpc_requests_failed_total`
- `etcd_grpc_active_streams`
- `etcd_grpc_unary_requests_duration_seconds`
### Dependency
- Upgrade [`github.com/ugorji/go/codec`](https://github.com/ugorji/go) to [**`ugorji/go@9c7f9b7`**](https://github.com/ugorji/go/commit/9c7f9b7a2bc3a520f7c7b30b34b7f85f47fe27b6), and [regenerate v2 `client`](https://github.com/etcd-io/etcd/pull/6945).
### Security, Authentication
See [security doc](https://etcd.io/docs/latest/op-guide/security/) for more details.
- SRV records (e.g., infra1.example.com) must match the discovery domain (i.e., example.com) if no custom certificate authority is given.
- `TLSConfig.ServerName` is ignored with user-provided certificates for backwards compatibility; to be deprecated.
- For example, `etcd --discovery-srv=example.com` will only authenticate peers/clients when the provided certs have root domain `example.com` as an entry in Subject Alternative Name (SAN) field.
### etcd server
- Automatic leadership transfer when leader steps down.
- etcd flags
- `--strict-reconfig-check` flag is set by default.
- Add `--log-output` flag.
- Add `--metrics` flag.
- etcd uses default route IP if advertise URL is not given.
- Cluster rejects removing members if quorum will be lost.
- Discovery now has upper limit for waiting on retries.
- Warn on binding listeners through domain names; to be deprecated.
- v3.0 and v3.1 with `--auto-compaction-retention=10` run periodic compaction on v3 key-value store for every 10-hour.
- Compactor only supports periodic compaction.
- Compactor records latest revisions every 5-minute, until it reaches the first compaction period (e.g. 10-hour).
- In order to retain key-value history of last compaction period, it uses the last revision that was fetched before compaction period, from the revision records that were collected every 5-minute.
- When `--auto-compaction-retention=10`, compactor uses revision 100 for compact revision where revision 100 is the latest revision fetched from 10 hours ago.
- If compaction succeeds or requested revision has already been compacted, it resets period timer and starts over with new historical revision records (e.g. restart revision collect and compact for the next 10-hour period).
- If compaction fails, it retries in 5 minutes.
### client v3
- Add `SetEndpoints` method; update endpoints at runtime.
- Add `Sync` method; auto-update endpoints at runtime.
- Add `Lease TimeToLive` API; fetch lease information.
- replace Config.Logger field with global logger.
- Get API responses are sorted in ascending order by default.
### etcdctl v3
- Add `lease timetolive` command.
- Add `--print-value-only` flag to get command.
- Add `--dest-prefix` flag to make-mirror command.
- `get` command responses are sorted in ascending order by default.
### gRPC Proxy
- Experimental gRPC proxy feature.
### Other
- `recipes` now conform to sessions defined in `clientv3/concurrency`.
- ACI has symlinks to `/usr/local/bin/etcd*`.
### Go
- Compile with [*Go 1.7.4*](https://golang.org/doc/devel/release.html#go1.7).
---

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,741 +0,0 @@
Previous change logs can be found at [CHANGELOG-3.4](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.4.md).
---
## v3.5.23 (TBA)
---
## v3.5.22 (2025-07-22)
### etcd server
- Fix [the compaction pause duration metric is not emitted for every compaction batch](https://github.com/etcd-io/etcd/pull/19771)
- Fix [mvcc: avoid double decrement of watcher gauge on close/cancel race](https://github.com/etcd-io/etcd/pull/20066)
- Fix [Watch on future revision returns old events or notifications](https://github.com/etcd-io/etcd/pull/20290)
- Fix [`--force-new-cluster` can't remove all other members in a corner case](https://github.com/etcd-io/etcd/pull/20339)
- Fix [v2store check (IsMetaStoreOnly) returns wrong result even there is no any auth data](https://github.com/etcd-io/etcd/pull/20357)
- Improve [help message for --quota-backend-bytes](https://github.com/etcd-io/etcd/pull/20380)
### Package `clientv3`
- [Replace `resolver.State.Addresses` with `resolver.State.Endpoint.Addresses`](https://github.com/etcd-io/etcd/pull/19783).
- [Deprecated the Metadata field in the Endpoint struct from the client/v3/naming/endpoints package](https://github.com/etcd-io/etcd/pull/19846).
### Dependencies
- Compile binaries using [go 1.23.11](https://github.com/etcd-io/etcd/pull/20321)
---
## v3.5.21 (2025-03-27)
### Dependencies
- Bump [github.com/golang-jwt/jwt/v4 from 4.5.1 to 4.5.2 to address CVE-2025-30204](https://github.com/etcd-io/etcd/pull/19646).
- Bump [bump golang.org/x/net from v0.36.0 to v0.38.0 to address CVE-2025-22870 and CVE-2025-22872](https://github.com/etcd-io/etcd/pull/19686).
---
## v3.5.20 (2025-03-21)
### etcd server
- Fix [the learner promotion changes not being persisted into v3store (bbolt)](https://github.com/etcd-io/etcd/pull/19563)
- Update [the RLock in Demoted method for read-only access to expiry](https://github.com/etcd-io/etcd/pull/19445)
### etcdctl
- Fix [command `etcdctl member promote` doesn't support json output](https://github.com/etcd-io/etcd/pull/19602)
### etcd grpc-proxy
- Fix [grpcproxy can get stuck in and endless loop causing high CPU usage](https://github.com/etcd-io/etcd/pull/19562)
---
## v3.5.19 (2025-03-05)
### etcd server
- Backport [add learner status check to readyz endpoint](https://github.com/etcd-io/etcd/pull/19280).
- Fix [performance regression due to uncertain compaction sleep interval](https://github.com/etcd-io/etcd/pull/19405).
### `tools/benchmark`
- Backport [add mixed read-write performance evaluation scripts](https://github.com/etcd-io/etcd/pull/19275).
### Dependencies
- Compile binaries using [go 1.23.7](https://github.com/etcd-io/etcd/pull/19528).
- Bump [golang.org/x/crypto to v0.35.0 to address CVE-2025-22869](https://github.com/etcd-io/etcd/pull/19478).
- Bump [golang.org/x/net to v0.36.0 to address CVE-2025-22870](https://github.com/etcd-io/etcd/pull/19530).
---
## v3.5.18 (2025-01-24)
### etcd server
- Avoid deadlock in etcd.Close when stopping during bootstrapping, see https://github.com/etcd-io/etcd/pull/19167 and https://github.com/etcd-io/etcd/pull/19258.
- [Print warning messages if any of the deprecated v2store related flags is set](https://github.com/etcd-io/etcd/pull/18999)
- Fix [missing delete event on watch opened on same revision as compaction request](https://github.com/etcd-io/etcd/pull/19249)
### Package `clientv3`
- Fix [runtime panic that occurs when KeepAlive is called with a Context implemented by an uncomparable type](https://github.com/etcd-io/etcd/pull/18937)
### etcdutl v3
- Add [command `etcdutl check v2store` to offline check whether v2store contains custom content](https://github.com/etcd-io/etcd/pull/19113)
### etcd grpc-proxy
- Add [`tls min/max version to grpc proxy`](https://github.com/etcd-io/etcd/pull/18829) to support setting TLS min and max version.
### Dependencies
- Bump [golang-jwt/jwt to 4.5.1 to address GO-2024-3250](https://github.com/etcd-io/etcd/pull/18899).
- Compile binaries using [go 1.22.11](https://github.com/etcd-io/etcd/pull/19211).
- Bump [golang.org/x/crypto to 0.32.0 to address CVE-2024-45337](https://github.com/etcd-io/etcd/pull/19154).
- Bump [golang.org/x/net to 0.34.0 to address CVE-2024-45338](https://github.com/etcd-io/etcd/pull/19158).
---
## v3.5.17 (2024-11-12)
### etcd server
- Fix [watchserver related goroutine leakage](https://github.com/etcd-io/etcd/pull/18784)
- Fix [risk of a partial write txn being applied](https://github.com/etcd-io/etcd/pull/18799)
- Fix [panicking occurred due to improper error handling during defragmentation](https://github.com/etcd-io/etcd/pull/18842)
- Fix [close temp file(s) in case an error happens during defragmentation](https://github.com/etcd-io/etcd/pull/18854)
### Dependencies
- Compile binaries using [go 1.22.9](https://github.com/etcd-io/etcd/pull/18849).
---
## v3.5.16 (2024-09-10)
### etcd server
- Fix [performance regression issue caused by the `ensureLeadership` in lease renew](https://github.com/etcd-io/etcd/pull/18439).
- [Keep the tombstone during compaction if it happens to be the compaction revision](https://github.com/etcd-io/etcd/pull/18474)
- Add [`etcd --experimental-compaction-sleep-interval`](https://github.com/etcd-io/etcd/pull/18514) flag to control the sleep interval between each compaction batch.
### Dependencies
- Compile binaries using [go 1.22.7](https://github.com/etcd-io/etcd/pull/18550).
- Upgrade [bbolt to v1.3.11](https://github.com/etcd-io/etcd/pull/18489).
---
## v3.5.15 (2024-07-19)
### etcd server
- Fix [add prometheus metric registration for metric `etcd_disk_wal_write_duration_seconds`](https://github.com/etcd-io/etcd/pull/18174).
- Add [Support multiple values for allowed client and peer TLS identities](https://github.com/etcd-io/etcd/pull/18160)
- Fix [noisy logs from simple auth token expiration by reducing log level to debug](https://github.com/etcd-io/etcd/pull/18245)
- [Differentiate the warning message for rejected client and peer connections](https://github.com/etcd-io/etcd/pull/18319)
### Package clientv3
- [Print gRPC metadata in guaranteed order using the official go fmt pkg](https://github.com/etcd-io/etcd/pull/18312).
### Dependencies
- Compile binaries using [go 1.21.12](https://github.com/etcd-io/etcd/pull/18271).
- [Fully address CVE-2023-45288 and fix govulncheck CI check](https://github.com/etcd-io/etcd/pull/18170)
## v3.5.14 (2024-05-29)
### etcd server
- Fix [LeaseTimeToLive returns error if leader changed](https://github.com/etcd-io/etcd/pull/17704).
- Add [metrics `etcd_disk_wal_write_duration_seconds`](https://github.com/etcd-io/etcd/pull/17616).
- Fix [ignore raft messages if member id mismatch](https://github.com/etcd-io/etcd/pull/17813).
- Update [the compaction log when bootstrap](https://github.com/etcd-io/etcd/pull/17830).
- Fix [Revision decreasing after panic during compaction](https://github.com/etcd-io/etcd/pull/17865)
- Add [`etcd --experimental-stop-grpc-service-on-defrag`](https://github.com/etcd-io/etcd/pull/17914) to enable client failover on defrag.
- Add [support for `AllowedCN` and `AllowedHostname` through config file](https://github.com/etcd-io/etcd/pull/18063)
### etcdutl v3
- Add [`--initial-memory-map-size` to `snapshot restore` to avoid memory allocation issues](https://github.com/etcd-io/etcd/pull/17977)
### Package `clientv3`
- Add [requests retry when receiving ErrGPRCNotSupportedForLearner and endpoints > 1](https://github.com/etcd-io/etcd/pull/17641).
- Fix [initialization for mu in client context](https://github.com/etcd-io/etcd/pull/17699).
### Dependencies
- Compile binaries using [go 1.21.10](https://github.com/etcd-io/etcd/pull/17980).
- Upgrade [bbolt to v1.3.10](https://github.com/etcd-io/etcd/pull/17943).
---
## v3.5.13 (2024-03-29)
### etcd server
- Fix leases wrongly revoked by the leader by [ignoring old leader's leases revoking request](https://github.com/etcd-io/etcd/pull/17425).
- Fix [no progress notification being sent for watch that doesn't get any events](https://github.com/etcd-io/etcd/pull/17566).
- Fix [watch event loss after compaction](https://github.com/etcd-io/etcd/pull/17612).
### Package `clientv3`
- Add [client backoff and retry config options](https://github.com/etcd-io/etcd/pull/17363).
- [Ignore SetKeepAlivePeriod errors on OpenBSD](https://github.com/etcd-io/etcd/pull/17387).
- [Support unix/unixs socket in client or peer URLs](https://github.com/etcd-io/etcd/pull/15940)
### gRPC Proxy
- Add [three flags (see below) for grpc-proxy](https://github.com/etcd-io/etcd/pull/17447)
- `--dial-keepalive-time`
- `--dial-keepalive-timeout`
- `--permit-without-stream`
### Dependencies
- Upgrade [bbolt to v1.3.9](https://github.com/etcd-io/etcd/pull/17483).
- Compile binaries using [go 1.21.8](https://github.com/etcd-io/etcd/pull/17537).
- Upgrade [google.golang.org/protobuf to v1.33.0 to address CVE-2024-24786](https://github.com/etcd-io/etcd/pull/17553).
- Upgrade github.com/sirupsen/logrus to v1.9.3 to address [PRISMA-2023-0056](https://github.com/etcd-io/etcd/pull/17482).
### Others
- [Make CGO_ENABLED configurable](https://github.com/etcd-io/etcd/pull/17421).
---
## v3.5.12 (2024-01-31)
### etcd server
- Fix [not validating database consistent index, and panicking on nil backend](https://github.com/etcd-io/etcd/pull/17151)
- Document [`experimental-enable-lease-checkpoint-persist` flag in etcd help](https://github.com/etcd-io/etcd/pull/17190)
- Fix [needlessly flocking snapshot files when deleting](https://github.com/etcd-io/etcd/pull/17206)
- Add [digest for etcd base image](https://github.com/etcd-io/etcd/pull/17205)
- Fix [delete inconsistencies in read buffer](https://github.com/etcd-io/etcd/pull/17230)
- Add [mvcc: print backend database size and size in use in compaction logs](https://github.com/etcd-io/etcd/pull/17291)
### Dependencies
- Compile binaries using [go 1.20.13](https://github.com/etcd-io/etcd/pull/17275)
- Upgrade [golang.org/x/crypto to v0.17+ to address CVE-2023-48795](https://github.com/etcd-io/etcd/pull/17346)
## v3.5.11 (2023-12-07)
### etcd server
- Fix distributed tracing by ensuring `--experimental-distributed-tracing-sampling-rate` configuration option is available to [set tracing sample rate](https://github.com/etcd-io/etcd/pull/16951).
- Fix [url redirects while checking peer urls during new member addition](https://github.com/etcd-io/etcd/pull/16986)
- Add [livez/readyz HTTP endpoints](https://github.com/etcd-io/etcd/pull/17039)
### Dependencies
- Compile binaries using [go 1.20.12](https://github.com/etcd-io/etcd/pull/17077)
- Fix [CVE-2023-47108](https://github.com/advisories/GHSA-8pgv-569h-w5rw) by [bumping go.opentelemetry.io/otel to 1.20.0 and go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to 0.46.0](https://github.com/etcd-io/etcd/pull/16946).
---
## v3.5.10 (2023-10-27)
### etcd server
- Fix [`--socket-reuse-port` and `--socket-reuse-address` not able to be set in configuration file](https://github.com/etcd-io/etcd/pull/16435).
- Fix [corruption check may get a `ErrCompacted` error when server has just been compacted](https://github.com/etcd-io/etcd/pull/16048)
- Improve [Lease put performance for the case that auth is disabled or the user is admin](https://github.com/etcd-io/etcd/pull/16019)
- Improve [Skip getting authInfo from incoming context when auth is disabled](https://github.com/etcd-io/etcd/pull/16241)
- Fix [Hash and HashKV have duplicated RESTful API](https://github.com/etcd-io/etcd/pull/16490)
### etcdutl v3
- Add [optional --bump-revision and --mark-compacted flag to etcdutl snapshot restore operation](https://github.com/etcd-io/etcd/pull/16165).
### etcdctl v3
- Add [optional --bump-revision and --mark-compacted flag to etcdctl snapshot restore operation](https://github.com/etcd-io/etcd/pull/16165).
### etcd grpc-proxy
- Fix [Memberlist results not updated when proxy node down](https://github.com/etcd-io/etcd/pull/15907).
### Package `clientv3`
- Fix [Multiple endpoints with same prefix got mixed up](https://github.com/etcd-io/etcd/pull/15939)
- Fix [Unexpected blocking when barrier waits on a nonexistent key](https://github.com/etcd-io/etcd/pull/16188)
- Fix [Reset auth token when failing to authenticate due to auth being disabled](https://github.com/etcd-io/etcd/pull/16241)
- Fix [panic in etcd validate secure endpoints](https://github.com/etcd-io/etcd/pull/16565)
### Dependencies
- Compile binaries using [go 1.20.10](https://github.com/etcd-io/etcd/pull/16745).
- Upgrade gRPC to 1.58.3 in https://github.com/etcd-io/etcd/pull/16625, https://github.com/etcd-io/etcd/pull/16781 and https://github.com/etcd-io/etcd/pull/16790. Note that gRPC server will reject requests with connection header (refer to https://github.com/grpc/grpc-go/pull/4803).
- Upgrade [bbolt to v1.3.8](https://github.com/etcd-io/etcd/pull/16833)
---
## v3.5.9 (2023-05-11)
### etcd server
- Fix [LeaseTimeToLive API may return keys to clients which have no read permission on the keys](https://github.com/etcd-io/etcd/pull/15815).
### Dependencies
- Compile binaries using [go 1.19.9](https://github.com/etcd-io/etcd/pull/15822).
---
## v3.5.8 (2023-04-13)
### etcd server
- Add [`etcd --tls-min-version --tls-max-version`](https://github.com/etcd-io/etcd/pull/15483) to enable support for TLS 1.3.
- Add [`etcd --listen-client-http-urls`](https://github.com/etcd-io/etcd/pull/15589) flag to support separating http server from grpc one, thus giving full immunity to [watch stream starvation under high read load](https://github.com/etcd-io/etcd/issues/15402).
- Change [http2 frame scheduler to random algorithm](https://github.com/etcd-io/etcd/pull/15452)
- Fix [Watch response traveling back in time when reconnecting member downloads snapshot from the leader](https://github.com/etcd-io/etcd/pull/15515)
- Fix [race when starting both secure & insecure gRPC servers on the same address](https://github.com/etcd-io/etcd/pull/15517)
- Fix [server/auth: disallow creating empty permission ranges](https://github.com/etcd-io/etcd/pull/15619)
- Fix [aligning zap log timestamp resolution to microseconds](https://github.com/etcd-io/etcd/pull/15240). Etcd now uses zap timestamp format: `2006-01-02T15:04:05.999999Z0700` (microsecond instead of milliseconds precision).
- Fix [wsproxy did not print log in JSON format](https://github.com/etcd-io/etcd/pull/15661).
- Fix [CVE-2021-28235](https://nvd.nist.gov/vuln/detail/CVE-2021-28235) by [clearing password after authenticating the user](https://github.com/etcd-io/etcd/pull/15653).
- Fix [etcdserver may panic when parsing a JWT token without username or revision](https://github.com/etcd-io/etcd/pull/15676).
- Fix [Requested watcher progress notifications are not synchronised with stream](https://github.com/etcd-io/etcd/pull/15695).
### Package `netutil`
- Fix [consistently format IPv6 addresses for comparison](https://github.com/etcd-io/etcd/pull/15187).
### Package `clientv3`
- Fix [etcd might send duplicated events to watch clients](https://github.com/etcd-io/etcd/pull/15274).
### Dependencies
- Recommend [Go 1.19+](https://github.com/etcd-io/etcd/pull/15337).
- Compile binaries using [go to 1.19.8](https://github.com/etcd-io/etcd/pull/15651)
- Upgrade [golang.org/x/net to v0.7.0](https://github.com/etcd-io/etcd/pull/15337)
- Upgrade [bbolt to v1.3.7](https://github.com/etcd-io/etcd/pull/15222).
### Docker image
- [Remove nsswitch.conf from docker image](https://github.com/etcd-io/etcd/pull/15161)
- Fix [etcd docker images all tagged with amd64 architecture](https://github.com/etcd-io/etcd/pull/15612)
---
## v3.5.7 (2023-01-20)
### etcd server
- Fix [Remove memberID from data corrupt alarm](https://github.com/etcd-io/etcd/pull/14852).
- Fix [Allow non mutating requests pass through quotaKVServer when NOSPACE](https://github.com/etcd-io/etcd/pull/14884).
- Fix [nil pointer panic for readonly txn due to nil response](https://github.com/etcd-io/etcd/pull/14899).
- Fix [The last record which was partially synced to disk isn't automatically repaired](https://github.com/etcd-io/etcd/pull/15069).
- Fix [etcdserver might promote a non-started learner](https://github.com/etcd-io/etcd/pull/15096).
### Package `clientv3`
- Reverted the fix to [auth invalid token and old revision errors in watch](https://github.com/etcd-io/etcd/pull/14995).
### Dependencies
- Recommend [Go 1.17+](https://github.com/etcd-io/etcd/pull/15019).
- Compile binaries using [Go 1.17.13](https://github.com/etcd-io/etcd/pull/15019)
- Bumped [some dependencies](https://github.com/etcd-io/etcd/pull/15018) to address some HIGH Vulnerabilities.
### Docker image
- Use [distroless base image](https://github.com/etcd-io/etcd/pull/15016) to address critical Vulnerabilities.
- Updated [base image from base-debian11 to static-debian11 and removed dependency on busybox](https://github.com/etcd-io/etcd/pull/15037).
---
## v3.5.6 (2022-11-21)
### etcd server
- Fix [auth invalid token and old revision errors in watch](https://github.com/etcd-io/etcd/pull/14547)
- Fix [avoid closing a watch with ID 0 incorrectly](https://github.com/etcd-io/etcd/pull/14563)
- Fix [auth: fix data consistency issue caused by recovery from snapshot](https://github.com/etcd-io/etcd/pull/14648)
- Fix [revision might be inconsistency between members when etcd crashes during processing defragmentation operation](https://github.com/etcd-io/etcd/pull/14733)
- Fix [timestamp in inconsistent format](https://github.com/etcd-io/etcd/pull/14799)
- Fix [Failed resolving host due to lost DNS record](https://github.com/etcd-io/etcd/pull/14573)
### Package `clientv3`
- Fix [Add backoff before retry when watch stream returns unavailable](https://github.com/etcd-io/etcd/pull/14582).
- Fix [stack overflow error in double barrier](https://github.com/etcd-io/etcd/pull/14658)
- Fix [Refreshing token on CommonName based authentication causes segmentation violation in client](https://github.com/etcd-io/etcd/pull/14790).
### etcd grpc-proxy
- Add [`etcd grpc-proxy start --listen-cipher-suites`](https://github.com/etcd-io/etcd/pull/14500) flag to support adding configurable cipher list.
---
## v3.5.5 (2022-09-15)
### Deprecations
- Deprecated [SetKeepAlive and SetKeepAlivePeriod in limitListenerConn](https://github.com/etcd-io/etcd/pull/14366).
### Package `clientv3`
- Fix [do not overwrite authTokenBundle on dial](https://github.com/etcd-io/etcd/pull/14132).
- Fix [IsOptsWithPrefix returns false even if WithPrefix() is included](https://github.com/etcd-io/etcd/pull/14187).
### etcd server
- [Build official darwin/arm64 artifacts](https://github.com/etcd-io/etcd/pull/14436).
- Add [`etcd --max-concurrent-streams`](https://github.com/etcd-io/etcd/pull/14219) flag to configure the max concurrent streams each client can open at a time, and defaults to math.MaxUint32.
- 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.
- Fix [unexpected error during txn](https://github.com/etcd-io/etcd/issues/14110).
- Fix [lease leak issue due to tokenProvider isn't enabled when restoring auth store from a snapshot](https://github.com/etcd-io/etcd/pull/13205).
- Fix [the race condition between goroutine and channel on the same leases to be revoked](https://github.com/etcd-io/etcd/pull/14087).
- Fix [lessor may continue to schedule checkpoint after stepping down leader role](https://github.com/etcd-io/etcd/pull/14087).
- Fix [Restrict the max size of each WAL entry to the remaining size of the WAL file](https://github.com/etcd-io/etcd/pull/14127).
- Fix [Protect rangePermCache with a RW lock correctly](https://github.com/etcd-io/etcd/pull/14227)
- Fix [memberID equals zero in corruption alarm](https://github.com/etcd-io/etcd/pull/14272)
- Fix [Durability API guarantee broken in single node cluster](https://github.com/etcd-io/etcd/pull/14424)
- Fix [etcd fails to start after performing alarm list operation and then power off/on](https://github.com/etcd-io/etcd/pull/14429)
- Fix [authentication data not loaded on member startup](https://github.com/etcd-io/etcd/pull/14409)
### etcdctl v3
- Fix [etcdctl move-leader may fail for multiple endpoints](https://github.com/etcd-io/etcd/pull/14434)
### Other
- [Bump golang.org/x/crypto to latest version](https://github.com/etcd-io/etcd/pull/13996) to address [CVE-2022-27191](https://github.com/advisories/GHSA-8c26-wmh5-6g9v).
- [Bump OpenTelemetry to 1.0.1 and gRPC to 1.41.0](https://github.com/etcd-io/etcd/pull/14312).
---
## v3.5.4 (2022-04-24)
### etcd server
- Fix [etcd panic on startup (auth enabled)](https://github.com/etcd-io/etcd/pull/13946)
### package `client/pkg/v3`
- [Revert the change of trimming the trailing dot from SRV.Target](https://github.com/etcd-io/etcd/pull/13950) returned by DNS lookup
---
## v3.5.3 (2022-04-13)
### etcd server
- Fix [Provide a better liveness probe for when etcd runs as a Kubernetes pod](https://github.com/etcd-io/etcd/pull/13706)
- Fix [inconsistent log format](https://github.com/etcd-io/etcd/pull/13864)
- Fix [Inconsistent revision and data occurs](https://github.com/etcd-io/etcd/pull/13908)
- Fix [Etcdserver is still in progress of processing LeaseGrantRequest when it receives a LeaseKeepAliveRequest on the same leaseID](https://github.com/etcd-io/etcd/pull/13932)
- Fix [consistent_index coming from snapshot is overwritten by the old local value](https://github.com/etcd-io/etcd/pull/13933)
- [Update container base image snapshot](https://github.com/etcd-io/etcd/pull/13862)
- Fix [Defrag unsets backend options](https://github.com/etcd-io/etcd/pull/13701).
### package `client/pkg/v3`
- [Trim the suffix dot from the target](https://github.com/etcd-io/etcd/pull/13714) in SRV records returned by DNS lookup
### etcdctl v3
- [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13727) when displaying member list in json.
---
## [v3.5.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.2) (2022-02-01)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.1...v3.5.2) and [v3.5 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_5/) for any breaking changes.
### etcd server
- Fix [exclude the same alarm type activated by multiple peers](https://github.com/etcd-io/etcd/pull/13476).
- Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to enable checkpoint persisting.
- Fix [Lease checkpoints don't prevent to reset ttl on leader change](https://github.com/etcd-io/etcd/pull/13508), requires enabling checkpoint persisting.
- Fix [assertion failed due to tx closed when recovering v3 backend from a snapshot db](https://github.com/etcd-io/etcd/pull/13501)
- Fix [segmentation violation(SIGSEGV) error due to premature unlocking of watchableStore](https://github.com/etcd-io/etcd/pull/13541)
---
## [v3.5.1](https://github.com/etcd-io/etcd/releases/tag/v3.5.1) (2021-10-15)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.5.1) and [v3.5 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_5/) for any breaking changes.
### etcd server
- Fix [self-signed-cert-validity parameter cannot be specified in the config file](https://github.com/etcd-io/etcd/pull/13237).
- Fix [ensure that cluster members stored in v2store and backend are in sync](https://github.com/etcd-io/etcd/pull/13348)
### etcd client
- [Fix etcd client sends invalid :authority header](https://github.com/etcd-io/etcd/issues/13192)
### package clientv3
- Endpoints self identify now as `etcd-endpoints://{id}/{authority}` where authority is based on first endpoint passed, for example `etcd-endpoints://0xc0009d8540/localhost:2079`
### Other
- Updated [base image](https://github.com/etcd-io/etcd/pull/13386) from `debian:buster-v1.4.0` to `debian:bullseye-20210927` to fix the following critical CVEs:
- [CVE-2021-3711](https://nvd.nist.gov/vuln/detail/CVE-2021-3711): miscalculation of a buffer size in openssl's SM2 decryption
- [CVE-2021-35942](https://nvd.nist.gov/vuln/detail/CVE-2021-35942): integer overflow flaw in glibc
- [CVE-2019-9893](https://nvd.nist.gov/vuln/detail/CVE-2019-9893): incorrect syscall argument generation in libseccomp
- [CVE-2021-36159](https://nvd.nist.gov/vuln/detail/CVE-2021-36159): libfetch in apk-tools mishandles numeric strings in FTP and HTTP protocols to allow out of bound reads.
---
## v3.5.0 (2021-06)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.4.0...v3.5.0) and [v3.5 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_5/) for any breaking changes.
- [v3.5.0](https://github.com/etcd-io/etcd/releases/tag/v3.5.0) (2021 TBD), see [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0-rc.1...v3.5.0).
- [v3.5.0-rc.1](https://github.com/etcd-io/etcd/releases/tag/v3.5.0-rc.1) (2021-06-10), see [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0-rc.0...v3.5.0-rc.1).
- [v3.5.0-rc.0](https://github.com/etcd-io/etcd/releases/tag/v3.5.0-rc.0) (2021-06-04), see [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0-beta.4...v3.5.0-rc.0).
- [v3.5.0-beta.4](https://github.com/etcd-io/etcd/releases/tag/v3.5.0-beta.4) (2021-05-26), see [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0-beta.3...v3.5.0-beta.4).
- [v3.5.0-beta.3](https://github.com/etcd-io/etcd/releases/tag/v3.5.0-beta.3) (2021-05-18), see [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0-beta.2...v3.5.0-beta.3).
- [v3.5.0-beta.2](https://github.com/etcd-io/etcd/releases/tag/v3.5.0-beta.2) (2021-05-18), see [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0-beta.1...v3.5.0-beta.2).
- [v3.5.0-beta.1](https://github.com/etcd-io/etcd/releases/tag/v3.5.0-beta.1) (2021-05-18), see [code changes](https://github.com/etcd-io/etcd/compare/v3.4.0...v3.5.0-beta.1).
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v3.5 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_3_5/).**
### Breaking Changes
- `go.etcd.io/etcd` Go packages have moved to `go.etcd.io/etcd/{api,pkg,raft,client,etcdctl,server,raft,tests}/v3` to follow the [Go modules](https://github.com/golang/go/wiki/Modules) conventions
- `go.etcd.io/clientv3/snapshot` SnapshotManager class have moved to `go.etcd.io/clientv3/etcdctl`.
The method `snapshot.Save` to download a snapshot from the remote server was preserved in 'go.etcd.io/clientv3/snapshot`.
- `go.etcd.io/client' package got migrated to 'go.etcd.io/client/v2'.
- Changed behavior of clientv3 API [MemberList](https://github.com/etcd-io/etcd/pull/11639).
- Previously, it is directly served with server's local data, which could be stale.
- Now, it is served with linearizable guarantee. If the server is disconnected from quorum, `MemberList` call will fail.
- [gRPC gateway](https://github.com/grpc-ecosystem/grpc-gateway) only supports [`/v3`](TODO) endpoint.
- Deprecated [`/v3beta`](https://github.com/etcd-io/etcd/pull/9298).
- `curl -L http://localhost:2379/v3beta/kv/put -X POST -d '{"key": "Zm9v", "value": "YmFy"}'` doesn't work in v3.5. Use `curl -L http://localhost:2379/v3/kv/put -X POST -d '{"key": "Zm9v", "value": "YmFy"}'` instead.
- **`etcd --experimental-enable-v2v3` flag remains experimental and to be deprecated.**
- v2 storage emulation feature will be deprecated in the next release.
- etcd 3.5 is the last version that supports V2 API. Flags `--enable-v2` and `--experimental-enable-v2v3` [are now deprecated](https://github.com/etcd-io/etcd/pull/12940) and will be removed in etcd v3.6 release.
- **`etcd --experimental-backend-bbolt-freelist-type` flag has been deprecated.** Use **`etcd --backend-bbolt-freelist-type`** instead. The default type is hashmap and it is stable now.
- **`etcd --debug` flag has been deprecated.** Use **`etcd --log-level=debug`** instead.
- Remove [`embed.Config.Debug`](https://github.com/etcd-io/etcd/pull/10947).
- **`etcd --log-output` flag has been deprecated.** Use **`etcd --log-outputs`** instead.
- **`etcd --logger=zap --log-outputs=stderr`** is now the default.
- **`etcd --logger=capnslog` flag value has been deprecated.**
- **`etcd --logger=zap --log-outputs=default` flag value is not supported.**.
- Use `etcd --logger=zap --log-outputs=stderr`.
- Or, use `etcd --logger=zap --log-outputs=systemd/journal` to send logs to the local systemd journal.
- Previously, if etcd parent process ID (PPID) is 1 (e.g. run with systemd), `etcd --logger=capnslog --log-outputs=default` redirects server logs to local systemd journal. And if write to journald fails, it writes to `os.Stderr` as a fallback.
- However, even with PPID 1, it can fail to dial systemd journal (e.g. run embedded etcd with Docker container). Then, [every single log write will fail](https://github.com/etcd-io/etcd/pull/9729) and fall back to `os.Stderr`, which is inefficient.
- To avoid this problem, systemd journal logging must be configured manually.
- **`etcd --log-outputs=stderr`** is now the default.
- **`etcd --log-package-levels` flag for `capnslog` has been deprecated.** Now, **`etcd --logger=zap --log-outputs=stderr`** is the default.
- **`[CLIENT-URL]/config/local/log` endpoint has been deprecated, as is `etcd --log-package-levels` flag.**
- `curl http://127.0.0.1:2379/config/local/log -XPUT -d '{"Level":"DEBUG"}'` won't work.
- Please use `etcd --logger=zap --log-outputs=stderr` instead.
- Deprecated `etcd_debugging_mvcc_db_total_size_in_bytes` Prometheus metric. Use `etcd_mvcc_db_total_size_in_bytes` instead.
- Deprecated `etcd_debugging_mvcc_put_total` Prometheus metric. Use `etcd_mvcc_put_total` instead.
- Deprecated `etcd_debugging_mvcc_delete_total` Prometheus metric. Use `etcd_mvcc_delete_total` instead.
- Deprecated `etcd_debugging_mvcc_txn_total` Prometheus metric. Use `etcd_mvcc_txn_total` instead.
- Deprecated `etcd_debugging_mvcc_range_total` Prometheus metric. Use `etcd_mvcc_range_total` instead.
- Main branch `/version` outputs `3.5.0-pre`, instead of `3.4.0+git`.
- Changed `proxy` package function signature to [support structured logger](https://github.com/etcd-io/etcd/pull/11614).
- Previously, `NewClusterProxy(c *clientv3.Client, advaddr string, prefix string) (pb.ClusterServer, <-chan struct{})`, now `NewClusterProxy(lg *zap.Logger, c *clientv3.Client, advaddr string, prefix string) (pb.ClusterServer, <-chan struct{})`.
- Previously, `Register(c *clientv3.Client, prefix string, addr string, ttl int)`, now `Register(lg *zap.Logger, c *clientv3.Client, prefix string, addr string, ttl int) <-chan struct{}`.
- Previously, `NewHandler(t *http.Transport, urlsFunc GetProxyURLs, failureWait time.Duration, refreshInterval time.Duration) http.Handler`, now `NewHandler(lg *zap.Logger, t *http.Transport, urlsFunc GetProxyURLs, failureWait time.Duration, refreshInterval time.Duration) http.Handler`.
- Changed `pkg/flags` function signature to [support structured logger](https://github.com/etcd-io/etcd/pull/11616).
- Previously, `SetFlagsFromEnv(prefix string, fs *flag.FlagSet) error`, now `SetFlagsFromEnv(lg *zap.Logger, prefix string, fs *flag.FlagSet) error`.
- Previously, `SetPflagsFromEnv(prefix string, fs *pflag.FlagSet) error`, now `SetPflagsFromEnv(lg *zap.Logger, prefix string, fs *pflag.FlagSet) error`.
- ClientV3 supports [grpc resolver API](https://github.com/etcd-io/etcd/blob/main/client/v3/naming/resolver/resolver.go).
- Endpoints can be managed using [endpoints.Manager](https://github.com/etcd-io/etcd/blob/main/client/v3/naming/endpoints/endpoints.go)
- Previously supported [GRPCResolver was decomissioned](https://github.com/etcd-io/etcd/pull/12675). Use [resolver](https://github.com/etcd-io/etcd/blob/main/client/v3/naming/resolver/resolver.go) instead.
- Turned on [--pre-vote by default](https://github.com/etcd-io/etcd/pull/12770). Should prevent disrupting RAFT leader by an individual member.
- [ETCD_CLIENT_DEBUG env](https://github.com/etcd-io/etcd/pull/12786): Now supports log levels (debug, info, warn, error, dpanic, panic, fatal). Only when set, overrides application-wide grpc logging settings.
- [Embed Etcd.Close()](https://github.com/etcd-io/etcd/pull/12828) needs to called exactly once and closes Etcd.Err() stream.
- [Embed Etcd does not override global/grpc logger](https://github.com/etcd-io/etcd/pull/12861) be default any longer. If desired, please call `embed.Config::SetupGlobalLoggers()` explicitly.
- [Embed Etcd custom logger should be configured using simpler builder `NewZapLoggerBuilder`](https://github.com/etcd-io/etcd/pull/12973).
- Client errors of `context cancelled` or `context deadline exceeded` are exposed as `codes.Canceled` and `codes.DeadlineExceeded`, instead of `codes.Unknown`.
### Storage format changes
- [WAL log's snapshots persists raftpb.ConfState](https://github.com/etcd-io/etcd/pull/12735)
- [Backend persists raftpb.ConfState](https://github.com/etcd-io/etcd/pull/12962) in the `meta` bucket `confState` key.
- [Backend persists applied term](https://github.com/etcd-io/etcd/pull/) in the `meta` bucket.
- Backend persists `downgrade` in the `cluster` bucket
### Security
- Add [`TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256` and `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256` to `etcd --cipher-suites`](https://github.com/etcd-io/etcd/pull/11864).
- Changed [the format of WAL entries related to auth for not keeping password as a plain text](https://github.com/etcd-io/etcd/pull/11943).
- Add third party [Security Audit Report](https://github.com/etcd-io/etcd/pull/12201).
- A [log warning](https://github.com/etcd-io/etcd/pull/12242) is added when etcd uses any existing directory that has a permission different than 700 on Linux and 777 on Windows.
- Add optional [`ClientCertFile` and `ClientKeyFile`](https://github.com/etcd-io/etcd/pull/12705) options for peer and client tls configuration when split certificates are used.
### Metrics, Monitoring
See [List of metrics](https://etcd.io/docs/latest/metrics/) for all metrics per release.
Note that any `etcd_debugging_*` metrics are experimental and subject to change.
- Deprecated `etcd_debugging_mvcc_db_total_size_in_bytes` Prometheus metric. Use `etcd_mvcc_db_total_size_in_bytes` instead.
- Deprecated `etcd_debugging_mvcc_put_total` Prometheus metric. Use `etcd_mvcc_put_total` instead.
- Deprecated `etcd_debugging_mvcc_delete_total` Prometheus metric. Use `etcd_mvcc_delete_total` instead.
- Deprecated `etcd_debugging_mvcc_txn_total` Prometheus metric. Use `etcd_mvcc_txn_total` instead.
- Deprecated `etcd_debugging_mvcc_range_total` Prometheus metric. Use `etcd_mvcc_range_total` instead.
- Add [`etcd_debugging_mvcc_current_revision`](https://github.com/etcd-io/etcd/pull/11126) Prometheus metric.
- Add [`etcd_debugging_mvcc_compact_revision`](https://github.com/etcd-io/etcd/pull/11126) Prometheus metric.
- Change [`etcd_cluster_version`](https://github.com/etcd-io/etcd/pull/11254) Prometheus metrics to include only major and minor version.
- Add [`etcd_debugging_mvcc_total_put_size_in_bytes`](https://github.com/etcd-io/etcd/pull/11374) Prometheus metric.
- Add [`etcd_server_client_requests_total` with `"type"` and `"client_api_version"` labels](https://github.com/etcd-io/etcd/pull/11687).
- Add [`etcd_wal_write_bytes_total`](https://github.com/etcd-io/etcd/pull/11738).
- Add [`etcd_debugging_auth_revision`](https://github.com/etcd-io/etcd/commit/f14d2a087f7b0fd6f7980b95b5e0b945109c95f3).
- Add [`os_fd_used` and `os_fd_limit` to monitor current OS file descriptors](https://github.com/etcd-io/etcd/pull/12214).
- Add [`etcd_disk_defrag_inflight`](https://github.com/etcd-io/etcd/pull/13395).
### etcd server
- Add [don't attempt to grant nil permission to a role](https://github.com/etcd-io/etcd/pull/13086).
- Add [don't activate alarms w/missing AlarmType](https://github.com/etcd-io/etcd/pull/13084).
- Add [`TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256` and `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256` to `etcd --cipher-suites`](https://github.com/etcd-io/etcd/pull/11864).
- Automatically [create parent directory if it does not exist](https://github.com/etcd-io/etcd/pull/9626) (fix [issue#9609](https://github.com/etcd-io/etcd/issues/9609)).
- v4.0 will configure `etcd --enable-v2=true --enable-v2v3=/aaa` to enable v2 API server that is backed by **v3 storage**.
- [`etcd --backend-bbolt-freelist-type`] flag is now stable.
- `etcd --experimental-backend-bbolt-freelist-type` has been deprecated.
- Support [downgrade API](https://github.com/etcd-io/etcd/pull/11715).
- Deprecate v2 apply on cluster version. [Use v3 request to set cluster version and recover cluster version from v3 backend](https://github.com/etcd-io/etcd/pull/11427).
- [Use v2 api to update cluster version to support mixed version cluster during upgrade](https://github.com/etcd-io/etcd/pull/12988).
- [Fix corruption bug in defrag](https://github.com/etcd-io/etcd/pull/11613).
- Fix [quorum protection logic when promoting a learner](https://github.com/etcd-io/etcd/pull/11640).
- Improve [peer corruption checker](https://github.com/etcd-io/etcd/pull/11621) to work when peer mTLS is enabled.
- Log [`[CLIENT-PORT]/health` check in server side](https://github.com/etcd-io/etcd/pull/11704).
- Log [successful etcd server-side health check in debug level](https://github.com/etcd-io/etcd/pull/12677).
- Improve [compaction performance when latest index is greater than 1-million](https://github.com/etcd-io/etcd/pull/11734).
- [Refactor consistentindex](https://github.com/etcd-io/etcd/pull/11699).
- [Add log when etcdserver failed to apply command](https://github.com/etcd-io/etcd/pull/11670).
- Improve [count-only range performance](https://github.com/etcd-io/etcd/pull/11771).
- Remove [redundant storage restore operation to shorten the startup time](https://github.com/etcd-io/etcd/pull/11779).
- With 40 million key test data,it can shorten the startup time from 5 min to 2.5 min.
- [Fix deadlock bug in mvcc](https://github.com/etcd-io/etcd/pull/11817).
- Fix [inconsistency between WAL and server snapshot](https://github.com/etcd-io/etcd/pull/11888).
- Previously, server restore fails if it had crashed after persisting raft hard state but before saving snapshot.
- See https://github.com/etcd-io/etcd/issues/10219 for more.
- Add [missing CRC checksum check in WAL validate method otherwise causes panic](https://github.com/etcd-io/etcd/pull/11924).
- See https://github.com/etcd-io/etcd/issues/11918.
- Improve logging around snapshot send and receive.
- [Push down RangeOptions.limit argv into index tree to reduce memory overhead](https://github.com/etcd-io/etcd/pull/11990).
- Add [reason field for /health response](https://github.com/etcd-io/etcd/pull/11983).
- Add [exclude alarms from health check conditionally](https://github.com/etcd-io/etcd/pull/12880).
- Add [`etcd --unsafe-no-fsync`](https://github.com/etcd-io/etcd/pull/11946) flag.
- Setting the flag disables all uses of fsync, which is unsafe and will cause data loss. This flag makes it possible to run an etcd node for testing and development without placing lots of load on the file system.
- Add [`etcd --auth-token-ttl`](https://github.com/etcd-io/etcd/pull/11980) flag to customize `simpleTokenTTL` settings.
- Improve [`runtime.FDUsage` call pattern to reduce objects malloc of Memory Usage and CPU Usage](https://github.com/etcd-io/etcd/pull/11986).
- Improve [mvcc.watchResponse channel Memory Usage](https://github.com/etcd-io/etcd/pull/11987).
- Log [expensive request info in UnaryInterceptor](https://github.com/etcd-io/etcd/pull/12086).
- [Fix invalid Go type in etcdserverpb](https://github.com/etcd-io/etcd/pull/12000).
- [Improve healthcheck by using v3 range request and its corresponding timeout](https://github.com/etcd-io/etcd/pull/12195).
- Add [`etcd --experimental-watch-progress-notify-interval`](https://github.com/etcd-io/etcd/pull/12216) flag to make watch progress notify interval configurable.
- Fix [server panic in slow writes warnings](https://github.com/etcd-io/etcd/issues/12197).
- Fixed via [PR#12238](https://github.com/etcd-io/etcd/pull/12238).
- [Fix server panic](https://github.com/etcd-io/etcd/pull/12288) when force-new-cluster flag is enabled in a cluster which had learner node.
- Add [`etcd --self-signed-cert-validity`](https://github.com/etcd-io/etcd/pull/12429) flag to support setting certificate expiration time.
- Notice, certificates generated by etcd are valid for 1 year by default when specifying the auto-tls or peer-auto-tls option.
- Add [`etcd --experimental-warning-apply-duration`](https://github.com/etcd-io/etcd/pull/12448) flag which allows apply duration threshold to be configurable.
- Add [`etcd --experimental-memory-mlock`](https://github.com/etcd-io/etcd/pull/TODO) flag which prevents etcd memory pages to be swapped out.
- Add [`etcd --socket-reuse-port`](https://github.com/etcd-io/etcd/pull/12702) flag
- Setting this flag enables `SO_REUSEPORT` which allows rebind of a port already in use. User should take caution when using this flag to ensure flock is properly enforced.
- Add [`etcd --socket-reuse-address`](https://github.com/etcd-io/etcd/pull/12702) flag
- Setting this flag enables `SO_REUSEADDR` which allows binding to an address in `TIME_WAIT` state, improving etcd restart time.
- Reduce [around 30% memory allocation by logging range response size without marshal](https://github.com/etcd-io/etcd/pull/12871).
- `ETCD_VERIFY="all"` environment triggers [additional verification of consistency](https://github.com/etcd-io/etcd/pull/12901) of etcd data-dir files.
- Add [`etcd --enable-log-rotation`](https://github.com/etcd-io/etcd/pull/12774) boolean flag which enables log rotation if true.
- Add [`etcd --log-rotation-config-json`](https://github.com/etcd-io/etcd/pull/12774) flag which allows passthrough of JSON config to configure log rotation for a file output target.
- Add experimental distributed tracing boolean flag [`--experimental-enable-distributed-tracing`](https://github.com/etcd-io/etcd/pull/12919) which enables tracing.
- Add [`etcd --experimental-distributed-tracing-address`](https://github.com/etcd-io/etcd/pull/12919) string flag which allows configuring the OpenTelemetry collector address.
- Add [`etcd --experimental-distributed-tracing-service-name`](https://github.com/etcd-io/etcd/pull/12919) string flag which allows changing the default "etcd" service name.
- Add [`etcd --experimental-distributed-tracing-instance-id`](https://github.com/etcd-io/etcd/pull/12919) string flag which configures an instance ID, which must be unique per etcd instance.
- Add [`--experimental-bootstrap-defrag-threshold-megabytes`](https://github.com/etcd-io/etcd/pull/12941) which configures a threshold for the unused db size and etcdserver will automatically perform defragmentation on bootstrap when it exceeds this value. The functionality is disabled if the value is 0.
### Package `runtime`
- Optimize [`runtime.FDUsage` by removing unnecessary sorting](https://github.com/etcd-io/etcd/pull/12214).
### Package `embed`
- Remove [`embed.Config.Debug`](https://github.com/etcd-io/etcd/pull/10947).
- Use `embed.Config.LogLevel` instead.
- Add [`embed.Config.ZapLoggerBuilder`](https://github.com/etcd-io/etcd/pull/11147) to allow creating a custom zap logger.
- Replace [global `*zap.Logger` with etcd server logger object](https://github.com/etcd-io/etcd/pull/12212).
- Add [`embed.Config.EnableLogRotation`](https://github.com/etcd-io/etcd/pull/12774) which enables log rotation if true.
- Add [`embed.Config.LogRotationConfigJSON`](https://github.com/etcd-io/etcd/pull/12774) to allow passthrough of JSON config to configure log rotation for a file output target.
- Add [`embed.Config.ExperimentalEnableDistributedTracing`](https://github.com/etcd-io/etcd/pull/12919) which enables experimental distributed tracing if true.
- Add [`embed.Config.ExperimentalDistributedTracingAddress`](https://github.com/etcd-io/etcd/pull/12919) which allows overriding default collector address.
- Add [`embed.Config.ExperimentalDistributedTracingServiceName`](https://github.com/etcd-io/etcd/pull/12919) which allows overriding default "etcd" service name.
- Add [`embed.Config.ExperimentalDistributedTracingServiceInstanceID`](https://github.com/etcd-io/etcd/pull/12919) which allows configuring an instance ID, which must be uniquer per etcd instance.
### Package `clientv3`
- Remove [excessive watch cancel logging messages](https://github.com/etcd-io/etcd/pull/12187).
- See [kubernetes/kubernetes#93450](https://github.com/kubernetes/kubernetes/issues/93450).
- Add [`TryLock`](https://github.com/etcd-io/etcd/pull/11104) method to `clientv3/concurrency/Mutex`. A non-blocking method on `Mutex` which does not wait to get lock on the Mutex, returns immediately if Mutex is locked by another session.
- Fix [client balancer failover against multiple endpoints](https://github.com/etcd-io/etcd/pull/11184).
- Fix [`"kube-apiserver: failover on multi-member etcd cluster fails certificate check on DNS mismatch"`](https://github.com/kubernetes/kubernetes/issues/83028).
- Fix [IPv6 endpoint parsing in client](https://github.com/etcd-io/etcd/pull/11211).
- Fix ["1.16: etcd client does not parse IPv6 addresses correctly when members are joining" (kubernetes#83550)](https://github.com/kubernetes/kubernetes/issues/83550).
- Fix [errors caused by grpc changing balancer/resolver API](https://github.com/etcd-io/etcd/pull/11564). This change is compatible with grpc >= [v1.26.0](https://github.com/grpc/grpc-go/releases/tag/v1.26.0), but is not compatible with < v1.26.0 version.
- Use [ServerName as the authority](https://github.com/etcd-io/etcd/pull/11574) after bumping to grpc v1.26.0. Remove workaround in [#11184](https://github.com/etcd-io/etcd/pull/11184).
- Fix [`"hasleader"` metadata embedding](https://github.com/etcd-io/etcd/pull/11687).
- Previously, `clientv3.WithRequireLeader(ctx)` was overwriting existing context keys.
- Fix [watch leak caused by lazy cancellation](https://github.com/etcd-io/etcd/pull/11850). When clients cancel their watches, a cancel request will now be immediately sent to the server instead of waiting for the next watch event.
- Make sure [save snapshot downloads checksum for integrity checks](https://github.com/etcd-io/etcd/pull/11896).
- Fix [auth token invalid after watch reconnects](https://github.com/etcd-io/etcd/pull/12264). Get AuthToken automatically when clientConn is ready.
- Improve [clientv3:get AuthToken gracefully without extra connection](https://github.com/etcd-io/etcd/pull/12165).
- Changed [clientv3 dialing code](https://github.com/etcd-io/etcd/pull/12671) to use grpc resolver API instead of custom balancer.
- Endpoints self identify now as `etcd-endpoints://{id}/#initially={list of endpoints}` e.g. `etcd-endpoints://0xc0009d8540/#initially=[localhost:2079]`
- Make sure [save snapshot downloads checksum for integrity checks](https://github.com/etcd-io/etcd/pull/11896).
### Package `lease`
- Fix [memory leak in follower nodes](https://github.com/etcd-io/etcd/pull/11731).
- https://github.com/etcd-io/etcd/issues/11495
- https://github.com/etcd-io/etcd/issues/11730
- Make sure [grant/revoke won't be applied repeatedly after restarting etcd](https://github.com/etcd-io/etcd/pull/11935).
### Package `wal`
- Add [`etcd_wal_write_bytes_total`](https://github.com/etcd-io/etcd/pull/11738).
- Handle [out-of-range slice bound in `ReadAll` and entry limit in `decodeRecord`](https://github.com/etcd-io/etcd/pull/11793).
### etcdctl v3
- Fix `etcdctl member add` command to prevent potential timeout. ([PR#11194](https://github.com/etcd-io/etcd/pull/11194) and [PR#11638](https://github.com/etcd-io/etcd/pull/11638))
- Add [`etcdctl watch --progress-notify`](https://github.com/etcd-io/etcd/pull/11462) flag.
- Add [`etcdctl auth status`](https://github.com/etcd-io/etcd/pull/11536) command to check if authentication is enabled
- Add [`etcdctl get --count-only`](https://github.com/etcd-io/etcd/pull/11743) flag for output type `fields`.
- Add [`etcdctl member list -w=json --hex`](https://github.com/etcd-io/etcd/pull/11812) flag to print memberListResponse in hex format json.
- Changed [`etcdctl lock <lockname> exec-command`](https://github.com/etcd-io/etcd/pull/12829) to return exit code of exec-command.
- [New tool: `etcdutl`](https://github.com/etcd-io/etcd/pull/12971) incorporated functionality of: `etcdctl snapshot status|restore`, `etcdctl backup`, `etcdctl defrag --data-dir ...`.
- [ETCDCTL_API=3 `etcdctl migrate`](https://github.com/etcd-io/etcd/pull/12971) has been decommissioned. Use etcd <=v3.4 to restore v2 storage.
### gRPC gateway
- [gRPC gateway](https://github.com/grpc-ecosystem/grpc-gateway) only supports [`/v3`](TODO) endpoint.
- Deprecated [`/v3beta`](https://github.com/etcd-io/etcd/pull/9298).
- `curl -L http://localhost:2379/v3beta/kv/put -X POST -d '{"key": "Zm9v", "value": "YmFy"}'` does work in v3.5. Use `curl -L http://localhost:2379/v3/kv/put -X POST -d '{"key": "Zm9v", "value": "YmFy"}'` instead.
- Set [`enable-grpc-gateway`](https://github.com/etcd-io/etcd/pull/12297) flag to true when using a config file to keep the defaults the same as the command line configuration.
### gRPC Proxy
- Fix [`panic on error`](https://github.com/etcd-io/etcd/pull/11694) for metrics handler.
- Add [gRPC keepalive related flags](https://github.com/etcd-io/etcd/pull/11711) `grpc-keepalive-min-time`, `grpc-keepalive-interval` and `grpc-keepalive-timeout`.
- [Fix grpc watch proxy hangs when failed to cancel a watcher](https://github.com/etcd-io/etcd/pull/12030) .
- Add [metrics handler for grpcproxy self](https://github.com/etcd-io/etcd/pull/12107).
- Add [health handler for grpcproxy self](https://github.com/etcd-io/etcd/pull/12114).
### Auth
- Fix [NoPassword check when adding user through GRPC gateway](https://github.com/etcd-io/etcd/pull/11418) ([issue#11414](https://github.com/etcd-io/etcd/issues/11414))
- Fix bug where [some auth related messages are logged at wrong level](https://github.com/etcd-io/etcd/pull/11586)
- [Fix a data corruption bug by saving consistent index](https://github.com/etcd-io/etcd/pull/11652).
- [Improve checkPassword performance](https://github.com/etcd-io/etcd/pull/11735).
- [Add authRevision field in AuthStatus](https://github.com/etcd-io/etcd/pull/11659).
- Fix [a bug of not refreshing expired tokens](https://github.com/etcd-io/etcd/pull/13308).
-
### API
- Add [`/v3/auth/status`](https://github.com/etcd-io/etcd/pull/11536) endpoint to check if authentication is enabled
- [Add `Linearizable` field to `etcdserverpb.MemberListRequest`](https://github.com/etcd-io/etcd/pull/11639).
- [Learner support Snapshot RPC](https://github.com/etcd-io/etcd/pull/12890/).
### Package `netutil`
- Remove [`netutil.DropPort/RecoverPort/SetLatency/RemoveLatency`](https://github.com/etcd-io/etcd/pull/12491).
- These are not used anymore. They were only used for older versions of functional testing.
- Removed to adhere to best security practices, minimize arbitrary shell invocation.
### `tools/etcd-dump-metrics`
- Implement [input validation to prevent arbitrary shell invocation](https://github.com/etcd-io/etcd/pull/12491).
### Dependency
- Upgrade [`google.golang.org/grpc`](https://github.com/grpc/grpc-go/releases) from [**`v1.23.0`**](https://github.com/grpc/grpc-go/releases/tag/v1.23.0) to [**`v1.37.0`**](https://github.com/grpc/grpc-go/releases/tag/v1.37.0).
- Upgrade [`go.uber.org/zap`](https://github.com/uber-go/zap/releases) from [**`v1.14.1`**](https://github.com/uber-go/zap/releases/tag/v1.14.1) to [**`v1.16.0`**](https://github.com/uber-go/zap/releases/tag/v1.16.0).
### Platforms
- etcd now [officially supports `arm64`](https://github.com/etcd-io/etcd/pull/12929).
- See https://github.com/etcd-io/etcd/pull/12928 for adding automated tests with `arm64` EC2 instances (Graviton 2).
- See https://github.com/etcd-io/website/pull/273 for new platform support tier policies.
### Release
- Add s390x build support ([PR#11548](https://github.com/etcd-io/etcd/pull/11548) and [PR#11358](https://github.com/etcd-io/etcd/pull/11358))
### Go
- Require [*Go 1.16+*](https://github.com/etcd-io/etcd/pull/11110).
- Compile with [*Go 1.16+*](https://golang.org/doc/devel/release.html#go1.16)
- etcd uses [go modules](https://github.com/etcd-io/etcd/pull/12279) (instead of vendor dir) to track dependencies.
### Project Governance
- The etcd team has added, a well defined and openly discussed, project [governance](https://github.com/etcd-io/etcd/pull/11175).
---

View File

@ -1,267 +0,0 @@
Previous change logs can be found at [CHANGELOG-3.5](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.5.md).
---
## v3.6.5 (TBA)
### etcd server
- [Remove the flag `--experimental-snapshot-catch-up-entries` from `etcd --help` output](https://github.com/etcd-io/etcd/pull/20422)
---
## v3.6.4 (2025-07-25)
### etcd server
- Fix [etcdserver bootstrap failure when replaying learner promotion operation due to not exist in v3store](https://github.com/etcd-io/etcd/pull/20387)
---
## v3.6.3 (2025-07-22)
### etcd server
- Fix [v2store check (IsMetaStoreOnly) returns wrong result even there is no any auth data](https://github.com/etcd-io/etcd/pull/20370)
- Improve [help message for --quota-backend-bytes](https://github.com/etcd-io/etcd/pull/20352)
---
## v3.6.2 (2025-07-09)
### etcd server
- Fix [Watch on future revision returns old events or notifications](https://github.com/etcd-io/etcd/pull/20286)
### Dependencies
- [Bump bbolt to v1.4.2](https://github.com/etcd-io/etcd/pull/20267)
- Compile binaries using [go 1.23.11](https://github.com/etcd-io/etcd/pull/20314).
---
## v3.6.1 (2025-06-06)
### etcd server
- [Replaced the deprecated/removed `UnaryServerInterceptor` and `StreamServerInterceptor` in otelgrpc with `NewServerHandler`](https://github.com/etcd-io/etcd/pull/20043)
- [Add protection on `PromoteMember` and `UpdateRaftAttributes` to prevent panicking](https://github.com/etcd-io/etcd/pull/20051)
- [Fix the issue that `--force-new-cluster` can't remove all other members in a corner case](https://github.com/etcd-io/etcd/pull/20071)
- Fix [mvcc: avoid double decrement of watcher gauge on close/cancel race](https://github.com/etcd-io/etcd/pull/20067)
- [Add validation to ensure there is no empty v3discovery endpoint](https://github.com/etcd-io/etcd/pull/20113)
### etcdctl
- Fix [command `etcdctl endpoint health` doesn't work when options are set via environment variables](https://github.com/etcd-io/etcd/pull/20121)
### Dependencies
- Compile binaries using [go 1.23.10](https://github.com/etcd-io/etcd/pull/20128).
---
## v3.6.0 (2025-05-15)
There isn't any production code change since v3.6.0-rc.5.
---
## v3.6.0-rc.5 (2025-05-08)
### etcd server
- Fix [the compaction pause duration metric is not emitted for every compaction batch](https://github.com/etcd-io/etcd/pull/19770)
### Package `clientv3`
- [Replace `resolver.State.Addresses` with `resolver.State.Endpoint.Addresses`](https://github.com/etcd-io/etcd/pull/19782).
- [Deprecated the Metadata field in the Endpoint struct from the client/v3/naming/endpoints package](https://github.com/etcd-io/etcd/pull/19842).
### Dependencies
- Compile binaries using [go 1.23.9](https://github.com/etcd-io/etcd/pull/19867).
---
## v3.6.0-rc.4 (2025-04-15)
### etcd server
- [Switch to validating v3 when v2 and v3 are synchronized](https://github.com/etcd-io/etcd/pull/19703).
### Dependencies
- Compile binaries using [go 1.23.8](https://github.com/etcd-io/etcd/pull/19724)
---
## v3.6.0-rc.3 (2025-03-27)
### etcd server
- [Auto sync members in v3store for the issues which have already been affected by #19557](https://github.com/etcd-io/etcd/pull/19636).
- [Move `client/internal/v2` into `server/internel/clientv2`](https://github.com/etcd-io/etcd/pull/19673).
- [Replace ExperimentalMaxLearners with a Feature Gate](https://github.com/etcd-io/etcd/pull/19560).
### etcd grpc-proxy
- Fix [grpcproxy can get stuck in and endless loop causing high CPU usage](https://github.com/etcd-io/etcd/pull/19562)
### Dependencies
- Bump [github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 to address CVE-2025-30204](https://github.com/etcd-io/etcd/pull/19647).
- Bump [bump golang.org/x/net from v0.37.0 to v0.38.0 to address CVE-2025-22872](https://github.com/etcd-io/etcd/pull/19687).
---
## v3.6.0-rc.2 (2025-03-05)
### etcd server
- Add [Prometheus metric to query server feature gates](https://github.com/etcd-io/etcd/pull/19495).
### Dependencies
- Compile binaries using [go 1.23.7](https://github.com/etcd-io/etcd/pull/19527).
- Bump [golang.org/x/net to v0.36.0 to address CVE-2025-22870](https://github.com/etcd-io/etcd/pull/19531).
- Bump [github.com/grpc-ecosystem/grpc-gateway/v2 to v2.26.3 to fix the issue of etcdserver crashing on receiving REST watch stream requests](https://github.com/etcd-io/etcd/pull/19522).
---
## v3.6.0-rc.1 (2025-02-25)
### etcdctl v3
- Add [`DowngradeInfo` in result of endpoint status](https://github.com/etcd-io/etcd/pull/19471)
### etcd server
- Add [`DowngradeInfo` to endpoint status response](https://github.com/etcd-io/etcd/pull/19471)
### Dependencies
- Bump [golang.org/x/crypto to v0.35.0 to address CVE-2025-22869](https://github.com/etcd-io/etcd/pull/19480).
---
## v3.6.0-rc.0 (2025-02-13)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0).
### Breaking Changes
- `etcd` will no longer start on data dir created by newer versions (for example etcd v3.6 will not run on v3.7+ data dir). To downgrade data dir please check out `etcdutl migrate` command.
- `etcd` doesn't support serving client requests on the peer listen endpoints (--listen-peer-urls). See [pull/13565](https://github.com/etcd-io/etcd/pull/13565).
- `etcdctl` will sleep(2s) in case of range delete without `--range` flag. See [pull/13747](https://github.com/etcd-io/etcd/pull/13747)
- Applications which depend on etcd v3.6 packages must be built with go version >= v1.18.
#### Flags Removed
- The following flags have been removed:
- `--enable-v2`
- `--experimental-enable-v2v3`
- `--proxy`
- `--proxy-failure-wait`
- `--proxy-refresh-interval`
- `--proxy-dial-timeout`
- `--proxy-write-timeout`
- `--proxy-read-timeout`
### Deprecations
- Deprecated [V2 discovery](https://etcd.io/docs/v3.5/dev-internal/discovery_protocol/).
- Deprecated [SetKeepAlive and SetKeepAlivePeriod in limitListenerConn](https://github.com/etcd-io/etcd/pull/14356).
- Removed [etcdctl defrag --data-dir](https://github.com/etcd-io/etcd/pull/13793).
- Removed [etcdctl snapshot status](https://github.com/etcd-io/etcd/pull/13809).
- Removed [etcdctl snapshot restore](https://github.com/etcd-io/etcd/pull/13809).
- Removed [NewZapCoreLoggerBuilder in server/embed](https://github.com/etcd-io/etcd/pull/19404)
### etcdctl v3
- Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133).
- When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639)
- [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 [`--max-txn-ops`](https://github.com/etcd-io/etcd/pull/14340) flag to make-mirror command.
- Add [`--consistency`](https://github.com/etcd-io/etcd/pull/15261) flag to member list command.
- Display [field `hash_revision`](https://github.com/etcd-io/etcd/pull/14812) for `etcdctl endpoint hash` command.
- Add [`--max-request-bytes` and `--max-recv-bytes`](https://github.com/etcd-io/etcd/pull/18718) global flags.
### etcdutl v3
- Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13142).
- Add `migrate` command for downgrading/upgrading etcd data dir files.
- Add [optional --bump-revision and --mark-compacted flag to etcdutl snapshot restore operation](https://github.com/etcd-io/etcd/pull/16029).
- Add [hashkv](https://github.com/etcd-io/etcd/pull/15965) command to print hash of keys and values up to given revision
- Removed [legacy etcdutl backup](https://github.com/etcd-io/etcd/pull/16662)
- [Count the number of keys from users perspective](https://github.com/etcd-io/etcd/pull/19344)
### Package `clientv3`
- [Support serializable `MemberList` operation](https://github.com/etcd-io/etcd/pull/15261).
### Package `server`
- Package `mvcc` was moved to `storage/mvcc`
- Package `mvcc/backend` was moved to `storage/backend`
- Package `mvcc/buckets` was moved to `storage/schema`
- Package `wal` was moved to `storage/wal`
- Package `datadir` was moved to `storage/datadir`
### Package `raft`
- [Decouple raft from etcd](https://github.com/etcd-io/etcd/issues/14713). Migrated raft to a separate [repository](https://github.com/etcd-io/raft), and renamed raft module to `go.etcd.io/raft/v3`.
### etcd server
- Add [`etcd --log-format`](https://github.com/etcd-io/etcd/pull/13339) flag to support log format.
- Add [`etcd --experimental-max-learners`](https://github.com/etcd-io/etcd/pull/13377) flag to allow configuration of learner max membership.
- Add [`etcd --experimental-enable-lease-checkpoint-persist`](https://github.com/etcd-io/etcd/pull/13508) flag to handle upgrade from v3.5.2 clusters with this feature enabled.
- Add [`etcdctl make-mirror --rev`](https://github.com/etcd-io/etcd/pull/13519) flag to support incremental mirror.
- Add [v3 discovery](https://github.com/etcd-io/etcd/pull/13635) to bootstrap a new etcd cluster.
- Add [field `storage`](https://github.com/etcd-io/etcd/pull/13772) into the response body of endpoint `/version`.
- Add [`etcd --max-concurrent-streams`](https://github.com/etcd-io/etcd/pull/14169) flag to configure the max concurrent streams each client can open at a time, and defaults to math.MaxUint32.
- Add [`etcd grpc-proxy --experimental-enable-grpc-logging`](https://github.com/etcd-io/etcd/pull/14266) flag to logging all grpc requests and responses.
- 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).
- 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).
- Add [`etcd --experimental-snapshot-catch-up-entries`](https://github.com/etcd-io/etcd/pull/15033) flag to configure number of entries for a slow follower to catch up after compacting the raft storage entries and defaults to 5k.
- Decreased [`--snapshot-count` default value from 100,000 to 10,000](https://github.com/etcd-io/etcd/pull/15408)
- Add [`etcd --tls-min-version --tls-max-version`](https://github.com/etcd-io/etcd/pull/15156) to enable support for TLS 1.3.
- Add [quota to endpoint status response](https://github.com/etcd-io/etcd/pull/17877)
- Add [feature gate `SetMemberLocalAddr`](https://github.com/etcd-io/etcd/pull/19413) to [enable using the first specified and non-loopback local address from initial-advertise-peer-urls as the local address when communicating with a peer]((https://github.com/etcd-io/etcd/pull/17661))
- Add [Support multiple values for allowed client and peer TLS identities](https://github.com/etcd-io/etcd/pull/18015)
- Add [`embed.Config.GRPCAdditionalServerOptions`](https://github.com/etcd-io/etcd/pull/14066) to support updating the default internal gRPC configuration for embedded use cases.
### etcd grpc-proxy
- Add [`etcd grpc-proxy start --endpoints-auto-sync-interval`](https://github.com/etcd-io/etcd/pull/14354) flag to enable and configure interval of auto sync of endpoints with server.
- Add [`etcd grpc-proxy start --listen-cipher-suites`](https://github.com/etcd-io/etcd/pull/14308) flag to support adding configurable cipher list.
- Add [`tls min/max version to grpc proxy`](https://github.com/etcd-io/etcd/pull/18816) to support setting TLS min and max version.
### tools/benchmark
- [Add etcd client autoSync flag](https://github.com/etcd-io/etcd/pull/13416)
### Metrics, Monitoring
See [List of metrics](https://etcd.io/docs/latest/metrics/) for all metrics per release.
- Add [`etcd_disk_defrag_inflight`](https://github.com/etcd-io/etcd/pull/13371).
- Add [`etcd_debugging_server_alarms`](https://github.com/etcd-io/etcd/pull/14276).
- Add [`etcd_server_range_duration_seconds`](https://github.com/etcd-io/etcd/pull/17983).
### Go
- Require [Go 1.23+](https://github.com/etcd-io/etcd/pull/16594).
- Compile with [Go 1.23+](https://go.dev/doc/devel/release#go1.21.minor). Please refer to [gc-guide](https://go.dev/doc/gc-guide) to configure `GOGC` and `GOMEMLIMIT` properly.
### Other
- Use Distroless as base image to make the image less vulnerable and reduce image size.
- [Upgrade grpc-gateway from v1 to v2](https://github.com/etcd-io/etcd/pull/16595).
- [Switch from grpc-ecosystem/go-grpc-prometheus to grpc-ecosystem/go-grpc-middleware/providers/prometheus](https://github.com/etcd-io/etcd/pull/19195).
---

View File

@ -1,30 +0,0 @@
Previous change logs can be found at [CHANGELOG-3.6](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.6.md).
---
## v3.7.0 (TBD)
### Breaking Changes
- [Removed all deprecated experimental flags](https://github.com/etcd-io/etcd/pull/19959)
- [Removed v2discovery](https://github.com/etcd-io/etcd/pull/20109)
- [Removed client/v2](https://github.com/etcd-io/etcd/pull/20117)
### etcd server
- [Update go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc to v0.61.0 and replaced the deprecated `UnaryServerInterceptor` and `StreamServerInterceptor` with `NewServerHandler`](https://github.com/etcd-io/etcd/pull/20017)
- [Add Support for Unix Socket endpoints](https://github.com/etcd-io/etcd/pull/19760)
### Package `pkg`
- [Optimize find performance by splitting intervals with the same left endpoint by their right endpoints](https://github.com/etcd-io/etcd/pull/19768)
- [netutil: Refactor IPv6 address comparison logic](https://github.com/etcd-io/etcd/pull/20365)
### Dependencies
- Compile binaries using [go 1.24.5](https://github.com/etcd-io/etcd/pull/20320)
### Deprecations
- Deprecated [UsageFunc in pkg/cobrautl](https://github.com/etcd-io/etcd/pull/18356).

View File

@ -1,44 +0,0 @@
Previous change logs can be found at [CHANGELOG-3.x](https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.x.md).
---
## v4.0.0 (TBD)
See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v4.0.0) and [v4.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_4_0/) for any breaking changes.
**Again, before running upgrades from any previous release, please make sure to read change logs below and [v4.0 upgrade guide](https://etcd.io/docs/latest/upgrades/upgrade_4_0/).**
### Breaking Changes
- [Secure etcd by default](https://github.com/etcd-io/etcd/issues/9475)?
- Deprecate [`etcd --proxy*`](TODO) flags; **no more v2 proxy**.
- Deprecate [v2 storage backend](https://github.com/etcd-io/etcd/issues/9232); **no more v2 store**.
- v2 API is still supported via [v2 emulation](TODO).
- Deprecate [`etcdctl backup`](TODO) command.
- `clientv3.Client.KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error)` is now [`clientv4.Client.KeepAlive(ctx context.Context, id LeaseID) <-chan *LeaseKeepAliveResponse`](TODO).
- Similar to `Watch`, [`KeepAlive` does not return errors](https://github.com/etcd-io/etcd/issues/7488).
- If there's an unknown server error, kill all open channels and create a new stream on the next `KeepAlive` call.
- Rename `github.com/coreos/client` to `github.com/coreos/clientv2`.
- [`etcd --experimental-initial-corrupt-check`](TODO) has been deprecated.
- Use [`etcd --initial-corrupt-check`](TODO) instead.
- [`etcd --experimental-corrupt-check-time`](TODO) has been deprecated.
- Use [`etcd --corrupt-check-time`](TODO) instead.
- Enable TLS 1.13, deprecate TLS cipher suites.
### etcd server
- [`etcd --initial-corrupt-check`](TODO) flag is now stable (`etcd --experimental-initial-corrupt-check` has been deprecated).
- `etcd --initial-corrupt-check=true` by default, to check cluster database hashes before serving client/peer traffic.
- [`etcd --corrupt-check-time`](TODO) flag is now stable (`etcd --experimental-corrupt-check-time` has been deprecated).
- `etcd --corrupt-check-time=12h` by default, to check cluster database hashes for every 12-hour.
- Enable TLS 1.13, deprecate TLS cipher suites.
### Go
- Require [*Go 2*](https://blog.golang.org/go2draft).
---

View File

@ -1,21 +0,0 @@
# Change logs
## Production recommendation
The minimum recommended etcd versions to run in **production** are v3.4.22+ and v3.5.6+. Refer to the [versioning policy](https://etcd.io/docs/v3.5/op-guide/versioning/) for more details.
### v3.5 data corruption issue
Running etcd v3.5.2, v3.5.1 and v3.5.0 under high load can cause a data corruption issue.
If etcd process is killed, occasionally some committed transactions are not reflected on all the members.
Recommendation is to upgrade to v3.5.4+.
If you have encountered data corruption, please follow instructions on https://etcd.io/docs/v3.5/op-guide/data_corruption/.
## Change log rules
1. Each patch release only includes changes against previous patch release.
For example, the change log of v3.5.5 should only include items which are new to v3.5.4.
2. For the first release (e.g. 3.4.0, 3.5.0, 3.6.0, 4.0.0 etc.) for each minor or major
version, it only includes changes which are new to the first release of previous minor
or major version. For example, v3.5.0 should only include items which are new to v3.4.0,
and v3.6.0 should only include items which are new to v3.5.0.

View File

@ -1,5 +1,5 @@
ARG ARCH=amd64 ARG ARCH=amd64
FROM --platform=linux/${ARCH} gcr.io/distroless/static-debian12@sha256:b7b9a6953e7bed6baaf37329331051d7bdc1b99c885f6dbeb72d75b1baad54f9 FROM --platform=linux/${ARCH} gcr.io/distroless/static-debian12@sha256:3f2b64ef97bd285e36132c684e6b2ae8f2723293d09aae046196cca64251acac
ADD etcd /usr/local/bin/ ADD etcd /usr/local/bin/
ADD etcdctl /usr/local/bin/ ADD etcdctl /usr/local/bin/

View File

@ -1,191 +0,0 @@
# Bump etcd Version in Kubernetes
This guide will walk through the update of etcd in Kubernetes to a new version (`kubernetes/kubernetes` repository).
> Currently we bump etcd v3.5.x for K8s release-1.33 and lower versions, and we bump etcd v3.6.x for K8s release-1.34 and higher versions.
You can use this [issue](https://github.com/kubernetes/kubernetes/issues/131101) as a reference when updating the etcd version in Kubernetes.
Bumping the etcd version in Kubernetes consists of two steps.
* Bump etcd client SDK
* Bump etcd image
> The commented lines in this document signifies the line to be changed
## Bump etcd client SDK
> Reference: [link](https://github.com/kubernetes/kubernetes/pull/131103)
You can refer to the guide [here](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/vendor.md) under the **Adding or updating a dependency** section.
1. Get all the etcd modules used in Kubernetes.
```bash
$ grep 'go.etcd.io/etcd/' go.mod | awk '{print $1}'
go.etcd.io/etcd/api/v3
go.etcd.io/etcd/client/pkg/v3
go.etcd.io/etcd/client/v3
go.etcd.io/etcd/client/v2
go.etcd.io/etcd/pkg/v3
go.etcd.io/etcd/raft/v3
go.etcd.io/etcd/server/v3
```
2. For each module, in the root directory of the `kubernetes/kubernetes` repository, fetch the new version in `go.mod` using the following command (using `client/v3` as an example):
```bash
hack/pin-dependency.sh go.etcd.io/etcd/client/v3 NEW_VERSION
```
3. Rebuild the `vendor` directory and update the `go.mod` files for all staging repositories using the command below. This automatically updates the licenses.
```bash
hack/update-vendor.sh
```
4. Check if the new dependency requires newer versions of existing dependencies we have pinned. You can check this by:
* Running `hack/lint-dependencies.sh` against your branch and against `master` and comparing the results.
* Checking if any new `replace` directives were added to `go.mod` files of components inside the staging directory.
## Bump etcd image
### Build etcd image
> Reference: [link 1](https://github.com/kubernetes/kubernetes/pull/131105) [link 2](https://github.com/kubernetes/kubernetes/pull/131126)
1. In `build/dependencies.yaml`, update the `version` of `etcd-image` to the new version. Update `golang: etcd release version` if necessary.
```yaml
- name: "etcd-image"
# version: 3.5.17
version: 3.5.21
refPaths:
- path: cluster/images/etcd/Makefile
match: BUNDLED_ETCD_VERSIONS\?|
---
- name: "golang: etcd release version"
# version: 1.22.9
version: 1.23.7 # https://github.com/etcd-io/etcd/blob/main/CHANGELOG/CHANGELOG-3.6.md
```
2. In `cluster/images/etcd/Makefile`, include the new version in `BUNDLED_ETCD_VERSIONS` and update the `LATEST_ETCD_VERSION` as well (the image tag will be generated from the `LATEST_ETCD_VERSION`). Update `GOLANG_VERSION` according to the version used to compile that release version (`"golang: etcd release version"` in step 1).
```Makefile
# BUNDLED_ETCD_VERSIONS?=3.4.18 3.5.17
BUNDLED_ETCD_VERSIONS?=3.4.18 3.5.21
# LATEST_ETCD_VERSION?=3.5.17
LATEST_ETCD_VERSION?=3.5.21
# GOLANG_VERSION := 1.22.9
GOLANG_VERSION := 1.23.7
```
3. In `cluster/images/etcd/migrate/options.go`, include the new version in the `supportedEtcdVersions` slice.
```go
var (
// supportedEtcdVersions = []string{"3.4.18", "3.5.17"}
supportedEtcdVersions = []string{"3.4.18", "3.5.21"}
)
```
### Publish etcd image
> Reference: [link](https://github.com/kubernetes/k8s.io/pull/7957)
1. When the previous step is merged, a post-commit job will run to build the image. You can find the newly built image in the [registry](https://gcr.io/k8s-staging-etcd/etcd).
2. Locate the newly built image and copy its SHA256 digest.
3. Inside the `kubernetes/k8s.io` repository, in `registry.k8s.io/images/k8s-staging-etcd/images.yaml`, create a new entry for the desired version and copy the SHA256 digest.
```yaml
"sha256:b4a9e4a7e1cf08844c7c4db6a19cab380fbf0aad702b8c01e578e9543671b9f9": ["3.5.17-0"]
# ADD:
"sha256:d58c035df557080a27387d687092e3fc2b64c6d0e3162dc51453a115f847d121": ["3.5.21-0"]
```
### Update to use the new etcd image
> Reference: [link](https://github.com/kubernetes/kubernetes/pull/131144)
1. In `build/dependencies.yaml`, change the `version` of `etcd` to the new version.
```yaml
# etcd
- name: "etcd"
# version: 3.5.17
version: 3.5.21
refPaths:
- path: cluster/gce/manifests/etcd.manifest
match: etcd_docker_tag|etcd_version
```
2. In `cluster/gce/manifests/etcd.manifest`, change the image tag to the new image tag and `TARGET_VERSION` to the new version.
```manifest
// "image": "{{ pillar.get('etcd_docker_repository', 'registry.k8s.io/etcd') }}:{{ pillar.get('etcd_docker_tag', '3.5.17-0') }}",
"image": "{{ pillar.get('etcd_docker_repository', 'registry.k8s.io/etcd') }}:{{ pillar.get('etcd_docker_tag', '3.5.21-0') }}",
---
{ "name": "TARGET_VERSION",
// "value": "{{ pillar.get('etcd_version', '3.5.17') }}"
"value": "{{ pillar.get('etcd_version', '3.5.21') }}"
},
```
3. In `cluster/gce/upgrade-aliases.sh`, update the exports for `ETCD_IMAGE` to the new image tag and `ETCD_VERSION` to the new version.
```sh
# export ETCD_IMAGE=3.5.17-0
export ETCD_IMAGE=3.5.21-0
# export ETCD_VERSION=3.5.17
export ETCD_VERSION=3.5.21
```
4. In `cmd/kubeadm/app/constants/constants.go`, change the `DefaultEtcdVersion` to the new version. In the same file, update `SupportedEtcdVersion` accordingly.
```go
// DefaultEtcdVersion = "3.5.17-0"
DefaultEtcdVersion = "3.5.21-0"
---
SupportedEtcdVersion = map[uint8]string{
// 30: "3.5.17-0",
// 31: "3.5.17-0",
// 32: "3.5.17-0",
// 33: "3.5.17-0",
30: "3.5.21-0",
31: "3.5.21-0",
32: "3.5.21-0",
33: "3.5.21-0",
}
```
5. In `hack/lib/etcd.sh`, update the `ETCD_VERSION`.
```sh
# ETCD_VERSION=${ETCD_VERSION:-3.5.17}
ETCD_VERSION=${ETCD_VERSION:-3.5.21}
```
6. In `staging/src/k8s.io/sample-apiserver/artifacts/example/deployment.yaml`, update the etcd image used.
```yaml
- name: etcd
# image: gcr.io/etcd-development/etcd:v3.5.17
image: gcr.io/etcd-development/etcd:v3.5.21
```
7. In `test/utils/image/manifest.go`, update the etcd image tag.
```go
// configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.17-0"}
configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.21-0"}
```

View File

@ -147,11 +147,11 @@ References:
[bbolt](https://github.com/etcd-io/bbolt) and [raft](https://github.com/etcd-io/raft) are two core dependencies of etcd. [bbolt](https://github.com/etcd-io/bbolt) and [raft](https://github.com/etcd-io/raft) are two core dependencies of etcd.
Both etcd 3.4.x and 3.5.x depend on bbolt 1.3.x, and etcd 3.6.x depends on bbolt 1.4.x. Both etcd 3.4.x and 3.5.x depend on bbolt 1.3.x, and etcd 3.6.x (`main` branch) depends on bbolt 1.4.x.
raft is included in the etcd repository for release-3.4 and release-3.5 branches, so etcd 3.4.x and 3.5.x do not depend on any raft is included in the etcd repository for release-3.4 and release-3.5 branches, so etcd 3.4.x and 3.5.x do not depend on any
external raft module. We moved raft into [a separate repository](https://github.com/etcd-io/raft) starting from 3.6, and the first raft external raft module. We moved raft into [a separate repository](https://github.com/etcd-io/raft) starting from 3.6 (`main` branch), and the first raft
release is v3.6.0, so etcd 3.6.0 depends on raft v3.6.0. release will be v3.6.0, so etcd 3.6.x will depend on raft 3.6.x.
Please see the table below: Please see the table below:

View File

@ -4,84 +4,80 @@ This document provides an overview of etcd features and general development guid
## Overview ## Overview
The etcd features fall into three stages: Alpha, Beta, and GA. The etcd features fall into three stages, experimental, stable, and unsafe.
### Alpha ### Experimental
Any new feature is usually added as an Alpha feature. An Alpha feature is characterized as below: Any new feature is usually added as an experimental feature. An experimental feature is characterized as below:
- Might be buggy due to a lack of user testing. Enabling the feature may not work as expected. - Might be buggy due to a lack of user testing. Enabling the feature may not work as expected.
- Disabled by default. - Disabled by default when added initially.
- Support for such a feature may be dropped at any time without notice - Support for such a feature may be dropped at any time without notice
- Feature-related issues may be given lower priorities. - Feature-related issues may be given lower priorities.
- It can be removed in the next minor or major release without following the feature deprecation policy unless it graduates to a more stable stage. - It can be removed in the next minor or major release without following the feature deprecation policy unless it graduates to a stable future.
### Beta ### Stable
A Beta feature is characterized as below: A stable feature is characterized as below:
- Supported as part of the supported releases of etcd. - Supported as part of the supported releases of etcd.
- Enabled by default. - May be enabled by default.
- Discontinuation of support must follow the feature deprecation policy. - Discontinuation of support must follow the feature deprecation policy.
### GA ### Unsafe
A GA feature is characterized as below: Unsafe features are rare and listed under the `Unsafe feature:` section in the etcd usage documentation. By default, they are disabled. They should be used with caution following documentation. An unsafe feature can be removed in the next minor or major release without following the feature deprecation policy.
- Supported as part of the supported releases of etcd.
- Always enabled; you cannot disable it. The corresponding feature gate is no longer needed.
- Discontinuation of support must follow the feature deprecation policy.
## Development Guidelines ## Development Guidelines
### Adding a new feature ### Adding a new feature
Any new enhancements to the etcd are typically added as an Alpha feature. Any new enhancements to the etcd are typically added as an experimental feature. The general development requirements are listed below. They can be somewhat flexible depending on the scope of the feature and review discussions and will evolve over time.
- Open an issue
etcd follows the Kubernetes [KEP process](https://github.com/kubernetes/enhancements/blob/master/keps/sig-architecture/0000-kep-process/README.md) for new enhancements. The general development requirements are listed below. They can be somewhat flexible depending on the scope of the feature and review discussions and will evolve over time.
- Open a [KEP](https://github.com/kubernetes/enhancements/issues) issue
- It must provide a clear need for the proposed feature. - It must provide a clear need for the proposed feature.
- It should list development work items as checkboxes. There must be one work item towards future graduation to Beta. - It should list development work items as checkboxes. There must be one work item towards future graduation to a stable future.
- Label the issue with `/sig etcd`. - Label the issue with `type/feature` and `experimental`.
- Keep the issue open for tracking purposes until a decision is made on graduation. - Keep the issue open for tracking purposes until a decision is made on graduation.
- Open a [KEP](https://github.com/kubernetes/enhancements) Pull Request (PR). - Open a Pull Request (PR)
- The KEP template can be simplified for etcd.
- It must provide clear graduation criteria for each stage.
- The KEP doc should reside in [keps/sig-etcd](https://github.com/kubernetes/enhancements/tree/master/keps/sig-etcd/)
- Open Pull Requests (PRs) in [etcd](https://github.com/etcd-io/etcd)
- Provide unit tests. Integration tests are also recommended as possible. - Provide unit tests. Integration tests are also recommended as possible.
- Provide robust e2e test coverage. If the feature being added is complicated or quickly needed, maintainers can decide to go with e2e tests for basic coverage initially and have robust coverage added at a later time before the feature graduation to the stable feature. - Provide robust e2e test coverage. If the feature being added is complicated or quickly needed, maintainers can decide to go with e2e tests for basic coverage initially and have robust coverage added at a later time before the feature graduation to the stable feature.
- Provide logs for proper debugging. - Provide logs for proper debugging.
- Provide metrics and benchmarks as needed. - Provide metrics and benchmarks as needed.
- Add an Alpha [feature gate](https://etcd.io/docs/v3.6/feature-gates/). - The Feature should be disabled by default.
- Any code changes or configuration flags related to the implementation of the feature must be gated with the feature gate e.g. `if cfg.ServerFeatureGate.Enabled(features.FeatureName)`. - Any configuration flags related to the implementation of the feature must be prefixed with `experimental` e.g. `--experimental-feature-name`.
- Add a CHANGELOG entry. - Add a CHANGELOG entry.
- At least two maintainers must approve the KEP and related code changes. - At least two maintainers must approve feature requirements and related code changes.
### Graduating a feature to the next stage ### Graduating an Experimental feature to Stable
It is important that features don't get stuck in one stage. They should be revisited and moved to the next stage once they meet the graduation criteria listed in the KEP. A feature should stay at one stage for at least one release before being promoted. It is important that experimental features don't get stuck in that stage. They should be revisited and moved to the stable stage following the graduation steps as described here.
#### Locate graduation candidate
Decide if an experimental feature is ready for graduation to the stable stage.
- Find the issue that was used to enable the experimental feature initially. One way to find such issues is to search for issues with `type/feature` and `experimental` labels.
- Fix any known open issues against the feature.
- Make sure the feature was enabled for at least one previous release. Check the PR(s) reference from the issue to see when the feature-related code changes were merged.
#### Provide implementation #### Provide implementation
If an experimental feature is found ready for graduation to the stable stage, open a Pull Request (PR) with the following changes.
If a feature is found ready for graduation to the next stage, open a Pull Request (PR) with the following changes. - Add robust e2e tests if not already provided.
- Update the feature `PreRelease` stage in `server/features/etcd_features.go`. - Add a new stable feature flag identical to the experimental feature flag but without the `--experimental` prefix.
- Update the status in the original KEP issue. - Deprecate the experimental feature following the [feature deprecation policy](#Deprecating-a-feature).
- Implementation must ensure that both the graduated and deprecated experimental feature flags work as expected. Note that both these flags will co-exist for the timeframe described in the feature deprecation policy.
- Enable the graduated feature by default if needed.
At least two maintainers must approve the work. Patch releases should not be considered for graduation. At least two maintainers must approve the work. Patch releases should not be considered for graduation.
### Deprecating a feature ### Deprecating a feature
#### Alpha #### Experimental
Alpha features can be removed without going through the deprecation process. An experimental feature deprecates when it graduates to the stable stage.
- Remove the feature gate in `server/features/etcd_features.go`, and clean up all relevant code. - Add a deprecation message in the documentation of the experimental feature with a recommendation to use a related stable feature. e.g. `DEPRECATED. Use <feature-name> instead.`
- Close the original KEP issue with reasons to drop the feature. - Add a `deprecated` label in the issue that was initially used to enable the experimental feature.
#### Beta and GA #### Stable
As the project evolves, a Beta/GA feature may sometimes need to be deprecated and removed. Such a situation should be handled using the steps below: As the project evolves, a stable feature may sometimes need to be deprecated and removed. Such a situation should be handled using the steps below:
- Create an issue for tracking purposes.
- Add a deprecation message in the feature usage documentation before a planned release for feature deprecation. e.g. `To be deprecated in <release>.`. If a new feature replaces the `To be deprecated` feature, then also provide a message saying so. e.g. `Use <feature-name> instead.`.
- Deprecate the feature in the planned release with a message as part of the feature usage documentation. e.g. `DEPRECATED`. If a new feature replaces the deprecated feature, then also provide a message saying so. e.g. `DEPRECATED. Use <feature-name> instead.`.
- Add a `deprecated` label in the related issue.
- A Beta/GA feature can only be deprecated after at least 2 minor or major releases. Remove the deprecated feature in the following release. Close any related issue(s). At least two maintainers must approve the work. Patch releases should not be considered for deprecation.
- Update original KEP issue if it has not been closed or create a new etcd issue with reasons and steps to deprecate the feature.
- Add the feature deprecation documentation in the release notes and feature gates documentation of the next minor/major release.
- In the next minor/major release, set the feature gate to `{Default: false, PreRelease: featuregate.Deprecated, LockedToDefault: false}` in `server/features/etcd_features.go`. Deprecated feature gates must respond with a warning when used.
- If the feature has GAed, and the original gated codes has been cleaned up, add the disablement codes back with the feature gate.
- In the minor/major release after the next, set the feature gate to `{Default: false, PreRelease: featuregate.Deprecated, LockedToDefault: true}` in `server/features/etcd_features.go`, and start cleaning the code.
At least two maintainers must approve the work. Patch releases should not be considered for deprecation.

View File

@ -6,17 +6,15 @@ The procedure includes some manual steps for sanity checking, but it can probabl
## Release management ## Release management
Under the leadership of **James Blair** [@jmhbnz](https://github.com/jmhbnz) and **Ivan Valdes Castillo** [@ivanvc](https://github.com/ivanvc), the following pool of release candidates manages the release of each etcd major/minor version as well as manages patches The following pool of release candidates manages the release of each etcd major/minor version as well as manages patches
to each stable release branch. They are responsible for communicating the timelines and status of each release and to each stable release branch. They are responsible for communicating the timelines and status of each release and
for ensuring the stability of the release branch. for ensuring the stability of the release branch.
- Benjamin Wang [@ahrtr](https://github.com/ahrtr) - Benjamin Wang [@ahrtr](https://github.com/ahrtr)
- Fu Wei [@fuweid](https://github.com/fuweid)
- James Blair [@jmhbnz](https://github.com/jmhbnz) - James Blair [@jmhbnz](https://github.com/jmhbnz)
- Ivan Valdes Castillo [@ivanvc](https://github.com/ivanvc)
- Marek Siarkowicz [@serathius](https://github.com/serathius) - Marek Siarkowicz [@serathius](https://github.com/serathius)
- Sahdev Zala [@spzala](https://github.com/spzala) - Sahdev Zala [@spzala](https://github.com/spzala)
- Siyuan Zhang [@siyuanfoundation](https://github.com/siyuanfoundation) - Wenjia Zhang [@wenjiaswe](https://github.com/wenjiaswe)
All release version numbers follow the format of [semantic versioning 2.0.0](http://semver.org/). All release version numbers follow the format of [semantic versioning 2.0.0](http://semver.org/).
@ -70,14 +68,10 @@ which don't need to be executed before releasing each version.
### Release steps ### Release steps
At least one day before the release:
1. Raise an issue to publish the release plan, e.g. [issues/17350](https://github.com/etcd-io/etcd/issues/17350). 1. Raise an issue to publish the release plan, e.g. [issues/17350](https://github.com/etcd-io/etcd/issues/17350).
2. Raise a `kubernetes/org` pull request ([example PR](https://github.com/kubernetes/org/pull/5582)) to ensure members of the release team are added to the [release github team](https://github.com/orgs/etcd-io/teams/release-etcd). 2. Raise a `kubernetes/org` pull request to temporarily elevate permissions for the GitHub release team.
3. Once permissions are elevated, temporarily relax [branch protections](https://github.com/etcd-io/etcd/settings/branches) to allow pushing changes directly to `release-*` branches in GitHub.
On the day of the release: 4. Verify you can pass the authentication to the image registries,
1. Verify you can pass the authentication to the image registries,
- `docker login gcr.io` - `docker login gcr.io`
- `docker login quay.io` - `docker login quay.io`
- If the release person doesn't have access to 1password, one of the owners (@ahrtr, @ivanvc, @jmhbnz, @serathius) needs to share the password with them per [this guide](https://support.1password.com/share-items/). See rough steps below, - If the release person doesn't have access to 1password, one of the owners (@ahrtr, @ivanvc, @jmhbnz, @serathius) needs to share the password with them per [this guide](https://support.1password.com/share-items/). See rough steps below,
@ -86,52 +80,45 @@ On the day of the release:
- Select `Password of quay.io`. - Select `Password of quay.io`.
- Click `Share` on the top right, and set expiration as `1 hour` and only available to the release person using his/her email. - Click `Share` on the top right, and set expiration as `1 hour` and only available to the release person using his/her email.
- Click `Copy Link` then send the link to the release person via slack or email. - Click `Copy Link` then send the link to the release person via slack or email.
2. Clone the etcd repository and checkout the target branch, 5. Clone the etcd repository and checkout the target branch,
- `git clone --branch release-3.X git@github.com:etcd-io/etcd.git` - `git clone --branch release-3.X git@github.com:etcd-io/etcd.git`
3. Run the release script under the repository's root directory, replacing `${VERSION}` with a value without the `v` prefix, i.e. `3.5.13`. 6. Run the release script under the repository's root directory, replacing `${VERSION}` with a value without the `v` prefix, i.e. `3.5.13`.
- `DRY_RUN=false ./scripts/release.sh ${VERSION}` - `DRY_RUN=false ./scripts/release.sh ${VERSION}`
- **NOTE:** When doing a pre-release (i.e., a version from the main branch, 3.6.0-alpha.2), you will need to explicitly set the branch to main: - **NOTE:** When doing a pre-release (i.e., a version from the main branch, 3.6.0-alpha.2), you will need to explicitly set the branch to main:
```
```bash
DRY_RUN=false BRANCH=main ./scripts/release.sh ${VERSION} DRY_RUN=false BRANCH=main ./scripts/release.sh ${VERSION}
``` ```
It generates all release binaries under the directory `/tmp/etcd-release-${VERSION}/etcd/release/` and images. Binaries are pushed to the Google Cloud bucket It generates all release binaries under the directory `/tmp/etcd-release-${VERSION}/etcd/release/` and images. Binaries are pushed to the Google Cloud bucket
under project `etcd-development`, and images are pushed to `quay.io` and `gcr.io`. under project `etcd-development`, and images are pushed to `quay.io` and `gcr.io`.
- It is advisable to do a dry run before the actual release. This will create a `/tmp` directory. Do **NOT** forget to remove this directory before the actual release. 7. Publish the release page on GitHub
```bash
DRY_RUN=true BRANCH=${BRANCH} ./scripts/release.sh ${VERSION}
```
4. Publish the release page on GitHub
- Open the **draft** release URL shown by the release script - Open the **draft** release URL shown by the release script
- Click the pen button at the top right to edit the release - Click the pen button at the top right to edit the release
- Review that it looks correct, reviewing that the bottom checkboxes are checked depending on the - Review that it looks correct, reviewing that the bottom checkboxes are checked depending on the
release version (v3.4 & v3.5 no checkboxes, v3.6 has the set as latest release checkbox checked, release version (v3.4 no checkboxes, v3.5 has the set as latest release checkbox checked,
v3.7 has the set as pre-release checkbox checked) v3.6 has the set as pre-release checkbox checked)
- Then, publish the release - Then, publish the release
5. Announce to the etcd-dev googlegroup 8. Announce to the etcd-dev googlegroup
Follow the format of previous release emails sent to etcd-dev@googlegroups.com, see an example below. After sending out the email, ask one of the mailing list maintainers to approve the email from the pending list. Additionally, label the release email as `Release`. Follow the format of previous release emails sent to etcd-dev@googlegroups.com, see an example below. After sending out the email, ask one of the mailing list maintainers to approve the email from the pending list. Additionally, label the release email as `Release`.
```text ```text
Hello, Hello,
etcd v3.4.30 is now public! etcd v3.4.30 is now public!
https://github.com/etcd-io/etcd/releases/tag/v3.4.30 https://github.com/etcd-io/etcd/releases/tag/v3.4.30
Thanks to everyone who contributed to the release! Thanks to everyone who contributed to the release!
etcd team etcd team
``` ```
6. Update the changelog to reflect the correct release date. 9. Update the changelog to reflect the correct release date.
7. Paste the release link to the issue raised in Step 1 and close the issue. 10. Paste the release link to the issue raised in Step 1 and close the issue.
8. Raise a follow-up `kubernetes/org` pull request to return the GitHub release team to empty, least privilege state. 11. Restore standard branch protection settings and raise a follow-up `kubernetes/org` pull request to return to least privilege permissions.
9. Crease a new stable branch through `git push origin release-${VERSION_MAJOR}.${VERSION_MINOR}` if this is a new major or minor stable release. 12. Crease a new stable branch through `git push origin release-${VERSION_MAJOR}.${VERSION_MINOR}` if this is a new major or minor stable release.
10. Re-generate a new password for quay.io if needed (e.g. shared to a contributor who isn't in the release team, and we should rotate the password at least once every 3 months). 13. Re-generate a new password for quay.io if needed (e.g. shared to a contributor who isn't in the release team, and we should rotate the password at least once every 3 months).
#### Release known issues #### Release known issues

View File

@ -12,18 +12,18 @@ Each item has an assigned priority. Refer to [priority definitions](https://gith
For a full list of tasks in `v3.6.0`, please see [milestone etcd-v3.6](https://github.com/etcd-io/etcd/milestone/38). For a full list of tasks in `v3.6.0`, please see [milestone etcd-v3.6](https://github.com/etcd-io/etcd/milestone/38).
| Title | Priority | Status | Note | | Title | Priority | Status | Note |
|--------------------------------------------------------------------------------------------------------------------|-----------------------------|-------------|--------------------------------------------------------------------------------------------------------------| |--------------------------------------------------------------------------------------------------------------------|----------|-------------|--------------------------------------------------------------------------------------------------------------|
| [Support downgrade](https://github.com/etcd-io/etcd/issues/11716) | priority/important-soon | In progress | etcd will support downgrade starting from 3.6.0. But it will also support offline downgrade from 3.5 to 3.4. | | [Support downgrade](https://github.com/etcd-io/etcd/issues/11716) | priority/important-soon | In progress | etcd will support downgrade starting from 3.6.0. But it will also support offline downgrade from 3.5 to 3.4. |
| [StoreV2 deprecation](https://github.com/etcd-io/etcd/issues/12913) | priority/important-soon | In progress | This task will be covered in both 3.6 and 3.7. | | [StoreV2 deprecation](https://github.com/etcd-io/etcd/issues/12913) | priority/important-soon | In progress | This task will be covered in both 3.6 and 3.7. |
| [Release raft 3.6.0](https://github.com/etcd-io/raft/issues/89) | priority/important-soon | Completed | etcd 3.6.0 will depends on raft 3.6.0 | | [Release raft 3.6.0](https://github.com/etcd-io/raft/issues/89) | priority/important-soon | Not started | etcd 3.6.0 will depends on raft 3.6.0 |
| [Release bbolt 1.4.0](https://github.com/etcd-io/bbolt/issues/553) | priority/important-soon | Completed | etcd 3.6.0 will depends on bbolt 1.4.0 | | [Release bbolt 1.4.0](https://github.com/etcd-io/bbolt/issues/553) | priority/important-soon | Not started | etcd 3.6.0 will depends on bbolt 1.4.0 |
| [Support /livez and /readyz endpoints](https://github.com/etcd-io/etcd/issues/16007) | priority/important-longterm | Completed | It provides clearer APIs, and can also work around the stalled writes issue | | [Support /livez and /readyz endpoints](https://github.com/etcd-io/etcd/issues/16007) | priority/important-longterm | In progress | It provides clearer APIs, and can also work around the stalled writes issue |
| [Bump gRPC](https://github.com/etcd-io/etcd/issues/16290) | priority/important-longterm | Completed | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. | | [Bump gRPC](https://github.com/etcd-io/etcd/issues/16290) | priority/important-longterm | Completed | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. |
| [Deprecate grpc-gateway or bump it](https://github.com/etcd-io/etcd/issues/14499) | priority/important-longterm | Completed | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. | | [Deprecate grpc-gateway or bump it](https://github.com/etcd-io/etcd/issues/14499) | priority/important-longterm | Completed | It isn't guaranteed to be resolved in 3.6, and might be postponed to 3.7 depending on the effort and risk. |
| [bbolt: Add logger into bbolt](https://github.com/etcd-io/bbolt/issues/509) | priority/important-longterm | Completed | It's important to diagnose bbolt issues | | [bbolt: Add logger into bbolt](https://github.com/etcd-io/bbolt/issues/509) | priority/important-longterm | Completed | It's important to diagnose bbolt issues |
| [bbolt: Add surgery commands](https://github.com/etcd-io/bbolt/issues/370) | priority/important-longterm | Completed | Surgery commands are important for fixing corrupted db files | | [bbolt: Add surgery commands](https://github.com/etcd-io/bbolt/issues/370) | priority/important-longterm | Completed | Surgery commands are important for fixing corrupted db files |
| [Evaluate and (Gradulate or deprecate/remove) experimental features](https://github.com/etcd-io/etcd/issues/16292) | priority/backlog | Not started | This task will be covered in both 3.6 and 3.7. | | [Evaluate and (Gradulate or deprecate/remove) experimental features](https://github.com/etcd-io/etcd/issues/16292) | priority/backlog | Not started | This task will be covered in both 3.6 and 3.7. |
## v3.7.0 ## v3.7.0
@ -32,9 +32,8 @@ For a full list of tasks in `v3.7.0`, please see [milestone etcd-v3.7](https://g
| Title | Priority | Note | | Title | Priority | Note |
|-------------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------| |-------------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------|
| [StoreV2 deprecation](https://github.com/etcd-io/etcd/issues/12913) | P0 | Finish the remaining tasks 3.7. | | [StoreV2 deprecation](https://github.com/etcd-io/etcd/issues/12913) | P0 | Finish the remaining tasks 3.7. |
| [Support range stream](https://github.com/etcd-io/etcd/issues/12342) | P0 | to be investigated & discussed. |
| [Refactor lease: Lease might be revoked by mistake by old leader](https://github.com/etcd-io/etcd/issues/15247) | P1 | to be investigated & discussed | | [Refactor lease: Lease might be revoked by mistake by old leader](https://github.com/etcd-io/etcd/issues/15247) | P1 | to be investigated & discussed |
| [Integrate raft's new feature (async write) into etcd](https://github.com/etcd-io/etcd/issues/16291) | P1 | It should improve the performance | | [Integrate raft's new feature (async write) into etcd](https://github.com/etcd-io/etcd/issues/16291) | P1 | It should improve the performance |
| [bbolt: Support customizing the bbolt rebalance threshold](https://github.com/etcd-io/bbolt/issues/422) | P2 | It may get rid of etcd's defragmentation. Both bbolt and etcd need to be changed. | | [bbolt: Support customizing the bbolt rebalance threshold](https://github.com/etcd-io/bbolt/issues/422) | P2 | It may get rid of etcd's defragmentation. Both bbolt and etcd need to be changed. |
| [Evaluate and (graduate or deprecate/remove) experimental features](https://github.com/etcd-io/etcd/issues/16292) | P2 | Finish the remaining tasks 3.7. | | [Evaluate and (graduate or deprecate/remove) experimental features](https://github.com/etcd-io/etcd/issues/16292) | P2 | Finish the remaining tasks 3.7. |

View File

@ -14,7 +14,7 @@ Following are a few example searches on PR for convenience:
## Scope ## Scope
These guidelines serve as a primary document for managing PRs and review policy in `etcd`. Everyone is welcome to help manage PRs but the work and responsibilities discussed in this document are created with `etcd` maintainers and active contributors in mind. These guidelines serve as a primary document for managing PRs in `etcd`. Everyone is welcome to help manage PRs but the work and responsibilities discussed in this document are created with `etcd` maintainers and active contributors in mind.
## Ensure tests are run ## Ensure tests are run
@ -30,32 +30,3 @@ Reviewers are responsive in a timely fashion, but considering everyone is busy,
## Verify important labels are in place ## Verify important labels are in place
Make sure that appropriate reviewers are added to the PR. Also, make sure that a milestone is identified. If any of these or other important labels are missing, add them. If a correct label cannot be decided, leave a comment for the maintainers to do so as needed. Make sure that appropriate reviewers are added to the PR. Also, make sure that a milestone is identified. If any of these or other important labels are missing, add them. If a correct label cannot be decided, leave a comment for the maintainers to do so as needed.
## Review policy
To ensure code quality and shared ownership, this review policy applies to all pull requests (PRs).
### Default rule
PRs should get at least two approvals (/lgtm or GitHub review approval) before merging.
Notes:
* Approvals should come from a maintainer, reviewer, or submodule owner familiar with the relevant code or area.
* If theres disagreement, maintainers should discuss and agree before merging.
### Exceptions for Less Impactful PRs
For low-risk changes — such as:
* CI workflows
* Documentation
* Comments
The rule can be relaxed:
* One approval is generally enough.
However:
* If the author is a maintainer, they should still get approval from another maintainer, reviewer, or submodule owner, even for minor changes.

View File

@ -36,12 +36,7 @@ weeks inactive voting period and as long as two maintainers are on board.
Changes in project governance could be initiated by opening a GitHub PR. Changes in project governance could be initiated by opening a GitHub PR.
## SIG-etcd Governance
[SIG-etcd Governance] is documented in the Kubernetes/community repository.
[community membership]: /Documentation/contributor-guide/community-membership.md [community membership]: /Documentation/contributor-guide/community-membership.md
[Code of Conduct]: /code-of-conduct.md [Code of Conduct]: /code-of-conduct.md
[contributor guide]: /CONTRIBUTING.md [contributor guide]: /CONTRIBUTING.md
[maintainers]: /OWNERS [maintainers]: /OWNERS
[SIG-etcd Governance]: https://github.com/kubernetes/community/blob/master/sig-etcd/charter.md#deviations-from-sig-governance

View File

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2013 The etcd Authors Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,8 +1,6 @@
REPOSITORY_ROOT := $(shell git rev-parse --show-toplevel)
.PHONY: all .PHONY: all
all: build all: build
include $(REPOSITORY_ROOT)/tests/robustness/Makefile include tests/robustness/makefile.mk
.PHONY: build .PHONY: build
build: build:
@ -56,10 +54,9 @@ test-grpcproxy-e2e: build
test-e2e-release: build test-e2e-release: build
PASSES="release e2e" ./scripts/test.sh $(GO_TEST_FLAGS) PASSES="release e2e" ./scripts/test.sh $(GO_TEST_FLAGS)
# When we release the first 3.7.0-alpha.0, we can remove `VERSION="3.7.99"` below.
.PHONY: test-release .PHONY: test-release
test-release: test-release:
PASSES="release_tests" VERSION="3.7.99" ./scripts/test.sh $(GO_TEST_FLAGS) PASSES="release_tests" ./scripts/test.sh $(GO_TEST_FLAGS)
.PHONY: test-robustness .PHONY: test-robustness
test-robustness: test-robustness:
@ -187,9 +184,12 @@ endif
# Tools # Tools
GOLANGCI_LINT_VERSION = $(shell cd tools/mod && go list -m -f {{.Version}} github.com/golangci/golangci-lint)
.PHONY: install-golangci-lint .PHONY: install-golangci-lint
install-golangci-lint: install-golangci-lint:
./scripts/verify_golangci-lint_version.sh ifeq (, $(shell which golangci-lint))
$(shell curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOPATH)/bin $(GOLANGCI_LINT_VERSION))
endif
.PHONY: install-lazyfs .PHONY: install-lazyfs
install-lazyfs: bin/lazyfs install-lazyfs: bin/lazyfs
@ -225,7 +225,3 @@ verify-go-versions:
.PHONY: sync-toolchain-directive .PHONY: sync-toolchain-directive
sync-toolchain-directive: sync-toolchain-directive:
./scripts/sync_go_toolchain_directive.sh ./scripts/sync_go_toolchain_directive.sh
.PHONY: markdown-diff-lint
markdown-diff-lint:
./scripts/markdown_diff_lint.sh

16
OWNERS
View File

@ -2,23 +2,11 @@
approvers: approvers:
- ahrtr # Benjamin Wang <benjamin.ahrtr@gmail.com> <benjamin.wang@broadcom.com> - ahrtr # Benjamin Wang <benjamin.ahrtr@gmail.com> <benjamin.wang@broadcom.com>
- fuweid # Wei Fu <fuweid89@gmail.com>
- jmhbnz # James Blair <jablair@redhat.com> <mail@jamesblair.net> - jmhbnz # James Blair <jablair@redhat.com> <mail@jamesblair.net>
- serathius # Marek Siarkowicz <siarkowicz@google.com> <marek.siarkowicz@gmail.com> - serathius # Marek Siarkowicz <siarkowicz@google.com> <marek.siarkowicz@gmail.com>
- spzala # Sahdev Zala <spzala@us.ibm.com> - spzala # Sahdev Zala <spzala@us.ibm.com>
- wenjiaswe # Wenjia Zhang <wenjiazhang@google.com> <wenjia.swe@gmail.com>
reviewers: reviewers:
- fuweid # Wei Fu <fuweid89@gmail.com>
- ivanvc # Ivan Valdes <ivan@vald.es> - ivanvc # Ivan Valdes <ivan@vald.es>
- siyuanfoundation # Siyuan Zhang <sizhang@google.com> <physicsbug@gmail.com> - siyuanfoundation # Siyuan Zhang <sizhang@google.com> <physicsbug@gmail.com>
emeritus_approvers:
- bdarnell # Ben Darnell <ben@bendarnell.com>
- fanminshi # Fanmin Shi <fanmin.shi@gmail.com>
- gyuho # Gyuho Lee <gyuhox@gmail.com>
- hexfusion # Sam Batschelet <sbatsche@redhat.com>
- heyitsanthony # Anthony Romano <romanoanthony061@gmail.com>
- jingyih # Jingyi Hu <jingyih@google.com>
- jpbetz # Joe Betz <jpbetz@google.com>
- mitake # Hitoshi Mitake <h.mitake@gmail.com>
- philips # Brandon Philips <brandon@ifup.org>
- ptabor # Piotr Tabor <piotr.tabor@gmail.com>
- wenjiaswe # Wenjia Zhang <wenjiazhang@google.com> <wenjia.swe@gmail.com>
- xiang90 # Xiang Li <xiangli.cs@gmail.com>

View File

@ -5,7 +5,7 @@
[![Tests](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml) [![Tests](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/tests.yaml)
[![codeql-analysis](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml) [![codeql-analysis](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/etcd-io/etcd/actions/workflows/codeql-analysis.yml)
[![Docs](https://img.shields.io/badge/docs-latest-green.svg)](https://etcd.io/docs) [![Docs](https://img.shields.io/badge/docs-latest-green.svg)](https://etcd.io/docs)
[![Godoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godocs.io/go.etcd.io/etcd/v3) [![Godoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/etcd-io/etcd)
[![Releases](https://img.shields.io/github/release/etcd-io/etcd/all.svg?style=flat-square)](https://github.com/etcd-io/etcd/releases) [![Releases](https://img.shields.io/github/release/etcd-io/etcd/all.svg?style=flat-square)](https://github.com/etcd-io/etcd/releases)
[![LICENSE](https://img.shields.io/github/license/etcd-io/etcd.svg?style=flat-square)](https://github.com/etcd-io/etcd/blob/main/LICENSE) [![LICENSE](https://img.shields.io/github/license/etcd-io/etcd.svg?style=flat-square)](https://github.com/etcd-io/etcd/blob/main/LICENSE)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/etcd-io/etcd/badge)](https://scorecard.dev/viewer/?uri=github.com/etcd-io/etcd) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/etcd-io/etcd/badge)](https://scorecard.dev/viewer/?uri=github.com/etcd-io/etcd)
@ -42,18 +42,6 @@ See [etcdctl][etcdctl] for a simple command line client.
[vulcand]: https://github.com/vulcand/vulcand [vulcand]: https://github.com/vulcand/vulcand
[etcdctl]: https://github.com/etcd-io/etcd/tree/main/etcdctl [etcdctl]: https://github.com/etcd-io/etcd/tree/main/etcdctl
## Documentation
The most common API documentation you'll need can be found here:
* [go.etcd.io/etcd/api/v3](https://godocs.io/go.etcd.io/etcd/api/v3)
* [go.etcd.io/etcd/client/pkg/v3](https://godocs.io/go.etcd.io/etcd/client/pkg/v3)
* [go.etcd.io/etcd/client/v3](https://godocs.io/go.etcd.io/etcd/client/v3)
* [go.etcd.io/etcd/etcdctl/v3](https://godocs.io/go.etcd.io/etcd/etcdctl/v3)
* [go.etcd.io/etcd/pkg/v3](https://godocs.io/go.etcd.io/etcd/pkg/v3)
* [go.etcd.io/etcd/raft/v3](https://godocs.io/go.etcd.io/etcd/raft/v3)
* [go.etcd.io/etcd/server/v3](https://godocs.io/go.etcd.io/etcd/server/v3)
## Maintainers ## Maintainers
[Maintainers](OWNERS) strive to shape an inclusive open source project culture where users are heard and contributors feel respected and empowered. Maintainers aim to build productive relationships across different companies and disciplines. Read more about [Maintainers role and responsibilities](Documentation/contributor-guide/community-membership.md#maintainers). [Maintainers](OWNERS) strive to shape an inclusive open source project culture where users are heard and contributors feel respected and empowered. Maintainers aim to build productive relationships across different companies and disciplines. Read more about [Maintainers role and responsibilities](Documentation/contributor-guide/community-membership.md#maintainers).
@ -198,7 +186,19 @@ See [PR management](https://github.com/etcd-io/etcd/blob/main/Documentation/cont
## etcd Emeritus Maintainers ## etcd Emeritus Maintainers
etcd [emeritus maintainers](OWNERS) dedicated a part of their career to etcd and reviewed code, triaged bugs and pushed the project forward over a substantial period of time. Their contribution is greatly appreciated. These emeritus maintainers dedicated a part of their career to etcd and reviewed code, triaged bugs and pushed the project forward over a substantial period of time. Their contribution is greatly appreciated.
* Fanmin Shi
* Anthony Romano
* Brandon Philips
* Joe Betz
* Gyuho Lee
* Jingyi Hu
* Xiang Li
* Ben Darnell
* Sam Batschelet
* Piotr Tabor
* Hitoshi Mitake
### License ### License

View File

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2020 The etcd Authors Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -46,9 +46,6 @@ func request_KV_Range_0(ctx context.Context, marshaler runtime.Marshaler, client
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Range(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Range(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -73,9 +70,6 @@ func request_KV_Put_0(ctx context.Context, marshaler runtime.Marshaler, client e
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Put(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Put(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -100,9 +94,6 @@ func request_KV_DeleteRange_0(ctx context.Context, marshaler runtime.Marshaler,
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.DeleteRange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.DeleteRange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -127,9 +118,6 @@ func request_KV_Txn_0(ctx context.Context, marshaler runtime.Marshaler, client e
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Txn(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Txn(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -154,9 +142,6 @@ func request_KV_Compact_0(ctx context.Context, marshaler runtime.Marshaler, clie
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Compact(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Compact(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -224,9 +209,6 @@ func request_Lease_LeaseGrant_0(ctx context.Context, marshaler runtime.Marshaler
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseGrant(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseGrant(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -251,9 +233,6 @@ func request_Lease_LeaseRevoke_0(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -278,9 +257,6 @@ func request_Lease_LeaseRevoke_1(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -348,9 +324,6 @@ func request_Lease_LeaseTimeToLive_0(ctx context.Context, marshaler runtime.Mars
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -375,9 +348,6 @@ func request_Lease_LeaseTimeToLive_1(ctx context.Context, marshaler runtime.Mars
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -402,9 +372,6 @@ func request_Lease_LeaseLeases_0(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -429,9 +396,6 @@ func request_Lease_LeaseLeases_1(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -456,9 +420,6 @@ func request_Cluster_MemberAdd_0(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.MemberAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.MemberAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -483,9 +444,6 @@ func request_Cluster_MemberRemove_0(ctx context.Context, marshaler runtime.Marsh
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.MemberRemove(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.MemberRemove(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -510,9 +468,6 @@ func request_Cluster_MemberUpdate_0(ctx context.Context, marshaler runtime.Marsh
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.MemberUpdate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.MemberUpdate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -537,9 +492,6 @@ func request_Cluster_MemberList_0(ctx context.Context, marshaler runtime.Marshal
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.MemberList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.MemberList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -564,9 +516,6 @@ func request_Cluster_MemberPromote_0(ctx context.Context, marshaler runtime.Mars
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.MemberPromote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.MemberPromote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -591,9 +540,6 @@ func request_Maintenance_Alarm_0(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Alarm(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Alarm(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -618,9 +564,6 @@ func request_Maintenance_Status_0(ctx context.Context, marshaler runtime.Marshal
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Status(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Status(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -645,9 +588,6 @@ func request_Maintenance_Defragment_0(ctx context.Context, marshaler runtime.Mar
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Defragment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Defragment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -672,9 +612,6 @@ func request_Maintenance_Hash_0(ctx context.Context, marshaler runtime.Marshaler
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Hash(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Hash(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -699,9 +636,6 @@ func request_Maintenance_HashKV_0(ctx context.Context, marshaler runtime.Marshal
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.HashKV(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.HashKV(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -726,9 +660,6 @@ func request_Maintenance_Snapshot_0(ctx context.Context, marshaler runtime.Marsh
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
stream, err := client.Snapshot(ctx, &protoReq) stream, err := client.Snapshot(ctx, &protoReq)
if err != nil { if err != nil {
return nil, metadata, err return nil, metadata, err
@ -749,9 +680,6 @@ func request_Maintenance_MoveLeader_0(ctx context.Context, marshaler runtime.Mar
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.MoveLeader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.MoveLeader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -776,9 +704,6 @@ func request_Maintenance_Downgrade_0(ctx context.Context, marshaler runtime.Mars
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Downgrade(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Downgrade(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -803,9 +728,6 @@ func request_Auth_AuthEnable_0(ctx context.Context, marshaler runtime.Marshaler,
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.AuthEnable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.AuthEnable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -830,9 +752,6 @@ func request_Auth_AuthDisable_0(ctx context.Context, marshaler runtime.Marshaler
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.AuthDisable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.AuthDisable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -857,9 +776,6 @@ func request_Auth_AuthStatus_0(ctx context.Context, marshaler runtime.Marshaler,
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.AuthStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.AuthStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -884,9 +800,6 @@ func request_Auth_Authenticate_0(ctx context.Context, marshaler runtime.Marshale
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -911,9 +824,6 @@ func request_Auth_UserAdd_0(ctx context.Context, marshaler runtime.Marshaler, cl
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -938,9 +848,6 @@ func request_Auth_UserGet_0(ctx context.Context, marshaler runtime.Marshaler, cl
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -965,9 +872,6 @@ func request_Auth_UserList_0(ctx context.Context, marshaler runtime.Marshaler, c
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -992,9 +896,6 @@ func request_Auth_UserDelete_0(ctx context.Context, marshaler runtime.Marshaler,
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1019,9 +920,6 @@ func request_Auth_UserChangePassword_0(ctx context.Context, marshaler runtime.Ma
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserChangePassword(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserChangePassword(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1046,9 +944,6 @@ func request_Auth_UserGrantRole_0(ctx context.Context, marshaler runtime.Marshal
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserGrantRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserGrantRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1073,9 +968,6 @@ func request_Auth_UserRevokeRole_0(ctx context.Context, marshaler runtime.Marsha
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.UserRevokeRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.UserRevokeRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1100,9 +992,6 @@ func request_Auth_RoleAdd_0(ctx context.Context, marshaler runtime.Marshaler, cl
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.RoleAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.RoleAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1127,9 +1016,6 @@ func request_Auth_RoleGet_0(ctx context.Context, marshaler runtime.Marshaler, cl
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.RoleGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.RoleGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1154,9 +1040,6 @@ func request_Auth_RoleList_0(ctx context.Context, marshaler runtime.Marshaler, c
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.RoleList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.RoleList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1181,9 +1064,6 @@ func request_Auth_RoleDelete_0(ctx context.Context, marshaler runtime.Marshaler,
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.RoleDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.RoleDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1208,9 +1088,6 @@ func request_Auth_RoleGrantPermission_0(ctx context.Context, marshaler runtime.M
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.RoleGrantPermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.RoleGrantPermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }
@ -1235,9 +1112,6 @@ func request_Auth_RoleRevokePermission_0(ctx context.Context, marshaler runtime.
if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
} }
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
msg, err := client.RoleRevokePermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) msg, err := client.RoleRevokePermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return protov1.MessageV2(msg), metadata, err return protov1.MessageV2(msg), metadata, err
} }

View File

@ -1,30 +1,29 @@
module go.etcd.io/etcd/api/v3 module go.etcd.io/etcd/api/v3
go 1.24 go 1.23.0
toolchain go1.24.5 toolchain go1.23.11
require ( require (
github.com/coreos/go-semver v0.3.1 github.com/coreos/go-semver v0.3.1
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.4 github.com/golang/protobuf v1.5.4
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
google.golang.org/grpc v1.74.2 google.golang.org/grpc v1.71.1
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.5
) )
require ( require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/kr/text v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/text v0.27.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@ -1,9 +1,10 @@
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@ -14,34 +15,34 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -51,20 +52,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -73,14 +74,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@ -26,7 +26,7 @@ import (
var ( var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with. // MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "3.0.0" MinClusterVersion = "3.0.0"
Version = "3.7.0-alpha.0" Version = "3.6.4"
APIVersion = "unknown" APIVersion = "unknown"
// Git SHA Value will be set during build // Git SHA Value will be set during build
@ -43,7 +43,6 @@ var (
V3_5 = semver.Version{Major: 3, Minor: 5} V3_5 = semver.Version{Major: 3, Minor: 5}
V3_6 = semver.Version{Major: 3, Minor: 6} V3_6 = semver.Version{Major: 3, Minor: 6}
V3_7 = semver.Version{Major: 3, Minor: 7} V3_7 = semver.Version{Major: 3, Minor: 7}
V3_8 = semver.Version{Major: 3, Minor: 8}
V4_0 = semver.Version{Major: 4, Minor: 0} V4_0 = semver.Version{Major: 4, Minor: 0}
// AllVersions keeps all the versions in ascending order. // AllVersions keeps all the versions in ascending order.

View File

@ -10,15 +10,6 @@
}, },
{ {
"project": "github.com/anishathalye/porcupine", "project": "github.com/anishathalye/porcupine",
"licenses": [
{
"type": "MIT License",
"confidence": 0.96875
}
]
},
{
"project": "github.com/antithesishq/antithesis-sdk-go",
"licenses": [ "licenses": [
{ {
"type": "MIT License", "type": "MIT License",
@ -45,7 +36,7 @@
] ]
}, },
{ {
"project": "github.com/cenkalti/backoff/v5", "project": "github.com/cenkalti/backoff/v4",
"licenses": [ "licenses": [
{ {
"type": "MIT License", "type": "MIT License",
@ -269,6 +260,33 @@
} }
] ]
}, },
{
"project": "github.com/klauspost/compress",
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 0.9376299376299376
}
]
},
{
"project": "github.com/klauspost/compress/internal/snapref",
"licenses": [
{
"type": "BSD 3-clause \"New\" or \"Revised\" License",
"confidence": 0.9663865546218487
}
]
},
{
"project": "github.com/klauspost/compress/zstd/internal/xxhash",
"licenses": [
{
"type": "MIT License",
"confidence": 1
}
]
},
{ {
"project": "github.com/mattn/go-colorable", "project": "github.com/mattn/go-colorable",
"licenses": [ "licenses": [
@ -305,24 +323,6 @@
} }
] ]
}, },
{
"project": "github.com/olekukonko/errors",
"licenses": [
{
"type": "MIT License",
"confidence": 1
}
]
},
{
"project": "github.com/olekukonko/ll",
"licenses": [
{
"type": "MIT License",
"confidence": 1
}
]
},
{ {
"project": "github.com/olekukonko/tablewriter", "project": "github.com/olekukonko/tablewriter",
"licenses": [ "licenses": [
@ -472,7 +472,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -481,7 +481,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -490,7 +490,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -499,7 +499,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -508,7 +508,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -517,7 +517,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -526,7 +526,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -535,7 +535,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -544,7 +544,7 @@
"licenses": [ "licenses": [
{ {
"type": "Apache License 2.0", "type": "Apache License 2.0",
"confidence": 0.9988925802879292 "confidence": 1
} }
] ]
}, },
@ -665,19 +665,6 @@
} }
] ]
}, },
{
"project": "go.yaml.in/yaml/v2",
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 1
},
{
"type": "MIT License",
"confidence": 0.8975609756097561
}
]
},
{ {
"project": "golang.org/x/crypto", "project": "golang.org/x/crypto",
"licenses": [ "licenses": [
@ -786,6 +773,15 @@
} }
] ]
}, },
{
"project": "sigs.k8s.io/json",
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 0.9617021276595744
}
]
},
{ {
"project": "sigs.k8s.io/yaml", "project": "sigs.k8s.io/yaml",
"licenses": [ "licenses": [
@ -798,5 +794,18 @@
"confidence": 1 "confidence": 1
} }
] ]
},
{
"project": "sigs.k8s.io/yaml/goyaml.v2",
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 1
},
{
"type": "MIT License",
"confidence": 0.8975609756097561
}
]
} }
] ]

202
cache/LICENSE vendored
View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 The etcd Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

4
cache/OWNERS vendored
View File

@ -1,4 +0,0 @@
# See the OWNERS docs at https://go.k8s.io/owners
labels:
- area/cache

3
cache/README.md vendored
View File

@ -1,3 +0,0 @@
# etcd cache
Experimental etcd client cache library.

388
cache/cache.go vendored
View File

@ -1,388 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"bytes"
"context"
"errors"
"fmt"
"sync"
"time"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
var (
// TODO: add gap-free replay for arbitrary startRevs and drop this guard.
// Returned when an option combination isnt yet handled by the cache (e.g. WithPrevKV, WithProgressNotify for Watch(), WithCountOnly for Get()).
ErrUnsupportedRequest = errors.New("cache: unsupported request parameters")
// Returned when the requested key or keyrange is invalid (empty or reversed) or lies outside c.prefix.
ErrKeyRangeInvalid = errors.New("cache: invalid or outofrange key range")
)
// Cache buffers a single etcd Watch for a given keyprefix and fanouts local watchers.
type Cache struct {
prefix string // prefix is the key-prefix this shard is responsible for ("" = root).
cfg Config // immutable runtime configuration
watcher clientv3.Watcher
kv clientv3.KV
demux *demux // demux fans incoming events out to active watchers and manages resync.
store *store // lastobserved snapshot
ready chan struct{}
stop context.CancelFunc
waitGroup sync.WaitGroup
internalCtx context.Context
}
// New builds a cache shard that watches only the requested prefix.
// For the root cache pass "".
func New(client *clientv3.Client, prefix string, opts ...Option) (*Cache, error) {
cfg := defaultConfig()
for _, opt := range opts {
opt(&cfg)
}
if cfg.HistoryWindowSize <= 0 {
return nil, fmt.Errorf("invalid HistoryWindowSize %d (must be > 0)", cfg.HistoryWindowSize)
}
internalCtx, cancel := context.WithCancel(context.Background())
cache := &Cache{
prefix: prefix,
cfg: cfg,
watcher: client.Watcher,
kv: client.KV,
store: newStore(),
ready: make(chan struct{}),
stop: cancel,
internalCtx: internalCtx,
}
cache.demux = NewDemux(internalCtx, &cache.waitGroup, cfg.HistoryWindowSize, cfg.ResyncInterval)
cache.waitGroup.Add(1)
go func() {
defer cache.waitGroup.Done()
cache.getWatchLoop(internalCtx)
}()
return cache, nil
}
// Watch registers a cache-backed watcher for a given key or prefix.
// It returns a WatchChan that streams WatchResponses containing events.
func (c *Cache) Watch(ctx context.Context, key string, opts ...clientv3.OpOption) clientv3.WatchChan {
if err := c.WaitReady(ctx); err != nil {
emptyWatchChan := make(chan clientv3.WatchResponse)
close(emptyWatchChan)
return emptyWatchChan
}
op := clientv3.OpWatch(key, opts...)
startRev := op.Rev()
if startRev != 0 {
if oldest := c.demux.PeekOldest(); oldest != 0 && startRev < oldest {
ch := make(chan clientv3.WatchResponse, 1)
ch <- clientv3.WatchResponse{
Canceled: true,
CompactRevision: startRev,
}
close(ch)
return ch
}
}
pred, err := c.validateWatch(key, op)
if err != nil {
ch := make(chan clientv3.WatchResponse, 1)
ch <- clientv3.WatchResponse{Canceled: true, CancelReason: err.Error()}
close(ch)
return ch
}
w := newWatcher(c.cfg.PerWatcherBufferSize, pred)
c.demux.Register(w, startRev)
responseChan := make(chan clientv3.WatchResponse)
c.waitGroup.Add(1)
go func() {
defer c.waitGroup.Done()
defer close(responseChan)
defer c.demux.Unregister(w)
for {
select {
case <-ctx.Done():
return
case <-c.internalCtx.Done():
return
case events, ok := <-w.eventQueue:
if !ok {
return
}
select {
case <-ctx.Done():
return
case <-c.internalCtx.Done():
return
case responseChan <- clientv3.WatchResponse{Events: events}:
}
}
}
}()
return responseChan
}
func (c *Cache) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
if err := c.WaitReady(ctx); err != nil {
return nil, err
}
op := clientv3.OpGet(key, opts...)
if _, err := c.validateGet(key, op); err != nil {
return nil, err
}
startKey := []byte(key)
endKey := op.RangeBytes()
kvs, rev, err := c.store.Get(startKey, endKey)
if err != nil {
return nil, err
}
return &clientv3.GetResponse{
Header: &pb.ResponseHeader{Revision: rev},
Kvs: kvs,
Count: int64(len(kvs)),
}, nil
}
// Ready reports whether the cache has finished its initial load.
func (c *Cache) Ready() bool {
select {
case <-c.ready:
return true
default:
return false
}
}
// WaitReady blocks until the cache is ready or the ctx is cancelled.
func (c *Cache) WaitReady(ctx context.Context) error {
select {
case <-c.ready:
return ctx.Err()
case <-ctx.Done():
return ctx.Err()
}
}
func (c *Cache) WaitForRevision(ctx context.Context, rev int64) error {
for {
if c.store.LatestRev() >= rev {
return nil
}
select {
case <-time.After(10 * time.Millisecond):
case <-ctx.Done():
return ctx.Err()
}
}
}
// Close cancels the private context and blocks until all goroutines return.
func (c *Cache) Close() {
c.stop()
c.waitGroup.Wait()
}
func (c *Cache) getWatchLoop(ctx context.Context) {
cfg := defaultConfig()
backoff := cfg.InitialBackoff
for {
if err := ctx.Err(); err != nil {
return
}
if err := c.getWatch(ctx); err != nil {
fmt.Printf("getWatch failed, will retry after %v: %v\n", backoff, err)
}
select {
case <-ctx.Done():
return
case <-time.After(backoff):
}
}
}
func (c *Cache) getWatch(ctx context.Context) error {
getResp, err := c.get(ctx)
if err != nil {
return err
}
return c.watch(ctx, getResp.Header.Revision+1)
}
func (c *Cache) get(ctx context.Context) (*clientv3.GetResponse, error) {
resp, err := c.kv.Get(ctx, c.prefix, clientv3.WithPrefix())
if err != nil {
return nil, err
}
c.store.Restore(resp.Kvs, resp.Header.Revision)
return resp, nil
}
func (c *Cache) watch(ctx context.Context, rev int64) error {
readyOnce := sync.Once{}
for {
watchCh := c.watcher.Watch(
ctx,
c.prefix,
clientv3.WithPrefix(),
clientv3.WithRev(rev),
clientv3.WithProgressNotify(),
clientv3.WithCreatedNotify(),
)
for resp := range watchCh {
readyOnce.Do(func() { close(c.ready) })
if err := resp.Err(); err != nil {
c.demux.Purge()
c.resetReady()
c.store.Reset()
return err
}
if err := c.store.Apply(resp.Events); err != nil {
c.demux.Purge()
c.resetReady()
c.store.Reset()
return err
}
c.demux.Broadcast(resp.Events)
}
if ctx.Err() != nil {
return ctx.Err()
}
}
}
func (c *Cache) resetReady() {
select {
case <-c.ready:
c.ready = make(chan struct{})
default:
}
}
func (c *Cache) validateWatch(key string, op clientv3.Op) (pred KeyPredicate, err error) {
switch {
case op.IsPrevKV():
return nil, fmt.Errorf("%w: PrevKV not supported", ErrUnsupportedRequest)
case op.IsFragment():
return nil, fmt.Errorf("%w: Fragment not supported", ErrUnsupportedRequest)
case op.IsProgressNotify():
return nil, fmt.Errorf("%w: ProgressNotify not supported", ErrUnsupportedRequest)
case op.IsCreatedNotify():
return nil, fmt.Errorf("%w: CreatedNotify not supported", ErrUnsupportedRequest)
case op.IsFilterPut():
return nil, fmt.Errorf("%w: FilterPut not supported", ErrUnsupportedRequest)
case op.IsFilterDelete():
return nil, fmt.Errorf("%w: FilterDelete not supported", ErrUnsupportedRequest)
}
startKey := []byte(key)
endKey := op.RangeBytes() // nil = single key, {0}=FromKey, else explicit range
if err := c.validateRange(startKey, endKey); err != nil {
return nil, err
}
return KeyPredForRange(startKey, endKey), nil
}
func (c *Cache) validateGet(key string, op clientv3.Op) (KeyPredicate, error) {
switch {
case op.IsCountOnly():
return nil, fmt.Errorf("%w: CountOnly not supported", ErrUnsupportedRequest)
case op.IsPrevKV():
return nil, fmt.Errorf("%w: PrevKV not supported", ErrUnsupportedRequest)
case op.IsSortSet():
return nil, fmt.Errorf("%w: SortSet not supported", ErrUnsupportedRequest)
case op.Limit() != 0:
return nil, fmt.Errorf("%w: Limit(%d) not supported", ErrUnsupportedRequest, op.Limit())
case op.MinModRev() != 0:
return nil, fmt.Errorf("%w: MinModRev(%d) not supported", ErrUnsupportedRequest, op.MinModRev())
case op.MaxModRev() != 0:
return nil, fmt.Errorf("%w: MaxModRev(%d) not supported", ErrUnsupportedRequest, op.MaxModRev())
case op.MinCreateRev() != 0:
return nil, fmt.Errorf("%w: MinCreateRev(%d) not supported", ErrUnsupportedRequest, op.MinCreateRev())
case op.MaxCreateRev() != 0:
return nil, fmt.Errorf("%w: MaxCreateRev(%d) not supported", ErrUnsupportedRequest, op.MaxCreateRev())
// cache now only serves serializable reads of the latest revision (rev == 0).
case op.Rev() != 0:
return nil, fmt.Errorf("%w: Rev(%d) not supported", ErrUnsupportedRequest, op.Rev())
case !op.IsSerializable():
return nil, fmt.Errorf("%w: non-serializable request", ErrUnsupportedRequest)
}
startKey := []byte(key)
endKey := op.RangeBytes()
if err := c.validateRange(startKey, endKey); err != nil {
return nil, err
}
return KeyPredForRange(startKey, endKey), nil
}
func (c *Cache) validateRange(startKey, endKey []byte) error {
prefixStart := []byte(c.prefix)
prefixEnd := []byte(clientv3.GetPrefixRangeEnd(c.prefix))
isSingleKey := len(endKey) == 0
isFromKey := len(endKey) == 1 && endKey[0] == 0
switch {
case isSingleKey:
if c.prefix == "" {
return nil
}
if bytes.Compare(startKey, prefixStart) < 0 || bytes.Compare(startKey, prefixEnd) >= 0 {
return ErrKeyRangeInvalid
}
return nil
case isFromKey:
if c.prefix != "" {
return ErrKeyRangeInvalid
}
return nil
default:
if bytes.Compare(endKey, startKey) <= 0 {
return ErrKeyRangeInvalid
}
if c.prefix == "" {
return nil
}
if bytes.Compare(startKey, prefixStart) < 0 || bytes.Compare(endKey, prefixEnd) > 0 {
return ErrKeyRangeInvalid
}
return nil
}
}

493
cache/cache_test.go vendored
View File

@ -1,493 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"context"
"testing"
"time"
"github.com/google/go-cmp/cmp"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
mvccpb "go.etcd.io/etcd/api/v3/mvccpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
func TestCacheWatchAtomicOrderedDelivery(t *testing.T) {
tests := []struct {
name string
sentBatches [][]*clientv3.Event
wantBatch []*clientv3.Event
}{
{
name: "single_event",
sentBatches: [][]*clientv3.Event{
{event(mvccpb.PUT, "/a", 5)},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 5),
},
},
{
name: "same_revision_batch",
sentBatches: [][]*clientv3.Event{
{
event(mvccpb.PUT, "/a", 10),
event(mvccpb.PUT, "/b", 10),
},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 10),
event(mvccpb.PUT, "/b", 10),
},
},
{
name: "mixed_revisions_in_single_response",
sentBatches: [][]*clientv3.Event{
{
event(mvccpb.PUT, "/a", 11),
event(mvccpb.PUT, "/b", 11),
event(mvccpb.PUT, "/c", 12),
},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 11),
event(mvccpb.PUT, "/b", 11),
event(mvccpb.PUT, "/c", 12),
},
},
{
name: "mixed_event_types_same_revision",
sentBatches: [][]*clientv3.Event{
{
event(mvccpb.PUT, "/x", 5),
event(mvccpb.PUT, "/y", 6),
event(mvccpb.DELETE, "/x", 6),
},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/x", 5),
event(mvccpb.PUT, "/y", 6),
event(mvccpb.DELETE, "/x", 6),
},
},
{
name: "all_events_in_one_response",
sentBatches: [][]*clientv3.Event{
{
event(mvccpb.PUT, "/a", 2),
event(mvccpb.PUT, "/b", 2),
event(mvccpb.PUT, "/c", 3),
event(mvccpb.PUT, "/d", 4),
event(mvccpb.PUT, "/e", 4),
event(mvccpb.PUT, "/f", 5),
event(mvccpb.PUT, "/g", 6),
event(mvccpb.PUT, "/h", 6),
event(mvccpb.PUT, "/i", 7),
event(mvccpb.PUT, "/j", 7),
},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 2),
event(mvccpb.PUT, "/b", 2),
event(mvccpb.PUT, "/c", 3),
event(mvccpb.PUT, "/d", 4),
event(mvccpb.PUT, "/e", 4),
event(mvccpb.PUT, "/f", 5),
event(mvccpb.PUT, "/g", 6),
event(mvccpb.PUT, "/h", 6),
event(mvccpb.PUT, "/i", 7),
event(mvccpb.PUT, "/j", 7),
},
},
{
name: "one_revision_group_per_response",
sentBatches: [][]*clientv3.Event{
{event(mvccpb.PUT, "/a", 2), event(mvccpb.PUT, "/b", 2)},
{event(mvccpb.PUT, "/c", 3)},
{event(mvccpb.PUT, "/d", 4), event(mvccpb.PUT, "/e", 4)},
{event(mvccpb.PUT, "/f", 5)},
{event(mvccpb.PUT, "/g", 6), event(mvccpb.PUT, "/h", 6)},
{event(mvccpb.PUT, "/i", 7), event(mvccpb.PUT, "/j", 7)},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 2),
event(mvccpb.PUT, "/b", 2),
event(mvccpb.PUT, "/c", 3),
event(mvccpb.PUT, "/d", 4),
event(mvccpb.PUT, "/e", 4),
event(mvccpb.PUT, "/f", 5),
event(mvccpb.PUT, "/g", 6),
event(mvccpb.PUT, "/h", 6),
event(mvccpb.PUT, "/i", 7),
event(mvccpb.PUT, "/j", 7),
},
},
{
name: "two_revision_groups_per_response",
sentBatches: [][]*clientv3.Event{
{event(mvccpb.PUT, "/a", 2), event(mvccpb.PUT, "/b", 2), event(mvccpb.PUT, "/c", 3)},
{event(mvccpb.PUT, "/d", 4), event(mvccpb.PUT, "/e", 4), event(mvccpb.PUT, "/f", 5)},
{event(mvccpb.PUT, "/g", 6), event(mvccpb.PUT, "/h", 6)},
{event(mvccpb.PUT, "/i", 7), event(mvccpb.PUT, "/j", 7)},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 2),
event(mvccpb.PUT, "/b", 2),
event(mvccpb.PUT, "/c", 3),
event(mvccpb.PUT, "/d", 4),
event(mvccpb.PUT, "/e", 4),
event(mvccpb.PUT, "/f", 5),
event(mvccpb.PUT, "/g", 6),
event(mvccpb.PUT, "/h", 6),
event(mvccpb.PUT, "/i", 7),
event(mvccpb.PUT, "/j", 7),
},
},
{
name: "three_revision_groups_per_response",
sentBatches: [][]*clientv3.Event{
{
event(mvccpb.PUT, "/a", 2), event(mvccpb.PUT, "/b", 2),
event(mvccpb.PUT, "/c", 3),
event(mvccpb.PUT, "/d", 4), event(mvccpb.PUT, "/e", 4),
},
{
event(mvccpb.PUT, "/f", 5),
event(mvccpb.PUT, "/g", 6), event(mvccpb.PUT, "/h", 6),
event(mvccpb.PUT, "/i", 7), event(mvccpb.PUT, "/j", 7),
},
},
wantBatch: []*clientv3.Event{
event(mvccpb.PUT, "/a", 2),
event(mvccpb.PUT, "/b", 2),
event(mvccpb.PUT, "/c", 3),
event(mvccpb.PUT, "/d", 4),
event(mvccpb.PUT, "/e", 4),
event(mvccpb.PUT, "/f", 5),
event(mvccpb.PUT, "/g", 6),
event(mvccpb.PUT, "/h", 6),
event(mvccpb.PUT, "/i", 7),
event(mvccpb.PUT, "/j", 7),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mw := newMockWatcher(16)
fakeClient := &clientv3.Client{
Watcher: mw,
KV: &kvStub{},
}
cache, err := New(fakeClient, "")
if err != nil {
t.Fatalf("New cache: %v", err)
}
if err != nil {
t.Fatalf("New cache: %v", err)
}
defer cache.Close()
mw.responses <- clientv3.WatchResponse{}
<-mw.registered
ctxWait, cancelWait := context.WithTimeout(t.Context(), time.Second)
if err := cache.WaitReady(ctxWait); err != nil {
t.Fatalf("cache did not become Ready(): %v", err)
}
cancelWait()
ctx, cancel := context.WithTimeout(t.Context(), 2*time.Second)
defer cancel()
watchCh := cache.Watch(ctx, "", clientv3.WithPrefix())
for _, batch := range tt.sentBatches {
mw.responses <- clientv3.WatchResponse{Events: batch}
}
close(mw.responses)
got := collectAndAssertAtomicEvents(ctx, t, watchCh, len(tt.wantBatch))
if diff := cmp.Diff(tt.wantBatch, got); diff != "" {
t.Fatalf("event mismatch (-want +got):\n%s", diff)
}
})
}
}
func TestValidateWatchRange(t *testing.T) {
type tc struct {
name string
watchKey string
opts []clientv3.OpOption
cachePrefix string
wantErr bool
}
tests := []tc{
{
name: "single key",
watchKey: "/a",
cachePrefix: "",
wantErr: false,
},
{
name: "prefix single key",
watchKey: "/foo/a",
cachePrefix: "/foo",
wantErr: false,
},
{
name: "single key outside prefix returns error",
watchKey: "/z",
cachePrefix: "/foo",
wantErr: true,
},
{
name: "explicit range",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithRange("/b")},
cachePrefix: "",
wantErr: false,
},
{
name: "exact prefix range",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithRange("/b")},
cachePrefix: "/a",
wantErr: false,
},
{
name: "prefix subrange",
watchKey: "/foo",
opts: []clientv3.OpOption{clientv3.WithRange("/foo/a")},
cachePrefix: "/foo",
wantErr: false,
},
{
name: "reverse range returns error",
watchKey: "/b",
opts: []clientv3.OpOption{clientv3.WithRange("/a")},
cachePrefix: "",
wantErr: true,
},
{
name: "empty range returns error",
watchKey: "/foo",
opts: []clientv3.OpOption{clientv3.WithRange("/foo")},
cachePrefix: "",
wantErr: true,
},
{
name: "range starting below cache prefix returns error",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithRange("/foo")},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "range encompassing cache prefix returns error",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithRange("/z")},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "range crossing prefixEnd returns error",
watchKey: "/foo",
opts: []clientv3.OpOption{clientv3.WithRange("/z")},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "empty prefix",
watchKey: "",
opts: []clientv3.OpOption{clientv3.WithPrefix()},
cachePrefix: "",
wantErr: false,
},
{
name: "empty prefix with cachePrefix returns error",
watchKey: "",
opts: []clientv3.OpOption{clientv3.WithPrefix()},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "prefix watch matches cachePrefix exactly",
watchKey: "/foo",
opts: []clientv3.OpOption{clientv3.WithPrefix()},
cachePrefix: "/foo",
wantErr: false,
},
{
name: "prefix watch inside cachePrefix",
watchKey: "/foo/bar",
opts: []clientv3.OpOption{clientv3.WithPrefix()},
cachePrefix: "/foo",
wantErr: false,
},
{
name: "prefix starting below cachePrefix returns error",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithPrefix()},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "prefix starting above shard prefixEnd returns error",
watchKey: "/fop",
opts: []clientv3.OpOption{clientv3.WithPrefix()},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "fromKey openended",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithFromKey()},
cachePrefix: "",
wantErr: false,
},
{
name: "fromKey starting at prefix start",
watchKey: "/foo",
opts: []clientv3.OpOption{clientv3.WithFromKey()},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "fromKey starting below prefixEnd",
watchKey: "/a",
opts: []clientv3.OpOption{clientv3.WithFromKey()},
cachePrefix: "/foo",
wantErr: true,
},
{
name: "fromKey starting above prefixEnd returns error",
watchKey: "/fop",
opts: []clientv3.OpOption{clientv3.WithFromKey()},
cachePrefix: "/foo",
wantErr: true,
},
}
for _, c := range tests {
t.Run(c.name, func(t *testing.T) {
dummyCache := &Cache{prefix: c.cachePrefix}
op := clientv3.OpGet(c.watchKey, c.opts...)
err := dummyCache.validateRange([]byte(c.watchKey), op.RangeBytes())
if gotErr := err != nil; gotErr != c.wantErr {
t.Fatalf("validateWatchRange(%q, %q, %v) err=%v, wantErr=%v",
c.cachePrefix, c.watchKey, c.opts, err, c.wantErr)
}
})
}
}
type mockWatcher struct {
responses chan clientv3.WatchResponse
registered chan struct{}
}
type kvStub struct{}
func (kvStub) Get(ctx context.Context, key string, _ ...clientv3.OpOption) (*clientv3.GetResponse, error) {
return &clientv3.GetResponse{Header: &pb.ResponseHeader{Revision: 0}}, nil
}
func (kvStub) Put(ctx context.Context, key, val string, _ ...clientv3.OpOption) (*clientv3.PutResponse, error) {
return nil, nil
}
func (kvStub) Delete(ctx context.Context, key string, _ ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
return nil, nil
}
func (kvStub) Compact(ctx context.Context, rev int64, _ ...clientv3.CompactOption) (*clientv3.CompactResponse, error) {
return nil, nil
}
func (kvStub) Do(ctx context.Context, op clientv3.Op) (clientv3.OpResponse, error) {
return clientv3.OpResponse{}, nil
}
func (kvStub) Txn(ctx context.Context) clientv3.Txn {
return nil
}
func newMockWatcher(buf int) *mockWatcher {
return &mockWatcher{
responses: make(chan clientv3.WatchResponse, buf),
registered: make(chan struct{}),
}
}
func (m *mockWatcher) Watch(_ context.Context, _ string, _ ...clientv3.OpOption) clientv3.WatchChan {
select { // prevent “close of closed channel” on re-watch
case <-m.registered:
default:
close(m.registered)
}
return m.responses
}
func (m *mockWatcher) RequestProgress(_ context.Context) error { return nil }
func (m *mockWatcher) Close() error { close(m.responses); return nil }
func event(eventType mvccpb.Event_EventType, key string, rev int64) *clientv3.Event {
return &clientv3.Event{
Type: eventType,
Kv: &mvccpb.KeyValue{
Key: []byte(key),
ModRevision: rev,
CreateRevision: rev,
Version: 1,
},
}
}
func collectAndAssertAtomicEvents(ctx context.Context, t *testing.T, watchCh clientv3.WatchChan, wantCount int) []*clientv3.Event {
t.Helper()
var events []*clientv3.Event
var lastRevision int64
for {
select {
case <-ctx.Done():
t.Fatalf("timed out waiting for events (%d/%d received)",
len(events), wantCount)
case resp, ok := <-watchCh:
if !ok {
return events
}
if len(resp.Events) != 0 && resp.Events[0].Kv.ModRevision == lastRevision {
t.Fatalf("same revision found as in previous response: %d", lastRevision)
}
for _, ev := range resp.Events {
if ev.Kv.ModRevision < lastRevision {
t.Fatalf("revision went backwards: last %d, now %d", lastRevision, ev.Kv.ModRevision)
}
events = append(events, ev)
lastRevision = ev.Kv.ModRevision
}
if wantCount != 0 && len(events) >= wantCount {
return events
}
}
}
}

72
cache/config.go vendored
View File

@ -1,72 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import "time"
type Config struct {
// PerWatcherBufferSize caps each watchers buffered channel.
// Bigger values tolerate brief client slow-downs at the cost of extra memory.
PerWatcherBufferSize int
// HistoryWindowSize is the max events kept in memory for replay.
// It defines how far back the cache can replay events to lagging watchers
HistoryWindowSize int
// ResyncInterval controls how often the demux attempts to catch a lagging watcher up by replaying events from History.
ResyncInterval time.Duration
// InitialBackoff is the first delay to wait before retrying an upstream etcd Watch after it ends with an error.
InitialBackoff time.Duration
// MaxBackoff caps the exponential back-off between successive upstream watch retries.
MaxBackoff time.Duration
// GetTimeout is the timeout applied to the first Get() used to bootstrap the cache.
GetTimeout time.Duration
}
// TODO: tune via performance/load tests.
func defaultConfig() Config {
return Config{
PerWatcherBufferSize: 10,
HistoryWindowSize: 2048,
ResyncInterval: 50 * time.Millisecond,
InitialBackoff: 50 * time.Millisecond,
MaxBackoff: 2 * time.Second,
GetTimeout: 5 * time.Second,
}
}
type Option func(*Config)
func WithPerWatcherBufferSize(n int) Option {
return func(c *Config) { c.PerWatcherBufferSize = n }
}
func WithHistoryWindowSize(n int) Option {
return func(c *Config) { c.HistoryWindowSize = n }
}
func WithResyncInterval(d time.Duration) Option {
return func(c *Config) { c.ResyncInterval = d }
}
func WithInitialBackoff(d time.Duration) Option {
return func(c *Config) { c.InitialBackoff = d }
}
func WithMaxBackoff(d time.Duration) Option {
return func(c *Config) { c.MaxBackoff = d }
}
func WithGetTimeout(d time.Duration) Option {
return func(c *Config) { c.GetTimeout = d }
}

185
cache/demux.go vendored
View File

@ -1,185 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"context"
"sync"
"time"
clientv3 "go.etcd.io/etcd/client/v3"
)
type demux struct {
mu sync.RWMutex
// activeWatchers & laggingWatchers hold the first revision the watcher still needs (nextRev).
activeWatchers map[*watcher]int64
laggingWatchers map[*watcher]int64
history *ringBuffer
resyncInterval time.Duration
}
func NewDemux(ctx context.Context, wg *sync.WaitGroup, historyWindowSize int, resyncInterval time.Duration) *demux {
d := newDemux(historyWindowSize, resyncInterval)
wg.Add(1)
go func() {
defer wg.Done()
d.resyncLoop(ctx)
}()
return d
}
func newDemux(historyWindowSize int, resyncInterval time.Duration) *demux {
return &demux{
activeWatchers: make(map[*watcher]int64),
laggingWatchers: make(map[*watcher]int64),
history: newRingBuffer(historyWindowSize),
resyncInterval: resyncInterval,
}
}
// resyncLoop periodically tries to catch lagging watchers up by replaying events from History.
func (d *demux) resyncLoop(ctx context.Context) {
timer := time.NewTimer(d.resyncInterval)
defer timer.Stop()
for {
select {
case <-ctx.Done():
return
case <-timer.C:
d.resyncLaggingWatchers()
timer.Reset(d.resyncInterval)
}
}
}
func (d *demux) Register(w *watcher, startingRev int64) {
d.mu.Lock()
defer d.mu.Unlock()
latestRev := d.history.PeekLatest()
// Special case: 0 means “newest”.
if startingRev == 0 {
if latestRev == 0 {
d.activeWatchers[w] = 0
return
}
startingRev = latestRev + 1
}
if startingRev <= latestRev {
d.laggingWatchers[w] = startingRev
} else {
d.activeWatchers[w] = startingRev
}
}
func (d *demux) Unregister(w *watcher) {
func() {
d.mu.Lock()
defer d.mu.Unlock()
delete(d.activeWatchers, w)
delete(d.laggingWatchers, w)
}()
w.Stop()
}
func (d *demux) Broadcast(events []*clientv3.Event) {
if len(events) == 0 {
return
}
d.mu.Lock()
defer d.mu.Unlock()
d.history.Append(events)
lastRev := events[len(events)-1].Kv.ModRevision
for w, nextRev := range d.activeWatchers {
start := len(events)
for i, ev := range events {
if ev.Kv.ModRevision >= nextRev {
start = i
break
}
}
if start == len(events) {
continue
}
if !w.enqueueEvent(events[start:]) { // overflow → lagging
d.laggingWatchers[w] = nextRev
delete(d.activeWatchers, w)
} else {
d.activeWatchers[w] = lastRev + 1
}
}
}
// Purge is called when etcd compaction invalidates our cached history, so clients should resubscribe.
func (d *demux) Purge() {
d.mu.Lock()
defer d.mu.Unlock()
d.history.RebaseHistory()
for w := range d.activeWatchers {
w.Stop()
}
for w := range d.laggingWatchers {
w.Stop()
}
d.activeWatchers = make(map[*watcher]int64)
d.laggingWatchers = make(map[*watcher]int64)
}
func (d *demux) resyncLaggingWatchers() {
d.mu.Lock()
defer d.mu.Unlock()
oldestRev := d.history.PeekOldest()
for w, nextRev := range d.laggingWatchers {
if oldestRev != 0 && nextRev < oldestRev {
w.Stop()
delete(d.laggingWatchers, w)
continue
}
// TODO: re-enable keypredicate in Filter when nonzero startRev or performance tuning is needed
missed := d.history.Filter(nextRev)
enqueueFailed := false
for _, eventBatch := range missed {
if !w.enqueueEvent(eventBatch) { // buffer overflow: watcher still lagging
enqueueFailed = true
break
}
nextRev = eventBatch[0].Kv.ModRevision + 1
}
if !enqueueFailed {
delete(d.laggingWatchers, w)
d.activeWatchers[w] = nextRev
} else {
d.laggingWatchers[w] = nextRev
}
}
}
func (d *demux) PeekOldest() int64 {
d.mu.RLock()
defer d.mu.RUnlock()
return d.history.PeekOldest()
}

165
cache/demux_test.go vendored
View File

@ -1,165 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"go.etcd.io/etcd/api/v3/mvccpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
func TestBroadcastBatching(t *testing.T) {
tests := []struct {
name string
input []int64
wantRevs []int64
wantSizes []int
}{
{
name: "two groups",
input: []int64{14, 14, 15, 15, 15},
wantRevs: []int64{14},
wantSizes: []int{5},
},
{
name: "single group",
input: []int64{7, 7, 7},
wantRevs: []int64{7},
wantSizes: []int{3},
},
{
name: "all distinct",
input: []int64{1, 2, 3},
wantRevs: []int64{1},
wantSizes: []int{3},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
d := newDemux(16, 10*time.Millisecond)
w := newWatcher(len(tt.input)+1, nil)
d.Register(w, 0)
d.Broadcast(eventRevs(tt.input...))
gotRevs, gotSizes := readBatches(t, w, len(tt.wantRevs))
if diff := cmp.Diff(tt.wantRevs, gotRevs); diff != "" {
t.Fatalf("revision mismatch (-want +got):\n%s", diff)
}
if diff := cmp.Diff(tt.wantSizes, gotSizes); diff != "" {
t.Fatalf("batch size mismatch (-want +got):\n%s", diff)
}
})
}
}
func TestSlowWatcherResync(t *testing.T) {
tests := []struct {
name string
input []int64
wantInitialRevs []int64
wantInitialSizes []int
wantResyncRevs []int64
wantResyncSizes []int
}{
{
name: "single event overflow",
input: []int64{1, 2, 3},
wantInitialRevs: []int64{1},
wantInitialSizes: []int{3},
wantResyncRevs: []int64{},
wantResyncSizes: []int{},
},
{
name: "multi events batch overflow",
input: []int64{10, 10, 11, 12, 12},
wantInitialRevs: []int64{10},
wantInitialSizes: []int{5},
wantResyncRevs: []int64{},
wantResyncSizes: []int{},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
d := newDemux(16, 10*time.Millisecond)
w := newWatcher(1, nil)
d.Register(w, 0)
d.Broadcast(eventRevs(tt.input...))
gotInitRevs, gotInitSizes := readBatches(t, w, len(tt.wantInitialRevs))
if diff := cmp.Diff(tt.wantInitialRevs, gotInitRevs); diff != "" {
t.Fatalf("initial revs mismatch (-want +got):\n%s", diff)
}
if diff := cmp.Diff(tt.wantInitialSizes, gotInitSizes); diff != "" {
t.Fatalf("initial batch sizes mismatch (-want +got):\n%s", diff)
}
gotRevs, gotSizes := make([]int64, 0, len(tt.wantResyncRevs)), make([]int, 0, len(tt.wantResyncRevs))
for len(gotRevs) < len(tt.wantResyncRevs) {
d.resyncLaggingWatchers()
revs, sizes := readBatches(t, w, 1)
gotRevs = append(gotRevs, revs...)
gotSizes = append(gotSizes, sizes...)
}
if diff := cmp.Diff(tt.wantResyncRevs, gotRevs); diff != "" {
t.Fatalf("resync revs mismatch (-want +got):\n%s", diff)
}
if diff := cmp.Diff(tt.wantResyncSizes, gotSizes); diff != "" {
t.Fatalf("resync batch sizes mismatch (-want +got):\n%s", diff)
}
})
}
}
func eventRevs(revs ...int64) []*clientv3.Event {
events := make([]*clientv3.Event, 0, len(revs))
for _, r := range revs {
kv := &mvccpb.KeyValue{
Key: []byte("k"),
Value: []byte("v"),
ModRevision: r,
}
events = append(events, &clientv3.Event{
Type: clientv3.EventTypePut,
Kv: kv,
})
}
return events
}
func readBatches(t *testing.T, w *watcher, n int) (revs []int64, sizes []int) {
t.Helper()
timeout := time.After(2 * time.Second)
for len(revs) < n {
select {
case batch := <-w.eventQueue:
revs = append(revs, batch[0].Kv.ModRevision)
sizes = append(sizes, len(batch))
case <-timeout:
t.Fatalf("timed out waiting for %d batches; got %d", n, len(revs))
}
}
return revs, sizes
}

35
cache/go.mod vendored
View File

@ -1,35 +0,0 @@
module go.etcd.io/etcd/cache/v3
go 1.24
toolchain go1.24.5
require (
github.com/google/go-cmp v0.7.0
go.etcd.io/etcd/api/v3 v3.6.0-alpha.0
go.etcd.io/etcd/client/v3 v3.6.0-alpha.0
)
require (
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.74.2 // indirect
google.golang.org/protobuf v1.36.6 // indirect
)
replace (
go.etcd.io/etcd/api/v3 => ../api
go.etcd.io/etcd/client/pkg/v3 => ../client/pkg
go.etcd.io/etcd/client/v3 => ../client/v3
)

107
cache/go.sum vendored
View File

@ -1,107 +0,0 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

52
cache/predicate.go vendored
View File

@ -1,52 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import "bytes"
type Prefix string
func (prefix Prefix) Match(key []byte) bool {
if prefix == "" {
return true
}
prefixLen := len(prefix)
return len(key) >= prefixLen && string(key[:prefixLen]) == string(prefix)
}
func ExactKey(key []byte) KeyPredicate {
return func(k []byte) bool { return bytes.Equal(k, key) }
}
func FromKey(start []byte) KeyPredicate {
return func(k []byte) bool { return bytes.Compare(k, start) >= 0 }
}
func Range(start, end []byte) KeyPredicate {
return func(k []byte) bool {
return bytes.Compare(k, start) >= 0 &&
bytes.Compare(k, end) < 0
}
}
func KeyPredForRange(start, end []byte) KeyPredicate {
if len(end) == 0 {
return ExactKey(start)
}
if len(end) == 1 && end[0] == 0 {
return FromKey(start)
}
return Range(start, end)
}

115
cache/ringbuffer.go vendored
View File

@ -1,115 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"fmt"
clientv3 "go.etcd.io/etcd/client/v3"
)
type ringBuffer struct {
buffer []batch
// head is the index immediately after the last non-empty entry in the buffer (i.e., the next write position).
head, tail, size int
}
// batch groups all events that share one ModRevision.
type batch struct {
rev int64
events []*clientv3.Event
}
type KeyPredicate = func([]byte) bool
func newRingBuffer(capacity int) *ringBuffer {
// assume capacity > 0 validated by Cache
return &ringBuffer{
buffer: make([]batch, capacity),
}
}
func (r *ringBuffer) Append(events []*clientv3.Event) {
start := 0
for end := 1; end < len(events); end++ {
if events[end].Kv.ModRevision != events[start].Kv.ModRevision {
r.append(batch{
rev: events[start].Kv.ModRevision,
events: events[start:end],
})
start = end
}
}
if start < len(events) {
r.append(batch{
rev: events[start].Kv.ModRevision,
events: events[start:],
})
}
}
func (r *ringBuffer) append(b batch) {
if len(b.events) == 0 {
return
}
if r.size == len(r.buffer) {
r.tail = (r.tail + 1) % len(r.buffer)
} else {
r.size++
}
r.buffer[r.head] = b
r.head = (r.head + 1) % len(r.buffer)
}
// Filter returns all events in the buffer whose ModRevision is >= minRev.
// TODO: use binary search on the ring buffer to locate the first entry >= nextRev instead of a full scan
func (r *ringBuffer) Filter(minRev int64) (eventBatches [][]*clientv3.Event) {
eventBatches = make([][]*clientv3.Event, 0, r.size)
for n, i := 0, r.tail; n < r.size; n, i = n+1, (i+1)%len(r.buffer) {
eventBatch := r.buffer[i]
if eventBatch.events == nil {
panic(fmt.Sprintf("ringBuffer.Filter: unexpected nil eventBatch at index %d", i))
}
if eventBatch.rev >= minRev {
eventBatches = append(eventBatches, eventBatch.events)
}
}
return eventBatches
}
// PeekLatest returns the most recently-appended event (or nil if empty).
func (r *ringBuffer) PeekLatest() int64 {
if r.size == 0 {
return 0
}
idx := (r.head - 1 + len(r.buffer)) % len(r.buffer)
return r.buffer[idx].rev
}
// PeekOldest returns the oldest event currently stored (or nil if empty).
func (r *ringBuffer) PeekOldest() int64 {
if r.size == 0 {
return 0
}
return r.buffer[r.tail].rev
}
func (r *ringBuffer) RebaseHistory() {
r.head, r.tail, r.size = 0, 0, 0
for i := range r.buffer {
r.buffer[i] = batch{}
}
}

View File

@ -1,308 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
"go.etcd.io/etcd/api/v3/mvccpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
func TestPeekLatestAndOldest(t *testing.T) {
tests := []struct {
name string
capacity int
revs []int64
wantLatestRev int64
wantOldestRev int64
}{
{
name: "empty_buffer",
capacity: 4,
revs: nil,
wantLatestRev: 0,
wantOldestRev: 0,
},
{
name: "single_element",
capacity: 8,
revs: []int64{1},
wantLatestRev: 1,
wantOldestRev: 1,
},
{
name: "ascending_fill",
capacity: 4,
revs: []int64{1, 2, 3, 4},
wantLatestRev: 4,
wantOldestRev: 1,
},
{
name: "overwrite_when_full",
capacity: 3,
revs: []int64{5, 6, 7, 8},
wantLatestRev: 8,
wantOldestRev: 6,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
rb := newRingBuffer(tt.capacity)
for _, r := range tt.revs {
batch, err := makeEventBatch(r, "k", 1)
if err != nil {
t.Fatalf("makeEventBatch(%d, k, 1) failed: %v", r, err)
}
rb.Append(batch)
}
latestRev := rb.PeekLatest()
oldestRev := rb.PeekOldest()
gotLatestRev := latestRev
gotOldestRev := oldestRev
if tt.wantLatestRev != gotLatestRev {
t.Fatalf("PeekLatest()=%d, want=%d", gotLatestRev, tt.wantLatestRev)
}
if tt.wantOldestRev != gotOldestRev {
t.Fatalf("PeekOldest()=%d, want=%d", gotOldestRev, tt.wantOldestRev)
}
})
}
}
func TestFilter(t *testing.T) {
tests := []struct {
name string
capacity int
revs []int64
minRev int64
wantFilteredRevs []int64
wantLatestRev int64
}{
{
name: "no_filter",
capacity: 5,
revs: []int64{1, 2, 3},
minRev: 0,
wantFilteredRevs: []int64{1, 2, 3},
wantLatestRev: 3,
},
{
name: "partial_match",
capacity: 5,
revs: []int64{10, 11, 12, 13},
minRev: 12,
wantFilteredRevs: []int64{12, 13},
wantLatestRev: 13,
},
{
name: "filter_when_full",
capacity: 3,
revs: []int64{20, 21, 22, 23, 24},
minRev: 23,
wantFilteredRevs: []int64{23, 24},
wantLatestRev: 24,
},
{
name: "none_match",
capacity: 4,
revs: []int64{30, 31},
minRev: 100,
wantFilteredRevs: []int64{},
wantLatestRev: 31,
},
{
name: "empty_buffer",
capacity: 3,
revs: nil,
minRev: 0,
wantFilteredRevs: []int64{},
wantLatestRev: 0,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
rb := newRingBuffer(tt.capacity)
for _, r := range tt.revs {
batch, err := makeEventBatch(r, "k", 11)
if err != nil {
t.Fatalf("makeEventBatch(%d, k, 11) failed: %v", r, err)
}
rb.Append(batch)
}
gotBatches := rb.Filter(tt.minRev)
gotRevs := make([]int64, len(gotBatches))
for i, b := range gotBatches {
gotRevs[i] = b[0].Kv.ModRevision
}
if diff := cmp.Diff(tt.wantFilteredRevs, gotRevs); diff != "" {
t.Fatalf("Filter() revisions mismatch (-want +got):\n%s", diff)
}
})
}
}
func TestAtomicOrdered(t *testing.T) {
tests := []struct {
name string
capacity int
inputs []struct {
rev int64
key string
size int
}
wantRev []int64
wantSize []int
}{
{
name: "unfiltered",
capacity: 5,
inputs: []struct {
rev int64
key string
size int
}{
{5, "a", 1},
{10, "b", 3},
{15, "c", 7},
{20, "d", 11},
},
wantRev: []int64{5, 10, 15, 20},
wantSize: []int{1, 3, 7, 11},
},
{
name: "across_wrap",
capacity: 3,
inputs: []struct {
rev int64
key string
size int
}{
{1, "a", 2},
{2, "b", 1},
{3, "c", 3},
{4, "d", 7},
},
wantRev: []int64{2, 3, 4},
wantSize: []int{1, 3, 7},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
rb := newRingBuffer(tt.capacity)
for _, in := range tt.inputs {
batch, err := makeEventBatch(in.rev, in.key, in.size)
if err != nil {
t.Fatalf("makeEventBatch(%d, k, 1) failed: %v", in.rev, err)
}
rb.Append(batch)
}
gotBatches := rb.Filter(0)
if len(gotBatches) != len(tt.wantRev) {
t.Fatalf("len(got) = %d, want %d", len(gotBatches), len(tt.wantRev))
}
for i, b := range gotBatches {
if b[0].Kv.ModRevision != tt.wantRev[i] {
t.Errorf("at idx %d: rev = %d, want %d", i, b[0].Kv.ModRevision, tt.wantRev[i])
}
if batchSize := len(b); batchSize != tt.wantSize[i] {
t.Errorf("at rev %d: events.len = %d, want %d", b[0].Kv.ModRevision, batchSize, tt.wantSize[i])
}
}
})
}
}
func TestRebaseHistory(t *testing.T) {
tests := []struct {
name string
revs []int64
}{
{
name: "rebase_empty_buffer",
revs: nil,
},
{
name: "rebase_after_data",
revs: []int64{7, 8, 9},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
rb := newRingBuffer(4)
for _, r := range tt.revs {
batch, err := makeEventBatch(r, "k", 1)
if err != nil {
t.Fatalf("makeEventBatch(%d, k, 1) failed: %v", r, err)
}
rb.Append(batch)
}
rb.RebaseHistory()
oldestRev := rb.PeekOldest()
latestRev := rb.PeekLatest()
if oldestRev != 0 {
t.Fatalf("PeekOldest()=%d, want=%d", oldestRev, 0)
}
if latestRev != 0 {
t.Fatalf("PeekLatest()=%d, want=%d", latestRev, 0)
}
batches := rb.Filter(0)
if len(batches) != 0 {
t.Fatalf("Filter() len(events)=%d, want=%d", len(batches), 0)
}
})
}
}
func makeEventBatch(rev int64, key string, batchSize int) ([]*clientv3.Event, error) {
if batchSize < 0 {
return nil, fmt.Errorf("invalid batchSize %d", batchSize)
}
events := make([]*clientv3.Event, batchSize)
for i := range events {
events[i] = &clientv3.Event{
Kv: &mvccpb.KeyValue{
Key: []byte(fmt.Sprintf("%s-%d", key, i)),
ModRevision: rev,
},
}
}
return events, nil
}

145
cache/store.go vendored
View File

@ -1,145 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"bytes"
"fmt"
"sort"
"sync"
"go.etcd.io/etcd/api/v3/mvccpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
var ErrNotInitialized = fmt.Errorf("cache: store not initialized")
type store struct {
mu sync.RWMutex
kvs map[string]*mvccpb.KeyValue
latestRev int64
}
func newStore() *store {
return &store{kvs: make(map[string]*mvccpb.KeyValue)}
}
func (s *store) Get(startKey, endKey []byte) ([]*mvccpb.KeyValue, int64, error) {
s.mu.RLock()
defer s.mu.RUnlock()
if s.latestRev == 0 {
return nil, 0, ErrNotInitialized
}
var out []*mvccpb.KeyValue
switch {
case len(endKey) == 0:
out = s.getSingle(startKey)
case isPrefixScan(endKey):
out = s.scanPrefix(startKey)
default:
out = s.scanRange(startKey, endKey)
}
sort.Slice(out, func(i, j int) bool {
return bytes.Compare(out[i].Key, out[j].Key) < 0 // default: lexicographical, ascendingbykey sort
})
return out, s.latestRev, nil
}
func (s *store) Restore(kvs []*mvccpb.KeyValue, rev int64) {
s.mu.Lock()
defer s.mu.Unlock()
s.kvs = make(map[string]*mvccpb.KeyValue, len(kvs))
for _, kv := range kvs {
s.kvs[string(kv.Key)] = kv
}
s.latestRev = rev
}
// Reset purges all in-memory state when the upstream watch stream reports compaction.
func (s *store) Reset() {
s.mu.Lock()
defer s.mu.Unlock()
s.kvs = make(map[string]*mvccpb.KeyValue)
s.latestRev = 0
}
func (s *store) Apply(events []*clientv3.Event) error {
s.mu.Lock()
defer s.mu.Unlock()
for _, ev := range events {
if ev.Kv.ModRevision < s.latestRev {
return fmt.Errorf("cache: stale event batch (rev %d < latest %d)", ev.Kv.ModRevision, s.latestRev)
}
}
for _, ev := range events {
switch ev.Type {
case clientv3.EventTypeDelete:
delete(s.kvs, string(ev.Kv.Key))
case clientv3.EventTypePut:
s.kvs[string(ev.Kv.Key)] = ev.Kv
}
if ev.Kv.ModRevision > s.latestRev {
s.latestRev = ev.Kv.ModRevision
}
}
return nil
}
func (s *store) LatestRev() int64 {
s.mu.RLock()
defer s.mu.RUnlock()
return s.latestRev
}
// getSingle fetches one key or nil
func (s *store) getSingle(key []byte) []*mvccpb.KeyValue {
if kv, ok := s.kvs[string(key)]; ok {
return []*mvccpb.KeyValue{kv}
}
return nil
}
// scanPrefix returns all keys >= startKey
func (s *store) scanPrefix(startKey []byte) []*mvccpb.KeyValue {
var res []*mvccpb.KeyValue
for _, kv := range s.kvs {
if bytes.Compare(kv.Key, startKey) >= 0 {
res = append(res, kv)
}
}
return res
}
// scanRange returns all keys in [startKey, endKey)
func (s *store) scanRange(startKey, endKey []byte) []*mvccpb.KeyValue {
var res []*mvccpb.KeyValue
for _, kv := range s.kvs {
if bytes.Compare(kv.Key, startKey) >= 0 && bytes.Compare(kv.Key, endKey) < 0 {
res = append(res, kv)
}
}
return res
}
// isPrefixScan detects endKey=={0} semantics
func isPrefixScan(endKey []byte) bool {
return len(endKey) == 1 && endKey[0] == 0
}

70
cache/watcher.go vendored
View File

@ -1,70 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"sync/atomic"
clientv3 "go.etcd.io/etcd/client/v3"
)
// watcher holds one clients buffered stream of events.
type watcher struct {
eventQueue chan []*clientv3.Event
keyPred KeyPredicate
stopped int32
done chan struct{} // closed together with Stop()
}
func newWatcher(bufSize int, pred KeyPredicate) *watcher {
return &watcher{
eventQueue: make(chan []*clientv3.Event, bufSize),
keyPred: pred,
done: make(chan struct{}),
}
}
// true -> events delivered (or filtered/duplicate)
// false -> buffer full (caller should mark watcher “lagging”)
func (w *watcher) enqueueEvent(eventBatch []*clientv3.Event) bool {
if w.keyPred != nil {
filtered := make([]*clientv3.Event, 0, len(eventBatch))
for _, event := range eventBatch {
if w.keyPred(event.Kv.Key) {
filtered = append(filtered, event)
}
}
if len(filtered) == 0 {
return true
}
eventBatch = filtered
}
select {
case w.eventQueue <- eventBatch:
return true
default:
return false
}
}
// Stop closes the event channel atomically.
func (w *watcher) Stop() {
if atomic.CompareAndSwapInt32(&w.stopped, 0, 1) {
close(w.eventQueue)
close(w.done)
}
}
func (w *watcher) Done() <-chan struct{} { return w.done }

View File

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2020 The etcd Authors Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -23,7 +23,7 @@ import (
) )
func TestLockAndUnlock(t *testing.T) { func TestLockAndUnlock(t *testing.T) {
f, err := os.CreateTemp(t.TempDir(), "lock") f, err := os.CreateTemp("", "lock")
require.NoError(t, err) require.NoError(t, err)
f.Close() f.Close()
defer func() { defer func() {

View File

@ -1,21 +1,21 @@
module go.etcd.io/etcd/client/pkg/v3 module go.etcd.io/etcd/client/pkg/v3
go 1.24 go 1.23.0
toolchain go1.24.5 toolchain go1.23.11
require ( require (
github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/go-systemd/v22 v22.5.0
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/sys v0.34.0 golang.org/x/sys v0.31.0
) )
require ( require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

View File

@ -1,8 +1,8 @@
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@ -12,11 +12,11 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@ -25,8 +25,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@ -19,6 +19,9 @@ import (
"os" "os"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.etcd.io/etcd/client/pkg/v3/verify" "go.etcd.io/etcd/client/pkg/v3/verify"
) )
@ -28,12 +31,15 @@ func BeforeTest(tb testing.TB) {
revertVerifyFunc := verify.EnableAllVerifications() revertVerifyFunc := verify.EnableAllVerifications()
path, err := os.Getwd()
require.NoError(tb, err)
tempDir := tb.TempDir() tempDir := tb.TempDir()
tb.Chdir(tempDir) require.NoError(tb, os.Chdir(tempDir))
tb.Logf("Changing working directory to: %s", tempDir) tb.Logf("Changing working directory to: %s", tempDir)
tb.Cleanup(func() { tb.Cleanup(func() {
revertVerifyFunc() revertVerifyFunc()
assert.NoError(tb, os.Chdir(path))
}) })
} }

View File

@ -47,6 +47,7 @@ func NewURLs(strs []string) (URLs, error) {
return nil, fmt.Errorf("URL must not contain a path: %s", in) return nil, fmt.Errorf("URL must not contain a path: %s", in)
} }
case "unix", "unixs": case "unix", "unixs":
break
default: default:
return nil, fmt.Errorf("URL scheme must be http, https, unix, or unixs: %s", in) return nil, fmt.Errorf("URL scheme must be http, https, unix, or unixs: %s", in)
} }

View File

@ -66,18 +66,9 @@ func DisableVerifications() func() {
// Verify performs verification if the assertions are enabled. // Verify performs verification if the assertions are enabled.
// In the default setup running in tests and skipped in the production code. // In the default setup running in tests and skipped in the production code.
func Verify(msg string, f VerifyFunc) { func Verify(f func()) {
if IsVerificationEnabled(envVerifyValueAssert) { if IsVerificationEnabled(envVerifyValueAssert) {
ok, details := f() f()
verifier(ok, msg, details)
}
}
type VerifyFunc func() (condition bool, details map[string]any)
func verifier(condition bool, msg string, details map[string]any) {
if !condition {
panic(fmt.Sprintf("%s. details: %v.", msg, details))
} }
} }

View File

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2020 The etcd Authors Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -43,7 +43,6 @@ import (
var ( var (
ErrNoAvailableEndpoints = errors.New("etcdclient: no available endpoints") ErrNoAvailableEndpoints = errors.New("etcdclient: no available endpoints")
ErrOldCluster = errors.New("etcdclient: old cluster version") ErrOldCluster = errors.New("etcdclient: old cluster version")
ErrMutuallyExclusiveCfg = errors.New("Username/Password and Token configurations are mutually exclusive")
) )
// Client provides and manages an etcd v3 client session. // Client provides and manages an etcd v3 client session.
@ -70,10 +69,7 @@ type Client struct {
// Username is a user name for authentication. // Username is a user name for authentication.
Username string Username string
// Password is a password for authentication. // Password is a password for authentication.
Password string Password string
// Token is a JWT used for authentication instead of a password.
Token string
authTokenBundle credentials.PerRPCCredentialsBundle authTokenBundle credentials.PerRPCCredentialsBundle
callOpts []grpc.CallOption callOpts []grpc.CallOption
@ -201,8 +197,10 @@ func (c *Client) Sync(ctx context.Context) error {
} }
// The linearizable `MemberList` returned successfully, so the // The linearizable `MemberList` returned successfully, so the
// endpoints shouldn't be empty. // endpoints shouldn't be empty.
verify.Verify("empty endpoints returned from etcd cluster", func() (bool, map[string]any) { verify.Verify(func() {
return len(eps) > 0, nil if len(eps) == 0 {
panic("empty endpoints returned from etcd cluster")
}
}) })
c.SetEndpoints(eps...) c.SetEndpoints(eps...)
c.lg.Debug("set etcd endpoints by autoSync", zap.Strings("endpoints", eps)) c.lg.Debug("set etcd endpoints by autoSync", zap.Strings("endpoints", eps))
@ -290,11 +288,6 @@ func (c *Client) Dial(ep string) (*grpc.ClientConn, error) {
func (c *Client) getToken(ctx context.Context) error { func (c *Client) getToken(ctx context.Context) error {
var err error // return last error in a case of fail var err error // return last error in a case of fail
if c.Token != "" {
c.authTokenBundle.UpdateAuthToken(c.Token)
return nil
}
if c.Username == "" || c.Password == "" { if c.Username == "" || c.Password == "" {
return nil return nil
} }
@ -383,10 +376,6 @@ func newClient(cfg *Config) (*Client, error) {
creds = credentials.NewTransportCredential(cfg.TLS) creds = credentials.NewTransportCredential(cfg.TLS)
} }
if cfg.Token != "" && (cfg.Username != "" || cfg.Password != "") {
return nil, ErrMutuallyExclusiveCfg
}
// use a temporary skeleton client to bootstrap first connection // use a temporary skeleton client to bootstrap first connection
baseCtx := context.TODO() baseCtx := context.TODO()
if cfg.Context != nil { if cfg.Context != nil {
@ -425,12 +414,6 @@ func newClient(cfg *Config) (*Client, error) {
client.Password = cfg.Password client.Password = cfg.Password
client.authTokenBundle = credentials.NewPerRPCCredentialBundle() client.authTokenBundle = credentials.NewPerRPCCredentialBundle()
} }
if cfg.Token != "" {
client.Token = cfg.Token
client.authTokenBundle = credentials.NewPerRPCCredentialBundle()
}
if cfg.MaxCallSendMsgSize > 0 || cfg.MaxCallRecvMsgSize > 0 { if cfg.MaxCallSendMsgSize > 0 || cfg.MaxCallRecvMsgSize > 0 {
if cfg.MaxCallRecvMsgSize > 0 && cfg.MaxCallSendMsgSize > cfg.MaxCallRecvMsgSize { if cfg.MaxCallRecvMsgSize > 0 && cfg.MaxCallSendMsgSize > cfg.MaxCallRecvMsgSize {
return nil, fmt.Errorf("gRPC message recv limit (%d bytes) must be greater than send limit (%d bytes)", cfg.MaxCallRecvMsgSize, cfg.MaxCallSendMsgSize) return nil, fmt.Errorf("gRPC message recv limit (%d bytes) must be greater than send limit (%d bytes)", cfg.MaxCallRecvMsgSize, cfg.MaxCallSendMsgSize)

View File

@ -196,18 +196,18 @@ func TestBackoffJitterFraction(t *testing.T) {
func TestIsHaltErr(t *testing.T) { func TestIsHaltErr(t *testing.T) {
assert.Truef(t, assert.Truef(t,
isHaltErr(t.Context(), errors.New("etcdserver: some etcdserver error")), isHaltErr(context.TODO(), errors.New("etcdserver: some etcdserver error")),
"error created by errors.New should be unavailable error", "error created by errors.New should be unavailable error",
) )
assert.Falsef(t, assert.Falsef(t,
isHaltErr(t.Context(), rpctypes.ErrGRPCStopped), isHaltErr(context.TODO(), rpctypes.ErrGRPCStopped),
`error "%v" should not be halt error`, rpctypes.ErrGRPCStopped, `error "%v" should not be halt error`, rpctypes.ErrGRPCStopped,
) )
assert.Falsef(t, assert.Falsef(t,
isHaltErr(t.Context(), rpctypes.ErrGRPCNoLeader), isHaltErr(context.TODO(), rpctypes.ErrGRPCNoLeader),
`error "%v" should not be halt error`, rpctypes.ErrGRPCNoLeader, `error "%v" should not be halt error`, rpctypes.ErrGRPCNoLeader,
) )
ctx, cancel := context.WithCancel(t.Context()) ctx, cancel := context.WithCancel(context.TODO())
assert.Falsef(t, assert.Falsef(t,
isHaltErr(ctx, nil), isHaltErr(ctx, nil),
"no error and active context should be halt error", "no error and active context should be halt error",
@ -221,18 +221,18 @@ func TestIsHaltErr(t *testing.T) {
func TestIsUnavailableErr(t *testing.T) { func TestIsUnavailableErr(t *testing.T) {
assert.Falsef(t, assert.Falsef(t,
isUnavailableErr(t.Context(), errors.New("etcdserver: some etcdserver error")), isUnavailableErr(context.TODO(), errors.New("etcdserver: some etcdserver error")),
"error created by errors.New should not be unavailable error", "error created by errors.New should not be unavailable error",
) )
assert.Truef(t, assert.Truef(t,
isUnavailableErr(t.Context(), rpctypes.ErrGRPCStopped), isUnavailableErr(context.TODO(), rpctypes.ErrGRPCStopped),
`error "%v" should be unavailable error`, rpctypes.ErrGRPCStopped, `error "%v" should be unavailable error`, rpctypes.ErrGRPCStopped,
) )
assert.Falsef(t, assert.Falsef(t,
isUnavailableErr(t.Context(), rpctypes.ErrGRPCNotCapable), isUnavailableErr(context.TODO(), rpctypes.ErrGRPCNotCapable),
"error %v should not be unavailable error", rpctypes.ErrGRPCNotCapable, "error %v should not be unavailable error", rpctypes.ErrGRPCNotCapable,
) )
ctx, cancel := context.WithCancel(t.Context()) ctx, cancel := context.WithCancel(context.TODO())
assert.Falsef(t, assert.Falsef(t,
isUnavailableErr(ctx, nil), isUnavailableErr(ctx, nil),
"no error and active context should not be unavailable error", "no error and active context should not be unavailable error",
@ -245,7 +245,7 @@ func TestIsUnavailableErr(t *testing.T) {
} }
func TestCloseCtxClient(t *testing.T) { func TestCloseCtxClient(t *testing.T) {
ctx := t.Context() ctx := context.Background()
c := NewCtxClient(ctx) c := NewCtxClient(ctx)
err := c.Close() err := c.Close()
// Close returns ctx.toErr, a nil error means an open Done channel // Close returns ctx.toErr, a nil error means an open Done channel
@ -255,7 +255,7 @@ func TestCloseCtxClient(t *testing.T) {
} }
func TestWithLogger(t *testing.T) { func TestWithLogger(t *testing.T) {
ctx := t.Context() ctx := context.Background()
c := NewCtxClient(ctx) c := NewCtxClient(ctx)
if c.lg == nil { if c.lg == nil {
t.Errorf("unexpected nil in *zap.Logger") t.Errorf("unexpected nil in *zap.Logger")
@ -268,7 +268,7 @@ func TestWithLogger(t *testing.T) {
} }
func TestZapWithLogger(t *testing.T) { func TestZapWithLogger(t *testing.T) {
ctx := t.Context() ctx := context.Background()
lg := zap.NewNop() lg := zap.NewNop()
c := NewCtxClient(ctx, WithZapLogger(lg)) c := NewCtxClient(ctx, WithZapLogger(lg))
@ -317,75 +317,6 @@ func TestAuthTokenBundleNoOverwrite(t *testing.T) {
} }
} }
func TestNewWithOnlyJWT(t *testing.T) {
// This call in particular changes working directory to the tmp dir of
// the test. The `etcd-auth-test:1` can be created in local directory,
// not exceeding the longest allowed path on OsX.
testutil.BeforeTest(t)
// Create a mock AuthServer to handle Authenticate RPCs.
lis, err := net.Listen("unix", "etcd-auth-test:1")
if err != nil {
t.Fatal(err)
}
defer lis.Close()
addr := "unix://" + lis.Addr().String()
srv := grpc.NewServer()
// Having a token removes the need to ever call Authenticate on the
// server. If that happens then this will cause a connection failure.
etcdserverpb.RegisterAuthServer(srv, mockFailingAuthServer{})
go srv.Serve(lis)
defer srv.Stop()
c, err := NewClient(t, Config{
DialTimeout: 5 * time.Second,
Endpoints: []string{addr},
Token: "foo",
})
if err != nil {
t.Fatal(err)
}
defer c.Close()
meta, err := c.authTokenBundle.PerRPCCredentials().GetRequestMetadata(t.Context(), "")
if err != nil {
t.Errorf("Error building request metadata: %s", err)
}
if tok, ok := meta[rpctypes.TokenFieldNameGRPC]; !ok {
t.Error("Token was not successfuly set in the auth bundle")
} else if tok != "foo" {
t.Errorf("Incorrect token set in auth bundle, got '%s', expected 'foo'", tok)
}
}
func TestNewOnlyJWTExclusivity(t *testing.T) {
testutil.BeforeTest(t)
// Create a mock AuthServer to handle Authenticate RPCs.
lis, err := net.Listen("unix", "etcd-auth-test:1")
if err != nil {
t.Fatal(err)
}
defer lis.Close()
addr := "unix://" + lis.Addr().String()
srv := grpc.NewServer()
// Having a token removes the need to ever call Authenticate on the
// server. If that happens then this will cause a connection failure.
etcdserverpb.RegisterAuthServer(srv, mockFailingAuthServer{})
go srv.Serve(lis)
defer srv.Stop()
_, err = NewClient(t, Config{
DialTimeout: 5 * time.Second,
Endpoints: []string{addr},
Token: "foo",
Username: "user",
Password: "pass",
})
require.ErrorIs(t, ErrMutuallyExclusiveCfg, err)
}
func TestSyncFiltersMembers(t *testing.T) { func TestSyncFiltersMembers(t *testing.T) {
c, _ := NewClient(t, Config{Endpoints: []string{"http://254.0.0.1:12345"}}) c, _ := NewClient(t, Config{Endpoints: []string{"http://254.0.0.1:12345"}})
defer c.Close() defer c.Close()
@ -396,7 +327,7 @@ func TestSyncFiltersMembers(t *testing.T) {
{ID: 2, Name: "isStartedAndNotLearner", ClientURLs: []string{"http://254.0.0.3:12345"}, IsLearner: false}, {ID: 2, Name: "isStartedAndNotLearner", ClientURLs: []string{"http://254.0.0.3:12345"}, IsLearner: false},
}, },
} }
c.Sync(t.Context()) c.Sync(context.Background())
endpoints := c.Endpoints() endpoints := c.Endpoints()
if len(endpoints) != 1 || endpoints[0] != "http://254.0.0.3:12345" { if len(endpoints) != 1 || endpoints[0] != "http://254.0.0.3:12345" {
@ -490,7 +421,7 @@ func TestClientRejectOldCluster(t *testing.T) {
endpointToVersion[tt.endpoints[j]] = tt.versions[j] endpointToVersion[tt.endpoints[j]] = tt.versions[j]
} }
c := &Client{ c := &Client{
ctx: t.Context(), ctx: context.Background(),
endpoints: tt.endpoints, endpoints: tt.endpoints,
epMu: new(sync.RWMutex), epMu: new(sync.RWMutex),
Maintenance: &mockMaintenance{ Maintenance: &mockMaintenance{
@ -545,14 +476,6 @@ func (mm mockMaintenance) Downgrade(ctx context.Context, action DowngradeAction,
return nil, nil return nil, nil
} }
type mockFailingAuthServer struct {
*etcdserverpb.UnimplementedAuthServer
}
func (mockFailingAuthServer) Authenticate(context.Context, *etcdserverpb.AuthenticateRequest) (*etcdserverpb.AuthenticateResponse, error) {
return nil, errors.New("this auth server always fails")
}
type mockAuthServer struct { type mockAuthServer struct {
*etcdserverpb.UnimplementedAuthServer *etcdserverpb.UnimplementedAuthServer
} }

View File

@ -66,9 +66,6 @@ type Config struct {
// Password is a password for authentication. // Password is a password for authentication.
Password string `json:"password"` Password string `json:"password"`
// Token is a JWT used for authentication instead of a password.
Token string `json:"token"`
// RejectOldCluster when set will refuse to create a client against an outdated cluster. // RejectOldCluster when set will refuse to create a client against an outdated cluster.
RejectOldCluster bool `json:"reject-old-cluster"` RejectOldCluster bool `json:"reject-old-cluster"`
@ -133,7 +130,6 @@ type SecureConfig struct {
type AuthConfig struct { type AuthConfig struct {
Username string `json:"username"` Username string `json:"username"`
Password string `json:"password"` Password string `json:"password"`
Token string `json:"token"`
} }
func (cs *ConfigSpec) Clone() *ConfigSpec { func (cs *ConfigSpec) Clone() *ConfigSpec {
@ -161,7 +157,7 @@ func (cs *ConfigSpec) Clone() *ConfigSpec {
} }
func (cfg AuthConfig) Empty() bool { func (cfg AuthConfig) Empty() bool {
return cfg.Username == "" && cfg.Password == "" && cfg.Token == "" return cfg.Username == "" && cfg.Password == ""
} }
// NewClientConfig creates a Config based on the provided ConfigSpec. // NewClientConfig creates a Config based on the provided ConfigSpec.
@ -184,7 +180,6 @@ func NewClientConfig(confSpec *ConfigSpec, lg *zap.Logger) (*Config, error) {
if confSpec.Auth != nil { if confSpec.Auth != nil {
cfg.Username = confSpec.Auth.Username cfg.Username = confSpec.Auth.Username
cfg.Password = confSpec.Auth.Password cfg.Password = confSpec.Auth.Password
cfg.Token = confSpec.Auth.Token
} }
return cfg, nil return cfg, nil

View File

@ -71,25 +71,6 @@ func TestNewClientConfig(t *testing.T) {
Password: "changeme", Password: "changeme",
}, },
}, },
{
name: "JWT specified",
spec: ConfigSpec{
Endpoints: []string{"http://192.168.0.12:2379"},
DialTimeout: 1 * time.Second,
KeepAliveTime: 4 * time.Second,
KeepAliveTimeout: 6 * time.Second,
Auth: &AuthConfig{
Token: "test",
},
},
expectedConf: Config{
Endpoints: []string{"http://192.168.0.12:2379"},
DialTimeout: 1 * time.Second,
DialKeepAliveTime: 4 * time.Second,
DialKeepAliveTimeout: 6 * time.Second,
Token: "test",
},
},
{ {
name: "default secure transport", name: "default secure transport",
spec: ConfigSpec{ spec: ConfigSpec{

View File

@ -15,6 +15,7 @@
package credentials package credentials
import ( import (
"context"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -24,7 +25,7 @@ import (
func TestUpdateAuthToken(t *testing.T) { func TestUpdateAuthToken(t *testing.T) {
bundle := NewPerRPCCredentialBundle() bundle := NewPerRPCCredentialBundle()
ctx := t.Context() ctx := context.TODO()
metadataBeforeUpdate, _ := bundle.PerRPCCredentials().GetRequestMetadata(ctx) metadataBeforeUpdate, _ := bundle.PerRPCCredentials().GetRequestMetadata(ctx)
assert.Empty(t, metadataBeforeUpdate) assert.Empty(t, metadataBeforeUpdate)

View File

@ -15,6 +15,7 @@
package clientv3 package clientv3
import ( import (
"context"
"reflect" "reflect"
"testing" "testing"
@ -26,7 +27,7 @@ import (
) )
func TestMetadataWithRequireLeader(t *testing.T) { func TestMetadataWithRequireLeader(t *testing.T) {
ctx := t.Context() ctx := context.TODO()
_, ok := metadata.FromOutgoingContext(ctx) _, ok := metadata.FromOutgoingContext(ctx)
require.Falsef(t, ok, "expected no outgoing metadata ctx key") require.Falsef(t, ok, "expected no outgoing metadata ctx key")
@ -47,7 +48,7 @@ func TestMetadataWithRequireLeader(t *testing.T) {
} }
func TestMetadataWithClientAPIVersion(t *testing.T) { func TestMetadataWithClientAPIVersion(t *testing.T) {
ctx := withVersion(WithRequireLeader(t.Context())) ctx := withVersion(WithRequireLeader(context.TODO()))
md, ok := metadata.FromOutgoingContext(ctx) md, ok := metadata.FromOutgoingContext(ctx)
require.Truef(t, ok, "expected outgoing metadata ctx key") require.Truef(t, ok, "expected outgoing metadata ctx key")

View File

@ -1,47 +1,44 @@
module go.etcd.io/etcd/client/v3 module go.etcd.io/etcd/client/v3
go 1.24 go 1.23.0
toolchain go1.24.5 toolchain go1.23.11
require ( require (
github.com/coreos/go-semver v0.3.1 github.com/coreos/go-semver v0.3.1
github.com/dustin/go-humanize v1.0.1 github.com/dustin/go-humanize v1.0.1
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_golang v1.20.5
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/api/v3 v3.6.4
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.4
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
google.golang.org/grpc v1.74.2 google.golang.org/grpc v1.71.1
sigs.k8s.io/yaml v1.5.0 sigs.k8s.io/yaml v1.4.0
) )
require ( require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.65.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/text v0.27.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/protobuf v1.36.5 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@ -6,12 +6,12 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@ -19,20 +19,21 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -41,44 +42,40 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -88,20 +85,20 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -110,18 +107,18 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -60,7 +60,7 @@ func (r *EtcdManualResolver) SetEndpoints(endpoints []string) {
} }
func (r EtcdManualResolver) updateState() { func (r EtcdManualResolver) updateState() {
if getCC(r) != nil { if r.CC != nil {
eps := make([]resolver.Endpoint, len(r.endpoints)) eps := make([]resolver.Endpoint, len(r.endpoints))
for i, ep := range r.endpoints { for i, ep := range r.endpoints {
addr, serverName := endpoint.Interpret(ep) addr, serverName := endpoint.Interpret(ep)
@ -75,13 +75,3 @@ func (r EtcdManualResolver) updateState() {
r.UpdateState(state) r.UpdateState(state)
} }
} }
func getCC(r EtcdManualResolver) (cc resolver.ClientConn) {
defer func() {
if rec := recover(); rec != nil {
cc = nil
}
}()
return r.CC()
}

View File

@ -134,7 +134,7 @@ func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*C
if err != nil { if err != nil {
return nil, ContextError(ctx, err) return nil, ContextError(ctx, err)
} }
return (*CompactResponse)(resp), nil return (*CompactResponse)(resp), err
} }
func (kv *kv) Txn(ctx context.Context) Txn { func (kv *kv) Txn(ctx context.Context) Txn {

View File

@ -127,31 +127,10 @@ func (op Op) IsKeysOnly() bool { return op.keysOnly }
// IsCountOnly returns whether countOnly is set. // IsCountOnly returns whether countOnly is set.
func (op Op) IsCountOnly() bool { return op.countOnly } func (op Op) IsCountOnly() bool { return op.countOnly }
// IsSortSet returns true if WithSort is set.
func (op Op) IsSortSet() bool { return op.sort != nil }
func (op Op) IsOptsWithFromKey() bool { return op.isOptsWithFromKey } func (op Op) IsOptsWithFromKey() bool { return op.isOptsWithFromKey }
func (op Op) IsOptsWithPrefix() bool { return op.isOptsWithPrefix } func (op Op) IsOptsWithPrefix() bool { return op.isOptsWithPrefix }
// IsPrevKV returns whether WithPrevKV() is set.
func (op Op) IsPrevKV() bool { return op.prevKV }
// IsFragment returns whether WithFragment() is set.
func (op Op) IsFragment() bool { return op.fragment }
// IsProgressNotify returns whether WithProgressNotify() is set.
func (op Op) IsProgressNotify() bool { return op.progressNotify }
// IsCreatedNotify returns whether WithCreatedNotify() is set.
func (op Op) IsCreatedNotify() bool { return op.createdNotify }
// IsFilterPut returns whether WithFilterPut() is set.
func (op Op) IsFilterPut() bool { return op.filterPut }
// IsFilterDelete returns whether WithFilterDelete() is set.
func (op Op) IsFilterDelete() bool { return op.filterDelete }
// MinModRev returns the operation's minimum modify revision. // MinModRev returns the operation's minimum modify revision.
func (op Op) MinModRev() int64 { return op.minModRev } func (op Op) MinModRev() int64 { return op.minModRev }
@ -329,7 +308,7 @@ func OpTxn(cmps []Cmp, thenOps []Op, elseOps []Op) Op {
return Op{t: tTxn, cmps: cmps, thenOps: thenOps, elseOps: elseOps} return Op{t: tTxn, cmps: cmps, thenOps: thenOps, elseOps: elseOps}
} }
func OpWatch(key string, opts ...OpOption) Op { func opWatch(key string, opts ...OpOption) Op {
ret := Op{t: tRange, key: []byte(key)} ret := Op{t: tRange, key: []byte(key)}
ret.applyOpts(opts) ret.applyOpts(opts)
switch { switch {

View File

@ -76,7 +76,7 @@ func TestKvOrdering(t *testing.T) {
tt.prevRev, tt.prevRev,
sync.RWMutex{}, sync.RWMutex{},
} }
res, err := kv.Get(t.Context(), "mockKey") res, err := kv.Get(context.TODO(), "mockKey")
if err != nil { if err != nil {
t.Errorf("#%d: expected response %+v, got error %+v", i, tt.response, err) t.Errorf("#%d: expected response %+v, got error %+v", i, tt.response, err)
} }
@ -131,9 +131,9 @@ func TestTxnOrdering(t *testing.T) {
sync.RWMutex{}, sync.RWMutex{},
} }
txn := &txnOrdering{ txn := &txnOrdering{
kv.Txn(t.Context()), kv.Txn(context.Background()),
kv, kv,
t.Context(), context.Background(),
sync.Mutex{}, sync.Mutex{},
[]clientv3.Cmp{}, []clientv3.Cmp{},
[]clientv3.Op{}, []clientv3.Op{},

View File

@ -351,11 +351,11 @@ func isContextError(err error) bool {
func contextErrToGRPCErr(err error) error { func contextErrToGRPCErr(err error) error {
switch { switch {
case errors.Is(err, context.DeadlineExceeded): case errors.Is(err, context.DeadlineExceeded):
return status.Error(codes.DeadlineExceeded, err.Error()) return status.Errorf(codes.DeadlineExceeded, err.Error())
case errors.Is(err, context.Canceled): case errors.Is(err, context.Canceled):
return status.Error(codes.Canceled, err.Error()) return status.Errorf(codes.Canceled, err.Error())
default: default:
return status.Error(codes.Unknown, err.Error()) return status.Errorf(codes.Unknown, err.Error())
} }
} }

View File

@ -15,6 +15,7 @@
package clientv3 package clientv3
import ( import (
"context"
"testing" "testing"
"time" "time"
@ -43,7 +44,7 @@ func TestTxnPanics(t *testing.T) {
{ {
f: func(errc chan string) { f: func(errc chan string) {
defer df(errc) defer df(errc)
kv.Txn(t.Context()).If(cmp).If(cmp) kv.Txn(context.TODO()).If(cmp).If(cmp)
}, },
err: "cannot call If twice!", err: "cannot call If twice!",
@ -51,7 +52,7 @@ func TestTxnPanics(t *testing.T) {
{ {
f: func(errc chan string) { f: func(errc chan string) {
defer df(errc) defer df(errc)
kv.Txn(t.Context()).Then(op).If(cmp) kv.Txn(context.TODO()).Then(op).If(cmp)
}, },
err: "cannot call If after Then!", err: "cannot call If after Then!",
@ -59,7 +60,7 @@ func TestTxnPanics(t *testing.T) {
{ {
f: func(errc chan string) { f: func(errc chan string) {
defer df(errc) defer df(errc)
kv.Txn(t.Context()).Else(op).If(cmp) kv.Txn(context.TODO()).Else(op).If(cmp)
}, },
err: "cannot call If after Else!", err: "cannot call If after Else!",
@ -67,7 +68,7 @@ func TestTxnPanics(t *testing.T) {
{ {
f: func(errc chan string) { f: func(errc chan string) {
defer df(errc) defer df(errc)
kv.Txn(t.Context()).Then(op).Then(op) kv.Txn(context.TODO()).Then(op).Then(op)
}, },
err: "cannot call Then twice!", err: "cannot call Then twice!",
@ -75,7 +76,7 @@ func TestTxnPanics(t *testing.T) {
{ {
f: func(errc chan string) { f: func(errc chan string) {
defer df(errc) defer df(errc)
kv.Txn(t.Context()).Else(op).Then(op) kv.Txn(context.TODO()).Else(op).Then(op)
}, },
err: "cannot call Then after Else!", err: "cannot call Then after Else!",
@ -83,7 +84,7 @@ func TestTxnPanics(t *testing.T) {
{ {
f: func(errc chan string) { f: func(errc chan string) {
defer df(errc) defer df(errc)
kv.Txn(t.Context()).Else(op).Else(op) kv.Txn(context.TODO()).Else(op).Else(op)
}, },
err: "cannot call Else twice!", err: "cannot call Else twice!",

View File

@ -105,8 +105,8 @@ type WatchResponse struct {
closeErr error closeErr error
// CancelReason is a reason of canceling watch // cancelReason is a reason of canceling watch
CancelReason string cancelReason string
} }
// IsCreate returns true if the event tells that the key is newly created. // IsCreate returns true if the event tells that the key is newly created.
@ -127,8 +127,8 @@ func (wr *WatchResponse) Err() error {
case wr.CompactRevision != 0: case wr.CompactRevision != 0:
return v3rpc.ErrCompacted return v3rpc.ErrCompacted
case wr.Canceled: case wr.Canceled:
if len(wr.CancelReason) != 0 { if len(wr.cancelReason) != 0 {
return v3rpc.Error(status.Error(codes.FailedPrecondition, wr.CancelReason)) return v3rpc.Error(status.Error(codes.FailedPrecondition, wr.cancelReason))
} }
return v3rpc.ErrFutureRev return v3rpc.ErrFutureRev
} }
@ -296,7 +296,7 @@ func (w *watcher) newWatcherGRPCStream(inctx context.Context) *watchGRPCStream {
// Watch posts a watch request to run() and waits for a new watcher channel // Watch posts a watch request to run() and waits for a new watcher channel
func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) WatchChan { func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) WatchChan {
ow := OpWatch(key, opts...) ow := opWatch(key, opts...)
var filters []pb.WatchCreateRequest_FilterType var filters []pb.WatchCreateRequest_FilterType
if ow.filterPut { if ow.filterPut {
@ -580,7 +580,7 @@ func (w *watchGRPCStream) run() {
case pbresp := <-w.respc: case pbresp := <-w.respc:
if cur == nil || pbresp.Created || pbresp.Canceled { if cur == nil || pbresp.Created || pbresp.Canceled {
cur = pbresp cur = pbresp
} else if cur.WatchId == pbresp.WatchId { } else if cur != nil && cur.WatchId == pbresp.WatchId {
// merge new events // merge new events
cur.Events = append(cur.Events, pbresp.Events...) cur.Events = append(cur.Events, pbresp.Events...)
// update "Fragment" field; last response with "Fragment" == false // update "Fragment" field; last response with "Fragment" == false
@ -723,7 +723,7 @@ func (w *watchGRPCStream) dispatchEvent(pbresp *pb.WatchResponse) bool {
CompactRevision: pbresp.CompactRevision, CompactRevision: pbresp.CompactRevision,
Created: pbresp.Created, Created: pbresp.Created,
Canceled: pbresp.Canceled, Canceled: pbresp.Canceled,
CancelReason: pbresp.CancelReason, cancelReason: pbresp.CancelReason,
} }
// watch IDs are zero indexed, so request notify watch responses are assigned a watch ID of InvalidWatchID to // watch IDs are zero indexed, so request notify watch responses are assigned a watch ID of InvalidWatchID to

View File

@ -72,7 +72,7 @@ func TestStreamKeyFromCtx(t *testing.T) {
}{ }{
{ {
name: "multiple keys", name: "multiple keys",
ctx: metadata.NewOutgoingContext(t.Context(), metadata.MD{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.MD{
"key1": []string{"value1"}, "key1": []string{"value1"},
"key2": []string{"value2a", "value2b"}, "key2": []string{"value2a", "value2b"},
}), }),
@ -80,19 +80,19 @@ func TestStreamKeyFromCtx(t *testing.T) {
}, },
{ {
name: "no keys", name: "no keys",
ctx: metadata.NewOutgoingContext(t.Context(), metadata.MD{}), ctx: metadata.NewOutgoingContext(context.Background(), metadata.MD{}),
expected: "map[]", expected: "map[]",
}, },
{ {
name: "only one key", name: "only one key",
ctx: metadata.NewOutgoingContext(t.Context(), metadata.MD{ ctx: metadata.NewOutgoingContext(context.Background(), metadata.MD{
"key1": []string{"value1", "value1a"}, "key1": []string{"value1", "value1a"},
}), }),
expected: "map[key1:[value1 value1a]]", expected: "map[key1:[value1 value1a]]",
}, },
{ {
name: "no metadata", name: "no metadata",
ctx: t.Context(), ctx: context.Background(),
expected: "", expected: "",
}, },
} }

View File

@ -73,7 +73,7 @@ func TestConfigFromFile(t *testing.T) {
} }
for i, tt := range tests { for i, tt := range tests {
tmpfile, err := os.CreateTemp(t.TempDir(), "clientcfg") tmpfile, err := os.CreateTemp("", "clientcfg")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -25,8 +25,6 @@ import (
"strconv" "strconv"
"time" "time"
"go.uber.org/zap"
"go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/client/pkg/v3/fileutil"
"go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/client/pkg/v3/types"
"go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp"
@ -36,6 +34,8 @@ import (
"go.etcd.io/etcd/server/v3/storage/wal/walpb" "go.etcd.io/etcd/server/v3/storage/wal/walpb"
"go.etcd.io/raft/v3" "go.etcd.io/raft/v3"
"go.etcd.io/raft/v3/raftpb" "go.etcd.io/raft/v3/raftpb"
"go.uber.org/zap"
) )
type commit struct { type commit struct {

View File

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2020 The etcd Authors Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -182,7 +182,7 @@ func newCheckPerfCommand(cmd *cobra.Command, args []string) {
bar := pb.New(cfg.duration) bar := pb.New(cfg.duration)
bar.Start() bar.Start()
r := report.NewReport("%4.4f", "", false) r := report.NewReport("%4.4f")
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(clients)) wg.Add(len(clients))
@ -353,7 +353,7 @@ func newCheckDatascaleCommand(cmd *cobra.Command, args []string) {
ksize, vsize := 512, 512 ksize, vsize := 512, 512
k, v := make([]byte, ksize), string(make([]byte, vsize)) k, v := make([]byte, ksize), string(make([]byte, vsize))
r := report.NewReport("%4.4f", "", false) r := report.NewReport("%4.4f")
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(len(clients)) wg.Add(len(clients))

View File

@ -58,7 +58,6 @@ type GlobalFlags struct {
User string User string
Password string Password string
Token string
Debug bool Debug bool
} }
@ -291,22 +290,13 @@ func authCfgFromCmd(cmd *cobra.Command) *clientv3.AuthConfig {
if err != nil { if err != nil {
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
} }
tokenFlag, err := cmd.Flags().GetString("auth-jwt-token")
if err != nil {
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
}
if userFlag == "" && tokenFlag == "" { if userFlag == "" {
return nil return nil
} }
var cfg clientv3.AuthConfig var cfg clientv3.AuthConfig
if tokenFlag != "" {
cfg.Token = tokenFlag
return &cfg
}
if passwordFlag == "" { if passwordFlag == "" {
splitted := strings.SplitN(userFlag, ":", 2) splitted := strings.SplitN(userFlag, ":", 2)
if len(splitted) < 2 { if len(splitted) < 2 {

View File

@ -17,53 +17,20 @@ package command
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"os" "os"
"strconv"
"strings"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
clientv3 "go.etcd.io/etcd/client/v3" clientv3 "go.etcd.io/etcd/client/v3"
) )
type jsonPrinter struct { type jsonPrinter struct {
writer io.Writer isHex bool
isHex bool
printer printer
} }
type (
HexResponseHeader pb.ResponseHeader
HexMember pb.Member
)
func (h *HexResponseHeader) MarshalJSON() ([]byte, error) {
type Alias pb.ResponseHeader
return json.Marshal(&struct {
ClusterID string `json:"cluster_id"`
MemberID string `json:"member_id"`
Alias
}{
ClusterID: fmt.Sprintf("%x", h.ClusterId),
MemberID: fmt.Sprintf("%x", h.MemberId),
Alias: (Alias)(*h),
})
}
func (m *HexMember) MarshalJSON() ([]byte, error) {
type Alias pb.Member
return json.Marshal(&struct {
ID string `json:"ID"`
Alias
}{
ID: fmt.Sprintf("%x", m.ID),
Alias: (Alias)(*m),
})
}
func newJSONPrinter(isHex bool) printer { func newJSONPrinter(isHex bool) printer {
return &jsonPrinter{ return &jsonPrinter{
writer: os.Stdout,
isHex: isHex, isHex: isHex,
printer: &printerRPC{newPrinterUnsupported("json"), printJSON}, printer: &printerRPC{newPrinterUnsupported("json"), printJSON},
} }
@ -73,106 +40,61 @@ func (p *jsonPrinter) EndpointHealth(r []epHealth) { printJSON(r) }
func (p *jsonPrinter) EndpointStatus(r []epStatus) { printJSON(r) } func (p *jsonPrinter) EndpointStatus(r []epStatus) { printJSON(r) }
func (p *jsonPrinter) EndpointHashKV(r []epHashKV) { printJSON(r) } func (p *jsonPrinter) EndpointHashKV(r []epHashKV) { printJSON(r) }
func (p *jsonPrinter) MemberAdd(r clientv3.MemberAddResponse) { p.printJSON(r) } func (p *jsonPrinter) MemberList(r clientv3.MemberListResponse) {
func (p *jsonPrinter) MemberRemove(_ uint64, r clientv3.MemberRemoveResponse) { p.printJSON(r) } if p.isHex {
func (p *jsonPrinter) MemberUpdate(_ uint64, r clientv3.MemberUpdateResponse) { p.printJSON(r) } printMemberListWithHexJSON(r)
func (p *jsonPrinter) MemberPromote(_ uint64, r clientv3.MemberPromoteResponse) { p.printJSON(r) } } else {
func (p *jsonPrinter) MemberList(r clientv3.MemberListResponse) { p.printJSON(r) } printJSON(r)
}
}
func printJSONTo(w io.Writer, v any) { func printJSON(v any) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err) fmt.Fprintf(os.Stderr, "%v\n", err)
return return
} }
fmt.Fprintln(w, string(b)) fmt.Println(string(b))
} }
func printJSON(v any) { func printMemberListWithHexJSON(r clientv3.MemberListResponse) {
printJSONTo(os.Stdout, v) var buffer strings.Builder
} var b []byte
buffer.WriteString("{\"header\":{\"cluster_id\":\"")
func (p *jsonPrinter) printJSON(v any) { b = strconv.AppendUint(nil, r.Header.ClusterId, 16)
var data any buffer.Write(b)
if !p.isHex { buffer.WriteString("\",\"member_id\":\"")
printJSONTo(p.writer, v) b = strconv.AppendUint(nil, r.Header.MemberId, 16)
return buffer.Write(b)
buffer.WriteString("\",\"raft_term\":")
b = strconv.AppendUint(nil, r.Header.RaftTerm, 10)
buffer.Write(b)
buffer.WriteByte('}')
for i := 0; i < len(r.Members); i++ {
if i == 0 {
buffer.WriteString(",\"members\":[{\"ID\":\"")
} else {
buffer.WriteString(",{\"ID\":\"")
}
b = strconv.AppendUint(nil, r.Members[i].ID, 16)
buffer.Write(b)
buffer.WriteString("\",\"name\":\"" + r.Members[i].Name + "\"," + "\"peerURLs\":")
b, err := json.Marshal(r.Members[i].PeerURLs)
if err != nil {
return
}
buffer.Write(b)
buffer.WriteString(",\"clientURLs\":")
b, err = json.Marshal(r.Members[i].ClientURLs)
if err != nil {
return
}
buffer.Write(b)
buffer.WriteByte('}')
if i == len(r.Members)-1 {
buffer.WriteString("]")
}
} }
buffer.WriteString("}")
switch r := v.(type) { fmt.Println(buffer.String())
case clientv3.MemberAddResponse:
type Alias clientv3.MemberAddResponse
data = &struct {
Header *HexResponseHeader `json:"header"`
Member *HexMember `json:"member"`
Members []*HexMember `json:"members"`
*Alias
}{
Header: (*HexResponseHeader)(r.Header),
Member: (*HexMember)(r.Member),
Members: toHexMembers(r.Members),
Alias: (*Alias)(&r),
}
case clientv3.MemberRemoveResponse:
type Alias clientv3.MemberRemoveResponse
data = &struct {
Header *HexResponseHeader `json:"header"`
Members []*HexMember `json:"members"`
*Alias
}{
Header: (*HexResponseHeader)(r.Header),
Members: toHexMembers(r.Members),
Alias: (*Alias)(&r),
}
case clientv3.MemberUpdateResponse:
type Alias clientv3.MemberUpdateResponse
data = &struct {
Header *HexResponseHeader `json:"header"`
Members []*HexMember `json:"members"`
*Alias
}{
Header: (*HexResponseHeader)(r.Header),
Members: toHexMembers(r.Members),
Alias: (*Alias)(&r),
}
case clientv3.MemberPromoteResponse:
type Alias clientv3.MemberPromoteResponse
data = &struct {
Header *HexResponseHeader `json:"header"`
Members []*HexMember `json:"members"`
*Alias
}{
Header: (*HexResponseHeader)(r.Header),
Members: toHexMembers(r.Members),
Alias: (*Alias)(&r),
}
case clientv3.MemberListResponse:
type Alias clientv3.MemberListResponse
data = &struct {
Header *HexResponseHeader `json:"header"`
Members []*HexMember `json:"members"`
*Alias
}{
Header: (*HexResponseHeader)(r.Header),
Members: toHexMembers(r.Members),
Alias: (*Alias)(&r),
}
default:
data = v
}
printJSONTo(p.writer, data)
}
func toHexMembers(members []*pb.Member) []*HexMember {
hexMembers := make([]*HexMember, len(members))
for i, member := range members {
hexMembers[i] = (*HexMember)(member)
}
return hexMembers
} }

View File

@ -1,328 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package command
import (
"bytes"
"encoding/json"
"fmt"
"math"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
clientv3 "go.etcd.io/etcd/client/v3"
)
const (
keyHeader = "header"
keyMember = "member"
keyMembers = "members"
keyClusterID = "cluster_id"
keyMemberID = "member_id"
keyRaftTerm = "raft_term"
keyRevision = "revision"
keyID = "ID"
)
func assertNumericFieldEqual(t *testing.T, obj map[string]any, key string, want int64) {
raw, ok := obj[key]
require.Truef(t, ok, "missing key %q in map %v", key, obj)
n, ok := raw.(json.Number)
require.Truef(t, ok, "field %q is not json.Number: %v", key, raw)
val, err := n.Int64()
require.NoErrorf(t, err, "failed to convert field %q to int64: %v", key, n)
assert.Equalf(t, want, val, "unexpected value for field %q", key)
}
func assertHexFieldEqual(t *testing.T, obj map[string]any, key string, want string) {
raw, ok := obj[key]
require.Truef(t, ok, "missing key %q in map %v", key, obj)
str, ok := raw.(string)
require.Truef(t, ok, "field %q is not a string: %v", key, str)
assert.Equalf(t, want, str, "unexpected value for hex field %q", key)
}
func assertHeader(t *testing.T, testGroup *testScenario, tt *testCase, got map[string]any) {
rawHeader, ok := got[keyHeader]
require.Truef(t, ok, "output does not contain %q field: %v", keyHeader, got)
header, ok := rawHeader.(map[string]any)
require.Truef(t, ok, "field %q is not map[string]any: %v", keyHeader, rawHeader)
if testGroup.isHex {
assertHexFieldEqual(t, header, keyClusterID, tt.wantHexString)
assertHexFieldEqual(t, header, keyMemberID, tt.wantHexString)
} else {
assertNumericFieldEqual(t, header, keyClusterID, tt.wantDecimalNumber)
assertNumericFieldEqual(t, header, keyMemberID, tt.wantDecimalNumber)
}
assertNumericFieldEqual(t, header, keyRaftTerm, tt.wantDecimalNumber)
assertNumericFieldEqual(t, header, keyRevision, tt.wantDecimalNumber)
}
func assertMember(t *testing.T, testGroup *testScenario, tt *testCase, rawMember any) {
member, ok := rawMember.(map[string]any)
require.Truef(t, ok, "field %q is not map[string]any: %v", keyMember, rawMember)
if testGroup.isHex {
assertHexFieldEqual(t, member, keyID, tt.wantHexString)
} else {
assertNumericFieldEqual(t, member, keyID, tt.wantDecimalNumber)
}
}
func assertMembers(t *testing.T, testGroup *testScenario, tt *testCase, got map[string]any) {
rawMembers, ok := got[keyMembers]
require.Truef(t, ok, "output does not contain %q field: %v", keyMembers, got)
members, ok := rawMembers.([]any)
require.Truef(t, ok, "field %q is not []any: %v", keyMembers, rawMembers)
for _, rawMember := range members {
assertMember(t, testGroup, tt, rawMember)
}
}
type testCase struct {
number uint64
wantHexString string
wantDecimalNumber int64
}
type testScenario struct {
name string
isHex bool
cases []testCase
}
var testCases = []testCase{
{1, "1", 1},
{100, "64", 100},
{1234567890, "499602d2", 1234567890},
{math.MaxInt64, "7fffffffffffffff", math.MaxInt64},
}
func TestMemberAdd(t *testing.T) {
tests := []testScenario{
{name: "decimal", isHex: false, cases: testCases},
{name: "hex", isHex: true, cases: testCases},
}
for _, testGroup := range tests {
t.Run(testGroup.name, func(t *testing.T) {
var buffer bytes.Buffer
p := &jsonPrinter{writer: &buffer, isHex: testGroup.isHex}
for _, tt := range testGroup.cases {
t.Run(fmt.Sprintf("number=%d", tt.number), func(t *testing.T) {
buffer.Reset()
decoder := json.NewDecoder(&buffer)
decoder.UseNumber()
response := clientv3.MemberAddResponse{
Header: &pb.ResponseHeader{
ClusterId: tt.number,
MemberId: tt.number,
Revision: int64(tt.number),
RaftTerm: tt.number,
},
Member: &pb.Member{ID: tt.number},
Members: []*pb.Member{{ID: tt.number}},
}
p.MemberAdd(response)
var got map[string]any
err := decoder.Decode(&got)
require.NoErrorf(t, err, "failed to decode JSON")
assertHeader(t, &testGroup, &tt, got)
rawMember, ok := got[keyMember]
require.Truef(t, ok, "output does not contain %q field: %v", keyMember, got)
assertMember(t, &testGroup, &tt, rawMember)
assertMembers(t, &testGroup, &tt, got)
})
}
})
}
}
func TestMemberRemove(t *testing.T) {
tests := []testScenario{
{name: "decimal", isHex: false, cases: testCases},
{name: "hex", isHex: true, cases: testCases},
}
for _, testGroup := range tests {
t.Run(testGroup.name, func(t *testing.T) {
var buffer bytes.Buffer
p := &jsonPrinter{writer: &buffer, isHex: testGroup.isHex}
for _, tt := range testGroup.cases {
t.Run(fmt.Sprintf("number=%d", tt.number), func(t *testing.T) {
buffer.Reset()
decoder := json.NewDecoder(&buffer)
decoder.UseNumber()
response := clientv3.MemberRemoveResponse{
Header: &pb.ResponseHeader{
ClusterId: tt.number,
MemberId: tt.number,
Revision: int64(tt.number),
RaftTerm: tt.number,
},
Members: []*pb.Member{{ID: tt.number}},
}
p.MemberRemove(0, response)
var got map[string]any
err := decoder.Decode(&got)
require.NoErrorf(t, err, "failed to decode JSON")
assertHeader(t, &testGroup, &tt, got)
assertMembers(t, &testGroup, &tt, got)
})
}
})
}
}
func TestMemberUpdate(t *testing.T) {
tests := []testScenario{
{name: "decimal", isHex: false, cases: testCases},
{name: "hex", isHex: true, cases: testCases},
}
for _, testGroup := range tests {
t.Run(testGroup.name, func(t *testing.T) {
var buffer bytes.Buffer
p := &jsonPrinter{writer: &buffer, isHex: testGroup.isHex}
for _, tt := range testGroup.cases {
t.Run(fmt.Sprintf("number=%d", tt.number), func(t *testing.T) {
buffer.Reset()
decoder := json.NewDecoder(&buffer)
decoder.UseNumber()
response := clientv3.MemberUpdateResponse{
Header: &pb.ResponseHeader{
ClusterId: tt.number,
MemberId: tt.number,
Revision: int64(tt.number),
RaftTerm: tt.number,
},
Members: []*pb.Member{{ID: tt.number}},
}
p.MemberUpdate(0, response)
var got map[string]any
err := decoder.Decode(&got)
require.NoErrorf(t, err, "failed to decode JSON")
assertHeader(t, &testGroup, &tt, got)
assertMembers(t, &testGroup, &tt, got)
})
}
})
}
}
func TestMemberPromote(t *testing.T) {
tests := []testScenario{
{name: "decimal", isHex: false, cases: testCases},
{name: "hex", isHex: true, cases: testCases},
}
for _, testGroup := range tests {
t.Run(testGroup.name, func(t *testing.T) {
var buffer bytes.Buffer
p := &jsonPrinter{writer: &buffer, isHex: testGroup.isHex}
for _, tt := range testGroup.cases {
t.Run(fmt.Sprintf("number=%d", tt.number), func(t *testing.T) {
buffer.Reset()
decoder := json.NewDecoder(&buffer)
decoder.UseNumber()
response := clientv3.MemberPromoteResponse{
Header: &pb.ResponseHeader{
ClusterId: tt.number,
MemberId: tt.number,
Revision: int64(tt.number),
RaftTerm: tt.number,
},
Members: []*pb.Member{{ID: tt.number}},
}
p.MemberPromote(0, response)
var got map[string]any
err := decoder.Decode(&got)
require.NoErrorf(t, err, "failed to decode JSON")
assertHeader(t, &testGroup, &tt, got)
assertMembers(t, &testGroup, &tt, got)
})
}
})
}
}
func TestMemberList(t *testing.T) {
tests := []testScenario{
{name: "decimal", isHex: false, cases: testCases},
{name: "hex", isHex: true, cases: testCases},
}
for _, testGroup := range tests {
t.Run(testGroup.name, func(t *testing.T) {
var buffer bytes.Buffer
p := &jsonPrinter{writer: &buffer, isHex: testGroup.isHex}
for _, tt := range testGroup.cases {
t.Run(fmt.Sprintf("number=%d", tt.number), func(t *testing.T) {
buffer.Reset()
decoder := json.NewDecoder(&buffer)
decoder.UseNumber()
response := clientv3.MemberListResponse{
Header: &pb.ResponseHeader{
ClusterId: tt.number,
MemberId: tt.number,
Revision: int64(tt.number),
RaftTerm: tt.number,
},
Members: []*pb.Member{{ID: tt.number}},
}
p.MemberList(response)
var got map[string]any
err := decoder.Decode(&got)
require.NoErrorf(t, err, "failed to decode JSON")
assertHeader(t, &testGroup, &tt, got)
assertMembers(t, &testGroup, &tt, got)
})
}
})
}
}

View File

@ -18,7 +18,6 @@ import (
"os" "os"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
v3 "go.etcd.io/etcd/client/v3" v3 "go.etcd.io/etcd/client/v3"
) )
@ -27,44 +26,44 @@ type tablePrinter struct{ printer }
func (tp *tablePrinter) MemberList(r v3.MemberListResponse) { func (tp *tablePrinter) MemberList(r v3.MemberListResponse) {
hdr, rows := makeMemberListTable(r) hdr, rows := makeMemberListTable(r)
cfgBuilder := tablewriter.NewConfigBuilder().WithRowAlignment(tw.AlignRight) table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) table.SetHeader(hdr)
table.Header(hdr)
for _, row := range rows { for _, row := range rows {
table.Append(row) table.Append(row)
} }
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render() table.Render()
} }
func (tp *tablePrinter) EndpointHealth(r []epHealth) { func (tp *tablePrinter) EndpointHealth(r []epHealth) {
hdr, rows := makeEndpointHealthTable(r) hdr, rows := makeEndpointHealthTable(r)
cfgBuilder := tablewriter.NewConfigBuilder().WithRowAlignment(tw.AlignRight) table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) table.SetHeader(hdr)
table.Header(hdr)
for _, row := range rows { for _, row := range rows {
table.Append(row) table.Append(row)
} }
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render() table.Render()
} }
func (tp *tablePrinter) EndpointStatus(r []epStatus) { func (tp *tablePrinter) EndpointStatus(r []epStatus) {
hdr, rows := makeEndpointStatusTable(r) hdr, rows := makeEndpointStatusTable(r)
cfgBuilder := tablewriter.NewConfigBuilder().WithRowAlignment(tw.AlignRight) table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) table.SetHeader(hdr)
table.Header(hdr)
for _, row := range rows { for _, row := range rows {
table.Append(row) table.Append(row)
} }
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render() table.Render()
} }
func (tp *tablePrinter) EndpointHashKV(r []epHashKV) { func (tp *tablePrinter) EndpointHashKV(r []epHashKV) {
hdr, rows := makeEndpointHashKVTable(r) hdr, rows := makeEndpointHashKVTable(r)
cfgBuilder := tablewriter.NewConfigBuilder().WithRowAlignment(tw.AlignRight) table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) table.SetHeader(hdr)
table.Header(hdr)
for _, row := range rows { for _, row := range rows {
table.Append(row) table.Append(row)
} }
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render() table.Render()
} }

View File

@ -23,7 +23,6 @@ import (
"go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/api/v3/version"
"go.etcd.io/etcd/etcdctl/v3/ctlv3/command" "go.etcd.io/etcd/etcdctl/v3/ctlv3/command"
"go.etcd.io/etcd/etcdctl/v3/util"
"go.etcd.io/etcd/pkg/v3/cobrautl" "go.etcd.io/etcd/pkg/v3/cobrautl"
) )
@ -70,7 +69,6 @@ func init() {
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file") rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file")
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file") rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.TrustedCAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle") rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.TrustedCAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")
rootCmd.PersistentFlags().StringVar(&globalFlags.Token, "auth-jwt-token", "", "JWT token used for authentication (if this option is used, --user and --password should not be set)")
rootCmd.PersistentFlags().StringVar(&globalFlags.User, "user", "", "username[:password] for authentication (prompt if password is not supplied)") rootCmd.PersistentFlags().StringVar(&globalFlags.User, "user", "", "username[:password] for authentication (prompt if password is not supplied)")
rootCmd.PersistentFlags().StringVar(&globalFlags.Password, "password", "", "password for authentication (if this option is used, --user option shouldn't include password)") rootCmd.PersistentFlags().StringVar(&globalFlags.Password, "password", "", "password for authentication (if this option is used, --user option shouldn't include password)")
rootCmd.PersistentFlags().StringVarP(&globalFlags.TLS.ServerName, "discovery-srv", "d", "", "domain name to query for SRV records describing cluster endpoints") rootCmd.PersistentFlags().StringVarP(&globalFlags.TLS.ServerName, "discovery-srv", "d", "", "domain name to query for SRV records describing cluster endpoints")
@ -104,7 +102,7 @@ func init() {
} }
func usageFunc(c *cobra.Command) error { func usageFunc(c *cobra.Command) error {
return util.UsageFunc(c, version.Version, version.APIVersion) return cobrautl.UsageFunc(c, version.Version, version.APIVersion)
} }
func Start() error { func Start() error {

View File

@ -1,50 +1,48 @@
module go.etcd.io/etcd/etcdctl/v3 module go.etcd.io/etcd/etcdctl/v3
go 1.24 go 1.23.0
toolchain go1.24.5 toolchain go1.23.11
require ( require (
github.com/bgentry/speakeasy v0.2.0 github.com/bgentry/speakeasy v0.2.0
github.com/cheggaaa/pb/v3 v3.1.7 github.com/cheggaaa/pb/v3 v3.1.6
github.com/dustin/go-humanize v1.0.1 github.com/dustin/go-humanize v1.0.1
github.com/olekukonko/tablewriter v1.0.9 github.com/olekukonko/tablewriter v0.0.5
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.7 github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/api/v3 v3.6.4
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.4
go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/v3 v3.6.4
go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/pkg/v3 v3.6.4
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/time v0.12.0 golang.org/x/time v0.9.0
google.golang.org/grpc v1.74.2 google.golang.org/grpc v1.71.1
) )
require ( require (
github.com/VividCortex/ewma v1.2.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.18.0 // indirect github.com/fatih/color v1.18.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/olekukonko/errors v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/olekukonko/ll v0.0.9 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.27.0 // indirect golang.org/x/text v0.23.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

View File

@ -6,21 +6,21 @@ github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE5
github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI= github.com/cheggaaa/pb/v3 v3.1.6 h1:h0x+vd7EiUohAJ29DJtJy+SNAc55t/elW3jCD086EXk=
github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ= github.com/cheggaaa/pb/v3 v3.1.6/go.mod h1:urxmfVtaxT+9aWk92DbsvXFZtNSWQSO5TRAp+MJ3l1s=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@ -32,16 +32,18 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -50,53 +52,50 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@ -112,8 +111,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -121,14 +120,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -137,14 +136,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@ -1,180 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// copied from https://github.com/rkt/rkt/blob/master/rkt/help.go
package util
import (
"fmt"
"io"
"os"
"strings"
"text/tabwriter"
"text/template"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
var (
commandUsageTemplate *template.Template
templFuncs = template.FuncMap{
"descToLines": func(s string) []string {
// trim leading/trailing whitespace and split into slice of lines
return strings.Split(strings.Trim(s, "\n\t "), "\n")
},
"cmdName": func(cmd *cobra.Command, startCmd *cobra.Command) string {
parts := []string{cmd.Name()}
for cmd.HasParent() && cmd.Parent().Name() != startCmd.Name() {
cmd = cmd.Parent()
parts = append([]string{cmd.Name()}, parts...)
}
return strings.Join(parts, " ")
},
"indent": func(s string) string {
pad := strings.Repeat(" ", 2)
return pad + strings.Replace(s, "\n", "\n"+pad, -1)
},
}
)
func init() {
commandUsage := `
{{ $cmd := .Cmd }}\
{{ $cmdname := cmdName .Cmd .Cmd.Root }}\
NAME:
{{if not .Cmd.HasParent}}\
{{printf "%s - %s" .Cmd.Name .Cmd.Short | indent}}
{{else}}\
{{printf "%s - %s" $cmdname .Cmd.Short | indent}}
{{end}}\
USAGE:
{{printf "%s" .Cmd.UseLine | indent}}
{{ if not .Cmd.HasParent }}\
VERSION:
{{printf "%s" .Version | indent}}
{{end}}\
{{if .Cmd.HasSubCommands}}\
API VERSION:
{{.APIVersion | indent}}
{{end}}\
{{if .Cmd.HasExample}}\
Examples:
{{.Cmd.Example}}
{{end}}\
{{if .Cmd.HasSubCommands}}\
COMMANDS:
{{range .SubCommands}}\
{{ $cmdname := cmdName . $cmd }}\
{{ if .Runnable }}\
{{printf "%s\t%s" $cmdname .Short | indent}}
{{end}}\
{{end}}\
{{end}}\
{{ if .Cmd.Long }}\
DESCRIPTION:
{{range $line := descToLines .Cmd.Long}}{{printf "%s" $line | indent}}
{{end}}\
{{end}}\
{{if .Cmd.HasLocalFlags}}\
OPTIONS:
{{.LocalFlags}}\
{{end}}\
{{if .Cmd.HasInheritedFlags}}\
GLOBAL OPTIONS:
{{.GlobalFlags}}\
{{end}}
`[1:]
commandUsageTemplate = template.Must(template.New("command_usage").Funcs(templFuncs).Parse(strings.ReplaceAll(commandUsage, "\\\n", "")))
}
func etcdFlagUsages(flagSet *pflag.FlagSet) string {
x := new(strings.Builder)
flagSet.VisitAll(func(flag *pflag.Flag) {
if len(flag.Deprecated) > 0 {
return
}
var format string
if len(flag.Shorthand) > 0 {
format = " -%s, --%s"
} else {
format = " %s --%s"
}
if len(flag.NoOptDefVal) > 0 {
format = format + "["
}
if flag.Value.Type() == "string" {
// put quotes on the value
format = format + "=%q"
} else {
format = format + "=%s"
}
if len(flag.NoOptDefVal) > 0 {
format = format + "]"
}
format = format + "\t%s\n"
shorthand := flag.Shorthand
fmt.Fprintf(x, format, shorthand, flag.Name, flag.DefValue, flag.Usage)
})
return x.String()
}
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
}
func UsageFunc(cmd *cobra.Command, version, APIVersion string) error {
subCommands := getSubCommands(cmd)
tabOut := getTabOutWithWriter(os.Stdout)
commandUsageTemplate.Execute(tabOut, struct {
Cmd *cobra.Command
LocalFlags string
GlobalFlags string
SubCommands []*cobra.Command
Version string
APIVersion string
}{
cmd,
etcdFlagUsages(cmd.LocalFlags()),
etcdFlagUsages(cmd.InheritedFlags()),
subCommands,
version,
APIVersion,
})
tabOut.Flush()
return nil
}
func getTabOutWithWriter(writer io.Writer) *tabwriter.Writer {
aTabOut := new(tabwriter.Writer)
aTabOut.Init(writer, 0, 8, 1, '\t', 0)
return aTabOut
}

View File

@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2020 The etcd Authors Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,4 +1,5 @@
# etcdutl etcdutl
========
`etcdutl` is a command line administration utility for [etcd][etcd]. `etcdutl` is a command line administration utility for [etcd][etcd].
@ -7,7 +8,7 @@ For operations over a network, please use `etcdctl`.
### DEFRAG [options] ### DEFRAG [options]
DEFRAG directly defragments an etcd data directory while etcd is not running. DEFRAG directly defragments an etcd data directory while etcd is not running.
When an etcd member reclaims storage space from deleted and compacted keys, the space is kept in a free list and the database file remains the same size. By defragmenting the database, the etcd member releases this free space back to the file system. When an etcd member reclaims storage space from deleted and compacted keys, the space is kept in a free list and the database file remains the same size. By defragmenting the database, the etcd member releases this free space back to the file system.
In order to defrag a live etcd instances over the network, please use `etcdctl defrag` instead. In order to defrag a live etcd instances over the network, please use `etcdctl defrag` instead.
@ -35,6 +36,7 @@ To defragment a data directory directly, use the `--data-dir` flag:
DEFRAG returns a zero exit code only if it succeeded in defragmenting all given endpoints. DEFRAG returns a zero exit code only if it succeeded in defragmenting all given endpoints.
### SNAPSHOT RESTORE [options] \<filename\> ### SNAPSHOT RESTORE [options] \<filename\>
SNAPSHOT RESTORE creates an etcd data directory for an etcd cluster member from a backend database snapshot and a new cluster configuration. Restoring the snapshot into each member for a new cluster configuration will initialize a new etcd cluster preloaded by the snapshot data. SNAPSHOT RESTORE creates an etcd data directory for an etcd cluster member from a backend database snapshot and a new cluster configuration. Restoring the snapshot into each member for a new cluster configuration will initialize a new etcd cluster preloaded by the snapshot data.
@ -172,74 +174,6 @@ Prints etcd version and API version.
# API version: 3.1 # API version: 3.1
``` ```
### LIST-BUCKET [options] \<data dir or db file path\>
`list-bucket` prints all bucket names.
#### Flags
- timeout -- Time to wait to obtain a file lock on db file, 0 to block indefinitely.
##### Examples for LIST-BUCKET
```bash
$ ./etcdutl list-bucket ~/tmp/etcd/default.etcd/member/snap/db
alarm
auth
authRoles
authUsers
cluster
key
lease
members
members_removed
meta
```
### ITERATE-BUCKET [options] \<data dir or db file path\> \<bucket name\>
`iterate-bucket` lists key-value pairs in a given bucket in reverse order.
#### Flags for ITERATE-BUCKET
- timeout -- Time to wait to obtain a file lock on db file, 0 to block indefinitely.
- limit -- Max number of key-value pairs to iterate (0 to iterate all).
- decode -- true to decode Protocol Buffer encoded data.
##### Examples for ITERATE-BUCKET
```bash
# with `--decode` option
$ ./etcdutl iterate-bucket ~/tmp/etcd/default.etcd/member/snap/db key --decode
rev={Revision:{Main:4 Sub:0} tombstone:false}, value=[key "k1" | val "v3" | created 2 | mod 4 | ver 3]
rev={Revision:{Main:3 Sub:0} tombstone:false}, value=[key "k1" | val "v2" | created 2 | mod 3 | ver 2]
rev={Revision:{Main:2 Sub:0} tombstone:false}, value=[key "k1" | val "v1" | created 2 | mod 2 | ver 1]
# without `--decode` option
$ ./etcdutl iterate-bucket ~/tmp/etcd/default.etcd/member/snap/db key
key="\x00\x00\x00\x00\x00\x00\x00\x04_\x00\x00\x00\x00\x00\x00\x00\x00", value="\n\x02k1\x10\x02\x18\x04 \x03*\x02v3"
key="\x00\x00\x00\x00\x00\x00\x00\x03_\x00\x00\x00\x00\x00\x00\x00\x00", value="\n\x02k1\x10\x02\x18\x03 \x02*\x02v2"
key="\x00\x00\x00\x00\x00\x00\x00\x02_\x00\x00\x00\x00\x00\x00\x00\x00", value="\n\x02k1\x10\x02\x18\x02 \x01*\x02v1"
```
### HASH [options] \<data dir or db file path\>
`hash` prints the hash of the db file.
#### Flags for HASH
- timeout -- Time to wait to obtain a file lock on db file, 0 to block indefinitely.
##### Examples for HASH
```bash
$ ./etcdutl hash ~/tmp/etcd/default.etcd/member/snap/db
db path: /Users/wachao/tmp/etcd/default.etcd/member/snap/db
Hash: 4031086527
```
## Exit codes ## Exit codes

View File

@ -45,9 +45,6 @@ func init() {
etcdutl.NewVersionCommand(), etcdutl.NewVersionCommand(),
etcdutl.NewCompletionCommand(), etcdutl.NewCompletionCommand(),
etcdutl.NewMigrateCommand(), etcdutl.NewMigrateCommand(),
etcdutl.NewListBucketCommand(),
etcdutl.NewIterateBucketCommand(),
etcdutl.NewHashCommand(),
) )
} }

View File

@ -1,276 +0,0 @@
// Copyright 2025 The etcd Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package etcdutl
import (
"encoding/binary"
"fmt"
"path/filepath"
"strings"
"time"
"github.com/spf13/cobra"
"go.uber.org/zap"
bolt "go.etcd.io/bbolt"
"go.etcd.io/etcd/api/v3/authpb"
"go.etcd.io/etcd/api/v3/mvccpb"
"go.etcd.io/etcd/client/pkg/v3/fileutil"
"go.etcd.io/etcd/server/v3/lease/leasepb"
"go.etcd.io/etcd/server/v3/storage/backend"
"go.etcd.io/etcd/server/v3/storage/datadir"
"go.etcd.io/etcd/server/v3/storage/mvcc"
"go.etcd.io/etcd/server/v3/storage/schema"
)
var (
// TODO: add this configure to top level etcdutl command
flockTimeout time.Duration
iterateBucketLimit uint64
iterateBucketDecode bool
)
func NewListBucketCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "list-bucket [data dir or db file path]",
Short: "bucket lists all buckets.",
Args: cobra.ExactArgs(1),
Run: listBucketCommandFunc,
}
// TODO: add this flag to top level etctutl command
cmd.PersistentFlags().DurationVar(&flockTimeout, "timeout", 10*time.Second, "time to wait to obtain a file lock on db file, 0 to block indefinitely")
return cmd
}
func NewIterateBucketCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "iterate-bucket [data dir or db file path] [bucket name]",
Short: "iterate-bucket lists key-value pairs in reverse order.",
Args: cobra.ExactArgs(2),
Run: iterateBucketCommandFunc,
}
// TODO: add this flag to top level etctutl command
cmd.PersistentFlags().DurationVar(&flockTimeout, "timeout", 10*time.Second, "time to wait to obtain a file lock on db file, 0 to block indefinitely")
cmd.PersistentFlags().Uint64Var(&iterateBucketLimit, "limit", 0, "max number of key-value pairs to iterate (0 to iterate all)")
cmd.PersistentFlags().BoolVar(&iterateBucketDecode, "decode", false, "true to decode Protocol Buffer encoded data")
return cmd
}
func NewHashCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "hash [data dir or db file path]",
Short: "hash computes the hash of db file.",
Args: cobra.ExactArgs(1),
Run: getHashCommandFunc,
}
// TODO: add this flag to top level etctutl command
cmd.PersistentFlags().DurationVar(&flockTimeout, "timeout", 10*time.Second, "time to wait to obtain a file lock on db file, 0 to block indefinitely")
return cmd
}
func listBucketCommandFunc(_ *cobra.Command, args []string) {
lg := GetLogger()
dp := args[0]
if !strings.HasSuffix(dp, "db") {
dp = filepath.Join(datadir.ToSnapDir(dp), "db")
}
if !fileutil.Exist(dp) {
lg.Fatal("db file not exist", zap.String("path", dp))
}
bts, err := getBuckets(dp)
if err != nil {
lg.Fatal("Failed to get buckets", zap.Error(err))
}
for _, b := range bts {
fmt.Println(b)
}
}
func getBuckets(dbPath string) (buckets []string, err error) {
db, derr := bolt.Open(dbPath, 0o600, &bolt.Options{Timeout: flockTimeout})
if derr != nil {
return nil, fmt.Errorf("failed to open bolt DB %w", derr)
}
defer db.Close()
err = db.View(func(tx *bolt.Tx) error {
return tx.ForEach(func(b []byte, _ *bolt.Bucket) error {
buckets = append(buckets, string(b))
return nil
})
})
return buckets, err
}
func iterateBucketCommandFunc(_ *cobra.Command, args []string) {
lg := GetLogger()
dp := args[0]
if !strings.HasSuffix(dp, "db") {
dp = filepath.Join(datadir.ToSnapDir(dp), "db")
}
if !fileutil.Exist(dp) {
lg.Fatal("db file not exist", zap.String("path", dp))
}
bucket := args[1]
err := iterateBucket(dp, bucket, iterateBucketLimit, iterateBucketDecode)
if err != nil {
lg.Fatal("Failed to iterate bucket", zap.Error(err))
}
}
type decoder func(k, v []byte)
// key is the bucket name, and value is the function to decode K/V in the bucket.
var decoders = map[string]decoder{
"key": keyDecoder,
"lease": leaseDecoder,
"auth": authDecoder,
"authRoles": authRolesDecoder,
"authUsers": authUsersDecoder,
"meta": metaDecoder,
}
func defaultDecoder(k, v []byte) {
fmt.Printf("key=%q, value=%q\n", k, v)
}
func keyDecoder(k, v []byte) {
rev := mvcc.BytesToBucketKey(k)
var kv mvccpb.KeyValue
if err := kv.Unmarshal(v); err != nil {
panic(err)
}
fmt.Printf("rev=%+v, value=[key %q | val %q | created %d | mod %d | ver %d]\n", rev, string(kv.Key), string(kv.Value), kv.CreateRevision, kv.ModRevision, kv.Version)
}
func bytesToLeaseID(bytes []byte) int64 {
if len(bytes) != 8 {
panic(fmt.Errorf("lease ID must be 8-byte"))
}
return int64(binary.BigEndian.Uint64(bytes))
}
func leaseDecoder(k, v []byte) {
leaseID := bytesToLeaseID(k)
var lpb leasepb.Lease
if err := lpb.Unmarshal(v); err != nil {
panic(err)
}
fmt.Printf("lease ID=%016x, TTL=%ds, remaining TTL=%ds\n", leaseID, lpb.TTL, lpb.RemainingTTL)
}
func authDecoder(k, v []byte) {
if string(k) == "authRevision" {
rev := binary.BigEndian.Uint64(v)
fmt.Printf("key=%q, value=%v\n", k, rev)
} else {
fmt.Printf("key=%q, value=%v\n", k, v)
}
}
func authRolesDecoder(_, v []byte) {
role := &authpb.Role{}
err := role.Unmarshal(v)
if err != nil {
panic(err)
}
fmt.Printf("role=%q, keyPermission=%v\n", string(role.Name), role.KeyPermission)
}
func authUsersDecoder(_, v []byte) {
user := &authpb.User{}
err := user.Unmarshal(v)
if err != nil {
panic(err)
}
fmt.Printf("user=%q, roles=%q, option=%v\n", user.Name, user.Roles, user.Options)
}
func metaDecoder(k, v []byte) {
if string(k) == string(schema.MetaConsistentIndexKeyName) || string(k) == string(schema.MetaTermKeyName) {
fmt.Printf("key=%q, value=%v\n", k, binary.BigEndian.Uint64(v))
} else if string(k) == string(schema.ScheduledCompactKeyName) || string(k) == string(schema.FinishedCompactKeyName) {
rev := mvcc.BytesToRev(v)
fmt.Printf("key=%q, value=%v\n", k, rev)
} else {
defaultDecoder(k, v)
}
}
func iterateBucket(dbPath, bucket string, limit uint64, decode bool) (err error) {
db, err := bolt.Open(dbPath, 0o600, &bolt.Options{Timeout: flockTimeout})
if err != nil {
return fmt.Errorf("failed to open bolt DB %w", err)
}
defer db.Close()
err = db.View(func(tx *bolt.Tx) error {
b := tx.Bucket([]byte(bucket))
if b == nil {
return fmt.Errorf("got nil bucket for %s", bucket)
}
c := b.Cursor()
// iterate in reverse order (use First() and Next() for ascending order)
for k, v := c.Last(); k != nil; k, v = c.Prev() {
// TODO: remove sensitive information
// (https://github.com/etcd-io/etcd/issues/7620)
if dec, ok := decoders[bucket]; decode && ok {
dec(k, v)
} else {
defaultDecoder(k, v)
}
limit--
if limit == 0 {
break
}
}
return nil
})
return err
}
func getHashCommandFunc(_ *cobra.Command, args []string) {
lg := GetLogger()
dp := args[0]
if !strings.HasSuffix(dp, "db") {
dp = filepath.Join(datadir.ToSnapDir(dp), "db")
}
if !fileutil.Exist(dp) {
lg.Fatal("db file not exist", zap.String("path", dp))
}
hash, err := getHash(dp)
if err != nil {
lg.Fatal("failed to get hash", zap.Error(err))
}
fmt.Printf("db path: %s\nHash: %d\n", dp, hash)
}
func getHash(dbPath string) (hash uint32, err error) {
b := backend.NewDefaultBackend(zap.NewNop(), dbPath)
return b.Hash(schema.DefaultIgnores)
}

View File

@ -18,7 +18,6 @@ import (
"os" "os"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
"go.etcd.io/etcd/etcdutl/v3/snapshot" "go.etcd.io/etcd/etcdutl/v3/snapshot"
) )
@ -27,22 +26,22 @@ type tablePrinter struct{ printer }
func (tp *tablePrinter) DBStatus(r snapshot.Status) { func (tp *tablePrinter) DBStatus(r snapshot.Status) {
hdr, rows := makeDBStatusTable(r) hdr, rows := makeDBStatusTable(r)
cfgBuilder := tablewriter.NewConfigBuilder().WithRowAlignment(tw.AlignRight) table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) table.SetHeader(hdr)
table.Header(hdr)
for _, row := range rows { for _, row := range rows {
table.Append(row) table.Append(row)
} }
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render() table.Render()
} }
func (tp *tablePrinter) DBHashKV(r HashKV) { func (tp *tablePrinter) DBHashKV(r HashKV) {
hdr, rows := makeDBHashKVTable(r) hdr, rows := makeDBHashKVTable(r)
cfgBuilder := tablewriter.NewConfigBuilder().WithRowAlignment(tw.AlignRight) table := tablewriter.NewWriter(os.Stdout)
table := tablewriter.NewTable(os.Stdout, tablewriter.WithConfig(cfgBuilder.Build())) table.SetHeader(hdr)
table.Header(hdr)
for _, row := range rows { for _, row := range rows {
table.Append(row) table.Append(row)
} }
table.SetAlignment(tablewriter.ALIGN_RIGHT)
table.Render() table.Render()
} }

View File

@ -1,8 +1,8 @@
module go.etcd.io/etcd/etcdutl/v3 module go.etcd.io/etcd/etcdutl/v3
go 1.24 go 1.23.0
toolchain go1.24.5 toolchain go1.23.11
replace ( replace (
go.etcd.io/etcd/api/v3 => ../api go.etcd.io/etcd/api/v3 => ../api
@ -23,78 +23,74 @@ replace (
require ( require (
github.com/coreos/go-semver v0.3.1 github.com/coreos/go-semver v0.3.1
github.com/dustin/go-humanize v1.0.1 github.com/dustin/go-humanize v1.0.1
github.com/olekukonko/tablewriter v1.0.9 github.com/olekukonko/tablewriter v0.0.5
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
go.etcd.io/bbolt v1.4.2 go.etcd.io/bbolt v1.4.2
go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/api/v3 v3.6.4
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.4
go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/v3 v3.6.4
go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/pkg/v3 v3.6.4
go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 go.etcd.io/etcd/server/v3 v3.6.4
go.etcd.io/raft/v3 v3.6.0 go.etcd.io/raft/v3 v3.6.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
) )
require ( require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.18.0 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.3 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/klauspost/compress v1.17.9 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/olekukonko/errors v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/olekukonko/ll v0.0.9 // indirect github.com/prometheus/client_golang v1.20.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/pflag v1.0.7 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/crypto v0.40.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/text v0.27.0 // indirect golang.org/x/time v0.9.0 // indirect
golang.org/x/time v0.12.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/grpc v1.71.1 // indirect
google.golang.org/grpc v1.74.2 // indirect google.golang.org/protobuf v1.36.5 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.5.0 // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
) )

View File

@ -1,7 +1,7 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
@ -10,95 +10,85 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8=
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@ -115,39 +105,35 @@ go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0 h1:rbRJ8BBoVMsQShESYZ0FkvcITu8X8QNwJogcLUmDNNw= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0/go.mod h1:ru6KHrNtNHxM4nD/vd6QrLVWgKhxPYgblq4VAtNawTQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@ -155,26 +141,25 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -183,14 +168,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@ -199,5 +184,7 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -15,6 +15,7 @@
package snapshot package snapshot
import ( import (
"context"
"errors" "errors"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -43,7 +44,7 @@ func TestSnapshotStatus(t *testing.T) {
status, err := NewV3(zap.NewNop()).Status(dbpath) status, err := NewV3(zap.NewNop()).Status(dbpath)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, uint32(0xe7a6e44b), status.Hash) assert.Equal(t, uint32(0x62132b4d), status.Hash)
assert.Equal(t, int64(11), status.Revision) assert.Equal(t, int64(11), status.Revision)
} }
@ -135,7 +136,7 @@ func TestSnapshotStatusTotalKey(t *testing.T) {
Key: []byte(key), Key: []byte(key),
Value: val, Value: val,
} }
_, err := srv.Put(t.Context(), &req) _, err := srv.Put(context.TODO(), &req)
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -149,10 +150,10 @@ func TestSnapshotStatusTotalKey(t *testing.T) {
key := []byte("key1") key := []byte("key1")
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
if i < 2 { if i < 2 {
_, err := srv.Put(t.Context(), &etcdserverpb.PutRequest{Key: key, Value: []byte(strconv.Itoa(i))}) _, err := srv.Put(context.TODO(), &etcdserverpb.PutRequest{Key: key, Value: []byte(strconv.Itoa(i))})
require.NoError(t, err) require.NoError(t, err)
} else { } else {
_, err := srv.DeleteRange(t.Context(), &etcdserverpb.DeleteRangeRequest{Key: key}) _, err := srv.DeleteRange(context.TODO(), &etcdserverpb.DeleteRangeRequest{Key: key})
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -165,9 +166,9 @@ func TestSnapshotStatusTotalKey(t *testing.T) {
// key1: create -> delete -> re-create -> delete // key1: create -> delete -> re-create -> delete
key := []byte("key1") key := []byte("key1")
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
_, err := srv.Put(t.Context(), &etcdserverpb.PutRequest{Key: key, Value: make([]byte, 1)}) _, err := srv.Put(context.TODO(), &etcdserverpb.PutRequest{Key: key, Value: make([]byte, 1)})
require.NoError(t, err) require.NoError(t, err)
_, err = srv.DeleteRange(t.Context(), &etcdserverpb.DeleteRangeRequest{Key: key}) _, err = srv.DeleteRange(context.TODO(), &etcdserverpb.DeleteRangeRequest{Key: key})
require.NoError(t, err) require.NoError(t, err)
} }
}, },
@ -180,10 +181,10 @@ func TestSnapshotStatusTotalKey(t *testing.T) {
key := []byte("key1") key := []byte("key1")
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
if i%2 == 0 { if i%2 == 0 {
_, err := srv.Put(t.Context(), &etcdserverpb.PutRequest{Key: key, Value: make([]byte, 1)}) _, err := srv.Put(context.TODO(), &etcdserverpb.PutRequest{Key: key, Value: make([]byte, 1)})
require.NoError(t, err) require.NoError(t, err)
} else { } else {
_, err := srv.DeleteRange(t.Context(), &etcdserverpb.DeleteRangeRequest{Key: key}) _, err := srv.DeleteRange(context.TODO(), &etcdserverpb.DeleteRangeRequest{Key: key})
require.NoError(t, err) require.NoError(t, err)
} }
} }
@ -194,11 +195,11 @@ func TestSnapshotStatusTotalKey(t *testing.T) {
name: "mixed deletions", name: "mixed deletions",
prepare: func(srv *etcdserver.EtcdServer) { prepare: func(srv *etcdserver.EtcdServer) {
// Put("key1") -> Put("key2")-> Delete("key1") // Put("key1") -> Put("key2")-> Delete("key1")
_, err := srv.Put(t.Context(), &etcdserverpb.PutRequest{Key: []byte("key1"), Value: make([]byte, 1)}) _, err := srv.Put(context.TODO(), &etcdserverpb.PutRequest{Key: []byte("key1"), Value: make([]byte, 1)})
require.NoError(t, err) require.NoError(t, err)
_, err = srv.Put(t.Context(), &etcdserverpb.PutRequest{Key: []byte("key2"), Value: make([]byte, 1)}) _, err = srv.Put(context.TODO(), &etcdserverpb.PutRequest{Key: []byte("key2"), Value: make([]byte, 1)})
require.NoError(t, err) require.NoError(t, err)
_, err = srv.DeleteRange(t.Context(), &etcdserverpb.DeleteRangeRequest{Key: []byte("key1")}) _, err = srv.DeleteRange(context.TODO(), &etcdserverpb.DeleteRangeRequest{Key: []byte("key1")})
require.NoError(t, err) require.NoError(t, err)
}, },
expected: 1, expected: 1,
@ -227,7 +228,7 @@ func insertKeys(t *testing.T, numKeys, valueSize int) func(*etcdserver.EtcdServe
Key: []byte(strconv.Itoa(i)), Key: []byte(strconv.Itoa(i)),
Value: val, Value: val,
} }
_, err := srv.Put(t.Context(), &req) _, err := srv.Put(context.TODO(), &req)
require.NoError(t, err) require.NoError(t, err)
} }
} }

94
go.mod
View File

@ -1,12 +1,11 @@
module go.etcd.io/etcd/v3 module go.etcd.io/etcd/v3
go 1.24 go 1.23.0
toolchain go1.24.5 toolchain go1.23.11
replace ( replace (
go.etcd.io/etcd/api/v3 => ./api go.etcd.io/etcd/api/v3 => ./api
go.etcd.io/etcd/cache/v3 => ./cache
go.etcd.io/etcd/client/pkg/v3 => ./client/pkg go.etcd.io/etcd/client/pkg/v3 => ./client/pkg
go.etcd.io/etcd/client/v3 => ./client/v3 go.etcd.io/etcd/client/v3 => ./client/v3
go.etcd.io/etcd/etcdctl/v3 => ./etcdctl go.etcd.io/etcd/etcdctl/v3 => ./etcdctl
@ -18,88 +17,87 @@ replace (
require ( require (
github.com/bgentry/speakeasy v0.2.0 github.com/bgentry/speakeasy v0.2.0
github.com/cheggaaa/pb/v3 v3.1.7 github.com/cheggaaa/pb/v3 v3.1.6
github.com/coreos/go-semver v0.3.1 github.com/coreos/go-semver v0.3.1
github.com/dustin/go-humanize v1.0.1 github.com/dustin/go-humanize v1.0.1
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
go.etcd.io/bbolt v1.4.2 go.etcd.io/bbolt v1.4.2
go.etcd.io/etcd/api/v3 v3.6.0-alpha.0 go.etcd.io/etcd/api/v3 v3.6.4
go.etcd.io/etcd/client/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/pkg/v3 v3.6.4
go.etcd.io/etcd/client/v3 v3.6.0-alpha.0 go.etcd.io/etcd/client/v3 v3.6.4
go.etcd.io/etcd/etcdctl/v3 v3.6.0-alpha.0 go.etcd.io/etcd/etcdctl/v3 v3.6.4
go.etcd.io/etcd/etcdutl/v3 v3.6.0-alpha.0 go.etcd.io/etcd/etcdutl/v3 v3.6.4
go.etcd.io/etcd/pkg/v3 v3.6.0-alpha.0 go.etcd.io/etcd/pkg/v3 v3.6.4
go.etcd.io/etcd/server/v3 v3.6.0-alpha.0 go.etcd.io/etcd/server/v3 v3.6.4
go.etcd.io/etcd/tests/v3 v3.0.0-00010101000000-000000000000 go.etcd.io/etcd/tests/v3 v3.6.4
go.etcd.io/raft/v3 v3.6.0 go.etcd.io/raft/v3 v3.6.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/time v0.12.0 golang.org/x/time v0.9.0
google.golang.org/grpc v1.74.2 google.golang.org/grpc v1.71.1
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.5
) )
require ( require (
github.com/VividCortex/ewma v1.2.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v5 v5.0.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.18.0 // indirect github.com/fatih/color v1.18.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.3 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/olekukonko/errors v1.1.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/olekukonko/ll v0.0.9 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/olekukonko/tablewriter v1.0.9 // indirect github.com/prometheus/client_golang v1.20.5 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/pflag v1.0.7 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/gofail v0.2.0 // indirect go.etcd.io/gofail v0.2.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/crypto v0.40.0 // indirect golang.org/x/net v0.38.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/sys v0.34.0 // indirect golang.org/x/text v0.23.0 // indirect
golang.org/x/text v0.27.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.5.0 // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
) )

164
go.sum
View File

@ -6,13 +6,13 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E=
github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI= github.com/cheggaaa/pb/v3 v3.1.6 h1:h0x+vd7EiUohAJ29DJtJy+SNAc55t/elW3jCD086EXk=
github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ= github.com/cheggaaa/pb/v3 v3.1.6/go.mod h1:urxmfVtaxT+9aWk92DbsvXFZtNSWQSO5TRAp+MJ3l1s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA=
@ -21,11 +21,10 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -37,19 +36,19 @@ github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -59,28 +58,29 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA=
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I= github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60= github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@ -93,46 +93,42 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8=
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@ -154,24 +150,24 @@ go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ=
go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0 h1:rbRJ8BBoVMsQShESYZ0FkvcITu8X8QNwJogcLUmDNNw= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.62.0/go.mod h1:ru6KHrNtNHxM4nD/vd6QrLVWgKhxPYgblq4VAtNawTQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
@ -181,15 +177,11 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -205,16 +197,16 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -222,14 +214,14 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -247,19 +239,19 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc= google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@ -271,5 +263,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/yaml v1.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s=
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4= sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

Some files were not shown because too many files have changed in this diff Show More