Skip to content

Commit

Permalink
feat: add run command, enable to run scripts in pods (#268)
Browse files Browse the repository at this point in the history
* feat: add run command, enable to run scripts in pods

* change test def for ci

* add file
  • Loading branch information
pepoviola authored Jul 13, 2022
1 parent 5ee2e85 commit 3d19294
Show file tree
Hide file tree
Showing 11 changed files with 167 additions and 17 deletions.
6 changes: 3 additions & 3 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ zombienet-system-event-assertion:
tags:
- zombienet-polkadot-integration-test

zombienet-custom-js-assertion:
zombienet-custom-scripts-assertion:
stage: deploy
<<: *kubernetes-env
image: "paritypr/zombienet:${CI_COMMIT_SHORT_SHA}"
Expand All @@ -307,7 +307,7 @@ zombienet-custom-js-assertion:
GH_DIR: 'https://github.com/paritytech/zombienet/tree/${CI_COMMIT_SHORT_SHA}/tests'

before_script:
- echo "Zombienet Tests Custom JS"
- echo "Zombienet Tests Custom Scripts (js, sh)"
- echo "paritypr/zombienet:${CI_COMMIT_SHORT_SHA}"
- echo "${GH_DIR}"
- export DEBUG=zombie*
Expand All @@ -316,7 +316,7 @@ zombienet-custom-js-assertion:

script:
- /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh
--test="0008-custom-js.feature"
--test="0008-custom-scripts.feature"
allow_failure: true
retry: 2
tags:
Expand Down
23 changes: 23 additions & 0 deletions src/networkNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getClient } from "./providers/client";

import { paraGetBlockHeight, paraIsRegistered, validateRuntimeCode } from "./jsapi-helpers";
import { decorators } from "./utils/colors";
import { resolve } from "path";

const debug = require("debug")("zombie::network-node");

Expand Down Expand Up @@ -358,6 +359,28 @@ export class NetworkNode implements NetworkNodeInterface {
}
}

async run(
scriptPath: string,
args: string[],
timeout = DEFAULT_INDIVIDUAL_TEST_TIMEOUT) {
const client = getClient();
const runScript = async (scriptPath: string, args: string[]) => {
const r = await client.runScript(this.name, scriptPath, args);
if( r.exitCode !== 0 ) throw new Error(`Error running cmd: ${scriptPath} with args ${args}`);
debug(r.stdout);
return r.stdout;
};

const resp = await Promise.race([
runScript(scriptPath, args),
new Promise((resolve) => setTimeout(() => {
const err = new Error(`Timeout(${timeout}), "running cmd: ${scriptPath} with args ${args} within ${timeout} secs".`);
return resolve(err);
}, timeout * 1000))
]);
if( resp instanceof Error ) throw resp;
}

