mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #12829 from garenchan/dev/etcdctl-lock
etcdctl: lock return exit code of exec-command
This commit is contained in:
commit
7168409e6b
@ -205,6 +205,7 @@ Note that any `etcd_debugging_*` metrics are experimental and subject to change.
|
||||
- Add [`etcdctl auth status`](https://github.com/etcd-io/etcd/pull/11536) command to check if authentication is enabled
|
||||
- Add [`etcdctl get --count-only`](https://github.com/etcd-io/etcd/pull/11743) flag for output type `fields`.
|
||||
- Add [`etcdctl member list -w=json --hex`](https://github.com/etcd-io/etcd/pull/11812) flag to print memberListResponse in hex format json.
|
||||
- Changed [`etcdctl lock <lockname> exec-command`](https://github.com/etcd-io/etcd/pull/12829) to return exit code of exec-command.
|
||||
|
||||
### gRPC gateway
|
||||
|
||||
|
@ -48,10 +48,25 @@ func lockCommandFunc(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
c := mustClientFromCmd(cmd)
|
||||
if err := lockUntilSignal(c, args[0], args[1:]); err != nil {
|
||||
ExitWithError(ExitError, err)
|
||||
code := getExitCodeFromError(err)
|
||||
ExitWithError(code, err)
|
||||
}
|
||||
}
|
||||
|
||||
func getExitCodeFromError(err error) int {
|
||||
if err == nil {
|
||||
return ExitSuccess
|
||||
}
|
||||
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
||||
return status.ExitStatus()
|
||||
}
|
||||
}
|
||||
|
||||
return ExitError
|
||||
}
|
||||
|
||||
func lockUntilSignal(c *clientv3.Client, lockname string, cmdArgs []string) error {
|
||||
s, err := concurrency.NewSession(c, concurrency.WithTTL(lockTTL))
|
||||
if err != nil {
|
||||
|
@ -15,6 +15,7 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -27,6 +28,10 @@ func TestCtlV3Lock(t *testing.T) {
|
||||
testCtl(t, testLock)
|
||||
}
|
||||
|
||||
func TestCtlV3LockWithCmd(t *testing.T) {
|
||||
testCtl(t, testLockWithCmd)
|
||||
}
|
||||
|
||||
func testLock(cx ctlCtx) {
|
||||
name := "a"
|
||||
|
||||
@ -95,6 +100,22 @@ func testLock(cx ctlCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
func testLockWithCmd(cx ctlCtx) {
|
||||
// exec command with zero exit code
|
||||
echoCmd := []string{"echo"}
|
||||
if err := ctlV3LockWithCmd(cx, echoCmd, ""); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
|
||||
// exec command with non-zero exit code
|
||||
code := 3
|
||||
awkCmd := []string{"awk", fmt.Sprintf("BEGIN{exit %d}", code)}
|
||||
expect := fmt.Sprintf("Error: exit status %d", code)
|
||||
if err := ctlV3LockWithCmd(cx, awkCmd, expect); err != nil {
|
||||
cx.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ctlV3Lock creates a lock process with a channel listening for when it acquires the lock.
|
||||
func ctlV3Lock(cx ctlCtx, name string) (*expect.ExpectProcess, <-chan string, error) {
|
||||
cmdArgs := append(cx.PrefixArgs(), "lock", name)
|
||||
@ -113,3 +134,11 @@ func ctlV3Lock(cx ctlCtx, name string) (*expect.ExpectProcess, <-chan string, er
|
||||
}()
|
||||
return proc, outc, err
|
||||
}
|
||||
|
||||
// ctlV3LockWithCmd creates a lock process to exec command.
|
||||
func ctlV3LockWithCmd(cx ctlCtx, execCmd []string, as ...string) error {
|
||||
// use command as lock name
|
||||
cmdArgs := append(cx.PrefixArgs(), "lock", execCmd[0])
|
||||
cmdArgs = append(cmdArgs, execCmd...)
|
||||
return spawnWithExpects(cmdArgs, as...)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user