@constellation-network/node-pilot 0.0.17 → 0.0.19
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 +39 -10
- package/dist/checks/check-dependencies.js +32 -26
- package/dist/checks/check-layers.js +2 -2
- package/dist/checks/check-network.js +2 -2
- package/dist/checks/check-pilot.d.ts +5 -0
- package/dist/checks/check-pilot.js +72 -0
- package/dist/checks/check-project.js +2 -1
- package/dist/checks/check-wallet.js +1 -1
- package/dist/commands/clean.d.ts +14 -0
- package/dist/commands/clean.js +45 -0
- package/dist/commands/config.js +5 -0
- package/dist/commands/restart.js +8 -3
- package/dist/commands/shutdown.d.ts +3 -0
- package/dist/commands/shutdown.js +19 -4
- package/dist/commands/status.js +3 -0
- package/dist/commands/test.js +3 -2
- package/dist/helpers/key-file-helper.js +46 -14
- package/dist/helpers/project-helper.d.ts +4 -0
- package/dist/helpers/project-helper.js +27 -5
- package/dist/helpers/prompt-helper.d.ts +1 -0
- package/dist/helpers/prompt-helper.js +13 -0
- package/dist/helpers/status-table-helper.js +29 -20
- package/dist/helpers/status-table.js +6 -3
- package/dist/services/cluster-service.js +4 -1
- package/dist/services/docker-service.d.ts +2 -1
- package/dist/services/docker-service.js +11 -4
- package/dist/services/fastforward-service.js +14 -3
- package/install-dependencies.sh +0 -48
- package/oclif.manifest.json +62 -2
- package/package.json +1 -1
- package/projects/hypergraph/test +0 -0
- package/projects/hypergraph/seedlist +0 -268
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ $ npm install -g @constellation-network/node-pilot
|
|
|
21
21
|
$ cpilot COMMAND
|
|
22
22
|
running command...
|
|
23
23
|
$ cpilot (--version|-v)
|
|
24
|
-
@constellation-network/node-pilot/0.0.
|
|
24
|
+
@constellation-network/node-pilot/0.0.19 darwin-arm64 node-v24.8.0
|
|
25
25
|
$ cpilot --help [COMMAND]
|
|
26
26
|
USAGE
|
|
27
27
|
$ cpilot COMMAND
|
|
@@ -37,6 +37,7 @@ If no command is entered, node-pilot will automatically perform a series of chec
|
|
|
37
37
|
|
|
38
38
|
# Commands
|
|
39
39
|
<!-- commands -->
|
|
40
|
+
* [`cpilot clean LAYER`](#cpilot-clean-layer)
|
|
40
41
|
* [`cpilot config`](#cpilot-config)
|
|
41
42
|
* [`cpilot config get [NAME]`](#cpilot-config-get-name)
|
|
42
43
|
* [`cpilot config set NAME VALUE`](#cpilot-config-set-name-value)
|
|
@@ -47,6 +48,31 @@ If no command is entered, node-pilot will automatically perform a series of chec
|
|
|
47
48
|
* [`cpilot shutdown`](#cpilot-shutdown)
|
|
48
49
|
* [`cpilot status`](#cpilot-status)
|
|
49
50
|
|
|
51
|
+
## `cpilot clean LAYER`
|
|
52
|
+
|
|
53
|
+
Remove data and/or logs from a validator node
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
USAGE
|
|
57
|
+
$ cpilot clean LAYER [-a] [-d] [-l]
|
|
58
|
+
|
|
59
|
+
ARGUMENTS
|
|
60
|
+
LAYER network layer to clean. e.g. gl0
|
|
61
|
+
|
|
62
|
+
FLAGS
|
|
63
|
+
-a, --all remove all data and logs
|
|
64
|
+
-d, --data remove data
|
|
65
|
+
-l, --logs remove logs
|
|
66
|
+
|
|
67
|
+
DESCRIPTION
|
|
68
|
+
Remove data and/or logs from a validator node
|
|
69
|
+
|
|
70
|
+
EXAMPLES
|
|
71
|
+
$ cpilot clean
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
_See code: [src/commands/clean.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/clean.ts)_
|
|
75
|
+
|
|
50
76
|
## `cpilot config`
|
|
51
77
|
|
|
52
78
|
Update configuration settings
|
|
@@ -62,7 +88,7 @@ EXAMPLES
|
|
|
62
88
|
$ cpilot config
|
|
63
89
|
```
|
|
64
90
|
|
|
65
|
-
_See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
91
|
+
_See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/config.ts)_
|
|
66
92
|
|
|
67
93
|
## `cpilot config get [NAME]`
|
|
68
94
|
|
|
@@ -86,7 +112,7 @@ EXAMPLES
|
|
|
86
112
|
$ cpilot config get gl0:CL_PUBLIC_HTTP_PORT
|
|
87
113
|
```
|
|
88
114
|
|
|
89
|
-
_See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
115
|
+
_See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/config/get.ts)_
|
|
90
116
|
|
|
91
117
|
## `cpilot config set NAME VALUE`
|
|
92
118
|
|
|
@@ -109,7 +135,7 @@ EXAMPLES
|
|
|
109
135
|
$ cpilot config set gl0:CL_PUBLIC_HTTP_PORT 9000
|
|
110
136
|
```
|
|
111
137
|
|
|
112
|
-
_See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
138
|
+
_See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/config/set.ts)_
|
|
113
139
|
|
|
114
140
|
## `cpilot help [COMMAND]`
|
|
115
141
|
|
|
@@ -146,7 +172,7 @@ EXAMPLES
|
|
|
146
172
|
$ cpilot info
|
|
147
173
|
```
|
|
148
174
|
|
|
149
|
-
_See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
175
|
+
_See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/info.ts)_
|
|
150
176
|
|
|
151
177
|
## `cpilot logs LAYER`
|
|
152
178
|
|
|
@@ -170,7 +196,7 @@ EXAMPLES
|
|
|
170
196
|
$ cpilot logs
|
|
171
197
|
```
|
|
172
198
|
|
|
173
|
-
_See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
199
|
+
_See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/logs.ts)_
|
|
174
200
|
|
|
175
201
|
## `cpilot restart [LAYER]`
|
|
176
202
|
|
|
@@ -198,7 +224,7 @@ EXAMPLES
|
|
|
198
224
|
$ cpilot restart
|
|
199
225
|
```
|
|
200
226
|
|
|
201
|
-
_See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
227
|
+
_See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/restart.ts)_
|
|
202
228
|
|
|
203
229
|
## `cpilot shutdown`
|
|
204
230
|
|
|
@@ -206,7 +232,10 @@ A full shutdown of the validator node
|
|
|
206
232
|
|
|
207
233
|
```
|
|
208
234
|
USAGE
|
|
209
|
-
$ cpilot shutdown
|
|
235
|
+
$ cpilot shutdown [-l <value>]
|
|
236
|
+
|
|
237
|
+
FLAGS
|
|
238
|
+
-l, --layer=<value> specify a layer to shutdown. e.g. gl0
|
|
210
239
|
|
|
211
240
|
DESCRIPTION
|
|
212
241
|
A full shutdown of the validator node
|
|
@@ -215,7 +244,7 @@ EXAMPLES
|
|
|
215
244
|
$ cpilot shutdown
|
|
216
245
|
```
|
|
217
246
|
|
|
218
|
-
_See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
247
|
+
_See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/shutdown.ts)_
|
|
219
248
|
|
|
220
249
|
## `cpilot status`
|
|
221
250
|
|
|
@@ -229,5 +258,5 @@ DESCRIPTION
|
|
|
229
258
|
Display node status and configuration settings
|
|
230
259
|
```
|
|
231
260
|
|
|
232
|
-
_See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
|
261
|
+
_See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.19/src/commands/status.ts)_
|
|
233
262
|
<!-- commandsstop -->
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
import shell from "shelljs";
|
|
@@ -8,37 +9,42 @@ import { shellService } from "../services/shell-service.js";
|
|
|
8
9
|
export const checkDependencies = async () => {
|
|
9
10
|
const dockerComposeVersion = await shellService.runCommand('docker compose version').catch(() => '');
|
|
10
11
|
clm.debug(`Docker compose version check: ${dockerComposeVersion || 'NOT_INSTALLED'}`);
|
|
11
|
-
if (dockerComposeVersion) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
process.exit(0);
|
|
12
|
+
if (!dockerComposeVersion) {
|
|
13
|
+
const isDockerV1Installed = await shellService.checkCommandAvailable('docker-compose');
|
|
14
|
+
if (isDockerV1Installed) {
|
|
15
|
+
clm.warn('You are using docker-compose v1. It needs to be uninstalled before upgrading to the latest version.');
|
|
16
|
+
// await promptHelper.doYouWishToContinue();
|
|
17
|
+
clm.step('\nRun the following command to uninstall docker-compose v1 and then run cpilot again:');
|
|
18
|
+
clm.preStep('for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done');
|
|
19
|
+
clm.echo('');
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
22
|
}
|
|
23
23
|
const isDockerInstalled = await shellService.checkCommandAvailable('docker');
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await promptHelper.doYouWishToContinue();
|
|
31
|
-
}
|
|
32
|
-
clm.debug(`Running install-dependencies.sh from ${pilotDir}`);
|
|
33
|
-
// const silent = !process.env.DEBUG;
|
|
34
|
-
const result = shell.exec('bash install-dependencies.sh', { cwd: pilotDir });
|
|
35
|
-
if (result.code > 0) {
|
|
36
|
-
console.log(result.stderr);
|
|
37
|
-
clm.error(`Failed to install dependencies. Please try again after resolving any errors.`);
|
|
38
|
-
}
|
|
24
|
+
const pilotDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../..`);
|
|
25
|
+
if (fs.existsSync(path.join(pilotDir, 'install-dependencies.sh'))) {
|
|
26
|
+
if (!isDockerInstalled) {
|
|
27
|
+
clm.step('Docker is required and needs to be installed.');
|
|
28
|
+
await promptHelper.doYouWishToContinue();
|
|
29
|
+
await installDependencies(pilotDir);
|
|
39
30
|
clm.postStep(`\nDocker has been installed. Please logout and login again to ensure the changes take effect. Then run cpilot again.`);
|
|
40
31
|
clm.echo('');
|
|
41
32
|
process.exit(0);
|
|
42
33
|
}
|
|
34
|
+
const isACLInstalled = await shellService.checkCommandAvailable('setfacl');
|
|
35
|
+
if (!isACLInstalled && os.platform() === 'linux') {
|
|
36
|
+
clm.step('ACL is required and needs to be installed.');
|
|
37
|
+
await promptHelper.doYouWishToContinue();
|
|
38
|
+
await installDependencies(pilotDir);
|
|
39
|
+
}
|
|
43
40
|
}
|
|
44
41
|
};
|
|
42
|
+
async function installDependencies(pilotDir) {
|
|
43
|
+
clm.debug(`Running install-dependencies.sh from ${pilotDir}`);
|
|
44
|
+
// const silent = !process.env.DEBUG;
|
|
45
|
+
const result = shell.exec('bash install-dependencies.sh', { cwd: pilotDir });
|
|
46
|
+
if (result.code > 0) {
|
|
47
|
+
console.log(result.stderr);
|
|
48
|
+
clm.error(`Failed to install dependencies. Please try again after resolving any errors.`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -34,7 +34,7 @@ export const checkLayers = {
|
|
|
34
34
|
await nodeService.pollForLayersState(layersToRun);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
clm.postStep('Node not started.');
|
|
37
|
+
clm.postStep('Validator Node not started.');
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
}
|
|
@@ -48,7 +48,7 @@ export const checkLayers = {
|
|
|
48
48
|
await nodeService.pollForLayersState(layersNotRunning);
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
clm.echo('Node not started.');
|
|
51
|
+
clm.echo('Validator Node not started.');
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -29,7 +29,7 @@ export const checkNetwork = {
|
|
|
29
29
|
clm.error(`Or to change the node ID, configure the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
|
|
30
30
|
}
|
|
31
31
|
configStore.setProjectFlag('duplicateNodeIdChecked', true);
|
|
32
|
-
clm.postStep('No duplicate Node found.');
|
|
32
|
+
clm.postStep('✅ No duplicate Node found.');
|
|
33
33
|
},
|
|
34
34
|
async checkSeedList() {
|
|
35
35
|
if (configStore.hasProjectFlag('seedListChecked')) {
|
|
@@ -42,7 +42,7 @@ export const checkNetwork = {
|
|
|
42
42
|
if (fs.existsSync(seedListFile)) {
|
|
43
43
|
const found = fs.readFileSync(seedListFile, 'utf8').includes(nodeId);
|
|
44
44
|
if (found) {
|
|
45
|
-
clm.postStep(
|
|
45
|
+
clm.postStep(`✅ Node ID found in ${type.toUpperCase()} seed list.`);
|
|
46
46
|
configStore.setProjectFlag('seedListChecked', true);
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { input } from "@inquirer/prompts";
|
|
2
|
+
import { JSONStorage } from "node-localstorage";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
6
|
+
import { clm } from "../clm.js";
|
|
7
|
+
import { configStore } from "../config-store.js";
|
|
8
|
+
import { projectHelper } from "../helpers/project-helper.js";
|
|
9
|
+
import { promptHelper } from "../helpers/prompt-helper.js";
|
|
10
|
+
import { shellService } from "../services/shell-service.js";
|
|
11
|
+
const REGISTRY_URL = 'https://registry.npmjs.org/';
|
|
12
|
+
export const checkNodePilot = {
|
|
13
|
+
async checkDiscordRegistration() {
|
|
14
|
+
if (configStore.hasProjectFlag('discordChecked')) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
await this.promptDiscordRegistration();
|
|
18
|
+
configStore.setProjectFlag('discordChecked', true);
|
|
19
|
+
},
|
|
20
|
+
async checkVersion() {
|
|
21
|
+
const packageUrl = new URL(encodeURIComponent(packageJson.name).replace(/^%40/, '@'), REGISTRY_URL);
|
|
22
|
+
const headers = {
|
|
23
|
+
accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*',
|
|
24
|
+
};
|
|
25
|
+
const result = await fetch(packageUrl.toString(), { headers }).then(res => res.json()).catch(() => null);
|
|
26
|
+
if (!result) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const latestVersion = result['dist-tags'].latest;
|
|
30
|
+
if (packageJson.version !== latestVersion) {
|
|
31
|
+
console.log('There is a new node-pilot version available.');
|
|
32
|
+
if (await promptHelper.confirmPrompt('Do you wish to upgrade now?')) {
|
|
33
|
+
await shellService.runCommand('npm install -g @constellationnetwork/node-pilot@latest');
|
|
34
|
+
await projectHelper.upgradeHypergraph();
|
|
35
|
+
clm.postStep('Run cpilot again to use the latest version');
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
async promptDiscordRegistration() {
|
|
41
|
+
const hcStorage = getHcStorage();
|
|
42
|
+
const join = await promptHelper.confirmPrompt('Do you want to enable Discord notifications for your node?:');
|
|
43
|
+
if (!join) {
|
|
44
|
+
hcStorage.setItem('user', { webHookEnabled: false });
|
|
45
|
+
clm.postStep('Discord notifications are disabled.');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
let answer = await input({
|
|
49
|
+
default: '',
|
|
50
|
+
message: `Provide your Discord username to have it included in the notification: `
|
|
51
|
+
});
|
|
52
|
+
answer = answer.trim();
|
|
53
|
+
if (answer === '') {
|
|
54
|
+
hcStorage.setItem('user', { webHookEnabled: true });
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (answer.charAt(0) === '@')
|
|
58
|
+
answer = answer.slice(1);
|
|
59
|
+
hcStorage.setItem('user', { discordUser: answer.trim(), webHookEnabled: true });
|
|
60
|
+
}
|
|
61
|
+
clm.postStep('Discord notifications are enabled.');
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
function getHcStorage() {
|
|
65
|
+
const { layersToRun, projectDir } = configStore.getProjectInfo();
|
|
66
|
+
const layer = layersToRun[0];
|
|
67
|
+
const hcPath = path.join(projectDir, layer, 'data', 'health-check');
|
|
68
|
+
if (fs.existsSync(hcPath)) {
|
|
69
|
+
fs.mkdirSync(hcPath, { recursive: true });
|
|
70
|
+
}
|
|
71
|
+
return new JSONStorage(hcPath);
|
|
72
|
+
}
|
|
@@ -103,7 +103,8 @@ export const checkProject = {
|
|
|
103
103
|
// spinner.color = 'green';
|
|
104
104
|
// }
|
|
105
105
|
// else {
|
|
106
|
-
clm.preStep('
|
|
106
|
+
clm.preStep('Tessellation and dependencies need to be installed. This may take a few minutes...');
|
|
107
|
+
await promptHelper.doYouWishToContinue();
|
|
107
108
|
// }
|
|
108
109
|
// const node = await clusterService.getClusterNodeInfo();
|
|
109
110
|
// const NODE_URL = `http://${node.host}:${node.publicPort}`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Clean extends Command {
|
|
3
|
+
static args: {
|
|
4
|
+
layer: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
+
data: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
logs: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { clm } from "../clm.js";
|
|
3
|
+
import { configStore } from "../config-store.js";
|
|
4
|
+
import { projectHelper } from "../helpers/project-helper.js";
|
|
5
|
+
import { promptHelper } from "../helpers/prompt-helper.js";
|
|
6
|
+
import { dockerService } from "../services/docker-service.js";
|
|
7
|
+
import { shellService } from "../services/shell-service.js";
|
|
8
|
+
export default class Clean extends Command {
|
|
9
|
+
static args = {
|
|
10
|
+
layer: Args.string({ description: 'network layer to clean. e.g. gl0', required: true }),
|
|
11
|
+
};
|
|
12
|
+
static description = 'Remove data and/or logs from a validator node';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %>',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
all: Flags.boolean({ char: 'a', description: 'remove all data and logs' }),
|
|
18
|
+
data: Flags.boolean({ char: 'd', description: 'remove data' }),
|
|
19
|
+
logs: Flags.boolean({ char: 'l', description: 'remove logs' })
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { args, flags } = await this.parse(Clean);
|
|
23
|
+
const { layersToRun } = configStore.getProjectInfo();
|
|
24
|
+
if (!layersToRun.includes(args.layer)) {
|
|
25
|
+
this.error(`Invalid layer: ${args.layer}. Available layers: ${layersToRun.join(',')}`);
|
|
26
|
+
}
|
|
27
|
+
const deleteLogs = flags.logs || flags.all;
|
|
28
|
+
const deleteData = flags.data || flags.all;
|
|
29
|
+
if (!deleteLogs && !deleteData) {
|
|
30
|
+
this.error('At least one of --data or --logs must be specified.');
|
|
31
|
+
}
|
|
32
|
+
if (await dockerService.isRunning()) {
|
|
33
|
+
clm.preStep('The validator node must be stopped first.');
|
|
34
|
+
await promptHelper.doYouWishToContinue();
|
|
35
|
+
await dockerService.dockerDown();
|
|
36
|
+
}
|
|
37
|
+
if (deleteData) {
|
|
38
|
+
await shellService.runProjectCommand(`sudo rm -rf ${args.layer}/data`);
|
|
39
|
+
projectHelper.prepareDataFolder();
|
|
40
|
+
}
|
|
41
|
+
if (deleteLogs) {
|
|
42
|
+
await shellService.runProjectCommand(`sudo rm -rf ${args.layer}/logs`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/commands/config.js
CHANGED
|
@@ -7,6 +7,7 @@ import { configHelper } from "../helpers/config-helper.js";
|
|
|
7
7
|
import { keyFileHelper } from "../helpers/key-file-helper.js";
|
|
8
8
|
import { promptHelper } from "../helpers/prompt-helper.js";
|
|
9
9
|
import { dockerService } from "../services/docker-service.js";
|
|
10
|
+
import { checkNodePilot } from "../checks/check-pilot.js";
|
|
10
11
|
export default class Config extends Command {
|
|
11
12
|
static description = 'Update configuration settings';
|
|
12
13
|
static examples = [
|
|
@@ -19,6 +20,7 @@ export default class Config extends Command {
|
|
|
19
20
|
const answer = await select({
|
|
20
21
|
choices: [
|
|
21
22
|
{ name: 'External IP Address', value: 'externalIp' },
|
|
23
|
+
{ name: `Discord Alerts`, value: 'discordAlerts' },
|
|
22
24
|
{ name: 'Java Memory', value: 'javaMemory' },
|
|
23
25
|
{ name: 'Key File', value: 'keyFile' },
|
|
24
26
|
{ name: 'Layers To Run', value: 'layersToRun' },
|
|
@@ -30,6 +32,9 @@ export default class Config extends Command {
|
|
|
30
32
|
if (answer === 'externalIp') {
|
|
31
33
|
await checkNetwork.configureIpAddress();
|
|
32
34
|
}
|
|
35
|
+
else if (answer === 'discordAlerts') {
|
|
36
|
+
await checkNodePilot.promptDiscordRegistration();
|
|
37
|
+
}
|
|
33
38
|
else if (answer === 'javaMemory') {
|
|
34
39
|
await shutdownNodeIfRunning();
|
|
35
40
|
await promptHelper.configureJavaMemoryArguments();
|
package/dist/commands/restart.js
CHANGED
|
@@ -36,6 +36,9 @@ export default class Restart extends BaseCommand {
|
|
|
36
36
|
// eslint-disable-next-line no-await-in-loop
|
|
37
37
|
await this.restart();
|
|
38
38
|
}
|
|
39
|
+
else {
|
|
40
|
+
serviceLog.log(' ' + project + ' version is the same. ');
|
|
41
|
+
}
|
|
39
42
|
}
|
|
40
43
|
configStore.setActiveProject(project);
|
|
41
44
|
return;
|
|
@@ -46,7 +49,7 @@ export default class Restart extends BaseCommand {
|
|
|
46
49
|
const activeProjects = configStore.getRunningProjects();
|
|
47
50
|
// serviceLog.log(` Active projects: ${activeProjects.join(', ')}...`);
|
|
48
51
|
for (const project of activeProjects) {
|
|
49
|
-
serviceLog.log(' ' + project + ' is
|
|
52
|
+
serviceLog.log(' ' + project + ' is being auto started...');
|
|
50
53
|
configStore.setActiveProject(project);
|
|
51
54
|
// eslint-disable-next-line no-await-in-loop
|
|
52
55
|
await this.restart();
|
|
@@ -75,8 +78,10 @@ export default class Restart extends BaseCommand {
|
|
|
75
78
|
// const pAll = layersToRun.map(l => nodeService.getNodeInfo(l));
|
|
76
79
|
// const info = await Promise.all(pAll);
|
|
77
80
|
// const isRunning = info.some(n => n.state !== 'Unavailable');
|
|
78
|
-
if (configStore.isRestarting())
|
|
81
|
+
if (configStore.isRestarting()) {
|
|
82
|
+
serviceLog.log('Restart already ACTIVE');
|
|
79
83
|
return;
|
|
84
|
+
}
|
|
80
85
|
configStore.setIsRestarting(true);
|
|
81
86
|
try {
|
|
82
87
|
if (await dockerService.isRunning()) {
|
|
@@ -89,7 +94,7 @@ export default class Restart extends BaseCommand {
|
|
|
89
94
|
clm.preStep('Checking for a new version...');
|
|
90
95
|
await checkProject.runUpgrade();
|
|
91
96
|
clm.preStep('Starting the node...');
|
|
92
|
-
await dockerService.
|
|
97
|
+
await dockerService.dockerRestartAll();
|
|
93
98
|
}
|
|
94
99
|
finally {
|
|
95
100
|
configStore.setIsRestarting(false);
|
|
@@ -2,5 +2,8 @@ import { Command } from '@oclif/core';
|
|
|
2
2
|
export default class Shutdown extends Command {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
layer: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
5
8
|
run(): Promise<void>;
|
|
6
9
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { configStore } from "../config-store.js";
|
|
3
3
|
import { configHelper } from "../helpers/config-helper.js";
|
|
4
4
|
import { dockerService } from "../services/docker-service.js";
|
|
@@ -8,11 +8,26 @@ export default class Shutdown extends Command {
|
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> <%= command.id %>',
|
|
10
10
|
];
|
|
11
|
+
static flags = {
|
|
12
|
+
layer: Flags.string({ char: 'l', description: 'specify a layer to shutdown. e.g. gl0' })
|
|
13
|
+
};
|
|
11
14
|
async run() {
|
|
12
15
|
configHelper.assertProject('No project found. ');
|
|
16
|
+
const { flags } = await this.parse(Shutdown);
|
|
13
17
|
const { layersToRun } = configStore.getProjectInfo();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
const layer = flags.layer;
|
|
19
|
+
if (layer) {
|
|
20
|
+
if (!layersToRun.includes(layer)) {
|
|
21
|
+
this.error(`Invalid layer: ${layer}. Available layers: ${layersToRun.join(',')}`);
|
|
22
|
+
}
|
|
23
|
+
await nodeService.leaveCluster(layer);
|
|
24
|
+
await nodeService.pollForLayersState([], 'Offline');
|
|
25
|
+
await dockerService.dockerDown([layer]);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
await nodeService.leaveClusterAllLayers();
|
|
29
|
+
await nodeService.pollForLayersState(layersToRun, 'Offline');
|
|
30
|
+
await dockerService.dockerDown();
|
|
31
|
+
}
|
|
17
32
|
}
|
|
18
33
|
}
|
package/dist/commands/status.js
CHANGED
|
@@ -3,6 +3,7 @@ import { checkInitialSetup } from "../checks/check-initial-setup.js";
|
|
|
3
3
|
import { checkLayers } from "../checks/check-layers.js";
|
|
4
4
|
import { checkNetwork } from "../checks/check-network.js";
|
|
5
5
|
import { checkNodeCtl } from "../checks/check-node-ctl.js";
|
|
6
|
+
import { checkNodePilot } from "../checks/check-pilot.js";
|
|
6
7
|
import { checkProject } from "../checks/check-project.js";
|
|
7
8
|
import { checkWallet } from "../checks/check-wallet.js";
|
|
8
9
|
import { keyFileHelper } from "../helpers/key-file-helper.js";
|
|
@@ -19,6 +20,8 @@ export async function checkInstallationAndConfigurationStatus() {
|
|
|
19
20
|
await checkProject.projectInstallation();
|
|
20
21
|
await checkNetwork.checkExternalIpAddress();
|
|
21
22
|
await checkNetwork.isNetworkConnectable();
|
|
23
|
+
await checkNodePilot.checkDiscordRegistration();
|
|
24
|
+
await checkNodePilot.checkVersion();
|
|
22
25
|
await checkProject.releaseVersion();
|
|
23
26
|
await checkNodeCtl.check4Migration();
|
|
24
27
|
await keyFileHelper.promptIfNoKeyFile();
|
package/dist/commands/test.js
CHANGED
|
@@ -4,7 +4,7 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { getRandomNode } from "../services/get-random-node.js";
|
|
7
|
-
import {
|
|
7
|
+
import { checkNodePilot } from "../checks/check-pilot.js";
|
|
8
8
|
export default class Test extends Command {
|
|
9
9
|
static description = 'node pilot test command';
|
|
10
10
|
static hidden = true;
|
|
@@ -18,7 +18,8 @@ export default class Test extends Command {
|
|
|
18
18
|
//
|
|
19
19
|
// await archiverService.syncToLatestSnapshot();
|
|
20
20
|
// await archiverService.checkLogsForMissingSnapshots();
|
|
21
|
-
await StatusTable.run();
|
|
21
|
+
// await StatusTable.run();
|
|
22
|
+
await checkNodePilot.checkVersion();
|
|
22
23
|
}
|
|
23
24
|
async testRandomNode() {
|
|
24
25
|
const filePath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../projects/hypergraph/networks/mainnet/source-nodes.env`);
|
|
@@ -60,40 +60,72 @@ export const keyFileHelper = {
|
|
|
60
60
|
return shellService.runCommandWithOutput(`java -jar ${projectDir}/dist/wallet.jar show-id`, env);
|
|
61
61
|
},
|
|
62
62
|
async importKeyFile() {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
const p12Files = fs.readdirSync(os.homedir())
|
|
64
|
+
.filter(file => file.endsWith('.p12'))
|
|
65
|
+
.map(file => ({ name: 'Import ~/' + file, value: file }));
|
|
66
|
+
let userKeyPath = '';
|
|
67
|
+
let answer = 'importAnother';
|
|
68
|
+
if (p12Files.length > 0) {
|
|
69
|
+
const choices = [
|
|
70
|
+
...p12Files,
|
|
71
|
+
{ name: 'Import a different key file', value: 'importAnother' }
|
|
72
|
+
];
|
|
73
|
+
answer = await select({ choices, message: 'Choose an option:' });
|
|
74
|
+
userKeyPath = path.join(os.homedir(), answer);
|
|
75
|
+
}
|
|
76
|
+
if (answer === 'importAnother') {
|
|
77
|
+
userKeyPath = await input({
|
|
78
|
+
message: 'Enter the path to your key file:',
|
|
79
|
+
validate(value) {
|
|
80
|
+
const fullPath = shellService.resolvePath(value.trim());
|
|
81
|
+
if (!fs.existsSync(fullPath)) {
|
|
82
|
+
return `${fullPath} does not exist. Please provide a valid path.`;
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
69
85
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
73
88
|
const { projectDir } = configStore.getProjectInfo();
|
|
74
89
|
const fullPath = shellService.resolvePath(userKeyPath.trim());
|
|
75
90
|
const keyStorePath = path.join(projectDir, "key.p12");
|
|
91
|
+
const tempKeyPath = path.join(projectDir, "temp.p12");
|
|
92
|
+
const envInfo = configStore.getEnvInfo();
|
|
93
|
+
// prompt for password
|
|
94
|
+
const keyPassword = await password({ message: 'Enter the key file password:' });
|
|
95
|
+
const keyAlias = await input({ message: 'Enter the key file alias:' });
|
|
96
|
+
configStore.setEnvInfo({ CL_KEYALIAS: keyAlias, CL_KEYSTORE: keyStorePath, CL_PASSWORD: keyPassword });
|
|
76
97
|
try {
|
|
98
|
+
if (fs.existsSync(keyStorePath))
|
|
99
|
+
fs.cpSync(keyStorePath, tempKeyPath, { force: true });
|
|
77
100
|
fs.copyFileSync(fullPath, keyStorePath);
|
|
78
101
|
}
|
|
79
102
|
catch (error) {
|
|
80
103
|
clm.error('Failed to import key file:' + error);
|
|
81
104
|
}
|
|
82
|
-
// prompt for password
|
|
83
|
-
const keyPassword = await password({ message: 'Enter the key file password:' });
|
|
84
|
-
const keyAlias = await input({ message: 'Enter the key file alias:' });
|
|
85
|
-
configStore.setEnvInfo({ CL_KEYALIAS: keyAlias, CL_KEYSTORE: keyStorePath, CL_PASSWORD: keyPassword });
|
|
86
105
|
try {
|
|
87
106
|
const dagAddress = await this.getAddress();
|
|
88
107
|
const nodeId = await this.getId();
|
|
89
108
|
configStore.setProjectInfo({ dagAddress, nodeId });
|
|
90
109
|
}
|
|
91
110
|
catch {
|
|
92
|
-
fs.
|
|
111
|
+
if (fs.existsSync(tempKeyPath)) {
|
|
112
|
+
// Revert back to original key file
|
|
113
|
+
fs.cpSync(tempKeyPath, keyStorePath, { force: true });
|
|
114
|
+
configStore.setEnvInfo({ CL_KEYALIAS: envInfo.CL_KEYALIAS, CL_KEYSTORE: envInfo.CL_KEYSTORE, CL_PASSWORD: envInfo.CL_PASSWORD });
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
fs.rmSync(keyStorePath);
|
|
118
|
+
}
|
|
93
119
|
clm.error('Failed to unlock the key file. Please check your key file information and try again.');
|
|
94
120
|
// await this.promptForKeyFile();
|
|
95
121
|
// return;
|
|
96
122
|
}
|
|
123
|
+
try {
|
|
124
|
+
fs.copyFileSync(fullPath, keyStorePath);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
clm.error('Failed to import key file:' + error);
|
|
128
|
+
}
|
|
97
129
|
clm.postStep('Key file imported successfully.\n');
|
|
98
130
|
},
|
|
99
131
|
async promptForKeyFile() {
|
|
@@ -6,5 +6,9 @@ export declare const projectHelper: {
|
|
|
6
6
|
installFromGithub(_repo: string): Promise<never>;
|
|
7
7
|
installHypergraph(): Promise<void>;
|
|
8
8
|
installProject(name: string, projectFolder: string): Promise<void>;
|
|
9
|
+
prepareDataFolder(): void;
|
|
9
10
|
selectProject(): Promise<void>;
|
|
11
|
+
upgradeEmbedded(name: string): Promise<void>;
|
|
12
|
+
upgradeHypergraph(): Promise<void>;
|
|
13
|
+
upgradeProject(name: string, projectFolder: string): Promise<void>;
|
|
10
14
|
};
|