Skip to content

Commit

Permalink
feat(test-tooling): env injenction for Besu, Fabric, Quorum AIOs
Browse files Browse the repository at this point in the history
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 <peter.somogyvari@accenture.com>
  • Loading branch information
petermetz committed Dec 2, 2021
1 parent 58d1ce9 commit bb0352d
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Checks } from "@hyperledger/cactus-common";

/**
* Converts an ES6 Map of environment variables into an
* array of strings which is the expected format of the Dockerode library that
* we heavily use in our testing code to launch containers for infrastructure
* simulation.
*
* @param envMap Environment variables as an ES6 map that will be converted into
* an array of strings.
*/
export function envMapToDocker(envMap: Map<string, unknown>): string[] {
Checks.truthy(envMap, "test-tooling#envMapToDocker()");
const out = [];
for (const [key, value] of envMap) {
out.push(`${key}=${value}`);
}
return out;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Checks } from "@hyperledger/cactus-common";

/**
* Converts the NodeJS formatted (POJO) environment variable object into an
* array of strings which is the expected format of the Dockerode library that
* we heavily use in our testing code to launch containers for infrastructure
* simulation.
*
* @param envNodeJs Environment variables in the format NodeJS provides it to
* the script file that it is running. It's just a plain on Javascript object
* that maps the environment variable names to values like this:
* ```json
* {
* "MY_ENV_VAR": "SomeInterestingValueOfMyEnvVar"
* }
* ```
*/
export function envNodeToDocker(envNodeJs: NodeJS.ProcessEnv): string[] {
Checks.truthy(envNodeJs, "test-tooling#envNodeToDocker()");
return Object.entries(envNodeJs).map((parts: [string, unknown]) => {
return `${parts[0]}=${parts[1]}`;
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Checks } from "@hyperledger/cactus-common";

/**
* Converts the NodeJS formatted (POJO) environment variable object into an ES6
* Map object containing the same information.
*
* @param envNodeJs Environment variables in the format NodeJS provides it to
* the script file that it is running. It's just a plain on Javascript object
* that maps the environment variable names to values like this:
* ```json
* {
* "MY_ENV_VAR": "SomeInterestingValueOfMyEnvVar"
* }
* ```
*/
export function envNodeToMap(
envNodeJs: NodeJS.ProcessEnv,
): Map<string, string> {
Checks.truthy(envNodeJs, "test-tooling#envNodeToDocker()");
const map = new Map();
Object.entries(envNodeJs).forEach(([key, value]) => map.set(key, value));
return map;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
import path from "path";
import fs from "fs";
import yaml from "js-yaml";
import { envMapToDocker } from "../common/env-map-to-docker";

export interface organizationDefinitionFabricV2 {
path: string;
Expand Down Expand Up @@ -1204,9 +1205,7 @@ export class FabricTestLedgerV1 implements ITestLedger {

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

if (this.container) {
await this.container.stop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,6 @@ export { isRunningInGithubAction } from "./github-actions/is-running-in-github-a
export { pruneDockerAllIfGithubAction } from "./github-actions/prune-docker-all-if-github-action";
export { IDockerPullProgress } from "./common/i-docker-pull-progress";
export { IDockerPullProgressDetail } from "./common/i-docker-pull-progress";
export { envNodeToDocker } from "./common/env-node-to-docker";
export { envMapToDocker } from "./common/env-map-to-docker";
export { envNodeToMap } from "./common/env-node-to-map";
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface IQuorumTestLedgerConstructorOptions {
rpcApiHttpPort?: number;
logLevel?: LogLevelDesc;
emitContainerLogs?: boolean;
readonly envVars?: string[];
}

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

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

this.envVars = options.envVars || [];

this.emitContainerLogs = Bools.isBooleanStrict(options.emitContainerLogs)
? (options.emitContainerLogs as boolean)
: true;
Expand Down Expand Up @@ -211,9 +215,7 @@ export class QuorumTestLedger implements ITestLedger {
[],
[],
{
// Env: [
// 'PRIVATE_CONFIG=ignore'// FIXME make it possible to have privacy configured programmatically for quorum
// ],
Env: this.envVars,
ExposedPorts: {
[`${this.rpcApiHttpPort}/tcp`]: {}, // quorum RPC - HTTP
"8546/tcp": {}, // quorum RPC - WebSocket
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import "jest-extended";

import { envNodeToDocker } from "../../../../main/typescript/public-api";
import { envMapToDocker } from "../../../../main/typescript/public-api";
import { envNodeToMap } from "../../../../main/typescript/public-api";

describe("test-tooling#envMapToDocker()", () => {
test("Empty Map", () => {
expect(envMapToDocker(new Map())).toBeArrayOfSize(0);
});

test("Non-empty Map", () => {
const data = new Map();
data.set("X", "Y");
const out = envMapToDocker(data);
expect(out).toBeArrayOfSize(1);
expect(out[0]).toEqual("X=Y");
});
});

describe("test-tooling#envNodeToDocker()", () => {
test("Empty POJO", () => {
expect(envNodeToDocker({})).toBeArrayOfSize(0);
});

test("Non-empty POJO", () => {
const data = { X: "Y" };
const out = envNodeToDocker(data);
expect(out).toBeArrayOfSize(1);
expect(out[0]).toEqual("X=Y");
});
});

describe("test-tooling#envNodeToMap()", () => {
test("Empty POJO", () => {
const out = envNodeToMap({});
expect(out).toBeTruthy();
expect(out).toBeInstanceOf(Map);
expect(out.size).toStrictEqual(0);
});

test("Non-empty POJO", () => {
const data = { X: "Y" };
const out = envNodeToMap(data);
expect(out).toBeTruthy();
expect(out).toBeInstanceOf(Map);
expect(out.size).toStrictEqual(1);
expect(out.get("X")).toStrictEqual("Y");
});
});

0 comments on commit bb0352d

Please sign in to comment.