@constellation-network/node-pilot 0.13.1-testnet → 0.13.2
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 +10 -28
- package/dist/checks/check-dependencies.js +13 -20
- package/dist/checks/check-initial-setup.d.ts +0 -10
- package/dist/checks/check-initial-setup.js +7 -55
- package/dist/checks/check-node-ctl.d.ts +5 -0
- package/dist/checks/check-node-ctl.js +88 -0
- package/dist/checks/check-pilot.d.ts +0 -1
- package/dist/checks/check-pilot.js +8 -34
- package/dist/checks/check-project.js +3 -4
- package/dist/commands/config.js +1 -1
- package/dist/commands/info.js +2 -2
- package/dist/commands/status.js +6 -3
- package/dist/config-store.d.ts +0 -4
- package/dist/config-store.js +0 -5
- package/dist/helpers/project-helper.d.ts +3 -3
- package/dist/helpers/project-helper.js +12 -15
- package/dist/services/fastforward-service.js +9 -8
- package/dist/services/migration-service.d.ts +1 -1
- package/dist/services/migration-service.js +25 -23
- package/dist/services/shell-service.js +5 -8
- package/dist/services/systemd-service.d.ts +0 -1
- package/dist/services/systemd-service.js +6 -19
- package/install-dependencies.sh +1 -1
- package/oclif.manifest.json +1 -24
- package/package.json +2 -2
- package/projects/hypergraph/Dockerfile +2 -2
- package/projects/hypergraph/docker-compose.yml +4 -4
- package/projects/hypergraph/networks/mainnet/network.env +3 -3
- package/projects/hypergraph/networks/testnet/network.env +3 -3
- package/projects/hypergraph/scripts/install-dependencies.sh +19 -19
- package/scripts/install_services.sh +5 -10
- package/dist/commands/uninstall.d.ts +0 -6
- package/dist/commands/uninstall.js +0 -24
- package/scripts/uninstall_services.sh +0 -37
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.13.
|
|
24
|
+
@constellation-network/node-pilot/0.13.2 darwin-arm64 node-v22.15.0
|
|
25
25
|
$ cpilot --help [COMMAND]
|
|
26
26
|
USAGE
|
|
27
27
|
$ cpilot COMMAND
|
|
@@ -47,7 +47,6 @@ If no command is entered, node-pilot will automatically perform a series of chec
|
|
|
47
47
|
* [`cpilot restart [LAYER]`](#cpilot-restart-layer)
|
|
48
48
|
* [`cpilot shutdown`](#cpilot-shutdown)
|
|
49
49
|
* [`cpilot status`](#cpilot-status)
|
|
50
|
-
* [`cpilot uninstall`](#cpilot-uninstall)
|
|
51
50
|
|
|
52
51
|
## `cpilot clean [LAYER]`
|
|
53
52
|
|
|
@@ -72,7 +71,7 @@ EXAMPLES
|
|
|
72
71
|
$ cpilot clean
|
|
73
72
|
```
|
|
74
73
|
|
|
75
|
-
_See code: [src/commands/clean.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
74
|
+
_See code: [src/commands/clean.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/clean.ts)_
|
|
76
75
|
|
|
77
76
|
## `cpilot config`
|
|
78
77
|
|
|
@@ -89,7 +88,7 @@ EXAMPLES
|
|
|
89
88
|
$ cpilot config
|
|
90
89
|
```
|
|
91
90
|
|
|
92
|
-
_See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
91
|
+
_See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/config.ts)_
|
|
93
92
|
|
|
94
93
|
## `cpilot config get [NAME]`
|
|
95
94
|
|
|
@@ -113,7 +112,7 @@ EXAMPLES
|
|
|
113
112
|
$ cpilot config get gl0:CL_PUBLIC_HTTP_PORT
|
|
114
113
|
```
|
|
115
114
|
|
|
116
|
-
_See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
115
|
+
_See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/config/get.ts)_
|
|
117
116
|
|
|
118
117
|
## `cpilot config set NAME VALUE`
|
|
119
118
|
|
|
@@ -136,7 +135,7 @@ EXAMPLES
|
|
|
136
135
|
$ cpilot config set gl0:CL_PUBLIC_HTTP_PORT 9000
|
|
137
136
|
```
|
|
138
137
|
|
|
139
|
-
_See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
138
|
+
_See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/config/set.ts)_
|
|
140
139
|
|
|
141
140
|
## `cpilot help [COMMAND]`
|
|
142
141
|
|
|
@@ -173,7 +172,7 @@ EXAMPLES
|
|
|
173
172
|
$ cpilot info
|
|
174
173
|
```
|
|
175
174
|
|
|
176
|
-
_See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
175
|
+
_See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/info.ts)_
|
|
177
176
|
|
|
178
177
|
## `cpilot logs LAYER`
|
|
179
178
|
|
|
@@ -199,7 +198,7 @@ EXAMPLES
|
|
|
199
198
|
$ cpilot logs
|
|
200
199
|
```
|
|
201
200
|
|
|
202
|
-
_See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
201
|
+
_See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/logs.ts)_
|
|
203
202
|
|
|
204
203
|
## `cpilot restart [LAYER]`
|
|
205
204
|
|
|
@@ -227,7 +226,7 @@ EXAMPLES
|
|
|
227
226
|
$ cpilot restart
|
|
228
227
|
```
|
|
229
228
|
|
|
230
|
-
_See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
229
|
+
_See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/restart.ts)_
|
|
231
230
|
|
|
232
231
|
## `cpilot shutdown`
|
|
233
232
|
|
|
@@ -244,7 +243,7 @@ EXAMPLES
|
|
|
244
243
|
$ cpilot shutdown
|
|
245
244
|
```
|
|
246
245
|
|
|
247
|
-
_See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
246
|
+
_See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/shutdown.ts)_
|
|
248
247
|
|
|
249
248
|
## `cpilot status`
|
|
250
249
|
|
|
@@ -258,22 +257,5 @@ DESCRIPTION
|
|
|
258
257
|
Display node status and configuration settings
|
|
259
258
|
```
|
|
260
259
|
|
|
261
|
-
_See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.
|
|
262
|
-
|
|
263
|
-
## `cpilot uninstall`
|
|
264
|
-
|
|
265
|
-
Uninstall Node Pilot
|
|
266
|
-
|
|
267
|
-
```
|
|
268
|
-
USAGE
|
|
269
|
-
$ cpilot uninstall
|
|
270
|
-
|
|
271
|
-
DESCRIPTION
|
|
272
|
-
Uninstall Node Pilot
|
|
273
|
-
|
|
274
|
-
EXAMPLES
|
|
275
|
-
$ cpilot uninstall
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
_See code: [src/commands/uninstall.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.1-testnet/src/commands/uninstall.ts)_
|
|
260
|
+
_See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.13.2/src/commands/status.ts)_
|
|
279
261
|
<!-- commandsstop -->
|
|
@@ -22,28 +22,21 @@ export const checkDependencies = async () => {
|
|
|
22
22
|
}
|
|
23
23
|
const isDockerInstalled = await shellService.checkCommandAvailable('docker');
|
|
24
24
|
const pilotDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../..`);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
clm.
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
await shellService.runCommand(`sudo usermod -aG docker ${user}`);
|
|
35
|
-
clm.postStep(`\n✅ Added user "${user}" to the docker group`);
|
|
36
|
-
clm.warn('\nPlease logout and login again in order for the group changes take effect.\n');
|
|
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);
|
|
30
|
+
clm.postStep(`\nDocker has been installed. Please logout and login again to ensure the changes take effect. Then run cpilot again.`);
|
|
31
|
+
clm.echo('');
|
|
37
32
|
process.exit(0);
|
|
38
33
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
clm.echo('');
|
|
46
|
-
process.exit(0);
|
|
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
|
+
}
|
|
47
40
|
}
|
|
48
41
|
};
|
|
49
42
|
async function installDependencies(pilotDir) {
|
|
@@ -1,13 +1,3 @@
|
|
|
1
1
|
export declare const checkInitialSetup: {
|
|
2
|
-
checkExistingUsers(): Promise<void>;
|
|
3
2
|
firstTimeRun(): Promise<void>;
|
|
4
|
-
getExistingInstallations(): Promise<{
|
|
5
|
-
currentUser: string;
|
|
6
|
-
otherUsers: never[];
|
|
7
|
-
rootUserHasPilot?: undefined;
|
|
8
|
-
} | {
|
|
9
|
-
currentUser: string;
|
|
10
|
-
otherUsers: string[];
|
|
11
|
-
rootUserHasPilot: boolean;
|
|
12
|
-
}>;
|
|
13
3
|
};
|
|
@@ -1,67 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { clm } from "../clm.js";
|
|
1
|
+
import chalk from "chalk";
|
|
5
2
|
import { configStore } from "../config-store.js";
|
|
6
|
-
import { shellService } from "../services/shell-service.js";
|
|
7
3
|
import { systemdService } from "../services/systemd-service.js";
|
|
8
4
|
import { checkDependencies } from "./check-dependencies.js";
|
|
9
5
|
import { checkHardware } from "./check-hardware.js";
|
|
10
6
|
export const checkInitialSetup = {
|
|
11
|
-
async checkExistingUsers() {
|
|
12
|
-
const { otherUsers } = await this.getExistingInstallations();
|
|
13
|
-
if (otherUsers.length > 0) {
|
|
14
|
-
clm.warn(`There are other users that have Node Pilot installed.\n ${otherUsers.join('\n ')}`);
|
|
15
|
-
clm.warn('To uninstall for another user, login as the user and run "cpilot uninstall".');
|
|
16
|
-
clm.error('Node Pilot can only be installed for one user at a time.\n');
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
7
|
async firstTimeRun() {
|
|
20
|
-
if (configStore.
|
|
8
|
+
if (configStore.getSystemInfo() !== null) {
|
|
21
9
|
return;
|
|
22
10
|
}
|
|
23
11
|
await checkDependencies();
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// console.log(" " + chalk.whiteBright("CONSTELLATION NETWORK") + " ");
|
|
30
|
-
// console.log(" " + chalk.whiteBright("NODE PILOT") + " ");
|
|
31
|
-
// console.log(chalk.whiteBright(" ****************************************"));
|
|
12
|
+
console.log(chalk.whiteBright("\n ****************************************"));
|
|
13
|
+
console.log(" " + chalk.whiteBright("CONSTELLATION NETWORK") + " ");
|
|
14
|
+
console.log(" " + chalk.whiteBright("NODE PILOT") + " ");
|
|
15
|
+
console.log(chalk.whiteBright(" ****************************************"));
|
|
16
|
+
await checkHardware.systemRequirements();
|
|
32
17
|
await systemdService.install();
|
|
33
|
-
configStore.setProjectFlag('firstTimeChecked', true);
|
|
34
18
|
},
|
|
35
|
-
async getExistingInstallations() {
|
|
36
|
-
const platform = os.platform();
|
|
37
|
-
const isLinux = platform === 'linux';
|
|
38
|
-
const homeFolder = isLinux ? '/home' : '/Users';
|
|
39
|
-
const currentUser = os.userInfo().username;
|
|
40
|
-
if (!fs.existsSync(homeFolder)) {
|
|
41
|
-
clm.warn(`Home folder path does not exist: ${homeFolder}`);
|
|
42
|
-
return { currentUser, otherUsers: [] };
|
|
43
|
-
}
|
|
44
|
-
const userFolders = fs.readdirSync(homeFolder).filter(file => fs.lstatSync(path.join(homeFolder, file)).isDirectory());
|
|
45
|
-
const usersWithPilot = [];
|
|
46
|
-
for (const folder of userFolders) {
|
|
47
|
-
const dirPath = path.join(homeFolder, folder, '.node-pilot');
|
|
48
|
-
// eslint-disable-next-line no-await-in-loop
|
|
49
|
-
const exists = await shellService.runCommandWithOutput(`sudo test -d "${dirPath}" && echo 1 || echo 0`);
|
|
50
|
-
if (exists === '1')
|
|
51
|
-
usersWithPilot.push(folder);
|
|
52
|
-
}
|
|
53
|
-
let rootUserHasPilot = false;
|
|
54
|
-
if (isLinux) {
|
|
55
|
-
const dirPath = path.join('/root', '.node-pilot');
|
|
56
|
-
const exists = await shellService.runCommandWithOutput(`sudo test -d "${dirPath}" && echo 1 || echo 0`);
|
|
57
|
-
if (exists === '1') {
|
|
58
|
-
usersWithPilot.push('root');
|
|
59
|
-
rootUserHasPilot = true;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// console.log(`Current currentUser: ${currentUser}`);
|
|
63
|
-
// console.log(`Users with Node Pilot installed: ${usersWithPilot.join(', ')}`);
|
|
64
|
-
// console.log(`Root currentUser has Node Pilot installed: ${rootUserHasPilot}`);
|
|
65
|
-
return { currentUser, otherUsers: usersWithPilot.filter(u => u !== currentUser), rootUserHasPilot };
|
|
66
|
-
}
|
|
67
19
|
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { input, password } from "@inquirer/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import yaml from "yaml";
|
|
6
|
+
import { clm } from "../clm.js";
|
|
7
|
+
import { configStore } from "../config-store.js";
|
|
8
|
+
import { keyFileHelper } from "../helpers/key-file-helper.js";
|
|
9
|
+
import { promptHelper } from "../helpers/prompt-helper.js";
|
|
10
|
+
import { dockerService } from "../services/docker-service.js";
|
|
11
|
+
import { nodeService } from "../services/node-service.js";
|
|
12
|
+
import { shellService } from "../services/shell-service.js";
|
|
13
|
+
export const checkNodeCtl = {
|
|
14
|
+
async check4Migration() {
|
|
15
|
+
if (configStore.hasProjectFlag('nodeCtlChecked')) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const { name } = configStore.getProjectInfo();
|
|
19
|
+
if (name.toLowerCase() !== 'hypergraph') {
|
|
20
|
+
configStore.setProjectFlag('nodeCtlChecked', true);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const hasNodeAdminUser = fs.existsSync('/home/nodeadmin');
|
|
24
|
+
if (hasNodeAdminUser) {
|
|
25
|
+
const isDockerRunning = await dockerService.isRunning();
|
|
26
|
+
const isPortOpen = await nodeService.isPortInUse(9000);
|
|
27
|
+
clm.step(chalk.bold('NODECTL has been detected.'));
|
|
28
|
+
if (!isDockerRunning && isPortOpen) {
|
|
29
|
+
clm.error('Please shutdown any Nodes being managed by NODECTL before proceeding.');
|
|
30
|
+
}
|
|
31
|
+
const cnPath = path.resolve('/var/tessellation/nodectl/cn-config.yaml');
|
|
32
|
+
if (fs.existsSync(cnPath)) {
|
|
33
|
+
const answer = await input({
|
|
34
|
+
default: 'y',
|
|
35
|
+
message: 'Would you like to import key file from nodectl? (y/n): '
|
|
36
|
+
});
|
|
37
|
+
if (answer.toLowerCase() === 'y') {
|
|
38
|
+
await this.importKeyInfo(cnPath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
configStore.setProjectFlag('nodeCtlChecked', true);
|
|
43
|
+
},
|
|
44
|
+
async importKeyInfo(cnPath) {
|
|
45
|
+
clm.step('Importing key file from nodectl...');
|
|
46
|
+
try {
|
|
47
|
+
clm.preStep('Making a sudo call to read the nodectl config file...');
|
|
48
|
+
await shellService.runCommand(`sudo chmod +r ${cnPath}`);
|
|
49
|
+
const doc = yaml.parse(fs.readFileSync(cnPath, 'utf8'));
|
|
50
|
+
// console.log(JSON.stringify(doc,null,2));
|
|
51
|
+
// eslint-disable-next-line camelcase
|
|
52
|
+
const { key_location, key_name } = doc.nodectl.global_p12;
|
|
53
|
+
const nodeCtlKeyPath = path.resolve(key_location, key_name);
|
|
54
|
+
clm.debug(`Found key file path in nodectl config file: ${nodeCtlKeyPath}`);
|
|
55
|
+
clm.step('Key file found at ' + chalk.cyan(nodeCtlKeyPath));
|
|
56
|
+
clm.preStep('Importing key file...');
|
|
57
|
+
const { projectDir } = configStore.getProjectInfo();
|
|
58
|
+
const pilotKeyPath = path.join(projectDir, 'key.p12');
|
|
59
|
+
// copy file to home directory, change owner to current user, and make it readable by all
|
|
60
|
+
clm.preStep('Making a sudo call to copy the key file...');
|
|
61
|
+
await shellService.runCommand(`sudo cp ${nodeCtlKeyPath} ${pilotKeyPath}; sudo chown $(whoami) ${pilotKeyPath}; chmod +r ${pilotKeyPath}`);
|
|
62
|
+
await this.promptForKeyFile(pilotKeyPath);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
console.error(error);
|
|
66
|
+
clm.warn('Failed to import key information from nodectl. You will need to import it manually.');
|
|
67
|
+
await promptHelper.doYouWishToContinue();
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
async promptForKeyFile(pilotKeyPath) {
|
|
71
|
+
// prompt for password
|
|
72
|
+
const keyPassword = await password({ message: 'Enter the key file password:' });
|
|
73
|
+
const keyAlias = await input({ message: 'Enter the key file alias:' });
|
|
74
|
+
configStore.setEnvInfo({ CL_KEYALIAS: keyAlias, CL_KEYSTORE: pilotKeyPath, CL_PASSWORD: keyPassword });
|
|
75
|
+
try {
|
|
76
|
+
const dagAddress = await keyFileHelper.getAddress();
|
|
77
|
+
const nodeId = await keyFileHelper.getId();
|
|
78
|
+
configStore.setProjectInfo({ dagAddress, nodeId });
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
clm.warn('Failed to unlock the key file. Please check your key file information and try again.');
|
|
82
|
+
fs.rmSync(pilotKeyPath);
|
|
83
|
+
await this.promptForKeyFile(pilotKeyPath);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
clm.postStep('Key file imported successfully.\n');
|
|
87
|
+
}
|
|
88
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import semver from "semver";
|
|
3
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
3
4
|
import { clm } from "../clm.js";
|
|
4
5
|
import { configStore } from "../config-store.js";
|
|
5
6
|
import { healthCheckConfig } from "../helpers/health-check-config.js";
|
|
@@ -8,7 +9,6 @@ import { promptHelper } from "../helpers/prompt-helper.js";
|
|
|
8
9
|
import { dockerService } from "../services/docker-service.js";
|
|
9
10
|
import { nodeService } from "../services/node-service.js";
|
|
10
11
|
import { shellService } from "../services/shell-service.js";
|
|
11
|
-
import { checkInitialSetup } from "./check-initial-setup.js";
|
|
12
12
|
const REGISTRY_URL = 'https://registry.npmjs.org/';
|
|
13
13
|
export const checkNodePilot = {
|
|
14
14
|
async checkDiscordRegistration() {
|
|
@@ -18,17 +18,6 @@ export const checkNodePilot = {
|
|
|
18
18
|
await this.promptDiscordRegistration();
|
|
19
19
|
configStore.setProjectFlag('discordChecked', true);
|
|
20
20
|
},
|
|
21
|
-
async checkMultipleUsers() {
|
|
22
|
-
if (configStore.hasProjectFlag('multipleUsersChecked')) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const { currentUser, otherUsers } = await checkInitialSetup.getExistingInstallations();
|
|
26
|
-
if (otherUsers.length > 0) {
|
|
27
|
-
clm.warn(`Multiple users have Node Pilot installed.\n ${currentUser} <-- current user\n ${otherUsers.join('\n ')}`);
|
|
28
|
-
clm.error('Login and run "cpilot uninstall" to remove the extra installation(s).');
|
|
29
|
-
}
|
|
30
|
-
configStore.setProjectFlag('multipleUsersChecked', true);
|
|
31
|
-
},
|
|
32
21
|
async checkVersion() {
|
|
33
22
|
const { currentVer, latestVer } = await this.compareVersions();
|
|
34
23
|
if (!latestVer || !currentVer || latestVer.compare(currentVer) === 0)
|
|
@@ -71,14 +60,13 @@ export const checkNodePilot = {
|
|
|
71
60
|
await shellService.runCommand(`sudo npm install -g @constellation-network/node-pilot@${latestVer.version}`);
|
|
72
61
|
if (hasMajorMinorChange) {
|
|
73
62
|
clm.step('Updating scripts and configuration files...');
|
|
74
|
-
projectHelper.upgradeHypergraph();
|
|
63
|
+
await projectHelper.upgradeHypergraph();
|
|
75
64
|
}
|
|
76
65
|
clm.postStep('Update completed. Run cpilot again to use the latest version');
|
|
77
66
|
process.exit(0);
|
|
78
67
|
},
|
|
79
68
|
async compareVersions() {
|
|
80
|
-
const
|
|
81
|
-
const packageUrl = new URL(encodeURIComponent(pilotReleaseName).replace(/^%40/, '@'), REGISTRY_URL);
|
|
69
|
+
const packageUrl = new URL(encodeURIComponent(packageJson.name).replace(/^%40/, '@'), REGISTRY_URL);
|
|
82
70
|
const headers = {
|
|
83
71
|
accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*',
|
|
84
72
|
};
|
|
@@ -86,24 +74,10 @@ export const checkNodePilot = {
|
|
|
86
74
|
if (!result) {
|
|
87
75
|
return { currentVer: undefined, latestVer: undefined };
|
|
88
76
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
else if (pilotVersion.includes('omegatest')) {
|
|
94
|
-
distTag = 'omegatest';
|
|
95
|
-
}
|
|
96
|
-
else if (pilotVersion.includes('intnet')) {
|
|
97
|
-
distTag = 'intnet';
|
|
98
|
-
}
|
|
99
|
-
const latestVer = semver.parse(result['dist-tags'][distTag]);
|
|
100
|
-
const currentVer = semver.parse(pilotVersion);
|
|
101
|
-
if (latestVer !== null && currentVer !== null) {
|
|
102
|
-
clm.debug(`Current version: ${currentVer?.version}, Latest version: ${latestVer?.version}`);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
clm.warn(`Unable to resolve version from dist-tag ${distTag} - ${JSON.stringify(result['dist-tags'])}`);
|
|
106
|
-
}
|
|
77
|
+
const { type } = configStore.getNetworkInfo();
|
|
78
|
+
const networkTag = type === 'testnet' ? 'testnet' : 'latest';
|
|
79
|
+
const latestVer = semver.parse(result['dist-tags'][networkTag]);
|
|
80
|
+
const currentVer = semver.parse(packageJson.version);
|
|
107
81
|
return { currentVer, latestVer };
|
|
108
82
|
},
|
|
109
83
|
isDiscordAlertsEnabled() {
|
|
@@ -143,7 +117,7 @@ export const checkNodePilot = {
|
|
|
143
117
|
const hasMajorMinorChange = latestVer.major !== currentVer.major || latestVer.minor !== currentVer.minor;
|
|
144
118
|
if (hasMajorMinorChange) {
|
|
145
119
|
clm.step('Updating scripts and configuration files...');
|
|
146
|
-
projectHelper.upgradeHypergraph();
|
|
120
|
+
await projectHelper.upgradeHypergraph();
|
|
147
121
|
}
|
|
148
122
|
}
|
|
149
123
|
};
|
|
@@ -12,9 +12,8 @@ import { shellService } from "../services/shell-service.js";
|
|
|
12
12
|
import { checkNetwork } from "./check-network.js";
|
|
13
13
|
function getJavaMemoryOptions(network, mem) {
|
|
14
14
|
if (network === 'testnet') {
|
|
15
|
-
const linuxOpt = (os.platform() === 'linux') ? ' -XX:+UseZGC
|
|
16
|
-
|
|
17
|
-
return `-Xms${mem}g -Xmx${mem}g${linuxOpt} -XX:+UseStringDeduplication --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED`;
|
|
15
|
+
const linuxOpt = (os.platform() === 'linux') ? ' -XX:+UseZGC' : '';
|
|
16
|
+
return `-Xms${mem}g -Xmx${mem}g -XX:+UnlockExperimentalVMOptions${linuxOpt} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heap_dumps/ -XX:+ExitOnOutOfMemoryError`;
|
|
18
17
|
}
|
|
19
18
|
return `-Xms1024M -Xmx${mem}g -Xss256K`;
|
|
20
19
|
}
|
|
@@ -63,7 +62,7 @@ export const checkProject = {
|
|
|
63
62
|
const network = type.toUpperCase();
|
|
64
63
|
const logMethod = type === currentNetwork ? clm.postStep : clm.debug;
|
|
65
64
|
logMethod(`${network}:: ${layersToRun[0]} memory allocation: ${mainLayerMem}GB`);
|
|
66
|
-
configStore.setEnvLayerInfo(type, layersToRun[0], { CL_DOCKER_JAVA_OPTS: getJavaMemoryOptions(
|
|
65
|
+
configStore.setEnvLayerInfo(type, layersToRun[0], { CL_DOCKER_JAVA_OPTS: getJavaMemoryOptions(currentNetwork, mainLayerMem) });
|
|
67
66
|
if (subLayerMem) {
|
|
68
67
|
logMethod(`${network}:: ${layersToRun[1]} memory allocation: ${subLayerMem}GB`);
|
|
69
68
|
configStore.setEnvLayerInfo(type, layersToRun[1], { CL_DOCKER_JAVA_OPTS: `-Xms1024M -Xmx${subLayerMem}G -Xss256K` });
|
package/dist/commands/config.js
CHANGED
|
@@ -25,7 +25,7 @@ export default class Config extends Command {
|
|
|
25
25
|
{ name: 'Java Memory', value: 'javaMemory' },
|
|
26
26
|
{ name: 'Key File', value: 'keyFile' },
|
|
27
27
|
{ name: 'Layers To Run', value: 'layersToRun' },
|
|
28
|
-
{ name: `
|
|
28
|
+
{ name: `Network`, value: 'network' },
|
|
29
29
|
],
|
|
30
30
|
message: 'What would you like to change?:',
|
|
31
31
|
});
|
package/dist/commands/info.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
2
3
|
import { checkNodePilot } from "../checks/check-pilot.js";
|
|
3
4
|
import { configStore } from "../config-store.js";
|
|
4
5
|
import { configHelper } from "../helpers/config-helper.js";
|
|
@@ -13,11 +14,10 @@ export default class Info extends Command {
|
|
|
13
14
|
const networkInfo = configStore.getNetworkInfo();
|
|
14
15
|
const { CL_EXTERNAL_IP: currentIpAddress } = configStore.getEnvInfo();
|
|
15
16
|
const { CL_DOCKER_JAVA_OPTS } = configStore.getEnvLayerInfo(networkInfo.type, 'gl0');
|
|
16
|
-
const { version } = configStore.getPilotReleaseInfo();
|
|
17
17
|
// Project Name
|
|
18
18
|
configHelper.showEnvInfo('Project Name', projectInfo.name);
|
|
19
19
|
// Pilot Version
|
|
20
|
-
configHelper.showEnvInfo('Node Pilot Version', version);
|
|
20
|
+
configHelper.showEnvInfo('Node Pilot Version', packageJson.version);
|
|
21
21
|
// External IP Address
|
|
22
22
|
configHelper.showEnvInfo('External IP Address', currentIpAddress);
|
|
23
23
|
// DAG Address
|
package/dist/commands/status.js
CHANGED
|
@@ -2,28 +2,31 @@ import { Command } from '@oclif/core';
|
|
|
2
2
|
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
|
+
import { checkNodeCtl } from "../checks/check-node-ctl.js";
|
|
5
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";
|
|
9
10
|
import { migrationService } from "../services/migration-service.js";
|
|
10
11
|
export default class Status extends Command {
|
|
12
|
+
// eslint-disable-next-line no-warning-comments
|
|
13
|
+
// TODO add -f flag to continuously monitor status
|
|
11
14
|
static description = 'Display node status and configuration settings';
|
|
12
15
|
async run() {
|
|
13
16
|
await checkInstallationAndConfigurationStatus();
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
export async function checkInstallationAndConfigurationStatus() {
|
|
20
|
+
await migrationService.runMigrations();
|
|
17
21
|
await checkInitialSetup.firstTimeRun();
|
|
18
|
-
await checkNodePilot.checkMultipleUsers();
|
|
19
22
|
await checkProject.projectInstallation();
|
|
20
|
-
await checkNodePilot.checkVersion();
|
|
21
|
-
migrationService.runMigrations();
|
|
22
23
|
await checkProject.checkJavaMemory();
|
|
23
24
|
await checkNetwork.checkExternalIpAddress();
|
|
24
25
|
await checkNetwork.isNetworkConnectable();
|
|
25
26
|
await checkNodePilot.checkDiscordRegistration();
|
|
27
|
+
await checkNodePilot.checkVersion();
|
|
26
28
|
await checkProject.releaseVersion();
|
|
29
|
+
await checkNodeCtl.check4Migration();
|
|
27
30
|
await keyFileHelper.promptIfNoKeyFile();
|
|
28
31
|
await checkNetwork.checkSeedList();
|
|
29
32
|
await checkNetwork.checkForExistingNodeIdInCluster();
|
package/dist/config-store.d.ts
CHANGED
|
@@ -12,10 +12,6 @@ declare class ConfigStore {
|
|
|
12
12
|
getEnvNetworkInfo(network: NetworkType): EnvNetworkInfo;
|
|
13
13
|
getLayerPortInfo(layer: TessellationLayer): PortInfo;
|
|
14
14
|
getNetworkInfo(): NetworkInfo;
|
|
15
|
-
getPilotReleaseInfo(): {
|
|
16
|
-
name: string;
|
|
17
|
-
version: string;
|
|
18
|
-
};
|
|
19
15
|
getProjectInfo(): ProjectInfo;
|
|
20
16
|
getProjects(): string[];
|
|
21
17
|
getRunningProjects(): string[];
|
package/dist/config-store.js
CHANGED
|
@@ -3,9 +3,7 @@ import { JSONStorage } from "node-localstorage";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import packageJson from '../package.json' with { type: 'json' };
|
|
7
6
|
import { clm } from "./clm.js";
|
|
8
|
-
const pilotReleaseInfo = { name: packageJson.name, version: packageJson.version };
|
|
9
7
|
class EmptyStorage extends JSONStorage {
|
|
10
8
|
constructor() { super("/tmp"); }
|
|
11
9
|
getItem(_key) { return null; }
|
|
@@ -84,9 +82,6 @@ class ConfigStore {
|
|
|
84
82
|
getNetworkInfo() {
|
|
85
83
|
return this.projectStore.getItem('network');
|
|
86
84
|
}
|
|
87
|
-
getPilotReleaseInfo() {
|
|
88
|
-
return pilotReleaseInfo;
|
|
89
|
-
}
|
|
90
85
|
getProjectInfo() {
|
|
91
86
|
return this.projectStore.getItem('project') || {};
|
|
92
87
|
}
|
|
@@ -9,7 +9,7 @@ export declare const projectHelper: {
|
|
|
9
9
|
installProject(name: string, projectFolder: string): Promise<void>;
|
|
10
10
|
prepareDataFolder(): void;
|
|
11
11
|
selectProject(): Promise<void>;
|
|
12
|
-
upgradeEmbedded(name: string): void
|
|
13
|
-
upgradeHypergraph(): void
|
|
14
|
-
upgradeProject(name: string, projectFolder: string): void
|
|
12
|
+
upgradeEmbedded(name: string): Promise<void>;
|
|
13
|
+
upgradeHypergraph(): Promise<void>;
|
|
14
|
+
upgradeProject(name: string, projectFolder: string): Promise<void>;
|
|
15
15
|
};
|
|
@@ -79,8 +79,6 @@ export const projectHelper = {
|
|
|
79
79
|
clm.error(`Project folder not found: ${projectFolder}`);
|
|
80
80
|
}
|
|
81
81
|
await this.installProject(name, projectFolder);
|
|
82
|
-
// Set the project version to match the latest Pilot version. This prevents previous migration scripts from running.
|
|
83
|
-
configStore.setProjectInfo({ version: configStore.getPilotReleaseInfo().version });
|
|
84
82
|
},
|
|
85
83
|
// curl -s https://api.github.com/repos/Constellation-Labs/pacaswap-metagraph/releases/latest | jq -r '.assets[] | select(.name | contains("node-pilot"))'
|
|
86
84
|
// use .tag_name for the release version
|
|
@@ -89,15 +87,14 @@ export const projectHelper = {
|
|
|
89
87
|
},
|
|
90
88
|
async installHypergraph() {
|
|
91
89
|
await this.installEmbedded('hypergraph');
|
|
90
|
+
const { projectDir } = configStore.getProjectInfo();
|
|
91
|
+
const { platform } = configStore.getSystemInfo();
|
|
92
92
|
this.prepareDataFolder();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// // set permission for group "docker" on the layer folder and any subfolders created later
|
|
99
|
-
// await shellService.runCommand(`sudo setfacl -Rm g:docker:rwX -dm g:docker:rwX ${layerDir}`)
|
|
100
|
-
// }
|
|
93
|
+
if (platform === 'linux') {
|
|
94
|
+
const layerDir = path.join(projectDir, 'gl0');
|
|
95
|
+
// set permission for group "docker" on the layer folder and any subfolders created later
|
|
96
|
+
await shellService.runCommand(`sudo setfacl -Rm g:docker:rwX -dm g:docker:rwX ${layerDir}`);
|
|
97
|
+
}
|
|
101
98
|
this.importEnvFiles();
|
|
102
99
|
},
|
|
103
100
|
async installProject(name, projectFolder) {
|
|
@@ -173,18 +170,18 @@ export const projectHelper = {
|
|
|
173
170
|
}
|
|
174
171
|
}
|
|
175
172
|
},
|
|
176
|
-
upgradeEmbedded(name) {
|
|
173
|
+
async upgradeEmbedded(name) {
|
|
177
174
|
const projectFolder = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../projects/${name}`);
|
|
178
175
|
if (!fs.existsSync(projectFolder)) {
|
|
179
176
|
clm.error(`Project folder not found: ${projectFolder}`);
|
|
180
177
|
}
|
|
181
|
-
this.upgradeProject(name, projectFolder);
|
|
178
|
+
await this.upgradeProject(name, projectFolder);
|
|
182
179
|
},
|
|
183
|
-
upgradeHypergraph() {
|
|
184
|
-
this.upgradeEmbedded('hypergraph');
|
|
180
|
+
async upgradeHypergraph() {
|
|
181
|
+
await this.upgradeEmbedded('hypergraph');
|
|
185
182
|
this.importEnvFiles();
|
|
186
183
|
},
|
|
187
|
-
upgradeProject(name, projectFolder) {
|
|
184
|
+
async upgradeProject(name, projectFolder) {
|
|
188
185
|
const { projectDir } = configStore.getProjectInfo();
|
|
189
186
|
clm.debug(`Upgrading project from ${projectFolder} to ${projectDir}`);
|
|
190
187
|
fs.cpSync(projectFolder, projectDir, { recursive: true });
|
|
@@ -5,6 +5,7 @@ import 'json-bigint-patch';
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { clm } from "../clm.js";
|
|
7
7
|
import { configStore } from "../config-store.js";
|
|
8
|
+
import { promptHelper } from "../helpers/prompt-helper.js";
|
|
8
9
|
import { shellService } from "./shell-service.js";
|
|
9
10
|
const CHUNK_SIZE = 20_000;
|
|
10
11
|
export class FastforwardService {
|
|
@@ -27,14 +28,14 @@ export class FastforwardService {
|
|
|
27
28
|
const ffs = new FastforwardService();
|
|
28
29
|
await ffs.runFastForwardSnapshot().catch(async (error) => {
|
|
29
30
|
clm.debug(error);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
clm.error('Failed to fast forward to latest snapshot. Please try again later
|
|
31
|
+
const { projectDir } = configStore.getProjectInfo();
|
|
32
|
+
const dataDir = path.join(projectDir, 'gl0', 'data', 'incremental_snapshot', 'ordinal');
|
|
33
|
+
if (fs.existsSync(dataDir) && fs.readdirSync(dataDir).length > 0) {
|
|
34
|
+
clm.warn('Failed to fast forward to latest snapshot. Skipping...');
|
|
35
|
+
await promptHelper.doYouWishToContinue();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
clm.error('Failed to fast forward to latest snapshot. Please try again later.');
|
|
38
39
|
});
|
|
39
40
|
}
|
|
40
41
|
async runFastForwardSnapshot() {
|
|
@@ -1,48 +1,50 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import semver from "semver";
|
|
3
|
+
import packageJson from '../../package.json' with { type: 'json' };
|
|
2
4
|
import { clm } from "../clm.js";
|
|
3
5
|
import { configStore } from "../config-store.js";
|
|
6
|
+
import { shellService } from "./shell-service.js";
|
|
4
7
|
export const migrationService = {
|
|
5
|
-
runMigrations() {
|
|
8
|
+
async runMigrations() {
|
|
6
9
|
const migrations = {
|
|
7
|
-
'0.
|
|
10
|
+
// '0.8.0': m080,
|
|
11
|
+
'0.12.3': m0123,
|
|
8
12
|
// add more migrations as needed
|
|
9
13
|
};
|
|
10
14
|
const { version = '0.0.0' } = configStore.getProjectInfo();
|
|
11
|
-
const { version: pilotVersion } = configStore.getPilotReleaseInfo();
|
|
12
15
|
const lastMigratedVersion = semver.parse(version);
|
|
13
|
-
const currentVersion = semver.parse(
|
|
16
|
+
const currentVersion = semver.parse(packageJson.version);
|
|
14
17
|
if (!lastMigratedVersion || !currentVersion) {
|
|
15
18
|
return;
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
// console.log(`Running migrations from ${lastMigratedVersion.version} to ${currentVersion.version}`);
|
|
21
|
+
// console.log(`semver.gt(v, version): ${semver.gt('0.8.0', version)}`);
|
|
22
|
+
// console.log(`semver.lte(v, currentVersion.version): ${semver.lte('0.8.0', currentVersion.version)}`)
|
|
20
23
|
const migrationVersions = Object.keys(migrations)
|
|
21
24
|
.filter(v => semver.gt(v, version) && semver.lte(v, currentVersion.version))
|
|
22
25
|
.sort(semver.compare);
|
|
23
26
|
if (migrationVersions.length > 0) {
|
|
24
27
|
clm.preStep(`Migration versions to run: ${migrationVersions}`);
|
|
25
28
|
for (const version of migrationVersions) {
|
|
26
|
-
|
|
29
|
+
// eslint-disable-next-line no-await-in-loop
|
|
30
|
+
await migrations[version]();
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
configStore.setProjectInfo({ version: currentVersion.toString() });
|
|
30
34
|
}
|
|
31
35
|
};
|
|
32
|
-
function
|
|
33
|
-
clm.step('Running migration 0.12.
|
|
34
|
-
configStore.
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
async function m0123() {
|
|
37
|
+
clm.step('Running migration 0.12.3...');
|
|
38
|
+
const netInfo = configStore.getNetworkInfo();
|
|
39
|
+
if (netInfo && netInfo.type === 'integrationnet') {
|
|
40
|
+
clm.preStep('Installing Node Pilot IntegrationNet version...');
|
|
41
|
+
await shellService.runCommand('sudo npm install -g @constellation-network/node-pilot@intnet');
|
|
42
|
+
clm.postStep('IntegrationNet version installed successfully.');
|
|
43
|
+
clm.warn(`Run ${chalk.cyanBright('cpilot')} again to start using the IntegrationNet version.`);
|
|
44
|
+
process.exit(0);
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
|
-
// function
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
// const result = shell.exec('bash install-java-21.sh', {cwd: pilotDir});
|
|
43
|
-
//
|
|
44
|
-
// if (result.code > 0) {
|
|
45
|
-
// console.log(result.stderr);
|
|
46
|
-
// clm.error(`Failed to install dependencies. Please try again after resolving any errors.`);
|
|
47
|
-
// }
|
|
47
|
+
// async function m080() {
|
|
48
|
+
// clm.step('Running migration 0.8.0...');
|
|
49
|
+
// configStore.setProjectFlag('javaMemoryChecked', false);
|
|
48
50
|
// }
|
|
@@ -7,7 +7,7 @@ import { configStore } from "../config-store.js";
|
|
|
7
7
|
export const shellService = {
|
|
8
8
|
async checkCommandAvailable(cmd) {
|
|
9
9
|
clm.debug(`Checking if command ${cmd} is available...`);
|
|
10
|
-
return this.runCommand(`command -v ${cmd}
|
|
10
|
+
return this.runCommand(`command -v ${cmd}`)
|
|
11
11
|
.then(() => true)
|
|
12
12
|
.catch((error) => {
|
|
13
13
|
clm.debug(`Run command error: ${error}`);
|
|
@@ -16,9 +16,8 @@ export const shellService = {
|
|
|
16
16
|
},
|
|
17
17
|
async execDockerShell(serviceName, command) {
|
|
18
18
|
const { projectDir } = configStore.getProjectInfo();
|
|
19
|
-
const silent = process.env.DEBUG !== 'true';
|
|
20
19
|
clm.debug(`Running command: docker compose exec ${serviceName} bash -c "${command}"`);
|
|
21
|
-
const result = shell.exec(`docker compose exec ${serviceName} bash -c "${command}"`, { cwd: projectDir, silent });
|
|
20
|
+
const result = shell.exec(`docker compose exec ${serviceName} bash -c "${command}"`, { cwd: projectDir, silent: true });
|
|
22
21
|
if (result.stderr && result.code > 0) {
|
|
23
22
|
clm.warn(`Command Failed - ${command} with stderr: ${result.stderr}`);
|
|
24
23
|
throw new Error(`Command Failed - ${command} with stderr: ${result.stderr}`);
|
|
@@ -47,15 +46,13 @@ export const shellService = {
|
|
|
47
46
|
const result = shell.exec(command, { env: nodeEnv, silent });
|
|
48
47
|
clm.debug(`END ${command}. Exit code: ${result.code}`);
|
|
49
48
|
if (result.code > 0) {
|
|
50
|
-
throw new Error(`Failed running command
|
|
49
|
+
throw new Error(`Failed running command: ${result.stderr}`);
|
|
51
50
|
}
|
|
52
51
|
return result;
|
|
53
52
|
},
|
|
54
53
|
async runCommandWithOutput(command, env) {
|
|
55
54
|
const result = await this.runCommand(command, env, true);
|
|
56
|
-
|
|
57
|
-
clm.debug(`Command Output: "${output}"`);
|
|
58
|
-
return output;
|
|
55
|
+
return result.stdout.trim();
|
|
59
56
|
},
|
|
60
57
|
async runProjectCommand(command, env, silent = false) {
|
|
61
58
|
const { projectDir } = configStore.getProjectInfo();
|
|
@@ -63,7 +60,7 @@ export const shellService = {
|
|
|
63
60
|
if (env) {
|
|
64
61
|
nodeEnv = { ...env, ...process.env };
|
|
65
62
|
}
|
|
66
|
-
clm.debug(`START Running command: "${command}" in directory: "${projectDir}"`);
|
|
63
|
+
clm.debug(`START Running command: "${command}" in directory: "${projectDir}"`);
|
|
67
64
|
return new Promise((resolve, reject) => {
|
|
68
65
|
shell.exec(command, { async: true, cwd: projectDir, env: nodeEnv, silent }, (code, stdout, stderr) => {
|
|
69
66
|
if (code === 0) {
|
|
@@ -1,35 +1,22 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { fileURLToPath } from "node:url";
|
|
5
4
|
import { clm } from "../clm.js";
|
|
5
|
+
import { configStore } from "../config-store.js";
|
|
6
6
|
import { shellService } from "./shell-service.js";
|
|
7
7
|
export const systemdService = {
|
|
8
8
|
async install() {
|
|
9
|
-
const platform =
|
|
9
|
+
const { platform } = configStore.getSystemInfo();
|
|
10
10
|
if (platform !== 'linux') {
|
|
11
11
|
clm.warn('Node Pilot services can only be installed on Linux systems. Skipping systemd service installation.\n');
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
-
const
|
|
15
|
-
if (!fs.existsSync(
|
|
16
|
-
clm.error(`Node Pilot install system services script not found: ${
|
|
14
|
+
const installServicesScript = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../scripts/install_services.sh`);
|
|
15
|
+
if (!fs.existsSync(installServicesScript)) {
|
|
16
|
+
clm.error(`Node Pilot install system services script not found: ${installServicesScript}`);
|
|
17
17
|
}
|
|
18
18
|
clm.preStep('Installing Node Pilot system services...');
|
|
19
|
-
await shellService.runCommand(
|
|
19
|
+
await shellService.runCommand(installServicesScript);
|
|
20
20
|
clm.postStep('\nNode Pilot system service started successfully.');
|
|
21
|
-
},
|
|
22
|
-
async uninstall() {
|
|
23
|
-
const platform = os.platform();
|
|
24
|
-
if (platform !== 'linux') {
|
|
25
|
-
clm.warn('Node Pilot services can only be installed on Linux systems. Skipping systemd service uninstallation.\n');
|
|
26
|
-
}
|
|
27
|
-
const scriptFile = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../scripts/uninstall_services.sh`);
|
|
28
|
-
if (!fs.existsSync(scriptFile)) {
|
|
29
|
-
clm.error(`Node Pilot uninstall system services script not found: ${scriptFile}`);
|
|
30
|
-
}
|
|
31
|
-
clm.preStep('Uninstalling Node Pilot system services...');
|
|
32
|
-
await shellService.runCommand(scriptFile);
|
|
33
|
-
clm.postStep('\nNode Pilot system service uninstalled successfully.');
|
|
34
21
|
}
|
|
35
22
|
};
|
package/install-dependencies.sh
CHANGED
package/oclif.manifest.json
CHANGED
|
@@ -272,29 +272,6 @@
|
|
|
272
272
|
"test.js"
|
|
273
273
|
]
|
|
274
274
|
},
|
|
275
|
-
"uninstall": {
|
|
276
|
-
"aliases": [],
|
|
277
|
-
"args": {},
|
|
278
|
-
"description": "Uninstall Node Pilot",
|
|
279
|
-
"examples": [
|
|
280
|
-
"<%= config.bin %> <%= command.id %>"
|
|
281
|
-
],
|
|
282
|
-
"flags": {},
|
|
283
|
-
"hasDynamicHelp": false,
|
|
284
|
-
"hiddenAliases": [],
|
|
285
|
-
"id": "uninstall",
|
|
286
|
-
"pluginAlias": "@constellation-network/node-pilot",
|
|
287
|
-
"pluginName": "@constellation-network/node-pilot",
|
|
288
|
-
"pluginType": "core",
|
|
289
|
-
"strict": true,
|
|
290
|
-
"enableJsonFlag": false,
|
|
291
|
-
"isESM": true,
|
|
292
|
-
"relativePath": [
|
|
293
|
-
"dist",
|
|
294
|
-
"commands",
|
|
295
|
-
"uninstall.js"
|
|
296
|
-
]
|
|
297
|
-
},
|
|
298
275
|
"config:get": {
|
|
299
276
|
"aliases": [],
|
|
300
277
|
"args": {
|
|
@@ -363,5 +340,5 @@
|
|
|
363
340
|
]
|
|
364
341
|
}
|
|
365
342
|
},
|
|
366
|
-
"version": "0.13.
|
|
343
|
+
"version": "0.13.2"
|
|
367
344
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constellation-network/node-pilot",
|
|
3
3
|
"description": "An easy deployment and monitoring tool for Constellation nodes.",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.2",
|
|
5
5
|
"author": "Frank Fox",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cpilot": "bin/run.js"
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"version": "oclif readme && git add README.md",
|
|
22
22
|
"start": "./bin/dev.js",
|
|
23
23
|
"debug": "DEBUG=true ./bin/dev.js",
|
|
24
|
-
"pub": "npm publish --access public
|
|
24
|
+
"pub": "npm publish --access public"
|
|
25
25
|
},
|
|
26
26
|
"types": "dist/index.d.ts",
|
|
27
27
|
"engines": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
FROM ubuntu:22.04
|
|
2
2
|
|
|
3
|
-
RUN apt update && apt install -y openjdk-
|
|
3
|
+
RUN apt update && apt install -y openjdk-11-jre
|
|
4
4
|
|
|
5
5
|
RUN apt install -y curl jq wget
|
|
6
6
|
|
|
@@ -39,7 +39,7 @@ COPY dist/gl0.jar /app/jars/gl0.jar
|
|
|
39
39
|
#COPY ./health-check /health-check
|
|
40
40
|
#RUN chmod +x /health-check/bin/run.sh
|
|
41
41
|
#RUN chmod +x /health-check/bin/hydrate.sh
|
|
42
|
-
RUN npm install -g "@constellation-network/node-pilot-health-check@0.0.
|
|
42
|
+
RUN npm install -g "@constellation-network/node-pilot-health-check@0.0.26"
|
|
43
43
|
|
|
44
44
|
# Add entrypoint
|
|
45
45
|
COPY ./entrypoint.sh /app/entrypoint.sh
|
|
@@ -8,7 +8,7 @@ services:
|
|
|
8
8
|
# volumes:
|
|
9
9
|
# - /var/run/docker.sock:/var/run/docker.sock
|
|
10
10
|
gl0:
|
|
11
|
-
image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-
|
|
11
|
+
image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-latest}
|
|
12
12
|
networks:
|
|
13
13
|
- tessellation-network
|
|
14
14
|
restart: unless-stopped
|
|
@@ -26,14 +26,14 @@ services:
|
|
|
26
26
|
test: ["CMD", "cpilotHC"]
|
|
27
27
|
# test: ["CMD", "/health-check/bin/run.sh"]
|
|
28
28
|
interval: 15s
|
|
29
|
-
retries:
|
|
29
|
+
retries: 1
|
|
30
30
|
timeout: 15s
|
|
31
31
|
start_period: 60s
|
|
32
32
|
profiles: ["gl0"]
|
|
33
33
|
# labels:
|
|
34
34
|
# autoheal: "true"
|
|
35
35
|
gl1:
|
|
36
|
-
image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-
|
|
36
|
+
image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-latest}
|
|
37
37
|
restart: unless-stopped
|
|
38
38
|
networks:
|
|
39
39
|
- tessellation-network
|
|
@@ -50,7 +50,7 @@ services:
|
|
|
50
50
|
test: ["CMD", "cpilotHC"]
|
|
51
51
|
# test: ["CMD", "/health-check/bin/run.sh"]
|
|
52
52
|
interval: 15s
|
|
53
|
-
retries:
|
|
53
|
+
retries: 1
|
|
54
54
|
timeout: 15s
|
|
55
55
|
start_period: 60s
|
|
56
56
|
profiles: ["gl1"]
|
|
@@ -3,6 +3,6 @@ CL_COLLATERAL=25000000000000
|
|
|
3
3
|
CL_L0_PEER_HTTP_PORT=9000
|
|
4
4
|
CL_L0_PEER_HTTP_HOST=52.53.46.33
|
|
5
5
|
CL_L0_PEER_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
|
|
6
|
-
CL_GLOBAL_L0_PEER_HTTP_PORT=9000
|
|
7
|
-
CL_GLOBAL_L0_PEER_HOST=52.53.46.33
|
|
8
|
-
CL_GLOBAL_L0_PEER_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
|
|
6
|
+
#CL_GLOBAL_L0_PEER_HTTP_PORT=9000
|
|
7
|
+
#CL_GLOBAL_L0_PEER_HOST=52.53.46.33
|
|
8
|
+
#CL_GLOBAL_L0_PEER_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
|
|
@@ -3,6 +3,6 @@ CL_COLLATERAL=0
|
|
|
3
3
|
CL_L0_PEER_HTTP_PORT=9000
|
|
4
4
|
CL_L0_PEER_HTTP_HOST=52.8.132.193
|
|
5
5
|
CL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
|
|
6
|
-
CL_GLOBAL_L0_PEER_HTTP_PORT=9000
|
|
7
|
-
CL_GLOBAL_L0_PEER_HOST=52.8.132.193
|
|
8
|
-
CL_GLOBAL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
|
|
6
|
+
#CL_GLOBAL_L0_PEER_HTTP_PORT=9000
|
|
7
|
+
#CL_GLOBAL_L0_PEER_HOST=52.8.132.193
|
|
8
|
+
#CL_GLOBAL_L0_PEER_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
|
|
@@ -21,57 +21,57 @@ check_java_home() {
|
|
|
21
21
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
# Check and install Java
|
|
24
|
+
# Check and install Java 11
|
|
25
25
|
check_java() {
|
|
26
|
-
# echo "Checking for Java
|
|
26
|
+
# echo "Checking for Java 11..."
|
|
27
27
|
if command -v java >/dev/null 2>&1; then
|
|
28
28
|
java_version=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
|
|
29
29
|
# echo "Found Java version: $java_version"
|
|
30
|
-
if [[ "$java_version" ==
|
|
31
|
-
echo "✅ Java
|
|
30
|
+
if [[ "$java_version" == 11* ]] || [[ "$java_version" == 1.11* ]]; then
|
|
31
|
+
echo "✅ Java 11 is installed."
|
|
32
32
|
return 0
|
|
33
33
|
else
|
|
34
|
-
echo "⚠️ Java is installed but not version
|
|
34
|
+
echo "⚠️ Java is installed but not version 11. Will attempt to install Java 11."
|
|
35
35
|
fi
|
|
36
36
|
else
|
|
37
|
-
echo "⚠️ Java not found. Will attempt to install Java
|
|
37
|
+
echo "⚠️ Java not found. Will attempt to install Java 11."
|
|
38
38
|
fi
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
case "$(uname)" in
|
|
42
42
|
Linux)
|
|
43
43
|
if command -v apt >/dev/null 2>&1; then
|
|
44
|
-
echo "Installing Java
|
|
45
|
-
sudo apt install -y openjdk-
|
|
44
|
+
echo "Installing Java 11 using apt..."
|
|
45
|
+
sudo apt install -y openjdk-11-jdk
|
|
46
46
|
elif command -v yum >/dev/null 2>&1; then
|
|
47
|
-
echo "Installing Java
|
|
48
|
-
sudo yum install -y java-
|
|
47
|
+
echo "Installing Java 11 using yum..."
|
|
48
|
+
sudo yum install -y java-11-openjdk-devel
|
|
49
49
|
else
|
|
50
|
-
echo "⚠️ Unsupported Linux distribution. Please install Java
|
|
50
|
+
echo "⚠️ Unsupported Linux distribution. Please install Java 11 manually."
|
|
51
51
|
return 1
|
|
52
52
|
fi
|
|
53
53
|
;;
|
|
54
54
|
Darwin)
|
|
55
55
|
if command -v brew >/dev/null 2>&1; then
|
|
56
|
-
echo "Installing Java
|
|
56
|
+
echo "Installing Java 11 using Homebrew..."
|
|
57
57
|
brew tap adoptopenjdk/openjdk
|
|
58
|
-
brew install --cask
|
|
58
|
+
brew install --cask adoptopenjdk11
|
|
59
59
|
else
|
|
60
|
-
echo "⚠️ Homebrew not found. Please install Java
|
|
60
|
+
echo "⚠️ Homebrew not found. Please install Java 11 manually."
|
|
61
61
|
return 1
|
|
62
62
|
fi
|
|
63
63
|
;;
|
|
64
64
|
MINGW*|MSYS*|CYGWIN*)
|
|
65
|
-
echo "On Windows, please install Java
|
|
65
|
+
echo "On Windows, please install Java 11 manually from https://adoptopenjdk.net/"
|
|
66
66
|
return 1
|
|
67
67
|
;;
|
|
68
68
|
*)
|
|
69
|
-
echo "⚠️ Unsupported OS: $(uname). Please install Java
|
|
69
|
+
echo "⚠️ Unsupported OS: $(uname). Please install Java 11 manually."
|
|
70
70
|
return 1
|
|
71
71
|
;;
|
|
72
72
|
esac
|
|
73
|
-
|
|
74
|
-
echo "✅ Java
|
|
73
|
+
|
|
74
|
+
echo "✅ Java 11 installation complete."
|
|
75
75
|
return 0
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
set -Eeuo pipefail
|
|
3
|
-
IFS=$'\n\t'
|
|
4
2
|
|
|
5
3
|
# Find cpilot in PATH
|
|
6
4
|
CPILOT=$(command -v cpilot)
|
|
@@ -18,7 +16,7 @@ if [ "$CURRENT_USER" = "root" ]; then
|
|
|
18
16
|
UNIT_TARGET="multi-user.target"
|
|
19
17
|
else
|
|
20
18
|
IS_ROOT=false
|
|
21
|
-
HOME_DIR=$(eval echo
|
|
19
|
+
HOME_DIR=$(eval echo ~$CURRENT_USER)
|
|
22
20
|
WORKING_DIR="$HOME_DIR/.config/systemd/user"
|
|
23
21
|
UNIT_TARGET="default.target"
|
|
24
22
|
fi
|
|
@@ -26,13 +24,9 @@ fi
|
|
|
26
24
|
BIN_DIRECTORY="$HOME_DIR/.node-pilot/scripts"
|
|
27
25
|
|
|
28
26
|
mkdir -p "$BIN_DIRECTORY"
|
|
29
|
-
mkdir -p "$WORKING_DIR"
|
|
30
27
|
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
echo "restart-unhealthy.service already exists in $WORKING_DIR. Skipping installation."
|
|
34
|
-
exit 0
|
|
35
|
-
fi
|
|
28
|
+
# Create working directory if it doesn't exist
|
|
29
|
+
mkdir -p "$WORKING_DIR"
|
|
36
30
|
|
|
37
31
|
# Create restart-unhealthy.service
|
|
38
32
|
cat << EOF > "$WORKING_DIR/restart-unhealthy.service"
|
|
@@ -67,6 +61,7 @@ cat << EOF > "$BIN_DIRECTORY/restart-unhealthy.sh"
|
|
|
67
61
|
#!/usr/bin/env bash
|
|
68
62
|
docker ps -q -f health=unhealthy | xargs --no-run-if-empty docker restart
|
|
69
63
|
EOF
|
|
64
|
+
|
|
70
65
|
chmod +x "$BIN_DIRECTORY/restart-unhealthy.sh"
|
|
71
66
|
|
|
72
67
|
# Create node-pilot-autostart.service
|
|
@@ -121,4 +116,4 @@ else
|
|
|
121
116
|
loginctl enable-linger "$CURRENT_USER"
|
|
122
117
|
fi
|
|
123
118
|
#systemctl --user status node-pilot-update.service
|
|
124
|
-
# systemctl --user status restart-unhealthy
|
|
119
|
+
# systemctl --user status restart-unhealthy
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import { clm } from "../clm.js";
|
|
5
|
-
import { promptHelper } from "../helpers/prompt-helper.js";
|
|
6
|
-
import { shellService } from "../services/shell-service.js";
|
|
7
|
-
import { systemdService } from "../services/systemd-service.js";
|
|
8
|
-
export default class Uninstall extends Command {
|
|
9
|
-
static description = 'Uninstall Node Pilot';
|
|
10
|
-
static examples = [
|
|
11
|
-
'<%= config.bin %> <%= command.id %>',
|
|
12
|
-
];
|
|
13
|
-
async run() {
|
|
14
|
-
const user = os.userInfo().username;
|
|
15
|
-
clm.warn(`You are about to uninstall Node Pilot for ${chalk.cyan(user)}.\nThis will also remove all the data and logs from your validator node.`);
|
|
16
|
-
await promptHelper.doYouWishToContinue();
|
|
17
|
-
clm.preStep('Uninstalling Node Pilot...');
|
|
18
|
-
await systemdService.uninstall();
|
|
19
|
-
const homeDir = os.homedir();
|
|
20
|
-
const nodePilotDir = `${homeDir}/.node-pilot`;
|
|
21
|
-
await shellService.runCommand(`sudo rm -rf ${nodePilotDir}`);
|
|
22
|
-
console.log(`Node Pilot uninstalled successfully for ${chalk.cyan(user)}.`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
# Uninstall Node Pilot systemctl services and timers
|
|
4
|
-
|
|
5
|
-
CURRENT_USER=$(id -un)
|
|
6
|
-
if [ "$CURRENT_USER" = "root" ]; then
|
|
7
|
-
IS_ROOT=true
|
|
8
|
-
WORKING_DIR="/etc/systemd/system"
|
|
9
|
-
else
|
|
10
|
-
IS_ROOT=false
|
|
11
|
-
HOME_DIR=$(eval echo ~$CURRENT_USER)
|
|
12
|
-
WORKING_DIR="$HOME_DIR/.config/systemd/user"
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
SERVICES=(restart-unhealthy.timer restart-unhealthy.service node-pilot-autostart.service node-pilot-update.service)
|
|
16
|
-
|
|
17
|
-
if [ "$IS_ROOT" = true ]; then
|
|
18
|
-
for SERVICE in "${SERVICES[@]}"; do
|
|
19
|
-
systemctl stop "$SERVICE" 2>/dev/null
|
|
20
|
-
systemctl disable "$SERVICE" 2>/dev/null
|
|
21
|
-
rm -f "$WORKING_DIR/$SERVICE"
|
|
22
|
-
echo "$SERVICE uninstalled."
|
|
23
|
-
done
|
|
24
|
-
systemctl daemon-reload
|
|
25
|
-
else
|
|
26
|
-
for SERVICE in "${SERVICES[@]}"; do
|
|
27
|
-
systemctl --user stop "$SERVICE" 2>/dev/null
|
|
28
|
-
systemctl --user disable "$SERVICE" 2>/dev/null
|
|
29
|
-
rm -f "$WORKING_DIR/$SERVICE"
|
|
30
|
-
echo "$SERVICE uninstalled ($CURRENT_USER)."
|
|
31
|
-
done
|
|
32
|
-
systemctl --user daemon-reload
|
|
33
|
-
# Optionally disable linger (uncomment if needed)
|
|
34
|
-
loginctl disable-linger "$CURRENT_USER"
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
echo "Node Pilot services and timers have been uninstalled."
|