Skip to content

Commit

Permalink
etcdctl: use user specified timeout value for entire command execution
Browse files Browse the repository at this point in the history
etcdctl should be capable to use a user specified timeout value for
total command execution, not only per request timeout. This commit
adds a new option --total-timeout to the command. The value passed via
this option is used as a timeout value of entire command execution.

Fixes coreos#3517
  • Loading branch information
mitake committed Sep 15, 2015
1 parent 51f1ee0 commit 4ec71d9
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 131 deletions.
28 changes: 15 additions & 13 deletions etcdctl/command/auth_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,29 @@ func NewAuthCommands() cli.Command {
Usage: "overall auth controls",
Subcommands: []cli.Command{
{
Name: "enable",
Usage: "enable auth access controls",
Action: actionAuthEnable,
Name: "enable",
Usage: "enable auth access controls",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionAuthEnable)
},
},
{
Name: "disable",
Usage: "disable auth access controls",
Action: actionAuthDisable,
Name: "disable",
Usage: "disable auth access controls",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionAuthDisable)
},
},
},
}
}

func actionAuthEnable(c *cli.Context) {
authEnableDisable(c, true)
func actionAuthEnable(c *cli.Context, ctx context.Context) {
authEnableDisable(c, true, ctx)
}

func actionAuthDisable(c *cli.Context) {
authEnableDisable(c, false)
func actionAuthDisable(c *cli.Context, ctx context.Context) {
authEnableDisable(c, false, ctx)
}

func mustNewAuthAPI(c *cli.Context) client.AuthAPI {
Expand All @@ -61,20 +65,18 @@ func mustNewAuthAPI(c *cli.Context) client.AuthAPI {
return client.NewAuthAPI(hc)
}

func authEnableDisable(c *cli.Context, enable bool) {
func authEnableDisable(c *cli.Context, enable bool, ctx context.Context) {
if len(c.Args()) != 0 {
fmt.Fprintln(os.Stderr, "No arguments accepted")
os.Exit(1)
}
s := mustNewAuthAPI(c)
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
var err error
if enable {
err = s.Enable(ctx)
} else {
err = s.Disable(ctx)
}
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand Down
55 changes: 25 additions & 30 deletions etcdctl/command/member_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

"github.com/coreos/etcd/Godeps/_workspace/src/github.com/codegangsta/cli"
"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
"github.com/coreos/etcd/client"
)

func NewMemberCommand() cli.Command {
Expand All @@ -30,38 +29,44 @@ func NewMemberCommand() cli.Command {
Usage: "member add, remove and list subcommands",
Subcommands: []cli.Command{
{
Name: "list",
Usage: "enumerate existing cluster members",
Action: actionMemberList,
Name: "list",
Usage: "enumerate existing cluster members",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionMemberList)
},
},
{
Name: "add",
Usage: "add a new member to the etcd cluster",
Action: actionMemberAdd,
Name: "add",
Usage: "add a new member to the etcd cluster",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionMemberAdd)
},
},
{
Name: "remove",
Usage: "remove an existing member from the etcd cluster",
Action: actionMemberRemove,
Name: "remove",
Usage: "remove an existing member from the etcd cluster",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionMemberRemove)
},
},
{
Name: "update",
Usage: "update an existing member in the etcd cluster",
Action: actionMemberUpdate,
Name: "update",
Usage: "update an existing member in the etcd cluster",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionMemberUpdate)
},
},
},
}
}

