@camunda8/cli 3.3.0-alpha.5 → 3.3.0-alpha.6
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/EXAMPLES.md +20 -0
- package/README.md +6 -0
- package/dist/default-plugins/cluster/c8ctl-plugin.js +182 -32
- package/package.json +1 -1
package/EXAMPLES.md
CHANGED
|
@@ -1233,6 +1233,26 @@ c8 cluster install alpha
|
|
|
1233
1233
|
c8 cluster delete 8.8
|
|
1234
1234
|
```
|
|
1235
1235
|
|
|
1236
|
+
### Purge Cluster Data
|
|
1237
|
+
|
|
1238
|
+
Wipe history and journal data while keeping the downloaded binary intact.
|
|
1239
|
+
The next `cluster start` begins with a fresh empty state without re-downloading anything.
|
|
1240
|
+
|
|
1241
|
+
```bash
|
|
1242
|
+
# Purge data for a specific version (version required, like delete)
|
|
1243
|
+
c8 cluster purge 8.9
|
|
1244
|
+
c8 cluster purge 8.9.0-alpha5
|
|
1245
|
+
|
|
1246
|
+
# Stop the running cluster and purge its data in one step
|
|
1247
|
+
c8 cluster stop --purge
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
If the target version is currently running, stop it first with `cluster stop`
|
|
1251
|
+
(or use `cluster stop --purge` to stop and purge in one step).
|
|
1252
|
+
|
|
1253
|
+
`cluster stop --purge` is the recommended way to reset a running cluster:
|
|
1254
|
+
it captures the running version, stops it, then purges the data atomically.
|
|
1255
|
+
|
|
1236
1256
|
### Typical Local Development Workflow
|
|
1237
1257
|
|
|
1238
1258
|
```bash
|
package/README.md
CHANGED
|
@@ -517,6 +517,12 @@ c8ctl cluster install 8.9
|
|
|
517
517
|
|
|
518
518
|
# Remove a cached version
|
|
519
519
|
c8ctl cluster delete 8.9
|
|
520
|
+
|
|
521
|
+
# Purge history and journal data for a version (binary stays intact)
|
|
522
|
+
c8ctl cluster purge 8.9
|
|
523
|
+
|
|
524
|
+
# Stop cluster and purge its runtime data in one step
|
|
525
|
+
c8ctl cluster stop --purge
|
|
520
526
|
```
|
|
521
527
|
|
|
522
528
|
#### Version Aliases
|
|
@@ -320,6 +320,7 @@ export const metadata = {
|
|
|
320
320
|
{ name: 'delete', description: 'Remove a cached version' },
|
|
321
321
|
{ name: 'log', description: 'Stream cluster logs' },
|
|
322
322
|
{ name: 'logs', description: 'Stream cluster logs' },
|
|
323
|
+
{ name: 'purge', description: 'Delete runtime data (keeps binary) so the next start is fresh' },
|
|
323
324
|
],
|
|
324
325
|
examples: [
|
|
325
326
|
{ command: 'c8ctl cluster start', description: 'Start a local Camunda 8 cluster (latest stable)' },
|
|
@@ -332,6 +333,8 @@ export const metadata = {
|
|
|
332
333
|
{ command: 'c8ctl cluster list-remote', description: 'List all versions available on the remote download server' },
|
|
333
334
|
{ command: 'c8ctl cluster install 8.8', description: 'Download a version without starting it' },
|
|
334
335
|
{ command: 'c8ctl cluster delete 8.8', description: 'Remove a locally cached version' },
|
|
336
|
+
{ command: 'c8ctl cluster purge 8.8', description: 'Delete runtime data for a version (binary stays intact)' },
|
|
337
|
+
{ command: 'c8ctl cluster stop --purge', description: 'Stop the running cluster and delete its runtime data' },
|
|
335
338
|
],
|
|
336
339
|
},
|
|
337
340
|
},
|
|
@@ -1043,13 +1046,16 @@ export async function stopC8Run(config, debug = false) {
|
|
|
1043
1046
|
logger.warn(
|
|
1044
1047
|
'Cluster marker file found, but no running cluster processes detected. Cleaning up stale marker.',
|
|
1045
1048
|
);
|
|
1046
|
-
|
|
1047
|
-
rmSync(markerFile);
|
|
1048
|
-
}
|
|
1049
|
+
let staleVersion = null;
|
|
1049
1050
|
if (existsSync(versionFile)) {
|
|
1051
|
+
const v = readFileSync(versionFile, 'utf-8').trim();
|
|
1052
|
+
if (v) staleVersion = v;
|
|
1050
1053
|
rmSync(versionFile);
|
|
1051
1054
|
}
|
|
1052
|
-
|
|
1055
|
+
if (existsSync(markerFile)) {
|
|
1056
|
+
rmSync(markerFile);
|
|
1057
|
+
}
|
|
1058
|
+
return staleVersion;
|
|
1053
1059
|
}
|
|
1054
1060
|
|
|
1055
1061
|
if (!markerExists && clusterAppearsRunning) {
|
|
@@ -1069,10 +1075,12 @@ export async function stopC8Run(config, debug = false) {
|
|
|
1069
1075
|
: [];
|
|
1070
1076
|
|
|
1071
1077
|
const versionsToTry = [];
|
|
1078
|
+
let stoppedVersion = null;
|
|
1072
1079
|
|
|
1073
1080
|
if (existsSync(versionFile)) {
|
|
1074
1081
|
const markerVersion = readFileSync(versionFile, 'utf-8').trim();
|
|
1075
1082
|
if (markerVersion) {
|
|
1083
|
+
stoppedVersion = markerVersion;
|
|
1076
1084
|
versionsToTry.push(markerVersion);
|
|
1077
1085
|
}
|
|
1078
1086
|
}
|
|
@@ -1186,6 +1194,7 @@ export async function stopC8Run(config, debug = false) {
|
|
|
1186
1194
|
}
|
|
1187
1195
|
|
|
1188
1196
|
logger.info('Cluster stopped.');
|
|
1197
|
+
return stoppedVersion;
|
|
1189
1198
|
}
|
|
1190
1199
|
|
|
1191
1200
|
// ---------------------------------------------------------------------------
|
|
@@ -1369,6 +1378,37 @@ export async function listRemoteVersions() {
|
|
|
1369
1378
|
console.log('');
|
|
1370
1379
|
}
|
|
1371
1380
|
|
|
1381
|
+
// ---------------------------------------------------------------------------
|
|
1382
|
+
// Shared helpers for delete / purge
|
|
1383
|
+
// ---------------------------------------------------------------------------
|
|
1384
|
+
|
|
1385
|
+
// Validate and resolve a version spec to the locally installed version name.
|
|
1386
|
+
// Aliases (stable, alpha) are resolved preferring the local cache so that
|
|
1387
|
+
// delete/purge operate on what is actually installed.
|
|
1388
|
+
async function resolveVersionArg(cacheDir, versionSpec) {
|
|
1389
|
+
validateVersionSpec(versionSpec);
|
|
1390
|
+
return isVersionAlias(versionSpec)
|
|
1391
|
+
? await resolveVersion(versionSpec, { preferLocal: true, cacheDir })
|
|
1392
|
+
: versionSpec;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
// Return true if the given version appears to be currently running.
|
|
1396
|
+
// Requires both marker files to identify the running version, then confirms
|
|
1397
|
+
// with live .process pidfiles. Without markers we cannot attribute any
|
|
1398
|
+
// running process to a specific version, so we return false — consistent
|
|
1399
|
+
// with stopC8Run treating marker absence as "not running".
|
|
1400
|
+
function isVersionRunning(cacheDir, version) {
|
|
1401
|
+
const markerFile = join(cacheDir, ACTIVE_MARKER_FILE);
|
|
1402
|
+
const versionFile = join(cacheDir, VERSION_MARKER_FILE);
|
|
1403
|
+
|
|
1404
|
+
if (!existsSync(markerFile) || !existsSync(versionFile)) return false;
|
|
1405
|
+
|
|
1406
|
+
const markerVersion = readFileSync(versionFile, 'utf-8').trim();
|
|
1407
|
+
if (markerVersion !== version) return false;
|
|
1408
|
+
|
|
1409
|
+
return hasRunningClusterPidfiles(cacheDir);
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1372
1412
|
// ---------------------------------------------------------------------------
|
|
1373
1413
|
// Delete cached version
|
|
1374
1414
|
// ---------------------------------------------------------------------------
|
|
@@ -1381,28 +1421,28 @@ export async function deleteVersion(cacheDir, versionSpec) {
|
|
|
1381
1421
|
process.exit(1);
|
|
1382
1422
|
}
|
|
1383
1423
|
|
|
1384
|
-
validateVersionSpec(versionSpec);
|
|
1385
|
-
|
|
1386
|
-
// Resolve named aliases (stable/alpha) to the actual cached version name.
|
|
1387
|
-
// Use preferLocal so we delete the version that's actually installed,
|
|
1388
|
-
// not whatever the remote currently resolves the alias to.
|
|
1389
1424
|
// Major.minor patterns like 8.8 are used as-is since the cache dir is named c8run-8.8.
|
|
1390
|
-
const resolvedVersion =
|
|
1391
|
-
? await resolveVersion(versionSpec, { preferLocal: true, cacheDir })
|
|
1392
|
-
: versionSpec;
|
|
1425
|
+
const resolvedVersion = await resolveVersionArg(cacheDir, versionSpec);
|
|
1393
1426
|
|
|
1394
1427
|
// Prevent deleting a currently running version
|
|
1395
|
-
|
|
1396
|
-
|
|
1428
|
+
if (isVersionRunning(cacheDir, resolvedVersion)) {
|
|
1429
|
+
logger.error(
|
|
1430
|
+
`Version ${resolvedVersion} is currently running. Stop it first with: c8ctl cluster stop`
|
|
1431
|
+
);
|
|
1432
|
+
process.exit(1);
|
|
1433
|
+
}
|
|
1397
1434
|
|
|
1398
|
-
if
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1435
|
+
// Safety backstop: if processes are running but either marker is absent we
|
|
1436
|
+
// cannot confirm the version, so refuse rather than risk deleting a live install.
|
|
1437
|
+
if (
|
|
1438
|
+
(!existsSync(join(cacheDir, ACTIVE_MARKER_FILE)) || !existsSync(join(cacheDir, VERSION_MARKER_FILE))) &&
|
|
1439
|
+
hasRunningClusterPidfiles(cacheDir)
|
|
1440
|
+
) {
|
|
1441
|
+
logger.error(
|
|
1442
|
+
'A cluster appears to be running (processes detected) but the cluster marker is missing. ' +
|
|
1443
|
+
'Run c8ctl cluster stop first.'
|
|
1444
|
+
);
|
|
1445
|
+
process.exit(1);
|
|
1406
1446
|
}
|
|
1407
1447
|
|
|
1408
1448
|
const config = { cacheDir, version: resolvedVersion };
|
|
@@ -1416,6 +1456,79 @@ export async function deleteVersion(cacheDir, versionSpec) {
|
|
|
1416
1456
|
logger.info(`Version ${versionSpec} has been deleted.`);
|
|
1417
1457
|
}
|
|
1418
1458
|
|
|
1459
|
+
// ---------------------------------------------------------------------------
|
|
1460
|
+
// Purge cluster data
|
|
1461
|
+
// ---------------------------------------------------------------------------
|
|
1462
|
+
|
|
1463
|
+
export async function purgeClusterData(cacheDir, versionSpec) {
|
|
1464
|
+
const logger = getLogger();
|
|
1465
|
+
|
|
1466
|
+
const resolvedVersion = await resolveVersionArg(cacheDir, versionSpec);
|
|
1467
|
+
|
|
1468
|
+
// Prevent purging a currently running version
|
|
1469
|
+
if (isVersionRunning(cacheDir, resolvedVersion)) {
|
|
1470
|
+
logger.error(
|
|
1471
|
+
`Version ${resolvedVersion} is currently running. ` +
|
|
1472
|
+
'Stop it first with: c8ctl cluster stop\n' +
|
|
1473
|
+
`Or stop and purge in one step: c8ctl cluster stop --purge`
|
|
1474
|
+
);
|
|
1475
|
+
process.exit(1);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
// Safety backstop: if processes are running but either marker is absent we
|
|
1479
|
+
// cannot confirm the version, so refuse rather than risk purging a live cluster.
|
|
1480
|
+
if (
|
|
1481
|
+
(!existsSync(join(cacheDir, ACTIVE_MARKER_FILE)) || !existsSync(join(cacheDir, VERSION_MARKER_FILE))) &&
|
|
1482
|
+
hasRunningClusterPidfiles(cacheDir)
|
|
1483
|
+
) {
|
|
1484
|
+
logger.error(
|
|
1485
|
+
'A cluster appears to be running (processes detected) but the cluster marker is missing. ' +
|
|
1486
|
+
'Run c8ctl cluster stop first.'
|
|
1487
|
+
);
|
|
1488
|
+
process.exit(1);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
const config = { cacheDir, version: resolvedVersion };
|
|
1492
|
+
if (!isC8RunInstalled(config)) {
|
|
1493
|
+
logger.error(`Version ${resolvedVersion} is not installed locally.`);
|
|
1494
|
+
process.exit(1);
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
const binaryPath = getC8RunBinaryPath(config);
|
|
1498
|
+
const binaryDir = dirname(binaryPath);
|
|
1499
|
+
|
|
1500
|
+
const deleted = [];
|
|
1501
|
+
|
|
1502
|
+
// Delete camunda-data (history data + application state)
|
|
1503
|
+
const camundaDataDir = join(binaryDir, 'camunda-data');
|
|
1504
|
+
if (existsSync(camundaDataDir)) {
|
|
1505
|
+
rmSync(camundaDataDir, { recursive: true });
|
|
1506
|
+
deleted.push('camunda-data');
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
// Delete Zeebe journal data inside camunda-zeebe-* subdirectory
|
|
1510
|
+
if (existsSync(binaryDir)) {
|
|
1511
|
+
for (const entry of readdirSync(binaryDir, { withFileTypes: true })) {
|
|
1512
|
+
if (!entry.isDirectory() || !entry.name.startsWith('camunda-zeebe-')) continue;
|
|
1513
|
+
const dataDir = join(binaryDir, entry.name, 'data');
|
|
1514
|
+
if (existsSync(dataDir)) {
|
|
1515
|
+
rmSync(dataDir, { recursive: true });
|
|
1516
|
+
deleted.push(join(entry.name, 'data'));
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
if (deleted.length > 0) {
|
|
1522
|
+
logger.info(`Purged runtime data for ${resolvedVersion}:`);
|
|
1523
|
+
for (const d of deleted) {
|
|
1524
|
+
logger.info(` deleted: ${d}`);
|
|
1525
|
+
}
|
|
1526
|
+
} else {
|
|
1527
|
+
logger.info(`No runtime data found for ${resolvedVersion} — nothing to delete.`);
|
|
1528
|
+
}
|
|
1529
|
+
logger.info(`Binary and installed files preserved. Start fresh with: c8ctl cluster start ${resolvedVersion}`);
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1419
1532
|
// ---------------------------------------------------------------------------
|
|
1420
1533
|
// Logs
|
|
1421
1534
|
// ---------------------------------------------------------------------------
|
|
@@ -1499,7 +1612,7 @@ export async function streamLogs(cacheDir) {
|
|
|
1499
1612
|
// ---------------------------------------------------------------------------
|
|
1500
1613
|
|
|
1501
1614
|
export function parsePluginArgs(args) {
|
|
1502
|
-
const result = { subcommand: null, version: null, debug: false };
|
|
1615
|
+
const result = { subcommand: null, version: null, debug: false, purge: false };
|
|
1503
1616
|
|
|
1504
1617
|
let i = 0;
|
|
1505
1618
|
while (i < args.length) {
|
|
@@ -1523,6 +1636,12 @@ export function parsePluginArgs(args) {
|
|
|
1523
1636
|
continue;
|
|
1524
1637
|
}
|
|
1525
1638
|
|
|
1639
|
+
if (arg === '--purge') {
|
|
1640
|
+
result.purge = true;
|
|
1641
|
+
i += 1;
|
|
1642
|
+
continue;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1526
1645
|
if (!arg.startsWith('-') && result.subcommand === null) {
|
|
1527
1646
|
result.subcommand = arg;
|
|
1528
1647
|
i += 1;
|
|
@@ -1546,7 +1665,7 @@ export function parsePluginArgs(args) {
|
|
|
1546
1665
|
// Plugin commands export
|
|
1547
1666
|
// ---------------------------------------------------------------------------
|
|
1548
1667
|
|
|
1549
|
-
const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'list', 'list-remote', 'install', 'delete', 'log', 'logs'];
|
|
1668
|
+
const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'list', 'list-remote', 'install', 'delete', 'purge', 'log', 'logs'];
|
|
1550
1669
|
|
|
1551
1670
|
export const commands = {
|
|
1552
1671
|
'cluster': async (args) => {
|
|
@@ -1556,28 +1675,31 @@ export const commands = {
|
|
|
1556
1675
|
if (!parsed.subcommand || !VALID_SUBCOMMANDS.includes(parsed.subcommand)) {
|
|
1557
1676
|
console.log('Usage:');
|
|
1558
1677
|
console.log(' c8ctl cluster start [<version>] [--debug]');
|
|
1559
|
-
console.log(' c8ctl cluster stop');
|
|
1678
|
+
console.log(' c8ctl cluster stop [--purge]');
|
|
1560
1679
|
console.log(' c8ctl cluster status');
|
|
1561
1680
|
console.log(' c8ctl cluster logs (alias: log)');
|
|
1562
1681
|
console.log(' c8ctl cluster list');
|
|
1563
1682
|
console.log(' c8ctl cluster list-remote');
|
|
1564
1683
|
console.log(' c8ctl cluster install <version>');
|
|
1565
1684
|
console.log(' c8ctl cluster delete <version>');
|
|
1685
|
+
console.log(' c8ctl cluster purge <version>');
|
|
1566
1686
|
console.log('');
|
|
1567
1687
|
console.log('Subcommands:');
|
|
1568
1688
|
console.log(' start Download (if needed) and start a local Camunda 8 cluster');
|
|
1569
|
-
console.log(' stop Stop the running local Camunda 8 cluster');
|
|
1689
|
+
console.log(' stop Stop the running local Camunda 8 cluster (--purge also deletes runtime data)');
|
|
1570
1690
|
console.log(' status Show whether a cluster is running and connection details');
|
|
1571
1691
|
console.log(' logs Stream log output from the running cluster');
|
|
1572
1692
|
console.log(' list List locally cached versions and available version aliases');
|
|
1573
1693
|
console.log(' list-remote List all versions available on the remote download server');
|
|
1574
1694
|
console.log(' install Download a version without starting it');
|
|
1575
1695
|
console.log(' delete Remove a locally cached version to reclaim disk space');
|
|
1696
|
+
console.log(' purge Delete runtime data for a version (binary stays intact, next start is fresh)');
|
|
1576
1697
|
console.log('');
|
|
1577
1698
|
console.log('Options:');
|
|
1578
1699
|
console.log(' <version> Camunda version, alias, or major.minor (default: stable)');
|
|
1579
1700
|
console.log(' --c8-version <version> Alternative flag form for version');
|
|
1580
1701
|
console.log(' --debug Stream raw c8run output during start');
|
|
1702
|
+
console.log(' --purge (stop only) also delete runtime data after stopping');
|
|
1581
1703
|
console.log('');
|
|
1582
1704
|
console.log('A <version> can be:');
|
|
1583
1705
|
console.log(' stable / alpha Named aliases');
|
|
@@ -1604,9 +1726,16 @@ export const commands = {
|
|
|
1604
1726
|
console.log(' c8ctl cluster list-remote');
|
|
1605
1727
|
console.log(' c8ctl cluster install 8.8');
|
|
1606
1728
|
console.log(' c8ctl cluster delete 8.8');
|
|
1729
|
+
console.log(' c8ctl cluster purge 8.8 # Delete runtime data, keep binary');
|
|
1730
|
+
console.log(' c8ctl cluster stop --purge # Stop cluster and delete its runtime data');
|
|
1607
1731
|
return;
|
|
1608
1732
|
}
|
|
1609
1733
|
|
|
1734
|
+
if (parsed.purge && parsed.subcommand !== 'stop') {
|
|
1735
|
+
logger.error('--purge can only be used with the stop subcommand. Example: c8ctl cluster stop --purge');
|
|
1736
|
+
process.exit(1);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1610
1739
|
if (parsed.subcommand === 'status') {
|
|
1611
1740
|
try {
|
|
1612
1741
|
await clusterStatus(getCacheDir());
|
|
@@ -1647,11 +1776,14 @@ export const commands = {
|
|
|
1647
1776
|
return;
|
|
1648
1777
|
}
|
|
1649
1778
|
|
|
1650
|
-
// install and
|
|
1651
|
-
if (!parsed.version && (parsed.subcommand === 'install' || parsed.subcommand === 'delete')) {
|
|
1652
|
-
const example =
|
|
1653
|
-
|
|
1654
|
-
|
|
1779
|
+
// install, delete, and purge require an explicit version argument
|
|
1780
|
+
if (!parsed.version && (parsed.subcommand === 'install' || parsed.subcommand === 'delete' || parsed.subcommand === 'purge')) {
|
|
1781
|
+
const example =
|
|
1782
|
+
parsed.subcommand === 'delete'
|
|
1783
|
+
? 'c8ctl cluster delete 8.8'
|
|
1784
|
+
: parsed.subcommand === 'purge'
|
|
1785
|
+
? 'c8ctl cluster purge 8.8'
|
|
1786
|
+
: 'c8ctl cluster install stable';
|
|
1655
1787
|
logger.error(`Please specify a version. Example: ${example}`);
|
|
1656
1788
|
process.exit(1);
|
|
1657
1789
|
}
|
|
@@ -1666,6 +1798,16 @@ export const commands = {
|
|
|
1666
1798
|
return;
|
|
1667
1799
|
}
|
|
1668
1800
|
|
|
1801
|
+
if (parsed.subcommand === 'purge') {
|
|
1802
|
+
try {
|
|
1803
|
+
await purgeClusterData(getCacheDir(), parsed.version);
|
|
1804
|
+
} catch (error) {
|
|
1805
|
+
logger.error(`Failed to purge cluster data: ${error}`);
|
|
1806
|
+
process.exit(1);
|
|
1807
|
+
}
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1669
1811
|
const versionSpec = parsed.version || 'stable';
|
|
1670
1812
|
if (!parsed.version && parsed.subcommand === 'start') {
|
|
1671
1813
|
logger.info(`No version specified, using default: "${versionSpec}"`);
|
|
@@ -1713,7 +1855,15 @@ export const commands = {
|
|
|
1713
1855
|
}
|
|
1714
1856
|
} else if (parsed.subcommand === 'stop') {
|
|
1715
1857
|
try {
|
|
1716
|
-
await stopC8Run(config, parsed.debug);
|
|
1858
|
+
const stoppedVersion = await stopC8Run(config, parsed.debug);
|
|
1859
|
+
if (parsed.purge) {
|
|
1860
|
+
if (!stoppedVersion) {
|
|
1861
|
+
logger.warn('Cannot determine which version to purge (version marker is missing). ' +
|
|
1862
|
+
'To purge manually, run: c8ctl cluster purge <version>');
|
|
1863
|
+
} else {
|
|
1864
|
+
await purgeClusterData(theCacheDir, stoppedVersion);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1717
1867
|
} catch (error) {
|
|
1718
1868
|
logger.error(`Failed to stop cluster: ${error}`);
|
|
1719
1869
|
process.exit(1);
|