Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 .go-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.25.9
1.25.10
2 changes: 1 addition & 1 deletion api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module go.etcd.io/etcd/api/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

require (
github.com/coreos/go-semver v0.3.1
Expand Down
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.6.11"
Version = "3.6.12"
APIVersion = "unknown"

// Git SHA Value will be set during build
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 @@ -19,7 +19,6 @@ import (
"io"
"math/rand"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
Expand All @@ -35,13 +34,7 @@ func TestIsDirWriteable(t *testing.T) {
tmpdir := t.TempDir()
require.NoErrorf(t, IsDirWriteable(tmpdir), "unexpected IsDirWriteable error")
require.NoErrorf(t, os.Chmod(tmpdir, 0o444), "unexpected os.Chmod error")
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
2 changes: 1 addition & 1 deletion client/pkg/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module go.etcd.io/etcd/client/pkg/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

require (
github.com/coreos/go-systemd/v22 v22.5.0
Expand Down
6 changes: 3 additions & 3 deletions client/v3/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ module go.etcd.io/etcd/client/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

require (
github.com/coreos/go-semver v0.3.1
github.com/dustin/go-humanize v1.0.1
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1
github.com/prometheus/client_golang v1.20.5
github.com/stretchr/testify v1.11.1
go.etcd.io/etcd/api/v3 v3.6.11
go.etcd.io/etcd/client/pkg/v3 v3.6.11
go.etcd.io/etcd/api/v3 v3.6.12
go.etcd.io/etcd/client/pkg/v3 v3.6.12
go.uber.org/zap v1.27.0
google.golang.org/grpc v1.79.3
sigs.k8s.io/yaml v1.4.0
Expand Down
10 changes: 5 additions & 5 deletions etcdctl/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module go.etcd.io/etcd/etcdctl/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

require (
github.com/bgentry/speakeasy v0.2.0
Expand All @@ -12,10 +12,10 @@ require (
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
go.etcd.io/etcd/api/v3 v3.6.11
go.etcd.io/etcd/client/pkg/v3 v3.6.11
go.etcd.io/etcd/client/v3 v3.6.11
go.etcd.io/etcd/pkg/v3 v3.6.11
go.etcd.io/etcd/api/v3 v3.6.12
go.etcd.io/etcd/client/pkg/v3 v3.6.12
go.etcd.io/etcd/client/v3 v3.6.12
go.etcd.io/etcd/pkg/v3 v3.6.12
go.uber.org/zap v1.27.0
golang.org/x/time v0.9.0
google.golang.org/grpc v1.79.3
Expand Down
14 changes: 14 additions & 0 deletions etcdutl/etcdutl/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package etcdutl

import (
"errors"
"os"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
Expand All @@ -29,6 +30,19 @@ import (
"go.etcd.io/raft/v3/raftpb"
)

// 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/hashkv_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ type HashKV struct {
}

func calculateHashKV(dbPath string, rev int64) (HashKV, error) {
if err := validateFilePath(dbPath); err != nil {
return HashKV{}, err
}
cfg := backend.DefaultBackendConfig(zap.NewNop())
cfg.Path = dbPath
b := backend.New(cfg)
Expand Down
3 changes: 3 additions & 0 deletions etcdutl/etcdutl/migrate_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ func (c *migrateConfig) finalize() error {
}

func migrateCommandFunc(c *migrateConfig) error {
if err := validateDataDir(c.dataDir); err != nil {
return err
}
dbPath := datadir.ToBackendFileName(c.dataDir)
be := backend.NewDefaultBackend(GetLogger(), dbPath)
defer be.Close()
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 @@ -94,6 +94,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
12 changes: 6 additions & 6 deletions etcdutl/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module go.etcd.io/etcd/etcdutl/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

replace (
go.etcd.io/etcd/api/v3 => ../api
Expand All @@ -27,11 +27,11 @@ require (
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.11.1
go.etcd.io/bbolt v1.4.3
go.etcd.io/etcd/api/v3 v3.6.11
go.etcd.io/etcd/client/pkg/v3 v3.6.11
go.etcd.io/etcd/client/v3 v3.6.11
go.etcd.io/etcd/pkg/v3 v3.6.11
go.etcd.io/etcd/server/v3 v3.6.11
go.etcd.io/etcd/api/v3 v3.6.12
go.etcd.io/etcd/client/pkg/v3 v3.6.12
go.etcd.io/etcd/client/v3 v3.6.12
go.etcd.io/etcd/pkg/v3 v3.6.12
go.etcd.io/etcd/server/v3 v3.6.12
go.etcd.io/raft/v3 v3.6.0
go.uber.org/zap v1.27.0
)
Expand Down
18 changes: 9 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module go.etcd.io/etcd/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

replace (
go.etcd.io/etcd/api/v3 => ./api
Expand All @@ -24,14 +24,14 @@ require (
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
go.etcd.io/bbolt v1.4.3
go.etcd.io/etcd/api/v3 v3.6.11
go.etcd.io/etcd/client/pkg/v3 v3.6.11
go.etcd.io/etcd/client/v3 v3.6.11
go.etcd.io/etcd/etcdctl/v3 v3.6.11
go.etcd.io/etcd/etcdutl/v3 v3.6.11
go.etcd.io/etcd/pkg/v3 v3.6.11
go.etcd.io/etcd/server/v3 v3.6.11
go.etcd.io/etcd/tests/v3 v3.6.11
go.etcd.io/etcd/api/v3 v3.6.12
go.etcd.io/etcd/client/pkg/v3 v3.6.12
go.etcd.io/etcd/client/v3 v3.6.12
go.etcd.io/etcd/etcdctl/v3 v3.6.12
go.etcd.io/etcd/etcdutl/v3 v3.6.12
go.etcd.io/etcd/pkg/v3 v3.6.12
go.etcd.io/etcd/server/v3 v3.6.12
go.etcd.io/etcd/tests/v3 v3.6.12
go.etcd.io/raft/v3 v3.6.0
go.uber.org/zap v1.27.0
golang.org/x/time v0.9.0
Expand Down
4 changes: 2 additions & 2 deletions pkg/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ module go.etcd.io/etcd/pkg/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

require (
github.com/creack/pty v1.1.18
github.com/dustin/go-humanize v1.0.1
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
go.etcd.io/etcd/client/pkg/v3 v3.6.11
go.etcd.io/etcd/client/pkg/v3 v3.6.12
go.uber.org/zap v1.27.0
google.golang.org/grpc v1.79.3
)
Expand Down
37 changes: 22 additions & 15 deletions server/etcdserver/api/membership/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,24 +619,31 @@ func (c *RaftCluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes,
c.Lock()
defer c.Unlock()

var (
m *Member
ok bool
)

if m, ok = c.members[id]; !ok {
c.lg.Info("Skipped updating non-existent member in v2store",
zap.String("cluster-id", c.cid.String()),
zap.String("local-member-id", c.localID.String()),
zap.String("updated-remote-peer-id", id.String()),
zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs),
zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner),
zap.Bool("should-apply-v3", bool(shouldApplyV3)),
)
return
}
// `MemberUpdateRequest` only supports updating PeerURLs.
m.RaftAttributes.PeerURLs = raftAttr.PeerURLs

if c.v2store != nil {
if _, ok := c.members[id]; ok {
m := *(c.members[id])
m.RaftAttributes = raftAttr
mustUpdateMemberInStore(c.lg, c.v2store, &m)
} else {
c.lg.Info("Skipped updating non-existent member in v2store",
zap.String("cluster-id", c.cid.String()),
zap.String("local-member-id", c.localID.String()),
zap.String("updated-remote-peer-id", id.String()),
zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs),
zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner),
)
}
mustUpdateMemberInStore(c.lg, c.v2store, m)
}

if c.be != nil && shouldApplyV3 {
c.members[id].RaftAttributes = raftAttr
c.be.MustSaveMemberToBackend(c.members[id])
c.be.MustSaveMemberToBackend(m)

c.lg.Info(
"updated member",
Expand Down
15 changes: 14 additions & 1 deletion server/etcdserver/api/membership/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1064,7 +1064,7 @@ func TestUpdateRaftAttributes(t *testing.T) {
wantMembers map[types.ID]*Member
}{
{
name: "update an existing member",
name: "update an existing voting member",
members: []*Member{
newTestMember(1, oldPeerURLs, "1", clientURLs),
newTestMember(2, oldPeerURLs, "2", clientURLs),
Expand All @@ -1075,6 +1075,18 @@ func TestUpdateRaftAttributes(t *testing.T) {
2: newTestMember(2, newPeerURLs, "2", clientURLs),
},
},
{
name: "update an existing learner member",
members: []*Member{
newTestMember(1, oldPeerURLs, "1", clientURLs),
newTestMemberAsLearner(2, oldPeerURLs, "2", clientURLs),
},
updateMemberID: 2,
wantMembers: map[types.ID]*Member{
1: newTestMember(1, oldPeerURLs, "1", clientURLs),
2: newTestMemberAsLearner(2, newPeerURLs, "2", clientURLs),
},
},
{
name: "update a non-exist member",
members: []*Member{
Expand All @@ -1100,6 +1112,7 @@ func TestUpdateRaftAttributes(t *testing.T) {

mst, _ := membersFromStore(c.lg, st)
require.Equal(t, tc.wantMembers, mst)
require.Equal(t, tc.wantMembers, c.members)
})
}
}
Expand Down
2 changes: 1 addition & 1 deletion server/etcdserver/api/v3rpc/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ func (ams *authMaintenanceServer) Alarm(ctx context.Context, ar *pb.AlarmRequest
}

func (ams *authMaintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) {
if err := ams.isPermitted(ctx); err != nil {
if err := ams.requireAuthInfo(ctx); err != nil {
return nil, togRPCError(err)
}

Expand Down
10 changes: 5 additions & 5 deletions server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module go.etcd.io/etcd/server/v3

go 1.25.0

toolchain go1.25.9
toolchain go1.25.10

require (
github.com/coreos/go-semver v0.3.1
Expand All @@ -26,10 +26,10 @@ require (
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2
go.etcd.io/bbolt v1.4.3
go.etcd.io/etcd/api/v3 v3.6.11
go.etcd.io/etcd/client/pkg/v3 v3.6.11
go.etcd.io/etcd/client/v3 v3.6.11
go.etcd.io/etcd/pkg/v3 v3.6.11
go.etcd.io/etcd/api/v3 v3.6.12
go.etcd.io/etcd/client/pkg/v3 v3.6.12
go.etcd.io/etcd/client/v3 v3.6.12
go.etcd.io/etcd/pkg/v3 v3.6.12
go.etcd.io/raft/v3 v3.6.0
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0
go.opentelemetry.io/otel v1.40.0
Expand Down
2 changes: 1 addition & 1 deletion tests/common/maintenance_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func TestStatusWithRootAuth(t *testing.T) {
}

func TestStatusWithUserAuth(t *testing.T) {
testStatusWithAuth(t, false, true, WithAuth("user0", "user0Pass"))
testStatusWithAuth(t, false, false, WithAuth("user0", "user0Pass"))
}

func testStatusWithAuth(t *testing.T, expectConnectionError, expectOperationError bool, opts ...config.ClientOption) {
Expand Down
Loading
Loading