diff --git a/README.md b/README.md index 1e3c69ca904..e9a72a39c8b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ As blockchain technology proliferates, blockchain integration will become an inc ### Supply Chain Example -1. Run the following command to pull up the container that will run the example application and the test ledgers as well: +1. Ensure a working installation of [Docker](https://docs.docker.com/desktop/) is present on your machine. +2. Run the following command to pull up the container that will run the example application and the test ledgers as well: ```sh docker run \ --rm \ @@ -30,11 +31,11 @@ As blockchain technology proliferates, blockchain integration will become an inc -p 4000:4000 \ -p 4100:4100 \ -p 4200:4200 \ - ghcr.io/hyperledger/cactus-example-supply-chain-app:2021-07-01--fix-1063-v2 + ghcr.io/hyperledger/cactus-example-supply-chain-app:2021-07-20--fix-720 ``` -2. Wait for the output to show the message `INFO (api-server): Cactus Cockpit reachable http://0.0.0.0:3100` -3. Visit http://localhost:3100 in a web browser with Javascript enabled -4. Use the graphical user interface to create data on both ledgers and observe that a consistent view of the data from different ledgers is provided. +3. Wait for the output to show the message `INFO (api-server): Cactus Cockpit reachable http://0.0.0.0:3100` +4. Visit http://localhost:3100 in a web browser with Javascript enabled +5. Use the graphical user interface to create data on both ledgers and observe that a consistent view of the data from different ledgers is provided. Once the last command has finished executing, open link printed on the console with a web browser of your choice diff --git a/examples/cactus-example-supply-chain-backend/src/main/typescript/infrastructure/supply-chain-app-dummy-infrastructure.ts b/examples/cactus-example-supply-chain-backend/src/main/typescript/infrastructure/supply-chain-app-dummy-infrastructure.ts index 3c18f46b80f..9a70110fb1c 100644 --- a/examples/cactus-example-supply-chain-backend/src/main/typescript/infrastructure/supply-chain-app-dummy-infrastructure.ts +++ b/examples/cactus-example-supply-chain-backend/src/main/typescript/infrastructure/supply-chain-app-dummy-infrastructure.ts @@ -103,13 +103,19 @@ export class SupplyChainAppDummyInfrastructure { const label = this.className; this.log = LoggerProvider.getOrCreate({ level, label }); - this.besu = new BesuTestLedger(); - this.quorum = new QuorumTestLedger(); + this.besu = new BesuTestLedger({ + logLevel: level, + }); + this.quorum = new QuorumTestLedger({ + logLevel: level, + emitContainerLogs: true, + }); this.fabric = new FabricTestLedgerV1({ publishAllPorts: true, imageName: "ghcr.io/hyperledger/cactus-fabric-all-in-one", imageVersion: "2021-03-02-ssh-hotfix", logLevel: level, + emitContainerLogs: true, }); if (this.options.keychain) { diff --git a/examples/supply-chain-app/README.md b/examples/supply-chain-app/README.md index 9c69ef5c801..2048044c527 100644 --- a/examples/supply-chain-app/README.md +++ b/examples/supply-chain-app/README.md @@ -14,7 +14,7 @@ -p 4000:4000 \ -p 4100:4100 \ -p 4200:4200 \ - ghcr.io/hyperledger/cactus-example-supply-chain-app:2021-07-01--fix-1063-v2 + ghcr.io/hyperledger/cactus-example-supply-chain-app:2021-07-20--fix-720 ``` 2. Observe the example application pulling up in the logs 1. the test ledger containers, diff --git a/packages/cactus-test-tooling/src/main/typescript/besu/besu-test-ledger.ts b/packages/cactus-test-tooling/src/main/typescript/besu/besu-test-ledger.ts index 59c9f13540f..51555c241d4 100644 --- a/packages/cactus-test-tooling/src/main/typescript/besu/besu-test-ledger.ts +++ b/packages/cactus-test-tooling/src/main/typescript/besu/besu-test-ledger.ts @@ -9,6 +9,7 @@ import { LogLevelDesc, Logger, LoggerProvider, + Bools, } from "@hyperledger/cactus-common"; import { ITestLedger } from "../i-test-ledger"; import { Streams } from "../common/streams"; @@ -22,6 +23,7 @@ export interface IBesuTestLedgerConstructorOptions { rpcApiWsPort?: number; envVars?: string[]; logLevel?: LogLevelDesc; + emitContainerLogs?: boolean; } export const BESU_TEST_LEDGER_DEFAULT_OPTIONS = Object.freeze({ @@ -52,6 +54,7 @@ export class BesuTestLedger implements ITestLedger { public readonly rpcApiHttpPort: number; public readonly rpcApiWsPort: number; public readonly envVars: string[]; + public readonly emitContainerLogs: boolean; private readonly log: Logger; private container: Container | undefined; @@ -73,6 +76,10 @@ export class BesuTestLedger implements ITestLedger { options.rpcApiWsPort || BESU_TEST_LEDGER_DEFAULT_OPTIONS.rpcApiWsPort; this.envVars = options.envVars || BESU_TEST_LEDGER_DEFAULT_OPTIONS.envVars; + this.emitContainerLogs = Bools.isBooleanStrict(options.emitContainerLogs) + ? (options.emitContainerLogs as boolean) + : true; + this.validateConstructorOptions(); const label = "besu-test-ledger"; const level = options.logLevel || "INFO"; @@ -255,6 +262,16 @@ export class BesuTestLedger implements ITestLedger { this.log.debug(`Started container OK. Waiting for healthcheck...`); this.container = container; this.containerId = container.id; + + if (this.emitContainerLogs) { + const logOptions = { follow: true, stderr: true, stdout: true }; + const logStream = await container.logs(logOptions); + logStream.on("data", (data: Buffer) => { + const fnTag = `[${this.getContainerImageName()}]`; + this.log.debug(`${fnTag} %o`, data.toString("utf-8")); + }); + } + try { await this.waitForHealthCheck(); this.log.debug(`Healthcheck passing OK.`); diff --git a/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts b/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts index 1140bb8d3aa..1d3f3c74881 100644 --- a/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts +++ b/packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts @@ -6,6 +6,12 @@ import Joi from "joi"; import tar from "tar-stream"; import Web3 from "web3"; import { Account } from "web3-core"; +import { + Bools, + Logger, + LoggerProvider, + LogLevelDesc, +} from "@hyperledger/cactus-common"; import { ITestLedger } from "../i-test-ledger"; import { Streams } from "../common/streams"; import { IKeyPair } from "../i-key-pair"; @@ -15,6 +21,8 @@ export interface IQuorumTestLedgerConstructorOptions { containerImageVersion?: string; containerImageName?: string; rpcApiHttpPort?: number; + logLevel?: LogLevelDesc; + emitContainerLogs?: boolean; } export const QUORUM_TEST_LEDGER_DEFAULT_OPTIONS = Object.freeze({ @@ -40,7 +48,9 @@ export class QuorumTestLedger implements ITestLedger { public readonly containerImageVersion: string; public readonly containerImageName: string; public readonly rpcApiHttpPort: number; + public readonly emitContainerLogs: boolean; + private readonly log: Logger; private container: Container | undefined; private containerId: string | undefined; @@ -60,7 +70,15 @@ export class QuorumTestLedger implements ITestLedger { options.rpcApiHttpPort || QUORUM_TEST_LEDGER_DEFAULT_OPTIONS.rpcApiHttpPort; + this.emitContainerLogs = Bools.isBooleanStrict(options.emitContainerLogs) + ? (options.emitContainerLogs as boolean) + : true; + this.validateConstructorOptions(); + + const label = "quorum-test-ledger"; + const level = options.logLevel || "INFO"; + this.log = LoggerProvider.getOrCreate({ level, label }); } public getContainer(): Container { @@ -174,6 +192,7 @@ export class QuorumTestLedger implements ITestLedger { public async start(omitPull = false): Promise { const containerNameAndTag = this.getContainerImageName(); + this.log.debug(`Starting Quorum Test Ledger: ${containerNameAndTag}`); if (this.container) { await this.container.stop(); await this.container.remove(); @@ -181,6 +200,7 @@ export class QuorumTestLedger implements ITestLedger { const docker = new Docker(); if (!omitPull) { + this.log.debug(`Pulling image: ${containerNameAndTag}`); await this.pullContainerImage(containerNameAndTag); } @@ -217,8 +237,21 @@ export class QuorumTestLedger implements ITestLedger { eventEmitter.once("start", async (container: Container) => { this.container = container; this.containerId = container.id; + + this.log.debug("Quorum Test Ledger container started booting OK."); + + if (this.emitContainerLogs) { + const logOptions = { follow: true, stderr: true, stdout: true }; + const logStream = await container.logs(logOptions); + logStream.on("data", (data: Buffer) => { + const fnTag = `[${this.getContainerImageName()}]`; + this.log.debug(`${fnTag} %o`, data.toString("utf-8")); + }); + } + try { await this.waitForHealthCheck(); + this.log.debug("Quorum Test Ledger container passed healthcheck OK"); resolve(container); } catch (ex) { reject(ex);