@_xtribe/cli 1.0.0-beta.11 → 1.0.0-beta.14
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/install-tribe.js +141 -5
- package/package.json +1 -1
package/install-tribe.js
CHANGED
|
@@ -392,14 +392,43 @@ async function checkColimaRunning() {
|
|
|
392
392
|
}
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
+
async function checkColimaHasKubernetes() {
|
|
396
|
+
try {
|
|
397
|
+
const colimaPath = await findCommand('colima') || path.join(binDir, 'colima');
|
|
398
|
+
const status = execSync(`${colimaPath} status`, { encoding: 'utf8' });
|
|
399
|
+
// Check if kubernetes is mentioned in the status
|
|
400
|
+
return status.toLowerCase().includes('kubernetes');
|
|
401
|
+
} catch {
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
395
406
|
async function startColimaWithKubernetes() {
|
|
396
407
|
const spinner = ora('Starting Colima with Kubernetes...').start();
|
|
397
408
|
|
|
398
409
|
try {
|
|
399
410
|
// Check if already running
|
|
400
411
|
if (await checkColimaRunning()) {
|
|
401
|
-
|
|
402
|
-
|
|
412
|
+
// Check if it has Kubernetes enabled
|
|
413
|
+
if (await checkColimaHasKubernetes()) {
|
|
414
|
+
spinner.succeed('Colima is already running with Kubernetes');
|
|
415
|
+
return true;
|
|
416
|
+
} else {
|
|
417
|
+
spinner.text = 'Colima is running without Kubernetes. Restarting with Kubernetes...';
|
|
418
|
+
|
|
419
|
+
// Stop existing Colima
|
|
420
|
+
const colimaPath = await findCommand('colima') || path.join(binDir, 'colima');
|
|
421
|
+
try {
|
|
422
|
+
execSync(`${colimaPath} stop`, {
|
|
423
|
+
stdio: 'pipe',
|
|
424
|
+
timeout: 30000
|
|
425
|
+
});
|
|
426
|
+
// Wait for it to fully stop
|
|
427
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
428
|
+
} catch (stopError) {
|
|
429
|
+
log.warning('Failed to stop Colima, attempting to start anyway...');
|
|
430
|
+
}
|
|
431
|
+
}
|
|
403
432
|
}
|
|
404
433
|
|
|
405
434
|
// Start Colima with Kubernetes enabled
|
|
@@ -407,12 +436,24 @@ async function startColimaWithKubernetes() {
|
|
|
407
436
|
const colimaPath = await findCommand('colima') || path.join(binDir, 'colima');
|
|
408
437
|
execSync(`${colimaPath} start --kubernetes --cpu 4 --memory 8 --disk 20`, {
|
|
409
438
|
stdio: 'pipe',
|
|
410
|
-
env: { ...process.env, PATH: `${binDir}:${process.env.PATH}` }
|
|
439
|
+
env: { ...process.env, PATH: `${binDir}:${process.env.PATH}` },
|
|
440
|
+
timeout: 300000 // 5 minute timeout for first start
|
|
411
441
|
});
|
|
412
442
|
|
|
413
|
-
//
|
|
443
|
+
// Give Colima a moment to stabilize after starting
|
|
444
|
+
spinner.text = 'Waiting for Colima to stabilize...';
|
|
445
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
446
|
+
|
|
447
|
+
// Verify it's working and set context
|
|
414
448
|
const kubectlPath = await findCommand('kubectl') || 'kubectl';
|
|
415
449
|
execSync(`${kubectlPath} version --client`, { stdio: 'ignore' });
|
|
450
|
+
|
|
451
|
+
// Set kubectl context to colima
|
|
452
|
+
try {
|
|
453
|
+
execSync(`${kubectlPath} config use-context colima`, { stdio: 'ignore' });
|
|
454
|
+
} catch {
|
|
455
|
+
// Context might not exist yet, that's OK
|
|
456
|
+
}
|
|
416
457
|
spinner.succeed('Colima started with Kubernetes');
|
|
417
458
|
return true;
|
|
418
459
|
} catch (error) {
|
|
@@ -460,6 +501,89 @@ async function deployTribeCluster() {
|
|
|
460
501
|
TRIBE_DEPLOYMENT_YAML: destYaml
|
|
461
502
|
};
|
|
462
503
|
|
|
504
|
+
// Wait for Kubernetes to be fully ready
|
|
505
|
+
spinner.text = 'Waiting for Kubernetes to be ready...';
|
|
506
|
+
const kubectlPath = await findCommand('kubectl') || 'kubectl';
|
|
507
|
+
let apiReady = false;
|
|
508
|
+
let contextSet = false;
|
|
509
|
+
|
|
510
|
+
// First, wait for the API server to be accessible
|
|
511
|
+
for (let i = 0; i < 30; i++) {
|
|
512
|
+
try {
|
|
513
|
+
// Try to get cluster info - this will work regardless of port
|
|
514
|
+
const clusterInfo = execSync(`${kubectlPath} cluster-info`, {
|
|
515
|
+
encoding: 'utf8',
|
|
516
|
+
env: env,
|
|
517
|
+
stdio: 'pipe'
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
// Check if we got valid cluster info
|
|
521
|
+
if (clusterInfo && clusterInfo.includes('is running at')) {
|
|
522
|
+
apiReady = true;
|
|
523
|
+
spinner.text = 'Kubernetes API server is ready';
|
|
524
|
+
|
|
525
|
+
// Extract the actual API server URL for logging
|
|
526
|
+
const urlMatch = clusterInfo.match(/is running at (https?:\/\/[^\s]+)/);
|
|
527
|
+
if (urlMatch) {
|
|
528
|
+
log.info(`Kubernetes API server: ${urlMatch[1]}`);
|
|
529
|
+
}
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
} catch (error) {
|
|
533
|
+
spinner.text = `Waiting for Kubernetes API server... (${i+1}/30)`;
|
|
534
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (!apiReady) {
|
|
539
|
+
spinner.warn('Kubernetes API server not ready after 60 seconds');
|
|
540
|
+
log.info('Deployment may fail. You can try running "tribe start" manually later.');
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// Set the kubectl context to colima
|
|
545
|
+
spinner.text = 'Setting kubectl context...';
|
|
546
|
+
try {
|
|
547
|
+
execSync(`${kubectlPath} config use-context colima`, {
|
|
548
|
+
stdio: 'ignore',
|
|
549
|
+
env: env
|
|
550
|
+
});
|
|
551
|
+
contextSet = true;
|
|
552
|
+
} catch {
|
|
553
|
+
log.warning('Could not set kubectl context to colima');
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Wait for the node to be ready
|
|
557
|
+
spinner.text = 'Waiting for Kubernetes node to be ready...';
|
|
558
|
+
let nodeReady = false;
|
|
559
|
+
for (let i = 0; i < 20; i++) {
|
|
560
|
+
try {
|
|
561
|
+
const nodeStatus = execSync(`${kubectlPath} get nodes -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}'`, {
|
|
562
|
+
encoding: 'utf8',
|
|
563
|
+
env: env
|
|
564
|
+
}).trim();
|
|
565
|
+
|
|
566
|
+
if (nodeStatus === 'True') {
|
|
567
|
+
nodeReady = true;
|
|
568
|
+
spinner.text = 'Kubernetes node is ready';
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
} catch {
|
|
572
|
+
// Node might not be registered yet
|
|
573
|
+
}
|
|
574
|
+
spinner.text = `Waiting for Kubernetes node... (${i+1}/20)`;
|
|
575
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
if (!nodeReady) {
|
|
579
|
+
spinner.warn('Kubernetes node not ready after 60 seconds');
|
|
580
|
+
log.info('The cluster may still be initializing. Proceeding with deployment...');
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// Small delay to let everything stabilize
|
|
584
|
+
spinner.text = 'Starting TRIBE deployment...';
|
|
585
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
586
|
+
|
|
463
587
|
// Execute tribe start
|
|
464
588
|
execSync(`${tribePath} start`, {
|
|
465
589
|
stdio: 'pipe',
|
|
@@ -475,7 +599,19 @@ async function deployTribeCluster() {
|
|
|
475
599
|
} catch (error) {
|
|
476
600
|
spinner.fail('Failed to deploy TRIBE cluster');
|
|
477
601
|
log.error(error.message);
|
|
478
|
-
|
|
602
|
+
|
|
603
|
+
// Check if this is a Kubernetes connectivity issue
|
|
604
|
+
if (error.message && error.message.includes('connection refused')) {
|
|
605
|
+
log.warning('\nIt appears Kubernetes is not ready or not enabled.');
|
|
606
|
+
log.info('Troubleshooting steps:');
|
|
607
|
+
log.info('1. Check Colima status: colima status');
|
|
608
|
+
log.info('2. If running without Kubernetes, restart it:');
|
|
609
|
+
log.info(' colima stop');
|
|
610
|
+
log.info(' colima start --kubernetes');
|
|
611
|
+
log.info('3. Then run: tribe start');
|
|
612
|
+
} else {
|
|
613
|
+
log.info('You can manually deploy later with: tribe start');
|
|
614
|
+
}
|
|
479
615
|
return false;
|
|
480
616
|
}
|
|
481
617
|
}
|