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
10 changes: 10 additions & 0 deletions raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ const noLimit = math.MaxUint64
// so that the proposer can be notified and fail fast.
var ErrProposalDropped = errors.New("raft proposal dropped")

// ErrConfChangeRejected is returned when a configuration change proposal is
// rejected by raft validation and converted to a no-op entry.
var ErrConfChangeRejected = errors.New("raft conf change rejected")

// lockedRand is a small wrapper around rand.Rand to provide
// synchronization among multiple raft groups. Only the methods needed
// by the code are exposed (e.g. Intn).
Expand Down Expand Up @@ -1306,6 +1310,8 @@ func stepLeader(r *raft, m *pb.Message) error {
return ErrProposalDropped
}

rejectedConfChange := false

for i := range m.GetEntries() {
e := m.GetEntries()[i]
var cc pb.ConfChangeI
Expand Down Expand Up @@ -1337,6 +1343,7 @@ func stepLeader(r *raft, m *pb.Message) error {
}

if failedCheck != "" && !r.disableConfChangeValidation {
rejectedConfChange = true
r.logger.Infof("%x ignoring conf change %s at config %s: %s", r.id, DescribeConfChange(cc), r.trk.Config, failedCheck)
m.GetEntries()[i] = &pb.Entry{Type: pb.EntryNormal.Enum()}
} else {
Expand All @@ -1350,6 +1357,9 @@ func stepLeader(r *raft, m *pb.Message) error {
return ErrProposalDropped
}
r.bcastAppend()
if rejectedConfChange {
return ErrConfChangeRejected
}
return nil
case pb.MsgReadIndex:
// only one voting member (the leader) in the cluster
Expand Down
6 changes: 5 additions & 1 deletion raft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2807,10 +2807,14 @@ func TestStepIgnoreConfig(t *testing.T) {
r := newTestRaft(1, 10, 1, newTestMemoryStorage(withPeers(1, 2)))
r.becomeCandidate()
r.becomeLeader()

r.Step(&pb.Message{From: new(uint64(1)), To: new(uint64(1)), Type: pb.MsgProp.Enum(), Entries: []*pb.Entry{{Type: pb.EntryConfChange.Enum()}}})
index := r.raftLog.lastIndex()
pendingConfIndex := r.pendingConfIndex
r.Step(&pb.Message{From: new(uint64(1)), To: new(uint64(1)), Type: pb.MsgProp.Enum(), Entries: []*pb.Entry{{Type: pb.EntryConfChange.Enum()}}})

err := r.Step(&pb.Message{From: new(uint64(1)), To: new(uint64(1)), Type: pb.MsgProp.Enum(), Entries: []*pb.Entry{{Type: pb.EntryConfChange.Enum()}}})
require.Equal(t, ErrConfChangeRejected, err)

wents := []*pb.Entry{{Type: pb.EntryNormal.Enum(), Term: new(uint64(1)), Index: new(uint64(3)), Data: nil}}
ents, err := r.raftLog.entries(index+1, noLimit)
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions rawnode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,13 +606,13 @@ func TestRawNodeStart(t *testing.T) {

_, err = storage.Entries(fi, fi, math.MaxUint64)
// TODO(tbg): match exact error
require.Error(t, err, "should not have been able to load first index")
require.Error(t, err, ErrCompacted)

li, err := storage.LastIndex()
require.NoError(t, err)

_, err = storage.Entries(li, li, math.MaxUint64)
require.Error(t, err, "should not have been able to load last index")
require.Error(t, err, ErrUnavailable)

hs, ics, err := storage.InitialState()
require.NoError(t, err)
Expand Down
2 changes: 2 additions & 0 deletions testdata/confchange_v2_add_single_explicit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ propose-conf-change 1
v3 v4 v5
----
INFO 1 ignoring conf change transition:ConfChangeTransitionAuto changes:{type:ConfChangeAddNode node_id:3} changes:{type:ConfChangeAddNode node_id:4} changes:{type:ConfChangeAddNode node_id:5} at config voters=(1 2)&&(1): must transition out of joint config first
raft conf change rejected

# Propose a transition out of the joint config. We'll see this at index 6 below.
propose-conf-change 1
Expand Down Expand Up @@ -165,6 +166,7 @@ stabilize
propose-conf-change 1
----
INFO 1 ignoring conf change transition:ConfChangeTransitionAuto at config voters=(1 2): not in joint state; refusing empty conf change
raft conf change rejected

# Finishes work for the empty entry we just proposed.
stabilize
Expand Down