Skip to content

Commit bb0352d

Browse files
committed
feat(test-tooling): env injenction for Besu, Fabric, Quorum AIOs
The Fabric, Quorum and Besu test ledger classes are now capable of injecting arbitrary environment variables into their containers which will help us in the future to update the supply chain app example (and other examples as well) to push their host environment variables into the containers they run internally. The hope with this is that it will make it possible for people in restricted environments (corporate firewalls/proxies) to run the example as well. Fixes #1580 Signed-off-by: Peter Somogyvari <[email protected]>
1 parent 58d1ce9 commit bb0352d

File tree

7 files changed

+125
-6
lines changed

7 files changed

+125
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Checks } from "@hyperledger/cactus-common";
2+
3+
/**
4+
* Converts an ES6 Map of environment variables into an
5+
* array of strings which is the expected format of the Dockerode library that
6+
* we heavily use in our testing code to launch containers for infrastructure
7+
* simulation.
8+
*
9+
* @param envMap Environment variables as an ES6 map that will be converted into
10+
* an array of strings.
11+
*/
12+
export function envMapToDocker(envMap: Map<string, unknown>): string[] {
13+
Checks.truthy(envMap, "test-tooling#envMapToDocker()");
14+
const out = [];
15+
for (const [key, value] of envMap) {
16+
out.push(`${key}=${value}`);
17+
}
18+
return out;
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Checks } from "@hyperledger/cactus-common";
2+
3+
/**
4+
* Converts the NodeJS formatted (POJO) environment variable object into an
5+
* array of strings which is the expected format of the Dockerode library that
6+
* we heavily use in our testing code to launch containers for infrastructure
7+
* simulation.
8+
*
9+
* @param envNodeJs Environment variables in the format NodeJS provides it to
10+
* the script file that it is running. It's just a plain on Javascript object
11+
* that maps the environment variable names to values like this:
12+
* ```json
13+
* {
14+
* "MY_ENV_VAR": "SomeInterestingValueOfMyEnvVar"
15+
* }
16+
* ```
17+
*/
18+
export function envNodeToDocker(envNodeJs: NodeJS.ProcessEnv): string[] {
19+
Checks.truthy(envNodeJs, "test-tooling#envNodeToDocker()");
20+
return Object.entries(envNodeJs).map((parts: [string, unknown]) => {
21+
return `${parts[0]}=${parts[1]}`;
22+
});
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Checks } from "@hyperledger/cactus-common";
2+
3+
/**
4+
* Converts the NodeJS formatted (POJO) environment variable object into an ES6
5+
* Map object containing the same information.
6+
*
7+
* @param envNodeJs Environment variables in the format NodeJS provides it to
8+
* the script file that it is running. It's just a plain on Javascript object
9+
* that maps the environment variable names to values like this:
10+
* ```json
11+
* {
12+
* "MY_ENV_VAR": "SomeInterestingValueOfMyEnvVar"
13+
* }
14+
* ```
15+
*/
16+
export function envNodeToMap(
17+
envNodeJs: NodeJS.ProcessEnv,
18+
): Map<string, string> {
19+
Checks.truthy(envNodeJs, "test-tooling#envNodeToDocker()");
20+
const map = new Map();
21+
Object.entries(envNodeJs).forEach(([key, value]) => map.set(key, value));
22+
return map;
23+
}

packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
import path from "path";
3333
import fs from "fs";
3434
import yaml from "js-yaml";
35+
import { envMapToDocker } from "../common/env-map-to-docker";
3536

