constellation/cli/internal/cmd/terminate.go
Daniel Weiße c52086c5ff
cli: refactor flag parsing code (#2425)
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
2023-10-16 15:05:29 +02:00

118 lines
3.3 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cmd
import (
"errors"
"fmt"
"io/fs"
"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
)
// NewTerminateCmd returns a new cobra.Command for the terminate command.
func NewTerminateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "terminate",
Short: "Terminate a Constellation cluster",
Long: "Terminate a Constellation cluster.\n\n" +
"The cluster can't be started again, and all persistent storage will be lost.",
Args: cobra.NoArgs,
RunE: runTerminate,
}
cmd.Flags().BoolP("yes", "y", false, "terminate the cluster without further confirmation")
return cmd
}
type terminateFlags struct {
rootFlags
yes bool
}
func (f *terminateFlags) parse(flags *pflag.FlagSet) error {
if err := f.rootFlags.parse(flags); err != nil {
return err
}
yes, err := flags.GetBool("yes")
if err != nil {
return fmt.Errorf("getting 'yes' flag: %w", err)
}
f.yes = yes
return nil
}
// runTerminate runs the terminate command.
func runTerminate(cmd *cobra.Command, _ []string) error {
spinner, err := newSpinnerOrStderr(cmd)
if err != nil {
return fmt.Errorf("creating spinner: %w", err)
}
defer spinner.Stop()
terminator := cloudcmd.NewTerminator()
logger, err := newCLILogger(cmd)
if err != nil {
return fmt.Errorf("creating logger: %w", err)
}
t := &terminateCmd{log: logger, fileHandler: file.NewHandler(afero.NewOsFs())}
if err := t.flags.parse(cmd.Flags()); err != nil {
return err
}
return t.terminate(cmd, terminator, spinner)
}
type terminateCmd struct {
log debugLog
fileHandler file.Handler
flags terminateFlags
}
func (t *terminateCmd) terminate(cmd *cobra.Command, terminator cloudTerminator, spinner spinnerInterf) error {
if !t.flags.yes {
cmd.Println("You are about to terminate a Constellation cluster.")
cmd.Println("All of its associated resources will be DESTROYED.")
cmd.Println("This action is irreversible and ALL DATA WILL BE LOST.")
ok, err := askToConfirm(cmd, "Do you want to continue?")
if err != nil {
return err
}
if !ok {
cmd.Println("The termination of the cluster was aborted.")
return nil
}
}
spinner.Start("Terminating", false)
err := terminator.Terminate(cmd.Context(), constants.TerraformWorkingDir, t.flags.tfLogLevel)
spinner.Stop()
if err != nil {
return fmt.Errorf("terminating Constellation cluster: %w", err)
}
cmd.Println("Your Constellation cluster was terminated successfully.")
var removeErr error
if err := t.fileHandler.Remove(constants.AdminConfFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
removeErr = errors.Join(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", t.flags.pathPrefixer.PrefixPrintablePath(constants.AdminConfFilename)))
}
if err := t.fileHandler.Remove(constants.StateFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
removeErr = errors.Join(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", t.flags.pathPrefixer.PrefixPrintablePath(constants.StateFilename)))
}
return removeErr
}