@constellation-network/node-pilot 0.0.7 → 0.0.9
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 +26 -18
- package/bin/dev.js +1 -6
- package/bin/run.js +1 -1
- package/dist/base-command.d.ts +9 -0
- package/dist/base-command.js +20 -0
- package/dist/checks/check-dependencies.d.ts +1 -0
- package/dist/checks/check-dependencies.js +44 -0
- package/dist/checks/check-hardware.js +3 -3
- package/dist/checks/check-initial-setup.js +6 -4
- package/dist/checks/check-layers.js +7 -7
- package/dist/checks/check-network.d.ts +3 -0
- package/dist/checks/check-network.js +92 -9
- package/dist/checks/check-node-ctl.d.ts +5 -0
- package/dist/checks/check-node-ctl.js +88 -0
- package/dist/checks/check-project.js +33 -13
- package/dist/checks/check-wallet.d.ts +3 -0
- package/dist/checks/check-wallet.js +37 -0
- package/dist/clm.d.ts +1 -0
- package/dist/clm.js +4 -1
- package/dist/commands/config/get.d.ts +6 -0
- package/dist/commands/config/get.js +57 -11
- package/dist/commands/config/set.d.ts +0 -1
- package/dist/commands/config/set.js +13 -11
- package/dist/commands/config.js +17 -22
- package/dist/commands/info.js +3 -2
- package/dist/commands/logs.d.ts +2 -1
- package/dist/commands/logs.js +12 -6
- package/dist/commands/restart.d.ts +5 -2
- package/dist/commands/restart.js +25 -5
- package/dist/commands/shutdown.js +3 -3
- package/dist/commands/status.js +8 -0
- package/dist/commands/test.d.ts +1 -0
- package/dist/commands/test.js +35 -5
- package/dist/config-store.d.ts +50 -34
- package/dist/config-store.js +80 -32
- package/dist/helpers/config-helper.js +2 -2
- package/dist/helpers/env-templates.d.ts +4 -3
- package/dist/helpers/env-templates.js +28 -20
- package/dist/helpers/key-file-helper.d.ts +2 -0
- package/dist/helpers/key-file-helper.js +52 -17
- package/dist/helpers/project-helper.d.ts +3 -2
- package/dist/helpers/project-helper.js +86 -35
- package/dist/helpers/prompt-helper.d.ts +0 -2
- package/dist/helpers/prompt-helper.js +15 -66
- package/dist/services/archiver-service.d.ts +17 -0
- package/dist/services/archiver-service.js +104 -0
- package/dist/services/cluster-service.d.ts +10 -5
- package/dist/services/cluster-service.js +46 -36
- package/dist/services/docker-service.d.ts +9 -0
- package/dist/services/docker-service.js +53 -0
- package/dist/services/fastforward-service.js +12 -6
- package/dist/services/get-random-node.d.ts +2 -0
- package/dist/services/get-random-node.js +16 -0
- package/dist/{helpers/github-helper.d.ts → services/github-service.d.ts} +1 -1
- package/dist/{helpers/github-helper.js → services/github-service.js} +1 -1
- package/dist/services/node-service.d.ts +4 -0
- package/dist/services/node-service.js +29 -14
- package/dist/services/shell-service.d.ts +3 -1
- package/dist/services/shell-service.js +32 -6
- package/dist/test.d.ts +1 -0
- package/dist/test.js +50 -0
- package/dist/types.d.ts +42 -3
- package/install-dependencies.sh +98 -0
- package/oclif.manifest.json +31 -4
- package/package.json +12 -8
- package/projects/hypergraph/Dockerfile +27 -18
- package/projects/hypergraph/docker-compose.yml +14 -12
- package/projects/hypergraph/networks/integrationnet/gl0.env +4 -0
- package/projects/hypergraph/networks/integrationnet/gl1.env +4 -0
- package/projects/hypergraph/networks/integrationnet/network.env +8 -0
- package/projects/hypergraph/networks/integrationnet/source-nodes.env +9 -0
- package/projects/hypergraph/networks/mainnet/gl0.env +4 -0
- package/projects/hypergraph/networks/mainnet/gl1.env +4 -0
- package/projects/hypergraph/networks/mainnet/network.env +8 -0
- package/projects/hypergraph/networks/mainnet/source-nodes.env +9 -0
- package/projects/hypergraph/networks/testnet/gl0.env +5 -0
- package/projects/hypergraph/networks/testnet/gl1.env +4 -0
- package/projects/hypergraph/networks/testnet/network.env +8 -0
- package/projects/hypergraph/networks/testnet/source-nodes.env +9 -0
- package/projects/hypergraph/scripts/check-version.sh +31 -0
- package/projects/hypergraph/scripts/docker-build.sh +12 -1
- package/projects/hypergraph/scripts/install-dependencies.sh +3 -3
- package/projects/hypergraph/scripts/install.sh +34 -31
- package/projects/hypergraph/seedlist +268 -0
- package/scripts/autoheal.sh +8 -0
- package/scripts/services/io.constellationnetwork.nodepilot.Updater.plist +16 -0
- package/scripts/services/node-pilot-autoheal.service +14 -0
- package/scripts/services/node-pilot-updater-hypergraph.service +15 -0
- package/scripts/updater.sh +13 -0
- package/dist/helpers/docker-helper.d.ts +0 -7
- package/dist/helpers/docker-helper.js +0 -37
- package/projects/hypergraph/layers/gl1.env +0 -3
- package/projects/hypergraph/networks/integrationnet.env +0 -9
- package/projects/hypergraph/networks/mainnet.env +0 -8
- package/projects/hypergraph/networks/testnet.env +0 -9
- package/projects/scripts/docker-cleanup.sh +0 -64
package/README.md
CHANGED
@@ -11,7 +11,7 @@ A new CLI generated with oclif
|
|
11
11
|
|
12
12
|
<!-- toc -->
|
13
13
|
* [Usage](#usage)
|
14
|
-
* [The
|
14
|
+
* [The TL;DR Version](#the-tldr-version)
|
15
15
|
* [Commands](#commands)
|
16
16
|
<!-- tocstop -->
|
17
17
|
# Usage
|
@@ -21,14 +21,14 @@ $ 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.9 darwin-arm64 node-v22.15.0
|
25
25
|
$ cpilot --help [COMMAND]
|
26
26
|
USAGE
|
27
27
|
$ cpilot COMMAND
|
28
28
|
...
|
29
29
|
```
|
30
30
|
<!-- usagestop -->
|
31
|
-
# The
|
31
|
+
# The TL;DR Version
|
32
32
|
#### Simply run cpilot with no commands.
|
33
33
|
```sh-session
|
34
34
|
$ cpilot
|
@@ -42,8 +42,8 @@ If no command is entered, node-pilot will automatically perform a series of chec
|
|
42
42
|
* [`cpilot config set NAME VALUE`](#cpilot-config-set-name-value)
|
43
43
|
* [`cpilot help [COMMAND]`](#cpilot-help-command)
|
44
44
|
* [`cpilot info`](#cpilot-info)
|
45
|
-
* [`cpilot logs
|
46
|
-
* [`cpilot restart`](#cpilot-restart)
|
45
|
+
* [`cpilot logs LAYER`](#cpilot-logs-layer)
|
46
|
+
* [`cpilot restart [LAYER]`](#cpilot-restart-layer)
|
47
47
|
* [`cpilot shutdown`](#cpilot-shutdown)
|
48
48
|
* [`cpilot status`](#cpilot-status)
|
49
49
|
|
@@ -62,7 +62,7 @@ EXAMPLES
|
|
62
62
|
$ cpilot config
|
63
63
|
```
|
64
64
|
|
65
|
-
_See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
65
|
+
_See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/config.ts)_
|
66
66
|
|
67
67
|
## `cpilot config get [NAME]`
|
68
68
|
|
@@ -86,7 +86,7 @@ EXAMPLES
|
|
86
86
|
$ cpilot config get gl0:CL_PUBLIC_HTTP_PORT
|
87
87
|
```
|
88
88
|
|
89
|
-
_See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
89
|
+
_See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/config/get.ts)_
|
90
90
|
|
91
91
|
## `cpilot config set NAME VALUE`
|
92
92
|
|
@@ -109,7 +109,7 @@ EXAMPLES
|
|
109
109
|
$ cpilot config set gl0:CL_PUBLIC_HTTP_PORT 9000
|
110
110
|
```
|
111
111
|
|
112
|
-
_See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
112
|
+
_See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/config/set.ts)_
|
113
113
|
|
114
114
|
## `cpilot help [COMMAND]`
|
115
115
|
|
@@ -146,21 +146,22 @@ EXAMPLES
|
|
146
146
|
$ cpilot info
|
147
147
|
```
|
148
148
|
|
149
|
-
_See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
149
|
+
_See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/info.ts)_
|
150
150
|
|
151
|
-
## `cpilot logs
|
151
|
+
## `cpilot logs LAYER`
|
152
152
|
|
153
153
|
view validator node runtime logs
|
154
154
|
|
155
155
|
```
|
156
156
|
USAGE
|
157
|
-
$ cpilot logs
|
157
|
+
$ cpilot logs LAYER [-f] [-n <value>]
|
158
158
|
|
159
159
|
ARGUMENTS
|
160
160
|
LAYER network layer to view. e.g. gl0
|
161
161
|
|
162
162
|
FLAGS
|
163
|
-
-f, --follow
|
163
|
+
-f, --follow continuously wait for additional data to be appended
|
164
|
+
-n, --numOfLines=<value> number of lines at the end of the log to display
|
164
165
|
|
165
166
|
DESCRIPTION
|
166
167
|
view validator node runtime logs
|
@@ -169,15 +170,22 @@ EXAMPLES
|
|
169
170
|
$ cpilot logs
|
170
171
|
```
|
171
172
|
|
172
|
-
_See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
173
|
+
_See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/logs.ts)_
|
173
174
|
|
174
|
-
## `cpilot restart`
|
175
|
+
## `cpilot restart [LAYER]`
|
175
176
|
|
176
177
|
A full shutdown of the validator node, then restart
|
177
178
|
|
178
179
|
```
|
179
180
|
USAGE
|
180
|
-
$ cpilot restart
|
181
|
+
$ cpilot restart [LAYER] [-p hypergraph]
|
182
|
+
|
183
|
+
ARGUMENTS
|
184
|
+
LAYER network layer to view. e.g. gl0
|
185
|
+
|
186
|
+
GLOBAL FLAGS
|
187
|
+
-p, --project=<option> Specify the project name to use
|
188
|
+
<options: hypergraph>
|
181
189
|
|
182
190
|
DESCRIPTION
|
183
191
|
A full shutdown of the validator node, then restart
|
@@ -186,7 +194,7 @@ EXAMPLES
|
|
186
194
|
$ cpilot restart
|
187
195
|
```
|
188
196
|
|
189
|
-
_See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
197
|
+
_See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/restart.ts)_
|
190
198
|
|
191
199
|
## `cpilot shutdown`
|
192
200
|
|
@@ -203,7 +211,7 @@ EXAMPLES
|
|
203
211
|
$ cpilot shutdown
|
204
212
|
```
|
205
213
|
|
206
|
-
_See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
214
|
+
_See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/shutdown.ts)_
|
207
215
|
|
208
216
|
## `cpilot status`
|
209
217
|
|
@@ -217,5 +225,5 @@ DESCRIPTION
|
|
217
225
|
Display node status and configuration settings
|
218
226
|
```
|
219
227
|
|
220
|
-
_See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.
|
228
|
+
_See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.9/src/commands/status.ts)_
|
221
229
|
<!-- commandsstop -->
|
package/bin/dev.js
CHANGED
@@ -5,15 +5,10 @@ const skipDefaultCommand = {
|
|
5
5
|
if (process.argv.length === 2) {
|
6
6
|
process.argv[2] = 'status';
|
7
7
|
}
|
8
|
-
else if (process.argv.length > 2 && process.argv
|
8
|
+
else if (process.argv.length > 2 && process.argv.every(a => a.startsWith('-')) && !skipDefaultCommand[process.argv[2]]) {
|
9
9
|
process.argv.splice(2, 0 , 'status');
|
10
10
|
}
|
11
11
|
|
12
12
|
import {execute} from '@oclif/core'
|
13
13
|
|
14
14
|
await execute({development: true, dir: import.meta.url})
|
15
|
-
|
16
|
-
// eslint-disable-next-line no-warning-comments
|
17
|
-
// TODO
|
18
|
-
// cpilot config set project pacaswap-metagraph
|
19
|
-
// cpilot config --project pacaswap-metagraph
|
package/bin/run.js
CHANGED
@@ -6,7 +6,7 @@ const skipDefaultCommand = {
|
|
6
6
|
if (process.argv.length === 2) {
|
7
7
|
process.argv[2] = 'status';
|
8
8
|
}
|
9
|
-
else if (process.argv.length > 2 && process.argv
|
9
|
+
else if (process.argv.length > 2 && process.argv.every(a => a.startsWith('-')) && !skipDefaultCommand[process.argv[2]]) {
|
10
10
|
process.argv.splice(2, 0 , 'status');
|
11
11
|
}
|
12
12
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Command } from '@oclif/core';
|
2
|
+
export declare abstract class BaseCommand extends Command {
|
3
|
+
static baseFlags: {
|
4
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
5
|
+
};
|
6
|
+
checkProject(flags: {
|
7
|
+
project?: string;
|
8
|
+
}): void;
|
9
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
// src/base.ts
|
2
|
+
import { Command, Flags } from '@oclif/core';
|
3
|
+
import { configStore } from "./config-store.js";
|
4
|
+
import { configHelper } from "./helpers/config-helper.js";
|
5
|
+
export class BaseCommand extends Command {
|
6
|
+
static baseFlags = {
|
7
|
+
project: Flags.string({
|
8
|
+
char: 'p',
|
9
|
+
description: 'Specify the project name to use',
|
10
|
+
helpGroup: 'GLOBAL', // Optional: Group this flag in the help output
|
11
|
+
options: configStore.getProjects()
|
12
|
+
})
|
13
|
+
};
|
14
|
+
checkProject(flags) {
|
15
|
+
configHelper.assertProject('No project found. ');
|
16
|
+
if (flags.project) {
|
17
|
+
configStore.changeProjectStore(flags.project);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const checkDependencies: () => Promise<void>;
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import fs from "node:fs";
|
2
|
+
import path from "node:path";
|
3
|
+
import { fileURLToPath } from "node:url";
|
4
|
+
import shell from "shelljs";
|
5
|
+
import { clm } from "../clm.js";
|
6
|
+
import { promptHelper } from "../helpers/prompt-helper.js";
|
7
|
+
import { shellService } from "../services/shell-service.js";
|
8
|
+
export const checkDependencies = async () => {
|
9
|
+
const dockerComposeVersion = await shellService.runCommand('docker compose version').catch(() => '');
|
10
|
+
clm.debug(`Docker compose version check: ${dockerComposeVersion || 'NOT_INSTALLED'}`);
|
11
|
+
if (dockerComposeVersion) {
|
12
|
+
return;
|
13
|
+
}
|
14
|
+
const isDockerV1Installed = await shellService.checkCommandAvailable('docker-compose');
|
15
|
+
if (isDockerV1Installed) {
|
16
|
+
clm.warn('You are using docker-compose v1. It needs to be uninstalled before upgrading to the latest version.');
|
17
|
+
// await promptHelper.doYouWishToContinue();
|
18
|
+
clm.step('\nRun the following command to uninstall docker-compose v1 and then run cpilot again:');
|
19
|
+
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');
|
20
|
+
clm.echo('');
|
21
|
+
process.exit(0);
|
22
|
+
}
|
23
|
+
const isDockerInstalled = await shellService.checkCommandAvailable('docker');
|
24
|
+
if (!isDockerInstalled) {
|
25
|
+
const pilotDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../..`);
|
26
|
+
if (fs.existsSync(path.join(pilotDir, 'install-dependencies.sh'))) {
|
27
|
+
// Skip prompt if already informed user of the upgrade
|
28
|
+
if (!isDockerV1Installed) {
|
29
|
+
clm.step('Docker is required and needs to be installed.');
|
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, silent });
|
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
|
+
}
|
39
|
+
clm.postStep(`\nDocker has been installed. Please logout and login again to ensure the changes take effect. Then run cpilot again.`);
|
40
|
+
clm.echo('');
|
41
|
+
process.exit(0);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
};
|
@@ -20,7 +20,7 @@ export const checkHardware = {
|
|
20
20
|
const numOfCores = os.availableParallelism();
|
21
21
|
let allPassed = true;
|
22
22
|
const formatActual = (value, recommended, units = '') => {
|
23
|
-
const passed = Number(value) >= recommended;
|
23
|
+
const passed = Math.ceil(Number(value)) >= recommended;
|
24
24
|
allPassed = allPassed && passed;
|
25
25
|
return passed ? chalk.greenBright(value + units) : chalk.redBright(value + units);
|
26
26
|
};
|
@@ -32,8 +32,8 @@ export const checkHardware = {
|
|
32
32
|
{ headerColor: 'white', value: 'ACTUAL' },
|
33
33
|
];
|
34
34
|
const rows = [
|
35
|
-
[fc("Disk size"), fc("
|
36
|
-
[fc("System memory"), fc("
|
35
|
+
[fc("Disk size"), fc("240 GB"), formatActual(totalSpaceGB, 240, " GB")],
|
36
|
+
[fc("System memory"), fc("16 GB"), formatActual(totalMemoryGB, 16, " GB")],
|
37
37
|
[fc("CPU cores"), fc("8 cores"), formatActual(numOfCores, 8, " cores")],
|
38
38
|
];
|
39
39
|
clm.echo(ttyTable(header, rows).render() + "\n");
|
@@ -1,15 +1,17 @@
|
|
1
1
|
import chalk from "chalk";
|
2
2
|
import { configStore } from "../config-store.js";
|
3
|
+
import { checkDependencies } from "./check-dependencies.js";
|
3
4
|
import { checkHardware } from "./check-hardware.js";
|
4
5
|
export const checkInitialSetup = {
|
5
6
|
async firstTimeRun() {
|
6
7
|
if (configStore.getSystemInfo() !== null) {
|
7
8
|
return;
|
8
9
|
}
|
9
|
-
|
10
|
-
console.log(
|
11
|
-
console.log("
|
12
|
-
console.log(chalk.
|
10
|
+
await checkDependencies();
|
11
|
+
console.log(chalk.whiteBright("\n ****************************************"));
|
12
|
+
console.log(" " + chalk.whiteBright("CONSTELLATION NETWORK") + " ");
|
13
|
+
console.log(" " + chalk.whiteBright("NODE PILOT") + " ");
|
14
|
+
console.log(chalk.whiteBright(" ****************************************"));
|
13
15
|
await checkHardware.systemRequirements();
|
14
16
|
},
|
15
17
|
};
|
@@ -2,7 +2,7 @@ import { input } from "@inquirer/prompts";
|
|
2
2
|
import chalk from "chalk";
|
3
3
|
import { clm } from "../clm.js";
|
4
4
|
import { configStore } from "../config-store.js";
|
5
|
-
import {
|
5
|
+
import { dockerService } from "../services/docker-service.js";
|
6
6
|
import { nodeService } from "../services/node-service.js";
|
7
7
|
export const checkLayers = {
|
8
8
|
async layersReadyToJoin() {
|
@@ -27,9 +27,9 @@ export const checkLayers = {
|
|
27
27
|
}
|
28
28
|
await input({ default: 'y', message: 'Would you like to start the validator(s)? (y/n): ' }).then(async (answer) => {
|
29
29
|
if (answer.toLowerCase() === 'y') {
|
30
|
-
await
|
30
|
+
await dockerService.dockerBuild();
|
31
31
|
clm.preStep('Starting the node...');
|
32
|
-
await
|
32
|
+
await dockerService.dockerUp();
|
33
33
|
await nodeService.pollForLayersState(layersToRun);
|
34
34
|
}
|
35
35
|
else {
|
@@ -40,11 +40,11 @@ export const checkLayers = {
|
|
40
40
|
else if (notRunningLayers.length > 0) {
|
41
41
|
const layersNotRunning = notRunningLayers.map(r => r.layer);
|
42
42
|
clm.preStep('The following Validator Node layers are not running: ' + chalk.cyan(layersNotRunning.join(', ')));
|
43
|
-
await input({ default: 'y', message: 'Would you like to
|
43
|
+
await input({ default: 'y', message: 'Would you like to start the validator(s)? (y/n): ' }).then(async (answer) => {
|
44
44
|
if (answer.toLowerCase() === 'y') {
|
45
|
-
clm.preStep('
|
46
|
-
await
|
47
|
-
await nodeService.pollForLayersState(
|
45
|
+
clm.preStep('Starting docker containers...');
|
46
|
+
await dockerService.dockerStartLayers(layersNotRunning);
|
47
|
+
await nodeService.pollForLayersState(layersNotRunning);
|
48
48
|
}
|
49
49
|
else {
|
50
50
|
clm.echo('Node not started.');
|
@@ -1,6 +1,9 @@
|
|
1
1
|
export declare const checkNetwork: {
|
2
|
+
checkForExistingNodeIdInCluster(): Promise<void>;
|
3
|
+
checkSeedList(): Promise<void>;
|
2
4
|
configureIpAddress(): Promise<void>;
|
3
5
|
detectExternalIpAddress(): Promise<void>;
|
4
6
|
enterIpAddressManually(): Promise<string>;
|
5
7
|
fetchIPAddress(): Promise<string>;
|
8
|
+
isNetworkConnectable(): Promise<boolean>;
|
6
9
|
};
|
@@ -1,14 +1,83 @@
|
|
1
1
|
import { input, select } from "@inquirer/prompts";
|
2
2
|
import chalk from "chalk";
|
3
|
+
import fs from "node:fs";
|
4
|
+
import path from "node:path";
|
3
5
|
import { clm } from "../clm.js";
|
4
6
|
import { configStore } from "../config-store.js";
|
7
|
+
import { clusterService } from "../services/cluster-service.js";
|
8
|
+
import { dockerService } from "../services/docker-service.js";
|
9
|
+
import { shellService } from "../services/shell-service.js";
|
5
10
|
export const checkNetwork = {
|
11
|
+
async checkForExistingNodeIdInCluster() {
|
12
|
+
if (configStore.hasProjectFlag('duplicateNodeIdChecked')) {
|
13
|
+
return;
|
14
|
+
}
|
15
|
+
clm.preStep('Checking for existing Node ID in cluster...');
|
16
|
+
const { nodeId } = configStore.getProjectInfo();
|
17
|
+
const clusterInfo = await clusterService.getClusterInfo();
|
18
|
+
const found = clusterInfo.some(node => node.id === nodeId);
|
19
|
+
const isDockerRunning = await dockerService.isRunning();
|
20
|
+
if (!isDockerRunning && found) {
|
21
|
+
clm.warn('Node ID already exists in the cluster.');
|
22
|
+
clm.warn('You need to shutdown your node from a previous installation before continuing.');
|
23
|
+
clm.error(`Or to change the node ID, configure the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
|
24
|
+
}
|
25
|
+
configStore.setProjectFlag('duplicateNodeIdChecked', true);
|
26
|
+
clm.postStep('No duplicate Node found.');
|
27
|
+
},
|
28
|
+
async checkSeedList() {
|
29
|
+
if (configStore.hasProjectFlag('seedListChecked')) {
|
30
|
+
return;
|
31
|
+
}
|
32
|
+
const { type } = configStore.getNetworkInfo();
|
33
|
+
clm.preStep(`Checking inclusion into seed list for ${type.toUpperCase()} network...`);
|
34
|
+
const { nodeId, projectDir } = configStore.getProjectInfo();
|
35
|
+
const seedListFile = path.resolve(projectDir, 'seedlist');
|
36
|
+
if (fs.existsSync(seedListFile)) {
|
37
|
+
const found = fs.readFileSync(seedListFile, 'utf8').includes(nodeId);
|
38
|
+
if (found) {
|
39
|
+
clm.postStep(`Node ID found in ${type.toUpperCase()} seed list.`);
|
40
|
+
configStore.setProjectFlag('seedListChecked', true);
|
41
|
+
return;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
const printNotFoundError = () => {
|
45
|
+
clm.warn(`Node ID not found in ${type.toUpperCase()} seed list. You may try again later.`);
|
46
|
+
clm.warn(`To change the Key File: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Key File')}`);
|
47
|
+
clm.error(`To change the Network: use ${chalk.cyan('cpilot config')}, and select ${chalk.cyan('Network')}`);
|
48
|
+
};
|
49
|
+
if (type === 'mainnet') {
|
50
|
+
// the mainnet seed list comed from a network release
|
51
|
+
printNotFoundError();
|
52
|
+
}
|
53
|
+
else {
|
54
|
+
const url = `https://constellationlabs-dag.s3.us-west-1.amazonaws.com/${type}-seedlist`;
|
55
|
+
const seedList = await fetch(url)
|
56
|
+
.then(res => {
|
57
|
+
if (res.ok)
|
58
|
+
return res.text();
|
59
|
+
throw new Error(`Failed`);
|
60
|
+
})
|
61
|
+
.catch(() => {
|
62
|
+
clm.error(`Failed to fetch seed list from ${url}. Try again later.`);
|
63
|
+
return '';
|
64
|
+
});
|
65
|
+
if (seedList.includes(nodeId)) {
|
66
|
+
clm.postStep(`Node ID found in ${type.toUpperCase()} seed list.`);
|
67
|
+
fs.writeFileSync(seedListFile, seedList);
|
68
|
+
configStore.setProjectFlag('seedListChecked', true);
|
69
|
+
}
|
70
|
+
else {
|
71
|
+
printNotFoundError();
|
72
|
+
}
|
73
|
+
}
|
74
|
+
},
|
6
75
|
async configureIpAddress() {
|
7
|
-
const { CL_EXTERNAL_IP: currentIpAddress } = configStore.
|
76
|
+
const { CL_EXTERNAL_IP: currentIpAddress } = configStore.getEnvInfo();
|
8
77
|
const detectedIpAddress = await checkNetwork.fetchIPAddress().catch(() => '');
|
9
78
|
if (!currentIpAddress && !detectedIpAddress) {
|
10
79
|
const newIpAddress = await checkNetwork.enterIpAddressManually();
|
11
|
-
configStore.
|
80
|
+
configStore.setEnvInfo({ CL_EXTERNAL_IP: newIpAddress });
|
12
81
|
return;
|
13
82
|
}
|
14
83
|
if (currentIpAddress) {
|
@@ -37,7 +106,7 @@ export const checkNetwork = {
|
|
37
106
|
else if (answer === 'manual') {
|
38
107
|
selectedIpAddress = await checkNetwork.enterIpAddressManually();
|
39
108
|
}
|
40
|
-
configStore.
|
109
|
+
configStore.setEnvInfo({ CL_EXTERNAL_IP: selectedIpAddress });
|
41
110
|
},
|
42
111
|
async detectExternalIpAddress() {
|
43
112
|
const externalIp = await this.fetchIPAddress()
|
@@ -46,7 +115,7 @@ export const checkNetwork = {
|
|
46
115
|
return this.enterIpAddressManually();
|
47
116
|
});
|
48
117
|
clm.postStep("\nExternal IP address: " + chalk.cyan(externalIp) + "\n");
|
49
|
-
configStore.
|
118
|
+
configStore.setEnvInfo({ CL_EXTERNAL_IP: externalIp });
|
50
119
|
},
|
51
120
|
async enterIpAddressManually() {
|
52
121
|
return input({
|
@@ -62,11 +131,25 @@ export const checkNetwork = {
|
|
62
131
|
});
|
63
132
|
},
|
64
133
|
async fetchIPAddress() {
|
65
|
-
return
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
134
|
+
return shellService.runCommandWithOutput('curl -4 https://ifconfig.me/ip');
|
135
|
+
},
|
136
|
+
async isNetworkConnectable() {
|
137
|
+
return clusterService.getClusterInfo()
|
138
|
+
.then(async (nodes) => {
|
139
|
+
const someAreReady = nodes.some(node => node.state === 'Ready');
|
140
|
+
if (!someAreReady) {
|
141
|
+
if (nodes.length > 0) {
|
142
|
+
clm.warn(`Found ${nodes.length} nodes in the cluster, but none are READY.`);
|
143
|
+
}
|
144
|
+
throw new Error(`Network is not connectable.`);
|
145
|
+
}
|
146
|
+
clm.debug(`Network is live. Found ${nodes.length} nodes in the cluster.`);
|
147
|
+
configStore.setClusterStats({ total: nodes.length });
|
148
|
+
return true;
|
149
|
+
})
|
150
|
+
.catch(() => {
|
151
|
+
clm.error(`Network is not in service. Please try again later.`);
|
152
|
+
return false;
|
70
153
|
});
|
71
154
|
}
|
72
155
|
};
|
@@ -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,11 +1,13 @@
|
|
1
1
|
import { input, select } from "@inquirer/prompts";
|
2
|
+
import chalk from "chalk";
|
3
|
+
import ora from 'ora';
|
2
4
|
import { clm } from "../clm.js";
|
3
5
|
import { configStore } from "../config-store.js";
|
4
6
|
import { configHelper } from "../helpers/config-helper.js";
|
5
|
-
import {
|
7
|
+
import { projectHelper } from "../helpers/project-helper.js";
|
6
8
|
import { promptHelper } from "../helpers/prompt-helper.js";
|
7
9
|
import { clusterService } from "../services/cluster-service.js";
|
8
|
-
import {
|
10
|
+
import { dockerService } from "../services/docker-service.js";
|
9
11
|
import { shellService } from "../services/shell-service.js";
|
10
12
|
import { checkNetwork } from "./check-network.js";
|
11
13
|
export const checkProject = {
|
@@ -13,7 +15,7 @@ export const checkProject = {
|
|
13
15
|
let updateNetworkType = false;
|
14
16
|
let updateLayers = false;
|
15
17
|
if (!configStore.hasProjects() || process.env.PILOT_ENV === 'test') {
|
16
|
-
await
|
18
|
+
await projectHelper.selectProject();
|
17
19
|
await checkNetwork.configureIpAddress();
|
18
20
|
updateNetworkType = true;
|
19
21
|
updateLayers = true;
|
@@ -79,20 +81,38 @@ export const checkProject = {
|
|
79
81
|
},
|
80
82
|
async runInstall() {
|
81
83
|
const nInfo = configStore.getNetworkInfo();
|
82
|
-
const
|
84
|
+
const node = await clusterService.getClusterNodeInfo();
|
85
|
+
const NODE_URL = `http://${node.host}:${node.publicPort}`;
|
83
86
|
let rInfo = await configHelper.getReleaseInfo();
|
84
|
-
if (rInfo && rInfo.network === nInfo.type && rInfo.version ===
|
85
|
-
clm.postStep(`Network files are already installed for ${nInfo.type} version ${
|
87
|
+
if (rInfo && rInfo.network === nInfo.type && rInfo.version === node.version) {
|
88
|
+
clm.postStep(`Network files are already installed for ${nInfo.type} version ${node.version}`);
|
86
89
|
return false;
|
87
90
|
}
|
88
|
-
const
|
89
|
-
const isRunning = nodeInfo.state !== 'Unavailable';
|
91
|
+
const isRunning = await dockerService.isRunning();
|
90
92
|
if (isRunning) {
|
91
|
-
await
|
93
|
+
await dockerService.dockerDown();
|
94
|
+
}
|
95
|
+
const silent = !process.env.DEBUG;
|
96
|
+
const spinner = ora('Running install script...');
|
97
|
+
if (silent) {
|
98
|
+
spinner.start();
|
99
|
+
spinner.color = 'green';
|
100
|
+
}
|
101
|
+
else {
|
102
|
+
clm.preStep('Running install script...');
|
103
|
+
}
|
104
|
+
// NOTE: may be different for metagraphs
|
105
|
+
await shellService.runProjectCommand(`scripts/install.sh ${nInfo.type}`, { NODE_URL }, silent)
|
106
|
+
.catch(() => {
|
107
|
+
spinner.stop();
|
108
|
+
if (silent) {
|
109
|
+
clm.error(`Install script failed. run: ${chalk.cyan("DEBUG=true cpilot")} for more details`);
|
110
|
+
}
|
111
|
+
clm.error('Install script failed. Please run cpilot again after correcting the error');
|
112
|
+
});
|
113
|
+
if (silent) {
|
114
|
+
spinner.stop();
|
92
115
|
}
|
93
|
-
clm.preStep('Running install script...');
|
94
|
-
const silent = false; // !process.env.DEBUG;
|
95
|
-
await shellService.runCommand(`scripts/install.sh ${nInfo.type}`, undefined, silent); // different for metagraphs
|
96
116
|
rInfo = await configHelper.getReleaseInfo();
|
97
117
|
configStore.setNetworkInfo({
|
98
118
|
type: rInfo.network,
|
@@ -103,7 +123,7 @@ export const checkProject = {
|
|
103
123
|
async runUpgrade() {
|
104
124
|
const changed = await this.runInstall();
|
105
125
|
if (changed) {
|
106
|
-
await
|
126
|
+
await dockerService.dockerBuild();
|
107
127
|
}
|
108
128
|
}
|
109
129
|
};
|