3637
export interface organizationDefinitionFabricV2 {
3738
path: string;
@@ -1204,9 +1205,7 @@ export class FabricTestLedgerV1 implements ITestLedger {
12041205

12051206
public async start(ops?: LedgerStartOptions): Promise<Container> {
12061207
const containerNameAndTag = this.getContainerImageName();
1207-
const dockerEnvVars: string[] = new Array(...this.envVars).map(
1208-
(pairs) => `${pairs[0]}=${pairs[1]}`,
1209-
);
1208+
const dockerEnvVars = envMapToDocker(this.envVars);
12101209

12111210
if (this.container) {
12121211
await this.container.stop();

packages/cactus-test-tooling/src/main/typescript/public-api.ts

+3
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,6 @@ export { isRunningInGithubAction } from "./github-actions/is-running-in-github-a
153153
export { pruneDockerAllIfGithubAction } from "./github-actions/prune-docker-all-if-github-action";
154154
export { IDockerPullProgress } from "./common/i-docker-pull-progress";
155155
export { IDockerPullProgressDetail } from "./common/i-docker-pull-progress";
156+
export { envNodeToDocker } from "./common/env-node-to-docker";
157+
export { envMapToDocker } from "./common/env-map-to-docker";
158+
export { envNodeToMap } from "./common/env-node-to-map";

packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface IQuorumTestLedgerConstructorOptions {
2424
rpcApiHttpPort?: number;
2525
logLevel?: LogLevelDesc;
2626
emitContainerLogs?: boolean;
27+
readonly envVars?: string[];
2728
}
2829

2930
export const QUORUM_TEST_LEDGER_DEFAULT_OPTIONS = Object.freeze({
@@ -54,6 +55,7 @@ export class QuorumTestLedger implements ITestLedger {
5455
private readonly log: Logger;
5556
private container: Container | undefined;
5657
private containerId: string | undefined;
58+
private readonly envVars: string[];
5759

5860
constructor(
5961
public readonly options: IQuorumTestLedgerConstructorOptions = {},
@@ -71,6 +73,8 @@ export class QuorumTestLedger implements ITestLedger {
7173
options.rpcApiHttpPort ||
7274
QUORUM_TEST_LEDGER_DEFAULT_OPTIONS.rpcApiHttpPort;
7375

76+
this.envVars = options.envVars || [];
77+
7478
this.emitContainerLogs = Bools.isBooleanStrict(options.emitContainerLogs)
7579
? (options.emitContainerLogs as boolean)
7680
: true;
@@ -211,9 +215,7 @@ export class QuorumTestLedger implements ITestLedger {
211215
[],
212216
[],
213217
{
214-
// Env: [
215-
// 'PRIVATE_CONFIG=ignore'// FIXME make it possible to have privacy configured programmatically for quorum
216-
// ],
218+
Env: this.envVars,
217219
ExposedPorts: {
218220
[`${this.rpcApiHttpPort}/tcp`]: {}, // quorum RPC - HTTP
219221
"8546/tcp": {}, // quorum RPC - WebSocket
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import "jest-extended";
2+
3+
import { envNodeToDocker } from "../../../../main/typescript/public-api";
4+
import { envMapToDocker } from "../../../../main/typescript/public-api";
5+
import { envNodeToMap } from "../../../../main/typescript/public-api";
6+
7+
describe("test-tooling#envMapToDocker()", () => {
8+
test("Empty Map", () => {
9+
expect(envMapToDocker(new Map())).toBeArrayOfSize(0);
10+
});
11+
12+
test("Non-empty Map", () => {
13+
const data = new Map();
14+
data.set("X", "Y");
15+
const out = envMapToDocker(data);
16+
expect(out).toBeArrayOfSize(1);
17+
expect(out[0]).toEqual("X=Y");
18+
});
19+
});
20+
21+
describe("test-tooling#envNodeToDocker()", () => {
22+
test("Empty POJO", () => {
23+
expect(envNodeToDocker({})).toBeArrayOfSize(0);
24+
});
25+
26+
test("Non-empty POJO", () => {
27+
const data = { X: "Y" };
28+
const out = envNodeToDocker(data);
29+
expect(out).toBeArrayOfSize(1);
30+
expect(out[0]).toEqual("X=Y");
31+
});
32+
});
33+
34+
describe("test-tooling#envNodeToMap()", () => {
35+
test("Empty POJO", () => {
36+
const out = envNodeToMap({});
37+
expect(out).toBeTruthy();
38+
expect(out).toBeInstanceOf(Map);
39+
expect(out.size).toStrictEqual(0);
40+
});
41+
42+
test("Non-empty POJO", () => {
43+
const data = { X: "Y" };
44+
const out = envNodeToMap(data);
45+
expect(out).toBeTruthy();
46+
expect(out).toBeInstanceOf(Map);
47+
expect(out.size).toStrictEqual(1);
48+
expect(out.get("X")).toStrictEqual("Y");
49+
});
50+
});

0 commit comments

Comments
 (0)