2022-03-22 11:03:15 -04:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/fs"
|
|
|
|
|
|
|
|
"github.com/spf13/afero"
|
|
|
|
"github.com/spf13/cobra"
|
2022-03-29 05:38:14 -04:00
|
|
|
"go.uber.org/multierr"
|
2022-03-22 11:03:15 -04:00
|
|
|
|
|
|
|
azure "github.com/edgelesssys/constellation/cli/azure/client"
|
|
|
|
ec2 "github.com/edgelesssys/constellation/cli/ec2/client"
|
|
|
|
"github.com/edgelesssys/constellation/cli/file"
|
|
|
|
gcp "github.com/edgelesssys/constellation/cli/gcp/client"
|
|
|
|
"github.com/edgelesssys/constellation/internal/config"
|
2022-04-06 04:36:58 -04:00
|
|
|
"github.com/edgelesssys/constellation/internal/constants"
|
2022-03-22 11:03:15 -04:00
|
|
|
"github.com/edgelesssys/constellation/internal/state"
|
|
|
|
)
|
|
|
|
|
|
|
|
func newTerminateCmd() *cobra.Command {
|
|
|
|
cmd := &cobra.Command{
|
|
|
|
Use: "terminate",
|
|
|
|
Short: "Terminate an existing Constellation.",
|
|
|
|
Long: "Terminate an existing Constellation. The Constellation can't be started again, and all persistent storage will be lost.",
|
|
|
|
Args: cobra.NoArgs,
|
|
|
|
RunE: runTerminate,
|
|
|
|
}
|
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
|
|
|
|
// runTerminate runs the terminate command.
|
|
|
|
func runTerminate(cmd *cobra.Command, args []string) error {
|
|
|
|
fileHandler := file.NewHandler(afero.NewOsFs())
|
|
|
|
devConfigName, err := cmd.Flags().GetString("dev-config")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
config, err := config.FromFile(fileHandler, devConfigName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return terminate(cmd, fileHandler, config)
|
|
|
|
}
|
|
|
|
|
|
|
|
func terminate(cmd *cobra.Command, fileHandler file.Handler, config *config.Config) error {
|
|
|
|
var stat state.ConstellationState
|
2022-04-06 04:36:58 -04:00
|
|
|
if err := fileHandler.ReadJSON(constants.StateFilename, &stat); err != nil {
|
2022-03-22 11:03:15 -04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-05 03:11:45 -04:00
|
|
|
cmd.Println("Terminating ...")
|
|
|
|
|
2022-03-22 11:03:15 -04:00
|
|
|
if len(stat.EC2Instances) != 0 || stat.EC2SecurityGroup != "" {
|
|
|
|
ec2client, err := ec2.NewFromDefault(cmd.Context())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := terminateEC2(cmd, ec2client, stat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: improve check, also look for other resources that might need to be terminated
|
|
|
|
if len(stat.GCPNodes) != 0 {
|
|
|
|
gcpclient, err := gcp.NewFromDefault(cmd.Context())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := terminateGCP(cmd, gcpclient, stat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(stat.AzureResourceGroup) != 0 {
|
|
|
|
azureclient, err := azure.NewFromDefault(stat.AzureSubscription, stat.AzureTenant)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := terminateAzure(cmd, azureclient, stat); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.Println("Your Constellation was terminated successfully.")
|
|
|
|
|
2022-03-29 05:38:14 -04:00
|
|
|
var retErr error
|
2022-04-06 04:36:58 -04:00
|
|
|
if err := fileHandler.Remove(constants.StateFilename); err != nil {
|
|
|
|
retErr = multierr.Append(err, fmt.Errorf("failed to remove file '%s', please remove manually", constants.StateFilename))
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-04-06 04:36:58 -04:00
|
|
|
if err := fileHandler.Remove(constants.AdminConfFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
|
|
retErr = multierr.Append(err, fmt.Errorf("failed to remove file '%s', please remove manually", constants.AdminConfFilename))
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
2022-03-29 05:38:14 -04:00
|
|
|
|
2022-04-06 04:36:58 -04:00
|
|
|
if err := fileHandler.Remove(constants.WGQuickConfigFilename); err != nil && !errors.Is(err, fs.ErrNotExist) {
|
|
|
|
retErr = multierr.Append(err, fmt.Errorf("failed to remove file '%s', please remove manually", constants.WGQuickConfigFilename))
|
2022-03-29 05:38:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return retErr
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func terminateAzure(cmd *cobra.Command, cl azureclient, stat state.ConstellationState) error {
|
|
|
|
if err := cl.SetState(stat); err != nil {
|
|
|
|
return fmt.Errorf("failed to terminate the Constellation: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := cl.TerminateServicePrincipal(cmd.Context()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return cl.TerminateResourceGroup(cmd.Context())
|
|
|
|
}
|
|
|
|
|
|
|
|
func terminateGCP(cmd *cobra.Command, cl gcpclient, stat state.ConstellationState) error {
|
|
|
|
if err := cl.SetState(stat); err != nil {
|
|
|
|
return fmt.Errorf("failed to terminate the Constellation: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := cl.TerminateInstances(cmd.Context()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := cl.TerminateFirewall(cmd.Context()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := cl.TerminateVPCs(cmd.Context()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return cl.TerminateServiceAccount(cmd.Context())
|
|
|
|
}
|
|
|
|
|
|
|
|
// terminateEC2 and remove the existing Constellation form the state file.
|
|
|
|
func terminateEC2(cmd *cobra.Command, cl ec2client, stat state.ConstellationState) error {
|
|
|
|
if err := cl.SetState(stat); err != nil {
|
|
|
|
return fmt.Errorf("failed to terminate the Constellation: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := cl.TerminateInstances(cmd.Context()); err != nil {
|
|
|
|
return fmt.Errorf("failed to terminate the Constellation: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return cl.DeleteSecurityGroup(cmd.Context())
|
|
|
|
}
|