diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/run-transaction-endpoint-v1.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts similarity index 90% rename from packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/run-transaction-endpoint-v1.test.ts rename to packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts index 98fde0573a..af6ec9a68a 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/run-transaction-endpoint-v1.test.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts @@ -24,9 +24,9 @@ import { RunTransactionRequest, FabricContractInvocationType, DefaultEventHandlerStrategy, -} from "../../../main/typescript/public-api"; +} from "../../../../main/typescript/public-api"; -import { IPluginLedgerConnectorFabricOptions } from "../../../main/typescript/plugin-ledger-connector-fabric"; +import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; import { DiscoveryOptions } from "fabric-network"; /** @@ -36,12 +36,18 @@ import { DiscoveryOptions } from "fabric-network"; * ``` */ -test("deploys contract from go source", async (t: Test) => { +test("runs tx on a Fabric v1.4.8 ledger", async (t: Test) => { const logLevel: LogLevelDesc = "TRACE"; const ledger = new FabricTestLedgerV1({ publishAllPorts: true, logLevel, + imageName: "hyperledger/cactus-fabric-all-in-one", + imageVersion: "2020-12-16-3ddfd8f-v1.4.8", + envVars: new Map([ + ["FABRIC_VERSION", "1.4.8"], + ["CA_VERSION", "1.4.9"], + ]), }); await ledger.start(); @@ -61,7 +67,7 @@ test("deploys contract from go source", async (t: Test) => { const keychainInstanceId = uuidv4(); const keychainId = uuidv4(); - const keychainEntryKey = "user1"; + const keychainEntryKey = "user2"; const keychainEntryValue = JSON.stringify(userIdentity); const keychainPlugin = new PluginKeychainMemory({ diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts new file mode 100644 index 0000000000..6a7fb66553 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts @@ -0,0 +1,177 @@ +import http from "http"; +import { AddressInfo } from "net"; + +import test, { Test } from "tape"; +import { v4 as uuidv4 } from "uuid"; + +import bodyParser from "body-parser"; +import express from "express"; + +import { FabricTestLedgerV1 } from "@hyperledger/cactus-test-tooling"; +import { PluginRegistry } from "@hyperledger/cactus-core"; + +import { + IListenOptions, + LogLevelDesc, + Servers, +} from "@hyperledger/cactus-common"; + +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; + +import { + PluginLedgerConnectorFabric, + DefaultApi as FabricApi, + RunTransactionRequest, + FabricContractInvocationType, + DefaultEventHandlerStrategy, +} from "../../../../main/typescript/public-api"; + +import { IPluginLedgerConnectorFabricOptions } from "../../../../main/typescript/plugin-ledger-connector-fabric"; +import { DiscoveryOptions } from "fabric-network"; + +/** + * Use this to debug issues with the fabric node SDK + * ```sh + * export HFC_LOGGING='{"debug":"console","info":"console"}' + * ``` + */ + +test("runs tx on a Fabric v2.2.0 ledger", async (t: Test) => { + const logLevel: LogLevelDesc = "TRACE"; + + const ledger = new FabricTestLedgerV1({ + publishAllPorts: true, + logLevel, + imageName: "hyperledger/cactus-fabric-all-in-one", + imageVersion: "2020-12-16-3ddfd8f-v2.2.0", + envVars: new Map([ + ["FABRIC_VERSION", "2.2.0"], + ["CA_VERSION", "1.4.9"], + ]), + }); + + await ledger.start(); + + const tearDownLedger = async () => { + await ledger.stop(); + await ledger.destroy(); + }; + test.onFinish(tearDownLedger); + + const [_, adminWallet] = await ledger.enrollAdmin(); + const [userIdentity] = await ledger.enrollUser(adminWallet); + + const connectionProfile = await ledger.getConnectionProfileOrg1(); + + const sshConfig = await ledger.getSshConfig(); + + const keychainInstanceId = uuidv4(); + const keychainId = uuidv4(); + const keychainEntryKey = "user2"; + const keychainEntryValue = JSON.stringify(userIdentity); + + const keychainPlugin = new PluginKeychainMemory({ + instanceId: keychainInstanceId, + keychainId, + logLevel, + backend: new Map([ + [keychainEntryKey, keychainEntryValue], + ["some-other-entry-key", "some-other-entry-value"], + ]), + }); + + const pluginRegistry = new PluginRegistry({ plugins: [keychainPlugin] }); + + const discoveryOptions: DiscoveryOptions = { + enabled: true, + asLocalhost: true, + }; + + const pluginOptions: IPluginLedgerConnectorFabricOptions = { + instanceId: uuidv4(), + pluginRegistry, + sshConfig, + logLevel, + connectionProfile, + discoveryOptions, + eventHandlerOptions: { + strategy: DefaultEventHandlerStrategy.NETWORKSCOPEALLFORTX, + }, + }; + const plugin = new PluginLedgerConnectorFabric(pluginOptions); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + const server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "localhost", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + test.onFinish(async () => await Servers.shutdown(server)); + const { address, port } = addressInfo; + const apiHost = `http://${address}:${port}`; + const apiClient = new FabricApi({ basePath: apiHost }); + + await plugin.installWebServices(expressApp); + + const carId = "CAR277"; + const carOwner = uuidv4(); + + { + const res = await apiClient.runTransactionV1({ + keychainId, + keychainRef: keychainEntryKey, + channelName: "mychannel", + chainCodeId: "fabcar", + invocationType: FabricContractInvocationType.CALL, + functionName: "queryAllCars", + functionArgs: [], + } as RunTransactionRequest); + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + const cars = JSON.parse(res.data.functionOutput); + } + + { + const req: RunTransactionRequest = { + keychainId, + keychainRef: keychainEntryKey, + channelName: "mychannel", + invocationType: FabricContractInvocationType.SEND, + chainCodeId: "fabcar", + functionName: "createCar", + functionArgs: [carId, "Trabant", "601", "Blue", carOwner], + }; + + const res = await apiClient.runTransactionV1(req); + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + } + + { + const res = await apiClient.runTransactionV1({ + keychainId, + keychainRef: keychainEntryKey, + channelName: "mychannel", + chainCodeId: "fabcar", + invocationType: FabricContractInvocationType.CALL, + functionName: "queryAllCars", + functionArgs: [], + } as RunTransactionRequest); + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + const cars = JSON.parse(res.data.functionOutput); + const car277 = cars.find((c: any) => c.Key === carId); + t.ok(car277, "Located Car record by its ID OK"); + t.ok(car277.Record, `Car object has "Record" property OK`); + t.ok(car277.Record.owner, `Car object has "Record"."owner" property OK`); + t.equal(car277.Record.owner, carOwner, `Car has expected owner OK`); + } + + t.end(); +}); diff --git a/packages/cactus-test-tooling/package-lock.json b/packages/cactus-test-tooling/package-lock.json index 4866fe715b..6eeb36769d 100644 --- a/packages/cactus-test-tooling/package-lock.json +++ b/packages/cactus-test-tooling/package-lock.json @@ -700,6 +700,11 @@ "delayed-stream": "~1.0.0" } }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", diff --git a/packages/cactus-test-tooling/package.json b/packages/cactus-test-tooling/package.json index 7cfe7324f8..3ef9cb6cb1 100644 --- a/packages/cactus-test-tooling/package.json +++ b/packages/cactus-test-tooling/package.json @@ -64,6 +64,7 @@ "dependencies": { "@hyperledger/cactus-common": "^0.2.0", "axios": "0.19.2", + "compare-versions": "3.6.0", "dockerode": "3.2.0", "extract-zip": "2.0.0", "fabric-client": "1.4.11", diff --git a/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts b/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts index 71ea518831..d9a44c62ab 100644 --- a/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts +++ b/packages/cactus-test-tooling/src/main/typescript/fabric/fabric-test-ledger-v1.ts @@ -1,6 +1,8 @@ import path from "path"; import { EventEmitter } from "events"; +import compareVersions, { compare } from "compare-versions"; + import Docker, { Container, ContainerCreateOptions, @@ -14,7 +16,7 @@ import { Gateway, } from "fabric-network"; import FabricCAServices from "fabric-ca-client"; -import Joi from "joi"; +import Joi, { array } from "joi"; import { ITestLedger } from "../i-test-ledger"; import { Containers } from "../common/containers"; import { @@ -31,6 +33,7 @@ export interface IFabricTestLedgerV1ConstructorOptions { publishAllPorts: boolean; imageVersion?: string; imageName?: string; + envVars?: Map; logLevel?: LogLevelDesc; } @@ -40,6 +43,7 @@ export interface IFabricTestLedgerV1ConstructorOptions { const DEFAULT_OPTS = Object.freeze({ imageVersion: "latest", imageName: "hyperledger/cactus-fabric-all-in-one", + envVars: new Map([["FABRIC_VERSION", "1.4.8"]]), }); export const FABRIC_TEST_LEDGER_DEFAULT_OPTIONS = DEFAULT_OPTS; @@ -53,6 +57,10 @@ const OPTS_JOI_SCHEMA: Joi.Schema = Joi.object().keys({ .regex(/[a-z0-9]+(?:[._-]{1,2}[a-z0-9]+)*/) .min(1) .required(), + envVars: Joi.object().pattern(/.*/, [ + Joi.string().required(), + Joi.string().min(1).required(), + ]), }); export const FABRIC_TEST_LEDGER_OPTIONS_JOI_SCHEMA = OPTS_JOI_SCHEMA; @@ -63,6 +71,7 @@ export class FabricTestLedgerV1 implements ITestLedger { public readonly imageVersion: string; public readonly imageName: string; public readonly publishAllPorts: boolean; + public readonly envVars: Map; private readonly log: Logger; @@ -84,6 +93,12 @@ export class FabricTestLedgerV1 implements ITestLedger { this.imageVersion = options.imageVersion || DEFAULT_OPTS.imageVersion; this.imageName = options.imageName || DEFAULT_OPTS.imageName; this.publishAllPorts = options.publishAllPorts; + this.envVars = options.envVars || DEFAULT_OPTS.envVars; + + if (compareVersions.compare(this.getFabricVersion(), "1.4", "<")) + this.log.warn( + `This version of Fabric ${this.getFabricVersion()} is unsupported` + ); this.validateConstructorOptions(); } @@ -101,6 +116,10 @@ export class FabricTestLedgerV1 implements ITestLedger { return `${this.imageName}:${this.imageVersion}`; } + public getFabricVersion(): string { + return `${this.envVars.get("FABRIC_VERSION")}`; + } + public getDefaultMspId(): string { return "Org1MSP"; } @@ -126,7 +145,7 @@ export class FabricTestLedgerV1 implements ITestLedger { const fnTag = `${this.className}#enrollUser()`; try { const mspId = this.getDefaultMspId(); - const enrollmentID = "user1"; + const enrollmentID = "user2"; const connectionProfile = await this.getConnectionProfileOrg1(); // Create a new gateway for connecting to our peer node. const gateway = new Gateway(); @@ -199,7 +218,17 @@ export class FabricTestLedgerV1 implements ITestLedger { const fnTag = `${this.className}#getConnectionProfileOrg1()`; const cInfo = await this.getContainerInfo(); const container = this.getContainer(); - const ccpJsonPath = "/fabric-samples/first-network/connection-org1.json"; + const CCP_JSON_PATH_FABRIC_V1: string = + "/fabric-samples/first-network/connection-org1.json"; + const CCP_JSON_PATH_FABRIC_V2: string = + "/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/connection-org1.json"; + const ccpJsonPath = compareVersions.compare( + this.getFabricVersion(), + "2.0", + "<" + ) + ? CCP_JSON_PATH_FABRIC_V1 + : CCP_JSON_PATH_FABRIC_V2; const ccpJson = await Containers.pullFile(container, ccpJsonPath); const ccp = JSON.parse(ccpJson); @@ -209,7 +238,7 @@ export class FabricTestLedgerV1 implements ITestLedger { const hostPort = await Containers.getPublicPort(privatePort, cInfo); ccp.peers["peer0.org1.example.com"].url = `grpcs://localhost:${hostPort}`; } - { + if (ccp.peers["peer1.org1.example.com"]) { // peer1.org1.example.com const privatePort = 8051; const hostPort = await Containers.getPublicPort(privatePort, cInfo); @@ -236,8 +265,17 @@ export class FabricTestLedgerV1 implements ITestLedger { const privatePort = 7050; const hostPort = await Containers.getPublicPort(privatePort, cInfo); const url = `grpcs://localhost:${hostPort}`; - const ordererPemPath = + const ORDERER_PEM_PATH_FABRIC_V1: string = "/fabric-samples/first-network/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem"; + const ORDERER_PEM_PATH_FABRIC_V2: string = + "/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"; + const ordererPemPath = compareVersions.compare( + this.getFabricVersion(), + "2.0", + "<" + ) + ? ORDERER_PEM_PATH_FABRIC_V1 + : ORDERER_PEM_PATH_FABRIC_V2; const pem = await Containers.pullFile(container, ordererPemPath); ccp.orderers = { @@ -301,6 +339,9 @@ export class FabricTestLedgerV1 implements ITestLedger { public async start(omitPull: boolean = false): Promise { const containerNameAndTag = this.getContainerImageName(); + const dockerEnvVars: string[] = new Array(...this.envVars).map( + (pairs) => `${pairs[0]}=${pairs[1]}` + ); if (this.container) { await this.container.stop(); @@ -329,6 +370,8 @@ export class FabricTestLedgerV1 implements ITestLedger { "10051/tcp": {}, // peer1.org2.example.com }, + Env: dockerEnvVars, + // This is a workaround needed for macOS which has issues with routing // to docker container's IP addresses directly... // https://stackoverflow.com/a/39217691 @@ -450,6 +493,7 @@ export class FabricTestLedgerV1 implements ITestLedger { imageVersion: this.imageVersion, imageName: this.imageName, publishAllPorts: this.publishAllPorts, + envVars: this.envVars, }, OPTS_JOI_SCHEMA ); diff --git a/tools/docker/fabric-all-in-one/Dockerfile b/tools/docker/fabric-all-in-one/Dockerfile_v1.4.x similarity index 92% rename from tools/docker/fabric-all-in-one/Dockerfile rename to tools/docker/fabric-all-in-one/Dockerfile_v1.4.x index fb03fbb95f..ccb11eab8e 100644 --- a/tools/docker/fabric-all-in-one/Dockerfile +++ b/tools/docker/fabric-all-in-one/Dockerfile_v1.4.x @@ -3,6 +3,7 @@ FROM docker:18.09.9-dind ARG FABRIC_VERSION=1.4.8 +ARG CA_VERSION=1.4.9 WORKDIR / @@ -34,6 +35,14 @@ RUN apk add --no-cache curl # The file binary is used to inspect exectubles when debugging container image issues RUN apk add --no-cache file +# Download and setup path variables for Go +RUN wget https://golang.org/dl/go1.15.5.linux-amd64.tar.gz +RUN tar -xvf go1.15.5.linux-amd64.tar.gz +RUN mv go /usr/local +ENV GOROOT=/usr/local/go +ENV GOPATH=/usr/local/go +ENV PATH=$PATH:$GOPATH/bin + # Needed because the Fabric binaries need the GNU libc dynamic linker to be executed # and alpine does not have that by default # @see https://askubuntu.com/a/1035037/1008695 @@ -71,7 +80,7 @@ RUN curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/release-2.2/s RUN chmod +x bootstrap.sh # Run the bootstrap here so that at least we can pre-fetch the git clone and the binary downloads resulting in # faster container startup speed since these steps will not have to be done, only the docker image pulls. -RUN /bootstrap.sh $FABRIC_VERSION $FABRIC_VERSION -d +RUN /bootstrap.sh ${FABRIC_VERSION} ${CA_VERSION} -d # Install supervisord because we need to run the docker daemon and also the fabric network # meaning that we have multiple processes to run. @@ -79,6 +88,7 @@ RUN apk add --no-cache supervisor COPY supervisord.conf /etc/supervisord.conf COPY run-fabric-network.sh / +COPY healthcheck.sh / # supervisord web ui/dashboard EXPOSE 9001 @@ -114,4 +124,4 @@ CMD ["--configuration", "/etc/supervisord.conf", "--nodaemon"] # We consider the container healthy once the default example fabcar contract has been deployed # and is responsive to queries as well -HEALTHCHECK --interval=1s --timeout=5s --start-period=60s --retries=300 CMD docker exec cli peer chaincode query --channelID mychannel --name fabcar --ctor '{"Args": [], "Function": "queryAllCars"}' +HEALTHCHECK --interval=1s --timeout=5s --start-period=60s --retries=300 CMD ./healthcheck.sh diff --git a/tools/docker/fabric-all-in-one/Dockerfile_v2.x b/tools/docker/fabric-all-in-one/Dockerfile_v2.x new file mode 100644 index 0000000000..6c4a107e00 --- /dev/null +++ b/tools/docker/fabric-all-in-one/Dockerfile_v2.x @@ -0,0 +1,127 @@ +# We need to use the older, more stable v18 here because of +# https://github.com/docker-library/docker/issues/170 +FROM docker:18.09.9-dind + +ARG FABRIC_VERSION=2.2.0 +ARG CA_VERSION=1.4.9 + +WORKDIR / + +RUN apk update + +# Install dependencies of Docker Compose +RUN apk add py-pip python3-dev libffi-dev openssl-dev gcc libc-dev make + +# Install python/pip - We need this because DinD 18.x has Python 2 +# And we cannot upgrade to DinD 19 because of +# https://github.com/docker-library/docker/issues/170 +ENV PYTHONUNBUFFERED=1 +RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python +RUN python3 -m ensurepip +RUN pip3 install --no-cache --upgrade pip setuptools + +# Install Docker Compose which is a dependency of Fabric Samples +RUN pip install docker-compose + +# Need git to clone the sources of the Fabric Samples repository from GitHub +RUN apk add --no-cache git + +# Fabric Samples needs bash, sh is not good enough here +RUN apk add --no-cache bash + +# Need curl to download the Fabric bootstrap script +RUN apk add --no-cache curl + +# The file binary is used to inspect exectubles when debugging container image issues +RUN apk add --no-cache file + +# Download and setup path variables for Go +RUN wget https://golang.org/dl/go1.15.5.linux-amd64.tar.gz +RUN tar -xvf go1.15.5.linux-amd64.tar.gz +RUN mv go /usr/local +ENV GOROOT=/usr/local/go +ENV GOPATH=/usr/local/go +ENV PATH=$PATH:$GOPATH/bin + +# Needed because the Fabric binaries need the GNU libc dynamic linker to be executed +# and alpine does not have that by default +# @see https://askubuntu.com/a/1035037/1008695 +# @see https://github.com/gliderlabs/docker-alpine/issues/219#issuecomment-254741346 +RUN apk add --no-cache libc6-compat + +ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus +RUN mkdir -p $CACTUS_CFG_PATH +# OpenSSH - need to have it so we can shell in and install/instantiate contracts +RUN apk add --no-cache openssh augeas + +# Configure the OpenSSH server we just installed +RUN augtool 'set /files/etc/ssh/sshd_config/AuthorizedKeysFile ".ssh/authorized_keys /etc/authorized_keys/%u"' +RUN augtool 'set /files/etc/ssh/sshd_config/PermitRootLogin yes' +RUN augtool 'set /files/etc/ssh/sshd_config/PasswordAuthentication no' +RUN augtool 'set /files/etc/ssh/sshd_config/Port 22' +# Create the server's key - without this sshd will refuse to start +RUN ssh-keygen -A + +# Generate an RSA keypair on the fly to avoid having to hardcode one in the image +# which technically does not pose a security threat since this is only a development +# image, but we do it like this anyway. +RUN mkdir ~/.ssh +RUN chmod 700 ~/.ssh/ +RUN touch ~/.ssh/authorized_keys +RUN ["/bin/bash", "-c", "ssh-keygen -t rsa -N '' -f $CACTUS_CFG_PATH/fabric-aio-image <<< y"] +RUN mv $CACTUS_CFG_PATH/fabric-aio-image $CACTUS_CFG_PATH/fabric-aio-image.key +RUN cp $CACTUS_CFG_PATH/fabric-aio-image.pub ~/.ssh/authorized_keys + +# Download and execute the Fabric bootstrap script, but instruct it with the -d +# flag to avoid pulling docker images because during the build phase of this image +# there is no docker daemon running yet so this has to happen in the CMD once a +# container has been started from the image => see ./run-fabric-network-sh +RUN curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/release-2.2/scripts/bootstrap.sh > /bootstrap.sh +RUN chmod +x bootstrap.sh +# Run the bootstrap here so that at least we can pre-fetch the git clone and the binary downloads resulting in +# faster container startup speed since these steps will not have to be done, only the docker image pulls. +RUN /bootstrap.sh ${FABRIC_VERSION} ${CA_VERSION} -d + +# Install supervisord because we need to run the docker daemon and also the fabric network +# meaning that we have multiple processes to run. +RUN apk add --no-cache supervisor +COPY supervisord.conf /etc/supervisord.conf + +COPY run-fabric-network.sh / +COPY healthcheck.sh / + +# supervisord web ui/dashboard +EXPOSE 9001 + +# peer1.org2.example.com +EXPOSE 10051 + +# peer0.org1.example.com +EXPOSE 7051 + +# peer0.org2.example.com +EXPOSE 9051 + +# peer1.org1.example.com +EXPOSE 8051 + +# orderer.example.com +EXPOSE 7050 + +# ca_peerOrg1 +EXPOSE 7054 + +# ca_peerOrg2 +EXPOSE 8054 + +# couchdb0, couchdb1, couchdb2, couchdb3 +EXPOSE 5984 6984 7984 8984 + +# Extend the parent image's entrypoint +# https://superuser.com/questions/1459466/can-i-add-an-additional-docker-entrypoint-script +ENTRYPOINT ["/usr/bin/supervisord"] +CMD ["--configuration", "/etc/supervisord.conf", "--nodaemon"] + +# We consider the container healthy once the default example fabcar contract has been deployed +# and is responsive to queries as well +HEALTHCHECK --interval=1s --timeout=5s --start-period=60s --retries=300 CMD ./healthcheck.sh diff --git a/tools/docker/fabric-all-in-one/README.md b/tools/docker/fabric-all-in-one/README.md index 4135197184..41589143cb 100644 --- a/tools/docker/fabric-all-in-one/README.md +++ b/tools/docker/fabric-all-in-one/README.md @@ -12,9 +12,14 @@ Example `.vscode/tasks.json` file for building/running the image: "version": "2.0.0", "tasks": [ { - "label": "Docker - BUILD and TAG: Latest", + "label": "Docker - BUILD and TAG: 1.4.x", "type": "shell", - "command": "docker build . -t hyperledger/cactus-fabric-all-in-one:latest" + "command": "docker build . -f Dockerfile_v1.4.x -t hyperledger/cactus-fabric-all-in-one:1.4.8" + }, + { + "label": "Docker - BUILD and TAG: 2.x", + "type": "shell", + "command": "docker build . -f Dockerfile_v2.x -t hyperledger/cactus-fabric-all-in-one:2.2.0" }, { "label": "Docker Compose - BUILD", @@ -32,7 +37,25 @@ Example `.vscode/tasks.json` file for building/running the image: ## Running Fabric CLI Container Commands +For Fabric 1.4.x + ```sh $ docker exec -it --workdir /fabric-samples/fabcar/ dindy docker exec cli peer chaincode query --channelID mychannel --name fabcar --ctor '{"Args": [], "Function": "queryAllCars"}' [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},{"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}] ``` + +For Fabric 2.x + +```sh +cd /fabric-samples/test-network +export PATH=${PWD}/../bin:${PWD}:$PATH +export FABRIC_CFG_PATH=$PWD/../config/ +# for peer command issued to peer0.org1.example.com +export CORE_PEER_TLS_ENABLED=true +export CORE_PEER_LOCALMSPID="Org1MSP" +export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt +export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp +export CORE_PEER_ADDRESS=localhost:7051 +peer chaincode query --channelID mychannel --name fabcar --ctor '{"Args": [], "Function": "queryAllCars"}' +[{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR277","Record":{"make":"Trabant","model":"601","colour":"Blue","owner":"4cf0a45d-1349-4900-927c-d03e2a2c4dfc"}},{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}] +``` diff --git a/tools/docker/fabric-all-in-one/healthcheck.sh b/tools/docker/fabric-all-in-one/healthcheck.sh new file mode 100755 index 0000000000..6663fd2d8f --- /dev/null +++ b/tools/docker/fabric-all-in-one/healthcheck.sh @@ -0,0 +1,18 @@ +if echo ${FABRIC_VERSION} | grep 2. +then + cd fabric-samples/test-network + export PATH=${PWD}/../bin:${PWD}:$PATH + export FABRIC_CFG_PATH=$PWD/../config/ + # for peer command issued to peer0.org1.example.com + export CORE_PEER_TLS_ENABLED=true + export CORE_PEER_LOCALMSPID="Org1MSP" + export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt + export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp + export CORE_PEER_ADDRESS=localhost:7051 + peer chaincode query --channelID mychannel --name fabcar --ctor '{"Args": [], "Function": "queryAllCars"}' +elif echo ${FABRIC_VERSION} | grep 1. +then + docker exec cli peer chaincode query --channelID mychannel --name fabcar --ctor '{"Args": [], "Function": "queryAllCars"}' +else + echo "Unsupported fabric version." +fi \ No newline at end of file diff --git a/tools/docker/fabric-all-in-one/run-fabric-network.sh b/tools/docker/fabric-all-in-one/run-fabric-network.sh index 512133393b..e801476b49 100755 --- a/tools/docker/fabric-all-in-one/run-fabric-network.sh +++ b/tools/docker/fabric-all-in-one/run-fabric-network.sh @@ -1,7 +1,6 @@ #!/bin/sh set -e -# TODO: make the verion numbers here injectable to the script -/bootstrap.sh 1.4.8 1.4.8 -b -s +/bootstrap.sh ${FABRIC_VERSION} ${CA_VERSION} -b -s cd /fabric-samples/fabcar/ ./startFabric.sh diff --git a/tools/docker/fabric-all-in-one/supervisord.conf b/tools/docker/fabric-all-in-one/supervisord.conf index 8f9af9e9d7..811a873c72 100644 --- a/tools/docker/fabric-all-in-one/supervisord.conf +++ b/tools/docker/fabric-all-in-one/supervisord.conf @@ -4,7 +4,6 @@ logfile_maxbytes = 50MB logfile_backups=10 loglevel = info - [program:sshd] command=/usr/sbin/sshd -D autostart=true