async getSpansByTraceId(traceId: string, collatorUrl: string): Promise<string[]> {
const url = `${collatorUrl}/api/traces/${traceId}`;
const response = await axios.get(url, { timeout: 2000 });
Expand Down
1 change: 1 addition & 0 deletions src/providers/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export abstract class Client {
resourceDef?: string,
scoped?: boolean
): Promise<RunCommandResponse>;
abstract runScript(identifier: string, scriptPath: string, args: string[]): Promise<RunCommandResponse>;
abstract spawnFromDef(
podDef: any,
filesToCopy?: fileMap[],
Expand Down
30 changes: 29 additions & 1 deletion src/providers/k8s/kubeClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import execa from "execa";
import { resolve } from "path";
import path, { resolve } from "path";
import {
DEFAULT_DATA_DIR,
DEFAULT_REMOTE_DIR,
Expand Down Expand Up @@ -600,6 +600,34 @@ export class KubeClient extends Client {
}
}

async runScript(identifier: string, scriptPath: string, args: string[] = []): Promise<RunCommandResponse> {
try {
const scriptFileName = path.basename(scriptPath);
const scriptPathInPod = `/tmp/${scriptFileName}`;
// upload the script
await this.copyFileToPod(identifier, scriptPath, scriptPathInPod, undefined, true);

// set as executable
const baseArgs = ["exec", `Pod/${identifier}`, "--"];
await this.runCommand([
...baseArgs,
"/bin/chmod",
"+x",
scriptPathInPod], undefined, true);

// exec
const result = await this.runCommand([...baseArgs, "bash", "-c", scriptPathInPod, ...args], undefined, true);

return {
exitCode: result.exitCode,
stdout: result.stdout,
};
} catch (error) {
debug(error);
throw error;
}
}

async isPodMonitorAvailable() {
let available = false;
try {
Expand Down
30 changes: 30 additions & 0 deletions src/providers/native/nativeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Client, RunCommandResponse, setClient } from "../client";
import { decorators } from "../../utils/colors";
import YAML from "yaml";
import { spawn } from "child_process";
import path from "path";

const debug = require("debug")("zombie::native::client");

Expand Down Expand Up @@ -179,6 +180,35 @@ export class NativeClient extends Client {
throw error;
}
}

async runScript(identifier: string, scriptPath: string, args: string[] = []): Promise<RunCommandResponse> {
try {
const scriptFileName = path.basename(scriptPath);
const scriptPathInPod = `${this.tmpDir}/${identifier}/${scriptFileName}`;
// upload the script
await fs.promises.cp(scriptPath, scriptPathInPod);

// set as executable
await execa(this.command, ["-c", ["chmod", "+x", scriptPathInPod].join(" ")]);

// exec
const result = await execa(this.command,[
"-c",
[`cd ${this.tmpDir}/${identifier}`,
"&&",
scriptPathInPod,
...args].join(" ")]);

return {
exitCode: result.exitCode,
stdout: result.stdout,
};
} catch (error) {
debug(error);
throw error;
}
}

async spawnFromDef(
podDef: any,
filesToCopy: fileMap[] = [],
Expand Down
32 changes: 31 additions & 1 deletion src/providers/podman/podmanClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import execa from "execa";
import { resolve } from "path";
import path, { resolve } from "path";
import { copy as fseCopy } from "fs-extra";
import {
DEFAULT_DATA_DIR,
Expand Down Expand Up @@ -268,6 +268,36 @@ export class PodmanClient extends Client {
throw error;
}
}

async runScript(podName: string, scriptPath: string, args: string[] = []): Promise<RunCommandResponse> {
try {
const scriptFileName = path.basename(scriptPath);
const scriptPathInPod = `/tmp/${scriptFileName}`;
const identifier = `${podName}_pod-${podName}`;

// upload the script
await this.runCommand(["cp", scriptPath, `${identifier}:${scriptPathInPod}`]);

// set as executable
const baseArgs = ["exec", identifier];
await this.runCommand([
...baseArgs,
"/bin/chmod",
"+x",
scriptPathInPod], undefined, true);

// exec
const result = await this.runCommand([...baseArgs, "bash", "-c", scriptPathInPod, ...args], undefined, true);

return {
exitCode: result.exitCode,
stdout: result.stdout,
};
} catch (error) {
debug(error);
throw error;
}
}
async spawnFromDef(
podDef: any,
filesToCopy: fileMap[] = [],
Expand Down
44 changes: 44 additions & 0 deletions src/test-runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@ const assertCustomJsRegex = new RegExp(
/^([\w-]+): js-script (\.{0,2}\/.*\.[\w]+)( with \"[\w ,-/]+\")?( return is (equal to|equals|=|==|greater than|>|at least|>=|lower than|<)? *(\d+))?( within (\d+) (seconds|secs|s))?$/i
);

// Run command in the node
const assertCustomShInNode = new RegExp(
/^([\w-]+): run (\.{0,2}\/.*\.[\w]+)( with \"[\w \,\-/]+\")?( return is (equal to|equals|=|==|greater than|>|at least|>=|lower than|<)? *(\d+))?( within (\d+) (seconds|secs|s))?$/i
);

// Backchannel
// alice: wait for name and use as X within 30s
const backchannelWait = new RegExp(
Expand Down Expand Up @@ -523,6 +528,45 @@ function parseAssertionLine(assertion: string) {
};
}

m = assertCustomShInNode.exec(assertion);
if (m && m[1] && m[2]) {
const nodeName = m[1];
const shFile = m[2];
const withArgs = m[3] ? m[3] : "";
const comparatorFn = getComparatorFn(m[5] || "");
let targetValue: string | number | undefined = m[6];
const t = m[8] ? parseInt(m[8], 10) : DEFAULT_INDIVIDUAL_TEST_TIMEOUT;

return async (
network: Network,
backchannelMap: BackchannelMap,
testFile: string
) => {
try {
const timeout: number|undefined = t;
const fileTestPath = path.dirname(testFile);
const resolvedShFilePath = path.resolve(fileTestPath, shFile);

const nodes = network.getNodes(nodeName);
const args = withArgs === "" ? [] : withArgs.split("with ").slice(1)[0].replaceAll('"',"").split(",");
const results = await Promise.all(nodes.map(node => node.run(resolvedShFilePath, args, timeout)));

if( comparatorFn && targetValue !== undefined) {
for(const value of results) {
assert[comparatorFn](value, targetValue);
}
}

// all the commands run successfully
expect(true).to.be.ok;
} catch(err: any) {
console.log(`\n\t ${decorators.red(`Error running script: ${shFile}`)}`);
console.log(`\t\t ${err.message}\n`);
throw new Error(err);
}
}
}

m = backchannelWait.exec(assertion);
if (m && m[1] && m[2] && m[3]) {
let timeout: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
Description: System Events Custom JS
Network: ./0008-custom-js.toml
Description: Custom Scripts (js and bash)
Network: ./0008-custom-scripts.toml
Creds: config


alice: is up
bob: is up
alice: js-script ./0008-custom.js return is greater than 1 within 200 seconds
alice: js-script ./0008-custom.js within 200 seconds
alice: run ./0008-custom.sh within 200 seconds
File renamed without changes.
11 changes: 1 addition & 10 deletions tests/0008-custom.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
const polkadotApi = require("@polkadot/api");

async function connect(apiUrl, types) {
const provider = new polkadotApi.WsProvider(apiUrl);
const api = new polkadotApi.ApiPromise({ provider, types });
await api.isReady;
return api;
}

async function run(nodeName, networkInfo, args) {
const {wsUri, userDefinedTypes} = networkInfo.nodesByName[nodeName];
const api = await connect(wsUri, userDefinedTypes);
const api = await zombie.connect(wsUri, userDefinedTypes);
const validator = await api.query.session.validators();
return validator.length;
}
Expand Down
2 changes: 2 additions & 0 deletions tests/0008-custom.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# just echo for this test
echo "OK"

0 comments on commit 3d19294

Please sign in to comment.