util/prompt: add a default and take default in non-interactive cases

The Tailscale CLI is the primary configuration interface and as such it
is used in scripts, container setups, and many other places that do not
have a terminal available and should not be made to respond to prompts.

The default is set to false where the "risky" API is being used by the
CLI and true otherwise, this means that the `--yes` flags are only
required under interactive runs and scripts do not need to be concerned
with prompts or extra flags.

Updates #19445

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker
2025-09-12 12:33:46 -07:00
committed by James Tucker
parent 442a3a779d
commit b9cdef18c0
5 changed files with 21 additions and 6 deletions

View File

@@ -6,19 +6,34 @@ package prompt
import (
"fmt"
"os"
"strings"
"github.com/mattn/go-isatty"
)
// YesNo takes a question and prompts the user to answer the
// question with a yes or no. It appends a [y/n] to the message.
func YesNo(msg string) bool {
fmt.Print(msg + " [y/n] ")
//
// If there is no TTY on both Stdin and Stdout, assume that we're in a script
// and return the dflt result.
func YesNo(msg string, dflt bool) bool {
if !(isatty.IsTerminal(os.Stdin.Fd()) && isatty.IsTerminal(os.Stdout.Fd())) {
return dflt
}
if dflt {
fmt.Print(msg + " [Y/n] ")
} else {
fmt.Print(msg + " [y/N] ")
}
var resp string
fmt.Scanln(&resp)
resp = strings.ToLower(resp)
switch resp {
case "y", "yes", "sure":
return true
case "":
return dflt
}
return false
}