@zombienet/orchestrator
Version:
ZombieNet aim to be a testing framework for substrate based blockchains, providing a simple cli tool that allow users to spawn and test ephemeral Substrate based networks
293 lines (292 loc) • 12.9 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.genCumulusCollatorCmd = genCumulusCollatorCmd;
exports.genCmd = genCmd;
const utils_1 = require("@zombienet/utils");
const constants_1 = require("./constants");
const sharedTypes_1 = require("./sharedTypes");
const debug = require("debug")("zombie::cmdGenerator");
function parseCmdWithArguments(commandWithArgs, useWrapper = true) {
const parts = commandWithArgs.split(" ");
let finalCommand = [];
if (["bash", "ash"].includes(parts[0])) {
finalCommand.push(parts[0]);
let partIndex;
if (parts[1] === "-c") {
finalCommand.push(parts[1]);
partIndex = 2;
}
else {
finalCommand.push("-c");
partIndex = 1;
}
finalCommand = [...finalCommand, ...[parts.slice(partIndex).join(" ")]];
}
else {
finalCommand = [commandWithArgs];
if (useWrapper)
finalCommand.unshift("/cfg/zombie-wrapper.sh");
}
return finalCommand;
}
function genCumulusCollatorCmd(nodeSetup_1) {
return __awaiter(this, arguments, void 0, function* (nodeSetup, cfgPath = "/cfg", dataPath = "/data", relayDataPath = "/relay-data", useWrapper = true) {
const { name, chain, parachainId, key, validator, commandWithArgs } = nodeSetup;
// command with args
if (commandWithArgs) {
return parseCmdWithArguments(commandWithArgs, useWrapper);
}
const parachainAddedArgs = {
"--name": true,
"--collator": true,
"--base-path": true,
"--port": true,
"--ws-port": true,
"--rpc-port": true,
"--chain": true,
"--prometheus-port": true,
};
// bind localhost only in native provider
const ip_to_bind = useWrapper ? "0.0.0.0" : "127.0.0.1";
let fullCmd = [
nodeSetup.command || constants_1.DEFAULT_COMMAND,
"--name",
name,
"--node-key",
key,
"--chain",
`${cfgPath}/${chain}-${parachainId}.json`,
"--base-path",
dataPath,
"--listen-addr",
`/ip4/${ip_to_bind}/tcp/${nodeSetup.p2pPort ? nodeSetup.p2pPort : constants_1.P2P_PORT}/ws`,
"--prometheus-external",
"--rpc-cors all",
// Do not add `--unsafe-rpc-external` in native provider
useWrapper ? "--unsafe-rpc-external" : "",
"--rpc-methods unsafe",
];
if (nodeSetup.substrateCliArgsVersion === sharedTypes_1.SubstrateCliArgsVersion.V0)
fullCmd.push("--unsafe-ws-external");
const portFlags = getPortFlagsByCliArgsVersion(nodeSetup);
for (const [k, v] of Object.entries(portFlags)) {
fullCmd.push(...[k, v.toString()]);
}
const chainParts = chain.split("_");
const relayChain = chainParts.length > 1 ? chainParts[chainParts.length - 1] : chainParts[0];
if (validator)
fullCmd.push(...["--collator"]);
// ports passed to the relaychain part of the collator binary
const collatorPorts = {
"--port": 0,
"--rpc-port": 0,
"--prometheus-port": 0,
};
if (nodeSetup.args.length > 0) {
let argsFullNode = null;
let argsParachain = null;
const splitIndex = nodeSetup.args.indexOf("--");
if (splitIndex < 0) {
argsParachain = nodeSetup.args;
}
else {
argsParachain = nodeSetup.args.slice(0, splitIndex);
argsFullNode = nodeSetup.args.slice(splitIndex + 1);
}
if (argsParachain) {
for (const arg of argsParachain) {
if (parachainAddedArgs[arg])
continue;
// add
debug(`adding ${arg}`);
fullCmd.push(arg);
}
}
// Arguments for the relay chain node part of the collator binary.
fullCmd.push(...[
"--",
"--base-path",
relayDataPath,
"--chain",
`${cfgPath}/${relayChain}.json`,
"--execution wasm",
]);
if (argsFullNode) {
// Add any additional flags to the CLI
for (const [index, arg] of argsFullNode.entries()) {
if (collatorPorts[arg] >= 0) {
// port passed as argument, we need to ensure is not a default one because it will be
// use by the parachain part.
const selectedPort = parseInt(argsFullNode[index + 1], 10);
if ([
constants_1.P2P_PORT,
constants_1.RPC_HTTP_PORT,
constants_1.RPC_WS_PORT,
nodeSetup.p2pPort,
nodeSetup.rpcPort,
nodeSetup.wsPort,
].includes(selectedPort)) {
console.log(utils_1.decorators.yellow(`WARN: default port configured, changing to use a random free port`));
const randomPort = yield (0, utils_1.getRandomPort)();
collatorPorts[arg] = randomPort;
argsFullNode[index + 1] = randomPort.toString();
}
}
}
// check ports
for (const portArg of Object.keys(collatorPorts)) {
if (collatorPorts[portArg] === 0) {
const randomPort = yield (0, utils_1.getRandomPort)();
argsFullNode.push(portArg);
argsFullNode.push(randomPort.toString());
debug(`Added ${portArg} with value ${randomPort}`);
}
}
fullCmd = fullCmd.concat(argsFullNode);
debug(`Added ${argsFullNode} to collator`);
}
else {
// ensure ports
for (const portArg of Object.keys(collatorPorts)) {
if (collatorPorts[portArg] === 0) {
const randomPort = yield (0, utils_1.getRandomPort)();
fullCmd.push(portArg);
fullCmd.push(randomPort.toString());
debug(`Added ${portArg} with value ${randomPort}`);
}
}
}
}
else {
// no args
// Arguments for the relay chain node part of the collator binary.
fullCmd.push(...["--", "--chain", `${cfgPath}/${relayChain}.json`, "--execution wasm"]);
// ensure ports
for (const portArg of Object.keys(collatorPorts)) {
if (collatorPorts[portArg] === 0) {
const randomPort = yield (0, utils_1.getRandomPort)();
fullCmd.push(portArg);
fullCmd.push(randomPort.toString());
debug(`Added ${portArg} with value ${randomPort}`);
}
}
}
const resolvedCmd = [fullCmd.join(" ")];
if (useWrapper)
resolvedCmd.unshift("/cfg/zombie-wrapper.sh");
return resolvedCmd;
});
}
function genCmd(nodeSetup_1) {
return __awaiter(this, arguments, void 0, function* (nodeSetup, cfgPath = "/cfg", dataPath = "/data", useWrapper = true) {
const { name, key, chain, commandWithArgs, fullCommand, telemetry, telemetryUrl, prometheus, validator, bootnodes, zombieRole, jaegerUrl, parachainId, } = nodeSetup;
let { command, args } = nodeSetup;
// fullCommand is NOT decorated by the `zombie` wrapper
// and is used internally in init containers.
if (fullCommand)
return ["bash", "-c", fullCommand];
// command with args
if (commandWithArgs) {
return parseCmdWithArguments(commandWithArgs, useWrapper);
}
if (!command)
command = constants_1.DEFAULT_COMMAND;
args = [...args];
args.push("--no-mdns");
if (key)
args.push(...["--node-key", key]);
if (!telemetry)
args.push("--no-telemetry");
else
args.push(...["--telemetry-url", telemetryUrl]);
if (prometheus && !args.includes("--prometheus-external"))
args.push("--prometheus-external");
if (jaegerUrl && zombieRole === sharedTypes_1.ZombieRole.Node)
args.push(...["--jaeger-agent", jaegerUrl]);
if (validator) {
if (!args.includes("--validator"))
args.push("--validator");
if (nodeSetup.substrateCliArgsVersion &&
nodeSetup.substrateCliArgsVersion >= sharedTypes_1.SubstrateCliArgsVersion.V2) {
args.push("--insecure-validator-i-know-what-i-do");
}
}
if (zombieRole === sharedTypes_1.ZombieRole.Collator && parachainId) {
const parachainIdArgIndex = args.findIndex((arg) => arg.includes("--parachain-id"));
if (parachainIdArgIndex >= 0)
args.splice(parachainIdArgIndex, 1);
args.push(`--parachain-id ${parachainId}`);
}
if (bootnodes && bootnodes.length)
args.push("--bootnodes", bootnodes.join(" "));
const portFlags = getPortFlagsByCliArgsVersion(nodeSetup);
for (const [k, v] of Object.entries(portFlags)) {
args.push(...[k, v.toString()]);
}
const listenIndex = args.findIndex((arg) => arg === "--listen-addr");
if (listenIndex >= 0) {
const listenAddrParts = args[listenIndex + 1].split("/");
listenAddrParts[4] = `${nodeSetup.p2pPort}`;
const listenAddr = listenAddrParts.join("/");
args[listenIndex + 1] = listenAddr;
}
else {
// no --listen-add args
// bind localhost only in native provider
const ip_to_bind = useWrapper ? "0.0.0.0" : "127.0.0.1";
args.push(...["--listen-addr", `/ip4/${ip_to_bind}/tcp/${nodeSetup.p2pPort}/ws`]);
}
// set our base path
const basePathFlagIndex = args.findIndex((arg) => arg === "--base-path");
if (basePathFlagIndex >= 0)
args.splice(basePathFlagIndex, 2);
args.push(...["--base-path", dataPath]);
if (nodeSetup.substrateCliArgsVersion === sharedTypes_1.SubstrateCliArgsVersion.V0)
args.push("--unsafe-ws-external");
const finalArgs = [
command,
"--chain",
`${cfgPath}/${chain}.json`,
"--name",
name,
"--rpc-cors",
"all",
// Do not add `--unsafe-rpc-external` in native provider
useWrapper ? "--unsafe-rpc-external" : "",
"--rpc-methods",
"unsafe",
...args,
];
const resolvedCmd = [finalArgs.join(" ")];
if (useWrapper)
resolvedCmd.unshift("/cfg/zombie-wrapper.sh");
return resolvedCmd;
});
}
const getPortFlagsByCliArgsVersion = (nodeSetup) => {
// port flags logic
const portFlags = {
"--prometheus-port": (nodeSetup.prometheusPort || constants_1.PROMETHEUS_PORT).toString(),
};
if (nodeSetup.substrateCliArgsVersion === sharedTypes_1.SubstrateCliArgsVersion.V0) {
portFlags["--rpc-port"] = (nodeSetup.rpcPort || constants_1.RPC_HTTP_PORT).toString();
portFlags["--ws-port"] = (nodeSetup.wsPort || constants_1.RPC_WS_PORT).toString();
}
else {
// use rpc_port as default (since ws_port was deprecated in https://github.com/paritytech/substrate/pull/13384)
const portToUse = nodeSetup.rpcPort
? nodeSetup.rpcPort
: nodeSetup.wsPort || constants_1.RPC_HTTP_PORT;
portFlags["--rpc-port"] = portToUse.toString();
}
return portFlags;
};