From 991ec3a76b4485331d0735ad8b6a5b1304c03572 Mon Sep 17 00:00:00 2001 From: Rohan CJ Date: Fri, 29 Nov 2024 17:23:18 +0530 Subject: [PATCH] fix(cli): platform destroy should prompt for confirmation Signed-off-by: Rohan CJ --- cmd/vclusterctl/cmd/platform/destroy.go | 22 +++++++++++++++++++++- pkg/cli/destroy/destroy.go | 1 + pkg/cli/start/start.go | 21 ++++++++++++--------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/cmd/vclusterctl/cmd/platform/destroy.go b/cmd/vclusterctl/cmd/platform/destroy.go index d884d8600..93fc264eb 100644 --- a/cmd/vclusterctl/cmd/platform/destroy.go +++ b/cmd/vclusterctl/cmd/platform/destroy.go @@ -4,8 +4,10 @@ import ( "context" "errors" "fmt" + "os" "github.com/loft-sh/log" + "github.com/loft-sh/log/survey" "github.com/loft-sh/vcluster/pkg/cli/destroy" "github.com/loft-sh/vcluster/pkg/cli/flags" "github.com/loft-sh/vcluster/pkg/cli/start" @@ -37,6 +39,9 @@ func NewDestroyCmd(globalFlags *flags.GlobalFlags) *cobra.Command { Destroys a vCluster Platform instance in your Kubernetes cluster. +Important: This action is done against the cluster the the kube-context is pointing to, and not the vCluster Platform instance that is logged in. +It does not require logging in to vCluster Platform. + Please make sure you meet the following requirements before running this command: @@ -59,6 +64,7 @@ VirtualClusterInstances managed with driver helm will be deleted, but the underl destroyCmd.Flags().BoolVar(&cmd.DeleteNamespace, "delete-namespace", true, "Whether to delete the namespace or not") destroyCmd.Flags().BoolVar(&cmd.IgnoreNotFound, "ignore-not-found", false, "Exit successfully if platform installation is not found") destroyCmd.Flags().BoolVar(&cmd.Force, "force", false, "Try uninstalling even if the platform is not installed. '--namespace' is required if true") + destroyCmd.Flags().BoolVar(&cmd.NonInteractive, "non-interactive", false, "Will not prompt for confirmation") destroyCmd.Flags().IntVar(&cmd.TimeoutMinutes, "timeout-minutes", 5, "How long to try deleting the platform before giving up") return destroyCmd @@ -66,7 +72,7 @@ VirtualClusterInstances managed with driver helm will be deleted, but the underl func (cmd *DestroyCmd) Run(ctx context.Context) error { // initialise clients, verify binaries exist, sanity-check context - err := cmd.Options.Prepare() + err := cmd.Options.Prepare(cmd.NonInteractive) if err != nil { return fmt.Errorf("failed to prepare clients: %w", err) } @@ -97,6 +103,20 @@ func (cmd *DestroyCmd) Run(ctx context.Context) error { return fmt.Errorf("platform not installed in namespace %q", cmd.Namespace) } + if !cmd.NonInteractive { + deleteOpt := "delete" + out, err := cmd.Log.Question(&survey.QuestionOptions{ + Question: fmt.Sprintf("IMPORTANT! You are destroy the vCluster Platform in the namespace %q.\nThis may result in data loss. Please ensure your kube-context is pointed at the right cluster.\n Please type %q to continue:", cmd.Namespace, deleteOpt), + }) + if err != nil { + return fmt.Errorf("failed to prompt for confirmation: %w", err) + } + if out != deleteOpt { + cmd.Log.Info("destroy cancelled") + return nil + } + } + err = destroy.Destroy(ctx, cmd.DeleteOptions) if err != nil { return fmt.Errorf("failed to destroy platform: %w", err) diff --git a/pkg/cli/destroy/destroy.go b/pkg/cli/destroy/destroy.go index d7bd5a156..65c6f4f4e 100644 --- a/pkg/cli/destroy/destroy.go +++ b/pkg/cli/destroy/destroy.go @@ -73,6 +73,7 @@ type DeleteOptions struct { DeleteNamespace bool IgnoreNotFound bool Force bool + NonInteractive bool TimeoutMinutes int } diff --git a/pkg/cli/start/start.go b/pkg/cli/start/start.go index 799e58865..184379a52 100644 --- a/pkg/cli/start/start.go +++ b/pkg/cli/start/start.go @@ -93,7 +93,7 @@ func (l *LoftStarter) Start(ctx context.Context) error { l.LocalPort = "9898" } - err := l.Prepare() + err := l.Prepare(false) if err != nil { return err } @@ -141,7 +141,7 @@ func (l *LoftStarter) Start(ctx context.Context) error { } // Prepare initializes clients, verifies the existense of binaries, and ensures we are starting with the right kube context -func (l *Options) Prepare() error { +func (l *Options) Prepare(cliNonInteractive bool) error { platformClient := platform.NewClientFromConfig(l.LoadedConfig(l.Log)) platformConfig := platformClient.Config().Platform @@ -160,15 +160,18 @@ func (l *Options) Prepare() error { if l.Context != "" { contextToLoad = l.Context } else if platformConfig.LastInstallContext != "" && platformConfig.LastInstallContext != contextToLoad { - contextToLoad, err = l.Log.Question(&survey.QuestionOptions{ - Question: product.Replace(fmt.Sprintf("Seems like you try to use 'vcluster %s' with a different kubernetes context than before. Please choose which kubernetes context you want to use", l.CommandName)), - DefaultValue: contextToLoad, - Options: []string{contextToLoad, platformConfig.LastInstallContext}, - }) - if err != nil { - return err + if !cliNonInteractive { + contextToLoad, err = l.Log.Question(&survey.QuestionOptions{ + Question: product.Replace(fmt.Sprintf("Seems like you try to use 'vcluster %s' with a different kubernetes context than before. Please choose which kubernetes context you want to use", l.CommandName)), + DefaultValue: contextToLoad, + Options: []string{contextToLoad, platformConfig.LastInstallContext}, + }) + if err != nil { + return err + } } } + l.Context = contextToLoad platformConfig.LastInstallContext = contextToLoad