From 3ac46f2d5701bc9fd8ce9393dd1f9c8555a76c0e Mon Sep 17 00:00:00 2001 From: l0r1s Date: Mon, 3 Apr 2023 23:28:35 +0300 Subject: [PATCH] feat: refactored into NodeResource for native provider --- .../providers/native/dynResourceDefinition.ts | 56 +------ .../src/providers/native/resources/index.ts | 1 + .../native/resources/node.resource.ts | 153 ++++++++++++++++++ .../src/providers/native/resources/types.ts | 37 +++++ 4 files changed, 195 insertions(+), 52 deletions(-) create mode 100644 javascript/packages/orchestrator/src/providers/native/resources/index.ts create mode 100644 javascript/packages/orchestrator/src/providers/native/resources/node.resource.ts create mode 100644 javascript/packages/orchestrator/src/providers/native/resources/types.ts diff --git a/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts b/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts index b68f91874..1ea59bf1a 100644 --- a/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts +++ b/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts @@ -1,5 +1,5 @@ import { getRandomPort, makeDir } from "@zombienet/utils"; -import { genCmd, genCumulusCollatorCmd } from "../../cmdGenerator"; +import { genCmd } from "../../cmdGenerator"; import { getUniqueName } from "../../configGenerator"; import { P2P_PORT, @@ -10,6 +10,7 @@ import { import { Network } from "../../network"; import { Node, envVars } from "../../types"; import { getClient } from "../client"; +import { NodeResource } from "./resources"; interface processEnvironment { [key: string]: string; @@ -60,58 +61,9 @@ export async function genNodeDef( nodeSetup: Node, ): Promise { const client = getClient(); - const name = nodeSetup.name; - const { rpcPort, wsPort, prometheusPort, p2pPort } = nodeSetup; - const ports = await getPorts(rpcPort, wsPort, prometheusPort, p2pPort); - const cfgPath = `${client.tmpDir}/${name}/cfg`; - await makeDir(cfgPath, true); - - const dataPath = `${client.tmpDir}/${name}/data`; - await makeDir(dataPath, true); + const nodeResource = new NodeResource(client, namespace, nodeSetup); - const relayDataPath = `${client.tmpDir}/${name}/relay-data`; - await makeDir(relayDataPath, true); - - let computedCommand; - if (nodeSetup.zombieRole === "cumulus-collator") { - computedCommand = await genCumulusCollatorCmd( - nodeSetup, - cfgPath, - dataPath, - relayDataPath, - false, - ); - } else { - computedCommand = await genCmd(nodeSetup, cfgPath, dataPath, false); - } - - return { - metadata: { - name: nodeSetup.name, - namespace: namespace, - labels: { - "zombie-role": nodeSetup.zombieRole - ? nodeSetup.zombieRole - : nodeSetup.validator - ? "authority" - : "full-node", - app: "zombienet", - "zombie-ns": namespace, - name: namespace, - instance: nodeSetup.name, - }, - }, - spec: { - cfgPath, - dataPath, - ports, - command: computedCommand, - env: nodeSetup.env.reduce((memo, item: envVars) => { - memo[item.name] = item.value; - return memo; - }, {} as processEnvironment), - }, - }; + return nodeResource.generateSpec(); } async function getPorts( diff --git a/javascript/packages/orchestrator/src/providers/native/resources/index.ts b/javascript/packages/orchestrator/src/providers/native/resources/index.ts new file mode 100644 index 000000000..2ec93ea9a --- /dev/null +++ b/javascript/packages/orchestrator/src/providers/native/resources/index.ts @@ -0,0 +1 @@ +export { NodeResource } from "./node.resource"; diff --git a/javascript/packages/orchestrator/src/providers/native/resources/node.resource.ts b/javascript/packages/orchestrator/src/providers/native/resources/node.resource.ts new file mode 100644 index 000000000..207e47103 --- /dev/null +++ b/javascript/packages/orchestrator/src/providers/native/resources/node.resource.ts @@ -0,0 +1,153 @@ +import { getRandomPort, makeDir } from "@zombienet/utils"; +import { genCmd, genCumulusCollatorCmd } from "../../../cmdGenerator"; +import { + P2P_PORT, + PROMETHEUS_PORT, + RPC_HTTP_PORT, + RPC_WS_PORT, +} from "../../../constants"; +import { Node, envVars } from "../../../types"; +import { Client } from "../../client"; +import { + NodeSpec, + Port, + PortProperty, + ProcessEnvironment, + ZombieRole, +} from "./types"; + +export class NodeResource { + protected readonly configPath: string; + protected readonly dataPath: string; + private readonly relayDataPath: string; + + constructor( + client: Client, + protected readonly namespace: string, + protected readonly nodeSetupConfig: Node, + ) { + const nodeRootPath = `${client.tmpDir}/${this.nodeSetupConfig.name}`; + this.configPath = `${nodeRootPath}/cfg`; + this.dataPath = `${nodeRootPath}/data`; + this.relayDataPath = `${nodeRootPath}/relay-data`; + } + + public async generateSpec() { + await this.createDirectories(); + const ports = await this.generatePorts(); + const command = await this.generateCommand(); + const zombieRole = this.getZombieRole(); + const env = this.getEnv(); + const nodeManifest = this.generateNodeSpec(ports, command, zombieRole, env); + + return nodeManifest; + } + + protected async createDirectories() { + try { + await makeDir(this.configPath, true); + await makeDir(this.dataPath, true); + await makeDir(this.relayDataPath, true); + } catch { + throw new Error( + `Error generating directories for ${this.nodeSetupConfig.name} resource`, + ); + } + } + + private async portFromNodeSetupConfigOrDefault(portProperty: PortProperty) { + if (this.nodeSetupConfig[portProperty]) { + return this.nodeSetupConfig[portProperty]; + } + + return getRandomPort(); + } + + private async generatePorts(): Promise { + return [ + { + containerPort: PROMETHEUS_PORT, + name: "prometheus", + flag: "--prometheus-port", + hostPort: await this.portFromNodeSetupConfigOrDefault("prometheusPort"), + }, + { + containerPort: RPC_HTTP_PORT, + name: "rpc", + flag: "--rpc-port", + hostPort: await this.portFromNodeSetupConfigOrDefault("rpcPort"), + }, + { + containerPort: RPC_WS_PORT, + name: "rpc-ws", + flag: "--ws-port", + hostPort: await this.portFromNodeSetupConfigOrDefault("wsPort"), + }, + { + containerPort: P2P_PORT, + name: "p2p", + flag: "--port", + hostPort: await this.portFromNodeSetupConfigOrDefault("p2pPort"), + }, + ]; + } + + protected generateCommand() { + if (this.nodeSetupConfig.zombieRole === "cumulus-collator") { + return genCumulusCollatorCmd( + this.nodeSetupConfig, + this.configPath, + this.dataPath, + this.relayDataPath, + false, + ); + } + + return genCmd(this.nodeSetupConfig, this.configPath, this.dataPath, false); + } + + protected getZombieRole(): ZombieRole { + const { zombieRole, validator } = this.nodeSetupConfig; + + if (zombieRole) return zombieRole; + + return validator ? "authority" : "full-node"; + } + + protected getEnv() { + const { env } = this.nodeSetupConfig; + + return env.reduce((memo, item: envVars) => { + memo[item.name] = item.value; + return memo; + }, {} as ProcessEnvironment); + } + + protected generateNodeSpec( + ports: Port[], + command: string[], + zombieRole: ZombieRole, + env: ProcessEnvironment, + ): NodeSpec { + return { + metadata: { + name: this.nodeSetupConfig.name, + namespace: this.namespace, + labels: { + "zombie-role": zombieRole, + app: "zombienet", + "zombie-ns": this.namespace, + name: this.namespace, + instance: this.nodeSetupConfig.name, + }, + }, + spec: { + cfgPath: this.configPath, + dataPath: this.dataPath, + ports, + command, + env, + }, + }; + } +} diff --git a/javascript/packages/orchestrator/src/providers/native/resources/types.ts b/javascript/packages/orchestrator/src/providers/native/resources/types.ts new file mode 100644 index 000000000..04242b227 --- /dev/null +++ b/javascript/packages/orchestrator/src/providers/native/resources/types.ts @@ -0,0 +1,37 @@ +import { Node } from "../../../types"; + +export interface ProcessEnvironment { + [key: string]: string; +} + +export type PortProperty = keyof NonNullable; + +export type ZombieRole = Node["zombieRole"] | "authority" | "full-node"; + +export interface Port { + containerPort: number; + name: "prometheus" | "rpc" | "rpc-ws" | "p2p"; + flag: string; + hostPort: number; +} + +export interface NodeSpec { + metadata: { + name: string; + namespace: string; + labels: { + "zombie-role": ZombieRole; + app: "zombienet"; + "zombie-ns": string; + name: string; + instance: string; + }; + }; + spec: { + cfgPath: string; + dataPath?: string; + ports: Port[]; + command: string[]; + env: ProcessEnvironment; + }; +}