// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"testing"
"github.com/hashicorp/consul/sdk/testutil"
)
func TestAPI_OperatorRaftGetConfiguration ( t * testing . T ) {
t . Parallel ( )
c , s := makeClient ( t )
defer s . Stop ( )
operator := c . Operator ( )
out , err := operator . RaftGetConfiguration ( nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( out . Servers ) != 1 ||
! out . Servers [ 0 ] . Leader ||
! out . Servers [ 0 ] . Voter {
t . Fatalf ( "bad: %v" , out )
}
}
func TestAPI_OperatorRaftRemovePeerByAddress ( t * testing . T ) {
t . Parallel ( )
c1 , s1 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s1 . Stop ( )
_ , s2 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
conf . Server = true
conf . Bootstrap = false
conf . RetryJoin = [ ] string { s1 . LANAddr }
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s2 . Stop ( )
s2 . WaitForVoting ( t )
operator := c1 . Operator ( )
err := operator . RaftRemovePeerByAddress ( s2 . ServerAddr , nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
cfg , err := c1 . Operator ( ) . RaftGetConfiguration ( nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( cfg . Servers ) != 1 {
t . Fatalf ( "more than 1 server left: %+v" , cfg . Servers )
}
}
func TestAPI_OperatorRaftRemovePeerByID ( t * testing . T ) {
t . Parallel ( )
c1 , s1 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s1 . Stop ( )
_ , s2 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
conf . Server = true
conf . Bootstrap = false
conf . RetryJoin = [ ] string { s1 . LANAddr }
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s2 . Stop ( )
s2 . WaitForVoting ( t )
operator := c1 . Operator ( )
err := operator . RaftRemovePeerByID ( s2 . Config . NodeID , nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
cfg , err := c1 . Operator ( ) . RaftGetConfiguration ( nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( cfg . Servers ) != 1 {
t . Fatalf ( "more than 1 server left: %+v" , cfg . Servers )
}
}
func TestAPI_OperatorRaftLeaderTransfer ( t * testing . T ) {
t . Parallel ( )
c1 , s1 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s1 . Stop ( )
_ , s2 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
conf . Server = true
conf . Bootstrap = false
conf . RetryJoin = [ ] string { s1 . LANAddr }
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s2 . Stop ( )
s2 . WaitForVoting ( t )
cfg , err := c1 . Operator ( ) . RaftGetConfiguration ( nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if len ( cfg . Servers ) != 2 {
t . Fatalf ( "not 2 servers: %#v" , cfg . Servers )
}
var leaderID string
for _ , srv := range cfg . Servers {
if srv . Leader {
leaderID = srv . ID
}
}
if leaderID == "" {
t . Fatalf ( "no leader: %+v" , cfg . Servers )
}
transfer , err := c1 . Operator ( ) . RaftLeaderTransfer ( "" , nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if ! transfer . Success {
t . Fatal ( "unsuccessful transfer" )
}
s2 . WaitForLeader ( t )
cfg , err = c1 . Operator ( ) . RaftGetConfiguration ( nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
var newLeaderID string
for _ , srv := range cfg . Servers {
if srv . Leader {
newLeaderID = srv . ID
}
}
if newLeaderID == "" {
t . Fatalf ( "no leader: %#v" , cfg . Servers )
}
if newLeaderID == leaderID {
t . Fatalf ( "leader did not change: %v == %v" , newLeaderID , leaderID )
}
_ , s3 := makeClientWithConfig ( t , nil , func ( conf * testutil . TestServerConfig ) {
conf . Server = true
conf . Bootstrap = false
conf . RetryJoin = [ ] string { s1 . LANAddr , s2 . LANAddr }
if conf . Autopilot == nil {
conf . Autopilot = & testutil . TestAutopilotConfig { }
}
conf . Autopilot . ServerStabilizationTime = "1ms"
} )
defer s3 . Stop ( )
s3 . WaitForVoting ( t )
// Transfer it to another member
transfer , err = c1 . Operator ( ) . RaftLeaderTransfer ( s3 . Config . NodeID , nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
if ! transfer . Success {
t . Fatal ( "unsuccessful transfer" )
}
s3 . WaitForLeader ( t )
cfg , err = c1 . Operator ( ) . RaftGetConfiguration ( nil )
if err != nil {
t . Fatalf ( "err: %v" , err )
}
newLeaderID = ""
for _ , srv := range cfg . Servers {
if srv . Leader {
newLeaderID = srv . ID
}
}
if newLeaderID == "" {
t . Fatalf ( "no leader: %#v" , cfg . Servers )
}
if newLeaderID != s3 . Config . NodeID {
t . Fatalf ( "leader is not s3: %v != %v" , newLeaderID , s3 . Config . NodeID )
}
}