mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-04-20 16:40:29 +00:00
122 lines
2.9 KiB
Go
122 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/UpCloudLtd/upcloud-go-api/v8/upcloud/request"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var teardownCmd = &cobra.Command{
|
|
Use: "teardown",
|
|
Short: "Destroy all infrastructure",
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
token, _ := cmd.Root().PersistentFlags().GetString("token")
|
|
return cmdTeardown(token)
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
rootCmd.AddCommand(teardownCmd)
|
|
}
|
|
|
|
func cmdTeardown(token string) error {
|
|
state, err := loadState()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
naming := state.Naming()
|
|
|
|
// Confirmation prompt
|
|
fmt.Printf("This will DESTROY all %s infrastructure:\n", naming.DisplayName())
|
|
fmt.Printf(" Zone: %s\n", state.Zone)
|
|
fmt.Printf(" Appview: %s (%s)\n", state.Appview.UUID, state.Appview.PublicIP)
|
|
fmt.Printf(" Hold: %s (%s)\n", state.Hold.UUID, state.Hold.PublicIP)
|
|
fmt.Printf(" Network: %s\n", state.Network.UUID)
|
|
fmt.Printf(" LB: %s\n", state.LB.UUID)
|
|
fmt.Println()
|
|
fmt.Print("Type 'yes' to confirm: ")
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
scanner.Scan()
|
|
if strings.TrimSpace(scanner.Text()) != "yes" {
|
|
fmt.Println("Aborted.")
|
|
return nil
|
|
}
|
|
|
|
svc, err := newService(token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
|
defer cancel()
|
|
|
|
// Delete LB first (depends on network)
|
|
if state.LB.UUID != "" {
|
|
fmt.Printf("Deleting load balancer %s...\n", state.LB.UUID)
|
|
if err := svc.DeleteLoadBalancer(ctx, &request.DeleteLoadBalancerRequest{
|
|
UUID: state.LB.UUID,
|
|
}); err != nil {
|
|
fmt.Printf(" Warning: %v\n", err)
|
|
}
|
|
}
|
|
|
|
// Stop and delete servers (must stop before delete, and delete storage)
|
|
for _, s := range []struct {
|
|
name string
|
|
uuid string
|
|
}{
|
|
{"appview", state.Appview.UUID},
|
|
{"hold", state.Hold.UUID},
|
|
} {
|
|
if s.uuid == "" {
|
|
continue
|
|
}
|
|
fmt.Printf("Stopping server %s (%s)...\n", s.name, s.uuid)
|
|
_, err := svc.StopServer(ctx, &request.StopServerRequest{
|
|
UUID: s.uuid,
|
|
})
|
|
if err != nil {
|
|
fmt.Printf(" Warning (stop): %v\n", err)
|
|
} else {
|
|
_, _ = svc.WaitForServerState(ctx, &request.WaitForServerStateRequest{
|
|
UUID: s.uuid,
|
|
DesiredState: "stopped",
|
|
})
|
|
}
|
|
|
|
fmt.Printf("Deleting server %s...\n", s.name)
|
|
if err := svc.DeleteServerAndStorages(ctx, &request.DeleteServerAndStoragesRequest{
|
|
UUID: s.uuid,
|
|
}); err != nil {
|
|
fmt.Printf(" Warning (delete): %v\n", err)
|
|
}
|
|
}
|
|
|
|
// Delete network (after servers are gone)
|
|
if state.Network.UUID != "" {
|
|
fmt.Printf("Deleting network %s...\n", state.Network.UUID)
|
|
if err := svc.DeleteNetwork(ctx, &request.DeleteNetworkRequest{
|
|
UUID: state.Network.UUID,
|
|
}); err != nil {
|
|
fmt.Printf(" Warning: %v\n", err)
|
|
}
|
|
}
|
|
|
|
// Remove state file
|
|
if err := deleteState(); err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("\nTeardown complete. All infrastructure destroyed.")
|
|
return nil
|
|
}
|