Merge pull request #6650 from gyuho/flag

*: tests, README on environment variables in etcdctl v3
release-3.1
Gyu-Ho Lee 2016-10-14 12:15:27 -07:00 committed by GitHub
commit 45588c1f9f
4 changed files with 55 additions and 9 deletions

View File

@ -25,6 +25,9 @@ func TestCtlV3PutClientTLS(t *testing.T) { testCtl(t, putTest, withCfg(confi
func TestCtlV3PutClientAutoTLS(t *testing.T) { testCtl(t, putTest, withCfg(configClientAutoTLS)) } func TestCtlV3PutClientAutoTLS(t *testing.T) { testCtl(t, putTest, withCfg(configClientAutoTLS)) }
func TestCtlV3PutPeerTLS(t *testing.T) { testCtl(t, putTest, withCfg(configPeerTLS)) } func TestCtlV3PutPeerTLS(t *testing.T) { testCtl(t, putTest, withCfg(configPeerTLS)) }
func TestCtlV3PutTimeout(t *testing.T) { testCtl(t, putTest, withDialTimeout(0)) } func TestCtlV3PutTimeout(t *testing.T) { testCtl(t, putTest, withDialTimeout(0)) }
func TestCtlV3PutClientTLSFlagByEnv(t *testing.T) {
testCtl(t, putTest, withCfg(configClientTLS), withFlagByEnv())
}
func TestCtlV3Get(t *testing.T) { testCtl(t, getTest) } func TestCtlV3Get(t *testing.T) { testCtl(t, getTest) }
func TestCtlV3GetNoTLS(t *testing.T) { testCtl(t, getTest, withCfg(configNoTLS)) } func TestCtlV3GetNoTLS(t *testing.T) { testCtl(t, getTest, withCfg(configNoTLS)) }

View File

@ -15,11 +15,13 @@
package e2e package e2e
import ( import (
"fmt"
"os" "os"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/coreos/etcd/pkg/flags"
"github.com/coreos/etcd/pkg/testutil" "github.com/coreos/etcd/pkg/testutil"
"github.com/coreos/etcd/version" "github.com/coreos/etcd/version"
) )
@ -57,6 +59,8 @@ type ctlCtx struct {
epc *etcdProcessCluster epc *etcdProcessCluster
envMap map[string]struct{}
dialTimeout time.Duration dialTimeout time.Duration
quorum bool // if true, set up 3-node cluster and linearizable read quorum bool // if true, set up 3-node cluster and linearizable read
@ -105,6 +109,10 @@ func withNoStrictReconfig() ctlOption {
return func(cx *ctlCtx) { cx.noStrictReconfig = true } return func(cx *ctlCtx) { cx.noStrictReconfig = true }
} }
func withFlagByEnv() ctlOption {
return func(cx *ctlCtx) { cx.envMap = make(map[string]struct{}) }
}
func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) { func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) {
defer testutil.AfterTest(t) defer testutil.AfterTest(t)
@ -133,6 +141,11 @@ func testCtl(t *testing.T, testFunc func(ctlCtx), opts ...ctlOption) {
defer func() { defer func() {
os.Unsetenv("ETCDCTL_API") os.Unsetenv("ETCDCTL_API")
if ret.envMap != nil {
for k := range ret.envMap {
os.Unsetenv(k)
}
}
if errC := ret.epc.Close(); errC != nil { if errC := ret.epc.Close(); errC != nil {
t.Fatalf("error closing etcd processes (%v)", errC) t.Fatalf("error closing etcd processes (%v)", errC)
} }
@ -160,22 +173,40 @@ func (cx *ctlCtx) prefixArgs(eps []string) []string {
panic("v3 proxy not implemented") panic("v3 proxy not implemented")
} }
cmdArgs := []string{ctlBinPath, "--endpoints", strings.Join(eps, ","), "--dial-timeout", cx.dialTimeout.String()} fmap := make(map[string]string)
fmap["endpoints"] = strings.Join(eps, ",")
fmap["dial-timeout"] = cx.dialTimeout.String()
if cx.epc.cfg.clientTLS == clientTLS { if cx.epc.cfg.clientTLS == clientTLS {
if cx.epc.cfg.isClientAutoTLS { if cx.epc.cfg.isClientAutoTLS {
cmdArgs = append(cmdArgs, "--insecure-transport=false", "--insecure-skip-tls-verify") fmap["insecure-transport"] = "false"
fmap["insecure-skip-tls-verify"] = "true"
} else { } else {
cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath) fmap["cacert"] = caPath
fmap["cert"] = certPath
fmap["key"] = privateKeyPath
} }
} }
if cx.user != "" { if cx.user != "" {
cmdArgs = append(cmdArgs, "--user="+cx.user+":"+cx.pass) fmap["user"] = cx.user + ":" + cx.pass
} }
useEnv := cx.envMap != nil
cmdArgs := []string{ctlBinPath}
for k, v := range fmap {
if useEnv {
ek := flags.FlagToEnv("ETCDCTL", k)
os.Setenv(ek, v)
cx.envMap[ek] = struct{}{}
} else {
cmdArgs = append(cmdArgs, fmt.Sprintf("--%s=%s", k, v))
}
}
return cmdArgs return cmdArgs
} }
// PrefixArgs prefixes etcdctl command.
// Make sure to unset environment variables after tests.
func (cx *ctlCtx) PrefixArgs() []string { func (cx *ctlCtx) PrefixArgs() []string {
return cx.prefixArgs(cx.epc.grpcEndpoints()) return cx.prefixArgs(cx.epc.grpcEndpoints())
} }

View File

@ -4,6 +4,17 @@ etcdctl
`etcdctl` is a command line client for [etcd][etcd]. `etcdctl` is a command line client for [etcd][etcd].
Make sure to set environment variable `ETCDCTL_API=3`. For etcdctl v2, please check [READMEv2][READMEv2]. Make sure to set environment variable `ETCDCTL_API=3`. For etcdctl v2, please check [READMEv2][READMEv2].
Global flags (e.g., `dial-timeout`, `--cacert`, `--cert`, `--key`) can be set with environment variables:
```
ETCDCTL_DIAL_TIMEOUT=3s
ETCDCTL_CACERT=/tmp/ca.pem
ETCDCTL_CERT=/tmp/cert.pem
ETCDCTL_KEY=/tmp/key.pem
```
Prefix flag strings with `ETCDCTL_`, convert all letters to upper-case, and replace dash(`-`) with underscore(`_`).
## Commands ## Commands
### VERSION ### VERSION

View File

@ -74,7 +74,7 @@ func SetFlagsFromEnv(prefix string, fs *flag.FlagSet) error {
var err error var err error
alreadySet := make(map[string]bool) alreadySet := make(map[string]bool)
fs.Visit(func(f *flag.Flag) { fs.Visit(func(f *flag.Flag) {
alreadySet[flagToEnv(prefix, f.Name)] = true alreadySet[FlagToEnv(prefix, f.Name)] = true
}) })
usedEnvKey := make(map[string]bool) usedEnvKey := make(map[string]bool)
fs.VisitAll(func(f *flag.Flag) { fs.VisitAll(func(f *flag.Flag) {
@ -94,7 +94,7 @@ func SetPflagsFromEnv(prefix string, fs *pflag.FlagSet) error {
usedEnvKey := make(map[string]bool) usedEnvKey := make(map[string]bool)
fs.VisitAll(func(f *pflag.Flag) { fs.VisitAll(func(f *pflag.Flag) {
if f.Changed { if f.Changed {
alreadySet[flagToEnv(prefix, f.Name)] = true alreadySet[FlagToEnv(prefix, f.Name)] = true
} }
if serr := setFlagFromEnv(fs, prefix, f.Name, usedEnvKey, alreadySet, false); serr != nil { if serr := setFlagFromEnv(fs, prefix, f.Name, usedEnvKey, alreadySet, false); serr != nil {
err = serr err = serr
@ -103,7 +103,8 @@ func SetPflagsFromEnv(prefix string, fs *pflag.FlagSet) error {
return err return err
} }
func flagToEnv(prefix, name string) string { // FlagToEnv converts flag string to upper-case environment variable key string.
func FlagToEnv(prefix, name string) string {
return prefix + "_" + strings.ToUpper(strings.Replace(name, "-", "_", -1)) return prefix + "_" + strings.ToUpper(strings.Replace(name, "-", "_", -1))
} }
@ -131,7 +132,7 @@ type flagSetter interface {
} }
func setFlagFromEnv(fs flagSetter, prefix, fname string, usedEnvKey, alreadySet map[string]bool, log bool) error { func setFlagFromEnv(fs flagSetter, prefix, fname string, usedEnvKey, alreadySet map[string]bool, log bool) error {
key := flagToEnv(prefix, fname) key := FlagToEnv(prefix, fname)
if !alreadySet[key] { if !alreadySet[key] {
val := os.Getenv(key) val := os.Getenv(key)
if val != "" { if val != "" {