Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
d0fe9f5
Bump go version to 1.24.12
ahrtr Jan 30, 2026
c880a59
Merge pull request #21217 from ahrtr/20260130_go_3.5
ahrtr Jan 30, 2026
b0e2819
Remove the use of grpc-go's Metadata field
ahrtr Feb 3, 2026
79966bb
Merge pull request #21242 from ahrtr/20260203_metadata_3.5
fuweid Feb 3, 2026
67d47c8
Bump go version to 1.24.13
tsujiri Feb 6, 2026
6b9c711
Merge pull request #21258 from nwnt/bump-3.5-to-gov1.24.3
ahrtr Feb 6, 2026
62d8759
version: bump up to 3.5.27
ivanvc Feb 13, 2026
0b23de0
dependency: bump go.opentelemetry.io/otel/sdk from v1.34.0 to v1.40.0
henrybear327 Feb 22, 2026
256a0d1
Merge pull request #21338 from henrybear327/dependency/release-3.5/go…
ahrtr Feb 22, 2026
8dc01dd
server/etcdserver/api/v3rpc: run metrics interceptors before handlers
ahrtr Feb 21, 2026
0865cd0
Merge pull request #21336 from ahrtr/20260221_metrics
ahrtr Feb 24, 2026
a2467fc
server/etcdmain: fix deadlock issue for grpcproxy
fuweid Feb 22, 2026
85c7d38
Merge pull request #21356 from fuweid/cherry-pick-21339
fuweid Feb 26, 2026
ae37d46
Print the endpoint the grpc request was actually sent to in unary int…
ahrtr Feb 26, 2026
5476771
Merge pull request #21380 from ahrtr/20260226_grpc_real_dp_3.5
fuweid Feb 26, 2026
9868620
Fix race berween read index and leader change causing a stale read
serathius Feb 25, 2026
d2c82b2
Merge pull request #21387 from serathius/stale-read-fix-release-3.5-2
serathius Feb 26, 2026
c15a064
etcdctl: fix slice bounds trimming single-quoted args
huajianxiaowanzi Feb 13, 2026
11b330f
etcdctl: add unit test for Argify
huajianxiaowanzi Feb 13, 2026
07e9a61
etcdctl: add license header
huajianxiaowanzi Feb 13, 2026
d741e38
Apply suggestion from @Copilot
huajianxiaowanzi Mar 2, 2026
6b12c35
[release-3.5] bump Go to 1.25.7
shuan1026 Mar 2, 2026
187061b
Merge pull request #21403 from huajianxiaowanzi/manual-backport-21307…
ahrtr Mar 2, 2026
93b40cf
Merge pull request #21405 from shuan1026/bump-3.5-to-gov1.25.7
ahrtr Mar 2, 2026
451c29f
Don't reuse same ReadIndex
serathius Feb 27, 2026
7198b2f
Merge pull request #21421 from serathius/read-request-id-release-3.5
serathius Mar 3, 2026
902e81c
Bump golang.org/x/net@ v0.51.0 fixes GO-2026-4559
ArkaSaha30 Mar 6, 2026
d5b5a2f
Merge pull request #21441 from ArkaSaha30/fix-cve-GO-2026-4559-3.5
ahrtr Mar 6, 2026
184258a
Bump Go to 1.25.8
ivanvc Mar 6, 2026
762373e
Merge pull request #21462 from ivanvc/release-3.5-go-1.25.8
ahrtr Mar 9, 2026
f936af2
server/etcdserver: guard unauthenticated endpoints with auth checks
fuweid Mar 11, 2026
2ab338b
tests: update test for auth
fuweid Mar 18, 2026
9e43033
server/etcdserver: enforce auth checks for nested txn ops
fuweid Mar 19, 2026
d1827e2
etcdserver: fix cannot promote with auth from follower
anhtranbk Mar 18, 2026
59c4e18
Merge commit from fork
ahrtr Mar 19, 2026
5116f6d
Merge commit from fork
ahrtr Mar 19, 2026
cd6b551
dependency: Bump google.golang.org/grpc from v1.71.1 to 1.79.3
ivanvc Mar 19, 2026
55abfaa
Add defer-recover block to prevent panic when cc is nil
joshjms Apr 24, 2025
29073bd
Merge pull request #21500 from ivanvc/release-3.5-grpc-go-1.79.3
ahrtr Mar 20, 2026
cc81d59
Merge pull request #21494 from anhtranbk/manual-backport-20792-releas…
ahrtr Mar 20, 2026
f22ac30
version: bump up to 3.5.28
ivanvc Mar 20, 2026
b2a6b3b
Fix etcdctl endpoint command with option --cluster when auth is enabled
ahrtr Mar 27, 2026
be6c385
Merge pull request #21532 from ahrtr/20260327_auth_etcdctl_3.5
ahrtr Mar 27, 2026
cdbfd65
etcdserver: allow non-admin to fetch member list and alarms
fuweid Mar 31, 2026
cda589d
Merge pull request #21550 from etcd-io/cherry-pick-35/allow-non-admin…
ahrtr Mar 31, 2026
30b5f44
version: bump up to 3.5.29
ivanvc Apr 1, 2026
9f478e7
*: bump go to 1.25.9
fuweid Apr 8, 2026
f4c194a
Merge pull request #21587 from fuweid/bump-go-to-1.25.9-35
fuweid Apr 8, 2026
548aa99
Add an e2e test to reproduce the adding member failure when one membe…
ahrtr Apr 26, 2026
701b837
Fix the issue of not being able to adding new member when one existin…
ahrtr Apr 26, 2026
121b351
Merge pull request #21669 from ahrtr/20260426_add_member_3.5
ahrtr Apr 27, 2026
500c535
Get all Put related auth check into a separate function 'checkPutAuth'
ahrtr Apr 28, 2026
b48fed4
Merge pull request #21682 from ahrtr/20260428_auth_refactor_3.5
ahrtr Apr 29, 2026
a061815
Add an integration test case to reproduce the read via PrevKv bypass …
ahrtr Apr 29, 2026
3f36577
Add an integration test to reproduce the issue of PutWithLease in a T…
ahrtr Apr 29, 2026
e8ce1ae
Fix the 'read via PrevKv' and 'Put with lease' in TXN bypass rbac che…
ahrtr Apr 29, 2026
118f8f9
Merge pull request #21687 from ahrtr/20260429_auth_3.5
ahrtr Apr 29, 2026
7d20602
version: bump up to 3.5.30
ivanvc May 1, 2026
aa3f1f1
Bump Go to 1.25.10 and fix govulncheck
silentred May 8, 2026
c60ef8f
Merge pull request #21728 from silentred/release-3.5-bump-go-1.25.10
ahrtr May 8, 2026
471c372
bugfix: MemberUpdate implicitly and unexpectedly promotes a learner
silentred May 11, 2026
c7f74b6
Merge pull request #21737 from silentred/release-3.5-bugfix-memberupd…
ahrtr May 11, 2026
06bcace
etcdutl: validate data file path and return consistent errors instead…
silentred May 20, 2026
70cf41a
Merge pull request #21769 from silentred/release-3.5-etcdutl-invalid-…
fuweid May 20, 2026
017b4d5
client/pkg/fileutil: use os.Getuid() to skip TestIsDirWriteable as root
vivekpatani May 22, 2026
a420637
Merge pull request #21793 from vivekpatani/cherry-pick-21788-release-3.5
ahrtr May 23, 2026
7d17200
[release-3.5] bump golang.org/x/crypto and golang.org/x/net to fix go…
Deln0r May 28, 2026
75bb96d
Merge pull request #21820 from Deln0r/release-3.5-bump-x-crypto
ahrtr May 28, 2026
5ddacc1
version: bump up to 3.5.31
ivanvc Jun 1, 2026
15d742a
Merge branch 'openshift-4.19' into HEAD
Jun 10, 2026
a019707
UPSTREAM: <drop>: manually resolve conflicts
Jun 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "3.0.0"
Version = "3.5.26"
Version = "3.5.31"
APIVersion = "unknown"

