Confirmation on destructive commands

This commit is contained in:
Alex Dadgar 2016-03-24 14:43:20 -07:00
parent 3320e1c3dd
commit 5d48a2bc71
3 changed files with 62 additions and 2 deletions

View File

@ -27,6 +27,9 @@ Node Drain Options:
-enable
Enable draining for the specified node.
-yes
Automatic yes to prompts.
`
return strings.TrimSpace(helpText)
}
@ -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
@ -108,6 +112,7 @@ 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 {
@ -115,6 +120,33 @@ func (c *NodeDrainCommand) Run(args []string) int {
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))

View File

@ -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.
`
@ -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
@ -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 {

View File

@ -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,
}