destroy.go
127 lines1
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package commands
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"strings"
)
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 := loadInfraConfig(".")
if err != nil {
log.Fatalf("load infra.json: %v", err)
}
// Find the instance.
var target *Instance
var serverType string
var instanceIdx int
for st, instances := range cfg.Instances {
found := false
for i := range instances {
if instances[i].Name == name {
target = &instances[i]
serverType = st
instanceIdx = i
found = true
break
}
}
if found {
break
}
}
if target == nil {
var names []string
for _, instances := range cfg.Instances {
for _, inst := range instances {
names = append(names, inst.Name)
}
}
if len(names) == 0 {
log.Fatal("No instances deployed.")
}
fmt.Fprintf(os.Stderr, "Instance %q not found. Available instances:\n", name)
for _, n := range names {
fmt.Fprintf(os.Stderr, " %s\n", n)
}
os.Exit(1)
}
// Confirmation.
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
}
}
p, err := initProvider(cfg.Platform)
if err != nil {
log.Fatal(err)
}
// Stop containers on the server before deleting.
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")
}
// Delete from cloud provider.
if target.ID != "" {
fmt.Printf("Deleting server from %s...\n", cfg.Platform.Provider)
if err := p.DeleteServer(target.ID); err != nil {
log.Fatalf("delete server: %v", err)
}
}
// Remove from infra.json.
instances := cfg.Instances[serverType]
cfg.Instances[serverType] = append(instances[:instanceIdx], instances[instanceIdx+1:]...)
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)
}