From d223d8be89ae3bb918b5b4a179d90a069ea3bbf7 Mon Sep 17 00:00:00 2001 From: Elena Izaguirre Date: Tue, 23 Nov 2021 12:45:00 +0100 Subject: [PATCH] refactor(api-server): instantiate plugins in api-server without install them Added parameter action to PluginImport to determine if the plugin should be installed. Enabled feature to instantiate plugins from cactus-cmd-api-server without install it. Enabled feature to install packages from github Added method create in class ConfigService to override old configuration. Method newExampleConfigConvict accepts a boolean parameter to force configuration override. Closes #1210 Signed-off-by: Elena Izaguirre --- .taprc | 2 + jest.config.js | 2 + packages/cactus-cmd-api-server/README.md | 15 +- .../src/main/typescript/api-server.ts | 107 ++++---- .../main/typescript/config/config-service.ts | 47 ++-- .../benchmark/artillery-api-benchmark.test.ts | 3 + .../jwt-endpoint-authorization.test.ts | 3 + .../plugin-import-from-github.test.ts | 81 ++++++ .../plugin-import-without-install.test.ts | 238 ++++++++++++++++++ .../integration/remote-plugin-imports.test.ts | 7 +- ...all-basic-plugin-consortium-manual.test.ts | 3 + ...stall-basic-plugin-keychain-memory.test.ts | 7 +- ...ugin-ledger-connector-fabric-0-7-0.test.ts | 7 +- ...ugin-ledger-connector-quorum-0-7-0.test.ts | 7 +- .../src/main/json/openapi.json | 15 +- .../generated/openapi/typescript-axios/api.ts | 17 ++ .../README.md | 8 +- .../README.md | 8 +- .../README.md | 8 +- .../README.md | 8 +- ...with-npm-install-version-selection.test.ts | 6 +- .../plugin-import-with-npm-install.test.ts | 3 + .../runtime-plugin-imports.test.ts | 6 +- 23 files changed, 515 insertions(+), 93 deletions(-) create mode 100644 packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-from-github.test.ts create mode 100644 packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-without-install.test.ts diff --git a/.taprc b/.taprc index ddd6261804..fbbb8ece34 100644 --- a/.taprc +++ b/.taprc @@ -163,6 +163,8 @@ files: - ./packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-unprotected-endpoint-authz.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-unprotected-endpoint-authz-ops-confirm.test.ts + - ./packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-from-github.test.ts + - ./packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-without-install.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts - ./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts diff --git a/jest.config.js b/jest.config.js index 73f4b7dce2..fb005a8d32 100644 --- a/jest.config.js +++ b/jest.config.js @@ -169,6 +169,8 @@ module.exports = { `./packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-unprotected-endpoint-authz.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-unprotected-endpoint-authz-ops-confirm.test.ts`, + `./packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-from-github.test.ts`, + `./packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-without-install.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts`, `./packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts`, diff --git a/packages/cactus-cmd-api-server/README.md b/packages/cactus-cmd-api-server/README.md index 094d687c6e..41c2e3a76d 100644 --- a/packages/cactus-cmd-api-server/README.md +++ b/packages/cactus-cmd-api-server/README.md @@ -102,7 +102,7 @@ if (require.main === module) { ### Remote Plugin Imports at Runtime Example ```typescript -import { PluginImportType } from "@hyperledger/cactus-core-api"; +import { PluginImportType, PluginImportAction } from "@hyperledger/cactus-core-api"; import { ApiServer } from "@hyperledger/cactus-cmd-api-server"; import { ConfigService } from "@hyperledger/cactus-cmd-api-server"; import { Logger, LoggerProvider } from "@hyperledger/cactus-common"; @@ -131,6 +131,9 @@ const main = async () => { // being imported by the API server regardless of the language the plugin // was written in. type: PluginImportType.REMOTE, + // The INSTALL value means that the plugin will be installed instead of + // only instantiate it + action: PluginImportAction.INSTALL, // The options that will be passed in to the plugin factory options: { keychainId: "_keychainId_", @@ -250,7 +253,7 @@ Once you've built the container, the following commands should work: --publish 4000:4000 \ cas \ ./node_modules/.bin/cactusapi \ - --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": { "connectionProfile": {}, "instanceId": "some-unique-instance-id"}}]' + --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": { "connectionProfile": {}, "instanceId": "some-unique-instance-id"}}]' ``` - Launch container with plugin configuration as an **environment variable**: @@ -259,7 +262,7 @@ Once you've built the container, the following commands should work: --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ cas ``` @@ -271,13 +274,13 @@ Once you've built the container, the following commands should work: --publish 4000:4000 \ cas \ ./node_modules/.bin/cactusapi \ - --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' + --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' ``` - Launch container with **configuration file** mounted from host machine: ```sh - echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' > cactus.json + echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' > cactus.json docker run \ --rm \ @@ -305,7 +308,7 @@ Don't have a Besu network on hand to test with? Test or develop against our Besu --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ cas ``` diff --git a/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts b/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts index 813a1dbfc3..4c0e87f508 100644 --- a/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts +++ b/packages/cactus-cmd-api-server/src/main/typescript/api-server.ts @@ -33,6 +33,7 @@ import { PluginFactoryFactory, PluginImport, Constants, + PluginImportAction, } from "@hyperledger/cactus-core-api"; import { PluginRegistry } from "@hyperledger/cactus-core"; @@ -279,19 +280,26 @@ export class ApiServer { } public async getOrInitPluginRegistry(): Promise { - if (!this.pluginRegistry) { - if (!this.options.pluginRegistry) { - this.log.info(`getOrInitPluginRegistry() initializing a new one...`); - this.pluginRegistry = await this.initPluginRegistry(); - } else { - this.log.info(`getOrInitPluginRegistry() re-using injected one...`); - this.pluginRegistry = this.options.pluginRegistry; + try { + if (!this.pluginRegistry) { + if (!this.options.pluginRegistry) { + this.log.info(`getOrInitPluginRegistry() initializing a new one...`); + this.pluginRegistry = await this.initPluginRegistry(); + } else { + this.log.info(`getOrInitPluginRegistry() re-using injected one...`); + this.pluginRegistry = this.options.pluginRegistry; + } } + await this.prometheusExporter.setTotalPluginImports( + await this.getPluginImportsCount(), + ); + return this.pluginRegistry; + } catch (e) { + this.pluginRegistry = new PluginRegistry({ plugins: [] }); + const errorMessage = `Failed init PluginRegistry: ${e.stack}`; + this.log.error(errorMessage); + throw new Error(errorMessage); } - await this.prometheusExporter.setTotalPluginImports( - await this.getPluginImportsCount(), - ); - return this.pluginRegistry; } public async initPluginRegistry(): Promise { @@ -311,43 +319,44 @@ export class ApiServer { pluginImport: PluginImport, registry: PluginRegistry, ): Promise { + const fnTag = `${this.className}#instantiatePlugin`; const { logLevel } = this.options.config; const { packageName, options } = pluginImport; this.log.info(`Creating plugin from package: ${packageName}`, options); const pluginOptions = { ...options, logLevel, pluginRegistry: registry }; - await this.installPluginPackage(pluginImport); - - const packagePath = path.join( - this.pluginsPath, - options.instanceId, - "node_modules", - packageName, - ); - this.log.debug("Package path: %o", packagePath); - - // eslint-disable-next-line @typescript-eslint/no-var-requires - const pluginPackage = require(/* webpackIgnore: true */ packagePath); - const createPluginFactory = pluginPackage.createPluginFactory as PluginFactoryFactory; - - const pluginFactoryOptions: IPluginFactoryOptions = { - pluginImportType: pluginImport.type, - }; - - const pluginFactory = await createPluginFactory(pluginFactoryOptions); - - const plugin = await pluginFactory.create(pluginOptions); - - // need to invoke the i-cactus-plugin onPluginInit functionality here before plugin registry can be used further try { - await plugin.onPluginInit(); - } catch (error) { - const fnTag = `${this.className}#instantiatePlugin`; - const packageName = plugin.getPackageName(); - const instanceId = plugin.getInstanceId(); + if (pluginImport.action == PluginImportAction.Install) { + await this.installPluginPackage(pluginImport); + } else { + this.log.info( + `The installation of the plugin package ${packageName} was skipped due to the configuration flag action`, + ); + } - const errorMessage = `${fnTag} failed calling onPluginInit() on the plugin '${packageName}' with the instanceId '${instanceId}'`; + const packagePath = path.join( + this.pluginsPath, + options.instanceId, + "node_modules", + packageName, + ); + this.log.debug("Package path: %o", packagePath); + + // eslint-disable-next-line @typescript-eslint/no-var-requires + const pluginPackage = require(/* webpackIgnore: true */ packagePath); + const createPluginFactory = pluginPackage.createPluginFactory as PluginFactoryFactory; + const pluginFactoryOptions: IPluginFactoryOptions = { + pluginImportType: pluginImport.type, + }; + const pluginFactory = await createPluginFactory(pluginFactoryOptions); + const plugin = await pluginFactory.create(pluginOptions); + + // need to invoke the i-cactus-plugin onPluginInit functionality here before plugin registry can be used further + await plugin.onPluginInit(); + return plugin; + } catch (error) { + const errorMessage = `${fnTag} failed instantiating plugin '${packageName}' with the instanceId '${options.instanceId}'`; this.log.error(errorMessage, error); if (error instanceof Error) { @@ -356,15 +365,15 @@ export class ApiServer { throw new RuntimeError(errorMessage, JSON.stringify(error)); } } - - return plugin; } private async installPluginPackage( pluginImport: PluginImport, ): Promise { const fnTag = `ApiServer#installPluginPackage()`; - const { packageName: pkgName } = pluginImport; + const pkgName = pluginImport.options.packageSrc + ? pluginImport.options.packageSrc + : pluginImport.packageName; const instanceId = pluginImport.options.instanceId; const pluginPackageDir = path.join(this.pluginsPath, instanceId); @@ -401,7 +410,14 @@ export class ApiServer { } this.log.info(`Installed ${pkgName} OK`); } catch (ex) { - throw new RuntimeError(`${fnTag} plugin install fail: ${pkgName}`, ex); + const errorMessage = `${fnTag} failed installing plugin '${pkgName}`; + this.log.error(errorMessage, ex); + + if (ex instanceof Error) { + throw new RuntimeError(errorMessage, ex); + } else { + throw new RuntimeError(errorMessage, JSON.stringify(ex)); + } } } @@ -654,9 +670,6 @@ export class ApiServer { this.log.info(`Authorization request handler configured OK.`); } - // const openApiValidator = this.createOpenApiValidator(); - // await openApiValidator.install(app); - this.getOrCreateWebServices(app); // The API server's own endpoints this.log.info(`Starting to install web services...`); diff --git a/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts b/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts index 50b78c4a76..b122e15c16 100644 --- a/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts +++ b/packages/cactus-cmd-api-server/src/main/typescript/config/config-service.ts @@ -15,6 +15,7 @@ import { Constants, PluginImport, PluginImportType, + PluginImportAction, } from "@hyperledger/cactus-core-api"; import { FORMAT_PLUGIN_ARRAY } from "./convict-plugin-array-format"; @@ -468,10 +469,12 @@ export class ConfigService { public newExampleConfigConvict( cactusApiServerOptions?: ICactusApiServerOptions, + overrides?: boolean, ): Config { cactusApiServerOptions = cactusApiServerOptions || this.newExampleConfig(); const env = this.newExampleConfigEnv(cactusApiServerOptions); - return this.getOrCreate({ env }); + const conf = overrides ? this.create({ env }) : this.getOrCreate({ env }); + return conf; } public newExampleConfig(): ICactusApiServerOptions { @@ -532,6 +535,7 @@ export class ConfigService { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidV4(), keychainId: uuidV4(), @@ -540,6 +544,7 @@ export class ConfigService { { packageName: "@hyperledger/cactus-plugin-consortium-manual", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidV4(), keyPairPem, @@ -610,26 +615,34 @@ export class ConfigService { args?: string[]; }): Config { if (!ConfigService.config) { - const schema: Schema = ConfigService.getConfigSchema(); - ConfigService.config = (convict as any)(schema, options); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error - if (ConfigService.config.get("configFile")) { - const configFilePath = ConfigService.config.get("configFile"); - ConfigService.config.loadFile(configFilePath); - } - ConfigService.config.validate(); - this.validateKeyPairMatch(); - const level = ConfigService.config.get("logLevel"); - const logger: Logger = LoggerProvider.getOrCreate({ - label: "config-service", - level, - }); - logger.info("Configuration validation OK."); + this.create(options); } return ConfigService.config; } + create(options?: { + env?: NodeJS.ProcessEnv; + args?: string[]; + }): Config { + const schema: Schema = ConfigService.getConfigSchema(); + ConfigService.config = (convict as any)(schema, options); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + if (ConfigService.config.get("configFile")) { + const configFilePath = ConfigService.config.get("configFile"); + ConfigService.config.loadFile(configFilePath); + } + ConfigService.config.validate(); + this.validateKeyPairMatch(); + const level = ConfigService.config.get("logLevel"); + const logger: Logger = LoggerProvider.getOrCreate({ + label: "config-service", + level, + }); + logger.info("Configuration validation OK."); + return ConfigService.config; + } + /** * Validation that prevents operators from mistakenly deploying a key pair * that they may not be operational for whatever reason. diff --git a/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts index ad1273b04d..d597befa09 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/benchmark/artillery-api-benchmark.test.ts @@ -13,6 +13,7 @@ import { LogLevelDesc, LoggerProvider } from "@hyperledger/cactus-common"; import { PluginImportType, ConsortiumDatabase, + PluginImportAction, } from "@hyperledger/cactus-core-api"; import { @@ -71,6 +72,7 @@ test("Start API server, and run Artillery benchmark test.", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId: uuidv4(), @@ -80,6 +82,7 @@ test("Start API server, and run Artillery benchmark test.", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-consortium-manual", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keyPairPem: keyPairPem, diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts index 8d426b95e6..513cc4da8b 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/integration/jwt-endpoint-authorization.test.ts @@ -14,6 +14,7 @@ import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; import { Configuration, ConsortiumDatabase, + PluginImportAction, PluginImportType, } from "@hyperledger/cactus-core-api"; import { AuthorizationProtocol } from "../../../main/typescript/config/authorization-protocol"; @@ -88,6 +89,7 @@ test(testCase, async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId: uuidv4(), @@ -97,6 +99,7 @@ test(testCase, async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-consortium-manual", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keyPairPem: keyPairPem, diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-from-github.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-from-github.test.ts new file mode 100644 index 0000000000..622494d9ca --- /dev/null +++ b/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-from-github.test.ts @@ -0,0 +1,81 @@ +import path from "path"; +import test, { Test } from "tape-promise/tape"; +import { v4 as uuidv4 } from "uuid"; +import { LogLevelDesc } from "@hyperledger/cactus-common"; +import { + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "../../../main/typescript/public-api"; + +const logLevel: LogLevelDesc = "TRACE"; + +test("can install plugins at runtime with specified version based on imports", async (t: Test) => { + const pluginsPath = path.join( + __dirname, + "../../../../../../", // walk back up to the project root + ".tmp/test/test-cmd-api-server/plugin-import-from-github_test/", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + + const configService = new ConfigService(); + + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = 0; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + apiServerOptions.plugins = [ + { + packageName: "@hyperledger/cactus-dummy-package", + type: PluginImportType.Local, + action: PluginImportAction.Install, + options: { + instanceId: uuidv4(), + keychainId: uuidv4(), + logLevel, + packageSrc: + "https://gitpkg.now.sh/hyperledger/cactus/packages/cactus-cmd-api-server/src/test/resources/cactus-dummy-package?main", + }, + }, + ]; + const config = configService.newExampleConfigConvict(apiServerOptions); + + const apiServer = new ApiServer({ + config: config.getProperties(), + }); + + const startResponse = apiServer.start(); + await t.doesNotReject( + startResponse, + "failed to start API server with dynamic plugin imports configured for it...", + ); + t.ok(startResponse, "startResponse truthy OK"); + + const packageFilePath = path.join( + pluginsPath, + apiServerOptions.plugins[0].options.instanceId, + "node_modules", + `${apiServerOptions.plugins[0].packageName}`, + "package.json", + ); + const { name, version } = await import(packageFilePath); + t.comment(name); + t.comment(version); + t.strictEquals( + name, + apiServerOptions.plugins[0].packageName, + `Package name strictly equal to ${apiServerOptions.plugins[0].packageName}`, + ); + + test.onFinish(() => apiServer.shutdown()); +}); diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-without-install.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-without-install.test.ts new file mode 100644 index 0000000000..83ddb93cf5 --- /dev/null +++ b/packages/cactus-cmd-api-server/src/test/typescript/integration/plugin-import-without-install.test.ts @@ -0,0 +1,238 @@ +import path from "path"; +import test, { Test } from "tape-promise/tape"; +import { v4 as uuidv4 } from "uuid"; +import { LogLevelDesc } from "@hyperledger/cactus-common"; +import { + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; +import { + ApiServer, + AuthorizationProtocol, + ConfigService, +} from "../../../main/typescript/public-api"; +import lmify from "lmify"; +import fs from "fs-extra"; + +const logLevel: LogLevelDesc = "TRACE"; + +test("can instantiate plugins at runtime without install them", async (t: Test) => { + test("if plugin is not already installed and we set action to instantiate, server starting will fail", async (t2: Test) => { + const pluginsPath = path.join( + __dirname, + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/plugin-import-without-install/", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + + const configService = new ConfigService(); + + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = 0; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + + const instanceId = uuidv4(); + const keychainId = uuidv4(); + const plugin = { + packageName: "@hyperledger/cactus-plugin-keychain-memory", + type: PluginImportType.Local, + action: PluginImportAction.Instantiate, + options: { + instanceId, + keychainId, + logLevel, + version: "0.9.0", + }, + }; + + apiServerOptions.plugins = [plugin]; + + const config = configService.newExampleConfigConvict(apiServerOptions); + + const apiServer = new ApiServer({ + config: config.getProperties(), + }); + + await t2.rejects(apiServer.start()); + + t2.end(); + }); + + test("if plugin is already installed and we send a different version, it keeps using plugin installed before call apiServer", async (t2: Test) => { + const pluginsPath = path.join( + __dirname, + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/plugin-import-without-install/", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + + const configService = new ConfigService(); + + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = 0; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + + const versionToSendServer = "0.7.0"; + const instanceId = uuidv4(); + const keychainId = uuidv4(); + const plugin = { + packageName: "@hyperledger/cactus-plugin-keychain-memory", + type: PluginImportType.Local, + action: PluginImportAction.Instantiate, + options: { + instanceId, + keychainId, + logLevel, + version: versionToSendServer, + }, + }; + apiServerOptions.plugins = [plugin]; + + const pluginPackageDir = path.join(pluginsPath, instanceId); + const versionToInstall = "0.10.0"; + + await fs.mkdirp(pluginPackageDir); + lmify.setPackageManager("npm"); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error + lmify.setRootDir(pluginPackageDir); + const out = await lmify.install([ + `${plugin.packageName}@${versionToInstall}`, + "--production", + "--audit=false", + "--progress=false", + "--fund=false", + `--prefix=${pluginPackageDir}`, + // "--ignore-workspace-root-check", + ]); + t2.equal(out.exitCode, 0, "Plugin installed correctly"); + + const config = configService.newExampleConfigConvict( + apiServerOptions, + true, + ); + const apiServer = new ApiServer({ + config: config.getProperties(), + }); + + await t2.doesNotReject( + apiServer.start(), + "apiServer was starting instantiating a plugin previously installed", + ); + + const packageFilePath = path.join( + pluginsPath, + plugin.options.instanceId, + "node_modules", + `${plugin.packageName}`, + "package.json", + ); + + const { version } = await import(packageFilePath); + + t2.strictEquals( + version, + versionToInstall, + "apiServer did not overwrite package", + ); + + const pluginsCount = apiServer.getPluginImportsCount(); + t2.equal(pluginsCount, 1, "apiServer instantiated 1 plugin"); + + await t2.doesNotReject( + apiServer.shutdown(), + "apiServer was stopped instantiating a plugin previously installed", + ); + + t2.end(); + }); + + test("if we send action as Installation, apiServer will install the plugin", async (t2: Test) => { + const pluginsPath = path.join( + __dirname, + "../../../../../../", // walk back up to the project root + ".tmp/test/cmd-api-server/plugin-import-without-install/", // the dir path from the root + uuidv4(), // then a random directory to ensure proper isolation + ); + const pluginManagerOptionsJson = JSON.stringify({ pluginsPath }); + + const configService = new ConfigService(); + + const apiServerOptions = configService.newExampleConfig(); + apiServerOptions.pluginManagerOptionsJson = pluginManagerOptionsJson; + apiServerOptions.authorizationProtocol = AuthorizationProtocol.NONE; + apiServerOptions.configFile = ""; + apiServerOptions.apiCorsDomainCsv = "*"; + apiServerOptions.apiPort = 0; + apiServerOptions.cockpitPort = 0; + apiServerOptions.grpcPort = 0; + apiServerOptions.apiTlsEnabled = false; + const versionToInstall = "0.8.0"; + apiServerOptions.plugins = [ + { + packageName: "@hyperledger/cactus-plugin-keychain-memory", + type: PluginImportType.Local, + action: PluginImportAction.Install, + options: { + instanceId: uuidv4(), + keychainId: uuidv4(), + logLevel, + version: versionToInstall, + }, + }, + ]; + + const config = configService.newExampleConfigConvict( + apiServerOptions, + true, + ); + + const apiServer = new ApiServer({ + config: config.getProperties(), + }); + + await t2.doesNotReject( + apiServer.start(), + "apiServer was starting instantiating a plugin previously installed", + ); + + const packageFilePath = path.join( + pluginsPath, + apiServerOptions.plugins[0].options.instanceId, + "node_modules", + `${apiServerOptions.plugins[0].packageName}`, + "package.json", + ); + + const { version } = await import(packageFilePath); + + t2.strictEquals( + version, + versionToInstall, + "apiServer installed the package", + ); + + const pluginsCount = apiServer.getPluginImportsCount(); + t2.equal(pluginsCount, 1, "apiServer instantiated 1 plugin"); + + await t2.doesNotReject(apiServer.shutdown(), "apiServer was stopped"); + + t2.end(); + }); + + t.end(); +}); diff --git a/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts index 8cf1d41ee2..6fab98a086 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/integration/remote-plugin-imports.test.ts @@ -16,7 +16,11 @@ import { } from "@hyperledger/cactus-test-tooling"; import { DefaultApi } from "@hyperledger/cactus-plugin-keychain-vault"; -import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import { + Configuration, + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; import path from "path"; test("NodeJS API server + Rust plugin work together", async (t: Test) => { @@ -80,6 +84,7 @@ test("NodeJS API server + Rust plugin work together", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-vault", type: PluginImportType.Remote, + action: PluginImportAction.Install, options: { keychainId: "_keychainId_", instanceId: "_instanceId_", 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 e446d691b9..268fe4739b 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 @@ -11,6 +11,7 @@ import { ICactusPlugin, Configuration, IPluginConsortium, + PluginImportAction, } from "@hyperledger/cactus-core-api"; import { @@ -65,6 +66,7 @@ test("can install plugin-consortium-manual", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId, @@ -74,6 +76,7 @@ test("can install plugin-consortium-manual", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-consortium-manual", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: consortiumPluginInstanceId, keyPairPem: keyPairPem, diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts index 9eae7e6a1c..ffe942bae1 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-keychain-memory.test.ts @@ -3,7 +3,11 @@ import { v4 as uuidv4 } from "uuid"; import { LogLevelDesc } from "@hyperledger/cactus-common"; -import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import { + Configuration, + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; import { ApiServer, @@ -45,6 +49,7 @@ test("can import plugins at runtime (CLI)", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId: uuidv4(), diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts index 5e0539d7a8..3dd45a1040 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-fabric-0-7-0.test.ts @@ -3,7 +3,11 @@ import { v4 as uuidv4 } from "uuid"; import { LogLevelDesc } from "@hyperledger/cactus-common"; -import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import { + Configuration, + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; import { ApiServer, @@ -43,6 +47,7 @@ test("can install plugin-ledger-connector-fabric", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-ledger-connector-fabric", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), logLevel, diff --git a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts index b1ff528465..5de6ac8900 100644 --- a/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts +++ b/packages/cactus-cmd-api-server/src/test/typescript/unit/plugins/install-basic-plugin-ledger-connector-quorum-0-7-0.test.ts @@ -4,7 +4,11 @@ import { v4 as uuidv4 } from "uuid"; import { LogLevelDesc } from "@hyperledger/cactus-common"; -import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import { + Configuration, + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; import { ApiServer, @@ -48,6 +52,7 @@ test("can import plugins at runtime (CLI)", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-ledger-connector-quorum", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), logLevel, diff --git a/packages/cactus-core-api/src/main/json/openapi.json b/packages/cactus-core-api/src/main/json/openapi.json index 6fc322df19..c10ff89dad 100644 --- a/packages/cactus-core-api/src/main/json/openapi.json +++ b/packages/cactus-core-api/src/main/json/openapi.json @@ -24,7 +24,8 @@ "type": "object", "required": [ "packageName", - "type" + "type", + "action" ], "properties": { "packageName": { @@ -38,6 +39,11 @@ "description": "", "$ref": "#/components/schemas/PluginImportType" }, + "action": { + "nullable": false, + "description": "", + "$ref": "#/components/schemas/PluginImportAction" + }, "options": {} } }, @@ -48,6 +54,13 @@ "org.hyperledger.cactus.plugin_import_type.REMOTE" ] }, + "PluginImportAction": { + "type": "string", + "enum": [ + "org.hyperledger.cactus.plugin_import_action.INSTANTIATE", + "org.hyperledger.cactus.plugin_import_action.INSTALL" + ] + }, "ConsensusAlgorithmFamily": { "type": "string", "description": "Enumerates a list of consensus algorithm families in existence. Does not intend to be an exhaustive list, just a practical one, meaning that we only include items here that are relevant to Hyperledger Cactus in fulfilling its own duties. This can be extended later as more sophisticated features of Cactus get implemented. This enum is meant to be first and foremost a useful abstraction for achieving practical tasks, not an encyclopedia and therefore we ask of everyone that this to be extended only in ways that serve a practical purpose for the runtime behavior of Cactus or Cactus plugins in general. The bottom line is that we can accept this enum being not 100% accurate as long as it 100% satisfies what it was designed to do.", diff --git a/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts index f8e82dc6cc..b9a0957d35 100644 --- a/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts +++ b/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -532,6 +532,12 @@ export interface PluginImport { * @memberof PluginImport */ type: PluginImportType; + /** + * + * @type {PluginImportAction} + * @memberof PluginImport + */ + action: PluginImportAction; /** * * @type {any} @@ -539,6 +545,17 @@ export interface PluginImport { */ options?: any | null; } +/** + * + * @export + * @enum {string} + */ + +export enum PluginImportAction { + Instantiate = 'org.hyperledger.cactus.plugin_import_action.INSTANTIATE', + Install = 'org.hyperledger.cactus.plugin_import_action.INSTALL' +} + /** * * @export diff --git a/packages/cactus-plugin-ledger-connector-besu/README.md b/packages/cactus-plugin-ledger-connector-besu/README.md index 1a2f7885df..0084b404d1 100644 --- a/packages/cactus-plugin-ledger-connector-besu/README.md +++ b/packages/cactus-plugin-ledger-connector-besu/README.md @@ -149,7 +149,7 @@ docker run \ --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ cplcb ``` @@ -161,13 +161,13 @@ docker run \ --publish 4000:4000 \ cplcb \ ./node_modules/.bin/cactusapi \ - --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' + --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' ``` Launch container with **configuration file** mounted from host machine: ```sh -echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' > cactus.json +echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' > cactus.json docker run \ --rm \ @@ -195,7 +195,7 @@ docker run \ --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}]' \ cplcb ``` diff --git a/packages/cactus-plugin-ledger-connector-fabric/README.md b/packages/cactus-plugin-ledger-connector-fabric/README.md index 0be54a011c..b3404c2969 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/README.md +++ b/packages/cactus-plugin-ledger-connector-fabric/README.md @@ -262,7 +262,7 @@ docker run \ --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { "CORE_PEER_LOCALMSPID": "Org1MSP", "CORE_PEER_ADDRESS": "peer0.org1.example.com:7051", "CORE_PEER_MSPCONFIGPATH": @@ -288,7 +288,7 @@ docker run \ --publish 4000:4000 \ cplcb \ ./node_modules/.bin/cactusapi \ - --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { "CORE_PEER_LOCALMSPID": "Org1MSP", "CORE_PEER_ADDRESS": "peer0.org1.example.com:7051", "CORE_PEER_MSPCONFIGPATH": @@ -308,7 +308,7 @@ docker run \ Launch container with **configuration file** mounted from host machine: ```sh -echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { +echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { "CORE_PEER_LOCALMSPID": "Org1MSP", "CORE_PEER_ADDRESS": "peer0.org1.example.com:7051", "CORE_PEER_MSPCONFIGPATH": @@ -350,7 +350,7 @@ docker run \ --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { "CORE_PEER_LOCALMSPID": "Org1MSP", "CORE_PEER_ADDRESS": "peer0.org1.example.com:7051", "CORE_PEER_MSPCONFIGPATH": diff --git a/packages/cactus-plugin-ledger-connector-iroha/README.md b/packages/cactus-plugin-ledger-connector-iroha/README.md index c7ed49ad7d..e168c46e42 100644 --- a/packages/cactus-plugin-ledger-connector-iroha/README.md +++ b/packages/cactus-plugin-ledger-connector-iroha/README.md @@ -126,7 +126,7 @@ docker run \ --publish 3000:3000 \ --publish 4000:4000 \ --publish 5000:5000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' \ cplcb ``` @@ -139,13 +139,13 @@ docker run \ --publish 5000:5000 \ cplcb \ ./node_modules/.bin/cactusapi \ - --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' + --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' ``` Launch container with **configuration file** mounted from host machine: ```sh -echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' > cactus.json +echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' > cactus.json docker run \ --rm \ @@ -175,7 +175,7 @@ docker run \ --publish 3000:3000 \ --publish 4000:4000 \ --publish 5000:5000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-iroha", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-iroha-connector-instance-id"}}]' \ cplcb ``` diff --git a/packages/cactus-plugin-ledger-connector-quorum/README.md b/packages/cactus-plugin-ledger-connector-quorum/README.md index c54966fdcd..bce6236eed 100644 --- a/packages/cactus-plugin-ledger-connector-quorum/README.md +++ b/packages/cactus-plugin-ledger-connector-quorum/README.md @@ -108,7 +108,7 @@ docker run \ --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' \ cplcb ``` @@ -120,13 +120,13 @@ docker run \ --publish 4000:4000 \ cplcb \ ./node_modules/.bin/cactusapi \ - --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' + --plugins='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' ``` Launch container with **configuration file** mounted from host machine: ```sh -echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' > cactus.json +echo '[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' > cactus.json docker run \ --rm \ @@ -154,7 +154,7 @@ docker run \ --rm \ --publish 3000:3000 \ --publish 4000:4000 \ - --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' \ + --env PLUGINS='[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}]' \ cplcb ``` diff --git a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install-version-selection.test.ts b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install-version-selection.test.ts index 05fd4b9a8f..db2d7bbe32 100644 --- a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install-version-selection.test.ts +++ b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install-version-selection.test.ts @@ -2,7 +2,10 @@ import path from "path"; import test, { Test } from "tape-promise/tape"; import { v4 as uuidv4 } from "uuid"; import { LogLevelDesc } from "@hyperledger/cactus-common"; -import { PluginImportType } from "@hyperledger/cactus-core-api"; +import { + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; import { ApiServer, AuthorizationProtocol, @@ -35,6 +38,7 @@ test("can install plugins at runtime with specified version based on imports", a { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId: uuidv4(), diff --git a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts index 3c22eac030..ea8882ba96 100644 --- a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts +++ b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/plugin-import-with-npm-install.test.ts @@ -8,6 +8,7 @@ import { LogLevelDesc } from "@hyperledger/cactus-common"; import { PluginImportType, ConsortiumDatabase, + PluginImportAction, } from "@hyperledger/cactus-core-api"; import { @@ -53,6 +54,7 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId: uuidv4(), @@ -62,6 +64,7 @@ test("can instal plugins at runtime based on imports", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-consortium-manual", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keyPairPem: keyPairPem, diff --git a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts index 7c6e075ec3..9e6b439c99 100644 --- a/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts +++ b/packages/cactus-test-cmd-api-server/src/test/typescript/integration/runtime-plugin-imports.test.ts @@ -9,7 +9,10 @@ import { AuthorizationProtocol, ConfigService, } from "@hyperledger/cactus-cmd-api-server"; -import { PluginImportType } from "@hyperledger/cactus-core-api"; +import { + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; const logLevel: LogLevelDesc = "TRACE"; @@ -36,6 +39,7 @@ test("can import plugins at runtime (CLI)", async (t: Test) => { { packageName: "@hyperledger/cactus-plugin-keychain-memory", type: PluginImportType.Local, + action: PluginImportAction.Install, options: { instanceId: uuidv4(), keychainId: uuidv4(),