func actionMemberList(c *cli.Context) {
func actionMemberList(c *cli.Context, ctx context.Context) {
if len(c.Args()) != 0 {
fmt.Fprintln(os.Stderr, "No arguments accepted")
os.Exit(1)
}
mAPI := mustNewMembersAPI(c)
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
members, err := mAPI.List(ctx)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -76,7 +81,7 @@ func actionMemberList(c *cli.Context) {
}
}

func actionMemberAdd(c *cli.Context) {
func actionMemberAdd(c *cli.Context, ctx context.Context) {
args := c.Args()
if len(args) != 2 {
fmt.Fprintln(os.Stderr, "Provide a name and a single member peerURL")
Expand All @@ -86,9 +91,7 @@ func actionMemberAdd(c *cli.Context) {
mAPI := mustNewMembersAPI(c)

url := args[1]
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
m, err := mAPI.Add(ctx, url)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -98,9 +101,7 @@ func actionMemberAdd(c *cli.Context) {
newName := args[0]
fmt.Printf("Added member named %s with ID %s to cluster\n", newName, newID)

ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
members, err := mAPI.List(ctx)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -123,7 +124,7 @@ func actionMemberAdd(c *cli.Context) {
fmt.Printf("ETCD_INITIAL_CLUSTER_STATE=\"existing\"\n")
}

func actionMemberRemove(c *cli.Context) {
func actionMemberRemove(c *cli.Context, ctx context.Context) {
args := c.Args()
if len(args) != 1 {
fmt.Fprintln(os.Stderr, "Provide a single member ID")
Expand All @@ -133,9 +134,7 @@ func actionMemberRemove(c *cli.Context) {

mAPI := mustNewMembersAPI(c)
// Get the list of members.
listctx, listCancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
members, err := mAPI.List(listctx)
listCancel()
members, err := mAPI.List(ctx)
if err != nil {
fmt.Fprintln(os.Stderr, "Error while verifying ID against known members:", err.Error())
os.Exit(1)
Expand All @@ -158,9 +157,7 @@ func actionMemberRemove(c *cli.Context) {
}

// Actually attempt to remove the member.
ctx, removeCancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
err = mAPI.Remove(ctx, removalID)
removeCancel()
if err != nil {
fmt.Fprintf(os.Stderr, "Received an error trying to remove member %s: %s", removalID, err.Error())
os.Exit(1)
Expand All @@ -169,7 +166,7 @@ func actionMemberRemove(c *cli.Context) {
fmt.Printf("Removed member %s from cluster\n", removalID)
}

func actionMemberUpdate(c *cli.Context) {
func actionMemberUpdate(c *cli.Context, ctx context.Context) {
args := c.Args()
if len(args) != 2 {
fmt.Fprintln(os.Stderr, "Provide an ID and a list of comma separated peerURL (0xabcd http://example.com,http://example1.com)")
Expand All @@ -180,9 +177,7 @@ func actionMemberUpdate(c *cli.Context) {

mid := args[0]
urls := args[1]
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
err := mAPI.Update(ctx, mid, strings.Split(urls, ","))
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand Down
72 changes: 35 additions & 37 deletions etcdctl/command/role_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,32 @@ func NewRoleCommands() cli.Command {
Usage: "role add, grant and revoke subcommands",
Subcommands: []cli.Command{
{
Name: "add",
Usage: "add a new role for the etcd cluster",
Action: actionRoleAdd,
Name: "add",
Usage: "add a new role for the etcd cluster",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionRoleAdd)
},
},
{
Name: "get",
Usage: "get details for a role",
Action: actionRoleGet,
Name: "get",
Usage: "get details for a role",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionRoleGet)
},
},
{
Name: "list",
Usage: "list all roles",
Action: actionRoleList,
Name: "list",
Usage: "list all roles",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionRoleList)
},
},
{
Name: "remove",
Usage: "remove a role from the etcd cluster",
Action: actionRoleRemove,
Name: "remove",
Usage: "remove a role from the etcd cluster",
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionRoleRemove)
},
},
{
Name: "grant",
Expand All @@ -60,7 +68,9 @@ func NewRoleCommands() cli.Command {
cli.BoolFlag{Name: "write", Usage: "Grant write-only access"},
cli.BoolFlag{Name: "readwrite", Usage: "Grant read-write access"},
},
Action: actionRoleGrant,
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionRoleGrant)
},
},
{
Name: "revoke",
Expand All @@ -71,7 +81,9 @@ func NewRoleCommands() cli.Command {
cli.BoolFlag{Name: "write", Usage: "Revoke write access"},
cli.BoolFlag{Name: "readwrite", Usage: "Revoke read-write access"},
},
Action: actionRoleRevoke,
Action: func(c *cli.Context) {
actionWithTotalTimeout(c, actionRoleRevoke)
},
},
},
}
Expand All @@ -87,15 +99,13 @@ func mustNewAuthRoleAPI(c *cli.Context) client.AuthRoleAPI {
return client.NewAuthRoleAPI(hc)
}

func actionRoleList(c *cli.Context) {
func actionRoleList(c *cli.Context, ctx context.Context) {
if len(c.Args()) != 0 {
fmt.Fprintln(os.Stderr, "No arguments accepted")
os.Exit(1)
}
r := mustNewAuthRoleAPI(c)
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
roles, err := r.ListRoles(ctx)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -106,18 +116,14 @@ func actionRoleList(c *cli.Context) {
}
}

func actionRoleAdd(c *cli.Context) {
func actionRoleAdd(c *cli.Context, ctx context.Context) {
api, role := mustRoleAPIAndName(c)
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
currentRole, err := api.GetRole(ctx, role)
cancel()
if currentRole != nil {
fmt.Fprintf(os.Stderr, "Role %s already exists\n", role)
os.Exit(1)
}
ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
err = api.AddRole(ctx, role)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -126,11 +132,9 @@ func actionRoleAdd(c *cli.Context) {
fmt.Printf("Role %s created\n", role)
}

func actionRoleRemove(c *cli.Context) {
func actionRoleRemove(c *cli.Context, ctx context.Context) {
api, role := mustRoleAPIAndName(c)
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
err := api.RemoveRole(ctx, role)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -139,15 +143,15 @@ func actionRoleRemove(c *cli.Context) {
fmt.Printf("Role %s removed\n", role)
}

func actionRoleGrant(c *cli.Context) {
roleGrantRevoke(c, true)
func actionRoleGrant(c *cli.Context, ctx context.Context) {
roleGrantRevoke(c, true, ctx)
}

func actionRoleRevoke(c *cli.Context) {
roleGrantRevoke(c, false)
func actionRoleRevoke(c *cli.Context, ctx context.Context) {
roleGrantRevoke(c, false, ctx)
}

func roleGrantRevoke(c *cli.Context, grant bool) {
func roleGrantRevoke(c *cli.Context, grant bool, ctx context.Context) {
path := c.String("path")
if path == "" {
fmt.Fprintln(os.Stderr, "No path specified; please use `-path`")
Expand Down Expand Up @@ -182,21 +186,17 @@ func roleGrantRevoke(c *cli.Context, grant bool) {
}

api, role := mustRoleAPIAndName(c)
ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
currentRole, err := api.GetRole(ctx, role)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
}
ctx, cancel = context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
var newRole *client.Role
if grant {
newRole, err = api.GrantRoleKV(ctx, role, []string{path}, permType)
} else {
newRole, err = api.RevokeRoleKV(ctx, role, []string{path}, permType)
}
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand All @@ -212,12 +212,10 @@ func roleGrantRevoke(c *cli.Context, grant bool) {
fmt.Printf("Role %s updated\n", role)
}

func actionRoleGet(c *cli.Context) {
func actionRoleGet(c *cli.Context, ctx context.Context) {
api, rolename := mustRoleAPIAndName(c)

ctx, cancel := context.WithTimeout(context.Background(), client.DefaultRequestTimeout)
role, err := api.GetRole(ctx, rolename)
cancel()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(1)
Expand Down
Loading

0 comments on commit 4ec71d9

Please sign in to comment.