quicklify 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -5
- package/README.tr.md +42 -5
- package/SECURITY.md +42 -9
- package/bin/quicklify-mcp +5 -0
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +2 -4
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +44 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/logs.d.ts +3 -2
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +6 -11
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/monitor.d.ts +3 -9
- package/dist/commands/monitor.d.ts.map +1 -1
- package/dist/commands/monitor.js +2 -47
- package/dist/commands/monitor.js.map +1 -1
- package/dist/commands/ssh.d.ts.map +1 -1
- package/dist/commands/ssh.js +4 -1
- package/dist/commands/ssh.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +25 -74
- package/dist/commands/status.js.map +1 -1
- package/dist/core/backup.d.ts +43 -0
- package/dist/core/backup.d.ts.map +1 -0
- package/dist/core/backup.js +259 -0
- package/dist/core/backup.js.map +1 -0
- package/dist/core/domain.d.ts +30 -0
- package/dist/core/domain.d.ts.map +1 -0
- package/dist/core/domain.js +174 -0
- package/dist/core/domain.js.map +1 -0
- package/dist/core/firewall.d.ts +25 -0
- package/dist/core/firewall.d.ts.map +1 -0
- package/dist/core/firewall.js +146 -0
- package/dist/core/firewall.js.map +1 -0
- package/dist/core/logs.d.ts +28 -0
- package/dist/core/logs.d.ts.map +1 -0
- package/dist/core/logs.js +129 -0
- package/dist/core/logs.js.map +1 -0
- package/dist/core/maintain.d.ts +41 -0
- package/dist/core/maintain.d.ts.map +1 -0
- package/dist/core/maintain.js +180 -0
- package/dist/core/maintain.js.map +1 -0
- package/dist/core/manage.d.ts +34 -0
- package/dist/core/manage.d.ts.map +1 -0
- package/dist/core/manage.js +203 -0
- package/dist/core/manage.js.map +1 -0
- package/dist/core/provision.d.ts +18 -0
- package/dist/core/provision.d.ts.map +1 -0
- package/dist/core/provision.js +197 -0
- package/dist/core/provision.js.map +1 -0
- package/dist/core/secure.d.ts +29 -0
- package/dist/core/secure.d.ts.map +1 -0
- package/dist/core/secure.js +198 -0
- package/dist/core/secure.js.map +1 -0
- package/dist/core/snapshot.d.ts +22 -0
- package/dist/core/snapshot.d.ts.map +1 -0
- package/dist/core/snapshot.js +58 -0
- package/dist/core/snapshot.js.map +1 -0
- package/dist/core/status.d.ts +12 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +43 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/tokens.d.ts +4 -0
- package/dist/core/tokens.d.ts.map +1 -0
- package/dist/core/tokens.js +23 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +16 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +105 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/serverBackup.d.ts +29 -0
- package/dist/mcp/tools/serverBackup.d.ts.map +1 -0
- package/dist/mcp/tools/serverBackup.js +376 -0
- package/dist/mcp/tools/serverBackup.js.map +1 -0
- package/dist/mcp/tools/serverInfo.d.ts +20 -0
- package/dist/mcp/tools/serverInfo.d.ts.map +1 -0
- package/dist/mcp/tools/serverInfo.js +219 -0
- package/dist/mcp/tools/serverInfo.js.map +1 -0
- package/dist/mcp/tools/serverLogs.d.ts +30 -0
- package/dist/mcp/tools/serverLogs.d.ts.map +1 -0
- package/dist/mcp/tools/serverLogs.js +145 -0
- package/dist/mcp/tools/serverLogs.js.map +1 -0
- package/dist/mcp/tools/serverMaintain.d.ts +22 -0
- package/dist/mcp/tools/serverMaintain.d.ts.map +1 -0
- package/dist/mcp/tools/serverMaintain.js +217 -0
- package/dist/mcp/tools/serverMaintain.js.map +1 -0
- package/dist/mcp/tools/serverManage.d.ts +33 -0
- package/dist/mcp/tools/serverManage.d.ts.map +1 -0
- package/dist/mcp/tools/serverManage.js +207 -0
- package/dist/mcp/tools/serverManage.js.map +1 -0
- package/dist/mcp/tools/serverProvision.d.ts +31 -0
- package/dist/mcp/tools/serverProvision.d.ts.map +1 -0
- package/dist/mcp/tools/serverProvision.js +125 -0
- package/dist/mcp/tools/serverProvision.js.map +1 -0
- package/dist/mcp/tools/serverSecure.d.ts +40 -0
- package/dist/mcp/tools/serverSecure.d.ts.map +1 -0
- package/dist/mcp/tools/serverSecure.js +396 -0
- package/dist/mcp/tools/serverSecure.js.map +1 -0
- package/dist/providers/vultr.d.ts.map +1 -1
- package/dist/providers/vultr.js +7 -1
- package/dist/providers/vultr.js.map +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/errorMapper.d.ts +1 -0
- package/dist/utils/errorMapper.d.ts.map +1 -1
- package/dist/utils/errorMapper.js +20 -0
- package/dist/utils/errorMapper.js.map +1 -1
- package/dist/utils/openBrowser.d.ts.map +1 -1
- package/dist/utils/openBrowser.js +6 -1
- package/dist/utils/openBrowser.js.map +1 -1
- package/dist/utils/ssh.d.ts +1 -0
- package/dist/utils/ssh.d.ts.map +1 -1
- package/dist/utils/ssh.js +6 -2
- package/dist/utils/ssh.js.map +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { sshExec, assertValidIp } from "../utils/ssh.js";
|
|
2
|
+
import { createProviderWithToken } from "../utils/providerFactory.js";
|
|
3
|
+
import { checkCoolifyHealth, getCloudServerStatus } from "./status.js";
|
|
4
|
+
import { getErrorMessage, mapSshError, mapProviderError } from "../utils/errorMapper.js";
|
|
5
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
6
|
+
const COOLIFY_UPDATE_CMD = "curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash";
|
|
7
|
+
// ─── Core Functions ──────────────────────────────────────────────────────────
|
|
8
|
+
export async function executeCoolifyUpdate(ip) {
|
|
9
|
+
assertValidIp(ip);
|
|
10
|
+
try {
|
|
11
|
+
const result = await sshExec(ip, COOLIFY_UPDATE_CMD);
|
|
12
|
+
if (result.code === 0) {
|
|
13
|
+
return { success: true, output: result.stdout || undefined };
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
success: false,
|
|
17
|
+
error: `Update failed (exit code ${result.code})`,
|
|
18
|
+
output: result.stderr || result.stdout || undefined,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const hint = mapSshError(error, ip);
|
|
23
|
+
return {
|
|
24
|
+
success: false,
|
|
25
|
+
error: getErrorMessage(error),
|
|
26
|
+
...(hint ? { hint } : {}),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function pollCoolifyHealth(ip, maxAttempts, intervalMs) {
|
|
31
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
32
|
+
const status = await checkCoolifyHealth(ip);
|
|
33
|
+
if (status === "running")
|
|
34
|
+
return true;
|
|
35
|
+
if (attempt < maxAttempts - 1) {
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
export async function rebootAndWait(server, apiToken, maxAttempts = 30, intervalMs = 2000, initialWaitMs = 10000) {
|
|
42
|
+
if (server.id.startsWith("manual-")) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
error: `Cannot reboot manually added server via API. Use SSH: ssh root@${server.ip} reboot`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const provider = createProviderWithToken(server.provider, apiToken);
|
|
50
|
+
await provider.rebootServer(server.id);
|
|
51
|
+
// Wait for reboot to initiate
|
|
52
|
+
await new Promise((resolve) => setTimeout(resolve, initialWaitMs));
|
|
53
|
+
// Poll until running
|
|
54
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
55
|
+
try {
|
|
56
|
+
const status = await provider.getServerStatus(server.id);
|
|
57
|
+
if (status === "running") {
|
|
58
|
+
return { success: true, finalStatus: "running" };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Server may be temporarily unreachable during reboot
|
|
63
|
+
}
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
finalStatus: "timeout",
|
|
69
|
+
error: "Server did not come back online in time",
|
|
70
|
+
hint: "The server may still be rebooting. Check status later.",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const hint = mapProviderError(error, server.provider);
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: getErrorMessage(error),
|
|
78
|
+
...(hint ? { hint } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export async function maintainServer(server, apiToken, options = {}) {
|
|
83
|
+
const isManual = server.id.startsWith("manual-");
|
|
84
|
+
const healthAttempts = options.healthPollAttempts ?? 12;
|
|
85
|
+
const healthInterval = options.healthPollIntervalMs ?? 5000;
|
|
86
|
+
const rebootAttempts = options.rebootMaxAttempts ?? 30;
|
|
87
|
+
const rebootInterval = options.rebootIntervalMs ?? 2000;
|
|
88
|
+
const rebootInitialWait = options.rebootInitialWaitMs ?? 10000;
|
|
89
|
+
const steps = [];
|
|
90
|
+
const result = {
|
|
91
|
+
server: server.name,
|
|
92
|
+
ip: server.ip,
|
|
93
|
+
provider: server.provider,
|
|
94
|
+
steps,
|
|
95
|
+
success: false,
|
|
96
|
+
};
|
|
97
|
+
// Step 1: Status check
|
|
98
|
+
if (isManual) {
|
|
99
|
+
steps.push({ step: 1, name: "Status Check", status: "skipped", detail: "Manual server — assuming running" });
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
try {
|
|
103
|
+
const serverStatus = await getCloudServerStatus(server, apiToken);
|
|
104
|
+
if (serverStatus !== "running") {
|
|
105
|
+
steps.push({ step: 1, name: "Status Check", status: "failure", detail: `Server is ${serverStatus}` });
|
|
106
|
+
steps.push({ step: 2, name: "Coolify Update", status: "skipped" });
|
|
107
|
+
steps.push({ step: 3, name: "Health Check", status: "skipped" });
|
|
108
|
+
steps.push({ step: 4, name: "Reboot", status: "skipped" });
|
|
109
|
+
steps.push({ step: 5, name: "Final Check", status: "skipped" });
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
steps.push({ step: 1, name: "Status Check", status: "success", detail: "Server is running" });
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const hint = mapProviderError(error, server.provider);
|
|
116
|
+
steps.push({
|
|
117
|
+
step: 1, name: "Status Check", status: "failure",
|
|
118
|
+
error: getErrorMessage(error), ...(hint ? { hint } : {}),
|
|
119
|
+
});
|
|
120
|
+
steps.push({ step: 2, name: "Coolify Update", status: "skipped" });
|
|
121
|
+
steps.push({ step: 3, name: "Health Check", status: "skipped" });
|
|
122
|
+
steps.push({ step: 4, name: "Reboot", status: "skipped" });
|
|
123
|
+
steps.push({ step: 5, name: "Final Check", status: "skipped" });
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Step 2: Coolify update
|
|
128
|
+
const updateResult = await executeCoolifyUpdate(server.ip);
|
|
129
|
+
if (!updateResult.success) {
|
|
130
|
+
steps.push({
|
|
131
|
+
step: 2, name: "Coolify Update", status: "failure",
|
|
132
|
+
error: updateResult.error, ...(updateResult.hint ? { hint: updateResult.hint } : {}),
|
|
133
|
+
});
|
|
134
|
+
steps.push({ step: 3, name: "Health Check", status: "skipped" });
|
|
135
|
+
steps.push({ step: 4, name: "Reboot", status: "skipped" });
|
|
136
|
+
steps.push({ step: 5, name: "Final Check", status: "skipped" });
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
steps.push({ step: 2, name: "Coolify Update", status: "success" });
|
|
140
|
+
// Step 3: Health check after update
|
|
141
|
+
const healthOk = await pollCoolifyHealth(server.ip, healthAttempts, healthInterval);
|
|
142
|
+
if (!healthOk) {
|
|
143
|
+
steps.push({ step: 3, name: "Health Check", status: "failure", detail: "Coolify did not respond after update" });
|
|
144
|
+
// Continue — partial success
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
steps.push({ step: 3, name: "Health Check", status: "success", detail: "Coolify is healthy" });
|
|
148
|
+
}
|
|
149
|
+
// Steps 4 & 5: Reboot + Final check (skip both if skipReboot or manual)
|
|
150
|
+
if (options.skipReboot || isManual) {
|
|
151
|
+
const reason = isManual ? "Manual server — no API reboot" : "Skipped by user";
|
|
152
|
+
steps.push({ step: 4, name: "Reboot", status: "skipped", detail: reason });
|
|
153
|
+
steps.push({ step: 5, name: "Final Check", status: "skipped", detail: reason });
|
|
154
|
+
result.success = steps.every((s) => s.status !== "failure");
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
// Step 4: Reboot
|
|
158
|
+
const rebootResult = await rebootAndWait(server, apiToken, rebootAttempts, rebootInterval, rebootInitialWait);
|
|
159
|
+
if (!rebootResult.success) {
|
|
160
|
+
steps.push({
|
|
161
|
+
step: 4, name: "Reboot", status: "failure",
|
|
162
|
+
error: rebootResult.error, ...(rebootResult.hint ? { hint: rebootResult.hint } : {}),
|
|
163
|
+
});
|
|
164
|
+
steps.push({ step: 5, name: "Final Check", status: "skipped" });
|
|
165
|
+
result.success = false;
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
steps.push({ step: 4, name: "Reboot", status: "success", detail: "Server rebooted" });
|
|
169
|
+
// Step 5: Final health check after reboot
|
|
170
|
+
const finalHealthOk = await pollCoolifyHealth(server.ip, healthAttempts, healthInterval);
|
|
171
|
+
if (finalHealthOk) {
|
|
172
|
+
steps.push({ step: 5, name: "Final Check", status: "success", detail: "Server and Coolify are running" });
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
steps.push({ step: 5, name: "Final Check", status: "failure", detail: "Server running but Coolify did not respond" });
|
|
176
|
+
}
|
|
177
|
+
result.success = steps.every((s) => s.status !== "failure");
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=maintain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintain.js","sourceRoot":"","sources":["../../src/core/maintain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ServerRecord } from "../types/index.js";
|
|
2
|
+
export declare function isSafeMode(): boolean;
|
|
3
|
+
export declare function isValidProvider(provider: string): boolean;
|
|
4
|
+
export declare function validateIpAddress(ip: string): string | null;
|
|
5
|
+
export declare function validateServerName(name: string): string | null;
|
|
6
|
+
export interface AddServerParams {
|
|
7
|
+
provider: string;
|
|
8
|
+
ip: string;
|
|
9
|
+
name: string;
|
|
10
|
+
skipVerify?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface AddServerResult {
|
|
13
|
+
success: boolean;
|
|
14
|
+
server?: ServerRecord;
|
|
15
|
+
coolifyStatus?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function addServerRecord(params: AddServerParams): Promise<AddServerResult>;
|
|
19
|
+
export interface RemoveServerResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
server?: ServerRecord;
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function removeServerRecord(query: string): RemoveServerResult;
|
|
25
|
+
export interface DestroyServerResult {
|
|
26
|
+
success: boolean;
|
|
27
|
+
server?: ServerRecord;
|
|
28
|
+
cloudDeleted: boolean;
|
|
29
|
+
localRemoved: boolean;
|
|
30
|
+
error?: string;
|
|
31
|
+
hint?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function destroyCloudServer(query: string): Promise<DestroyServerResult>;
|
|
34
|
+
//# sourceMappingURL=manage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../src/core/manage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAMD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa3D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS9D;AAID,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAmGvF;AAID,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAYpE;AAID,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAiEpF"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { getServers, saveServer, removeServer, findServer } from "../utils/config.js";
|
|
2
|
+
import { createProviderWithToken } from "../utils/providerFactory.js";
|
|
3
|
+
import { sshExec, checkSshAvailable } from "../utils/ssh.js";
|
|
4
|
+
import { getErrorMessage, mapProviderError } from "../utils/errorMapper.js";
|
|
5
|
+
import { getProviderToken } from "./tokens.js";
|
|
6
|
+
// ─── SAFE_MODE ────────────────────────────────────────────────────────────────
|
|
7
|
+
export function isSafeMode() {
|
|
8
|
+
return process.env.QUICKLIFY_SAFE_MODE === "true";
|
|
9
|
+
}
|
|
10
|
+
// ─── Validation ───────────────────────────────────────────────────────────────
|
|
11
|
+
const VALID_PROVIDERS = ["hetzner", "digitalocean", "vultr", "linode"];
|
|
12
|
+
export function isValidProvider(provider) {
|
|
13
|
+
return VALID_PROVIDERS.includes(provider);
|
|
14
|
+
}
|
|
15
|
+
export function validateIpAddress(ip) {
|
|
16
|
+
if (!ip)
|
|
17
|
+
return "IP address is required";
|
|
18
|
+
if (!/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(ip)) {
|
|
19
|
+
return "Invalid IP address format";
|
|
20
|
+
}
|
|
21
|
+
const octets = ip.split(".").map(Number);
|
|
22
|
+
if (octets.some((o) => o < 0 || o > 255)) {
|
|
23
|
+
return "Invalid IP address (octets must be 0-255)";
|
|
24
|
+
}
|
|
25
|
+
if (ip === "0.0.0.0" || ip.startsWith("127.")) {
|
|
26
|
+
return "Reserved IP address not allowed";
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
export function validateServerName(name) {
|
|
31
|
+
if (!name)
|
|
32
|
+
return "Server name is required";
|
|
33
|
+
if (name.length < 3 || name.length > 63) {
|
|
34
|
+
return "Server name must be 3-63 characters";
|
|
35
|
+
}
|
|
36
|
+
if (!/^[a-z][a-z0-9-]*[a-z0-9]$/.test(name)) {
|
|
37
|
+
return "Must start with a letter, end with letter/number, only lowercase letters, numbers, hyphens";
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
export async function addServerRecord(params) {
|
|
42
|
+
// Validate provider
|
|
43
|
+
if (!isValidProvider(params.provider)) {
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
error: `Invalid provider: ${params.provider}. Valid: ${VALID_PROVIDERS.join(", ")}`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Get token from env
|
|
50
|
+
const token = getProviderToken(params.provider);
|
|
51
|
+
if (!token) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
error: `No API token found for provider: ${params.provider}. Set ${params.provider.toUpperCase()}_TOKEN environment variable`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Validate IP
|
|
58
|
+
const ipError = validateIpAddress(params.ip);
|
|
59
|
+
if (ipError) {
|
|
60
|
+
return { success: false, error: ipError };
|
|
61
|
+
}
|
|
62
|
+
// Check duplicate
|
|
63
|
+
const existing = getServers();
|
|
64
|
+
const duplicate = existing.find((s) => s.ip === params.ip);
|
|
65
|
+
if (duplicate) {
|
|
66
|
+
return {
|
|
67
|
+
success: false,
|
|
68
|
+
error: `Server with IP ${params.ip} already exists: ${duplicate.name}`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Validate name
|
|
72
|
+
const nameError = validateServerName(params.name);
|
|
73
|
+
if (nameError) {
|
|
74
|
+
return { success: false, error: nameError };
|
|
75
|
+
}
|
|
76
|
+
// Validate API token
|
|
77
|
+
try {
|
|
78
|
+
const provider = createProviderWithToken(params.provider, token);
|
|
79
|
+
const valid = await provider.validateToken(token);
|
|
80
|
+
if (!valid) {
|
|
81
|
+
return { success: false, error: `Invalid API token for ${params.provider}` };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: `Token validation failed: ${getErrorMessage(error)}`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
// Optional Coolify verification via SSH
|
|
91
|
+
let coolifyStatus = "skipped";
|
|
92
|
+
if (!params.skipVerify) {
|
|
93
|
+
if (!checkSshAvailable()) {
|
|
94
|
+
coolifyStatus = "ssh_unavailable";
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
try {
|
|
98
|
+
const result = await sshExec(params.ip, "curl -s -o /dev/null -w '%{http_code}' http://localhost:8000/api/health");
|
|
99
|
+
if (result.code === 0 && result.stdout.trim().includes("200")) {
|
|
100
|
+
coolifyStatus = "running";
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const dockerResult = await sshExec(params.ip, "docker ps --format '{{.Names}}' 2>/dev/null | grep -q coolify && echo OK");
|
|
104
|
+
if (dockerResult.code === 0 && dockerResult.stdout.trim().includes("OK")) {
|
|
105
|
+
coolifyStatus = "containers_detected";
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
coolifyStatus = "not_detected";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
process.stderr.write(`[warn] Coolify verification failed: ${getErrorMessage(error)}\n`);
|
|
114
|
+
coolifyStatus = "verification_failed";
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Save to config
|
|
119
|
+
const record = {
|
|
120
|
+
id: `manual-${Date.now()}`,
|
|
121
|
+
name: params.name,
|
|
122
|
+
provider: params.provider,
|
|
123
|
+
ip: params.ip,
|
|
124
|
+
region: "unknown",
|
|
125
|
+
size: "unknown",
|
|
126
|
+
createdAt: new Date().toISOString(),
|
|
127
|
+
};
|
|
128
|
+
saveServer(record);
|
|
129
|
+
return { success: true, server: record, coolifyStatus };
|
|
130
|
+
}
|
|
131
|
+
export function removeServerRecord(query) {
|
|
132
|
+
const server = findServer(query);
|
|
133
|
+
if (!server) {
|
|
134
|
+
return { success: false, error: `Server not found: ${query}` };
|
|
135
|
+
}
|
|
136
|
+
const removed = removeServer(server.id);
|
|
137
|
+
if (!removed) {
|
|
138
|
+
return { success: false, error: `Failed to remove server: ${server.name}` };
|
|
139
|
+
}
|
|
140
|
+
return { success: true, server };
|
|
141
|
+
}
|
|
142
|
+
export async function destroyCloudServer(query) {
|
|
143
|
+
const server = findServer(query);
|
|
144
|
+
if (!server) {
|
|
145
|
+
return {
|
|
146
|
+
success: false,
|
|
147
|
+
cloudDeleted: false,
|
|
148
|
+
localRemoved: false,
|
|
149
|
+
error: `Server not found: ${query}`,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
// Manual servers can only be removed, not destroyed
|
|
153
|
+
if (server.id.startsWith("manual-")) {
|
|
154
|
+
return {
|
|
155
|
+
success: false,
|
|
156
|
+
server,
|
|
157
|
+
cloudDeleted: false,
|
|
158
|
+
localRemoved: false,
|
|
159
|
+
error: `Server "${server.name}" was manually added (no cloud provider ID). Use 'remove' action instead.`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Get token from env
|
|
163
|
+
const token = getProviderToken(server.provider);
|
|
164
|
+
if (!token) {
|
|
165
|
+
return {
|
|
166
|
+
success: false,
|
|
167
|
+
server,
|
|
168
|
+
cloudDeleted: false,
|
|
169
|
+
localRemoved: false,
|
|
170
|
+
error: `No API token for ${server.provider}. Set ${server.provider.toUpperCase()}_TOKEN environment variable`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const provider = createProviderWithToken(server.provider, token);
|
|
175
|
+
await provider.destroyServer(server.id);
|
|
176
|
+
removeServer(server.id);
|
|
177
|
+
return { success: true, server, cloudDeleted: true, localRemoved: true };
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const message = getErrorMessage(error);
|
|
181
|
+
const isNotFound = message.toLowerCase().includes("not found") || message.toLowerCase().includes("not_found");
|
|
182
|
+
if (isNotFound) {
|
|
183
|
+
removeServer(server.id);
|
|
184
|
+
return {
|
|
185
|
+
success: true,
|
|
186
|
+
server,
|
|
187
|
+
cloudDeleted: false,
|
|
188
|
+
localRemoved: true,
|
|
189
|
+
hint: `Server not found on ${server.provider} (may have been deleted manually). Removed from local config.`,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const hint = mapProviderError(error, server.provider);
|
|
193
|
+
return {
|
|
194
|
+
success: false,
|
|
195
|
+
server,
|
|
196
|
+
cloudDeleted: false,
|
|
197
|
+
localRemoved: false,
|
|
198
|
+
error: message,
|
|
199
|
+
...(hint ? { hint } : {}),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=manage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.js","sourceRoot":"","sources":["../../src/core/manage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CloudProvider } from "../providers/base.js";
|
|
2
|
+
import type { ServerRecord } from "../types/index.js";
|
|
3
|
+
export interface ProvisionConfig {
|
|
4
|
+
provider: string;
|
|
5
|
+
region?: string;
|
|
6
|
+
size?: string;
|
|
7
|
+
name: string;
|
|
8
|
+
template?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ProvisionResult {
|
|
11
|
+
success: boolean;
|
|
12
|
+
server?: ServerRecord;
|
|
13
|
+
error?: string;
|
|
14
|
+
hint?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function uploadSshKeyBestEffort(provider: CloudProvider): Promise<string[]>;
|
|
17
|
+
export declare function provisionServer(config: ProvisionConfig): Promise<ProvisionResult>;
|
|
18
|
+
//# sourceMappingURL=provision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../../src/core/provision.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAyBD,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBvF;AAID,wBAAsB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA0JvF"}
|