@constellation-network/node-pilot 0.0.14 → 0.0.16

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 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.14 darwin-arm64 node-v22.15.0
24
+ @constellation-network/node-pilot/0.0.16 darwin-arm64 node-v24.8.0
25
25
  $ cpilot --help [COMMAND]
26
26
  USAGE
27
27
  $ cpilot COMMAND
@@ -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.14/src/commands/config.ts)_
65
+ _See code: [src/commands/config.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/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.14/src/commands/config/get.ts)_
89
+ _See code: [src/commands/config/get.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/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.14/src/commands/config/set.ts)_
112
+ _See code: [src/commands/config/set.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/src/commands/config/set.ts)_
113
113
 
114
114
  ## `cpilot help [COMMAND]`
115
115
 
@@ -146,7 +146,7 @@ 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.14/src/commands/info.ts)_
149
+ _See code: [src/commands/info.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/src/commands/info.ts)_
150
150
 
151
151
  ## `cpilot logs LAYER`
152
152
 
@@ -170,7 +170,7 @@ EXAMPLES
170
170
  $ cpilot logs
171
171
  ```
172
172
 
173
- _See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.14/src/commands/logs.ts)_
173
+ _See code: [src/commands/logs.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/src/commands/logs.ts)_
174
174
 
175
175
  ## `cpilot restart [LAYER]`
176
176
 
@@ -198,7 +198,7 @@ EXAMPLES
198
198
  $ cpilot restart
199
199
  ```
200
200
 
201
- _See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.14/src/commands/restart.ts)_
201
+ _See code: [src/commands/restart.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/src/commands/restart.ts)_
202
202
 
203
203
  ## `cpilot shutdown`
204
204
 
@@ -215,7 +215,7 @@ EXAMPLES
215
215
  $ cpilot shutdown
216
216
  ```
217
217
 
218
- _See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.14/src/commands/shutdown.ts)_
218
+ _See code: [src/commands/shutdown.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/src/commands/shutdown.ts)_
219
219
 
220
220
  ## `cpilot status`
221
221
 
@@ -229,5 +229,5 @@ DESCRIPTION
229
229
  Display node status and configuration settings
230
230
  ```
231
231
 
