From 7d9926bd2576d2334a08acb59f916ddcfe642d9c Mon Sep 17 00:00:00 2001 From: Allen Zhong Date: Fri, 19 Nov 2021 13:43:32 +0800 Subject: [PATCH 1/2] add significant warning when `--force` is set for scale-in --- pkg/cluster/manager/scale_in.go | 12 +++++++---- pkg/tui/tui.go | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/pkg/cluster/manager/scale_in.go b/pkg/cluster/manager/scale_in.go index beee220a6d..344b96f25d 100644 --- a/pkg/cluster/manager/scale_in.go +++ b/pkg/cluster/manager/scale_in.go @@ -49,11 +49,15 @@ func (m *Manager) ScaleIn( ) if !skipConfirm { if force { - if err := tui.PromptForConfirmOrAbortError( + log.Warnf(color.HiRedString(tui.ASCIIArtWarning)) + if err := tui.PromptForAnswerOrAbortError( + "Yes, I know my data might be lost.", color.HiRedString("Forcing scale in is unsafe and may result in data loss for stateful components.\n"+ - "The process is irreversible and could NOT be cancelled.\n") + - "Only use `--force` when some of the servers are already permanently offline.\n" + - "Are you sure to continue? [y/N]:", + "DO NOT use `--force` if you have any component in ")+ + color.YellowString("Pending Offline")+color.HiRedString(" status.\n")+ + color.HiRedString("The process is irreversible and could NOT be cancelled.\n")+ + "Only use `--force` when some of the servers are already permanently offline.\n"+ + "Are you sure to continue?", ); err != nil { return err } diff --git a/pkg/tui/tui.go b/pkg/tui/tui.go index a53d2ea488..aa2e6b7038 100644 --- a/pkg/tui/tui.go +++ b/pkg/tui/tui.go @@ -21,6 +21,7 @@ import ( "syscall" "github.com/AstroProfundis/tabby" + "github.com/fatih/color" "github.com/pingcap/tiup/pkg/utils/mock" "golang.org/x/term" ) @@ -59,6 +60,21 @@ func addRow(t *tabby.Tabby, rawLine []string, header bool) { } } +// pre-defined ascii art strings +const ( + ASCIIArtWarning = ` + █ █░▄▄▄ ██▀███ ███▄ █ ██▓███▄ █ ▄████ ▐██▌ ▐██▌ ▐██▌ + ▓█░ █ ░█▒████▄ ▓██ ▒ ██▒██ ▀█ █▓██▒██ ▀█ █ ██▒ ▀█▒ ▐██▌ ▐██▌ ▐██▌ + ▒█░ █ ░█▒██ ▀█▄ ▓██ ░▄█ ▓██ ▀█ ██▒██▓██ ▀█ ██▒██░▄▄▄░ ▐██▌ ▐██▌ ▐██▌ + ░█░ █ ░█░██▄▄▄▄██▒██▀▀█▄ ▓██▒ ▐▌██░██▓██▒ ▐▌██░▓█ ██▓ ▓██▒ ▓██▒ ▓██▒ + ░░██▒██▓ ▓█ ▓██░██▓ ▒██▒██░ ▓██░██▒██░ ▓██░▒▓███▀▒ ▒▄▄ ▒▄▄ ▒▄▄ + ░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒▓ ░▒▓░ ▒░ ▒ ▒░▓ ░ ▒░ ▒ ▒ ░▒ ▒ ░▀▀▒ ░▀▀▒ ░▀▀▒ + ▒ ░ ░ ▒ ▒▒ ░ ░▒ ░ ▒░ ░░ ░ ▒░▒ ░ ░░ ░ ▒░ ░ ░ ░ ░ ░ ░ ░ ░ + ░ ░ ░ ▒ ░░ ░ ░ ░ ░ ▒ ░ ░ ░ ░░ ░ ░ ░ ░ ░ + ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ +` +) + // Prompt accepts input from console by user func Prompt(prompt string) string { if prompt != "" { @@ -106,6 +122,25 @@ func PromptForConfirmOrAbortError(format string, a ...interface{}) error { return nil } +// PromptForConfirmAnswer accepts string from console by user, default to empty and only return +// true if the user input is exactly the same as pre-defined answer. +func PromptForConfirmAnswer(answer string, format string, a ...interface{}) (bool, string) { + ans := Prompt(fmt.Sprintf(format, a...) + fmt.Sprintf("\n(Type \"%s\" to continue)\n:", color.CyanString(answer))) + if ans == answer { + return true, ans + } + return false, ans +} + +// PromptForAnswerOrAbortError accepts string from console by user, generates AbortError if user does +// not input the pre-defined answer. +func PromptForAnswerOrAbortError(answer string, format string, a ...interface{}) error { + if pass, ans := PromptForConfirmAnswer(answer, format, a...); !pass { + return errOperationAbort.New("Operation aborted by user (with incorrect answer '%s')", ans) + } + return nil +} + // PromptForPassword reads a password input from console func PromptForPassword(format string, a ...interface{}) string { defer fmt.Println("") From 7ef1087ef4e16e16d05709f8805c5eeda7275024 Mon Sep 17 00:00:00 2001 From: Allen Zhong Date: Fri, 19 Nov 2021 16:27:17 +0800 Subject: [PATCH 2/2] update ascii art --- pkg/tui/tui.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pkg/tui/tui.go b/pkg/tui/tui.go index aa2e6b7038..b566eb96cf 100644 --- a/pkg/tui/tui.go +++ b/pkg/tui/tui.go @@ -63,15 +63,11 @@ func addRow(t *tabby.Tabby, rawLine []string, header bool) { // pre-defined ascii art strings const ( ASCIIArtWarning = ` - █ █░▄▄▄ ██▀███ ███▄ █ ██▓███▄ █ ▄████ ▐██▌ ▐██▌ ▐██▌ - ▓█░ █ ░█▒████▄ ▓██ ▒ ██▒██ ▀█ █▓██▒██ ▀█ █ ██▒ ▀█▒ ▐██▌ ▐██▌ ▐██▌ - ▒█░ █ ░█▒██ ▀█▄ ▓██ ░▄█ ▓██ ▀█ ██▒██▓██ ▀█ ██▒██░▄▄▄░ ▐██▌ ▐██▌ ▐██▌ - ░█░ █ ░█░██▄▄▄▄██▒██▀▀█▄ ▓██▒ ▐▌██░██▓██▒ ▐▌██░▓█ ██▓ ▓██▒ ▓██▒ ▓██▒ - ░░██▒██▓ ▓█ ▓██░██▓ ▒██▒██░ ▓██░██▒██░ ▓██░▒▓███▀▒ ▒▄▄ ▒▄▄ ▒▄▄ - ░ ▓░▒ ▒ ▒▒ ▓▒█░ ▒▓ ░▒▓░ ▒░ ▒ ▒░▓ ░ ▒░ ▒ ▒ ░▒ ▒ ░▀▀▒ ░▀▀▒ ░▀▀▒ - ▒ ░ ░ ▒ ▒▒ ░ ░▒ ░ ▒░ ░░ ░ ▒░▒ ░ ░░ ░ ▒░ ░ ░ ░ ░ ░ ░ ░ ░ - ░ ░ ░ ▒ ░░ ░ ░ ░ ░ ▒ ░ ░ ░ ░░ ░ ░ ░ ░ ░ - ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ + ██ ██ █████ ██████ ███ ██ ██ ███ ██ ██████ + ██ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██ ██ + ██ █ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ███ + ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ + ███ ███ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██████ ` )