etcdctl/ctlv3: fix watch with exec commands
Following command was failing because the parser incorrectly picks up the second "watch" string in exec command, thus passing wrong exec commands. ``` ETCDCTL_API=3 ./bin/etcdctl watch aaa -- echo watch event received panic: runtime error: slice bounds out of range goroutine 1 [running]: github.com/coreos/etcd/etcdctl/ctlv3/command.parseWatchArgs(0xc42002e080, 0x8, 0x8, 0xc420206a20, 0x5, 0x6, 0x0, 0x0, 0x0, 0x0, ...) /home/gyuho/go/src/github.com/coreos/etcd/etcdctl/ctlv3/command/watch_command.go:303 +0xbed github.com/coreos/etcd/etcdctl/ctlv3/command.watchCommandFunc(0xc4202a7180, 0xc420206a20, 0x5, 0x6) /home/gyuho/go/src/github.com/coreos/etcd/etcdctl/ctlv3/command/watch_command.go:73 +0x11d github.com/coreos/etcd/vendor/github.com/spf13/cobra.(*Command).execute(0xc4202a7180, 0xc420206960, 0x6, 0x6, 0xc4202a7180, 0xc420206960) /home/gyuho/go/src/github.com/coreos/etcd/vendor/github.com/spf13/cobra/command.go:766 +0x2c1 github.com/coreos/etcd/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0x1363de0, 0xc420128638, 0xc420185e01, 0xc420185ee8) /home/gyuho/go/src/github.com/coreos/etcd/vendor/github.com/spf13/cobra/command.go:852 +0x30a github.com/coreos/etcd/vendor/github.com/spf13/cobra.(*Command).Execute(0x1363de0, 0x0, 0x0) /home/gyuho/go/src/github.com/coreos/etcd/vendor/github.com/spf13/cobra/command.go:800 +0x2b github.com/coreos/etcd/etcdctl/ctlv3.Start() /home/gyuho/go/src/github.com/coreos/etcd/etcdctl/ctlv3/ctl_nocov.go:25 +0x8e main.main() /home/gyuho/go/src/github.com/coreos/etcd/etcdctl/main.go:40 +0x17b ``` Signed-off-by: Gyuho Lee <gyuhox@gmail.com>release-3.4
parent
2ad0acdea8
commit
44cda79105
|
@ -179,118 +179,159 @@ func printWatchCh(c *clientv3.Client, ch clientv3.WatchChan, execArgs []string)
|
||||||
// "--" characters are invalid arguments for "spf13/cobra" library,
|
// "--" characters are invalid arguments for "spf13/cobra" library,
|
||||||
// so no need to handle such cases.
|
// so no need to handle such cases.
|
||||||
func parseWatchArgs(osArgs, commandArgs []string, envKey, envRange string, interactive bool) (watchArgs []string, execArgs []string, err error) {
|
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)
|
// remove preceding commands (e.g. ./bin/etcdctl watch)
|
||||||
idx := 0
|
// handle "./bin/etcdctl watch foo -- echo watch event"
|
||||||
for idx = range watchArgs {
|
for idx := range rawArgs {
|
||||||
if watchArgs[idx] == "watch" {
|
if rawArgs[idx] == "watch" {
|
||||||
|
rawArgs = rawArgs[idx+1:]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if idx < len(watchArgs)-1 || envKey != "" {
|
|
||||||
if idx < len(watchArgs)-1 {
|
// remove preceding commands (e.g. "watch foo bar" in interactive mode)
|
||||||
watchArgs = watchArgs[idx+1:]
|
// 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
|
execIdx, execExist := 0, false
|
||||||
for execIdx = range osArgs {
|
if !interactive {
|
||||||
v := osArgs[execIdx]
|
for execIdx = range rawArgs {
|
||||||
if v == "--" && execIdx != len(osArgs)-1 {
|
if rawArgs[execIdx] == "--" {
|
||||||
execExist = true
|
execExist = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if execExist && execIdx == len(rawArgs)-1 {
|
||||||
if idx == len(watchArgs)-1 && envKey != "" {
|
// "watch foo bar --" should error
|
||||||
if len(watchArgs) > 0 && !interactive {
|
return nil, nil, errBadArgsNumSeparator
|
||||||
// "watch --rev 1 -- echo Hello World" has no conflict
|
}
|
||||||
if !execExist {
|
// "watch" with no argument should error
|
||||||
// "watch foo" with ETCDCTL_WATCH_KEY=foo
|
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
|
||||||
|
}
|
||||||
|
// watchArgs has extra:
|
||||||
|
// ETCDCTL_WATCH_KEY=foo watch foo -- echo 1
|
||||||
|
// watchArgs: foo echo 1
|
||||||
|
if ridx == execIdx {
|
||||||
|
return nil, nil, errBadArgsNumConflictEnv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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"])
|
// (watchArgs==["foo"])
|
||||||
return nil, nil, errBadArgsNumConflictEnv
|
return nil, nil, errBadArgsNumConflictEnv
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// otherwise, watch with no argument and environment key is set
|
for execIdx = range watchArgs {
|
||||||
// if interactive, first "watch" command string should be removed
|
if watchArgs[execIdx] == "--" {
|
||||||
if interactive {
|
execExist = true
|
||||||
watchArgs = []string{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "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--
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if oidx == execIdx { // watchArgs has extra
|
|
||||||
return nil, nil, errBadArgsNumConflictEnv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if interactive { // "watch" not found
|
|
||||||
return nil, nil, errBadArgsInteractiveWatch
|
|
||||||
}
|
|
||||||
if len(watchArgs) < 1 && envKey == "" {
|
|
||||||
return nil, nil, errBadArgsNum
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove preceding commands (e.g. ./bin/etcdctl watch)
|
|
||||||
for idx = range osArgs {
|
|
||||||
if osArgs[idx] == "watch" {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if idx < len(osArgs)-1 {
|
if execExist && execIdx == len(watchArgs)-1 {
|
||||||
osArgs = osArgs[idx+1:]
|
// "watch foo bar --" should error
|
||||||
} else if envKey == "" {
|
watchPrefix, watchRev, watchPrevKey = false, 0, false
|
||||||
return nil, nil, errBadArgsNum
|
return nil, nil, errBadArgsNumSeparator
|
||||||
}
|
}
|
||||||
|
|
||||||
argsWithSep := osArgs
|
flagset := NewWatchCommand().Flags()
|
||||||
if interactive { // interactive mode pass "--" to the command args
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
argsWithSep := rawArgs
|
||||||
|
if interactive {
|
||||||
|
// interactive mode directly passes "--" to the command args
|
||||||
argsWithSep = watchArgs
|
argsWithSep = watchArgs
|
||||||
}
|
}
|
||||||
foundSep := false
|
|
||||||
|
idx, foundSep := 0, false
|
||||||
for idx = range argsWithSep {
|
for idx = range argsWithSep {
|
||||||
if argsWithSep[idx] == "--" {
|
if argsWithSep[idx] == "--" {
|
||||||
foundSep = true
|
foundSep = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if foundSep {
|
||||||
|
execArgs = argsWithSep[idx+1:]
|
||||||
|
}
|
||||||
|
|
||||||
if interactive {
|
if interactive {
|
||||||
flagset := NewWatchCommand().Flags()
|
flagset := NewWatchCommand().Flags()
|
||||||
if err := flagset.Parse(argsWithSep); err != nil {
|
if err := flagset.Parse(argsWithSep); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
watchArgs = flagset.Args()
|
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
|
// "ETCDCTL_WATCH_KEY=foo watch -- echo hello"
|
||||||
// should be translated to "watch foo -- echo hello"
|
// should translate "watch foo -- echo hello"
|
||||||
// (watchArgs=["echo","hello"] should be ["foo","echo","hello"])
|
// (watchArgs=["echo","hello"] should be ["foo","echo","hello"])
|
||||||
if envKey != "" {
|
if envKey != "" {
|
||||||
tmp := []string{envKey}
|
ranges := []string{envKey}
|
||||||
if envRange != "" {
|
if envRange != "" {
|
||||||
tmp = append(tmp, envRange)
|
ranges = append(ranges, envRange)
|
||||||
}
|
}
|
||||||
watchArgs = append(tmp, watchArgs...)
|
watchArgs = append(ranges, watchArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !foundSep {
|
if !foundSep {
|
||||||
return watchArgs, nil, nil
|
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",
|
// "watch foo bar --rev 1 -- echo hello" or "watch foo --rev 1 bar -- echo hello",
|
||||||
// then "watchArgs" is "foo bar echo hello"
|
// then "watchArgs" is "foo bar echo hello"
|
||||||
// so need ignore args after "argsWithSep[idx]", which is "--"
|
// so need ignore args after "argsWithSep[idx]", which is "--"
|
||||||
|
|
|
@ -26,6 +26,10 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
envKey, envRange string
|
envKey, envRange string
|
||||||
interactive bool
|
interactive bool
|
||||||
|
|
||||||
|
interactiveWatchPrefix bool
|
||||||
|
interactiveWatchRev int64
|
||||||
|
interactiveWatchPrevKey bool
|
||||||
|
|
||||||
watchArgs []string
|
watchArgs []string
|
||||||
execArgs []string
|
execArgs []string
|
||||||
err error
|
err error
|
||||||
|
@ -145,6 +149,14 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
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"},
|
osArgs: []string{"./bin/etcdctl", "watch", "foo", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||||
commandArgs: []string{"foo", "echo", "Hello", "World"},
|
commandArgs: []string{"foo", "echo", "Hello", "World"},
|
||||||
|
@ -153,6 +165,22 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
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"},
|
osArgs: []string{"./bin/etcdctl", "watch", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||||
commandArgs: []string{"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"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
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"},
|
osArgs: []string{"./bin/etcdctl", "watch", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||||
commandArgs: []string{"echo", "Hello", "World"},
|
commandArgs: []string{"echo", "Hello", "World"},
|
||||||
|
@ -218,6 +270,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"foo", "bar", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"foo", "bar", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: nil,
|
watchArgs: nil,
|
||||||
execArgs: nil,
|
execArgs: nil,
|
||||||
err: errBadArgsInteractiveWatch,
|
err: errBadArgsInteractiveWatch,
|
||||||
|
@ -226,6 +281,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo"},
|
commandArgs: []string{"watch", "foo"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo"},
|
watchArgs: []string{"foo"},
|
||||||
execArgs: nil,
|
execArgs: nil,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -234,6 +292,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo", "bar"},
|
commandArgs: []string{"watch", "foo", "bar"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: nil,
|
execArgs: nil,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -244,6 +305,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
envKey: "foo",
|
envKey: "foo",
|
||||||
envRange: "bar",
|
envRange: "bar",
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: nil,
|
execArgs: nil,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -254,6 +318,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
envKey: "hello world!",
|
envKey: "hello world!",
|
||||||
envRange: "bar",
|
envRange: "bar",
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"hello world!", "bar"},
|
watchArgs: []string{"hello world!", "bar"},
|
||||||
execArgs: nil,
|
execArgs: nil,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -262,6 +329,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo", "--rev", "1"},
|
commandArgs: []string{"watch", "foo", "--rev", "1"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 1,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo"},
|
watchArgs: []string{"foo"},
|
||||||
execArgs: nil,
|
execArgs: nil,
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -270,6 +340,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo", "--rev", "1", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "foo", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 1,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo"},
|
watchArgs: []string{"foo"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -278,15 +351,90 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "--rev", "1", "foo", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "--rev", "1", "foo", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 1,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo"},
|
watchArgs: []string{"foo"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
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", "--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", "--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", "--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", "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", "--rev", "1", "--prefix"},
|
||||||
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
|
watchArgs: nil,
|
||||||
|
execArgs: nil,
|
||||||
|
err: errBadArgsNum,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "--", "echo", "Hello", "World"},
|
||||||
envKey: "foo",
|
envKey: "foo",
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo"},
|
watchArgs: []string{"foo"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -297,6 +445,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
envKey: "foo",
|
envKey: "foo",
|
||||||
envRange: "bar",
|
envRange: "bar",
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -305,6 +456,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo", "bar", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 0,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -313,6 +467,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "--rev", "1", "foo", "bar", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "--rev", "1", "foo", "bar", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 1,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -323,6 +480,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
envKey: "foo",
|
envKey: "foo",
|
||||||
envRange: "bar",
|
envRange: "bar",
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 1,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -331,6 +491,9 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo", "--rev", "1", "bar", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "foo", "--rev", "1", "bar", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
interactive: true,
|
||||||
|
interactiveWatchPrefix: false,
|
||||||
|
interactiveWatchRev: 1,
|
||||||
|
interactiveWatchPrevKey: false,
|
||||||
watchArgs: []string{"foo", "bar"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -339,6 +502,31 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
osArgs: []string{"./bin/etcdctl", "watch", "-i"},
|
||||||
commandArgs: []string{"watch", "foo", "bar", "--rev", "1", "--", "echo", "Hello", "World"},
|
commandArgs: []string{"watch", "foo", "bar", "--rev", "1", "--", "echo", "Hello", "World"},
|
||||||
interactive: true,
|
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"},
|
watchArgs: []string{"foo", "bar"},
|
||||||
execArgs: []string{"echo", "Hello", "World"},
|
execArgs: []string{"echo", "Hello", "World"},
|
||||||
err: nil,
|
err: nil,
|
||||||
|
@ -355,5 +543,16 @@ func Test_parseWatchArgs(t *testing.T) {
|
||||||
if !reflect.DeepEqual(execArgs, ts.execArgs) {
|
if !reflect.DeepEqual(execArgs, ts.execArgs) {
|
||||||
t.Fatalf("#%d: execArgs expected %q, got %v", i, ts.execArgs, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue