From 3ac46f2d5701bc9fd8ce9393dd1f9c8555a76c0e Mon Sep 17 00:00:00 2001 From: l0r1s Date: Mon, 3 Apr 2023 23:28:35 +0300 Subject: [PATCH 1/2] 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; + }; +} From df00db59c424926da13204a8efb2da533846863f Mon Sep 17 00:00:00 2001 From: l0r1s Date: Mon, 3 Apr 2023 23:35:05 +0300 Subject: [PATCH 2/2] feat: refactored into a BootNodeResource with NodeResource base class for native provider --- .../providers/native/dynResourceDefinition.ts | 87 ++----------------- .../native/resources/bootnode.resource.ts | 52 +++++++++++ .../src/providers/native/resources/index.ts | 1 + 3 files changed, 58 insertions(+), 82 deletions(-) create mode 100644 javascript/packages/orchestrator/src/providers/native/resources/bootnode.resource.ts diff --git a/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts b/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts index 1ea59bf1a..36aa94501 100644 --- a/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts +++ b/javascript/packages/orchestrator/src/providers/native/dynResourceDefinition.ts @@ -1,59 +1,18 @@ -import { getRandomPort, makeDir } from "@zombienet/utils"; -import { genCmd } from "../../cmdGenerator"; +import { getRandomPort } from "@zombienet/utils"; import { getUniqueName } from "../../configGenerator"; -import { - P2P_PORT, - PROMETHEUS_PORT, - RPC_HTTP_PORT, - RPC_WS_PORT, -} from "../../constants"; import { Network } from "../../network"; -import { Node, envVars } from "../../types"; +import { Node } from "../../types"; import { getClient } from "../client"; -import { NodeResource } from "./resources"; - -interface processEnvironment { - [key: string]: string; -} +import { BootNodeResource, NodeResource } from "./resources"; export async function genBootnodeDef( namespace: string, 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 bootNodeResource = new BootNodeResource(client, namespace, nodeSetup); - const dataPath = `${client.tmpDir}/${name}/data`; - await makeDir(dataPath, true); - - const command = await genCmd(nodeSetup, cfgPath, dataPath, false); - return { - metadata: { - name: "bootnode", - namespace: namespace, - labels: { - name: namespace, - instance: "bootnode", - "zombie-role": "bootnode", - app: "zombienet", - "zombie-ns": namespace, - }, - }, - spec: { - cfgPath: `${client.tmpDir}/${nodeSetup.name}/cfg`, - ports, - command, - env: nodeSetup.env.reduce((memo, item: envVars) => { - memo[item.name] = item.value; - return memo; - }, {} as processEnvironment), - }, - }; + return bootNodeResource.generateSpec(); } export async function genNodeDef( @@ -66,42 +25,6 @@ export async function genNodeDef( return nodeResource.generateSpec(); } -async function getPorts( - rpc?: number, - ws?: number, - prometheus?: number, - p2p?: number, -) { - const ports = [ - { - containerPort: PROMETHEUS_PORT, - name: "prometheus", - flag: "--prometheus-port", - hostPort: prometheus || (await getRandomPort()), - }, - { - containerPort: RPC_HTTP_PORT, - name: "rpc", - flag: "--rpc-port", - hostPort: rpc || (await getRandomPort()), - }, - { - containerPort: RPC_WS_PORT, - name: "ws", - flag: "--ws-port", - hostPort: ws || (await getRandomPort()), - }, - { - containerPort: P2P_PORT, - name: "p2p", - flag: "--port", - hostPort: p2p || (await getRandomPort()), - }, - ]; - - return ports; -} - export function replaceNetworkRef(podDef: any, network: Network) { // replace command if needed if (Array.isArray(podDef.spec.command)) { diff --git a/javascript/packages/orchestrator/src/providers/native/resources/bootnode.resource.ts b/javascript/packages/orchestrator/src/providers/native/resources/bootnode.resource.ts new file mode 100644 index 000000000..0a0a80ed9 --- /dev/null +++ b/javascript/packages/orchestrator/src/providers/native/resources/bootnode.resource.ts @@ -0,0 +1,52 @@ +import { makeDir } from "@zombienet/utils"; +import { genCmd } from "../../../cmdGenerator"; +import { NodeResource } from "./node.resource"; +import { NodeSpec, Port, ProcessEnvironment, ZombieRole } from "./types"; + +export class BootNodeResource extends NodeResource { + protected async createDirectories() { + try { + await makeDir(this.configPath, true); + await makeDir(this.dataPath, true); + } catch { + throw new Error( + `Error generating directories for ${this.nodeSetupConfig.name} resource`, + ); + } + } + + protected generateCommand() { + return genCmd(this.nodeSetupConfig, this.configPath, this.dataPath, false); + } + + protected getZombieRole(): ZombieRole { + return "bootnode"; + } + + protected generateNodeSpec( + ports: Port[], + command: string[], + zombieRole: ZombieRole, + env: ProcessEnvironment, + ): NodeSpec { + return { + metadata: { + name: "bootnode", + namespace: this.namespace, + labels: { + name: this.namespace, + instance: "bootnode", + "zombie-role": zombieRole, + app: "zombienet", + "zombie-ns": this.namespace, + }, + }, + spec: { + cfgPath: this.configPath, + ports, + command, + env, + }, + }; + } +} diff --git a/javascript/packages/orchestrator/src/providers/native/resources/index.ts b/javascript/packages/orchestrator/src/providers/native/resources/index.ts index 2ec93ea9a..597ab10ea 100644 --- a/javascript/packages/orchestrator/src/providers/native/resources/index.ts +++ b/javascript/packages/orchestrator/src/providers/native/resources/index.ts @@ -1 +1,2 @@ +export { BootNodeResource } from "./bootnode.resource"; export { NodeResource } from "./node.resource";