From 6fed945fb5f8321b4e632bf1c8967cb2a926609d Mon Sep 17 00:00:00 2001 From: adrianbatuto Date: Tue, 20 Aug 2024 00:51:27 +0800 Subject: [PATCH] feat(corda): dockerfile update to include cordapps Primary Changes ---------------- 1. Created AIO to support the deployment of Cordapps in Corda 5 2. Created corda-v5-cordapp-deployment.test.ts to test the AIO Fixes #3442 Signed-off-by: adrianbatuto --- .../package.json | 1 + .../corda-v5-cordapp-deployment.test.ts | 584 ++++++++++++++++++ .../typescript/corda/corda-v5-test-ledger.ts | 5 + .../corda-v5/cordapps-deployment/Dockerfile | 79 +++ .../corda-v5/cordapps-deployment/README.md | 7 + .../cordapps-deployment/healthcheck.sh | 30 + .../cordapps-deployment/start-services.sh | 12 + .../cordapps-deployment/supervisord.conf | 28 + yarn.lock | 1 + 9 files changed, 747 insertions(+) create mode 100644 packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v5-x/corda-v5-cordapp-deployment.test.ts create mode 100644 tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/Dockerfile create mode 100644 tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/README.md create mode 100755 tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/healthcheck.sh create mode 100755 tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/start-services.sh create mode 100644 tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/supervisord.conf diff --git a/packages/cactus-plugin-ledger-connector-corda/package.json b/packages/cactus-plugin-ledger-connector-corda/package.json index 2fbcec0150..33e1bf6ac0 100644 --- a/packages/cactus-plugin-ledger-connector-corda/package.json +++ b/packages/cactus-plugin-ledger-connector-corda/package.json @@ -63,6 +63,7 @@ "axios": "1.6.0", "express": "4.19.2", "express-openapi-validator": "5.2.0", + "form-data": "4.0.0", "http-errors-enhanced-cjs": "2.0.1", "internal-ip": "6.2.0", "joi": "17.13.3", diff --git a/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v5-x/corda-v5-cordapp-deployment.test.ts b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v5-x/corda-v5-cordapp-deployment.test.ts new file mode 100644 index 0000000000..e4c3cba07b --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/corda-v5-x/corda-v5-cordapp-deployment.test.ts @@ -0,0 +1,584 @@ +import "jest-extended"; +import { CordaV5TestLedger } from "@hyperledger/cactus-test-tooling"; +import fetch from "node-fetch"; +import FormData from "form-data"; +import https from "https"; + +describe("Corda Test Case", () => { + const cordaV5TestLedger = new CordaV5TestLedger({ + imageName: "cactuts/cordappdeployment", + imageVersion: "latest", + }); + beforeAll(async () => { + await cordaV5TestLedger.start(); + expect(cordaV5TestLedger).toBeTruthy(); + }); + afterAll(async () => { + await cordaV5TestLedger.stop(); + await cordaV5TestLedger.destroy(); + }); + + describe("Upload Certificates and CPI ", () => { + const username = "admin"; + const password = "admin"; + const auth = + "Basic " + Buffer.from(`${username}:${password}`).toString("base64"); + let cpiHash = ""; + let aliceHoldingId = ""; + let bobHoldingId = ""; + let charlieHoldingId = ""; + let daveHoldingId = ""; + let notaryRep1HoldingId = ""; + let operatorCpiHash = ""; + const agent = new https.Agent({ rejectUnauthorized: false }); + test("Get and upload digicert-ca", async () => { + const cpiFilePath = "/CSDE-cordapp-template-kotlin/config/r3-ca-key.pem"; + const r3KeyBuffer = + await cordaV5TestLedger.getFileFromContainer(cpiFilePath); + const form = new FormData(); + form.append("alias", "digicert-ca"); + form.append("certificate", r3KeyBuffer, "r3-ca-key.pem"); + const response = await fetch( + "https://localhost:8888/api/v1/certificates/cluster/code-signer", + { + method: "PUT", + body: form, + headers: { + accept: "*/*", + Authorization: auth, + ...form.getHeaders(), + }, + agent: agent, + }, + ); + expect(response.status).toBe(204); + }); + test("Get and upload default key", async () => { + const defaultKeyFilePath = + "/CSDE-cordapp-template-kotlin/config/gradle-plugin-default-key.pem"; + const defaultKeyBuffer = + await cordaV5TestLedger.getFileFromContainer(defaultKeyFilePath); + const form = new FormData(); + form.append("alias", "gradle-plugin-default-key"); + form.append( + "certificate", + defaultKeyBuffer, + "gradle-plugin-default-key.pem", + ); + const response = await fetch( + "https://localhost:8888/api/v1/certificates/cluster/code-signer", + { + method: "PUT", + body: form, + headers: { + accept: "*/*", + Authorization: auth, + ...form.getHeaders(), + }, + agent: agent, + }, + ); + expect(response.status).toBe(204); + }); + test("Get and upload signing key", async () => { + const signingKeyFilePath = + "/CSDE-cordapp-template-kotlin/workspace/signingkey1.pem"; + const signingKeyBuffer = + await cordaV5TestLedger.getFileFromContainer(signingKeyFilePath); + const form = new FormData(); + form.append("alias", "my-signing-key"); + form.append("certificate", signingKeyBuffer, "signingkey1.pem"); + const response = await fetch( + "https://localhost:8888/api/v1/certificates/cluster/code-signer", + { + method: "PUT", + body: form, + headers: { + accept: "*/*", + Authorization: auth, + ...form.getHeaders(), + }, + agent: agent, + }, + ); + expect(response.status).toBe(204); + }); + test("Query Certificates", async () => { + const response = await fetch( + "https://localhost:8888/api/v1/certificates/cluster/code-signer", + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + expect(response.status).toBe(200); + }); + test("Get and upload CPI", async () => { + const cpiFilePath = + "/CSDE-cordapp-template-kotlin/workflows/build/MyCorDapp-1.0-SNAPSHOT.cpi"; + const cpiBuffer = + await cordaV5TestLedger.getFileFromContainer(cpiFilePath); + const form = new FormData(); + form.append("upload", cpiBuffer, "MyCorDapp-1.0-SNAPSHOT.cpi"); + let response = await fetch("https://localhost:8888/api/v1/cpi", { + method: "POST", + body: form, + headers: { + accept: "*/*", + Authorization: auth, + ...form.getHeaders(), + }, + agent: agent, + }); + let responseBody = await response.json(); + expect(response.status).toBe(200); + const requestId = responseBody.id; + + // Wait time to make sure upload is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + + response = await fetch( + `https://localhost:8888/api/v1/cpi/status/${requestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBody = await response.json(); + cpiHash = responseBody.cpiFileChecksum; + + // Notary Server + const operatorCpiFilePath = + "/CSDE-cordapp-template-kotlin/workflows/build/NotaryServer-1.0-SNAPSHOT.cpi"; + const operatorCpiBuffer = + await cordaV5TestLedger.getFileFromContainer(operatorCpiFilePath); + const form2 = new FormData(); + form2.append( + "upload", + operatorCpiBuffer, + "NotaryServer-1.0-SNAPSHOT.cpi", + ); + let response2 = await fetch("https://localhost:8888/api/v1/cpi", { + method: "POST", + body: form2, + headers: { + accept: "*/*", + Authorization: auth, + ...form2.getHeaders(), + }, + agent: agent, + }); + let response2Body = await response2.json(); + console.log("check response body " + JSON.stringify(response2Body)); + expect(response2.status).toBe(200); + const operatorRequestId = response2Body.id; + + // Wait time to make sure upload is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + + response2 = await fetch( + `https://localhost:8888/api/v1/cpi/status/${operatorRequestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + response2Body = await response2.json(); + operatorCpiHash = response2Body.cpiFileChecksum; + }); + test("Create Virtual Nodes", async () => { + const X500Alice = "CN=Alice, OU=Test Dept, O=R3, L=London, C=GB"; + const X500Bob = "CN=Bob, OU=Test Dept, O=R3, L=London, C=GB"; + const X500Charlie = "CN=Charlie, OU=Test Dept, O=R3, L=London, C=GB"; + const X500Dave = "CN=Dave, OU=Test Dept, O=R3, L=London, C=GB"; + const X500NotaryRep1 = + "CN=NotaryRep1, OU=Test Dept, O=R3, L=London, C=GB"; + let responseAlice = await fetch( + `https://localhost:8888/api/v1/virtualnode`, + { + method: "POST", + body: JSON.stringify({ + cpiFileChecksum: cpiHash, + x500Name: X500Alice, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyAlice = await responseAlice.json(); + aliceHoldingId = responseBodyAlice.requestId; + + // Wait time to make sure Node creation is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + + responseAlice = await fetch( + `https://localhost:8888/api/v1/virtualnode/status/${aliceHoldingId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyAlice = await responseAlice.json(); + expect(responseBodyAlice.status).toBe("SUCCEEDED"); + + //BOB + let responseBob = await fetch( + `https://localhost:8888/api/v1/virtualnode`, + { + method: "POST", + body: JSON.stringify({ + cpiFileChecksum: cpiHash, + x500Name: X500Bob, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyBob = await responseBob.json(); + bobHoldingId = responseBodyBob.requestId; + + // Wait time to make sure Node creation is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + responseBob = await fetch( + `https://localhost:8888/api/v1/virtualnode/status/${bobHoldingId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyBob = await responseBob.json(); + expect(responseBodyBob.status).toBe("SUCCEEDED"); + // Charlie + let responseCharlie = await fetch( + `https://localhost:8888/api/v1/virtualnode`, + { + method: "POST", + body: JSON.stringify({ + cpiFileChecksum: cpiHash, + x500Name: X500Charlie, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyCharlie = await responseCharlie.json(); + charlieHoldingId = responseBodyCharlie.requestId; + + // Wait time to make sure Node creation is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + responseCharlie = await fetch( + `https://localhost:8888/api/v1/virtualnode/status/${charlieHoldingId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyCharlie = await responseCharlie.json(); + expect(responseBodyCharlie.status).toBe("SUCCEEDED"); + // Dave + let responseDave = await fetch( + `https://localhost:8888/api/v1/virtualnode`, + { + method: "POST", + body: JSON.stringify({ + cpiFileChecksum: cpiHash, + x500Name: X500Dave, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyDave = await responseDave.json(); + daveHoldingId = responseBodyDave.requestId; + + // Wait time to make sure Node creation is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + responseDave = await fetch( + `https://localhost:8888/api/v1/virtualnode/status/${daveHoldingId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyDave = await responseDave.json(); + expect(responseBodyDave.status).toBe("SUCCEEDED"); + //NotaryRep1 + let responseNotaryRep1 = await fetch( + `https://localhost:8888/api/v1/virtualnode`, + { + method: "POST", + body: JSON.stringify({ + cpiFileChecksum: operatorCpiHash, + x500Name: X500NotaryRep1, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyNotaryRep1 = await responseNotaryRep1.json(); + notaryRep1HoldingId = responseBodyNotaryRep1.requestId; + + // Wait time to make sure Node creation is done + await new Promise((resolve) => setTimeout(resolve, 5000)); + responseNotaryRep1 = await fetch( + `https://localhost:8888/api/v1/virtualnode/status/${notaryRep1HoldingId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyNotaryRep1 = await responseNotaryRep1.json(); + expect(responseBodyNotaryRep1.status).toBe("SUCCEEDED"); + }); + test("Register Virtual Nodes", async () => { + let responseAlice = await fetch( + `https://localhost:8888/api/v1/membership/${aliceHoldingId}`, + { + method: "POST", + body: JSON.stringify({ + context: { + "corda.key.scheme": "CORDA.ECDSA.SECP256R1", + }, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyAlice = await responseAlice.json(); + const aliceRequestId = responseBodyAlice.registrationId; + // Wait time to make sure Approval is done + await new Promise((resolve) => setTimeout(resolve, 30000)); + responseAlice = await fetch( + `https://localhost:8888/api/v1/membership/${aliceHoldingId}/${aliceRequestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyAlice = await responseAlice.json(); + console.log( + "checking alice approval " + JSON.stringify(responseBodyAlice), + ); + expect(responseBodyAlice.registrationStatus).toBe("APPROVED"); + + //BOB + let responseBob = await fetch( + `https://localhost:8888/api/v1/membership/${bobHoldingId}`, + { + method: "POST", + body: JSON.stringify({ + context: { + "corda.key.scheme": "CORDA.ECDSA.SECP256R1", + }, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyBob = await responseBob.json(); + const bobRequestId = responseBodyBob.registrationId; + // Wait time to make sure Approval is done + await new Promise((resolve) => setTimeout(resolve, 30000)); + responseBob = await fetch( + `https://localhost:8888/api/v1/membership/${bobHoldingId}/${bobRequestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyBob = await responseBob.json(); + console.log("checking bob approval " + JSON.stringify(responseBodyBob)); + expect(responseBodyBob.registrationStatus).toBe("APPROVED"); + + //Charlie + let responseCharlie = await fetch( + `https://localhost:8888/api/v1/membership/${charlieHoldingId}`, + { + method: "POST", + body: JSON.stringify({ + context: { + "corda.key.scheme": "CORDA.ECDSA.SECP256R1", + }, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyCharlie = await responseCharlie.json(); + const charlieRequestId = responseBodyCharlie.registrationId; + // Wait time to make sure Approval is done + await new Promise((resolve) => setTimeout(resolve, 30000)); + responseCharlie = await fetch( + `https://localhost:8888/api/v1/membership/${charlieHoldingId}/${charlieRequestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyCharlie = await responseCharlie.json(); + console.log( + "checking charlie approval " + JSON.stringify(responseBodyCharlie), + ); + expect(responseBodyCharlie.registrationStatus).toBe("APPROVED"); + //Dave + let responseDave = await fetch( + `https://localhost:8888/api/v1/membership/${daveHoldingId}`, + { + method: "POST", + body: JSON.stringify({ + context: { + "corda.key.scheme": "CORDA.ECDSA.SECP256R1", + }, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyDave = await responseDave.json(); + const daveRequestId = responseBodyDave.registrationId; + // Wait time to make sure Approval is done + await new Promise((resolve) => setTimeout(resolve, 30000)); + responseDave = await fetch( + `https://localhost:8888/api/v1/membership/${daveHoldingId}/${daveRequestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyDave = await responseDave.json(); + console.log("checking dave approval " + JSON.stringify(responseBodyDave)); + expect(responseBodyDave.registrationStatus).toBe("APPROVED"); + //NotaryRep + let responseNotaryRep1 = await fetch( + `https://localhost:8888/api/v1/membership/${notaryRep1HoldingId}`, + { + method: "POST", + body: JSON.stringify({ + context: { + "corda.key.scheme": "CORDA.ECDSA.SECP256R1", + }, + }), + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + let responseBodyNotaryRep1 = await responseNotaryRep1.json(); + const notaryRep1RequestId = responseBodyNotaryRep1.registrationId; + // Wait time to make sure Approval is done + await new Promise((resolve) => setTimeout(resolve, 60000)); + responseNotaryRep1 = await fetch( + `https://localhost:8888/api/v1/membership/${notaryRep1HoldingId}/${notaryRep1RequestId}`, + { + method: "GET", + headers: { + Authorization: auth, + }, + agent: agent, + }, + ); + responseBodyNotaryRep1 = await responseNotaryRep1.json(); + console.log( + "checking notaryRep1 approval " + + JSON.stringify(responseBodyNotaryRep1), + ); + expect(responseBodyNotaryRep1.registrationStatus).toBe("APPROVED"); + }); + test("Start Sample Flow", async () => { + const createSampleFlow = { + clientRequestId: "create-1", + flowClassName: + "com.r3.developers.csdetemplate.utxoexample.workflows.CreateNewChatFlow", + requestBody: { + chatName: "Chat with Bob", + otherMember: "CN=Bob, OU=Test Dept, O=R3, L=London, C=GB", + message: "Hello Bob", + }, + }; + const cordaReqBuff = Buffer.from(JSON.stringify(createSampleFlow)); + const response = await fetch( + `https://localhost:8888/api/v1/flow/${aliceHoldingId}`, + { + method: `POST`, + headers: { + Authorization: auth, + }, + body: cordaReqBuff, + agent, + }, + ); + const responseBody = await response.json(); + expect(responseBody.flowStatus).toBe("START_REQUESTED"); + }); + test("Get sample flow", async () => { + const response2 = await fetch( + `https://localhost:8888/api/v1/flow/${aliceHoldingId}/create-1`, + { + method: `GET`, + headers: { + Authorization: auth, + }, + agent, + }, + ); + const response2Body = await response2.json(); + console.log(response2Body); + expect(response2Body.flowStatus).toBe("COMPLETED"); + }); + }); +}); diff --git a/packages/cactus-test-tooling/src/main/typescript/corda/corda-v5-test-ledger.ts b/packages/cactus-test-tooling/src/main/typescript/corda/corda-v5-test-ledger.ts index 57c452be1a..d79ee65fd1 100644 --- a/packages/cactus-test-tooling/src/main/typescript/corda/corda-v5-test-ledger.ts +++ b/packages/cactus-test-tooling/src/main/typescript/corda/corda-v5-test-ledger.ts @@ -254,6 +254,11 @@ export class CordaV5TestLedger implements ITestLedger { throw new Error(`${fnTag} ${validationResult.error.annotate()}`); } } + public async getFileFromContainer(filePath: string): Promise { + const container = this.getContainer(); + const binaryFile = await Containers.pullBinaryFile(container, filePath); + return binaryFile; + } } export function extractShortHash(shortHashID: string, name: string) { diff --git a/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/Dockerfile b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/Dockerfile new file mode 100644 index 0000000000..87bb01f578 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/Dockerfile @@ -0,0 +1,79 @@ +FROM docker:20.10.3-dind + +RUN apk update +RUN apk add py-pip python3-dev libffi-dev openssl-dev gcc libc-dev make + +# Need curl for healthchecks +RUN apk add --no-cache curl + +# Need to run shell script run.sh for Corda CLI +RUN apk add --no-cache bash + +# The file binary is used to inspect exectubles when debugging container image issues +RUN apk add --no-cache file +RUN apk add --no-cache ca-certificates +RUN apk add --no-cache tzdata +RUN apk add --no-cache gnupg + +#----------------- INSTALLING CORDA CDSE PREREQUISITES -------------------- +#-------------------------------------------------------------------------- + +# Installing Zulu17 JDK +RUN wget -P /etc/apk/keys/ \ +https://cdn.azul.com/public_keys/alpine-signing@azul.com-5d5dc44c.rsa.pub +RUN echo "https://repos.azul.com/zulu/alpine" | tee -a /etc/apk/repositories +RUN apk update +RUN apk add --no-cache zulu17-jdk + +# Installing Corda CLI +RUN mkdir /platform-jars && \ + wget -O /platform-jars/binary.tar.gz \ + https://download.corda.net/c5-release-pack/f82c7008-3b72-48fb-8e25-5ca38a9483b1-5.1.0/platform-jars-5.1.0.tar.gz + +RUN cd /platform-jars/ && \ + tar -xvzf binary.tar.gz && \ + cp net/corda/cli/deployment/corda-cli-installer/5.1.0.0/corda-cli-installer-5.1.0.0.zip . && \ + unzip corda-cli-installer-5.1.0.0.zip -d corda-cli-installer && \ + corda-cli-installer/./install.sh +ENV PATH="$PATH:~/.corda/cli" +#-------------------------------------------------------------------------- +#-------------------------------------------------------------------------- + +# Installing CORDA CDSE +RUN apk add --no-cache git +RUN git clone https://github.com/corda/CSDE-cordapp-template-kotlin.git + +RUN cd CSDE-cordapp-template-kotlin/ && \ + git checkout release/corda-5-0 && \ + sed -i 's/cordaNotaryPluginsVersion=5.0.0.0/cordaNotaryPluginsVersion=5.0.1.0/' gradle.properties && \ + sed -i 's/combinedWorkerJarVersion=5.0.0.0/combinedWorkerJarVersion=5.0.1.0/' gradle.properties && \ + sed -i 's/import static org.gradle.api.JavaVersion.VERSION_11/import static org.gradle.api.JavaVersion.VERSION_17/' build.gradle && \ + sed -i 's/def javaVersion = VERSION_11/def javaVersion = VERSION_17/' build.gradle + +RUN apk add --no-cache supervisor +## TO FIX: Exposing the required ports 5005, 5432 and 8888 for CSDE +## and 9001 for supervisor. Currently commented because of "--network host" being used to run the container +# EXPOSE 5005 +# EXPOSE 5432 +# EXPOSE 8888 +# EXPOSE 9001 +EXPOSE 22 + +COPY supervisord.conf /etc/supervisord.conf + +COPY start-services.sh /start-services.sh +RUN chmod +x /start-services.sh + +COPY healthcheck.sh /healthcheck.sh +RUN chmod +x /healthcheck.sh + +WORKDIR /CSDE-cordapp-template-kotlin/ + +# 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"] + +HEALTHCHECK --interval=30s --timeout=60s --start-period=200s --retries=100 CMD /healthcheck.sh + + diff --git a/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/README.md b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/README.md new file mode 100644 index 0000000000..0092751045 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/README.md @@ -0,0 +1,7 @@ +# Instructions to compile and run the new Corda v5.0 test network + +To create an image of the dockerfile run: +`DOCKER_BUILDKIT=1 docker build ./tools/docker/corda-all-in-one/corda-v5/cordapps-deployment -t cordappdeployment` + +To run the AIO, execute: +`docker run -it --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock --network host -d cordappdeployment` \ No newline at end of file diff --git a/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/healthcheck.sh b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/healthcheck.sh new file mode 100755 index 0000000000..e863966304 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/healthcheck.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# Check if CPI has been generated +check_cpi_exists() { + local file_path="/CSDE-cordapp-template-kotlin/workflows/build/MyCorDapp-1.0-SNAPSHOT.cpi" + + if [ ! -f "$file_path" ]; then + echo "CPI file not found at $file_path. Exiting with status code 1." + exit 1 + else + echo "CPI file found at $file_path." + fi +} + +# Check if the endpoint is accessible +checkCurlSuccess() { + echo "Executing checkCurlSuccess function..." + local response_code + response_code=$(curl -k -s -o /dev/null -w "%{http_code}" -u admin:admin "https://localhost:8888/api/v1/cpi") + if [ "$response_code" -eq 200 ]; then + echo "CURL request successful." + else + echo "CURL request failed with response code: $response_code" + exit 1 + fi +} +check_cpi_exists +checkCurlSuccess + +exit 0 \ No newline at end of file diff --git a/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/start-services.sh b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/start-services.sh new file mode 100755 index 0000000000..66228fa634 --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/start-services.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Navigate to the specified directory +cd /CSDE-cordapp-template-kotlin/ + +# Check if the directory change was successful +if [ $? -eq 0 ]; then + # Run the gradlew command + ./gradlew 3-buildCpis +else + echo "Failed to change directory to /CSDE-cordapp-template-kotlin/" +fi diff --git a/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/supervisord.conf b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/supervisord.conf new file mode 100644 index 0000000000..4d576bd5cb --- /dev/null +++ b/tools/docker/corda-all-in-one/corda-v5/cordapps-deployment/supervisord.conf @@ -0,0 +1,28 @@ +[supervisord] +logfile_maxbytes = 50MB +logfile_backups=10 +loglevel = info + +[inet_http_server] +port = 0.0.0.0:9001 + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[program:startCorda] +directory=/CSDE-cordapp-template-kotlin +command=/bin/bash -c "./gradlew startCorda" +autostart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + +[program:5vbuildCpis] +directory=/ +command=/bin/bash -c "./start-services.sh" +autostart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 9d7b282d75..1a49745291 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10287,6 +10287,7 @@ __metadata: body-parser: "npm:1.20.2" express: "npm:4.19.2" express-openapi-validator: "npm:5.2.0" + form-data: "npm:4.0.0" http-errors-enhanced-cjs: "npm:2.0.1" internal-ip: "npm:6.2.0" joi: "npm:17.13.3"