mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #9688 from gyuho/fix-watch
etcdctl/ctlv3: fix watch with exec commands, interactive mode flag parsing
This commit is contained in:
commit
14a2d0d54d
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,6 +9,7 @@
|
||||
*.log
|
||||
/etcd
|
||||
/hack/insta-discovery/.env
|
||||
*.coverprofile
|
||||
*.test
|
||||
hack/tls-setup/certs
|
||||
.idea
|
||||
|
3
Makefile
3
Makefile
@ -20,9 +20,12 @@ clean:
|
||||
rm -f ./codecov
|
||||
rm -rf ./agent-*
|
||||
rm -rf ./covdir
|
||||
rm -f ./*.coverprofile
|
||||
rm -f ./*.log
|
||||
rm -f ./bin/Dockerfile-release
|
||||
rm -rf ./bin/*.etcd
|
||||
rm -rf ./default.etcd
|
||||
rm -rf ./tests/e2e/default.etcd
|
||||
rm -rf ./gopath
|
||||
rm -rf ./gopath.proto
|
||||
rm -rf ./release
|
||||
|
@ -179,118 +179,159 @@ func printWatchCh(c *clientv3.Client, ch clientv3.WatchChan, execArgs []string)
|
||||
// "--" characters are invalid arguments for "spf13/cobra" library,
|
||||
// so no need to handle such cases.
|
||||
func parseWatchArgs(osArgs, commandArgs []string, envKey, envRange string, interactive bool) (watchArgs []string, execArgs []string, err error) {
|
||||
watchArgs = commandArgs
|
||||
rawArgs := make([]string, len(osArgs))
|
||||
copy(rawArgs, osArgs)
|
||||
watchArgs = make([]string, len(commandArgs))
|
||||
copy(watchArgs, commandArgs)
|
||||
|
||||
// remove preceding commands (e.g. "watch foo bar" in interactive mode)
|
||||
idx := 0
|
||||
for idx = range watchArgs {
|
||||
if watchArgs[idx] == "watch" {
|
||||
// remove preceding commands (e.g. ./bin/etcdctl watch)
|
||||
// handle "./bin/etcdctl watch foo -- echo watch event"
|
||||
for idx := range rawArgs {
|
||||
if rawArgs[idx] == "watch" {
|
||||
rawArgs = rawArgs[idx+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
if idx < len(watchArgs)-1 || envKey != "" {
|
||||
if idx < len(watchArgs)-1 {
|
||||
watchArgs = watchArgs[idx+1:]
|
||||
}
|
||||
|
||||
execIdx, execExist := 0, false
|
||||
for execIdx = range osArgs {
|
||||
v := osArgs[execIdx]
|
||||
if v == "--" && execIdx != len(osArgs)-1 {
|
||||
// remove preceding commands (e.g. "watch foo bar" in interactive mode)
|
||||
// handle "./bin/etcdctl watch foo -- echo watch event"
|
||||
if interactive {
|
||||
if watchArgs[0] != "watch" {
|
||||
// "watch" not found
|
||||
watchPrefix, watchRev, watchPrevKey = false, 0, false
|
||||
return nil, nil, errBadArgsInteractiveWatch
|
||||
}
|
||||
watchArgs = watchArgs[1:]
|
||||
}
|
||||
|
||||
execIdx, execExist := 0, false
|
||||
if !interactive {
|
||||
for execIdx = range rawArgs {
|
||||
if rawArgs[execIdx] == "--" {
|
||||
execExist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if idx == len(watchArgs)-1 && envKey != "" {
|
||||
if len(watchArgs) > 0 && !interactive {
|
||||
// "watch --rev 1 -- echo Hello World" has no conflict
|
||||
if !execExist {
|
||||
// "watch foo" with ETCDCTL_WATCH_KEY=foo
|
||||
// (watchArgs==["foo"])
|
||||
return nil, nil, errBadArgsNumConflictEnv
|
||||
}
|
||||
}
|
||||
// otherwise, watch with no argument and environment key is set
|
||||
// if interactive, first "watch" command string should be removed
|
||||
if interactive {
|
||||
watchArgs = []string{}
|
||||
}
|
||||
if execExist && execIdx == len(rawArgs)-1 {
|
||||
// "watch foo bar --" should error
|
||||
return nil, nil, errBadArgsNumSeparator
|
||||
}
|
||||
|
||||
// "watch foo -- echo hello" with ETCDCTL_WATCH_KEY=foo
|
||||
// (watchArgs==["foo","echo","hello"])
|
||||
if envKey != "" && execExist {
|
||||
widx, oidx := 0, len(osArgs)-1
|
||||
for widx = len(watchArgs) - 1; widx >= 0; widx-- {
|
||||
if watchArgs[widx] == osArgs[oidx] {
|
||||
oidx--
|
||||
// "watch" with no argument should error
|
||||
if !execExist && len(rawArgs) < 1 && envKey == "" {
|
||||
return nil, nil, errBadArgsNum
|
||||
}
|
||||
if execExist && envKey != "" {
|
||||
// "ETCDCTL_WATCH_KEY=foo watch foo -- echo 1" should error
|
||||
// (watchArgs==["foo","echo","1"])
|
||||
widx, ridx := len(watchArgs)-1, len(rawArgs)-1
|
||||
for ; widx >= 0; widx-- {
|
||||
if watchArgs[widx] == rawArgs[ridx] {
|
||||
ridx--
|
||||
continue
|
||||
}
|
||||
if oidx == execIdx { // watchArgs has extra
|
||||
// watchArgs has extra:
|
||||
// ETCDCTL_WATCH_KEY=foo watch foo -- echo 1
|
||||
// watchArgs: foo echo 1
|
||||
if ridx == execIdx {
|
||||
return nil, nil, errBadArgsNumConflictEnv
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if interactive { // "watch" not found
|
||||
return nil, nil, errBadArgsInteractiveWatch
|
||||
}
|
||||
if len(watchArgs) < 1 && envKey == "" {
|
||||
return nil, nil, errBadArgsNum
|
||||
}
|
||||
// check conflicting arguments
|
||||
// e.g. "watch --rev 1 -- echo Hello World" has no conflict
|
||||
if !execExist && len(watchArgs) > 0 && envKey != "" {
|
||||
// "ETCDCTL_WATCH_KEY=foo watch foo" should error
|
||||
// (watchArgs==["foo"])
|
||||
return nil, nil, errBadArgsNumConflictEnv
|
||||
}
|
||||
} else {
|
||||
for execIdx = range watchArgs {
|
||||
if watchArgs[execIdx] == "--" {
|
||||
execExist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if execExist && execIdx == len(watchArgs)-1 {
|
||||
// "watch foo bar --" should error
|
||||
watchPrefix, watchRev, watchPrevKey = false, 0, false
|
||||
return nil, nil, errBadArgsNumSeparator
|
||||
}
|
||||
|
||||
// remove preceding commands (e.g. ./bin/etcdctl watch)
|
||||
for idx = range osArgs {
|
||||
if osArgs[idx] == "watch" {
|
||||
break
|
||||
flagset := NewWatchCommand().Flags()
|
||||
if err := flagset.Parse(watchArgs); err != nil {
|
||||
watchPrefix, watchRev, watchPrevKey = false, 0, false
|
||||
return nil, nil, err
|
||||
}
|
||||
pArgs := flagset.Args()
|
||||
|
||||
// "watch" with no argument should error
|
||||
if !execExist && envKey == "" && len(pArgs) < 1 {
|
||||
watchPrefix, watchRev, watchPrevKey = false, 0, false
|
||||
return nil, nil, errBadArgsNum
|
||||
}
|
||||
// check conflicting arguments
|
||||
// e.g. "watch --rev 1 -- echo Hello World" has no conflict
|
||||
if !execExist && len(pArgs) > 0 && envKey != "" {
|
||||
// "ETCDCTL_WATCH_KEY=foo watch foo" should error
|
||||
// (watchArgs==["foo"])
|
||||
watchPrefix, watchRev, watchPrevKey = false, 0, false
|
||||
return nil, nil, errBadArgsNumConflictEnv
|
||||
}
|
||||
}
|
||||
if idx < len(osArgs)-1 {
|
||||
osArgs = osArgs[idx+1:]
|
||||
} else if envKey == "" {
|
||||
return nil, nil, errBadArgsNum
|
||||
}
|
||||
|
||||
argsWithSep := osArgs
|
||||
if interactive { // interactive mode pass "--" to the command args
|
||||
argsWithSep := rawArgs
|
||||
if interactive {
|
||||
// interactive mode directly passes "--" to the command args
|
||||
argsWithSep = watchArgs
|
||||
}
|
||||
foundSep := false
|
||||
|
||||
idx, foundSep := 0, false
|
||||
for idx = range argsWithSep {
|
||||
if argsWithSep[idx] == "--" {
|
||||
foundSep = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if foundSep {
|
||||
execArgs = argsWithSep[idx+1:]
|
||||
}
|
||||
|
||||
if interactive {
|
||||
flagset := NewWatchCommand().Flags()
|
||||
if err := flagset.Parse(argsWithSep); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
watchArgs = flagset.Args()
|
||||
|
||||
watchPrefix, err = flagset.GetBool("prefix")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
watchRev, err = flagset.GetInt64("rev")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
watchPrevKey, err = flagset.GetBool("prev-kv")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// "watch -- echo hello" with ETCDCTL_WATCH_KEY=foo
|
||||
// should be translated to "watch foo -- echo hello"
|
||||
// "ETCDCTL_WATCH_KEY=foo watch -- echo hello"
|
||||
// should translate "watch foo -- echo hello"
|
||||
// (watchArgs=["echo","hello"] should be ["foo","echo","hello"])
|
||||
if envKey != "" {
|
||||
tmp := []string{envKey}
|
||||
ranges := []string{envKey}
|
||||
if envRange != "" {
|
||||
tmp = append(tmp, envRange)
|
||||
ranges = append(ranges, envRange)
|
||||
}
|
||||
watchArgs = append(tmp, watchArgs...)
|
||||
watchArgs = append(ranges, watchArgs...)
|
||||
}
|
||||
|
||||
if !foundSep {
|
||||
return watchArgs, nil, nil
|
||||
}
|
||||
|
||||
if idx == len(argsWithSep)-1 {
|
||||
// "watch foo bar --" should error
|
||||
return nil, nil, errBadArgsNumSeparator
|
||||
}
|
||||
execArgs = argsWithSep[idx+1:]
|
||||
|
||||
// "watch foo bar --rev 1 -- echo hello" or "watch foo --rev 1 bar -- echo hello",
|
||||
// then "watchArgs" is "foo bar echo hello"
|
||||
// so need ignore args after "argsWithSep[idx]", which is "--"
|
||||
|
@ -26,6 +26,10 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||
envKey, envRange string
|
||||
interactive bool
|
||||
|
||||
interactiveWatchPrefix bool
|
||||
interactiveWatchRev int64
|
||||
interactiveWatchPrevKey bool
|
||||
|
||||
watchArgs []string
|
||||
execArgs []string
|
||||
err error
|
||||
@ -145,6 +149,14 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "foo", "--", "echo", "watch", "event", "received"},
|
||||
commandArgs: []string{"foo", "echo", "watch", "event", "received"},
|
||||
interactive: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "watch", "event", "received"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "foo", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
commandArgs: []string{"foo", "echo", "Hello", "World"},
|
||||
@ -153,6 +165,22 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "foo", "--rev", "1", "--", "echo", "watch", "event", "received"},
|
||||
commandArgs: []string{"foo", "echo", "watch", "event", "received"},
|
||||
interactive: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "watch", "event", "received"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "--rev", "1", "foo", "--", "echo", "watch", "event", "received"},
|
||||
commandArgs: []string{"foo", "echo", "watch", "event", "received"},
|
||||
interactive: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "watch", "event", "received"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||
commandArgs: []string{"foo", "bar", "echo", "Hello", "World"},
|
||||
@ -185,6 +213,30 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "foo", "bar", "--rev", "1", "--", "echo", "watch", "event", "received"},
|
||||
commandArgs: []string{"foo", "bar", "echo", "watch", "event", "received"},
|
||||
interactive: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "watch", "event", "received"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "foo", "--rev", "1", "bar", "--", "echo", "Hello", "World"},
|
||||
commandArgs: []string{"foo", "bar", "echo", "Hello", "World"},
|
||||
interactive: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "--rev", "1", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||
commandArgs: []string{"foo", "bar", "echo", "Hello", "World"},
|
||||
interactive: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
commandArgs: []string{"echo", "Hello", "World"},
|
||||
@ -215,133 +267,269 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||
err: errBadArgsNumConflictEnv,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"foo", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: nil,
|
||||
execArgs: nil,
|
||||
err: errBadArgsInteractiveWatch,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"foo", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: nil,
|
||||
execArgs: nil,
|
||||
err: errBadArgsInteractiveWatch,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch"},
|
||||
envKey: "foo",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch"},
|
||||
envKey: "foo",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch"},
|
||||
envKey: "hello world!",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
watchArgs: []string{"hello world!", "bar"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch"},
|
||||
envKey: "hello world!",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"hello world!", "bar"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "--rev", "1"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "--rev", "1"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "foo", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "foo", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--", "echo", "Hello", "World"},
|
||||
envKey: "foo",
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "5", "--prev-kv", "foo", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 5,
|
||||
interactiveWatchPrevKey: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--", "echo", "Hello", "World"},
|
||||
envKey: "foo",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1"},
|
||||
envKey: "foo",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: nil,
|
||||
execArgs: nil,
|
||||
err: errBadArgsNum,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "--prefix"},
|
||||
envKey: "foo",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: true,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
envKey: "foo",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "100", "--prefix", "--prev-kv"},
|
||||
envKey: "foo",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: true,
|
||||
interactiveWatchRev: 100,
|
||||
interactiveWatchPrevKey: true,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: nil,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "--rev", "1", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "--prefix"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: nil,
|
||||
execArgs: nil,
|
||||
err: errBadArgsNum,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--", "echo", "Hello", "World"},
|
||||
envKey: "foo",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--", "echo", "Hello", "World"},
|
||||
envKey: "foo",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 0,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
envKey: "foo",
|
||||
envRange: "bar",
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "--rev", "1", "bar", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: false,
|
||||
interactiveWatchRev: 1,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar", "--rev", "7", "--prefix", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: true,
|
||||
interactiveWatchRev: 7,
|
||||
interactiveWatchPrevKey: false,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||
commandArgs: []string{"watch", "foo", "bar", "--rev", "7", "--prefix", "--prev-kv", "--", "echo", "Hello", "World"},
|
||||
interactive: true,
|
||||
interactiveWatchPrefix: true,
|
||||
interactiveWatchRev: 7,
|
||||
interactiveWatchPrevKey: true,
|
||||
watchArgs: []string{"foo", "bar"},
|
||||
execArgs: []string{"echo", "Hello", "World"},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
for i, ts := range tt {
|
||||
@ -355,5 +543,16 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||
if !reflect.DeepEqual(execArgs, ts.execArgs) {
|
||||
t.Fatalf("#%d: execArgs expected %q, got %v", i, ts.execArgs, execArgs)
|
||||
}
|
||||
if ts.interactive {
|
||||
if ts.interactiveWatchPrefix != watchPrefix {
|
||||
t.Fatalf("#%d: interactive watchPrefix expected %v, got %v", i, ts.interactiveWatchPrefix, watchPrefix)
|
||||
}
|
||||
if ts.interactiveWatchRev != watchRev {
|
||||
t.Fatalf("#%d: interactive watchRev expected %d, got %d", i, ts.interactiveWatchRev, watchRev)
|
||||
}
|
||||
if ts.interactiveWatchPrevKey != watchPrevKey {
|
||||
t.Fatalf("#%d: interactive watchPrevKey expected %v, got %v", i, ts.interactiveWatchPrevKey, watchPrevKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
134
tests/e2e/ctl_v3_watch_cov_test.go
Normal file
134
tests/e2e/ctl_v3_watch_cov_test.go
Normal file
@ -0,0 +1,134 @@
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build cov
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCtlV3Watch(t *testing.T) { testCtl(t, watchTest) }
|
||||
func TestCtlV3WatchNoTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configNoTLS)) }
|
||||
func TestCtlV3WatchClientTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configClientTLS)) }
|
||||
func TestCtlV3WatchPeerTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configPeerTLS)) }
|
||||
func TestCtlV3WatchTimeout(t *testing.T) { testCtl(t, watchTest, withDialTimeout(0)) }
|
||||
|
||||
func TestCtlV3WatchInteractive(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive())
|
||||
}
|
||||
func TestCtlV3WatchInteractiveNoTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configNoTLS))
|
||||
}
|
||||
func TestCtlV3WatchInteractiveClientTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configClientTLS))
|
||||
}
|
||||
func TestCtlV3WatchInteractivePeerTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configPeerTLS))
|
||||
}
|
||||
|
||||
func watchTest(cx ctlCtx) {
|
||||
tests := []struct {
|
||||
puts []kv
|
||||
envKey string
|
||||
envRange string
|
||||
args []string
|
||||
|
||||
wkv []kvExec
|
||||
}{
|
||||
{ // watch 1 key
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1"},
|
||||
wkv: []kvExec{{key: "sample", val: "value"}},
|
||||
},
|
||||
{ // watch 1 key with env
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
args: []string{"--rev", "1"},
|
||||
wkv: []kvExec{{key: "sample", val: "value"}},
|
||||
},
|
||||
|
||||
// coverage tests get extra arguments:
|
||||
// ./bin/etcdctl_test -test.coverprofile=e2e.1525392462795198897.coverprofile -test.outputdir=../..
|
||||
// do not test watch exec commands
|
||||
|
||||
{ // watch 3 keys by prefix
|
||||
puts: []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
|
||||
args: []string{"key", "--rev", "1", "--prefix"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}},
|
||||
},
|
||||
{ // watch 3 keys by prefix, with env
|
||||
puts: []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
|
||||
envKey: "key",
|
||||
args: []string{"--rev", "1", "--prefix"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}},
|
||||
},
|
||||
{ // watch by revision
|
||||
puts: []kv{{"etcd", "revision_1"}, {"etcd", "revision_2"}, {"etcd", "revision_3"}},
|
||||
args: []string{"etcd", "--rev", "2"},
|
||||
wkv: []kvExec{{key: "etcd", val: "revision_2"}, {key: "etcd", val: "revision_3"}},
|
||||
},
|
||||
{ // watch 3 keys by range
|
||||
puts: []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
||||
args: []string{"key", "key3", "--rev", "1"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
||||
},
|
||||
{ // watch 3 keys by range, with env
|
||||
puts: []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
||||
envKey: "key",
|
||||
envRange: "key3",
|
||||
args: []string{"--rev", "1"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
donec := make(chan struct{})
|
||||
go func(i int, puts []kv) {
|
||||
for j := range puts {
|
||||
if err := ctlV3Put(cx, puts[j].key, puts[j].val, ""); err != nil {
|
||||
cx.t.Fatalf("watchTest #%d-%d: ctlV3Put error (%v)", i, j, err)
|
||||
}
|
||||
}
|
||||
close(donec)
|
||||
}(i, tt.puts)
|
||||
|
||||
unsetEnv := func() {}
|
||||
if tt.envKey != "" || tt.envRange != "" {
|
||||
if tt.envKey != "" {
|
||||
os.Setenv("ETCDCTL_WATCH_KEY", tt.envKey)
|
||||
unsetEnv = func() { os.Unsetenv("ETCDCTL_WATCH_KEY") }
|
||||
}
|
||||
if tt.envRange != "" {
|
||||
os.Setenv("ETCDCTL_WATCH_RANGE_END", tt.envRange)
|
||||
unsetEnv = func() { os.Unsetenv("ETCDCTL_WATCH_RANGE_END") }
|
||||
}
|
||||
if tt.envKey != "" && tt.envRange != "" {
|
||||
unsetEnv = func() {
|
||||
os.Unsetenv("ETCDCTL_WATCH_KEY")
|
||||
os.Unsetenv("ETCDCTL_WATCH_RANGE_END")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := ctlV3Watch(cx, tt.args, tt.wkv...); err != nil {
|
||||
if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
|
||||
cx.t.Errorf("watchTest #%d: ctlV3Watch error (%v)", i, err)
|
||||
}
|
||||
}
|
||||
unsetEnv()
|
||||
<-donec
|
||||
}
|
||||
}
|
167
tests/e2e/ctl_v3_watch_no_cov_test.go
Normal file
167
tests/e2e/ctl_v3_watch_no_cov_test.go
Normal file
@ -0,0 +1,167 @@
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !cov
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCtlV3Watch(t *testing.T) { testCtl(t, watchTest) }
|
||||
func TestCtlV3WatchNoTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configNoTLS)) }
|
||||
func TestCtlV3WatchClientTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configClientTLS)) }
|
||||
func TestCtlV3WatchPeerTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configPeerTLS)) }
|
||||
func TestCtlV3WatchTimeout(t *testing.T) { testCtl(t, watchTest, withDialTimeout(0)) }
|
||||
|
||||
func TestCtlV3WatchInteractive(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive())
|
||||
}
|
||||
func TestCtlV3WatchInteractiveNoTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configNoTLS))
|
||||
}
|
||||
func TestCtlV3WatchInteractiveClientTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configClientTLS))
|
||||
}
|
||||
func TestCtlV3WatchInteractivePeerTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configPeerTLS))
|
||||
}
|
||||
|
||||
func watchTest(cx ctlCtx) {
|
||||
tests := []struct {
|
||||
puts []kv
|
||||
envKey string
|
||||
envRange string
|
||||
args []string
|
||||
|
||||
wkv []kvExec
|
||||
}{
|
||||
{ // watch 1 key
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1"},
|
||||
wkv: []kvExec{{key: "sample", val: "value"}},
|
||||
},
|
||||
{ // watch 1 key with env
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
args: []string{"--rev", "1"},
|
||||
wkv: []kvExec{{key: "sample", val: "value"}},
|
||||
},
|
||||
{ // watch 1 key with ${ETCD_WATCH_VALUE}
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1", "--", "env"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: `ETCD_WATCH_VALUE="value"`}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received", with env
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
args: []string{"--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"--rev", "1", "sample", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo \"Hello World!\""
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"--rev", "1", "sample", "--", "echo", "\"Hello World!\""},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "Hello World!"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "samplx", "--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
envRange: "samplx",
|
||||
args: []string{"--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1", "samplx", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 3 keys by prefix
|
||||
puts: []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
|
||||
args: []string{"key", "--rev", "1", "--prefix"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}},
|
||||
},
|
||||
{ // watch 3 keys by prefix, with env
|
||||
puts: []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
|
||||
envKey: "key",
|
||||
args: []string{"--rev", "1", "--prefix"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}},
|
||||
},
|
||||
{ // watch by revision
|
||||
puts: []kv{{"etcd", "revision_1"}, {"etcd", "revision_2"}, {"etcd", "revision_3"}},
|
||||
args: []string{"etcd", "--rev", "2"},
|
||||
wkv: []kvExec{{key: "etcd", val: "revision_2"}, {key: "etcd", val: "revision_3"}},
|
||||
},
|
||||
{ // watch 3 keys by range
|
||||
puts: []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
||||
args: []string{"key", "key3", "--rev", "1"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
||||
},
|
||||
{ // watch 3 keys by range, with env
|
||||
puts: []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
||||
envKey: "key",
|
||||
envRange: "key3",
|
||||
args: []string{"--rev", "1"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
donec := make(chan struct{})
|
||||
go func(i int, puts []kv) {
|
||||
for j := range puts {
|
||||
if err := ctlV3Put(cx, puts[j].key, puts[j].val, ""); err != nil {
|
||||
cx.t.Fatalf("watchTest #%d-%d: ctlV3Put error (%v)", i, j, err)
|
||||
}
|
||||
}
|
||||
close(donec)
|
||||
}(i, tt.puts)
|
||||
|
||||
unsetEnv := func() {}
|
||||
if tt.envKey != "" || tt.envRange != "" {
|
||||
if tt.envKey != "" {
|
||||
os.Setenv("ETCDCTL_WATCH_KEY", tt.envKey)
|
||||
unsetEnv = func() { os.Unsetenv("ETCDCTL_WATCH_KEY") }
|
||||
}
|
||||
if tt.envRange != "" {
|
||||
os.Setenv("ETCDCTL_WATCH_RANGE_END", tt.envRange)
|
||||
unsetEnv = func() { os.Unsetenv("ETCDCTL_WATCH_RANGE_END") }
|
||||
}
|
||||
if tt.envKey != "" && tt.envRange != "" {
|
||||
unsetEnv = func() {
|
||||
os.Unsetenv("ETCDCTL_WATCH_KEY")
|
||||
os.Unsetenv("ETCDCTL_WATCH_RANGE_END")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := ctlV3Watch(cx, tt.args, tt.wkv...); err != nil {
|
||||
if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
|
||||
cx.t.Errorf("watchTest #%d: ctlV3Watch error (%v)", i, err)
|
||||
}
|
||||
}
|
||||
unsetEnv()
|
||||
<-donec
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 The etcd Authors
|
||||
// Copyright 2018 The etcd Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -14,167 +14,13 @@
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCtlV3Watch(t *testing.T) { testCtl(t, watchTest) }
|
||||
func TestCtlV3WatchNoTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configNoTLS)) }
|
||||
func TestCtlV3WatchClientTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configClientTLS)) }
|
||||
func TestCtlV3WatchPeerTLS(t *testing.T) { testCtl(t, watchTest, withCfg(configPeerTLS)) }
|
||||
func TestCtlV3WatchTimeout(t *testing.T) { testCtl(t, watchTest, withDialTimeout(0)) }
|
||||
|
||||
func TestCtlV3WatchInteractive(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive())
|
||||
}
|
||||
func TestCtlV3WatchInteractiveNoTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configNoTLS))
|
||||
}
|
||||
func TestCtlV3WatchInteractiveClientTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configClientTLS))
|
||||
}
|
||||
func TestCtlV3WatchInteractivePeerTLS(t *testing.T) {
|
||||
testCtl(t, watchTest, withInteractive(), withCfg(configPeerTLS))
|
||||
}
|
||||
import "strings"
|
||||
|
||||
type kvExec struct {
|
||||
key, val string
|
||||
execOutput string
|
||||
}
|
||||
|
||||
func watchTest(cx ctlCtx) {
|
||||
tests := []struct {
|
||||
puts []kv
|
||||
envKey string
|
||||
envRange string
|
||||
args []string
|
||||
|
||||
wkv []kvExec
|
||||
}{
|
||||
{ // watch 1 key
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1"},
|
||||
wkv: []kvExec{{key: "sample", val: "value"}},
|
||||
},
|
||||
{ // watch 1 key with env
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
args: []string{"--rev", "1"},
|
||||
wkv: []kvExec{{key: "sample", val: "value"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with ${ETCD_WATCH_VALUE}
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1", "--", "env"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: `ETCD_WATCH_VALUE="value"`}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received", with env
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
args: []string{"--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"--rev", "1", "sample", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo \"Hello World!\""
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"--rev", "1", "sample", "--", "echo", "\"Hello World!\""},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "Hello World!"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "samplx", "--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
envKey: "sample",
|
||||
envRange: "samplx",
|
||||
args: []string{"--rev", "1", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 1 key with "echo watch event received"
|
||||
puts: []kv{{"sample", "value"}},
|
||||
args: []string{"sample", "--rev", "1", "samplx", "--", "echo", "watch event received"},
|
||||
wkv: []kvExec{{key: "sample", val: "value", execOutput: "watch event received"}},
|
||||
},
|
||||
{ // watch 3 keys by prefix
|
||||
puts: []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
|
||||
args: []string{"key", "--rev", "1", "--prefix"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}},
|
||||
},
|
||||
{ // watch 3 keys by prefix, with env
|
||||
puts: []kv{{"key1", "val1"}, {"key2", "val2"}, {"key3", "val3"}},
|
||||
envKey: "key",
|
||||
args: []string{"--rev", "1", "--prefix"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}, {key: "key3", val: "val3"}},
|
||||
},
|
||||
{ // watch by revision
|
||||
puts: []kv{{"etcd", "revision_1"}, {"etcd", "revision_2"}, {"etcd", "revision_3"}},
|
||||
args: []string{"etcd", "--rev", "2"},
|
||||
wkv: []kvExec{{key: "etcd", val: "revision_2"}, {key: "etcd", val: "revision_3"}},
|
||||
},
|
||||
{ // watch 3 keys by range
|
||||
puts: []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
||||
args: []string{"key", "key3", "--rev", "1"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
||||
},
|
||||
{ // watch 3 keys by range, with env
|
||||
puts: []kv{{"key1", "val1"}, {"key3", "val3"}, {"key2", "val2"}},
|
||||
envKey: "key",
|
||||
envRange: "key3",
|
||||
args: []string{"--rev", "1"},
|
||||
wkv: []kvExec{{key: "key1", val: "val1"}, {key: "key2", val: "val2"}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
donec := make(chan struct{})
|
||||
go func(i int, puts []kv) {
|
||||
for j := range puts {
|
||||
if err := ctlV3Put(cx, puts[j].key, puts[j].val, ""); err != nil {
|
||||
cx.t.Fatalf("watchTest #%d-%d: ctlV3Put error (%v)", i, j, err)
|
||||
}
|
||||
}
|
||||
close(donec)
|
||||
}(i, tt.puts)
|
||||
|
||||
unsetEnv := func() {}
|
||||
if tt.envKey != "" || tt.envRange != "" {
|
||||
if tt.envKey != "" {
|
||||
os.Setenv("ETCDCTL_WATCH_KEY", tt.envKey)
|
||||
unsetEnv = func() { os.Unsetenv("ETCDCTL_WATCH_KEY") }
|
||||
}
|
||||
if tt.envRange != "" {
|
||||
os.Setenv("ETCDCTL_WATCH_RANGE_END", tt.envRange)
|
||||
unsetEnv = func() { os.Unsetenv("ETCDCTL_WATCH_RANGE_END") }
|
||||
}
|
||||
if tt.envKey != "" && tt.envRange != "" {
|
||||
unsetEnv = func() {
|
||||
os.Unsetenv("ETCDCTL_WATCH_KEY")
|
||||
os.Unsetenv("ETCDCTL_WATCH_RANGE_END")
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := ctlV3Watch(cx, tt.args, tt.wkv...); err != nil {
|
||||
if cx.dialTimeout > 0 && !isGRPCTimedout(err) {
|
||||
cx.t.Errorf("watchTest #%d: ctlV3Watch error (%v)", i, err)
|
||||
}
|
||||
}
|
||||
unsetEnv()
|
||||
<-donec
|
||||
}
|
||||
}
|
||||
|
||||
func setupWatchArgs(cx ctlCtx, args []string) []string {
|
||||
cmdArgs := append(cx.PrefixArgs(), "watch")
|
||||
if cx.interactive {
|
||||
|
Loading…
x
Reference in New Issue
Block a user