Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confirmation on destructive commands #983

Merged
merged 1 commit into from
Mar 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion command/node_drain.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ Node Drain Options:

-enable
Enable draining for the specified node.

-yes
Automatic yes to prompts.
`
return strings.TrimSpace(helpText)
}
Expand All @@ -36,12 +39,13 @@ func (c *NodeDrainCommand) Synopsis() string {
}

func (c *NodeDrainCommand) Run(args []string) int {
var enable, disable bool
var enable, disable, autoYes bool

flags := c.Meta.FlagSet("node-drain", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&enable, "enable", false, "Enable drain mode")
flags.BoolVar(&disable, "disable", false, "Disable drain mode")
flags.BoolVar(&autoYes, "yes", false, "Automatic yes to prompts.")

if err := flags.Parse(args); err != nil {
return 1
Expand Down Expand Up @@ -108,13 +112,41 @@ func (c *NodeDrainCommand) Run(args []string) int {
c.Ui.Output(fmt.Sprintf("Prefix matched multiple nodes\n\n%s", formatList(out)))
return 0
}

// Prefix lookup matched a single node
node, _, err := client.Nodes().Info(nodes[0].ID, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error toggling drain mode: %s", err))
return 1
}

// Confirm drain if the node was a prefix match.
if nodeID != node.ID && !autoYes {
verb := "enable"
if disable {
verb = "disable"
}
question := fmt.Sprintf("Are you sure you want to %s drain mode for node %q? [y/N]", verb, node.ID)
answer, err := c.Ui.Ask(question)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to parse answer: %v", err))
return 1
}

if answer == "" || strings.ToLower(answer)[0] == 'n' {
// No case
c.Ui.Output("Canceling drain toggle")
return 0
} else if strings.ToLower(answer)[0] == 'y' {
// Non exact match yes
c.Ui.Output("For confirmation, an exact ‘y’ is required.")
return 0
} else if answer != "y" {
c.Ui.Output("No confirmation detected. For confirmation, an exact 'y' is required.")
return 1
}
}

// Toggle node draining
if _, err := client.Nodes().ToggleDrain(node.ID, enable, nil); err != nil {
c.Ui.Error(fmt.Sprintf("Error toggling drain mode: %s", err))
Expand Down
29 changes: 28 additions & 1 deletion command/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ Stop Options:
to the screen, which can be used to call up a monitor later if
needed using the eval-monitor command.

-yes
Automatic yes to prompts.

-verbose
Display full information.
`
Expand All @@ -42,12 +45,13 @@ func (c *StopCommand) Synopsis() string {
}

func (c *StopCommand) Run(args []string) int {
var detach, verbose bool
var detach, verbose, autoYes bool

flags := c.Meta.FlagSet("stop", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&detach, "detach", false, "")
flags.BoolVar(&verbose, "verbose", false, "")
flags.BoolVar(&autoYes, "yes", false, "")

if err := flags.Parse(args); err != nil {
return 1
Expand Down Expand Up @@ -104,6 +108,29 @@ func (c *StopCommand) Run(args []string) int {
return 1
}

// Confirm the stop if the job was a prefix match.
if jobID != job.ID && !autoYes {
question := fmt.Sprintf("Are you sure you want to stop job %q? [y/N]", job.ID)
answer, err := c.Ui.Ask(question)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to parse answer: %v", err))
return 1
}

if answer == "" || strings.ToLower(answer)[0] == 'n' {
// No case
c.Ui.Output("Cancelling job stop")
return 0
} else if strings.ToLower(answer)[0] == 'y' {
// Non exact match yes
c.Ui.Output("For confirmation, an exact ‘y’ is required.")
return 0
} else if answer != "y" {
c.Ui.Output("No confirmation detected. For confirmation, an exact 'y' is required.")
return 1
}
}

// Invoke the stop
evalID, _, err := client.Jobs().Deregister(job.ID, nil)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
meta := *metaPtr
if meta.Ui == nil {
meta.Ui = &cli.BasicUi{
Reader: os.Stdin,
Writer: os.Stdout,
ErrorWriter: os.Stderr,
}
Expand Down