2022-09-05 03:06:08 -04:00
|
|
|
/*
|
|
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
2022-03-22 11:03:15 -04:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/fs"
|
|
|
|
|
|
|
|
"github.com/spf13/afero"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
2022-09-21 07:47:57 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
|
2023-08-08 09:42:06 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix"
|
2023-04-14 08:15:07 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/cli/internal/terraform"
|
2022-09-21 07:47:57 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
|
|
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
2022-03-22 11:03:15 -04:00
|
|
|
)
|
|
|
|
|
2022-06-08 02:14:28 -04:00
|
|
|
// NewTerminateCmd returns a new cobra.Command for the terminate command.
|
|
|
|
func NewTerminateCmd() *cobra.Command {
|
2022-03-22 11:03:15 -04:00
|
|
|
cmd := &cobra.Command{
|
|
|
|
Use: "terminate",
|
2022-05-09 11:02:47 -04:00
|
|
|
Short: "Terminate a Constellation cluster",
|
2023-01-17 08:01:56 -05:00
|
|
|
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,
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
2022-10-31 11:58:15 -04:00
|
|
|
cmd.Flags().BoolP("yes", "y", false, "terminate the cluster without further confirmation")
|
2022-03-22 11:03:15 -04:00
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
|
|
|
|
// runTerminate runs the terminate command.
|
2023-03-20 06:03:36 -04:00
|
|
|
func runTerminate(cmd *cobra.Command, _ []string) error {
|
2022-03-22 11:03:15 -04:00
|
|
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
2023-02-16 09:43:19 -05:00
|
|
|
spinner, err := newSpinnerOrStderr(cmd)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating spinner: %w", err)
|
|
|
|
}
|
2022-10-07 13:35:07 -04:00
|
|
|
defer spinner.Stop()
|
2022-04-13 07:01:38 -04:00
|
|
|
terminator := cloudcmd.NewTerminator()
|
|
|
|
|
2022-10-07 13:35:07 -04:00
|
|
|
return terminate(cmd, terminator, fileHandler, spinner)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-10-07 13:35:07 -04:00
|
|
|
func terminate(cmd *cobra.Command, terminator cloudTerminator, fileHandler file.Handler, spinner spinnerInterf,
|
|
|
|
) error {
|
2023-04-14 08:15:07 -04:00
|
|
|
flags, err := parseTerminateFlags(cmd)
|
2022-10-31 11:58:15 -04:00
|
|
|
if err != nil {
|
2023-04-14 08:15:07 -04:00
|
|
|
return fmt.Errorf("parsing flags: %w", err)
|
2022-10-31 11:58:15 -04:00
|
|
|
}
|
2023-08-08 09:42:06 -04:00
|
|
|
pf := pathprefix.New(flags.workspace)
|
2022-10-31 11:58:15 -04:00
|
|
|
|
2023-04-14 08:15:07 -04:00
|
|
|
if !flags.yes {
|
2022-10-31 11:58:15 -04:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-07 13:35:07 -04:00
|
|
|
spinner.Start("Terminating", false)
|
2023-08-04 07:53:51 -04:00
|
|
|
err = terminator.Terminate(cmd.Context(), constants.TerraformWorkingDir, flags.logLevel)
|
2022-10-04 12:17:05 -04:00
|
|
|
spinner.Stop()
|
|
|
|
if err != nil {
|
2022-06-09 10:10:42 -04:00
|
|
|
return fmt.Errorf("terminating Constellation cluster: %w", err)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-05-04 03:13:46 -04:00
|
|
|
cmd.Println("Your Constellation cluster was terminated successfully.")
|
2022-03-22 11:03:15 -04:00
|
|
|
|
2023-02-07 09:19:59 -05:00
|
|
|
var removeErr error
|
2022-04-06 04:36:58 -04:00
|
|
|
if err := fileHandler.Remove(constants.AdminConfFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
2023-08-08 09:42:06 -04:00
|
|
|
removeErr = errors.Join(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", pf.PrefixPath(constants.AdminConfFilename)))
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
2022-03-29 05:38:14 -04:00
|
|
|
|
2023-08-04 07:53:51 -04:00
|
|
|
if err := fileHandler.Remove(constants.ClusterIDsFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
2023-08-08 09:42:06 -04:00
|
|
|
removeErr = errors.Join(err, fmt.Errorf("failed to remove file: '%s', please remove it manually", pf.PrefixPath(constants.ClusterIDsFilename)))
|
2022-07-05 07:59:46 -04:00
|
|
|
}
|
|
|
|
|
2023-02-07 09:19:59 -05:00
|
|
|
return removeErr
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
2023-04-14 08:15:07 -04:00
|
|
|
|
|
|
|
type terminateFlags struct {
|
2023-08-04 07:53:51 -04:00
|
|
|
yes bool
|
|
|
|
workspace string
|
|
|
|
logLevel terraform.LogLevel
|
2023-04-14 08:15:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func parseTerminateFlags(cmd *cobra.Command) (terminateFlags, error) {
|
|
|
|
yes, err := cmd.Flags().GetBool("yes")
|
|
|
|
if err != nil {
|
|
|
|
return terminateFlags{}, fmt.Errorf("parsing yes bool: %w", err)
|
|
|
|
}
|
|
|
|
logLevelString, err := cmd.Flags().GetString("tf-log")
|
|
|
|
if err != nil {
|
|
|
|
return terminateFlags{}, fmt.Errorf("parsing tf-log string: %w", err)
|
|
|
|
}
|
|
|
|
logLevel, err := terraform.ParseLogLevel(logLevelString)
|
|
|
|
if err != nil {
|
|
|
|
return terminateFlags{}, fmt.Errorf("parsing Terraform log level %s: %w", logLevelString, err)
|
|
|
|
}
|
2023-08-04 07:53:51 -04:00
|
|
|
workspace, err := cmd.Flags().GetString("workspace")
|
|
|
|
if err != nil {
|
|
|
|
return terminateFlags{}, fmt.Errorf("parsing workspace string: %w", err)
|
|
|
|
}
|
2023-04-14 08:15:07 -04:00
|
|
|
|
|
|
|
return terminateFlags{
|
2023-08-04 07:53:51 -04:00
|
|
|
yes: yes,
|
|
|
|
workspace: workspace,
|
|
|
|
logLevel: logLevel,
|
2023-04-14 08:15:07 -04:00
|
|
|
}, nil
|
|
|
|
}
|