diff --git a/tests/e2e/cluster_proxy_test.go b/tests/e2e/cluster_proxy_test.go index b96a10037..f11db67ac 100644 --- a/tests/e2e/cluster_proxy_test.go +++ b/tests/e2e/cluster_proxy_test.go @@ -132,7 +132,7 @@ func (pp *proxyProc) start() error { if pp.proc != nil { panic("already started") } - proc, err := spawnCmdWithLogger(pp.lg, append([]string{pp.execPath}, pp.args...)) + proc, err := spawnCmdWithLogger(pp.lg, append([]string{pp.execPath}, pp.args...), nil) if err != nil { return err } diff --git a/tests/e2e/ctl_v2_test.go b/tests/e2e/ctl_v2_test.go index 107f1c2f7..0aae87bc8 100644 --- a/tests/e2e/ctl_v2_test.go +++ b/tests/e2e/ctl_v2_test.go @@ -505,7 +505,7 @@ func etcdctlBackup(t testing.TB, clus *etcdProcessCluster, dataDir, backupDir st cmdArgs = append(cmdArgs, "--with-v3=false") } t.Logf("Running: %v", cmdArgs) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, nil) if err != nil { return err } diff --git a/tests/e2e/ctl_v3_alarm_test.go b/tests/e2e/ctl_v3_alarm_test.go index 7b9b445b0..19852c30b 100644 --- a/tests/e2e/ctl_v3_alarm_test.go +++ b/tests/e2e/ctl_v3_alarm_test.go @@ -101,5 +101,5 @@ func alarmTest(cx ctlCtx) { func ctlV3Alarm(cx ctlCtx, cmd string, as ...string) error { cmdArgs := append(cx.PrefixArgs(), "alarm", cmd) - return spawnWithExpects(cmdArgs, as...) + return spawnWithExpects(cmdArgs, cx.envMap, as...) } diff --git a/tests/e2e/ctl_v3_auth_test.go b/tests/e2e/ctl_v3_auth_test.go index 58a3b61e0..11db1b389 100644 --- a/tests/e2e/ctl_v3_auth_test.go +++ b/tests/e2e/ctl_v3_auth_test.go @@ -93,7 +93,7 @@ func authEnable(cx ctlCtx) error { func ctlV3AuthEnable(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgs(), "auth", "enable") - return spawnWithExpect(cmdArgs, "Authentication Enabled") + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Enabled") } func authDisableTest(cx ctlCtx) { @@ -139,12 +139,12 @@ func authDisableTest(cx ctlCtx) { func ctlV3AuthDisable(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgs(), "auth", "disable") - return spawnWithExpect(cmdArgs, "Authentication Disabled") + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Disabled") } func authStatusTest(cx ctlCtx) { cmdArgs := append(cx.PrefixArgs(), "auth", "status") - if err := spawnWithExpects(cmdArgs, "Authentication Status: false", "AuthRevision:"); err != nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "Authentication Status: false", "AuthRevision:"); err != nil { cx.t.Fatal(err) } @@ -155,15 +155,15 @@ func authStatusTest(cx ctlCtx) { cx.user, cx.pass = "root", "root" cmdArgs = append(cx.PrefixArgs(), "auth", "status") - if err := spawnWithExpects(cmdArgs, "Authentication Status: true", "AuthRevision:"); err != nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "Authentication Status: true", "AuthRevision:"); err != nil { cx.t.Fatal(err) } cmdArgs = append(cx.PrefixArgs(), "auth", "status", "--write-out", "json") - if err := spawnWithExpect(cmdArgs, "enabled"); err != nil { + if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, "enabled"); err != nil { cx.t.Fatal(err) } - if err := spawnWithExpect(cmdArgs, "authRevision"); err != nil { + if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, "authRevision"); err != nil { cx.t.Fatal(err) } } @@ -381,25 +381,25 @@ func authRoleRevokeDuringOpsTest(cx ctlCtx) { } func ctlV3PutFailAuth(cx ctlCtx, key, val string) error { - return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "authentication failed") + return spawnWithExpectWithEnv(append(cx.PrefixArgs(), "put", key, val), cx.envMap, "authentication failed") } func ctlV3PutFailPerm(cx ctlCtx, key, val string) error { - return spawnWithExpect(append(cx.PrefixArgs(), "put", key, val), "permission denied") + return spawnWithExpectWithEnv(append(cx.PrefixArgs(), "put", key, val), cx.envMap, "permission denied") } func authSetupTestUser(cx ctlCtx) { if err := ctlV3User(cx, []string{"add", "test-user", "--interactive=false"}, "User test-user created", []string{"pass"}); err != nil { cx.t.Fatal(err) } - if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil { + if err := spawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role"), cx.envMap, "Role test-role created"); err != nil { cx.t.Fatal(err) } if err := ctlV3User(cx, []string{"grant-role", "test-user", "test-role"}, "Role test-role is granted to user test-user", nil); err != nil { cx.t.Fatal(err) } cmd := append(cx.PrefixArgs(), "role", "grant-permission", "test-role", "readwrite", "foo") - if err := spawnWithExpect(cmd, "Role test-role updated"); err != nil { + if err := spawnWithExpectWithEnv(cmd, cx.envMap, "Role test-role updated"); err != nil { cx.t.Fatal(err) } } @@ -611,7 +611,7 @@ func authTestCertCN(cx ctlCtx) { if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil { cx.t.Fatal(err) } - if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role"), "Role test-role created"); err != nil { + if err := spawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role"), cx.envMap, "Role test-role created"); err != nil { cx.t.Fatal(err) } if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role"}, "Role test-role is granted to user example.com", nil); err != nil { @@ -921,13 +921,13 @@ func authTestRoleGet(cx ctlCtx) { "KV Read:", "foo", "KV Write:", "foo", } - if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil { + if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), cx.envMap, expected...); err != nil { cx.t.Fatal(err) } // test-user can get the information of test-role because it belongs to the role cx.user, cx.pass = "test-user", "pass" - if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), expected...); err != nil { + if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "test-role"), cx.envMap, expected...); err != nil { cx.t.Fatal(err) } @@ -935,7 +935,7 @@ func authTestRoleGet(cx ctlCtx) { expected = []string{ "Error: etcdserver: permission denied", } - if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "root"), expected...); err != nil { + if err := spawnWithExpects(append(cx.PrefixArgs(), "role", "get", "root"), cx.envMap, expected...); err != nil { cx.t.Fatal(err) } } @@ -952,13 +952,13 @@ func authTestUserGet(cx ctlCtx) { "Roles: test-role", } - if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil { + if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), cx.envMap, expected...); err != nil { cx.t.Fatal(err) } // test-user can get the information of test-user itself cx.user, cx.pass = "test-user", "pass" - if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), expected...); err != nil { + if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "test-user"), cx.envMap, expected...); err != nil { cx.t.Fatal(err) } @@ -966,7 +966,7 @@ func authTestUserGet(cx ctlCtx) { expected = []string{ "Error: etcdserver: permission denied", } - if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "root"), expected...); err != nil { + if err := spawnWithExpects(append(cx.PrefixArgs(), "user", "get", "root"), cx.envMap, expected...); err != nil { cx.t.Fatal(err) } } @@ -977,7 +977,7 @@ func authTestRoleList(cx ctlCtx) { } cx.user, cx.pass = "root", "root" authSetupTestUser(cx) - if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "list"), "test-role"); err != nil { + if err := spawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "list"), cx.envMap, "test-role"); err != nil { cx.t.Fatal(err) } } @@ -1088,7 +1088,7 @@ func certCNAndUsername(cx ctlCtx, noPassword bool) { cx.t.Fatal(err) } } - if err := spawnWithExpect(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), "Role test-role-cn created"); err != nil { + if err := spawnWithExpectWithEnv(append(cx.PrefixArgs(), "role", "add", "test-role-cn"), cx.envMap, "Role test-role-cn created"); err != nil { cx.t.Fatal(err) } if err := ctlV3User(cx, []string{"grant-role", "example.com", "test-role-cn"}, "Role test-role-cn is granted to user example.com", nil); err != nil { diff --git a/tests/e2e/ctl_v3_compact_test.go b/tests/e2e/ctl_v3_compact_test.go index 5b0c51eb4..4852382c8 100644 --- a/tests/e2e/ctl_v3_compact_test.go +++ b/tests/e2e/ctl_v3_compact_test.go @@ -71,5 +71,5 @@ func ctlV3Compact(cx ctlCtx, rev int64, physical bool) error { if physical { cmdArgs = append(cmdArgs, "--physical") } - return spawnWithExpect(cmdArgs, "compacted revision "+rs) + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "compacted revision "+rs) } diff --git a/tests/e2e/ctl_v3_defrag_test.go b/tests/e2e/ctl_v3_defrag_test.go index 8fbe476f0..f1a63094f 100644 --- a/tests/e2e/ctl_v3_defrag_test.go +++ b/tests/e2e/ctl_v3_defrag_test.go @@ -52,13 +52,13 @@ func ctlV3OnlineDefrag(cx ctlCtx) error { for i := range lines { lines[i] = "Finished defragmenting etcd member" } - return spawnWithExpects(cmdArgs, lines...) + return spawnWithExpects(cmdArgs, cx.envMap, lines...) } func ctlV3OfflineDefrag(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgsUtl(), "defrag", "--data-dir", cx.dataDir) lines := []string{"finished defragmenting directory"} - return spawnWithExpects(cmdArgs, lines...) + return spawnWithExpects(cmdArgs, cx.envMap, lines...) } func defragOfflineTest(cx ctlCtx) { diff --git a/tests/e2e/ctl_v3_elect_test.go b/tests/e2e/ctl_v3_elect_test.go index 332ce9708..9b7891560 100644 --- a/tests/e2e/ctl_v3_elect_test.go +++ b/tests/e2e/ctl_v3_elect_test.go @@ -98,7 +98,7 @@ func testElect(cx ctlCtx) { // ctlV3Elect creates a elect process with a channel listening for when it wins the election. func ctlV3Elect(cx ctlCtx, name, proposal string) (*expect.ExpectProcess, <-chan string, error) { cmdArgs := append(cx.PrefixArgs(), "elect", name, proposal) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) outc := make(chan string, 1) if err != nil { close(outc) diff --git a/tests/e2e/ctl_v3_endpoint_test.go b/tests/e2e/ctl_v3_endpoint_test.go index 3c4e7d72b..33dd7f5c6 100644 --- a/tests/e2e/ctl_v3_endpoint_test.go +++ b/tests/e2e/ctl_v3_endpoint_test.go @@ -40,7 +40,7 @@ func ctlV3EndpointHealth(cx ctlCtx) error { for i := range lines { lines[i] = "is healthy" } - return spawnWithExpects(cmdArgs, lines...) + return spawnWithExpects(cmdArgs, cx.envMap, lines...) } func endpointStatusTest(cx ctlCtx) { @@ -56,7 +56,7 @@ func ctlV3EndpointStatus(cx ctlCtx) error { u, _ := url.Parse(ep) eps = append(eps, u.Host) } - return spawnWithExpects(cmdArgs, eps...) + return spawnWithExpects(cmdArgs, cx.envMap, eps...) } func endpointHashKVTest(cx ctlCtx) { @@ -88,5 +88,5 @@ func ctlV3EndpointHashKV(cx ctlCtx) error { u, _ := url.Parse(ep) ss = append(ss, fmt.Sprintf("%s, %d", u.Host, hresp.Hash)) } - return spawnWithExpects(cmdArgs, ss...) + return spawnWithExpects(cmdArgs, cx.envMap, ss...) } diff --git a/tests/e2e/ctl_v3_kv_test.go b/tests/e2e/ctl_v3_kv_test.go index 1952ddd22..17b156a0d 100644 --- a/tests/e2e/ctl_v3_kv_test.go +++ b/tests/e2e/ctl_v3_kv_test.go @@ -190,7 +190,7 @@ func getFormatTest(cx ctlCtx) { cmdArgs = append(cmdArgs, "--print-value-only") } cmdArgs = append(cmdArgs, "abc") - if err := spawnWithExpect(cmdArgs, tt.wstr); err != nil { + if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, tt.wstr); err != nil { cx.t.Errorf("#%d: error (%v), wanted %v", i, err, tt.wstr) } } @@ -228,24 +228,24 @@ func getKeysOnlyTest(cx ctlCtx) { cx.t.Fatal(err) } cmdArgs := append(cx.PrefixArgs(), []string{"get", "--keys-only", "key"}...) - if err := spawnWithExpect(cmdArgs, "key"); err != nil { + if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, "key"); err != nil { cx.t.Fatal(err) } - if err := spawnWithExpects(cmdArgs, "val"); err == nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "val"); err == nil { cx.t.Fatalf("got value but passed --keys-only") } } func getCountOnlyTest(cx ctlCtx) { cmdArgs := append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) - if err := spawnWithExpects(cmdArgs, "\"Count\" : 0"); err != nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 0"); err != nil { cx.t.Fatal(err) } if err := ctlV3Put(cx, "key", "val", ""); err != nil { cx.t.Fatal(err) } cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) - if err := spawnWithExpects(cmdArgs, "\"Count\" : 1"); err != nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 1"); err != nil { cx.t.Fatal(err) } if err := ctlV3Put(cx, "key1", "val", ""); err != nil { @@ -255,21 +255,21 @@ func getCountOnlyTest(cx ctlCtx) { cx.t.Fatal(err) } cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) - if err := spawnWithExpects(cmdArgs, "\"Count\" : 2"); err != nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 2"); err != nil { cx.t.Fatal(err) } if err := ctlV3Put(cx, "key2", "val", ""); err != nil { cx.t.Fatal(err) } cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) - if err := spawnWithExpects(cmdArgs, "\"Count\" : 3"); err != nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, "\"Count\" : 3"); err != nil { cx.t.Fatal(err) } expected := []string{ "\"Count\" : 3", } cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key3", "--prefix", "--write-out=fields"}...) - if err := spawnWithExpects(cmdArgs, expected...); err == nil { + if err := spawnWithExpects(cmdArgs, cx.envMap, expected...); err == nil { cx.t.Fatal(err) } } @@ -348,7 +348,7 @@ func ctlV3Put(cx ctlCtx, key, value, leaseID string, flags ...string) error { if len(flags) != 0 { cmdArgs = append(cmdArgs, flags...) } - return spawnWithExpect(cmdArgs, "OK") + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "OK") } type kv struct { @@ -365,7 +365,7 @@ func ctlV3Get(cx ctlCtx, args []string, kvs ...kv) error { for _, elem := range kvs { lines = append(lines, elem.key, elem.val) } - return spawnWithExpects(cmdArgs, lines...) + return spawnWithExpects(cmdArgs, cx.envMap, lines...) } // ctlV3GetWithErr runs "get" command expecting no output but error @@ -375,11 +375,11 @@ func ctlV3GetWithErr(cx ctlCtx, args []string, errs []string) error { if !cx.quorum { cmdArgs = append(cmdArgs, "--consistency", "s") } - return spawnWithExpects(cmdArgs, errs...) + return spawnWithExpects(cmdArgs, cx.envMap, errs...) } func ctlV3Del(cx ctlCtx, args []string, num int) error { cmdArgs := append(cx.PrefixArgs(), "del") cmdArgs = append(cmdArgs, args...) - return spawnWithExpects(cmdArgs, fmt.Sprintf("%d", num)) + return spawnWithExpects(cmdArgs, cx.envMap, fmt.Sprintf("%d", num)) } diff --git a/tests/e2e/ctl_v3_lease_test.go b/tests/e2e/ctl_v3_lease_test.go index 59e47bc1f..0dc445202 100644 --- a/tests/e2e/ctl_v3_lease_test.go +++ b/tests/e2e/ctl_v3_lease_test.go @@ -113,7 +113,7 @@ func leaseTestGrantTimeToLive(cx ctlCtx) { } cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", id, "--keys") - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { cx.t.Fatalf("leaseTestGrantTimeToLive: error (%v)", err) } @@ -146,7 +146,7 @@ func leaseTestGrantLeasesList(cx ctlCtx) error { } cmdArgs := append(cx.PrefixArgs(), "lease", "list") - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return fmt.Errorf("lease list failed (%v)", err) } @@ -177,7 +177,7 @@ func leaseTestTimeToLiveExpire(cx ctlCtx, ttl int) error { time.Sleep(time.Duration(ttl+1) * time.Second) cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", leaseID) exp := fmt.Sprintf("lease %s already expired", leaseID) - if err = spawnWithExpect(cmdArgs, exp); err != nil { + if err = spawnWithExpectWithEnv(cmdArgs, cx.envMap, exp); err != nil { return fmt.Errorf("lease not properly expired: (%v)", err) } if err := ctlV3Get(cx, []string{"key"}); err != nil { @@ -247,7 +247,7 @@ func leaseTestRevoke(cx ctlCtx) error { func ctlV3LeaseGrant(cx ctlCtx, ttl int) (string, error) { cmdArgs := append(cx.PrefixArgs(), "lease", "grant", strconv.Itoa(ttl)) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return "", err } @@ -271,7 +271,7 @@ func ctlV3LeaseGrant(cx ctlCtx, ttl int) (string, error) { func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error { cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", leaseID) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, nil) if err != nil { return err } @@ -285,7 +285,7 @@ func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error { func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error { cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", "--once", leaseID) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, nil) if err != nil { return err } @@ -298,5 +298,5 @@ func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error { func ctlV3LeaseRevoke(cx ctlCtx, leaseID string) error { cmdArgs := append(cx.PrefixArgs(), "lease", "revoke", leaseID) - return spawnWithExpect(cmdArgs, fmt.Sprintf("lease %s revoked", leaseID)) + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("lease %s revoked", leaseID)) } diff --git a/tests/e2e/ctl_v3_lock_test.go b/tests/e2e/ctl_v3_lock_test.go index e88000a15..5330afb0a 100644 --- a/tests/e2e/ctl_v3_lock_test.go +++ b/tests/e2e/ctl_v3_lock_test.go @@ -119,7 +119,7 @@ func testLockWithCmd(cx ctlCtx) { // ctlV3Lock creates a lock process with a channel listening for when it acquires the lock. func ctlV3Lock(cx ctlCtx, name string) (*expect.ExpectProcess, <-chan string, error) { cmdArgs := append(cx.PrefixArgs(), "lock", name) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) outc := make(chan string, 1) if err != nil { close(outc) @@ -140,5 +140,5 @@ func ctlV3LockWithCmd(cx ctlCtx, execCmd []string, as ...string) error { // use command as lock name cmdArgs := append(cx.PrefixArgs(), "lock", execCmd[0]) cmdArgs = append(cmdArgs, execCmd...) - return spawnWithExpects(cmdArgs, as...) + return spawnWithExpects(cmdArgs, cx.envMap, as...) } diff --git a/tests/e2e/ctl_v3_make_mirror_test.go b/tests/e2e/ctl_v3_make_mirror_test.go index f15340670..491af15bd 100644 --- a/tests/e2e/ctl_v3_make_mirror_test.go +++ b/tests/e2e/ctl_v3_make_mirror_test.go @@ -83,7 +83,7 @@ func testMirrorCommand(cx ctlCtx, flags []string, sourcekvs []kv, destkvs []kvEx cmdArgs := append(cx.PrefixArgs(), "make-mirror") cmdArgs = append(cmdArgs, flags...) cmdArgs = append(cmdArgs, fmt.Sprintf("localhost:%d", mirrorcfg.basePort)) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { cx.t.Fatal(err) } diff --git a/tests/e2e/ctl_v3_member_test.go b/tests/e2e/ctl_v3_member_test.go index 76198569c..f92526ed6 100644 --- a/tests/e2e/ctl_v3_member_test.go +++ b/tests/e2e/ctl_v3_member_test.go @@ -95,13 +95,13 @@ func ctlV3MemberList(cx ctlCtx) error { for i := range lines { lines[i] = "started" } - return spawnWithExpects(cmdArgs, lines...) + return spawnWithExpects(cmdArgs, cx.envMap, lines...) } func getMemberList(cx ctlCtx) (etcdserverpb.MemberListResponse, error) { cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "member", "list") - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return etcdserverpb.MemberListResponse{}, err } @@ -130,7 +130,7 @@ func memberListWithHexTest(cx ctlCtx) { cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "--hex", "member", "list") - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { cx.t.Fatalf("memberListWithHexTest error (%v)", err) } @@ -177,7 +177,7 @@ func memberRemoveTest(cx ctlCtx) { func ctlV3MemberRemove(cx ctlCtx, ep, memberID, clusterID string) error { cmdArgs := append(cx.prefixArgs([]string{ep}), "member", "remove", memberID) - return spawnWithExpect(cmdArgs, fmt.Sprintf("%s removed from cluster %s", memberID, clusterID)) + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("%s removed from cluster %s", memberID, clusterID)) } func memberAddTest(cx ctlCtx) { @@ -197,7 +197,7 @@ func ctlV3MemberAdd(cx ctlCtx, peerURL string, isLearner bool) error { if isLearner { cmdArgs = append(cmdArgs, "--learner") } - return spawnWithExpect(cmdArgs, " added to cluster ") + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, " added to cluster ") } func memberUpdateTest(cx ctlCtx) { @@ -215,5 +215,5 @@ func memberUpdateTest(cx ctlCtx) { func ctlV3MemberUpdate(cx ctlCtx, memberID, peerURL string) error { cmdArgs := append(cx.PrefixArgs(), "member", "update", memberID, fmt.Sprintf("--peer-urls=%s", peerURL)) - return spawnWithExpect(cmdArgs, " updated in cluster ") + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, " updated in cluster ") } diff --git a/tests/e2e/ctl_v3_move_leader_test.go b/tests/e2e/ctl_v3_move_leader_test.go index 08abc37e2..05dc49939 100644 --- a/tests/e2e/ctl_v3_move_leader_test.go +++ b/tests/e2e/ctl_v3_move_leader_test.go @@ -97,21 +97,22 @@ func testCtlV3MoveLeader(t *testing.T, cfg etcdProcessClusterConfig) { } tests := []struct { - prefixes []string - expect string + eps []string + expect string }{ { // request to non-leader - cx.prefixArgs([]string{cx.epc.EndpointsV3()[(leadIdx+1)%3]}), + []string{cx.epc.EndpointsV3()[(leadIdx+1)%3]}, "no leader endpoint given at ", }, { // request to leader - cx.prefixArgs([]string{cx.epc.EndpointsV3()[leadIdx]}), + []string{cx.epc.EndpointsV3()[leadIdx]}, fmt.Sprintf("Leadership transferred from %s to %s", types.ID(leaderID), types.ID(transferee)), }, } for i, tc := range tests { - cmdArgs := append(tc.prefixes, "move-leader", types.ID(transferee).String()) - if err := spawnWithExpect(cmdArgs, tc.expect); err != nil { + prefix := cx.prefixArgs(tc.eps) + cmdArgs := append(prefix, "move-leader", types.ID(transferee).String()) + if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, tc.expect); err != nil { t.Fatalf("#%d: %v", i, err) } } diff --git a/tests/e2e/ctl_v3_role_test.go b/tests/e2e/ctl_v3_role_test.go index fb4e5de60..1200bb5bf 100644 --- a/tests/e2e/ctl_v3_role_test.go +++ b/tests/e2e/ctl_v3_role_test.go @@ -96,7 +96,7 @@ func ctlV3Role(cx ctlCtx, args []string, expStr string) error { cmdArgs := append(cx.PrefixArgs(), "role") cmdArgs = append(cmdArgs, args...) - return spawnWithExpect(cmdArgs, expStr) + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, expStr) } func ctlV3RoleGrantPermission(cx ctlCtx, rolename string, perm grantingPerm) error { @@ -110,7 +110,7 @@ func ctlV3RoleGrantPermission(cx ctlCtx, rolename string, perm grantingPerm) err cmdArgs = append(cmdArgs, rolename) cmdArgs = append(cmdArgs, grantingPermToArgs(perm)...) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return err } @@ -136,7 +136,7 @@ func ctlV3RoleRevokePermission(cx ctlCtx, rolename string, key, rangeEnd string, expStr = fmt.Sprintf("Permission of key %s is revoked from role %s", key, rolename) } - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return err } diff --git a/tests/e2e/ctl_v3_snapshot_test.go b/tests/e2e/ctl_v3_snapshot_test.go index ce172f4c1..ea2b5ec21 100644 --- a/tests/e2e/ctl_v3_snapshot_test.go +++ b/tests/e2e/ctl_v3_snapshot_test.go @@ -84,10 +84,11 @@ func snapshotCorruptTest(cx ctlCtx) { datadir := cx.t.TempDir() - serr := spawnWithExpect( + serr := spawnWithExpectWithEnv( append(cx.PrefixArgsUtl(), "snapshot", "restore", "--data-dir", datadir, fpath), + cx.envMap, "expected sha256") if serr != nil { @@ -117,10 +118,11 @@ func snapshotStatusBeforeRestoreTest(cx ctlCtx) { dataDir := cx.t.TempDir() defer os.RemoveAll(dataDir) - serr := spawnWithExpect( + serr := spawnWithExpectWithEnv( append(cx.PrefixArgsUtl(), "snapshot", "restore", "--data-dir", dataDir, fpath), + cx.envMap, "added member") if serr != nil { cx.t.Fatal(serr) @@ -129,13 +131,13 @@ func snapshotStatusBeforeRestoreTest(cx ctlCtx) { func ctlV3SnapshotSave(cx ctlCtx, fpath string) error { cmdArgs := append(cx.PrefixArgs(), "snapshot", "save", fpath) - return spawnWithExpect(cmdArgs, fmt.Sprintf("Snapshot saved at %s", fpath)) + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, fmt.Sprintf("Snapshot saved at %s", fpath)) } func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) { cmdArgs := append(cx.PrefixArgsUtl(), "--write-out", "json", "snapshot", "status", fpath) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, nil) if err != nil { return snapshot.Status{}, err } @@ -202,7 +204,10 @@ func testIssue6361(t *testing.T, etcdutl bool) { fpath := filepath.Join(t.TempDir(), "test.snapshot") t.Log("etcdctl saving snapshot...") - if err = spawnWithExpect(append(prefixArgs, "snapshot", "save", fpath), fmt.Sprintf("Snapshot saved at %s", fpath)); err != nil { + if err = spawnWithExpects(append(prefixArgs, "snapshot", "save", fpath), + nil, + fmt.Sprintf("Snapshot saved at %s", fpath), + ); err != nil { t.Fatal(err) } @@ -262,7 +267,7 @@ func testIssue6361(t *testing.T, etcdutl bool) { nepc, err = spawnCmd([]string{epc.procs[0].Config().execPath, "--name", name2, "--listen-client-urls", clientURL, "--advertise-client-urls", clientURL, "--listen-peer-urls", peerURL, "--initial-advertise-peer-urls", peerURL, - "--initial-cluster", initialCluster2, "--initial-cluster-state", "existing", "--data-dir", newDataDir2}) + "--initial-cluster", initialCluster2, "--initial-cluster-state", "existing", "--data-dir", newDataDir2}, nil) if err != nil { t.Fatal(err) } diff --git a/tests/e2e/ctl_v3_test.go b/tests/e2e/ctl_v3_test.go index 5c8bb2fe9..320b81e64 100644 --- a/tests/e2e/ctl_v3_test.go +++ b/tests/e2e/ctl_v3_test.go @@ -104,7 +104,7 @@ func clusterVersionTest(cx ctlCtx, expected string) { func ctlV3Version(cx ctlCtx) error { cmdArgs := append(cx.PrefixArgs(), "version") - return spawnWithExpect(cmdArgs, version.Version) + return spawnWithExpectWithEnv(cmdArgs, cx.envMap, version.Version) } // TestCtlV3DialWithHTTPScheme ensures that client handles endpoints with HTTPS scheme. @@ -114,7 +114,7 @@ func TestCtlV3DialWithHTTPScheme(t *testing.T) { func dialWithSchemeTest(cx ctlCtx) { cmdArgs := append(cx.prefixArgs(cx.epc.EndpointsV3()), "put", "foo", "bar") - if err := spawnWithExpect(cmdArgs, "OK"); err != nil { + if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, "OK"); err != nil { cx.t.Fatal(err) } } @@ -129,7 +129,7 @@ type ctlCtx struct { epc *etcdProcessCluster - envMap map[string]struct{} + envMap map[string]string dialTimeout time.Duration @@ -201,7 +201,7 @@ func withApiPrefix(p string) ctlOption { } func withFlagByEnv() ctlOption { - return func(cx *ctlCtx) { cx.envMap = make(map[string]struct{}) } + return func(cx *ctlCtx) { cx.envMap = make(map[string]string) } } func withEtcdutl() ctlOption { @@ -248,6 +248,7 @@ func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc fun for k := range ret.envMap { os.Unsetenv(k) } + ret.envMap = make(map[string]string) } if ret.epc != nil { if errC := ret.epc.Close(); errC != nil { @@ -311,8 +312,7 @@ func (cx *ctlCtx) prefixArgs(eps []string) []string { for k, v := range fmap { if useEnv { ek := flags.FlagToEnv("ETCDCTL", k) - os.Setenv(ek, v) - cx.envMap[ek] = struct{}{} + cx.envMap[ek] = v } else { cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) } diff --git a/tests/e2e/ctl_v3_txn_test.go b/tests/e2e/ctl_v3_txn_test.go index bbcec5db6..6fd4ed16b 100644 --- a/tests/e2e/ctl_v3_txn_test.go +++ b/tests/e2e/ctl_v3_txn_test.go @@ -102,7 +102,7 @@ func ctlV3Txn(cx ctlCtx, rqs txnRequests) error { if cx.interactive { cmdArgs = append(cmdArgs, "--interactive") } - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return err } diff --git a/tests/e2e/ctl_v3_user_test.go b/tests/e2e/ctl_v3_user_test.go index 8672ae7b6..d4e409a17 100644 --- a/tests/e2e/ctl_v3_user_test.go +++ b/tests/e2e/ctl_v3_user_test.go @@ -179,7 +179,7 @@ func ctlV3User(cx ctlCtx, args []string, expStr string, stdIn []string) error { cmdArgs := append(cx.PrefixArgs(), "user") cmdArgs = append(cmdArgs, args...) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) if err != nil { return err } diff --git a/tests/e2e/ctl_v3_watch_test.go b/tests/e2e/ctl_v3_watch_test.go index fe25da1b7..0e0f24e94 100644 --- a/tests/e2e/ctl_v3_watch_test.go +++ b/tests/e2e/ctl_v3_watch_test.go @@ -35,7 +35,7 @@ func setupWatchArgs(cx ctlCtx, args []string) []string { func ctlV3Watch(cx ctlCtx, args []string, kvs ...kvExec) error { cmdArgs := setupWatchArgs(cx, args) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, nil) if err != nil { return err } @@ -66,7 +66,7 @@ func ctlV3Watch(cx ctlCtx, args []string, kvs ...kvExec) error { func ctlV3WatchFailPerm(cx ctlCtx, args []string) error { cmdArgs := setupWatchArgs(cx, args) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, nil) if err != nil { return err } diff --git a/tests/e2e/etcd_config_test.go b/tests/e2e/etcd_config_test.go index ef39a52e5..266cb971b 100644 --- a/tests/e2e/etcd_config_test.go +++ b/tests/e2e/etcd_config_test.go @@ -29,7 +29,7 @@ const exampleConfigFile = "../../etcd.conf.yml.sample" func TestEtcdExampleConfig(t *testing.T) { skipInShortMode(t) - proc, err := spawnCmd([]string{binDir + "/etcd", "--config-file", exampleConfigFile}) + proc, err := spawnCmd([]string{binDir + "/etcd", "--config-file", exampleConfigFile}, nil) if err != nil { t.Fatal(err) } @@ -75,7 +75,7 @@ func TestEtcdMultiPeer(t *testing.T) { "--initial-advertise-peer-urls", fmt.Sprintf("http://127.0.0.1:%d", etcdProcessBasePort+i), "--initial-cluster", ic, } - p, err := spawnCmd(args) + p, err := spawnCmd(args, nil) if err != nil { t.Fatal(err) } @@ -106,7 +106,7 @@ func TestEtcdUnixPeers(t *testing.T) { "--listen-peer-urls", "unix://etcd.unix:1", "--initial-advertise-peer-urls", "unix://etcd.unix:1", "--initial-cluster", "e1=unix://etcd.unix:1", - }, + }, nil, ) defer os.Remove("etcd.unix:1") if err != nil { @@ -183,7 +183,7 @@ func TestEtcdPeerCNAuth(t *testing.T) { commonArgs = append(commonArgs, args...) - p, err := spawnCmd(commonArgs) + p, err := spawnCmd(commonArgs, nil) if err != nil { t.Fatal(err) } @@ -262,7 +262,7 @@ func TestEtcdPeerNameAuth(t *testing.T) { commonArgs = append(commonArgs, args...) - p, err := spawnCmd(commonArgs) + p, err := spawnCmd(commonArgs, nil) if err != nil { t.Fatal(err) } @@ -308,7 +308,7 @@ func TestGrpcproxyAndCommonName(t *testing.T) { t.Errorf("Unexpected error: %s", err) } - p, err := spawnCmd(argsWithEmptyCN) + p, err := spawnCmd(argsWithEmptyCN, nil) defer func() { if p != nil { p.Stop() @@ -323,7 +323,7 @@ func TestGrpcproxyAndCommonName(t *testing.T) { func TestBootstrapDefragFlag(t *testing.T) { skipInShortMode(t) - proc, err := spawnCmd([]string{binDir + "/etcd", "--experimental-bootstrap-defrag-threshold-megabytes", "1000"}) + proc, err := spawnCmd([]string{binDir + "/etcd", "--experimental-bootstrap-defrag-threshold-megabytes", "1000"}, nil) if err != nil { t.Fatal(err) } diff --git a/tests/e2e/etcd_corrupt_test.go b/tests/e2e/etcd_corrupt_test.go index edc95c010..87431b6f6 100644 --- a/tests/e2e/etcd_corrupt_test.go +++ b/tests/e2e/etcd_corrupt_test.go @@ -87,7 +87,7 @@ func corruptTest(cx ctlCtx) { cx.t.Log("restarting etcd[0]") ep := cx.epc.procs[0] - proc, err := spawnCmd(append([]string{ep.Config().execPath}, ep.Config().args...)) + proc, err := spawnCmd(append([]string{ep.Config().execPath}, ep.Config().args...), cx.envMap) if err != nil { cx.t.Fatal(err) } diff --git a/tests/e2e/etcd_process.go b/tests/e2e/etcd_process.go index f744fa81c..c61001cec 100644 --- a/tests/e2e/etcd_process.go +++ b/tests/e2e/etcd_process.go @@ -92,7 +92,7 @@ func (ep *etcdServerProcess) Start() error { panic("already started") } ep.cfg.lg.Info("starting server...", zap.String("name", ep.cfg.name)) - proc, err := spawnCmdWithLogger(ep.cfg.lg, append([]string{ep.cfg.execPath}, ep.cfg.args...)) + proc, err := spawnCmdWithLogger(ep.cfg.lg, append([]string{ep.cfg.execPath}, ep.cfg.args...), nil) if err != nil { return err } diff --git a/tests/e2e/etcd_spawn_nocov.go b/tests/e2e/etcd_spawn_nocov.go index b0e872fb2..2ed551394 100644 --- a/tests/e2e/etcd_spawn_nocov.go +++ b/tests/e2e/etcd_spawn_nocov.go @@ -18,6 +18,7 @@ package e2e import ( + "fmt" "os" "strings" @@ -27,20 +28,41 @@ import ( const noOutputLineCount = 0 // regular binaries emit no extra lines -func spawnCmd(args []string) (*expect.ExpectProcess, error) { - return spawnCmdWithLogger(zap.NewNop(), args) +func spawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) { + return spawnCmdWithLogger(zap.NewNop(), args, envVars) } -func spawnCmdWithLogger(lg *zap.Logger, args []string) (*expect.ExpectProcess, error) { +func spawnCmdWithLogger(lg *zap.Logger, args []string, envVars map[string]string) (*expect.ExpectProcess, error) { wd, err := os.Getwd() if err != nil { return nil, err } + env := mergeEnvVariables(envVars) if strings.HasSuffix(args[0], "/etcdctl3") { - env := append(os.Environ(), "ETCDCTL_API=3") - lg.Info("spawning process with ETCDCTL_API=3", zap.Strings("args", args), zap.String("working-dir", wd)) + env = append(env, "ETCDCTL_API=3") + lg.Info("spawning process with ETCDCTL_API=3", zap.Strings("args", args), zap.String("working-dir", wd), zap.Strings("environment-variables", env)) return expect.NewExpectWithEnv(ctlBinPath, args[1:], env) } - lg.Info("spawning process", zap.Strings("args", args), zap.String("working-dir", wd)) - return expect.NewExpect(args[0], args[1:]...) + lg.Info("spawning process", zap.Strings("args", args), zap.String("working-dir", wd), zap.Strings("environment-variables", env)) + return expect.NewExpectWithEnv(args[0], args[1:], env) +} + +func mergeEnvVariables(envVars map[string]string) []string { + var env []string + // Environment variables are passed as parameter have higher priority + // than os environment variables. + for k, v := range envVars { + env = append(env, fmt.Sprintf("%s=%s", k, v)) + } + + // Now, we can set os environment variables not passed as parameter. + currVars := os.Environ() + for _, v := range currVars { + p := strings.Split(v, "=") + if _, ok := envVars[p[0]]; !ok { + env = append(env, fmt.Sprintf("%s=%s", p[0], p[1])) + } + } + + return env } diff --git a/tests/e2e/util.go b/tests/e2e/util.go index 2841d94fb..2aa45bc95 100644 --- a/tests/e2e/util.go +++ b/tests/e2e/util.go @@ -40,16 +40,20 @@ func waitReadyExpectProc(exproc *expect.ExpectProcess, readyStrs []string) error } func spawnWithExpect(args []string, expected string) error { - return spawnWithExpects(args, []string{expected}...) + return spawnWithExpects(args, nil, []string{expected}...) } -func spawnWithExpects(args []string, xs ...string) error { - _, err := spawnWithExpectLines(args, xs...) +func spawnWithExpectWithEnv(args []string, envVars map[string]string, expected string) error { + return spawnWithExpects(args, envVars, []string{expected}...) +} + +func spawnWithExpects(args []string, envVars map[string]string, xs ...string) error { + _, err := spawnWithExpectLines(args, envVars, xs...) return err } -func spawnWithExpectLines(args []string, xs ...string) ([]string, error) { - proc, err := spawnCmd(args) +func spawnWithExpectLines(args []string, envVars map[string]string, xs ...string) ([]string, error) { + proc, err := spawnCmd(args, envVars) if err != nil { return nil, err } diff --git a/tests/e2e/v2store_deprecation_test.go b/tests/e2e/v2store_deprecation_test.go index 06ad555d0..cf6c28200 100644 --- a/tests/e2e/v2store_deprecation_test.go +++ b/tests/e2e/v2store_deprecation_test.go @@ -63,7 +63,7 @@ func assertVerifyCanStartV2deprecationNotYet(t testing.TB, dataDirPath string) { func assertVerifyCannotStartV2deprecationWriteOnly(t testing.TB, dataDirPath string) { t.Log("Verify its infeasible to start etcd with --v2-deprecation=write-only mode") - proc, err := spawnCmd([]string{binDir + "/etcd", "--v2-deprecation=write-only", "--data-dir=" + dataDirPath}) + proc, err := spawnCmd([]string{binDir + "/etcd", "--v2-deprecation=write-only", "--data-dir=" + dataDirPath}, nil) assert.NoError(t, err) _, err = proc.Expect("detected disallowed custom content in v2store for stage --v2-deprecation=write-only") @@ -90,7 +90,7 @@ func TestV2Deprecation(t *testing.T) { func TestV2DeprecationWriteOnlyNoV2Api(t *testing.T) { BeforeTest(t) - proc, err := spawnCmd([]string{binDir + "/etcd", "--v2-deprecation=write-only", "--enable-v2"}) + proc, err := spawnCmd([]string{binDir + "/etcd", "--v2-deprecation=write-only", "--enable-v2"}, nil) assert.NoError(t, err) _, err = proc.Expect("--enable-v2 and --v2-deprecation=write-only are mutually exclusive") diff --git a/tests/e2e/v3_curl_test.go b/tests/e2e/v3_curl_test.go index 7c6971150..4c34fda4d 100644 --- a/tests/e2e/v3_curl_test.go +++ b/tests/e2e/v3_curl_test.go @@ -244,7 +244,7 @@ func testV3CurlAuth(cx ctlCtx) { ) cmdArgs = cURLPrefixArgs(cx.epc, "POST", cURLReq{endpoint: path.Join(p, "/auth/authenticate"), value: string(authreq)}) - proc, err := spawnCmd(cmdArgs) + proc, err := spawnCmd(cmdArgs, cx.envMap) testutil.AssertNil(cx.t, err) defer proc.Close() @@ -286,7 +286,7 @@ func testV3CurlCampaign(cx ctlCtx) { endpoint: path.Join(cx.apiPrefix, "/election/campaign"), value: string(cdata), }) - lines, err := spawnWithExpectLines(cargs, `"leader":{"name":"`) + lines, err := spawnWithExpectLines(cargs, cx.envMap, `"leader":{"name":"`) if err != nil { cx.t.Fatalf("failed post campaign request (%s) (%v)", cx.apiPrefix, err) }