Decouple prefixArgs from os.Env dependency

prefixArgs uses os.Setenv in e2e tests instead envMap.
This creates overwrites in some test cases and have an impact
on test quality and isolation between tests.
This PR uses ctlcontext envMap in each tests with high priority
and merges os environment variables with low priority.
This commit is contained in:
Arda Güçlü 2021-09-13 12:28:56 +03:00 committed by Marek Siarkowicz
parent 4312298b73
commit 6e2fe84ebd
27 changed files with 139 additions and 107 deletions

View File

@ -132,7 +132,7 @@ func (pp *proxyProc) start() error {
if pp.proc != nil { if pp.proc != nil {
panic("already started") 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 { if err != nil {
return err return err
} }

View File

@ -505,7 +505,7 @@ func etcdctlBackup(t testing.TB, clus *etcdProcessCluster, dataDir, backupDir st
cmdArgs = append(cmdArgs, "--with-v3=false") cmdArgs = append(cmdArgs, "--with-v3=false")
} }
t.Logf("Running: %v", cmdArgs) t.Logf("Running: %v", cmdArgs)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@ -101,5 +101,5 @@ func alarmTest(cx ctlCtx) {
func ctlV3Alarm(cx ctlCtx, cmd string, as ...string) error { func ctlV3Alarm(cx ctlCtx, cmd string, as ...string) error {
cmdArgs := append(cx.PrefixArgs(), "alarm", cmd) cmdArgs := append(cx.PrefixArgs(), "alarm", cmd)
return spawnWithExpects(cmdArgs, as...) return spawnWithExpects(cmdArgs, cx.envMap, as...)
} }

View File

@ -93,7 +93,7 @@ func authEnable(cx ctlCtx) error {
func ctlV3AuthEnable(cx ctlCtx) error { func ctlV3AuthEnable(cx ctlCtx) error {
cmdArgs := append(cx.PrefixArgs(), "auth", "enable") cmdArgs := append(cx.PrefixArgs(), "auth", "enable")
return spawnWithExpect(cmdArgs, "Authentication Enabled") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Enabled")
} }
func authDisableTest(cx ctlCtx) { func authDisableTest(cx ctlCtx) {
@ -139,12 +139,12 @@ func authDisableTest(cx ctlCtx) {
func ctlV3AuthDisable(cx ctlCtx) error { func ctlV3AuthDisable(cx ctlCtx) error {
cmdArgs := append(cx.PrefixArgs(), "auth", "disable") cmdArgs := append(cx.PrefixArgs(), "auth", "disable")
return spawnWithExpect(cmdArgs, "Authentication Disabled") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "Authentication Disabled")
} }
func authStatusTest(cx ctlCtx) { func authStatusTest(cx ctlCtx) {
cmdArgs := append(cx.PrefixArgs(), "auth", "status") 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) cx.t.Fatal(err)
} }
@ -155,15 +155,15 @@ func authStatusTest(cx ctlCtx) {
cx.user, cx.pass = "root", "root" cx.user, cx.pass = "root", "root"
cmdArgs = append(cx.PrefixArgs(), "auth", "status") 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) cx.t.Fatal(err)
} }
cmdArgs = append(cx.PrefixArgs(), "auth", "status", "--write-out", "json") 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) cx.t.Fatal(err)
} }
if err := spawnWithExpect(cmdArgs, "authRevision"); err != nil { if err := spawnWithExpectWithEnv(cmdArgs, cx.envMap, "authRevision"); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
} }
@ -381,25 +381,25 @@ func authRoleRevokeDuringOpsTest(cx ctlCtx) {
} }
func ctlV3PutFailAuth(cx ctlCtx, key, val string) error { 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 { 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) { func authSetupTestUser(cx ctlCtx) {
if err := ctlV3User(cx, []string{"add", "test-user", "--interactive=false"}, "User test-user created", []string{"pass"}); err != nil { if err := ctlV3User(cx, []string{"add", "test-user", "--interactive=false"}, "User test-user created", []string{"pass"}); err != nil {
cx.t.Fatal(err) 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) 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 { 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) cx.t.Fatal(err)
} }
cmd := append(cx.PrefixArgs(), "role", "grant-permission", "test-role", "readwrite", "foo") 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) 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 { if err := ctlV3User(cx, []string{"add", "example.com", "--interactive=false"}, "User example.com created", []string{""}); err != nil {
cx.t.Fatal(err) 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) 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 { 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 Read:", "foo",
"KV Write:", "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) cx.t.Fatal(err)
} }
// test-user can get the information of test-role because it belongs to the role // test-user can get the information of test-role because it belongs to the role
cx.user, cx.pass = "test-user", "pass" 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) cx.t.Fatal(err)
} }
@ -935,7 +935,7 @@ func authTestRoleGet(cx ctlCtx) {
expected = []string{ expected = []string{
"Error: etcdserver: permission denied", "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) cx.t.Fatal(err)
} }
} }
@ -952,13 +952,13 @@ func authTestUserGet(cx ctlCtx) {
"Roles: test-role", "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) cx.t.Fatal(err)
} }
// test-user can get the information of test-user itself // test-user can get the information of test-user itself
cx.user, cx.pass = "test-user", "pass" 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) cx.t.Fatal(err)
} }
@ -966,7 +966,7 @@ func authTestUserGet(cx ctlCtx) {
expected = []string{ expected = []string{
"Error: etcdserver: permission denied", "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) cx.t.Fatal(err)
} }
} }
@ -977,7 +977,7 @@ func authTestRoleList(cx ctlCtx) {
} }
cx.user, cx.pass = "root", "root" cx.user, cx.pass = "root", "root"
authSetupTestUser(cx) 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) cx.t.Fatal(err)
} }
} }
@ -1088,7 +1088,7 @@ func certCNAndUsername(cx ctlCtx, noPassword bool) {
cx.t.Fatal(err) 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) 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 { 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 {

View File

@ -71,5 +71,5 @@ func ctlV3Compact(cx ctlCtx, rev int64, physical bool) error {
if physical { if physical {
cmdArgs = append(cmdArgs, "--physical") cmdArgs = append(cmdArgs, "--physical")
} }
return spawnWithExpect(cmdArgs, "compacted revision "+rs) return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "compacted revision "+rs)
} }

