diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2247f1ec2f..c87fe81525 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -437,7 +437,7 @@ jobs: JEST_TEST_COVERAGE_PATH: ./code-coverage-ts/cactus-cmd-api-server JEST_TEST_CODE_COVERAGE_ENABLED: true TAPE_TEST_PATTERN: >- - --files={./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/certificates-work-for-mutual-tls.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/generates-working-certificates.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-js-proto-loader-client-healthcheck.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-proto-gen-ts-client-healthcheck.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-proto-gen-ts-client-m-tls-enabled.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts} + --files={./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/certificates-work-for-mutual-tls.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/generates-working-certificates.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-js-proto-loader-client-healthcheck.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-proto-gen-ts-client-healthcheck.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-proto-gen-ts-client-m-tls-enabled.test.ts,./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts} TAPE_TEST_RUNNER_DISABLED: false runs-on: ubuntu-22.04 steps: diff --git a/.taprc b/.taprc index 9960759de4..21648be886 100644 --- a/.taprc +++ b/.taprc @@ -47,7 +47,6 @@ files: - ./packages/cactus-test-plugin-htlc-eth-besu/src/test/typescript/integration/plugin-htlc-eth-besu/get-single-status-endpoint.test.ts - ./packages/cactus-test-plugin-htlc-eth-besu/src/test/typescript/integration/plugin-htlc-eth-besu/openapi/openapi-validation.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts - - ./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/generates-working-certificates.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/certificates-work-for-mutual-tls.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-proto-gen-ts-client-healthcheck.test.ts diff --git a/jest.config.js b/jest.config.js index afd33edea9..4639041b3d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -60,7 +60,6 @@ module.exports = { `./packages/cactus-test-plugin-htlc-eth-besu/src/test/typescript/integration/plugin-htlc-eth-besu/get--status-endpoint-invalid.test.ts`, `./packages/cactus-test-plugin-htlc-eth-besu/src/test/typescript/integration/plugin-htlc-eth-besu/openapi/openapi-validation.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts`, - `./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/generates-working-certificates.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/config/self-signed-certificate-generator/certificates-work-for-mutual-tls.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/grpc-proto-gen-ts-client-healthcheck.test.ts`, diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts index 0bca605609..c8c555fa6e 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-consortium-manual.test.ts @@ -1,199 +1,200 @@ -import path from "path"; -import test, { Test } from "tape-promise/tape"; -import { v4 as uuidv4 } from "uuid"; +import { randomUUID as uuidv4 } from "node:crypto"; +import path from "node:path"; + +import "jest-extended"; import { generateKeyPair, exportPKCS8 } from "jose"; +import { StatusCodes } from "http-status-codes"; import { LogLevelDesc } from "@hyperledger/cactus-common"; - import { - PluginImportType, ConsortiumDatabase, ICactusPlugin, - Configuration, IPluginConsortium, + PluginImport, PluginImportAction, + PluginImportType, } from "@hyperledger/cactus-core-api"; -import { - ApiServer, - AuthorizationProtocol, - ConfigService, -} from "../../../../main/typescript/public-api"; - +import { ApiServer } from "../../../../main/typescript/api-server"; import { K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS } from "../../../../main/typescript/prometheus-exporter/metrics"; +import { DefaultApi as ApiServerApi } from "../../../../main/typescript/generated/openapi/typescript-axios/api"; +import { ConfigService } from "../../../../main/typescript/config/config-service"; +import { AuthorizationProtocol } from "../../../../main/typescript/config/authorization-protocol"; +import { Configuration } from "../../../../main/typescript/generated/openapi/typescript-axios"; -import { DefaultApi as ApiServerApi } from "../../../../main/typescript/public-api"; - -const logLevel: LogLevelDesc = "TRACE"; - -test("can install plugin-consortium-manual", async (t: Test) => { +describe("ApiServer", () => { + const logLevel: LogLevelDesc = "INFO"; const keychainId = uuidv4(); const consortiumPluginInstanceId = uuidv4(); - // Adding a new plugin to update the prometheus metric K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS - const keyPair = await await generateKeyPair("ES256K"); - const keyPairPem = await exportPKCS8(keyPair.privateKey); - const db: ConsortiumDatabase = { - cactusNode: [], - consortium: [], - consortiumMember: [], - ledger: [], - pluginInstance: [], - }; - const pluginsPath = path.join( __dirname, // start at the current file's path "../../../../../../../", // walk back up to the project root - ".tmp/test/cmd-api-server/plugin-import-with-npm-install_test", // the dir path from the root + ".tmp/test/cmd-api-server/install-basic-plugin-consortium-manual_test", // the dir path from the root uuidv4(), // then a random directory to ensure proper isolation ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + + let pluginImports: PluginImport[]; + const configService = new ConfigService(); - const apiServerOptions = await configService.newExampleConfig(); - const pluginManagerOptions = { pluginsPath }; - const pluginManagerOptionsJson = JSON.stringify(pluginManagerOptions); - - apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; - apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; - apiServerOptions.configFile = ""; - apiServerOptions.apiCorsDomainCsv = "*"; - apiServerOptions.apiPort = 0; - apiServerOptions.cockpitPort = 0; - apiServerOptions.grpcPort = 0; - apiServerOptions.crpcPort = 0; - apiServerOptions.apiTlsEnabled = false; - apiServerOptions.plugins = [ - { - packageName: "@hyperledger/cactus-plugin-keychain-memory", - type: PluginImportType.Local, - action: PluginImportAction.Install, - options: { - instanceId: uuidv4(), - keychainId, - logLevel, + let apiServer: ApiServer; + let apiClient: ApiServerApi; + + beforeAll(async () => { + // Adding a new plugin to update the prometheus metric K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + const keyPair = await await generateKeyPair("ES256K"); + const keyPairPem = await exportPKCS8(keyPair.privateKey); + const db: ConsortiumDatabase = { + cactusNode: [], + consortium: [], + consortiumMember: [], + ledger: [], + pluginInstance: [], + }; + + pluginImports = [ + { + packageName: "@hyperledger/cactus-plugin-keychain-memory", + type: PluginImportType.Local, + action: PluginImportAction.Install, + options: { + instanceId: uuidv4(), + keychainId, + logLevel, + }, }, - }, - { - packageName: "@hyperledger/cactus-plugin-consortium-manual", - type: PluginImportType.Local, - action: PluginImportAction.Install, - options: { - instanceId: consortiumPluginInstanceId, - keyPairPem: keyPairPem, - consortiumDatabase: db, + { + packageName: "@hyperledger/cactus-plugin-consortium-manual", + type: PluginImportType.Local, + action: PluginImportAction.Install, + options: { + instanceId: consortiumPluginInstanceId, + keyPairPem: keyPairPem, + consortiumDatabase: db, + }, }, - }, - ]; - const config = await configService.newExampleConfigConvict(apiServerOptions); - - const apiServer = new ApiServer({ - config: config.getProperties(), + ]; + + const apiSrvOpts = await configService.newExampleConfig(); + apiSrvOpts.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiSrvOpts.authorizationProtocol = AuthorizationProtocol.NONE; + apiSrvOpts.logLevel = logLevel; + apiSrvOpts.configFile = ""; + apiSrvOpts.apiCorsDomainCsv = "*"; + apiSrvOpts.apiPort = 0; + apiSrvOpts.cockpitPort = 0; + apiSrvOpts.grpcPort = 0; + apiSrvOpts.crpcPort = 0; + apiSrvOpts.apiTlsEnabled = false; + apiSrvOpts.plugins = pluginImports; + const config = await configService.newExampleConfigConvict(apiSrvOpts); + + apiServer = new ApiServer({ + config: config.getProperties(), + }); + + const startResponse = apiServer.start(); + await expect(startResponse).toResolve(); + + const addressInfoApi = (await startResponse).addressInfoApi; + const protocol = apiSrvOpts.apiTlsEnabled ? "https" : "http"; + const { address, port } = addressInfoApi; + const apiHost = `${protocol}://${address}:${port}`; + + const apiConfig = new Configuration({ basePath: apiHost }); + apiClient = new ApiServerApi(apiConfig); }); - test.onFinish(() => apiServer.shutdown()); - - const startResponse = apiServer.start(); - await t.doesNotReject(startResponse, "started API server OK"); - t.ok(startResponse, "startResponse truthy OK"); + afterAll(async () => { + await apiServer.shutdown(); + }); - const addressInfoApi = (await startResponse).addressInfoApi; - const protocol = apiServerOptions.apiTlsEnabled ? "https" : "http"; - const { address, port } = addressInfoApi; - const apiHost = `${protocol}://${address}:${port}`; - t.comment( - `Metrics URL: ${apiHost}/api/v1/api-server/get-prometheus-exporter-metrics`, - ); + it("can install plugin-consortium-manual", async () => { + { + const res = await apiClient.getPrometheusMetricsV1(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " Total number of plugins imported\n" + + "# TYPE " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " gauge\n" + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '{type="' + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '"} 2'; + + expect(res).toMatchObject({ + status: StatusCodes.OK, + data: expect.stringContaining(promMetricsOutput), + }); + } + + const pluginRegistry = await apiServer.getOrInitPluginRegistry(); + + // this is not a working plugin but we are just testing the monitoring so + // it's okay for this particular test case. Do not copy this to other test + // cases or if you do remove right after you copied it ;-) + pluginRegistry.plugins.push({} as ICactusPlugin); - const apiConfig = new Configuration({ basePath: apiHost }); - const apiClient = new ApiServerApi(apiConfig); - - { - const res = await apiClient.getPrometheusMetricsV1(); - const promMetricsOutput = - "# HELP " + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - " Total number of plugins imported\n" + - "# TYPE " + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - " gauge\n" + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - '{type="' + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - '"} 2'; - t.ok(res); - t.ok(res.data); - t.equal(res.status, 200); - t.true( - res.data.includes(promMetricsOutput), - "Total 2 plugins imported as expected. RESULT OK", - ); - } - - const pluginRegistry = await apiServer.getOrInitPluginRegistry(); - - // this is not a working plugin but we are just testing the monitoring so - // it's okay for this particular test case. Do not copy this to other test - // cases or if you do remove right after you copied it ;-) - pluginRegistry.plugins.push({} as ICactusPlugin); - - { - const res = await apiClient.getPrometheusMetricsV1(); - const promMetricsOutput = - "# HELP " + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - " Total number of plugins imported\n" + - "# TYPE " + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - " gauge\n" + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - '{type="' + - K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + - '"} 3'; - t.ok(res); - t.ok(res.data); - t.equal(res.status, 200); - t.true( - res.data.includes(promMetricsOutput), - "Total 3 plugins imported as expected. RESULT OK", - ); - } - // clean up after ourselves, - // e.g. remove the dummy plugin instance we just pushed - pluginRegistry.plugins.pop(); - - const keychain = pluginRegistry.findOneByKeychainId(keychainId); - - const hasX1 = await keychain.has("x"); - t.false(hasX1, "hasX1 === false OK"); - - await keychain.set("x", "y"); - - const hasX2 = await keychain.has("x"); - t.true(hasX2, "hasX2 === true OK"); - - type DummyConsortiumPlugin = IPluginConsortium< - unknown, - unknown, - unknown, - unknown - >; - - // TODO - use the new getOneById implementation once - // https://github.com/hyperledger/cactus/issues/1197 - // has been resolved - const consortiumPlugin = pluginRegistry - .getPlugins() - .find( - (it) => it.getInstanceId() === consortiumPluginInstanceId, - ) as DummyConsortiumPlugin; - - t.ok(consortiumPlugin, "consortiumPlugin located via instance ID truthy OK"); - - // FIXME - uncomment this once https://github.com/hyperledger/cactus/issues/1199 - // has been resolved (and also published to npm) - // const nodeJwsRes = await consortiumPlugin.getNodeJws({}); - // t.ok(nodeJwsRes, "nodeJwsRes truthy OK"); - - t.end(); + { + const res = await apiClient.getPrometheusMetricsV1(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " Total number of plugins imported\n" + + "# TYPE " + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + " gauge\n" + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '{type="' + + K_CACTUS_API_SERVER_TOTAL_PLUGIN_IMPORTS + + '"} 3'; + + expect(res).toMatchObject({ + status: StatusCodes.OK, + data: expect.stringContaining(promMetricsOutput), + }); + } + // clean up after ourselves, + // e.g. remove the dummy plugin instance we just pushed + pluginRegistry.plugins.pop(); + + const keychain = pluginRegistry.findOneByKeychainId(keychainId); + + const hasX1 = await keychain.has("x"); + expect(hasX1).toBeFalse(); + + await keychain.set("x", "y"); + + const hasX2 = await keychain.has("x"); + expect(hasX2).toBeTrue(); + + type DummyConsortiumPlugin = IPluginConsortium< + unknown, + unknown, + unknown, + unknown + >; + + // TODO - use the new getOneById implementation once + // https://github.com/hyperledger/cactus/issues/1197 + // has been resolved + const consortiumPlugin = pluginRegistry + .getPlugins() + .find( + (it) => it.getInstanceId() === consortiumPluginInstanceId, + ) as DummyConsortiumPlugin; + + expect(consortiumPlugin).toBeTruthy(); + expect(consortiumPlugin).toBeObject(); + + // FIXME - uncomment this once https://github.com/hyperledger/cactus/issues/1199 + // has been resolved (and also published to npm) + // const nodeJwsRes = await consortiumPlugin.getNodeJws({}); + // t.ok(nodeJwsRes, "nodeJwsRes truthy OK"); + }); });