destroy.go

101 lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
package commands

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strings"

	"congo.gg/cmd/internal"
)

const destroyUsage = `Remove a deployed server instance

Usage:
  congo destroy <name> [flags]

Flags:
  --force    Skip confirmation prompt

Stops all services, deletes the server from the cloud provider,
and removes the instance from infra.json.

Examples:
  congo destroy web-1           # with confirmation
  congo destroy web-1 --force   # skip confirmation
`

func Destroy() {
	fs := flag.NewFlagSet("destroy", flag.ExitOnError)
	fs.Usage = func() { fmt.Print(destroyUsage) }

	force := fs.Bool("force", false, "Skip confirmation prompt")
	fs.Parse(os.Args[2:])

	name := fs.Arg(0)
	if name == "" {
		fs.Usage()
		os.Exit(1)
	}

	cfg, err := scaffold.LoadInfraConfig(".")
	if err != nil {
		log.Fatalf("load infra.json: %v", err)
	}

	target, serverType, err := scaffold.FindInstance(cfg, name)
	if err != nil {
		log.Fatal(err)
	}

	if !*force {
		fmt.Printf("This will permanently delete %s (%s).\n", target.Name, target.IP)
		fmt.Print("Type the instance name to confirm: ")

		scanner := bufio.NewScanner(os.Stdin)
		scanner.Scan()
		if strings.TrimSpace(scanner.Text()) != name {
			fmt.Println("Aborted.")
			return
		}
	}

	providers, err := scaffold.InitProviders(cfg)
	if err != nil {
		log.Fatal(err)
	}
	p := scaffold.ProviderFor(providers, cfg, serverType)

	if target.IP != "" {
		server := target.ToServer()
		fmt.Printf("Stopping services on %s...\n", target.Name)
		server.SSH("bash", "-c", "docker stop $(docker ps -q) 2>/dev/null")
	}

	if target.ID != "" {
		pc := cfg.PlatformFor(serverType)
		fmt.Printf("Deleting server from %s...\n", pc.Provider)
		if err := p.DeleteServer(target.ID); err != nil {
			log.Fatalf("delete server: %v", err)
		}
	}

	// Remove from infra.json.
	instances := cfg.Instances[serverType]
	for i := range instances {
		if instances[i].Name == name {
			cfg.Instances[serverType] = append(instances[:i], instances[i+1:]...)
			break
		}
	}
	if len(cfg.Instances[serverType]) == 0 {
		delete(cfg.Instances, serverType)
	}
	if err := cfg.Save("."); err != nil {
		log.Fatalf("save infra.json: %v", err)
	}

	fmt.Printf("Destroyed %s.\n", name)
}