genbox 1.0.34 → 1.0.35
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/dist/commands/status.js +107 -39
- package/package.json +1 -1
package/dist/commands/status.js
CHANGED
|
@@ -187,56 +187,124 @@ exports.statusCommand = new commander_1.Command('status')
|
|
|
187
187
|
console.error(chalk_1.default.red(error.message));
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
console.log(chalk_1.default.blue(`[INFO] Checking
|
|
190
|
+
console.log(chalk_1.default.blue(`[INFO] Checking status of ${selectedName}...`));
|
|
191
191
|
console.log('');
|
|
192
|
-
// 3. Check
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
'
|
|
201
|
-
|
|
202
|
-
'
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
192
|
+
// 3. Check status from DB first (more reliable than SSH)
|
|
193
|
+
const dbStatus = target.status; // 'provisioning' | 'running' | 'error' etc.
|
|
194
|
+
const setupDuration = target.setupDuration;
|
|
195
|
+
const setupCompletedAt = target.setupCompletedAt;
|
|
196
|
+
// If DB says RUNNING and we have setupCompletedAt, setup is complete
|
|
197
|
+
if (dbStatus === 'running' && setupCompletedAt) {
|
|
198
|
+
const durationStr = setupDuration ? formatDuration(setupDuration) : 'unknown';
|
|
199
|
+
console.log(chalk_1.default.green(`[SUCCESS] Setup completed! (took ${durationStr})`));
|
|
200
|
+
console.log('');
|
|
201
|
+
// Show Docker containers status
|
|
202
|
+
const dockerStatus = sshExec(target.ipAddress, keyPath, 'docker ps --format "{{.Names}}\\t{{.Status}}" 2>/dev/null', 10);
|
|
203
|
+
if (dockerStatus && dockerStatus.trim()) {
|
|
204
|
+
console.log(chalk_1.default.blue('[INFO] === Docker Services ==='));
|
|
205
|
+
console.log('NAMES\tSTATUS');
|
|
206
|
+
console.log(dockerStatus);
|
|
207
|
+
console.log('');
|
|
208
|
+
}
|
|
209
|
+
// Show PM2 processes
|
|
210
|
+
const pm2Status = sshExec(target.ipAddress, keyPath, 'source ~/.nvm/nvm.sh 2>/dev/null; pm2 list 2>/dev/null || echo ""', 10);
|
|
211
|
+
if (pm2Status && pm2Status.trim() && !pm2Status.includes('No process')) {
|
|
212
|
+
console.log(chalk_1.default.blue('[INFO] === PM2 Services ==='));
|
|
213
|
+
console.log(pm2Status);
|
|
214
|
+
console.log('');
|
|
215
|
+
}
|
|
216
|
+
// Show URLs if available
|
|
217
|
+
if (target.urls && Object.keys(target.urls).length > 0) {
|
|
218
|
+
console.log(chalk_1.default.blue('[INFO] === Service URLs ==='));
|
|
219
|
+
for (const [service, url] of Object.entries(target.urls)) {
|
|
220
|
+
console.log(` ${service}: ${chalk_1.default.cyan(url)}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
211
223
|
return;
|
|
212
224
|
}
|
|
213
|
-
if
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
225
|
+
// If DB says PROVISIONING, check if we can SSH to get progress
|
|
226
|
+
if (dbStatus === 'provisioning') {
|
|
227
|
+
// Try to SSH and check cloud-init progress
|
|
228
|
+
let status = sshExec(target.ipAddress, keyPath, 'cloud-init status 2>&1');
|
|
229
|
+
if (!status) {
|
|
230
|
+
console.log(chalk_1.default.yellow('[WARN] Unable to connect to server. It may still be booting.'));
|
|
231
|
+
return;
|
|
218
232
|
}
|
|
219
|
-
|
|
220
|
-
|
|
233
|
+
// Check for SSH connection errors (timeout, refused, etc.)
|
|
234
|
+
const sshErrors = [
|
|
235
|
+
'Operation timed out',
|
|
236
|
+
'Connection refused',
|
|
237
|
+
'Connection timed out',
|
|
238
|
+
'No route to host',
|
|
239
|
+
'Network is unreachable',
|
|
240
|
+
'ssh: connect to host',
|
|
241
|
+
];
|
|
242
|
+
if (sshErrors.some(err => status.includes(err))) {
|
|
243
|
+
console.log(chalk_1.default.yellow('[INFO] Server is still initializing - SSH is not yet available.'));
|
|
244
|
+
console.log(chalk_1.default.dim(' This is normal for newly created servers.'));
|
|
245
|
+
console.log(chalk_1.default.dim(' Please wait 1-2 minutes and try again.'));
|
|
246
|
+
return;
|
|
221
247
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
console.log(` SSH Ready: ${formatDuration(timing.sshReady)}`);
|
|
248
|
+
// Cloud-init still running
|
|
249
|
+
if (status.includes('running')) {
|
|
250
|
+
// Get timing breakdown
|
|
251
|
+
const timing = getTimingBreakdown(target.ipAddress, keyPath);
|
|
227
252
|
if (timing.total !== null) {
|
|
228
|
-
console.log(`
|
|
253
|
+
console.log(chalk_1.default.yellow(`[INFO] Setup in progress... (elapsed: ${formatDuration(timing.total)})`));
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
console.log(chalk_1.default.yellow('[INFO] Setup in progress...'));
|
|
229
257
|
}
|
|
230
258
|
console.log('');
|
|
259
|
+
// Show timing breakdown so far
|
|
260
|
+
if (timing.sshReady !== null) {
|
|
261
|
+
console.log(chalk_1.default.blue('[INFO] === Timing So Far ==='));
|
|
262
|
+
console.log(` SSH Ready: ${formatDuration(timing.sshReady)}`);
|
|
263
|
+
if (timing.total !== null) {
|
|
264
|
+
console.log(` Elapsed: ${formatDuration(timing.total)}`);
|
|
265
|
+
}
|
|
266
|
+
console.log('');
|
|
267
|
+
}
|
|
268
|
+
console.log(chalk_1.default.blue('[INFO] Latest setup progress:'));
|
|
269
|
+
// Tail cloud-init output log for progress
|
|
270
|
+
const logOutput = sshExec(target.ipAddress, keyPath, "sudo tail -30 /var/log/cloud-init-output.log 2>/dev/null | grep -E '^===|^#|Progress:|DONE|error|Error|failed|Failed' || sudo tail -20 /var/log/cloud-init-output.log", 15);
|
|
271
|
+
if (logOutput) {
|
|
272
|
+
console.log(logOutput);
|
|
273
|
+
}
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// Cloud-init done but callback might not have been received yet
|
|
277
|
+
if (status.includes('done')) {
|
|
278
|
+
console.log(chalk_1.default.green('[SUCCESS] Setup completed!'));
|
|
279
|
+
console.log(chalk_1.default.dim(' (Waiting for status update...)'));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// Cloud-init not found (already cleaned up) - show generic status
|
|
283
|
+
if (status.includes('not found') || status.includes('command not found')) {
|
|
284
|
+
console.log(chalk_1.default.yellow('[INFO] Setup is finalizing...'));
|
|
285
|
+
return;
|
|
231
286
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
287
|
+
// Other status
|
|
288
|
+
console.log(chalk_1.default.yellow(`[INFO] Status: ${status}`));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// If DB says ERROR
|
|
292
|
+
if (dbStatus === 'error') {
|
|
293
|
+
console.log(chalk_1.default.red('[ERROR] Setup failed!'));
|
|
294
|
+
console.log(chalk_1.default.dim(' Run `genbox connect` to investigate.'));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
// Fallback: try legacy cloud-init check for backwards compatibility
|
|
298
|
+
let status = sshExec(target.ipAddress, keyPath, 'cloud-init status 2>&1');
|
|
299
|
+
if (!status || status.includes('not found')) {
|
|
300
|
+
// No cloud-init, check our status file
|
|
301
|
+
const genboxStatus = sshExec(target.ipAddress, keyPath, 'cat ~/.genbox-status 2>/dev/null');
|
|
302
|
+
if (genboxStatus && genboxStatus.includes('Setup Complete')) {
|
|
303
|
+
console.log(chalk_1.default.green('[SUCCESS] Setup completed!'));
|
|
304
|
+
return;
|
|
237
305
|
}
|
|
238
306
|
}
|
|
239
|
-
|
|
307
|
+
if (status && status.includes('done')) {
|
|
240
308
|
// Get timing breakdown
|
|
241
309
|
const timing = getTimingBreakdown(target.ipAddress, keyPath);
|
|
242
310
|
console.log(chalk_1.default.green(`[SUCCESS] Cloud-init completed!${timing.total !== null ? ` (${formatDuration(timing.total)})` : ''}`));
|