View File

@ -52,13 +52,13 @@ func ctlV3OnlineDefrag(cx ctlCtx) error {
for i := range lines { for i := range lines {
lines[i] = "Finished defragmenting etcd member" lines[i] = "Finished defragmenting etcd member"
} }
return spawnWithExpects(cmdArgs, lines...) return spawnWithExpects(cmdArgs, cx.envMap, lines...)
} }
func ctlV3OfflineDefrag(cx ctlCtx) error { func ctlV3OfflineDefrag(cx ctlCtx) error {
cmdArgs := append(cx.PrefixArgsUtl(), "defrag", "--data-dir", cx.dataDir) cmdArgs := append(cx.PrefixArgsUtl(), "defrag", "--data-dir", cx.dataDir)
lines := []string{"finished defragmenting directory"} lines := []string{"finished defragmenting directory"}
return spawnWithExpects(cmdArgs, lines...) return spawnWithExpects(cmdArgs, cx.envMap, lines...)
} }
func defragOfflineTest(cx ctlCtx) { func defragOfflineTest(cx ctlCtx) {

View File

@ -98,7 +98,7 @@ func testElect(cx ctlCtx) {
// ctlV3Elect creates a elect process with a channel listening for when it wins the election. // 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) { func ctlV3Elect(cx ctlCtx, name, proposal string) (*expect.ExpectProcess, <-chan string, error) {
cmdArgs := append(cx.PrefixArgs(), "elect", name, proposal) cmdArgs := append(cx.PrefixArgs(), "elect", name, proposal)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
outc := make(chan string, 1) outc := make(chan string, 1)
if err != nil { if err != nil {
close(outc) close(outc)

View File

@ -40,7 +40,7 @@ func ctlV3EndpointHealth(cx ctlCtx) error {
for i := range lines { for i := range lines {
lines[i] = "is healthy" lines[i] = "is healthy"
} }
return spawnWithExpects(cmdArgs, lines...) return spawnWithExpects(cmdArgs, cx.envMap, lines...)
} }
func endpointStatusTest(cx ctlCtx) { func endpointStatusTest(cx ctlCtx) {
@ -56,7 +56,7 @@ func ctlV3EndpointStatus(cx ctlCtx) error {
u, _ := url.Parse(ep) u, _ := url.Parse(ep)
eps = append(eps, u.Host) eps = append(eps, u.Host)
} }
return spawnWithExpects(cmdArgs, eps...) return spawnWithExpects(cmdArgs, cx.envMap, eps...)
} }
func endpointHashKVTest(cx ctlCtx) { func endpointHashKVTest(cx ctlCtx) {
@ -88,5 +88,5 @@ func ctlV3EndpointHashKV(cx ctlCtx) error {
u, _ := url.Parse(ep) u, _ := url.Parse(ep)
ss = append(ss, fmt.Sprintf("%s, %d", u.Host, hresp.Hash)) ss = append(ss, fmt.Sprintf("%s, %d", u.Host, hresp.Hash))
} }
return spawnWithExpects(cmdArgs, ss...) return spawnWithExpects(cmdArgs, cx.envMap, ss...)
} }

View File

@ -190,7 +190,7 @@ func getFormatTest(cx ctlCtx) {
cmdArgs = append(cmdArgs, "--print-value-only") cmdArgs = append(cmdArgs, "--print-value-only")
} }
cmdArgs = append(cmdArgs, "abc") 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) cx.t.Errorf("#%d: error (%v), wanted %v", i, err, tt.wstr)
} }
} }
@ -228,24 +228,24 @@ func getKeysOnlyTest(cx ctlCtx) {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
cmdArgs := append(cx.PrefixArgs(), []string{"get", "--keys-only", "key"}...) 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) 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") cx.t.Fatalf("got value but passed --keys-only")
} }
} }
func getCountOnlyTest(cx ctlCtx) { func getCountOnlyTest(cx ctlCtx) {
cmdArgs := append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) 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) cx.t.Fatal(err)
} }
if err := ctlV3Put(cx, "key", "val", ""); err != nil { if err := ctlV3Put(cx, "key", "val", ""); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) 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) cx.t.Fatal(err)
} }
if err := ctlV3Put(cx, "key1", "val", ""); err != nil { if err := ctlV3Put(cx, "key1", "val", ""); err != nil {
@ -255,21 +255,21 @@ func getCountOnlyTest(cx ctlCtx) {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) 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) cx.t.Fatal(err)
} }
if err := ctlV3Put(cx, "key2", "val", ""); err != nil { if err := ctlV3Put(cx, "key2", "val", ""); err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key", "--prefix", "--write-out=fields"}...) 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) cx.t.Fatal(err)
} }
expected := []string{ expected := []string{
"\"Count\" : 3", "\"Count\" : 3",
} }
cmdArgs = append(cx.PrefixArgs(), []string{"get", "--count-only", "key3", "--prefix", "--write-out=fields"}...) 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) cx.t.Fatal(err)
} }
} }
@ -348,7 +348,7 @@ func ctlV3Put(cx ctlCtx, key, value, leaseID string, flags ...string) error {
if len(flags) != 0 { if len(flags) != 0 {
cmdArgs = append(cmdArgs, flags...) cmdArgs = append(cmdArgs, flags...)
} }
return spawnWithExpect(cmdArgs, "OK") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, "OK")
} }
type kv struct { type kv struct {
@ -365,7 +365,7 @@ func ctlV3Get(cx ctlCtx, args []string, kvs ...kv) error {
for _, elem := range kvs { for _, elem := range kvs {
lines = append(lines, elem.key, elem.val) 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 // 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 { if !cx.quorum {
cmdArgs = append(cmdArgs, "--consistency", "s") cmdArgs = append(cmdArgs, "--consistency", "s")
} }
return spawnWithExpects(cmdArgs, errs...) return spawnWithExpects(cmdArgs, cx.envMap, errs...)
} }
func ctlV3Del(cx ctlCtx, args []string, num int) error { func ctlV3Del(cx ctlCtx, args []string, num int) error {
cmdArgs := append(cx.PrefixArgs(), "del") cmdArgs := append(cx.PrefixArgs(), "del")
cmdArgs = append(cmdArgs, args...) cmdArgs = append(cmdArgs, args...)
return spawnWithExpects(cmdArgs, fmt.Sprintf("%d", num)) return spawnWithExpects(cmdArgs, cx.envMap, fmt.Sprintf("%d", num))
} }

View File

@ -113,7 +113,7 @@ func leaseTestGrantTimeToLive(cx ctlCtx) {
} }
cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", id, "--keys") cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", id, "--keys")
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
cx.t.Fatalf("leaseTestGrantTimeToLive: error (%v)", err) cx.t.Fatalf("leaseTestGrantTimeToLive: error (%v)", err)
} }
@ -146,7 +146,7 @@ func leaseTestGrantLeasesList(cx ctlCtx) error {
} }
cmdArgs := append(cx.PrefixArgs(), "lease", "list") cmdArgs := append(cx.PrefixArgs(), "lease", "list")
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
return fmt.Errorf("lease list failed (%v)", err) 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) time.Sleep(time.Duration(ttl+1) * time.Second)
cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", leaseID) cmdArgs := append(cx.PrefixArgs(), "lease", "timetolive", leaseID)
exp := fmt.Sprintf("lease %s already expired", 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) return fmt.Errorf("lease not properly expired: (%v)", err)
} }
if err := ctlV3Get(cx, []string{"key"}); err != nil { 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) { func ctlV3LeaseGrant(cx ctlCtx, ttl int) (string, error) {
cmdArgs := append(cx.PrefixArgs(), "lease", "grant", strconv.Itoa(ttl)) cmdArgs := append(cx.PrefixArgs(), "lease", "grant", strconv.Itoa(ttl))
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -271,7 +271,7 @@ func ctlV3LeaseGrant(cx ctlCtx, ttl int) (string, error) {
func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error { func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error {
cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", leaseID) cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", leaseID)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, nil)
if err != nil { if err != nil {
return err return err
} }
@ -285,7 +285,7 @@ func ctlV3LeaseKeepAlive(cx ctlCtx, leaseID string) error {
func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error { func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error {
cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", "--once", leaseID) cmdArgs := append(cx.PrefixArgs(), "lease", "keep-alive", "--once", leaseID)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, nil)
if err != nil { if err != nil {
return err return err
} }
@ -298,5 +298,5 @@ func ctlV3LeaseKeepAliveOnce(cx ctlCtx, leaseID string) error {
func ctlV3LeaseRevoke(cx ctlCtx, leaseID string) error { func ctlV3LeaseRevoke(cx ctlCtx, leaseID string) error {
cmdArgs := append(cx.PrefixArgs(), "lease", "revoke", leaseID) 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))
} }

View File

@ -119,7 +119,7 @@ func testLockWithCmd(cx ctlCtx) {
// ctlV3Lock creates a lock process with a channel listening for when it acquires the lock. // 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) { func ctlV3Lock(cx ctlCtx, name string) (*expect.ExpectProcess, <-chan string, error) {
cmdArgs := append(cx.PrefixArgs(), "lock", name) cmdArgs := append(cx.PrefixArgs(), "lock", name)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
outc := make(chan string, 1) outc := make(chan string, 1)
if err != nil { if err != nil {
close(outc) close(outc)
@ -140,5 +140,5 @@ func ctlV3LockWithCmd(cx ctlCtx, execCmd []string, as ...string) error {
// use command as lock name // use command as lock name
cmdArgs := append(cx.PrefixArgs(), "lock", execCmd[0]) cmdArgs := append(cx.PrefixArgs(), "lock", execCmd[0])
cmdArgs = append(cmdArgs, execCmd...) cmdArgs = append(cmdArgs, execCmd...)
return spawnWithExpects(cmdArgs, as...) return spawnWithExpects(cmdArgs, cx.envMap, as...)
} }

View File

@ -83,7 +83,7 @@ func testMirrorCommand(cx ctlCtx, flags []string, sourcekvs []kv, destkvs []kvEx
cmdArgs := append(cx.PrefixArgs(), "make-mirror") cmdArgs := append(cx.PrefixArgs(), "make-mirror")
cmdArgs = append(cmdArgs, flags...) cmdArgs = append(cmdArgs, flags...)
cmdArgs = append(cmdArgs, fmt.Sprintf("localhost:%d", mirrorcfg.basePort)) cmdArgs = append(cmdArgs, fmt.Sprintf("localhost:%d", mirrorcfg.basePort))
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }

View File

@ -95,13 +95,13 @@ func ctlV3MemberList(cx ctlCtx) error {
for i := range lines { for i := range lines {
lines[i] = "started" lines[i] = "started"
} }
return spawnWithExpects(cmdArgs, lines...) return spawnWithExpects(cmdArgs, cx.envMap, lines...)
} }
func getMemberList(cx ctlCtx) (etcdserverpb.MemberListResponse, error) { func getMemberList(cx ctlCtx) (etcdserverpb.MemberListResponse, error) {
cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "member", "list") cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "member", "list")
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
return etcdserverpb.MemberListResponse{}, err return etcdserverpb.MemberListResponse{}, err
} }
@ -130,7 +130,7 @@ func memberListWithHexTest(cx ctlCtx) {
cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "--hex", "member", "list") cmdArgs := append(cx.PrefixArgs(), "--write-out", "json", "--hex", "member", "list")
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
cx.t.Fatalf("memberListWithHexTest error (%v)", err) cx.t.Fatalf("memberListWithHexTest error (%v)", err)
} }
@ -177,7 +177,7 @@ func memberRemoveTest(cx ctlCtx) {
func ctlV3MemberRemove(cx ctlCtx, ep, memberID, clusterID string) error { func ctlV3MemberRemove(cx ctlCtx, ep, memberID, clusterID string) error {
cmdArgs := append(cx.prefixArgs([]string{ep}), "member", "remove", memberID) 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) { func memberAddTest(cx ctlCtx) {
@ -197,7 +197,7 @@ func ctlV3MemberAdd(cx ctlCtx, peerURL string, isLearner bool) error {
if isLearner { if isLearner {
cmdArgs = append(cmdArgs, "--learner") cmdArgs = append(cmdArgs, "--learner")
} }
return spawnWithExpect(cmdArgs, " added to cluster ") return spawnWithExpectWithEnv(cmdArgs, cx.envMap, " added to cluster ")
} }
func memberUpdateTest(cx ctlCtx) { func memberUpdateTest(cx ctlCtx) {
@ -215,5 +215,5 @@ func memberUpdateTest(cx ctlCtx) {
func ctlV3MemberUpdate(cx ctlCtx, memberID, peerURL string) error { func ctlV3MemberUpdate(cx ctlCtx, memberID, peerURL string) error {
cmdArgs := append(cx.PrefixArgs(), "member", "update", memberID, fmt.Sprintf("--peer-urls=%s", peerURL)) 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 ")
} }

View File

@ -97,21 +97,22 @@ func testCtlV3MoveLeader(t *testing.T, cfg etcdProcessClusterConfig) {
} }
tests := []struct { tests := []struct {
prefixes []string eps []string
expect string expect string
}{ }{
{ // request to non-leader { // 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 ", "no leader endpoint given at ",
}, },
{ // request to leader { // 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)), fmt.Sprintf("Leadership transferred from %s to %s", types.ID(leaderID), types.ID(transferee)),
}, },
} }
for i, tc := range tests { for i, tc := range tests {
cmdArgs := append(tc.prefixes, "move-leader", types.ID(transferee).String()) prefix := cx.prefixArgs(tc.eps)
if err := spawnWithExpect(cmdArgs, tc.expect); err != nil { 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) t.Fatalf("#%d: %v", i, err)
} }
} }

View File

@ -96,7 +96,7 @@ func ctlV3Role(cx ctlCtx, args []string, expStr string) error {
cmdArgs := append(cx.PrefixArgs(), "role") cmdArgs := append(cx.PrefixArgs(), "role")
cmdArgs = append(cmdArgs, args...) cmdArgs = append(cmdArgs, args...)
return spawnWithExpect(cmdArgs, expStr) return spawnWithExpectWithEnv(cmdArgs, cx.envMap, expStr)
} }
func ctlV3RoleGrantPermission(cx ctlCtx, rolename string, perm grantingPerm) error { 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, rolename)
cmdArgs = append(cmdArgs, grantingPermToArgs(perm)...) cmdArgs = append(cmdArgs, grantingPermToArgs(perm)...)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
return err 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) 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 { if err != nil {
return err return err
} }

View File

@ -84,10 +84,11 @@ func snapshotCorruptTest(cx ctlCtx) {
datadir := cx.t.TempDir() datadir := cx.t.TempDir()
serr := spawnWithExpect( serr := spawnWithExpectWithEnv(
append(cx.PrefixArgsUtl(), "snapshot", "restore", append(cx.PrefixArgsUtl(), "snapshot", "restore",
"--data-dir", datadir, "--data-dir", datadir,
fpath), fpath),
cx.envMap,
"expected sha256") "expected sha256")
if serr != nil { if serr != nil {
@ -117,10 +118,11 @@ func snapshotStatusBeforeRestoreTest(cx ctlCtx) {
dataDir := cx.t.TempDir() dataDir := cx.t.TempDir()
defer os.RemoveAll(dataDir) defer os.RemoveAll(dataDir)
serr := spawnWithExpect( serr := spawnWithExpectWithEnv(
append(cx.PrefixArgsUtl(), "snapshot", "restore", append(cx.PrefixArgsUtl(), "snapshot", "restore",
"--data-dir", dataDir, "--data-dir", dataDir,
fpath), fpath),
cx.envMap,
"added member") "added member")
if serr != nil { if serr != nil {
cx.t.Fatal(serr) cx.t.Fatal(serr)
@ -129,13 +131,13 @@ func snapshotStatusBeforeRestoreTest(cx ctlCtx) {
func ctlV3SnapshotSave(cx ctlCtx, fpath string) error { func ctlV3SnapshotSave(cx ctlCtx, fpath string) error {
cmdArgs := append(cx.PrefixArgs(), "snapshot", "save", fpath) 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) { func getSnapshotStatus(cx ctlCtx, fpath string) (snapshot.Status, error) {
cmdArgs := append(cx.PrefixArgsUtl(), "--write-out", "json", "snapshot", "status", fpath) cmdArgs := append(cx.PrefixArgsUtl(), "--write-out", "json", "snapshot", "status", fpath)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, nil)
if err != nil { if err != nil {
return snapshot.Status{}, err return snapshot.Status{}, err
} }
@ -202,7 +204,10 @@ func testIssue6361(t *testing.T, etcdutl bool) {
fpath := filepath.Join(t.TempDir(), "test.snapshot") fpath := filepath.Join(t.TempDir(), "test.snapshot")
t.Log("etcdctl saving 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) 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, nepc, err = spawnCmd([]string{epc.procs[0].Config().execPath, "--name", name2,
"--listen-client-urls", clientURL, "--advertise-client-urls", clientURL, "--listen-client-urls", clientURL, "--advertise-client-urls", clientURL,
"--listen-peer-urls", peerURL, "--initial-advertise-peer-urls", peerURL, "--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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -104,7 +104,7 @@ func clusterVersionTest(cx ctlCtx, expected string) {
func ctlV3Version(cx ctlCtx) error { func ctlV3Version(cx ctlCtx) error {
cmdArgs := append(cx.PrefixArgs(), "version") 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. // TestCtlV3DialWithHTTPScheme ensures that client handles endpoints with HTTPS scheme.
@ -114,7 +114,7 @@ func TestCtlV3DialWithHTTPScheme(t *testing.T) {
func dialWithSchemeTest(cx ctlCtx) { func dialWithSchemeTest(cx ctlCtx) {
cmdArgs := append(cx.prefixArgs(cx.epc.EndpointsV3()), "put", "foo", "bar") 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) cx.t.Fatal(err)
} }
} }
@ -129,7 +129,7 @@ type ctlCtx struct {
epc *etcdProcessCluster epc *etcdProcessCluster
envMap map[string]struct{} envMap map[string]string
dialTimeout time.Duration dialTimeout time.Duration
@ -201,7 +201,7 @@ func withApiPrefix(p string) ctlOption {
} }
func withFlagByEnv() 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 { func withEtcdutl() ctlOption {
@ -248,6 +248,7 @@ func testCtlWithOffline(t *testing.T, testFunc func(ctlCtx), testOfflineFunc fun
for k := range ret.envMap { for k := range ret.envMap {
os.Unsetenv(k) os.Unsetenv(k)
} }
ret.envMap = make(map[string]string)
} }
if ret.epc != nil { if ret.epc != nil {
if errC := ret.epc.Close(); errC != nil { if errC := ret.epc.Close(); errC != nil {
@ -311,8 +312,7 @@ func (cx *ctlCtx) prefixArgs(eps []string) []string {
for k, v := range fmap { for k, v := range fmap {
if useEnv { if useEnv {
ek := flags.FlagToEnv("ETCDCTL", k) ek := flags.FlagToEnv("ETCDCTL", k)
os.Setenv(ek, v) cx.envMap[ek] = v
cx.envMap[ek] = struct{}{}
} else { } else {
cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v)) cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v))
} }

View File

@ -102,7 +102,7 @@ func ctlV3Txn(cx ctlCtx, rqs txnRequests) error {
if cx.interactive { if cx.interactive {
cmdArgs = append(cmdArgs, "--interactive") cmdArgs = append(cmdArgs, "--interactive")
} }
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
return err return err
} }

View File

@ -179,7 +179,7 @@ func ctlV3User(cx ctlCtx, args []string, expStr string, stdIn []string) error {
cmdArgs := append(cx.PrefixArgs(), "user") cmdArgs := append(cx.PrefixArgs(), "user")
cmdArgs = append(cmdArgs, args...) cmdArgs = append(cmdArgs, args...)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, cx.envMap)
if err != nil { if err != nil {
return err return err
} }

View File

@ -35,7 +35,7 @@ func setupWatchArgs(cx ctlCtx, args []string) []string {
func ctlV3Watch(cx ctlCtx, args []string, kvs ...kvExec) error { func ctlV3Watch(cx ctlCtx, args []string, kvs ...kvExec) error {
cmdArgs := setupWatchArgs(cx, args) cmdArgs := setupWatchArgs(cx, args)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, nil)
if err != nil { if err != nil {
return err return err
} }
@ -66,7 +66,7 @@ func ctlV3Watch(cx ctlCtx, args []string, kvs ...kvExec) error {
func ctlV3WatchFailPerm(cx ctlCtx, args []string) error { func ctlV3WatchFailPerm(cx ctlCtx, args []string) error {
cmdArgs := setupWatchArgs(cx, args) cmdArgs := setupWatchArgs(cx, args)
proc, err := spawnCmd(cmdArgs) proc, err := spawnCmd(cmdArgs, nil)
if err != nil { if err != nil {
return err return err
} }

View File

@ -29,7 +29,7 @@ const exampleConfigFile = "../../etcd.conf.yml.sample"
func TestEtcdExampleConfig(t *testing.T) { func TestEtcdExampleConfig(t *testing.T) {
skipInShortMode(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 { if err != nil {
t.Fatal(err) 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-advertise-peer-urls", fmt.Sprintf("http://127.0.0.1:%d", etcdProcessBasePort+i),
"--initial-cluster", ic, "--initial-cluster", ic,
} }
p, err := spawnCmd(args) p, err := spawnCmd(args, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -106,7 +106,7 @@ func TestEtcdUnixPeers(t *testing.T) {
"--listen-peer-urls", "unix://etcd.unix:1", "--listen-peer-urls", "unix://etcd.unix:1",
"--initial-advertise-peer-urls", "unix://etcd.unix:1", "--initial-advertise-peer-urls", "unix://etcd.unix:1",
"--initial-cluster", "e1=unix://etcd.unix:1", "--initial-cluster", "e1=unix://etcd.unix:1",
}, }, nil,
) )
defer os.Remove("etcd.unix:1") defer os.Remove("etcd.unix:1")
if err != nil { if err != nil {
@ -183,7 +183,7 @@ func TestEtcdPeerCNAuth(t *testing.T) {
commonArgs = append(commonArgs, args...) commonArgs = append(commonArgs, args...)
p, err := spawnCmd(commonArgs) p, err := spawnCmd(commonArgs, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -262,7 +262,7 @@ func TestEtcdPeerNameAuth(t *testing.T) {
commonArgs = append(commonArgs, args...) commonArgs = append(commonArgs, args...)
p, err := spawnCmd(commonArgs) p, err := spawnCmd(commonArgs, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -308,7 +308,7 @@ func TestGrpcproxyAndCommonName(t *testing.T) {
t.Errorf("Unexpected error: %s", err) t.Errorf("Unexpected error: %s", err)
} }
p, err := spawnCmd(argsWithEmptyCN) p, err := spawnCmd(argsWithEmptyCN, nil)
defer func() { defer func() {
if p != nil { if p != nil {
p.Stop() p.Stop()
@ -323,7 +323,7 @@ func TestGrpcproxyAndCommonName(t *testing.T) {
func TestBootstrapDefragFlag(t *testing.T) { func TestBootstrapDefragFlag(t *testing.T) {
skipInShortMode(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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -87,7 +87,7 @@ func corruptTest(cx ctlCtx) {
cx.t.Log("restarting etcd[0]") cx.t.Log("restarting etcd[0]")
ep := cx.epc.procs[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 { if err != nil {
cx.t.Fatal(err) cx.t.Fatal(err)
} }

View File

@ -92,7 +92,7 @@ func (ep *etcdServerProcess) Start() error {
panic("already started") panic("already started")
} }
ep.cfg.lg.Info("starting server...", zap.String("name", ep.cfg.name)) 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 { if err != nil {
return err return err
} }

View File

@ -18,6 +18,7 @@
package e2e package e2e
import ( import (
"fmt"
"os" "os"
"strings" "strings"
@ -27,20 +28,41 @@ import (
const noOutputLineCount = 0 // regular binaries emit no extra lines const noOutputLineCount = 0 // regular binaries emit no extra lines
func spawnCmd(args []string) (*expect.ExpectProcess, error) { func spawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) {
return spawnCmdWithLogger(zap.NewNop(), args) 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() wd, err := os.Getwd()
if err != nil { if err != nil {
return nil, err return nil, err
} }
env := mergeEnvVariables(envVars)
if strings.HasSuffix(args[0], "/etcdctl3") { if strings.HasSuffix(args[0], "/etcdctl3") {
env := append(os.Environ(), "ETCDCTL_API=3") env = append(env, "ETCDCTL_API=3")
lg.Info("spawning process with ETCDCTL_API=3", zap.Strings("args", args), zap.String("working-dir", wd)) 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) return expect.NewExpectWithEnv(ctlBinPath, args[1:], env)
} }
lg.Info("spawning process", zap.Strings("args", args), zap.String("working-dir", wd)) lg.Info("spawning process", zap.Strings("args", args), zap.String("working-dir", wd), zap.Strings("environment-variables", env))
return expect.NewExpect(args[0], args[1:]...) 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
} }

View File

@ -40,16 +40,20 @@ func waitReadyExpectProc(exproc *expect.ExpectProcess, readyStrs []string) error
} }
func spawnWithExpect(args []string, expected 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 { func spawnWithExpectWithEnv(args []string, envVars map[string]string, expected string) error {
_, err := spawnWithExpectLines(args, xs...) return spawnWithExpects(args, envVars, []string{expected}...)
}
func spawnWithExpects(args []string, envVars map[string]string, xs ...string) error {
_, err := spawnWithExpectLines(args, envVars, xs...)
return err return err
} }
func spawnWithExpectLines(args []string, xs ...string) ([]string, error) { func spawnWithExpectLines(args []string, envVars map[string]string, xs ...string) ([]string, error) {
proc, err := spawnCmd(args) proc, err := spawnCmd(args, envVars)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -63,7 +63,7 @@ func assertVerifyCanStartV2deprecationNotYet(t testing.TB, dataDirPath string) {
func assertVerifyCannotStartV2deprecationWriteOnly(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") 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) assert.NoError(t, err)
_, err = proc.Expect("detected disallowed custom content in v2store for stage --v2-deprecation=write-only") _, 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) { func TestV2DeprecationWriteOnlyNoV2Api(t *testing.T) {
BeforeTest(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) assert.NoError(t, err)
_, err = proc.Expect("--enable-v2 and --v2-deprecation=write-only are mutually exclusive") _, err = proc.Expect("--enable-v2 and --v2-deprecation=write-only are mutually exclusive")

View File

@ -244,7 +244,7 @@ func testV3CurlAuth(cx ctlCtx) {
) )
cmdArgs = cURLPrefixArgs(cx.epc, "POST", cURLReq{endpoint: path.Join(p, "/auth/authenticate"), value: string(authreq)}) 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) testutil.AssertNil(cx.t, err)
defer proc.Close() defer proc.Close()
@ -286,7 +286,7 @@ func testV3CurlCampaign(cx ctlCtx) {
endpoint: path.Join(cx.apiPrefix, "/election/campaign"), endpoint: path.Join(cx.apiPrefix, "/election/campaign"),
value: string(cdata), value: string(cdata),
}) })
lines, err := spawnWithExpectLines(cargs, `"leader":{"name":"`) lines, err := spawnWithExpectLines(cargs, cx.envMap, `"leader":{"name":"`)
if err != nil { if err != nil {
cx.t.Fatalf("failed post campaign request (%s) (%v)", cx.apiPrefix, err) cx.t.Fatalf("failed post campaign request (%s) (%v)", cx.apiPrefix, err)
} }