// Git SHA Value will be set during build
Expand Down
8 changes: 4 additions & 4 deletions bill-of-materials.json
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 1
"confidence": 0.9647812166488794
}
]
},
Expand All @@ -589,7 +589,7 @@
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 1
"confidence": 0.9647812166488794
}
]
},
Expand All @@ -598,7 +598,7 @@
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 1
"confidence": 0.9647812166488794
}
]
},
Expand All @@ -607,7 +607,7 @@
"licenses": [
{
"type": "Apache License 2.0",
"confidence": 1
"confidence": 0.9647812166488794
}
]
},
Expand Down
9 changes: 1 addition & 8 deletions client/pkg/fileutil/fileutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"io/ioutil"
"math/rand"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
Expand All @@ -42,13 +41,7 @@ func TestIsDirWriteable(t *testing.T) {
if err = os.Chmod(tmpdir, 0444); err != nil {
t.Fatalf("unexpected os.Chmod error: %v", err)
}
me, err := user.Current()
if err != nil {
// err can be non-nil when cross compiled
// http://stackoverflow.com/questions/20609415/cross-compiling-user-current-not-implemented-on-linux-amd64
t.Skipf("failed to get current user: %v", err)
}
if me.Name == "root" || runtime.GOOS == "windows" {
if os.Getuid() == 0 || runtime.GOOS == "windows" {
// ideally we should check CAP_DAC_OVERRIDE.
// but it does not matter for tests.
// Chmod is not supported under windows.
Expand Down
5 changes: 1 addition & 4 deletions client/v3/naming/endpoints/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@ type Endpoint struct {
// Since etcd 3.1
Addr string

// Metadata is the information associated with Addr, which may be used
// to make load balancing decision.
// Metadata is the information associated with Addr.
// Since etcd 3.1
//
// Deprecated: The field is deprecated and will be removed in 3.7.
Metadata any
}

Expand Down
3 changes: 1 addition & 2 deletions client/v3/naming/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ func convertToGRPCEndpoint(ups map[string]*endpoints.Update) []gresolver.Endpoin
ep := gresolver.Endpoint{
Addresses: []gresolver.Address{
{
Addr: up.Endpoint.Addr,
Metadata: up.Endpoint.Metadata,
Addr: up.Endpoint.Addr,
},
},
}
Expand Down
4 changes: 4 additions & 0 deletions client/v3/retry_interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
"google.golang.org/grpc/status"
)

Expand All @@ -41,6 +42,8 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
ctx = withVersion(ctx)
grpcOpts, retryOpts := filterCallOptions(opts)
var p peer.Peer
grpcOpts = append(grpcOpts, grpc.Peer(&p))
callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts)
// short circuit for simplicity, and avoiding allocations.
if callOpts.max == 0 {
Expand All @@ -63,6 +66,7 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien
c.GetLogger().Warn(
"retrying of unary invoker failed",
zap.String("target", cc.Target()),
zap.String("peer", p.String()),
zap.Uint("attempt", attempt),
zap.Error(lastErr),
)
Expand Down
3 changes: 2 additions & 1 deletion etcdctl/ctlv3/command/ep_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ func endpointsFromCluster(cmd *cobra.Command) []string {
}

sec := secureCfgFromCmd(cmd)
au := authCfgFromCmd(cmd)
dt := dialTimeoutFromCmd(cmd)
ka := keepAliveTimeFromCmd(cmd)
kat := keepAliveTimeoutFromCmd(cmd)
Expand All @@ -255,7 +256,7 @@ func endpointsFromCluster(cmd *cobra.Command) []string {
}
// exclude auth for not asking needless password (MemberList() doesn't need authentication)

cfg, err := newClientCfg(eps, dt, ka, kat, sec, nil)
cfg, err := newClientCfg(eps, dt, ka, kat, sec, au)
if err != nil {
cobrautl.ExitWithError(cobrautl.ExitError, err)
}
Expand Down
2 changes: 1 addition & 1 deletion etcdctl/ctlv3/command/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func argify(s string) []string {
}
if args[i][0] == '\'' {
// 'single-quoted string'
args[i] = args[i][1 : len(args)-1]
args[i] = args[i][1 : len(args[i])-1]
} else if args[i][0] == '"' {
// "double quoted string"
if _, err := fmt.Sscanf(args[i], "%q", &args[i]); err != nil {
Expand Down
78 changes: 78 additions & 0 deletions etcdctl/ctlv3/command/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2026 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 (
"reflect"
"testing"
)

func TestArgify(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{
name: "empty string",
input: "",
expected: nil,
},
{
name: "simple args",
input: "foo bar baz",
expected: []string{"foo", "bar", "baz"},
},
{
name: "single-quoted string",
input: "'hello world'",
expected: []string{"hello world"},
},
{
name: "double-quoted string",
input: `"hello world"`,
expected: []string{"hello world"},
},
{
name: "mixed args",
input: "put 'my key' 'my value'",
expected: []string{"put", "my key", "my value"},
},
{
name: "empty single-quoted string",
input: "''",
expected: []string{""},
},
{
name: "empty double-quoted string",
input: `""`,
expected: []string{""},
},
{
name: "double-quoted with escape",
input: `"hello\"world"`,
expected: []string{`hello"world`},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := argify(tt.input)
if !reflect.DeepEqual(result, tt.expected) {
t.Errorf("argify(%q) = %v, want %v", tt.input, result, tt.expected)
}
})
}
}
9 changes: 8 additions & 1 deletion etcdutl/etcdutl/backup_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"go.etcd.io/etcd/api/v3/etcdserverpb"
"go.etcd.io/etcd/client/pkg/v3/fileutil"
"go.etcd.io/etcd/client/pkg/v3/types"
"go.etcd.io/etcd/pkg/v3/cobrautl"
"go.etcd.io/etcd/pkg/v3/idutil"
"go.etcd.io/etcd/pkg/v3/pbutil"
"go.etcd.io/etcd/raft/v3/raftpb"
Expand Down Expand Up @@ -68,7 +69,9 @@ func NewBackupCommand() *cobra.Command {
}

func doBackup(cmd *cobra.Command, args []string) {
HandleBackup(withV3, dataDir, backupDir, walDir, backupWalDir)
if err := HandleBackup(withV3, dataDir, backupDir, walDir, backupWalDir); err != nil {
cobrautl.ExitWithError(cobrautl.ExitError, err)
}
}

type desiredCluster struct {
Expand Down Expand Up @@ -103,6 +106,10 @@ func newDesiredCluster() desiredCluster {
func HandleBackup(withV3 bool, srcDir string, destDir string, srcWAL string, destWAL string) error {
lg := GetLogger()

if err := validateDataDir(srcDir); err != nil {
return err
}

srcSnap := datadir.ToSnapDir(srcDir)
destSnap := datadir.ToSnapDir(destDir)

Expand Down
16 changes: 16 additions & 0 deletions etcdutl/etcdutl/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,28 @@
package etcdutl

import (
"os"

"go.etcd.io/etcd/client/pkg/v3/logutil"
"go.etcd.io/etcd/pkg/v3/cobrautl"
"go.etcd.io/etcd/server/v3/datadir"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// validateDataDir checks if the data directory's backend database file exists.
func validateDataDir(dataDir string) error {
dbPath := datadir.ToBackendFileName(dataDir)
return validateFilePath(dbPath)
}

// validateFilePath checks if the specified file exists.
// It returns an error encountered by os.Stat, such as os.ErrNotExist, os.ErrPermission, etc.
func validateFilePath(filePath string) error {
_, err := os.Stat(filePath)
return err
}

func GetLogger() *zap.Logger {
config := logutil.DefaultZapLoggerConfig
config.Encoding = "console"
Expand Down
9 changes: 7 additions & 2 deletions etcdutl/etcdutl/defrag_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,13 @@ func defragCommandFunc(cmd *cobra.Command, args []string) {
}

func DefragData(dataDir string) error {
var be backend.Backend
lg := GetLogger()
var (
be backend.Backend
lg = GetLogger()
)
if err := validateDataDir(dataDir); err != nil {
return err
}
bch := make(chan struct{})
dbDir := datadir.ToBackendFileName(dataDir)
go func() {
Expand Down
3 changes: 3 additions & 0 deletions etcdutl/etcdutl/snapshot_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ func SnapshotStatusCommandFunc(cmd *cobra.Command, args []string) {
err := fmt.Errorf("snapshot status requires exactly one argument")
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
}
if err := validateFilePath(args[0]); err != nil {
cobrautl.ExitWithError(cobrautl.ExitError, err)
}
printer := initPrinterFromCmd(cmd)

lg := GetLogger()
Expand Down
Loading