Skip to content

Commit 3c65dfa

Browse files
authored
Merge pull request #19602 from ahrtr/3.5_add_learner_test_20250314
[release-3.5] Fix the issue that learner promotion command doesn't support json output
2 parents 0d8349e + 341af03 commit 3c65dfa

File tree

5 files changed

+62
-11
lines changed

5 files changed

+62
-11
lines changed

etcdctl/ctlv3/command/printer.go

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ func (p *printerRPC) MemberAdd(r v3.MemberAddResponse) { p.p((*pb.MemberAddRespo
107107
func (p *printerRPC) MemberRemove(id uint64, r v3.MemberRemoveResponse) {
108108
p.p((*pb.MemberRemoveResponse)(&r))
109109
}
110+
func (p *printerRPC) MemberPromote(id uint64, r v3.MemberPromoteResponse) {
111+
p.p((*pb.MemberPromoteResponse)(&r))
112+
}
110113
func (p *printerRPC) MemberUpdate(id uint64, r v3.MemberUpdateResponse) {
111114
p.p((*pb.MemberUpdateResponse)(&r))
112115
}

tests/e2e/ctl_v3_member_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"strings"
2323
"testing"
2424

25+
"github.com/stretchr/testify/require"
26+
2527
"go.etcd.io/etcd/api/v3/etcdserverpb"
2628
"go.etcd.io/etcd/tests/v3/framework/e2e"
2729
)
@@ -227,3 +229,32 @@ func ctlV3MemberUpdate(cx ctlCtx, memberID, peerURL string) error {
227229
cmdArgs := append(cx.PrefixArgs(), "member", "update", memberID, fmt.Sprintf("--peer-urls=%s", peerURL))
228230
return e2e.SpawnWithExpectWithEnv(cmdArgs, cx.envMap, " updated in cluster ")
229231
}
232+
233+
func TestCtlV3PromotingLearner(t *testing.T) {
234+
e2e.BeforeTest(t)
235+
236+
t.Log("Create a single node etcd cluster")
237+
cfg := e2e.NewConfigNoTLS()
238+
cfg.BasePeerScheme = "unix"
239+
cfg.ClusterSize = 1
240+
241+
epc, err := e2e.NewEtcdProcessCluster(t, cfg)
242+
require.NoError(t, err, "failed to start etcd cluster: %v", err)
243+
defer func() {
244+
derr := epc.Close()
245+
require.NoError(t, derr, "failed to close etcd cluster: %v", derr)
246+
}()
247+
248+
t.Log("Add and start a learner")
249+
learnerID, err := epc.StartNewProc(nil, true, t)
250+
require.NoError(t, err)
251+
252+
t.Log("Write a key to ensure the cluster is healthy so far")
253+
etcdctl := epc.Procs[0].Etcdctl(e2e.ClientNonTLS, false, false)
254+
err = etcdctl.Put("foo", "bar")
255+
require.NoError(t, err)
256+
257+
t.Logf("Promoting the learner %x", learnerID)
258+
_, err = etcdctl.MemberPromote(learnerID)
259+
require.NoError(t, err)
260+
}

tests/e2e/etcd_mix_versions_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func mixVersionsSnapshotTestByAddingMember(t *testing.T, cfg e2e.EtcdProcessClus
101101
newCfg := *epc.Cfg
102102
newCfg.Version = newInstanceVersion
103103
t.Log("Starting a new etcd instance")
104-
_, err = epc.StartNewProc(&newCfg, t)
104+
_, err = epc.StartNewProc(&newCfg, false, t)
105105
require.NoError(t, err, "failed to start the new etcd instance: %v", err)
106106
defer epc.Close()
107107

tests/framework/e2e/cluster.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"testing"
2525
"time"
2626

27+
clientv3 "go.etcd.io/etcd/client/v3"
2728
"go.etcd.io/etcd/pkg/v3/proxy"
2829
"go.etcd.io/etcd/server/v3/etcdserver"
2930
"go.uber.org/zap"
@@ -628,8 +629,8 @@ func (epc *EtcdProcessCluster) WithStopSignal(sig os.Signal) (ret os.Signal) {
628629
// StartNewProc grows cluster size by one with two phases
629630
// Phase 1 - Inform cluster of new configuration
630631
// Phase 2 - Start new member
631-
func (epc *EtcdProcessCluster) StartNewProc(cfg *EtcdProcessClusterConfig, tb testing.TB) (memberID uint64, err error) {
632-
memberID, serverCfg, err := epc.AddMember(cfg, tb)
632+
func (epc *EtcdProcessCluster) StartNewProc(cfg *EtcdProcessClusterConfig, isLearner bool, tb testing.TB) (memberID uint64, err error) {
633+
memberID, serverCfg, err := epc.AddMember(cfg, isLearner, tb)
633634
if err != nil {
634635
return 0, err
635636
}
@@ -643,12 +644,11 @@ func (epc *EtcdProcessCluster) StartNewProc(cfg *EtcdProcessClusterConfig, tb te
643644
}
644645

645646
// AddMember adds a new member to the cluster without starting it.
646-
func (epc *EtcdProcessCluster) AddMember(cfg *EtcdProcessClusterConfig, tb testing.TB) (memberID uint64, serverCfg *EtcdServerProcessConfig, err error) {
647-
if cfg != nil {
648-
serverCfg = cfg.EtcdServerProcessConfig(tb, epc.nextSeq)
649-
} else {
650-
serverCfg = epc.Cfg.EtcdServerProcessConfig(tb, epc.nextSeq)
647+
func (epc *EtcdProcessCluster) AddMember(cfg *EtcdProcessClusterConfig, isLearner bool, tb testing.TB) (memberID uint64, serverCfg *EtcdServerProcessConfig, err error) {
648+
if cfg == nil {
649+
cfg = epc.Cfg
651650
}
651+
serverCfg = cfg.EtcdServerProcessConfig(tb, epc.nextSeq)
652652

653653
epc.nextSeq++
654654

@@ -664,9 +664,17 @@ func (epc *EtcdProcessCluster) AddMember(cfg *EtcdProcessClusterConfig, tb testi
664664
// First add new member to cluster
665665
tb.Logf("add new member to cluster; member-name %s, member-peer-url %s", serverCfg.Name, serverCfg.Purl.String())
666666
memberCtl := NewEtcdctl(epc.Procs[0].EndpointsV3(), cfg.ClientTLS, cfg.IsClientAutoTLS, false)
667-
resp, err := memberCtl.MemberAdd(serverCfg.Name, []string{serverCfg.Purl.String()})
668-
if err != nil {
669-
return 0, nil, fmt.Errorf("failed to add new member: %w", err)
667+
var (
668+
resp *clientv3.MemberAddResponse
669+
mErr error
670+
)
671+
if isLearner {
672+
resp, mErr = memberCtl.MemberAddAsLearner(serverCfg.Name, []string{serverCfg.Purl.String()})
673+
} else {
674+
resp, mErr = memberCtl.MemberAdd(serverCfg.Name, []string{serverCfg.Purl.String()})
675+
}
676+
if mErr != nil {
677+
return 0, nil, fmt.Errorf("failed to add new member: %w", mErr)
670678
}
671679

672680
return resp.Member.ID, serverCfg, nil

tests/framework/e2e/etcdctl.go

+9
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,15 @@ func (ctl *Etcdctl) MemberRemove(id uint64) (*clientv3.MemberRemoveResponse, err
174174
return &resp, err
175175
}
176176

177+
func (ctl *Etcdctl) MemberPromote(id uint64) (*clientv3.MemberPromoteResponse, error) {
178+
if ctl.v2 {
179+
panic("Unsupported method for v2")
180+
}
181+
var resp clientv3.MemberPromoteResponse
182+
err := ctl.spawnJsonCmd(&resp, "member", "promote", fmt.Sprintf("%x", id))
183+
return &resp, err
184+
}
185+
177186
func (ctl *Etcdctl) Compact(rev int64) (*clientv3.CompactResponse, error) {
178187
if ctl.v2 {
179188
panic("Unsupported method for v2")

0 commit comments

Comments
 (0)