diff --git a/command/node_drain.go b/command/node_drain.go index 8b73ed3444f..3238142c7f2 100644 --- a/command/node_drain.go +++ b/command/node_drain.go @@ -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)) diff --git a/command/stop.go b/command/stop.go index b970ca847d4..d3daaf955a0 100644 --- a/command/stop.go +++ b/command/stop.go @@ -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 { diff --git a/commands.go b/commands.go index 7a6709d12cb..2374dea068b 100644 --- a/commands.go +++ b/commands.go @@ -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, }