summaryrefslogtreecommitdiffstats
path: root/cmd/deploy/manage.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/deploy/manage.go')
-rw-r--r--cmd/deploy/manage.go306
1 files changed, 0 insertions, 306 deletions
diff --git a/cmd/deploy/manage.go b/cmd/deploy/manage.go
deleted file mode 100644
index 1f52b92..0000000
--- a/cmd/deploy/manage.go
+++ /dev/null
@@ -1,306 +0,0 @@
1package main
2
3import (
4 "flag"
5 "fmt"
6 "os"
7
8 "github.com/bdw/deploy/internal/ssh"
9 "github.com/bdw/deploy/internal/state"
10)
11
12func runRemove(args []string) {
13 fs := flag.NewFlagSet("remove", flag.ExitOnError)
14 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
15 fs.Parse(args)
16
17 if len(fs.Args()) == 0 {
18 fmt.Fprintf(os.Stderr, "Error: app name is required\n")
19 fmt.Fprintf(os.Stderr, "Usage: deploy remove <app-name> --host user@vps-ip\n")
20 os.Exit(1)
21 }
22
23 name := fs.Args()[0]
24
25 // Load state
26 st, err := state.Load()
27 if err != nil {
28 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
29 os.Exit(1)
30 }
31
32 // Get host from flag or state default
33 if *host == "" {
34 *host = st.GetDefaultHost()
35 }
36
37 if *host == "" {
38 fmt.Fprintf(os.Stderr, "Error: --host is required\n")
39 fs.Usage()
40 os.Exit(1)
41 }
42
43 // Get app info
44 app, err := st.GetApp(*host, name)
45 if err != nil {
46 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
47 os.Exit(1)
48 }
49
50 fmt.Printf("Removing deployment: %s\n", name)
51
52 // Connect to VPS
53 client, err := ssh.Connect(*host)
54 if err != nil {
55 fmt.Fprintf(os.Stderr, "Error connecting to VPS: %v\n", err)
56 os.Exit(1)
57 }
58 defer client.Close()
59
60 if app.Type == "app" {
61 // Stop and disable service
62 fmt.Println("→ Stopping service...")
63 client.RunSudo(fmt.Sprintf("systemctl stop %s", name))
64 client.RunSudo(fmt.Sprintf("systemctl disable %s", name))
65
66 // Remove systemd unit
67 client.RunSudo(fmt.Sprintf("rm -f /etc/systemd/system/%s.service", name))
68 client.RunSudo("systemctl daemon-reload")
69
70 // Remove binary
71 client.RunSudo(fmt.Sprintf("rm -f /usr/local/bin/%s", name))
72
73 // Remove working directory
74 client.RunSudo(fmt.Sprintf("rm -rf /var/lib/%s", name))
75
76 // Remove env file
77 client.RunSudo(fmt.Sprintf("rm -f /etc/deploy/env/%s.env", name))
78
79 // Remove user
80 client.RunSudo(fmt.Sprintf("userdel %s", name))
81 } else {
82 // Remove static site files
83 fmt.Println("→ Removing files...")
84 client.RunSudo(fmt.Sprintf("rm -rf /var/www/%s", name))
85 }
86
87 // Remove Caddy config
88 fmt.Println("→ Removing Caddy config...")
89 client.RunSudo(fmt.Sprintf("rm -f /etc/caddy/sites-enabled/%s.caddy", name))
90
91 // Reload Caddy
92 fmt.Println("→ Reloading Caddy...")
93 if _, err := client.RunSudo("systemctl reload caddy"); err != nil {
94 fmt.Fprintf(os.Stderr, "Warning: Error reloading Caddy: %v\n", err)
95 }
96
97 // Update state
98 if err := st.RemoveApp(*host, name); err != nil {
99 fmt.Fprintf(os.Stderr, "Error updating state: %v\n", err)
100 os.Exit(1)
101 }
102 if err := st.Save(); err != nil {
103 fmt.Fprintf(os.Stderr, "Error saving state: %v\n", err)
104 os.Exit(1)
105 }
106
107 fmt.Printf("✓ Deployment removed successfully\n")
108}
109
110func runLogs(args []string) {
111 fs := flag.NewFlagSet("logs", flag.ExitOnError)
112 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
113 follow := fs.Bool("f", false, "Follow logs")
114 lines := fs.Int("n", 50, "Number of lines to show")
115 fs.Parse(args)
116
117 if len(fs.Args()) == 0 {
118 fmt.Fprintf(os.Stderr, "Error: app name is required\n")
119 fmt.Fprintf(os.Stderr, "Usage: deploy logs <app-name> --host user@vps-ip\n")
120 os.Exit(1)
121 }
122
123 name := fs.Args()[0]
124
125 // Load state
126 st, err := state.Load()
127 if err != nil {
128 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
129 os.Exit(1)
130 }
131
132 // Get host from flag or state default
133 if *host == "" {
134 *host = st.GetDefaultHost()
135 }
136
137 if *host == "" {
138 fmt.Fprintf(os.Stderr, "Error: --host is required\n")
139 fs.Usage()
140 os.Exit(1)
141 }
142
143 app, err := st.GetApp(*host, name)
144 if err != nil {
145 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
146 os.Exit(1)
147 }
148
149 if app.Type != "app" {
150 fmt.Fprintf(os.Stderr, "Error: logs are only available for apps, not static sites\n")
151 os.Exit(1)
152 }
153
154 // Connect to VPS
155 client, err := ssh.Connect(*host)
156 if err != nil {
157 fmt.Fprintf(os.Stderr, "Error connecting to VPS: %v\n", err)
158 os.Exit(1)
159 }
160 defer client.Close()
161
162 // Build journalctl command
163 cmd := fmt.Sprintf("journalctl -u %s -n %d", name, *lines)
164 if *follow {
165 cmd += " -f"
166 }
167
168 // Run command
169 if *follow {
170 // Stream output for follow mode (no sudo needed for journalctl)
171 if err := client.RunStream(cmd); err != nil {
172 fmt.Fprintf(os.Stderr, "Error fetching logs: %v\n", err)
173 os.Exit(1)
174 }
175 } else {
176 // Buffer output for non-follow mode (no sudo needed for journalctl)
177 output, err := client.Run(cmd)
178 if err != nil {
179 fmt.Fprintf(os.Stderr, "Error fetching logs: %v\n", err)
180 os.Exit(1)
181 }
182 fmt.Print(output)
183 }
184}
185
186func runStatus(args []string) {
187 fs := flag.NewFlagSet("status", flag.ExitOnError)
188 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
189 fs.Parse(args)
190
191 if len(fs.Args()) == 0 {
192 fmt.Fprintf(os.Stderr, "Error: app name is required\n")
193 fmt.Fprintf(os.Stderr, "Usage: deploy status <app-name> --host user@vps-ip\n")
194 os.Exit(1)
195 }
196
197 name := fs.Args()[0]
198
199 // Load state
200 st, err := state.Load()
201 if err != nil {
202 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
203 os.Exit(1)
204 }
205
206 // Get host from flag or state default
207 if *host == "" {
208 *host = st.GetDefaultHost()
209 }
210
211 if *host == "" {
212 fmt.Fprintf(os.Stderr, "Error: --host is required\n")
213 fs.Usage()
214 os.Exit(1)
215 }
216
217 app, err := st.GetApp(*host, name)
218 if err != nil {
219 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
220 os.Exit(1)
221 }
222
223 if app.Type != "app" {
224 fmt.Fprintf(os.Stderr, "Error: status is only available for apps, not static sites\n")
225 os.Exit(1)
226 }
227
228 // Connect to VPS
229 client, err := ssh.Connect(*host)
230 if err != nil {
231 fmt.Fprintf(os.Stderr, "Error connecting to VPS: %v\n", err)
232 os.Exit(1)
233 }
234 defer client.Close()
235
236 // Get status
237 output, err := client.RunSudo(fmt.Sprintf("systemctl status %s", name))
238 if err != nil {
239 // systemctl status returns non-zero for non-active services
240 // but we still want to show the output
241 fmt.Print(output)
242 return
243 }
244
245 fmt.Print(output)
246}
247
248func runRestart(args []string) {
249 fs := flag.NewFlagSet("restart", flag.ExitOnError)
250 host := fs.String("host", "", "VPS host (SSH config alias or user@host)")
251 fs.Parse(args)
252
253 if len(fs.Args()) == 0 {
254 fmt.Fprintf(os.Stderr, "Error: app name is required\n")
255 fmt.Fprintf(os.Stderr, "Usage: deploy restart <app-name> --host user@vps-ip\n")
256 os.Exit(1)
257 }
258
259 name := fs.Args()[0]
260
261 // Load state
262 st, err := state.Load()
263 if err != nil {
264 fmt.Fprintf(os.Stderr, "Error loading state: %v\n", err)
265 os.Exit(1)
266 }
267
268 // Get host from flag or state default
269 if *host == "" {
270 *host = st.GetDefaultHost()
271 }
272
273 if *host == "" {
274 fmt.Fprintf(os.Stderr, "Error: --host is required\n")
275 fs.Usage()
276 os.Exit(1)
277 }
278
279 app, err := st.GetApp(*host, name)
280 if err != nil {
281 fmt.Fprintf(os.Stderr, "Error: %v\n", err)
282 os.Exit(1)
283 }
284
285 if app.Type != "app" {
286 fmt.Fprintf(os.Stderr, "Error: restart is only available for apps, not static sites\n")
287 os.Exit(1)
288 }
289
290 // Connect to VPS
291 client, err := ssh.Connect(*host)
292 if err != nil {
293 fmt.Fprintf(os.Stderr, "Error connecting to VPS: %v\n", err)
294 os.Exit(1)
295 }
296 defer client.Close()
297
298 // Restart service
299 fmt.Printf("Restarting %s...\n", name)
300 if _, err := client.RunSudo(fmt.Sprintf("systemctl restart %s", name)); err != nil {
301 fmt.Fprintf(os.Stderr, "Error restarting service: %v\n", err)
302 os.Exit(1)
303 }
304
305 fmt.Println("✓ Service restarted successfully")
306}