232
- _See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.14/src/commands/status.ts)_
232
+ _See code: [src/commands/status.ts](https://github.com/Constellation-Labs/node-pilot/blob/v0.0.16/src/commands/status.ts)_
233
233
  <!-- commandsstop -->
@@ -30,8 +30,8 @@ export const checkDependencies = async () => {
30
30
  await promptHelper.doYouWishToContinue();
31
31
  }
32
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 });
33
+ // const silent = !process.env.DEBUG;
34
+ const result = shell.exec('bash install-dependencies.sh', { cwd: pilotDir });
35
35
  if (result.code > 0) {
36
36
  console.log(result.stderr);
37
37
  clm.error(`Failed to install dependencies. Please try again after resolving any errors.`);
@@ -13,9 +13,7 @@ export const checkHardware = {
13
13
  const totalSpaceGB = (r.bsize * r.blocks / (1024 * 1024 * 1024)).toFixed(2);
14
14
  // const usage = diskusage.checkSync(os.homedir());
15
15
  // const usableSpaceGB = (usage.total / (1024 * 1024 * 1024)).toFixed(2);
16
- // Retrieve sys memory
17
- const totalMemoryBytes = os.totalmem();
18
- const totalMemoryGB = (totalMemoryBytes / (1024 * 1024 * 1024)).toFixed(2);
16
+ const totalMemoryGB = (os.totalmem() / (1024 * 1024 * 1024)).toFixed(2);
19
17
  // Retrieve number of CPU cores
20
18
  const numOfCores = os.availableParallelism();
21
19
  let allPassed = true;
@@ -2,6 +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 { StatusTable } from "../helpers/status-table.js";
5
6
  import { dockerService } from "../services/docker-service.js";
6
7
  import { nodeService } from "../services/node-service.js";
7
8
  export const checkLayers = {
@@ -62,17 +63,7 @@ export const checkLayers = {
62
63
  }
63
64
  },
64
65
  async layersStatus() {
65
- const { layersToRun } = configStore.getProjectInfo();
66
- const promises = layersToRun.map(l => nodeService.getNodeInfo(l));
67
- const results = await Promise.all(promises);
68
- const states = results.map(r => r.state);
69
- clm.preStep("-----------------------");
70
- clm.preStep(" VALIDATOR NODE STATUS ");
71
- clm.preStep("-----------------------");
72
- for (const [i, layer] of layersToRun.entries()) {
73
- const state = states[i];
74
- clm.step(` "${layer.toUpperCase()}" is "${state}"`);
75
- }
66
+ await StatusTable.run();
76
67
  },
77
68
  async nodeReadyToJoin(layer) {
78
69
  const status = await nodeService.getNodeInfo(layer);
@@ -1,4 +1,5 @@
1
1
  export declare const checkNetwork: {
2
+ checkExternalIpAddress(): Promise<void> | undefined;
2
3
  checkForExistingNodeIdInCluster(): Promise<void>;
3
4
  checkSeedList(): Promise<void>;
4
5
  configureIpAddress(): Promise<void>;
@@ -8,6 +8,12 @@ import { clusterService } from "../services/cluster-service.js";
8
8
  import { dockerService } from "../services/docker-service.js";
9
9
  import { shellService } from "../services/shell-service.js";
10
10
  export const checkNetwork = {
11
+ checkExternalIpAddress() {
12
+ const { CL_EXTERNAL_IP } = configStore.getEnvInfo();
13
+ if (!CL_EXTERNAL_IP) {
14
+ return this.configureIpAddress();
15
+ }
16
+ },
11
17
  async checkForExistingNodeIdInCluster() {
12
18
  if (configStore.hasProjectFlag('duplicateNodeIdChecked')) {
13
19
  return;
@@ -1,6 +1,4 @@
1
1
  import { input, select } from "@inquirer/prompts";
2
- import chalk from "chalk";
3
- import ora from 'ora';
4
2
  import { clm } from "../clm.js";
5
3
  import { configStore } from "../config-store.js";
6
4
  import { configHelper } from "../helpers/config-helper.js";
@@ -96,29 +94,31 @@ export const checkProject = {
96
94
  if (isRunning) {
97
95
  await dockerService.dockerDown();
98
96
  }
99
- const silent = !process.env.DEBUG;
100
- const spinner = ora('Running install script...');
101
- if (silent) {
102
- spinner.start();
103
- spinner.color = 'green';
104
- }
105
- else {
106
- clm.preStep('Running install script...');
107
- }
97
+ // const silent = !process.env.DEBUG;
98
+ //
99
+ // const spinner = ora('');
100
+ //
101
+ // if (silent) {
102
+ // spinner.start();
103
+ // spinner.color = 'green';
104
+ // }
105
+ // else {
106
+ clm.preStep('Running install script...');
107
+ // }
108
108
  // const node = await clusterService.getClusterNodeInfo();
109
109
  // const NODE_URL = `http://${node.host}:${node.publicPort}`;
110
110
  // NOTE: may be different for metagraphs
111
- await shellService.runProjectCommand(`scripts/install.sh ${nInfo.type}`, undefined, silent)
111
+ await shellService.runProjectCommand(`scripts/install.sh ${nInfo.type}`, undefined, false)
112
112
  .catch(() => {
113
- spinner.stop();
114
- if (silent) {
115
- clm.error(`Install script failed. run: ${chalk.cyan("DEBUG=true cpilot")} for more details`);
116
- }
113
+ // spinner.stop();
114
+ // if (silent) {
115
+ // clm.error(`Install script failed. run: ${chalk.cyan("DEBUG=true cpilot")} for more details`);
116
+ // }
117
117
  clm.error('Install script failed. Please run cpilot again after correcting the error');
118
118
  });
119
- if (silent) {
120
- spinner.stop();
121
- }
119
+ // if (silent) {
120
+ // spinner.stop();
121
+ // }
122
122
  rInfo = await configHelper.getReleaseInfo();
123
123
  configStore.setNetworkInfo({
124
124
  type: rInfo.network,
@@ -20,7 +20,7 @@ export default class Info extends Command {
20
20
  // Node ID
21
21
  configHelper.showEnvInfo('Node ID', projectInfo.nodeId);
22
22
  // Layers to Run
23
- configHelper.showEnvInfo('Layers to Run', projectInfo.layersToRun.join(', '));
23
+ configHelper.showEnvInfo('Layers to Run', projectInfo.layersToRun?.join(', '));
24
24
  // Network type
25
25
  configHelper.showEnvInfo('Network', networkInfo.type);
26
26
  // Network version
@@ -27,7 +27,7 @@ export default class Restart extends BaseCommand {
27
27
  serviceLog.log('Executing "cpilot restart --update" at ' + new Date().toLocaleString('en-US', { timeZone: 'America/Los_Angeles' }));
28
28
  const project = configStore.getActiveProject();
29
29
  const activeProjects = configStore.getRunningProjects();
30
- serviceLog.log(` Active projects: ${activeProjects.join(', ')}...`);
30
+ // serviceLog.log(` Active projects: ${activeProjects.join(', ')}...`);
31
31
  for (const project of activeProjects) {
32
32
  configStore.setActiveProject(project);
33
33
  // eslint-disable-next-line no-await-in-loop
@@ -44,7 +44,7 @@ export default class Restart extends BaseCommand {
44
44
  serviceLog.log('Executing "cpilot restart --autostart" at ' + new Date().toLocaleString('en-US', { timeZone: 'America/Los_Angeles' }));
45
45
  const project = configStore.getActiveProject();
46
46
  const activeProjects = configStore.getRunningProjects();
47
- serviceLog.log(` Active projects: ${activeProjects.join(', ')}...`);
47
+ // serviceLog.log(` Active projects: ${activeProjects.join(', ')}...`);
48
48
  for (const project of activeProjects) {
49
49
  serviceLog.log(' ' + project + ' is restarting...');
50
50
  configStore.setActiveProject(project);
@@ -17,6 +17,7 @@ export default class Status extends Command {
17
17
  export async function checkInstallationAndConfigurationStatus() {
18
18
  await checkInitialSetup.firstTimeRun();
19
19
  await checkProject.projectInstallation();
20
+ await checkNetwork.checkExternalIpAddress();
20
21
  await checkNetwork.isNetworkConnectable();
21
22
  await checkProject.releaseVersion();
22
23
  await checkNodeCtl.check4Migration();
@@ -4,6 +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 { StatusTable } from "../helpers/status-table.js";
7
8
  export default class Test extends Command {
8
9
  static description = 'node pilot test command';
9
10
  static hidden = true;
@@ -17,6 +18,7 @@ export default class Test extends Command {
17
18
  //
18
19
  // await archiverService.syncToLatestSnapshot();
19
20
  // await archiverService.checkLogsForMissingSnapshots();
21
+ await StatusTable.run();
20
22
  }
21
23
  async testRandomNode() {
22
24
  const filePath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../projects/hypergraph/networks/mainnet/source-nodes.env`);
@@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url';
6
6
  import { clm } from "../clm.js";
7
7
  import { configStore } from "../config-store.js";
8
8
  import { githubService } from "../services/github-service.js";
9
+ import { shellService } from "../services/shell-service.js";
9
10
  import { configHelper } from "./config-helper.js";
10
11
  import { getLayerEnvFileContent } from "./env-templates.js";
11
12
  export const projectHelper = {
@@ -63,11 +64,17 @@ export const projectHelper = {
63
64
  async installHypergraph() {
64
65
  await this.installEmbedded('hypergraph');
65
66
  const { projectDir } = configStore.getProjectInfo();
66
- // Create gl0 folders for fast forward feature before Docker does
67
+ const { platform } = configStore.getSystemInfo();
68
+ // Create gl0 folder for the fast-forward feature before Docker does
67
69
  const gl0DataDir = path.join(projectDir, 'gl0', 'data');
68
70
  fs.mkdirSync(path.join(gl0DataDir, 'incremental_snapshot'), { recursive: true });
69
71
  fs.mkdirSync(path.join(gl0DataDir, 'snapshot_info'));
70
72
  fs.mkdirSync(path.join(gl0DataDir, 'tmp'));
73
+ if (platform === 'linux') {
74
+ const layerDir = path.join(projectDir, 'gl0');
75
+ // set permission for group "docker" on the layer folder and any subfolders created later
76
+ await shellService.runCommand(`sudo setfacl -Rm g:docker:rwX -dm g:docker:rwX ${layerDir}`);
77
+ }
71
78
  this.importEnvFiles();
72
79
  },
73
80
  async installProject(name, projectFolder) {
@@ -0,0 +1,31 @@
1
+ export declare const statusTableHeader: ({
2
+ color: string;
3
+ headerColor: string;
4
+ value: string;
5
+ formatter?: undefined;
6
+ width?: undefined;
7
+ } | {
8
+ color: string;
9
+ formatter: (startTime: number | string) => string;
10
+ headerColor: string;
11
+ value: string;
12
+ width?: undefined;
13
+ } | {
14
+ color: string;
15
+ formatter: (value: string) => string;
16
+ headerColor: string;
17
+ value: string;
18
+ width: number;
19
+ })[];
20
+ export type NodeStatusInfo = {
21
+ clusterOrdinal: number;
22
+ clusterSession: string;
23
+ clusterState: string;
24
+ cpuUsage: string;
25
+ error: string;
26
+ memUsage: string;
27
+ ordinal: number;
28
+ pilotSession: string;
29
+ session: string;
30
+ state: string;
31
+ };
@@ -0,0 +1,88 @@
1
+ class CellFormatter {
2
+ formatCpu(value) {
3
+ if (value === '-')
4
+ return value;
5
+ const num = Number.parseInt(value, 10);
6
+ if (num === 0)
7
+ return value;
8
+ if (num < 60)
9
+ return this.style(value.toString(), "green");
10
+ if (num < 90)
11
+ return this.style(value.toString(), "yellow", "bold");
12
+ return this.style(value.toString(), "red", "bold");
13
+ }
14
+ formatDistance(value) {
15
+ if (value === '-')
16
+ return value;
17
+ const num = Number(value);
18
+ if (num === 0)
19
+ return value;
20
+ if (num < 4)
21
+ return this.style(value.toString(), "bgYellow", "bold");
22
+ return this.style(value.toString(), "bgRed", "bold");
23
+ }
24
+ formatError(value) {
25
+ if (value === '-')
26
+ return value;
27
+ return this.style(value, "bgRed", "bold");
28
+ }
29
+ formatMem(value) {
30
+ if (value === '-')
31
+ return value;
32
+ const num = Number.parseInt(value.split('(')[1], 10);
33
+ if (num === 0)
34
+ return value;
35
+ if (num < 70)
36
+ return this.style(value.toString(), "green");
37
+ if (num < 90)
38
+ return this.style(value.toString(), "yellow", "bold");
39
+ return this.style(value.toString(), "red", "bold");
40
+ }
41
+ formatOrdinal(value) {
42
+ const [v, changed] = value.split(':');
43
+ if (changed) {
44
+ return this.style(v, "whiteBright");
45
+ }
46
+ return this.style(v, "cyan");
47
+ }
48
+ formatState(value) {
49
+ if (value === 'Offline')
50
+ return this.style(value, "bgRed", "bold");
51
+ if (value === 'Ready')
52
+ return this.style(value, "green");
53
+ if (value === 'ReadyToJoin')
54
+ return this.style(value, "yellow", "bold");
55
+ if (value === 'Restarting')
56
+ return this.style(value, "yellow", "bold");
57
+ return this.style(value, "white");
58
+ }
59
+ formatUpTIme(startTime) {
60
+ if (!startTime)
61
+ return '-';
62
+ const upTimeMs = Date.now() - Number(startTime);
63
+ const upTimeSec = Math.floor(upTimeMs / 1000);
64
+ const hours = Math.floor(upTimeSec / 3600);
65
+ const minutes = Math.floor((upTimeSec % 3600) / 60);
66
+ const seconds = upTimeSec % 60;
67
+ if (hours < 1 && minutes < 1)
68
+ return `${seconds}s`;
69
+ return hours > 0 ? `${hours}h ${minutes}m ${seconds}s` : `${minutes}m ${seconds}s`;
70
+ }
71
+ style(value, color, style) {
72
+ return `c${color}v${value}s${style}`;
73
+ }
74
+ }
75
+ const { formatCpu, formatDistance, formatError, formatMem, formatOrdinal, formatState, formatUpTIme } = new CellFormatter();
76
+ // Layer | Uptime | State | Ordinal | Distance from cluster | Cluster State | CPU Usage | Mem Usage | Error
77
+ export const statusTableHeader = [
78
+ { color: 'white', headerColor: 'whiteBright', value: 'Network' },
79
+ { color: 'whiteBright', headerColor: 'whiteBright', value: 'Layer' },
80
+ { color: 'white', formatter: formatUpTIme, headerColor: 'whiteBright', value: 'Uptime' },
81
+ { color: 'white', formatter: formatState, headerColor: 'whiteBright', value: 'Node State', width: 24 },
82
+ { color: 'white', formatter: formatOrdinal, headerColor: 'whiteBright', value: 'Ordinal' },
83
+ { color: 'white', formatter: formatDistance, headerColor: 'whiteBright', value: 'Distance' },
84
+ { color: 'white', formatter: formatState, headerColor: 'whiteBright', value: 'Cluster State', width: 16 },
85
+ { color: 'white', formatter: formatCpu, headerColor: 'whiteBright', value: 'CPU Usage', width: 12 },
86
+ { color: 'white', formatter: formatMem, headerColor: 'whiteBright', value: 'Mem Usage (GB)', width: 16 },
87
+ { color: 'white', formatter: formatError, headerColor: 'whiteBright', value: 'Error', width: 22 },
88
+ ];
@@ -0,0 +1,8 @@
1
+ export declare class StatusTable {
2
+ private alreadyRendered;
3
+ private previousHeight;
4
+ static run(): Promise<void>;
5
+ private getProjectInfo;
6
+ private monitorState;
7
+ private render;
8
+ }
@@ -0,0 +1,122 @@
1
+ import { createPrompt, useKeypress } from '@inquirer/core';
2
+ import fs from "node:fs";
3
+ import os from "node:os";
4
+ import ttyTable from "tty-table";
5
+ import { clm } from "../clm.js";
6
+ import { configStore } from "../config-store.js";
7
+ import { statusTableHeader } from "./status-table-helper.js";
8
+ export class StatusTable {
9
+ alreadyRendered = false;
10
+ previousHeight = 0;
11
+ static async run() {
12
+ process.on("exit", () => {
13
+ // show cursor
14
+ console.log("\u001B[?25h");
15
+ });
16
+ process.on("SIGINT", () => {
17
+ process.exit();
18
+ });
19
+ const table = new StatusTable();
20
+ table.monitorState();
21
+ const onKeyPress = createPrompt((_, done) => {
22
+ useKeypress(() => { done(''); });
23
+ return '';
24
+ });
25
+ await onKeyPress({});
26
+ console.log("\u001B[?25h");
27
+ process.exit();
28
+ }
29
+ getProjectInfo() {
30
+ const appPath = os.homedir() + '/.node-pilot';
31
+ const activeProject = configStore.getActiveProject();
32
+ const projects = configStore.getRunningProjects();
33
+ if (!activeProject || projects.length === 0) {
34
+ clm.error("No running projects found.");
35
+ }
36
+ const info = [];
37
+ for (const project of projects) {
38
+ configStore.setActiveProject(project);
39
+ const { layersToRun } = configStore.getProjectInfo();
40
+ const { type: network } = configStore.getNetworkInfo();
41
+ for (const layer of layersToRun) {
42
+ info.push({ layer, network, path: `${appPath}/${project}/${layer}/data/health-check/node`, project });
43
+ }
44
+ }
45
+ configStore.setActiveProject(activeProject);
46
+ return info;
47
+ }
48
+ async monitorState() {
49
+ const projects = this.getProjectInfo();
50
+ const values = {};
51
+ while (true) {
52
+ const rows = [];
53
+ for (const p of projects) {
54
+ if (!values[p.layer])
55
+ values[p.layer] = {};
56
+ const n = JSON.parse(fs.readFileSync(p.path, 'utf8'));
57
+ const projectName = p.project === 'hypergraph' ? '' : p.project;
58
+ const network = p.network === 'integrationnet' ? 'intnet' : p.network;
59
+ const distance = Number.isNaN(n.clusterOrdinal - n.ordinal) ? '-' : String(n.clusterOrdinal - n.ordinal);
60
+ const ordinal = (values[p.layer].ordinal === n.ordinal) ? String(n.ordinal) : n.ordinal + ':true';
61
+ rows.push([
62
+ projectName + ':' + network,
63
+ p.layer,
64
+ n.session, // n.pilotSession,
65
+ n.state,
66
+ n.ordinal ? ordinal : '-',
67
+ distance,
68
+ n.clusterState || 'Ready',
69
+ n.cpuUsage || '-',
70
+ n.memUsage || '-',
71
+ n.error || '-'
72
+ ]);
73
+ values[p.layer].ordinal = n.ordinal;
74
+ }
75
+ this.render(rows);
76
+ process.stdout.write(" * press any key to cancel");
77
+ // eslint-disable-next-line no-await-in-loop
78
+ await sleep(1);
79
+ }
80
+ }
81
+ render(rows) {
82
+ const header = [...statusTableHeader];
83
+ // const emptyColumns = Array.from({length: rows[0].length}).fill(0) as number[];
84
+ // for (const [, row] of rows.entries()) {
85
+ // for (const [j, cell] of row.entries()) {
86
+ // if (cell === '-') emptyColumns[j] += 1;
87
+ // }
88
+ // }
89
+ //
90
+ // for (const [j, cell] of emptyColumns.entries()) {
91
+ // if(cell === rows.length) {
92
+ // header.splice(j, 1);
93
+ // for (const [, row] of rows.entries()) {
94
+ // row.splice(j, 1);
95
+ // }
96
+ // }
97
+ // }
98
+ const options = { terminalAdapter: true };
99
+ const t1 = ttyTable(header, rows, options);
100
+ // hide cursor
101
+ console.log("\u001B[?25l");
102
+ // wipe existing if already rendered
103
+ if (this.alreadyRendered) {
104
+ // move cursor up number to the top of the previous print before deleting
105
+ console.log(`\u001B[${this.previousHeight + 3}A`);
106
+ // delete to end of terminal
107
+ console.log("\u001B[0J");
108
+ }
109
+ else {
110
+ this.alreadyRendered = true;
111
+ }
112
+ console.log(t1.render());
113
+ // reset the previous height to the height of this output
114
+ // for when we next clear the print
115
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
116
+ // @ts-expect-error
117
+ this.previousHeight = t1.height;
118
+ }
119
+ }
120
+ function sleep(sec) {
121
+ return new Promise(resolve => { setTimeout(resolve, sec * 1000); });
122
+ }
@@ -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
  const CHUNK_SIZE = 20_000;
9
10
  export class FastforwardService {
10
11
  dataDir;
@@ -15,21 +16,22 @@ export class FastforwardService {
15
16
  const { projectDir } = configStore.getProjectInfo();
16
17
  const { type } = configStore.getNetworkInfo();
17
18
  this.network = type;
18
- this.tmpDir = path.join(projectDir, 'gl0', 'tmp');
19
19
  this.dataDir = path.join(projectDir, 'gl0', 'data');
20
+ this.tmpDir = path.join(projectDir, 'gl0', 'data', 'tmp');
20
21
  fs.mkdirSync(this.tmpDir, { recursive: true });
21
- fs.mkdirSync(this.dataDir, { recursive: true });
22
- const env = configStore.getEnvNetworkInfo(type);
23
- // this.lbUrl = `https://l0-lb-${this.network}.constellationnetwork.io`;
24
- this.lbUrl = `http://${env.CL_L0_PEER_HTTP_HOST}:${env.CL_L0_PEER_HTTP_PORT}`;
22
+ // const env = configStore.getEnvNetworkInfo(type);
23
+ this.lbUrl = `https://l0-lb-${this.network}.constellationnetwork.io`;
24
+ // this.lbUrl = `http://${env.CL_L0_PEER_HTTP_HOST}:${env.CL_L0_PEER_HTTP_PORT}`;
25
25
  }
26
26
  static async synctoLatestSnapshot() {
27
27
  const ffs = new FastforwardService();
28
- await ffs.runFastForwardSnapshot().catch(() => {
28
+ await ffs.runFastForwardSnapshot().catch(async (error) => {
29
+ clm.debug(error);
29
30
  const { projectDir } = configStore.getProjectInfo();
30
31
  const dataDir = path.join(projectDir, 'gl0', 'data', 'incremental_snapshot', 'ordinal');
31
32
  if (fs.existsSync(dataDir) && fs.readdirSync(dataDir).length > 0) {
32
33
  clm.warn('Failed to fast forward to latest snapshot. Skipping...');
34
+ await promptHelper.doYouWishToContinue();
33
35
  return;
34
36
  }
35
37
  clm.error('Failed to fast forward to latest snapshot. Please try again later.');
@@ -43,7 +45,10 @@ export class FastforwardService {
43
45
  // clm.debug('hash', Buffer.from(jsSha256.sha256(compressedSnapshotIncremental)).toString('hex'));
44
46
  const snapshotInfoDir = path.join(this.dataDir, 'snapshot_info');
45
47
  fs.mkdirSync(snapshotInfoDir, { recursive: true });
46
- fs.writeFileSync(path.join(snapshotInfoDir, ordinal.toString()), compressedSnapshotInfo);
48
+ const ordinalDir = path.join(snapshotInfoDir, ordinal.toString());
49
+ clm.debug('Saving compressedSnapshotInfo to: ' + ordinalDir);
50
+ fs.writeFileSync(ordinalDir, compressedSnapshotInfo);
51
+ clm.debug('Saving compressedSnapshotIncremental to: ' + this.tmpDir);
47
52
  fs.writeFileSync(path.join(this.tmpDir, ordinal.toString() + '.c'), compressedSnapshotIncremental);
48
53
  await this.saveSnapshotFiles(ordinal.toString(), hash);
49
54
  clm.postStep(`Fastforward to snapshot "${ordinal}" completed.`);
@@ -94,9 +99,12 @@ export class FastforwardService {
94
99
  clm.warn(`Snapshot ${destOrdinalFile} already exists. Skipping...`);
95
100
  return;
96
101
  }
102
+ clm.debug(`Saving snapshot ${ordinal} to ${destOrdinalFile}`);
97
103
  fs.copyFileSync(ordinalFile, destOrdinalFile);
98
104
  const hashFile = path.join(hashDir, hash);
105
+ clm.debug(`Saving hashFile to ${hashFile}`);
99
106
  fs.linkSync(destOrdinalFile, hashFile);
107
+ clm.debug(`Saving snapshot version to ${path.join(this.dataDir, 'snapshot-version')}`);
100
108
  fs.writeFileSync(path.join(this.dataDir, 'snapshot-version'), `${this.network}:${ordinal}`);
101
109
  }
102
110
  }
@@ -13,6 +13,7 @@ export const nodeService = {
13
13
  .then(res => {
14
14
  if (res.ok)
15
15
  return res.json().then(i => ({ ...i, layer }));
16
+ clm.debug(`Failed to get node info from ${res.url} (${res.status})`);
16
17
  throw new Error(`Failed`);
17
18
  })
18
19
  .catch(() => ({ layer, state: "Unavailable" }));
@@ -62,7 +63,7 @@ export const nodeService = {
62
63
  const url = `http://localhost:${cliPort}/cluster/join`;
63
64
  clm.preStep(`Joining ${layer} to cluster`); // on ${cliPort}...${body} ... ${url}`);
64
65
  await shellService.execDockerShell(layer, `curl -X POST '${url}' -H 'Content-Type: application/json' --data '${body}'`);
65
- await this.pollForState(layer, 'Ready');
66
+ // await this.pollForState(layer, 'Ready');
66
67
  },
67
68
  async leaveCluster(layer) {
68
69
  const { state } = await this.getNodeInfo(layer);
@@ -103,7 +104,7 @@ export const nodeService = {
103
104
  async pollForState(layer, expectedState = 'ReadyToJoin') {
104
105
  clm.preStep(`Waiting for ${layer.toUpperCase()} Validator Node to become ${expectedState}...`);
105
106
  await sleep(1);
106
- for (let i = 1; i <= 60; i++) {
107
+ for (let i = 1; i <= 24; i++) {
107
108
  // eslint-disable-next-line no-await-in-loop
108
109
  const { state } = await this.getNodeInfo(layer);
109
110
  if (expectedState === 'Offline' && (state === "Unavailable" || state === "ReadyToJoin" || state === "SessionStarted"))
@@ -123,7 +124,7 @@ export const nodeService = {
123
124
  // eslint-disable-next-line no-await-in-loop
124
125
  await sleep(5);
125
126
  }
126
- clm.warn(`${layer} is not ${expectedState} after 5 minutes`);
127
+ clm.warn(`${layer} is not ${expectedState} after 2 minutes`);
127
128
  return false;
128
129
  }
129
130
  };
package/dist/types.d.ts CHANGED
@@ -38,14 +38,6 @@ export type ClusterStats = {
38
38
  startTime: string;
39
39
  total: number;
40
40
  };
41
- export type NodeStatusInfo = {
42
- clusterSession: string;
43
- id: string;
44
- inConsensus: boolean;
45
- inNetwork: boolean;
46
- ip: string;
47
- session: string;
48
- };
49
41
  export type NodeDiagnosticInfo = {
50
42
  collateral: number;
51
43
  hasCollateral: boolean;
@@ -3,6 +3,32 @@
3
3
  # Break on any error
4
4
  set -e
5
5
 
6
+ check_acl() {
7
+ # echo "Checking if ACL is enabled on filesystem"
8
+ if [[ "$(getfacl . | grep 'mask:')" != "" ]]; then
9
+ echo "✅ ACL is enabled on filesystem."
10
+ return 0
11
+ else
12
+ echo "⚠️ ACL is not enabled on filesystem. Attempting to enable it now."
13
+ if [[ "$(uname)" == "Linux" ]]; then
14
+ if command -v apt >/dev/null 2>&1; then
15
+ echo "Enabling ACL using apt..."
16
+ sudo apt install -y acl
17
+ else
18
+ echo "⚠️ Unsupported Linux distribution. Please enable ACL manually."
19
+ return 1
20
+ fi
21
+ echo "✅ ACL installation complete. "
22
+ elif [[ "$(uname)" == "Darwin" ]]; then
23
+ echo "⚠️ macOS does not support enabling ACL via this script. Please ensure ACL is enabled manually."
24
+ return 1
25
+ else
26
+ echo "⚠️ Unsupported OS: $(uname). Please enable ACL manually."
27
+ return 1
28
+ fi
29
+ fi
30
+ }
31
+
6
32
  # Check and install curl
7
33
  check_curl() {
8
34
  # echo "Checking for curl..."
@@ -62,16 +88,10 @@ check_docker() {
62
88
 
63
89
  case "$(uname)" in
64
90
  Linux)
65
- if command -v apt >/dev/null 2>&1; then
66
- echo "Installing Docker using script..."
67
- curl -fsSL https://get.docker.com -o get-docker.sh
68
- sudo sh ./get-docker.sh
69
- sudo usermod -aG docker $USER
70
- echo "Docker installed. You may need to log out and back in for group changes to take effect."
71
- else
72
- echo "⚠️ Unsupported Linux distribution. Please install Docker manually."
73
- return 1
74
- fi
91
+ echo "Installing Docker using script..."
92
+ curl -fsSL https://get.docker.com | sudo sh
93
+ sudo usermod -aG docker $USER
94
+ echo "Docker installed. You NEED to log out and log back in for the changes to take effect."
75
95
  ;;
76
96
  Darwin)
77
97
  echo "Please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
@@ -94,5 +114,6 @@ check_docker() {
94
114
 
95
115
  # Run all checks
96
116
  echo "🔍 Checking and installing required dependencies..."
117
+ check_acl
97
118
  check_curl
98
119
  check_docker
@@ -276,5 +276,5 @@
276
276
  ]
277
277
  }
278
278
  },
279
- "version": "0.0.14"
279
+ "version": "0.0.16"
280
280
  }
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.0.14",
4
+ "version": "0.0.16",
5
5
  "author": "Frank Fox",
6
6
  "bin": {
7
7
  "cpilot": "bin/run.js"
@@ -70,7 +70,8 @@
70
70
  "projects",
71
71
  "scripts",
72
72
  "README.md",
73
- "LICENSE"
73
+ "LICENSE",
74
+ "!**/source-nodes.env"
74
75
  ],
75
76
  "homepage": "https://github.com/Constellation-Labs/node-pilot",
76
77
  "keywords": [
@@ -3,10 +3,10 @@ networks:
3
3
  driver: bridge
4
4
 
5
5
  services:
6
- autoheal:
7
- image: willfarrell/autoheal
8
- volumes:
9
- - /var/run/docker.sock:/var/run/docker.sock
6
+ # autoheal:
7
+ # image: willfarrell/autoheal
8
+ # volumes:
9
+ # - /var/run/docker.sock:/var/run/docker.sock
10
10
  gl0:
11
11
  image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-latest}
12
12
  networks:
@@ -30,8 +30,8 @@ services:
30
30
  timeout: 15s
31
31
  start_period: 60s
32
32
  profiles: ["gl0"]
33
- labels:
34
- autoheal: "true"
33
+ # labels:
34
+ # autoheal: "true"
35
35
  gl1:
36
36
  image: constellationnetwork/tessellation${CL_DOCKER_CORE_REPO:-}:${DOCKER_IMAGE_VERSION:-latest}
37
37
  restart: unless-stopped
@@ -46,10 +46,11 @@ services:
46
46
  - ./gl1/data:/app/data
47
47
  - ./gl1/logs:/app/logs
48
48
  - ./key.p12:/app/key.p12:ro
49
- # healthcheck:
50
- # test: ["CMD", "/app/internal-health-check.sh"]
51
- # interval: 3s
52
- # timeout: 5s
53
- # retries: 5
54
- # start_period: 10s
49
+ healthcheck:
50
+ test: ["CMD", "cpilotHC"]
51
+ # test: ["CMD", "/health-check/bin/run.sh"]
52
+ interval: 15s
53
+ retries: 1
54
+ timeout: 15s
55
+ start_period: 60s
55
56
  profiles: ["gl1"]
@@ -11,7 +11,7 @@ check_java_home() {
11
11
  JAVA_HOME_LINE='export JAVA_HOME="$(dirname "$(dirname "$(readlink -f "$(which java)")")")"'
12
12
  echo "JAVA_HOME is not set. Attempting to set automatically"
13
13
  echo "Please ensure the following line is in your ~/.bashrc or ~/.zshrc file:"
14
- echo "Script will attempt to now add it for you and run it, but this only adds to .bashrc"
14
+ echo "Script will attempt to now add it for you and run it, but this only adds to .bashrc"
15
15
  echo $JAVA_HOME_LINE
16
16
  echo "$JAVA_HOME_LINE" >> $HOME/.bashrc
17
17
  echo "Adding JAVA_HOME to current environment"
@@ -215,94 +215,6 @@ check_curl() {
215
215
  return 0
216
216
  }
217
217
 
218
- # Check and install Docker Engine
219
- check_docker() {
220
- # echo "Checking for Docker..."
221
- if command -v docker >/dev/null 2>&1; then
222
- echo "✅ Docker is already installed."
223
- return 0
224
- fi
225
-
226
- echo "⚠️ Docker not found. Will attempt to install Docker."
227
-
228
- case "$(uname)" in
229
- Linux)
230
- if command -v apt >/dev/null 2>&1; then
231
- echo "Installing Docker using script..."
232
- curl -fsSL https://get.docker.com -o get-docker.sh
233
- sudo sh ./get-docker.sh
234
- sudo usermod -aG docker $USER
235
- echo "Docker installed. You may need to log out and back in for group changes to take effect."
236
- else
237
- echo "⚠️ Unsupported Linux distribution. Please install Docker manually."
238
- return 1
239
- fi
240
- ;;
241
- Darwin)
242
- echo "Please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
243
- return 1
244
- ;;
245
- MINGW*|MSYS*|CYGWIN*)
246
- echo "On Windows, please install Docker Desktop manually from https://www.docker.com/products/docker-desktop"
247
- return 1
248
- ;;
249
- *)
250
- echo "⚠️ Unsupported OS: $(uname). Please install Docker manually."
251
- return 1
252
- ;;
253
- esac
254
-
255
- echo "✅ Docker installation complete."
256
- return 0
257
- }
258
-
259
- # Check and install Node.js
260
- check_node() {
261
- # echo "Checking for Node.js..."
262
- if [ -d "$HOME/.nvm" ]; then
263
- echo "✅ Node.js is already installed."
264
- return 0
265
- fi
266
-
267
- echo "⚠️ Node.js not found. Will attempt to install Node.js."
268
-
269
- case "$(uname)" in
270
- Linux)
271
- echo "Installing Node.js using nvm..."
272
- # NPM
273
- curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
274
-
275
- # Load nvm without needing to open a new terminal
276
- export NVM_DIR="$HOME/.nvm"
277
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
278
- [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
279
-
280
- # Install node
281
- nvm install 22
282
-
283
- # Verify installation
284
- echo "Node version: $(node -v)"
285
- echo "NPM version: $(npm -v)"
286
- echo "NPX version: $(npx -v)"
287
- ;;
288
- Darwin)
289
- if command -v brew >/dev/null 2>&1; then
290
- echo "Installing Node.js using Homebrew..."
291
- brew install node
292
- else
293
- echo "⚠️ Homebrew not found. Please install Node.js manually."
294
- return 1
295
- fi
296
- ;;
297
- *)
298
- echo "⚠️ No Node.js installation needed for this OS: $(uname)"
299
- return 0
300
- ;;
301
- esac
302
-
303
- echo "✅ Node.js installation complete."
304
- return 0
305
- }
306
218
 
307
219
  # Run all checks
308
220
  echo "🔍 Checking and installing required dependencies..."
@@ -311,7 +223,5 @@ check_java_home
311
223
  check_jq
312
224
  check_wget
313
225
  check_curl
314
- check_docker
315
- check_node
316
226
 
317
227
  echo "All dependency checks completed."
@@ -103,6 +103,11 @@ download_asset() {
103
103
 
104
104
  # Download the asset
105
105
  echo "$ASSET_NAME -> $OUTPUT_NAME"
106
+ # DEBUG=${DEBUG:-false}
107
+ # SILENT="-s"
108
+ # if [ "$DEBUG" = "true" ]; then
109
+ # SILENT="-#"
110
+ # fi
106
111
  curl -# -L -H "Accept: application/octet-stream" -o "$OUTPUT_DIR/$OUTPUT_NAME" "$DOWNLOAD_URL"
107
112
 
108
113
  if [ $? -ne 0 ]; then
@@ -1,71 +1,119 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
+ # Find cpilot in PATH
3
4
  CPILOT=$(command -v cpilot)
4
5
  if [ -z "$CPILOT" ]; then
5
6
  echo "cpilot command not found. Please ensure Node Pilot is installed and accessible in your PATH."
6
7
  exit 1
7
8
  fi
8
9
 
9
- WORKING_DIR=/home/$USER/.config/systemd/user
10
+ # Get current user and home directory reliably
11
+ CURRENT_USER=$(id -un)
12
+ if [ "$CURRENT_USER" = "root" ]; then
13
+ IS_ROOT=true
14
+ WORKING_DIR="/etc/systemd/system"
15
+ HOME_DIR="/root"
16
+ UNIT_TARGET="multi-user.target"
17
+ else
18
+ IS_ROOT=false
19
+ HOME_DIR=$(eval echo ~$CURRENT_USER)
20
+ WORKING_DIR="$HOME_DIR/.config/systemd/user"
21
+ UNIT_TARGET="default.target"
22
+ fi
23
+
24
+ BIN_DIRECTORY="$HOME_DIR/.node-pilot/scripts"
10
25
 
11
- mkdir -p $WORKING_DIR
26
+ mkdir -p "$BIN_DIRECTORY"
12
27
 
13
- cat << EOF > $WORKING_DIR/restart-unhealthy.service
28
+ # Create working directory if it doesn't exist
29
+ mkdir -p "$WORKING_DIR"
30
+
31
+ # Create restart-unhealthy.service
32
+ cat << EOF > "$WORKING_DIR/restart-unhealthy.service"
14
33
  [Unit]
15
34
  Description=Restart unhealthy docker containers
16
35
  After=docker.service
17
36
  Wants=docker.service
18
37
 
19
38
  [Service]
20
- ExecStart=$WORKING_DIR/restart-unhealthy.sh
21
- Restart=always
22
- RestartSec=60s
39
+ Type=oneshot
40
+ ExecStart=$BIN_DIRECTORY/restart-unhealthy.sh
41
+ EOF
42
+
43
+ # Create restart-unhealthy.timer
44
+ cat <<EOF > "$WORKING_DIR/restart-unhealthy.timer"
45
+ [Unit]
46
+ Description=Run docker unhealthy restart every 5 minutes
47
+ Requires=restart-unhealthy.service
48
+ After=docker.service
49
+ Wants=docker.service
50
+
51
+ [Timer]
52
+ OnCalendar=*:0/1
53
+ Persistent=true
23
54
 
24
55
  [Install]
25
- WantedBy=docker.service
56
+ WantedBy=timers.target
26
57
  EOF
27
58
 
28
- cat << EOF > $WORKING_DIR/restart-unhealthy.sh
59
+ # Create restart-unhealthy.sh
60
+ cat << EOF > "$BIN_DIRECTORY/restart-unhealthy.sh"
29
61
  #!/usr/bin/env bash
30
62
  docker ps -q -f health=unhealthy | xargs --no-run-if-empty docker restart
31
63
  EOF
32
64
 
33
- chmod +x $WORKING_DIR/restart-unhealthy.sh
65
+ chmod +x "$BIN_DIRECTORY/restart-unhealthy.sh"
34
66
 
35
- cat << EOF > $WORKING_DIR/node-pilot-autostart.service
67
+ # Create node-pilot-autostart.service
68
+ cat << EOF > "$WORKING_DIR/node-pilot-autostart.service"
36
69
  [Unit]
37
70
  Description=Constellation Network Node Auto Restart Service
38
- After=default.target
71
+ After=$UNIT_TARGET
39
72
 
40
73
  [Service]
41
- ExecStart=$CPILOT restart --autostart
74
+ ExecStart=cpilot restart --autostart
42
75
 
43
76
  [Install]
44
- WantedBy=default.target
77
+ WantedBy=$UNIT_TARGET
45
78
  EOF
46
79
 
47
- cat << EOF > $WORKING_DIR/node-pilot-update.service
80
+ # Create node-pilot-update.service
81
+ cat << EOF > "$WORKING_DIR/node-pilot-update.service"
48
82
  [Unit]
49
83
  Description=Constellation Node Pilot Updater Service
50
- After=default.target
84
+ After=$UNIT_TARGET
51
85
 
52
86
  [Service]
53
- ExecStart=$CPILOT restart --update
87
+ ExecStart=cpilot restart --update
54
88
  Restart=always
55
89
  RestartSec=5m
56
90
 
57
91
  [Install]
58
- WantedBy=default.target
92
+ WantedBy=$UNIT_TARGET
59
93
  EOF
60
94
 
61
- systemctl --user daemon-reload
62
-
63
- systemctl --user enable restart-unhealthy.service
64
- systemctl --user enable node-pilot-autostart.service
65
- systemctl --user enable node-pilot-update.service
66
-
67
- systemctl --user start restart-unhealthy.service
68
- systemctl --user start node-pilot-autostart.service
69
- systemctl --user start node-pilot-update.service
70
-
71
- loginctl enable-linger $USER
95
+ # Enable and start services/timers
96
+ if [ "$IS_ROOT" = true ]; then
97
+ systemctl daemon-reload
98
+ systemctl enable restart-unhealthy.timer
99
+ systemctl enable node-pilot-autostart.service
100
+ systemctl enable node-pilot-update.service
101
+
102
+ systemctl start restart-unhealthy.timer
103
+ systemctl start node-pilot-autostart.service
104
+ systemctl start node-pilot-update.service
105
+ else
106
+ systemctl --user daemon-reload
107
+ systemctl --user enable restart-unhealthy.timer
108
+ systemctl --user enable node-pilot-autostart.service
109
+ systemctl --user enable node-pilot-update.service
110
+
111
+ systemctl --user start restart-unhealthy.timer
112
+ systemctl --user start node-pilot-autostart.service
113
+ systemctl --user start node-pilot-update.service
114
+
115
+ # Enable linger for the user to allow user services to run without login
116
+ loginctl enable-linger "$CURRENT_USER"
117
+ fi
118
+ #systemctl --user status node-pilot-update.service
119
+ # systemctl --user status restart-unhealthy
@@ -0,0 +1,11 @@
1
+ [Unit]
2
+ Description=Constellation Node Pilot Updater Service
3
+ After=default.target
4
+
5
+ [Service]
6
+ ExecStart=/bin/bash -lc "echo $HOME : $(which node) >> /home/ubuntu/service.log"
7
+ Restart=always
8
+ RestartSec=5m
9
+
10
+ [Install]
11
+ WantedBy=default.target
@@ -1,9 +0,0 @@
1
- SOURCE_NODE_1_PORT=9000
2
- SOURCE_NODE_1_HOST=13.52.205.240
3
- SOURCE_NODE_1_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
4
- SOURCE_NODE_2_PORT=9000
5
- SOURCE_NODE_2_HOST=50.18.155.22
6
- SOURCE_NODE_2_ID=3458a688925a4bd89f2ac2c695362e44d2e0c2903bdbb41b341a4d39283b22d8c85b487bd33cc5d36dbe5e31b5b00a10a6eab802718ead4ed7192ade5a5d1941
7
- SOURCE_NODE_3_PORT=9000
8
- SOURCE_NODE_3_HOST=52.9.216.57
9
- SOURCE_NODE_3_ID=46daea11ca239cb8c0c8cdeb27db9dbe9c03744908a8a389a60d14df2ddde409260a93334d74957331eec1af323f458b12b3a6c3b8e05885608aae7e3a77eac7
@@ -1,9 +0,0 @@
1
- SOURCE_NODE_1_PORT=9000
2
- SOURCE_NODE_1_HOST=52.53.46.33
3
- SOURCE_NODE_1_ID=e0c1ee6ec43510f0e16d2969a7a7c074a5c8cdb477c074fe9c32a9aad8cbc8ff1dff60bb81923e0db437d2686a9b65b86c403e6a21fa32b6acc4e61be4d70925
4
- SOURCE_NODE_2_PORT=9000
5
- SOURCE_NODE_2_HOST=54.215.18.98
6
- SOURCE_NODE_2_ID=629880a5b8d4cc6d12aec26f24230a463825c429723153aeaff29475b29e39d2406af0f8b034ba7798ae598dbd5f513d642bcbbeef088290abeadac61a0445d6
7
- SOURCE_NODE_3_PORT=9000
8
- SOURCE_NODE_3_HOST=54.151.19.111
9
- SOURCE_NODE_3_ID=710b3dc521b805aea7a798d61f5d4dae39601124f1f34fac9738a78047adeff60931ba522250226b87a2194d3b7d39da8d2cbffa35d6502c70f1a7e97132a4b0
@@ -1,9 +0,0 @@
1
- SOURCE_NODE_1_PORT=9000
2
- SOURCE_NODE_1_HOST=52.8.132.193
3
- SOURCE_NODE_1_ID=e2f4496e5872682d7a55aa06e507a58e96b5d48a5286bfdff7ed780fa464d9e789b2760ecd840f4cb3ee6e1c1d81b2ee844c88dbebf149b1084b7313eb680714
4
- SOURCE_NODE_2_PORT=9000
5
- SOURCE_NODE_2_HOST=13.57.110.45
6
- SOURCE_NODE_2_ID=3458a688925a4bd89f2ac2c695362e44d2e0c2903bdbb41b341a4d39283b22d8c85b487bd33cc5d36dbe5e31b5b00a10a6eab802718ead4ed7192ade5a5d1941
7
- SOURCE_NODE_3_PORT=9000
8
- SOURCE_NODE_3_HOST=54.153.23.79
9
- SOURCE_NODE_3_ID=46daea11ca239cb8c0c8cdeb27db9dbe9c03744908a8a389a60d14df2ddde409260a93334d74957331eec1af323f458b12b3a6c3b8e05885608aae7e3a77eac7