From 04f7fd9b412bd39a93c984afbc4408a2eeb142e4 Mon Sep 17 00:00:00 2001 From: Robin Cernin Date: Wed, 10 Mar 2021 08:43:52 +1000 Subject: [PATCH] etcdctl: allow move-leader to connect to multiple endpoints with TLS Re-opening closed PR #11775 which was originaly authored by benmoss. The mustClientForCmd function is responsible for parsing environment variables and flags into configuration data. A change was made in #9382 to call Fatal if a flag is provided multiple times. This means that we cannot call the mustClientForCmd function more than once, since it will think that flags parsed the first time are now being redefined and error out. Some people have commented about this in #8380 but I don't think there's an open issue for it. --- etcdctl/ctlv3/command/move_leader_command.go | 4 ++-- tests/e2e/ctl_v3_move_leader_test.go | 21 +++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/etcdctl/ctlv3/command/move_leader_command.go b/etcdctl/ctlv3/command/move_leader_command.go index 098c897cd7a..b70fabdee3c 100644 --- a/etcdctl/ctlv3/command/move_leader_command.go +++ b/etcdctl/ctlv3/command/move_leader_command.go @@ -43,7 +43,8 @@ func transferLeadershipCommandFunc(cmd *cobra.Command, args []string) { cobrautl.ExitWithError(cobrautl.ExitBadArgs, err) } - c := mustClientFromCmd(cmd) + cfg := clientConfigFromCmd(cmd) + c := cfg.mustClient() eps := c.Endpoints() c.Close() @@ -53,7 +54,6 @@ func transferLeadershipCommandFunc(cmd *cobra.Command, args []string) { var leaderCli *clientv3.Client var leaderID uint64 for _, ep := range eps { - cfg := clientConfigFromCmd(cmd) cfg.endpoints = []string{ep} cli := cfg.mustClient() resp, serr := cli.Status(ctx, ep) diff --git a/tests/e2e/ctl_v3_move_leader_test.go b/tests/e2e/ctl_v3_move_leader_test.go index 08abc37e26b..a86f97a0a4f 100644 --- a/tests/e2e/ctl_v3_move_leader_test.go +++ b/tests/e2e/ctl_v3_move_leader_test.go @@ -28,17 +28,26 @@ import ( ) func TestCtlV3MoveLeaderSecure(t *testing.T) { - testCtlV3MoveLeader(t, *newConfigTLS()) + testCtlV3MoveLeader(t, withCfg(*newConfigTLS())) + testCtlV3MoveLeader(t, withCfg(*newConfigTLS()), withFlagByEnv()) } func TestCtlV3MoveLeaderInsecure(t *testing.T) { - testCtlV3MoveLeader(t, *newConfigNoTLS()) + testCtlV3MoveLeader(t, withCfg(*newConfigNoTLS())) + testCtlV3MoveLeader(t, withCfg(*newConfigNoTLS()), withFlagByEnv()) } -func testCtlV3MoveLeader(t *testing.T, cfg etcdProcessClusterConfig) { +func testCtlV3MoveLeader(t *testing.T, opts ...ctlOption) { BeforeTest(t) - epc := setupEtcdctlTest(t, &cfg, true) + ret := ctlCtx{ + t: t, + cfg: *newConfigAutoTLS(), + dialTimeout: 7 * time.Second, + } + ret.applyOpts(opts) + + epc := setupEtcdctlTest(t, &ret.cfg, true) defer func() { if errC := epc.Close(); errC != nil { t.Fatalf("error closing etcd processes (%v)", errC) @@ -46,7 +55,7 @@ func testCtlV3MoveLeader(t *testing.T, cfg etcdProcessClusterConfig) { }() var tcfg *tls.Config - if cfg.clientTLS == clientTLS { + if ret.cfg.clientTLS == clientTLS { tinfo := transport.TLSInfo{ CertFile: certPath, KeyFile: privateKeyPath, @@ -94,11 +103,13 @@ func testCtlV3MoveLeader(t *testing.T, cfg etcdProcessClusterConfig) { cfg: *newConfigNoTLS(), dialTimeout: 7 * time.Second, epc: epc, + envMap: map[string]struct{}{}, } tests := []struct { prefixes []string expect string + }{ { // request to non-leader cx.prefixArgs([]string{cx.epc.EndpointsV3()[(leadIdx+1)%3]}),