Skip to content

Commit e491fc6

Browse files
committed
containerized and tested working
1 parent 38b75ab commit e491fc6

File tree

8 files changed

+191
-115
lines changed

8 files changed

+191
-115
lines changed

container-manager/docker-compose.yml

Lines changed: 0 additions & 9 deletions
This file was deleted.

container-manager/src/express.js

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,20 @@ app.get("/", (req, res) => {
1313
});
1414

1515
app.get("/test", async (req, res) => {
16+
console.log("/test called");
1617
const response = await state.checkMining();
1718
console.log(response);
1819
res.setHeader("Content-Type", "application/json");
1920
res.send(JSON.stringify(response, null, 2));
2021
});
2122

2223
app.get("/state", async (req, res) => {
23-
// const response = await state.getContainersState()
24+
console.log("/state called");
2425
const response = await state.getSubnetContainers();
2526
res.setHeader("Content-Type", "application/json");
2627
res.send(JSON.stringify(response, null, 2));
2728
});
2829

29-
app.get("/start_subnet", async (req, res) => {
30-
await exec.startComposeProfile("machine1");
31-
const response = await docker.getContainersState();
32-
res.setHeader("Content-Type", "application/json");
33-
res.send(JSON.stringify(response, null, 2));
34-
});
35-
3630
app.get("/events", (req, res) => {
3731
res.setHeader("Content-Type", "text/event-stream");
3832
res.setHeader("Cache-Control", "no-cache");
@@ -60,26 +54,42 @@ app.get("/stream", async (req, res) => {
6054
res.setHeader("Content-Type", "text/event-stream");
6155
res.setHeader("Cache-Control", "no-cache");
6256
res.setHeader("Connection", "keep-alive");
63-
await exec.executeTest(
64-
"",
65-
(data) => {
66-
res.write(`data:${data}\n\n`);
67-
},
68-
() => {
69-
res.write("event: close\ndata: Connection closed by server\n\n");
70-
res.end();
71-
}
72-
);
57+
const dataCallback = (data) => {
58+
res.write(`data:${data}\n\n`);
59+
};
60+
61+
const doneCallback = () => {
62+
res.write("event: close\ndata: Connection closed by server\n\n");
63+
res.end();
64+
};
65+
await exec.executeTest("", dataCallback, doneCallback);
66+
// await exec.executeTest(
67+
// "",
68+
// (data) => {
69+
// res.write(`data:${data}\n\n`);
70+
// },
71+
// () => {
72+
// res.write("event: close\ndata: Connection closed by server\n\n");
73+
// res.end();
74+
// }
75+
// );
7376

7477
// Handle client disconnect
7578
req.on("close", () => {
7679
res.end();
7780
});
7881
});
7982

83+
app.get("/start_subnet", async (req, res) => {
84+
console.log("/start_subnet called");
85+
const response = await exec.startComposeProfile("machine1");
86+
res.setHeader("Content-Type", "application/json");
87+
res.send(JSON.stringify(response, null, 2));
88+
});
89+
8090
app.get("/deploy_csc", async (req, res) => {
81-
exec.deployContract("csc");
82-
const response = await docker.getContainersState();
91+
console.log("/deploy_csc called");
92+
const response = await exec.deployContract("csc");
8393
res.setHeader("Content-Type", "application/json");
8494
res.send(JSON.stringify(response, null, 2));
8595
});

container-manager/src/libs/config.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ const fs = require("fs");
33
const yaml = require("js-yaml");
44
const path = require("path");
55
const mountPath = path.join(__dirname, "../../mount/generated/");
6-
console.log(mountPath);
7-
86
const config = {};
97

8+
module.exports = config;
9+
1010
initModule();
1111

1212
function initModule() {
@@ -15,6 +15,11 @@ function initModule() {
1515
throw Error(`Incomplete mount, did not find: ${name}`);
1616
}
1717
config["compose"] = getComposeCommand();
18+
19+
config["hostPath"] = process.env.HOSTPWD || "";
20+
if (config["hostPath"] === "") {
21+
throw Error("Incomplete container start, did not find env: HOSTPWD");
22+
}
1823
}
1924

2025
function checkFiles() {

container-manager/src/libs/exec.js

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,72 +10,91 @@ module.exports = {
1010
executeTest,
1111
};
1212

13-
function startComposeProfile(profile) {
14-
const compose = config.compose;
15-
executeCommandSync(`${compose} --profile ${profile} pull`);
16-
executeCommandSync(`${compose} --profile ${profile} up -d`);
13+
const streamExecOutput = (data) => {
14+
console.log(data);
15+
};
16+
17+
const doneExec = () => {
18+
console.log("Execute Done!!");
19+
};
20+
21+
async function startComposeProfile(profile) {
22+
await execute(
23+
`${config.compose} --profile ${profile} pull`,
24+
streamExecOutput,
25+
doneExec
26+
);
27+
await execute(
28+
`${config.compose} --profile ${profile} up -d`,
29+
streamExecOutput,
30+
doneExec
31+
);
32+
return {};
1733
}
1834

19-
function stopComposeProfile(profile) {
20-
const compose = config.compose;
21-
executeCommandSync(`${compose} --profile ${profile} down`);
35+
async function stopComposeProfile(profile) {
36+
await execute(
37+
`${config.compose} --profile ${profile} down`,
38+
streamExecOutput,
39+
doneExec
40+
);
41+
return {};
2242
}
2343

24-
function deployContract() {
44+
async function deployContract() {
2545
// docker pull xinfinorg/csc:feature-v0.3.0
2646
// docker run -v ${PWD}/:/app/cicd/mnt/ --network generated_docker_net xinfinorg/csc:feature-v0.3.0 full
2747
// need to figure what to use instead of ${PWD}, probably need host full path
2848

29-
executeCommandSync(`docker pull xinfinorg/csc:feature-v0.3.0`);
30-
executeCommandSync(
31-
`docker run -v /Users/wp/Git/Subnet-Deployment/container-manager/mount/generated/:/app/cicd/mount/ --network generated_docker_net xinfinorg/csc:feature-v0.3.0 full`
32-
);
49+
await execute(
50+
`docker pull xinfinorg/csc:feature-v0.3.0`,
51+
streamExecOutput,
52+
doneExec
53+
); //TODO: pass version from some global conf or env
54+
await execute(
55+
`docker run -v ${config.hostPath}/generated/:/app/cicd/mount/ --network docker_net xinfinorg/csc:feature-v0.3.0 full`,
56+
streamExecOutput,
57+
doneExec
58+
); //TODO: use detected network name
59+
return {};
3360
}
3461

35-
// function executeCommandSync(command) {
36-
// const pathCommand = 'cd '+mountPath+';'+'export PWD=/Users/wp/Git/Subnet-Deployment/container-manager/mount/generated;'+command
37-
// const output = execSync(pathCommand).toString();
38-
// console.log(`Command output: ${output}`);
39-
// return output;
40-
// // // Example usage:
41-
// // try {
42-
// // const output = executeCommandSync('ls -l');
43-
// // console.log('Command output:', output);
44-
// // } catch (error) {
45-
// // console.error('Error:', error);
46-
// // }
47-
// }
48-
49-
//test command
50-
// executeTest('echo a; sleep 1; echo b; sleep 1; echo c; sleep 1; skdjf;asjdkfasjdflsa; sleep 1; exit 1; sleep 1; echo f')
5162
async function executeTest(command, outputHandler, doneHandler) {
5263
command =
5364
"echo $RANDOM; sleep 1; echo $RANDOM; sleep 1; echo a; sleep 1; echo b; sleep 1; echo c; sleep 1; echo d; sleep 1; echo e; sleep 1; echo f";
65+
execute(command, outputHandler, doneHandler);
66+
}
67+
68+
async function execute(command, outputHandler, doneHandler) {
69+
console.log("executing", command);
5470
const pathCommand =
5571
"cd " +
5672
mountPath +
5773
";" +
5874
"export PWD=/Users/wp/Git/Subnet-Deployment/container-manager/mount/generated;" +
5975
command;
60-
execProcess = exec(pathCommand);
61-
62-
execProcess.stdout.on("data", (data) => {
63-
process.stdout.write(data.toString());
64-
outputHandler(data.toString());
65-
});
66-
67-
execProcess.stderr.on("data", (data) => {
68-
console.error(data.toString());
69-
outputHandler(data.toString());
70-
});
7176

72-
execProcess.on("error", (err) => {
73-
console.error("Failed to start exec process:", err.message);
74-
doneHandler();
77+
const prom = new Promise((resolve, reject) => {
78+
const execProcess = exec(pathCommand);
79+
execProcess.stdout.on("data", (data) => {
80+
outputHandler(data.toString());
81+
// process.stdout.write(data.toString());
82+
});
83+
execProcess.stderr.on("data", (data) => {
84+
console.error(data.toString());
85+
outputHandler(data.toString());
86+
});
87+
execProcess.on("error", (err) => {
88+
console.error("Failed to start exec process:", err.message);
89+
doneHandler();
90+
reject(err); // Reject the Promise on error
91+
});
92+
execProcess.on("close", (code) => {
93+
console.log(`Exec process exited with code ${code}`);
94+
doneHandler();
95+
resolve(code); // Resolve the Promise on close
96+
});
7597
});
7698

77-
execProcess.on("close", (code) => {
78-
console.log(`Exec process exited with code ${code}`);
79-
doneHandler();
80-
});
99+
return prom;
81100
}

container-manager/src/libs/state.js

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,20 @@ async function getSubnetContainers() {
1919
const filtered = [];
2020
for (let i = 0; i < containers.length; i++) {
2121
if (containers[i].Names[0].includes("generated")) {
22-
const networkName = containers[i].HostConfig.NetworkMode;
2322
const c = {
2423
name: containers[i].Names[0].substring(1),
2524
image: containers[i].Image,
2625
state: containers[i].State,
2726
status: containers[i].Status,
28-
network: networkName,
29-
ip: containers[i].NetworkSettings.Networks[networkName].IPAMConfig
30-
.IPv4Address,
3127
};
28+
const networkName = containers[i].HostConfig.NetworkMode;
29+
const ip =
30+
containers[i].NetworkSettings.Networks[networkName].IPAMConfig
31+
.IPv4Address;
32+
const rpcPort = extractRPCPort(c.name);
33+
c.network = networkName;
34+
c.ip = ip;
35+
c.rpcPort = rpcPort;
3236
filtered.push(c);
3337
}
3438
}
@@ -61,8 +65,8 @@ async function checkMining() {
6165
for (let i = 0; i < containers.length; i++) {
6266
const c = containers[i];
6367
if (c.name.includes("subnet") && c.state == "running") {
64-
blockHeights.push(await checkBlock(c.ip));
65-
peerCounts.push(await checkPeers(c.ip));
68+
blockHeights.push(await checkBlock(c.ip, c.rpcPort));
69+
peerCounts.push(await checkPeers(c.ip, c.rpcPort));
6670
}
6771
}
6872
return {
@@ -71,9 +75,8 @@ async function checkMining() {
7175
};
7276
}
7377

74-
async function checkBlock(containerIP) {
75-
// const url = `http://${containerIP}:8545`;
76-
const url = `http://localhost:8545`; //local testing
78+
async function checkBlock(containerIP, containerPort) {
79+
let url = `http://${containerIP}:${containerPort}`;
7780
const data = {
7881
jsonrpc: "2.0",
7982
method: "XDPoS_getV2BlockByNumber",
@@ -85,18 +88,23 @@ async function checkBlock(containerIP) {
8588
};
8689

8790
try {
88-
const response = await axios.post(url, data, { headers });
91+
let response;
92+
try {
93+
response = await axios.post(url, data, { headers, timeout: 2000 });
94+
} catch (error) {
95+
url = `http://localhost:${containerPort}`; //fallback for local testing
96+
response = await axios.post(url, data, { headers, timeout: 2000 });
97+
}
8998
let block = response.data.result.Number;
9099
if (block == null) block = 0;
91100
return block;
92101
} catch (error) {
93-
console.error(error);
102+
console.log(error);
94103
}
95104
}
96105

97-
async function checkPeers(containerIP) {
98-
// const url = `http://${containerIP}:8545`;
99-
const url = `http://localhost:8545`; //local testing
106+
async function checkPeers(containerIP, containerPort) {
107+
let url = `http://${containerIP}:${containerPort}`;
100108
const data = {
101109
jsonrpc: "2.0",
102110
method: "net_peerCount",
@@ -107,7 +115,13 @@ async function checkPeers(containerIP) {
107115
};
108116

109117
try {
110-
const response = await axios.post(url, data, { headers });
118+
let response;
119+
try {
120+
response = await axios.post(url, data, { headers, timeout: 2000 });
121+
} catch (error) {
122+
url = `http://localhost:${containerPort}`; //fallback for local testing
123+
response = await axios.post(url, data, { headers, timeout: 2000 });
124+
}
111125
const peerHex = response.data.result;
112126
const peerCount = parseInt(peerHex, 16);
113127
return peerCount;
@@ -133,3 +147,12 @@ function isSubnetContainer(container) {
133147
}
134148
return [isSubnet, name];
135149
}
150+
151+
function extractRPCPort(name) {
152+
const shortName = name.split("-")[1];
153+
nodeNum = parseInt(shortName.replace("subnet", ""));
154+
// if (nodeNum === null) {
155+
// return 9999;
156+
// }
157+
return 8545 + nodeNum - 1;
158+
}

container-manager/start.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
current_dir="$(cd "$(dirname "$0")" && pwd)"
4+
network_name="docker_net"
5+
6+
mkdir -p generated/scripts
7+
8+
if ! docker network inspect "$network_name" > /dev/null 2>&1; then
9+
echo "Network '$network_name' does not exist. Creating it..."
10+
docker network create --subnet 192.168.25.0/24 "$network_name"
11+
else
12+
echo "Joining existing network '$network_name'"
13+
fi
14+
15+
docker run -d \
16+
--network "docker_net" --ip=192.168.25.111 \
17+
-p 3000:3000 \
18+
-v /var/run/docker.sock:/var/run/docker.sock \
19+
-v $current_dir/generated:/mount/generated \
20+
-e HOSTPWD=/Users/wp/Git/Subnet-Deployment/container-manager/mount \
21+
api-test
22+
23+
24+
# services:
25+
# docker-tester:
26+
# image: api-test
27+
# volumes:
28+
# - /var/run/docker.sock:/var/run/docker.sock
29+
# - ${PWD}/mount/generated/:/mount/generated/
30+
# ports:
31+
# - 3000:3000

0 commit comments

Comments
 (0)