From 3f8da407a1495662704241ea38f52ee6746d099a Mon Sep 17 00:00:00 2001 From: Jagpreet Singh Sasan Date: Thu, 11 Mar 2021 11:39:53 +0530 Subject: [PATCH] feat(keychain-memory): add prometheus exporter Primary Change -------------- 1. The keychain-memory plugin now includes the prometheus metrics exporter integration 2. OpenAPI spec now has api endpoint for the getting the prometheus metrics Refactorings that were also necessary to accomodate 1) and 2) ------------------------------------------------------------ 3. GetPrometheusMetricsV1 class is created to handle the corresponding api endpoint 4. IPluginKeychainMemoryOptions interface in PluginKeychainMemory class now has a prometheusExporter optional field 5. The PluginKeychainMemory class has relevant functions and codes to incorporate prometheus exporter 6. deploy-contract-from-json.test.ts is changed to incorporate the prometheus exporter 7. Added Readme.md on the prometheus exporter usage Fixes #537 Signed-off-by: Jagpreet Singh Sasan --- .../cactus-plugin-keychain-memory/README.md | 40 +- .../package-lock.json | 476 +++++++++++++++ .../package.json | 12 +- .../src/main/json/openapi.json | 573 ++++++++++++++++++ .../openapi/typescript-axios/.gitignore | 4 + .../.openapi-generator-ignore | 27 + .../typescript-axios/.openapi-generator/FILES | 4 + .../.openapi-generator/VERSION | 1 + .../generated/openapi/typescript-axios/api.ts | 539 ++++++++++++++++ .../openapi/typescript-axios/base.ts | 71 +++ .../openapi/typescript-axios/configuration.ts | 76 +++ .../openapi/typescript-axios/index.ts | 18 + ...prometheus-exporter-metrics-endpoint-v1.ts | 81 +++ .../main/typescript/plugin-keychain-memory.ts | 54 ++ .../prometheus-exporter/data-fetcher.ts | 9 + .../typescript/prometheus-exporter/metrics.ts | 7 + .../prometheus-exporter.ts | 41 ++ .../prometheus-exporter/response.type.ts | 3 + .../src/main/typescript/public-api.ts | 1 + .../unit/plugin-keychain-memory.test.ts | 43 ++ 20 files changed, 2075 insertions(+), 5 deletions(-) create mode 100644 packages/cactus-plugin-keychain-memory/src/main/json/openapi.json create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.gitignore create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts create mode 100644 packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts diff --git a/packages/cactus-plugin-keychain-memory/README.md b/packages/cactus-plugin-keychain-memory/README.md index fa4a2c57af8..a7263de4002 100644 --- a/packages/cactus-plugin-keychain-memory/README.md +++ b/packages/cactus-plugin-keychain-memory/README.md @@ -1,9 +1,41 @@ # `@hyperledger/cactus-plugin-keychain-memory` -> TODO: description +## Prometheus Exporter -## Usage +This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Keychain memory plugin. + +### Usage +The prometheus exporter object is initialized in the `PluginKeychainMemory` class constructor itself, so instantiating the object of the `PluginKeychainMemory` class, gives access to the exporter object. +You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginKeychainMemoryOptions` interface for `PluginKeychainMemory` constructor. + +`getPrometheusExporterMetricsV1` function returns the prometheus exporter metrics, currently displaying the total key count, which currently increments everytime the `set()` and `delete()` method of the `PluginKeychainMemory` class is called. + +### Prometheus Integration +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). +Once Prometheus is setup, the corresponding scrape_config needs to be added to the prometheus.yml + +```(yaml) +- job_name: 'keychain_memory_exporter' + metrics_path: api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics + scrape_interval: 5s + static_configs: + - targets: ['{host}:{port}'] ``` -// TODO: DEMONSTRATE API -``` + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) +`Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-keychain-plugin/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. +On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus_keychain_memory_total_key_count** and click **execute** + +### Helper code + +###### response.type.ts +This file contains the various responses of the metrics. + +###### data-fetcher.ts +This file contains functions encasing the logic to process the data points + +###### metrics.ts +This file lists all the prometheus metrics and what they are used for. diff --git a/packages/cactus-plugin-keychain-memory/package-lock.json b/packages/cactus-plugin-keychain-memory/package-lock.json index b9dc24ea1c1..61c6c2eda68 100644 --- a/packages/cactus-plugin-keychain-memory/package-lock.json +++ b/packages/cactus-plugin-keychain-memory/package-lock.json @@ -4,23 +4,305 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", + "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz", + "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "@types/joi": { "version": "14.3.4", "resolved": "https://registry.npmjs.org/@types/joi/-/joi-14.3.4.tgz", "integrity": "sha512-1TQNDJvIKlgYXGNIABfgFp9y0FziDpuGrd799Q5RcnsDu+krD+eeW/0Fs5PHARvWWFelOhIG2OPCo6KbadBM4A==", "dev": true }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "@types/node": { + "version": "14.14.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==", + "dev": true + }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", + "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/uuid": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz", "integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ==", "dev": true }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "bintrees": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", + "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "follow-redirects": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "hoek": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, "isemail": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", @@ -39,11 +321,181 @@ "topo": "3.x.x" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" + }, + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "requires": { + "mime-db": "1.46.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "prom-client": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.1.0.tgz", + "integrity": "sha512-jT9VccZCWrJWXdyEtQddCDszYsiuWj5T0ekrPszi/WEegj3IZy6Mm09iOOVM86A4IKMWq8hZkT2dD9MaSe+sng==", + "requires": { + "tdigest": "^0.1.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "tdigest": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", + "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "requires": { + "bintrees": "1.0.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "topo": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", @@ -52,15 +504,39 @@ "hoek": "6.x.x" } }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, "typescript-optional": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/typescript-optional/-/typescript-optional-2.0.1.tgz", "integrity": "sha512-xuwmqsCjE4OeeMKxbNX3jjNcISGzYh5Q9R1rM5OyxEVNIr94CB5llCkfKW+1nZTKbbUV0axN3QAUuX2fus/DhQ==" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" } } } diff --git a/packages/cactus-plugin-keychain-memory/package.json b/packages/cactus-plugin-keychain-memory/package.json index 316e2c218a0..0cd7c3cdc9a 100644 --- a/packages/cactus-plugin-keychain-memory/package.json +++ b/packages/cactus-plugin-keychain-memory/package.json @@ -12,6 +12,8 @@ "dist/*" ], "scripts": { + "generate-sdk": "openapi-generator generate --input-spec src/main/json/openapi.json -g typescript-axios -o ./src/main/typescript/generated/openapi/typescript-axios/ --reserved-words-mappings protected=protected", + "pretsc": "npm run generate-sdk", "tsc": "tsc --project ./tsconfig.json", "watch": "npm-watch", "webpack": "npm-run-all webpack:dev webpack:prod", @@ -31,7 +33,10 @@ "ignore": [ "src/**/generated/*" ], - "extensions": ["ts", "json"], + "extensions": [ + "ts", + "json" + ], "quiet": true, "verbose": false, "runOnChangeOnly": true @@ -79,12 +84,17 @@ "homepage": "https://github.com/hyperledger/cactus#readme", "dependencies": { "@hyperledger/cactus-common": "0.3.0", + "@hyperledger/cactus-core": "0.3.0", "@hyperledger/cactus-core-api": "0.3.0", + "axios": "0.21.1", + "express": "4.17.1", "joi": "14.3.1", + "prom-client": "13.1.0", "typescript-optional": "2.0.1", "uuid": "8.3.2" }, "devDependencies": { + "@types/express": "4.17.8", "@types/joi": "14.3.4", "@types/uuid": "8.3.0" } diff --git a/packages/cactus-plugin-keychain-memory/src/main/json/openapi.json b/packages/cactus-plugin-keychain-memory/src/main/json/openapi.json new file mode 100644 index 00000000000..2db1b3962f4 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/json/openapi.json @@ -0,0 +1,573 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Hyperledger Cactus Plugin - Keychain Memory ", + "description": "Contains/describes the Hyperledger Cactus Keychain Memory plugin.", + "version": "0.2.0", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "servers": [ + { + "url": "https://www.cactus.stream/{basePath}", + "description": "Public test instance", + "variables": { + "basePath": { + "default": "" + } + } + }, + { + "url": "http://localhost:4000/{basePath}", + "description": "Local test instance", + "variables": { + "basePath": { + "default": "" + } + } + } + ], + "components": { + "schemas": { + "PluginImport": { + "type": "object", + "required": [ + "packageName", + "type" + ], + "properties": { + "packageName": { + "type": "string", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "type": { + "nullable": false, + "description": "", + "$ref": "#/components/schemas/PluginImportType" + }, + "options": {} + } + }, + "PluginImportType": { + "type": "string", + "enum": [ + "org.hyperledger.cactus.plugin_import_type.LOCAL", + "org.hyperledger.cactus.plugin_import_type.REMOTE" + ] + }, + "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 foremest 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.", + "enum": [ + "org.hyperledger.cactus.consensusalgorithm.PROOF_OF_AUTHORITY", + "org.hyperledger.cactus.consensusalgorithm.PROOF_OF_STAKE", + "org.hyperledger.cactus.consensusalgorithm.PROOF_OF_WORK" + ] + }, + "PrimaryKey": { + "type": "string", + "minLength": 1, + "maxLength": 128, + "nullable": false + }, + "ConsortiumMemberId": { + "$ref": "#/components/schemas/PrimaryKey", + "description": "ID of Consortium member who operates the ledger (if any). Defined as an optional property in case the ledger is a permissionless and/or public one such as the Bitcoin or Ethereum mainnets." + }, + "CactusNodeId": { + "$ref": "#/components/schemas/PrimaryKey", + "description": "ID of a Cactus node that must uniquely distinguish it from all other Cactus nodes within a Consortium. Note that API server instances do not have their own identity the way a node does." + }, + "ConsortiumId": { + "$ref": "#/components/schemas/PrimaryKey" + }, + "LedgerId": { + "description": "String that uniquely identifies a ledger within a Cactus consortium so that transactions can be routed to the correct ledger.", + "$ref": "#/components/schemas/PrimaryKey" + }, + "PluginInstanceId": { + "description": "String that uniquely identifies a plugin instance within a Cactus consortium so that requests can be addressed/routed directly to individual plugins when necessary.", + "$ref": "#/components/schemas/PrimaryKey" + }, + "ConsortiumDatabase": { + "required": [ + "consortium", + "ledger", + "consortiumMember", + "cactusNode", + "pluginInstance" + ], + "properties": { + "consortium": { + "description": "A collection of Consortium entities. In practice this should only ever contain a single consortium, but we defined it as an array to keep the convention up with the rest of the collections defined in the Consortium data in general. Also, if we ever decide to somehow have some sort of consortium to consortium integration (which does not make much sense in the current frame of mind of the author in the year 2020) then having this as an array will have proven itself to be an excellent long term compatibility/extensibility decision indeed.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Consortium" + }, + "default": [], + "minItems": 0, + "maxItems": 2048 + }, + "ledger": { + "description": "The complete collection of all ledger entities inexistence within the consortium.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Ledger" + }, + "default": [], + "minItems": 0, + "maxItems": 2048 + }, + "consortiumMember": { + "description": "The complete collection of all consortium member entities in existence within the consortium.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ConsortiumMember" + }, + "default": [], + "minItems": 0, + "maxItems": 2048 + }, + "cactusNode": { + "description": "The complete collection of all cactus nodes entities in existence within the consortium.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CactusNode" + }, + "default": [], + "minItems": 0, + "maxItems": 2048 + }, + "pluginInstance": { + "description": "The complete collection of all plugin instance entities in existence within the consortium.", + "type": "array", + "items": { + "$ref": "#/components/schemas/PluginInstance" + }, + "default": [], + "minItems": 0, + "maxItems": 2048 + } + } + }, + "Ledger": { + "type": "object", + "required": [ + "id", + "ledgerType" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/LedgerId" + }, + "ledgerType": { + "$ref": "#/components/schemas/LedgerType", + "nullable": false + }, + "consortiumMemberId": { + "$ref": "#/components/schemas/ConsortiumMemberId" + } + } + }, + "LedgerType": { + "description": "Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation.", + "type": "string", + "enum": [ + "BESU_1X", + "BESU_2X", + "BURROW_0X", + "CORDA_4X", + "FABRIC_14X", + "FABRIC_2", + "QUORUM_2X", + "SAWTOOTH_1X" + ] + }, + "Consortium": { + "type": "object", + "required": [ + "id", + "name", + "mainApiHost", + "memberIds" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/ConsortiumId" + }, + "name": { + "type": "string" + }, + "mainApiHost": { + "type": "string" + }, + "memberIds": { + "description": "The collection (array) of primary keys of consortium member entities that belong to this Consortium.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ConsortiumMemberId" + }, + "default": [], + "minItems": 1, + "maxItems": 2048, + "nullable": false + } + } + }, + "ConsortiumMember": { + "type": "object", + "required": [ + "id", + "name", + "nodeIds" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/ConsortiumMemberId" + }, + "name": { + "type": "string", + "description": "The human readable name a Consortium member can be referred to while making it easy for humans to distinguish this particular consortium member entity from any other ones.", + "minLength": 1, + "maxLength": 2048, + "nullable": false + }, + "nodeIds": { + "type": "array", + "default": [], + "nullable": false, + "minItems": 1, + "maxItems": 2048, + "items": { + "$ref": "#/components/schemas/CactusNodeId" + } + } + } + }, + "CactusNodeMeta": { + "description": "A Cactus node meta information", + "type": "object", + "required": [ + "nodeApiHost", + "publicKeyPem" + ], + "properties": { + "nodeApiHost": { + "type": "string", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "publicKeyPem": { + "description": "The PEM encoded public key that was used to generate the JWS included in the response (the jws property)", + "type": "string", + "minLength": 1, + "maxLength": 65535, + "nullable": false, + "format": "Must only contain the public key, never include here the PEM that also contains a private key. See PEM format: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail" + } + } + }, + "CactusNode": { + "description": "A Cactus node can be a single server, or a set of servers behind a loand balancer acting as one.", + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/CactusNodeMeta" + }, + { + "type": "object", + "required": [ + "id", + "consortiumId", + "nodeApiHost", + "memberId", + "publicKeyPem", + "pluginInstanceIds", + "ledgerIds" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/CactusNodeId", + "example": "809a76ba-cfb8-4045-a5c6-ed70a7314c25" + }, + "consortiumId": { + "$ref": "#/components/schemas/ConsortiumId", + "description": "ID of the Cactus Consortium this node is in.", + "example": "3e2670d9-2d14-45bd-96f5-33e2c4b4e3fb" + }, + "memberId": { + "$ref": "#/components/schemas/ConsortiumMemberId", + "example": "b3674a28-e442-4feb-b1f3-8cbe46c20e5e" + }, + "ledgerIds": { + "description": "Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions.", + "type": "array", + "nullable": false, + "minItems": 0, + "maxItems": 2048, + "default": [], + "items": { + "$ref": "#/components/schemas/LedgerId" + } + }, + "pluginInstanceIds": { + "type": "array", + "nullable": false, + "minItems": 0, + "maxItems": 2048, + "default": [], + "items": { + "$ref": "#/components/schemas/PluginInstanceId" + } + } + } + } + ] + }, + "PluginInstance": { + "type": "object", + "required": [ + "id", + "packageName" + ], + "properties": { + "id": { + "$ref": "PluginInstanceId" + }, + "packageName": { + "type": "string", + "minLength": 1, + "maxLength": 4096, + "nullable": false + } + } + }, + "JWSCompact": { + "description": "A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard.", + "type": "string", + "minLength": 5, + "maxLength": 65535, + "pattern": "/^[a-zA-Z0-9-_]+?.[a-zA-Z0-9-_]+?.([a-zA-Z0-9-_]+)?$/", + "example": "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.DOCNCqEMN7CQ_z-RMndiyldljXOk6WFIZxRzNF5Ylg4" + }, + "JWSRecipient": { + "description": "A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard.", + "type": "object", + "required": [ + "signature" + ], + "properties": { + "signature": { + "type": "string" + }, + "protected": { + "type": "string" + }, + "header": { + "type": "object", + "additionalProperties": true + } + } + }, + "JWSGeneral": { + "type": "object", + "required": [ + "payload", + "signatures" + ], + "properties": { + "payload": { + "type": "string", + "minLength": 1, + "maxLength": 65535 + }, + "signatures": { + "type": "array", + "items": { + "$ref": "#/components/schemas/JWSRecipient" + } + } + } + }, + "GetKeychainEntryRequest": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "type": "string", + "description": "The key for the entry to get from the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + } + } + }, + "GetKeychainEntryResponse": { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "description": "The key that was used to retrieve the value from the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "value": { + "type": "string", + "description": "The value associated with the requested key on the keychain.", + "minLength": 0, + "maxLength": 10485760, + "nullable": false + } + } + }, + "SetKeychainEntryRequest": { + "type": "object", + "required": [ + "key", + "value" + ], + "properties": { + "key": { + "type": "string", + "description": "The key for the entry to set on the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + }, + "value": { + "type": "string", + "description": "The value that will be associated with the key on the keychain.", + "minLength": 0, + "maxLength": 10485760, + "nullable": false + } + } + }, + "SetKeychainEntryResponse": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "type": "string", + "description": "The key that was used to set the value on the keychain.", + "minLength": 1, + "maxLength": 1024, + "nullable": false + } + } + }, + "PrometheusExporterMetricsResponse": { + "type": "string", + "nullable": false + } + }, + "requestBodies": { + "keychain_get_entry_request_body": { + "description": "Requst body to obtain a keychain entry via its key", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetKeychainEntryRequest" + } + } + } + }, + "keychain_set_entry_request_body": { + "description": "Requst body to write/update a keychain entry via its key", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetKeychainEntryRequest" + } + } + } + } + }, + "responses": { + "keychain_get_entry_200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetKeychainEntryResponse" + } + } + } + }, + "keychain_get_entry_400": { + "description": "Bad request. Key must be a string and longer than 0, shorter than 1024 characters." + }, + "keychain_get_entry_401": { + "description": "Authorization information is missing or invalid." + }, + "keychain_get_entry_404": { + "description": "A keychain item with the specified key was not found." + }, + "keychain_get_entry_500": { + "description": "Unexpected error." + }, + "keychain_set_entry_200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetKeychainEntryResponse" + } + } + } + }, + "keychain_set_entry_400": { + "description": "Bad request. Key must be a string and longer than 0, shorter than 1024 characters." + }, + "keychain_set_entry_401": { + "description": "Authorization information is missing or invalid." + }, + "keychain_set_entry_500": { + "description": "Unexpected error." + } + } + }, + "paths": { + "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics": { + "get": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics" + } + }, + "operationId": "getPrometheusExporterMetricsV1", + "summary": "Get the Prometheus Metrics", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/PrometheusExporterMetricsResponse" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.gitignore b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.gitignore new file mode 100644 index 00000000000..205d8013f46 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.gitignore @@ -0,0 +1,4 @@ +wwwroot/*.js +node_modules +typings +dist \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore new file mode 100644 index 00000000000..9548c6c6859 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore @@ -0,0 +1,27 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md + +.gitignore +.npmignore +git_push.sh \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES new file mode 100644 index 00000000000..c123dd7d454 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES @@ -0,0 +1,4 @@ +api.ts +base.ts +configuration.ts +index.ts diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION new file mode 100644 index 00000000000..1a487e1a2e3 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION @@ -0,0 +1 @@ +5.0.0-beta2 \ No newline at end of file diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts new file mode 100644 index 00000000000..b8f70ed3f6b --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -0,0 +1,539 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from './configuration'; +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from './base'; + +/** + * A Cactus node can be a single server, or a set of servers behind a loand balancer acting as one. + * @export + * @interface CactusNode + */ +export interface CactusNode { + /** + * + * @type {string} + * @memberof CactusNode + */ + nodeApiHost: string; + /** + * The PEM encoded public key that was used to generate the JWS included in the response (the jws property) + * @type {string} + * @memberof CactusNode + */ + publicKeyPem: string; + /** + * + * @type {string} + * @memberof CactusNode + */ + id: string; + /** + * + * @type {string} + * @memberof CactusNode + */ + consortiumId: string; + /** + * + * @type {string} + * @memberof CactusNode + */ + memberId: string; + /** + * Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. + * @type {Array} + * @memberof CactusNode + */ + ledgerIds: Array; + /** + * + * @type {Array} + * @memberof CactusNode + */ + pluginInstanceIds: Array; +} +/** + * + * @export + * @interface CactusNodeAllOf + */ +export interface CactusNodeAllOf { + /** + * + * @type {string} + * @memberof CactusNodeAllOf + */ + id: string; + /** + * + * @type {string} + * @memberof CactusNodeAllOf + */ + consortiumId: string; + /** + * + * @type {string} + * @memberof CactusNodeAllOf + */ + memberId: string; + /** + * Stores an array of Ledger entity IDs that are reachable (routable) via this Cactus Node. This information is used by the client side SDK API client to figure out at runtime where to send API requests that are specific to a certain ledger such as requests to execute transactions. + * @type {Array} + * @memberof CactusNodeAllOf + */ + ledgerIds: Array; + /** + * + * @type {Array} + * @memberof CactusNodeAllOf + */ + pluginInstanceIds: Array; +} +/** + * A Cactus node meta information + * @export + * @interface CactusNodeMeta + */ +export interface CactusNodeMeta { + /** + * + * @type {string} + * @memberof CactusNodeMeta + */ + nodeApiHost: string; + /** + * The PEM encoded public key that was used to generate the JWS included in the response (the jws property) + * @type {string} + * @memberof CactusNodeMeta + */ + publicKeyPem: string; +} +/** + * 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 foremest 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. + * @export + * @enum {string} + */ +export enum ConsensusAlgorithmFamily { + AUTHORITY = 'org.hyperledger.cactus.consensusalgorithm.PROOF_OF_AUTHORITY', + STAKE = 'org.hyperledger.cactus.consensusalgorithm.PROOF_OF_STAKE', + WORK = 'org.hyperledger.cactus.consensusalgorithm.PROOF_OF_WORK' +} + +/** + * + * @export + * @interface Consortium + */ +export interface Consortium { + /** + * + * @type {string} + * @memberof Consortium + */ + id: string; + /** + * + * @type {string} + * @memberof Consortium + */ + name: string; + /** + * + * @type {string} + * @memberof Consortium + */ + mainApiHost: string; + /** + * The collection (array) of primary keys of consortium member entities that belong to this Consortium. + * @type {Array} + * @memberof Consortium + */ + memberIds: Array; +} +/** + * + * @export + * @interface ConsortiumDatabase + */ +export interface ConsortiumDatabase { + /** + * A collection of Consortium entities. In practice this should only ever contain a single consortium, but we defined it as an array to keep the convention up with the rest of the collections defined in the Consortium data in general. Also, if we ever decide to somehow have some sort of consortium to consortium integration (which does not make much sense in the current frame of mind of the author in the year 2020) then having this as an array will have proven itself to be an excellent long term compatibility/extensibility decision indeed. + * @type {Array} + * @memberof ConsortiumDatabase + */ + consortium: Array; + /** + * The complete collection of all ledger entities inexistence within the consortium. + * @type {Array} + * @memberof ConsortiumDatabase + */ + ledger: Array; + /** + * The complete collection of all consortium member entities in existence within the consortium. + * @type {Array} + * @memberof ConsortiumDatabase + */ + consortiumMember: Array; + /** + * The complete collection of all cactus nodes entities in existence within the consortium. + * @type {Array} + * @memberof ConsortiumDatabase + */ + cactusNode: Array; + /** + * The complete collection of all plugin instance entities in existence within the consortium. + * @type {Array} + * @memberof ConsortiumDatabase + */ + pluginInstance: Array; +} +/** + * + * @export + * @interface ConsortiumMember + */ +export interface ConsortiumMember { + /** + * + * @type {string} + * @memberof ConsortiumMember + */ + id: string; + /** + * The human readable name a Consortium member can be referred to while making it easy for humans to distinguish this particular consortium member entity from any other ones. + * @type {string} + * @memberof ConsortiumMember + */ + name: string; + /** + * + * @type {Array} + * @memberof ConsortiumMember + */ + nodeIds: Array; +} +/** + * + * @export + * @interface GetKeychainEntryRequest + */ +export interface GetKeychainEntryRequest { + /** + * The key for the entry to get from the keychain. + * @type {string} + * @memberof GetKeychainEntryRequest + */ + key: string; +} +/** + * + * @export + * @interface GetKeychainEntryResponse + */ +export interface GetKeychainEntryResponse { + /** + * The key that was used to retrieve the value from the keychain. + * @type {string} + * @memberof GetKeychainEntryResponse + */ + key: string; + /** + * The value associated with the requested key on the keychain. + * @type {string} + * @memberof GetKeychainEntryResponse + */ + value: string; +} +/** + * + * @export + * @interface JWSGeneral + */ +export interface JWSGeneral { + /** + * + * @type {string} + * @memberof JWSGeneral + */ + payload: string; + /** + * + * @type {Array} + * @memberof JWSGeneral + */ + signatures: Array; +} +/** + * A JSON Web Signature. See: https://tools.ietf.org/html/rfc7515 for info about standard. + * @export + * @interface JWSRecipient + */ +export interface JWSRecipient { + /** + * + * @type {string} + * @memberof JWSRecipient + */ + signature: string; + /** + * + * @type {string} + * @memberof JWSRecipient + */ + protected?: string; + /** + * + * @type {{ [key: string]: object; }} + * @memberof JWSRecipient + */ + header?: { [key: string]: object; }; +} +/** + * + * @export + * @interface Ledger + */ +export interface Ledger { + /** + * + * @type {string} + * @memberof Ledger + */ + id: string; + /** + * + * @type {LedgerType} + * @memberof Ledger + */ + ledgerType: LedgerType; + /** + * + * @type {string} + * @memberof Ledger + */ + consortiumMemberId?: string; +} +/** + * Enumerates the different ledger vendors and their major versions encoded within the name of the LedgerType. For example \"BESU_1X\" involves all of the [1.0.0;2.0.0) where 1.0.0 is included and anything up until, but not 2.0.0. See: https://stackoverflow.com/a/4396303/698470 for further explanation. + * @export + * @enum {string} + */ +export enum LedgerType { + BESU1X = 'BESU_1X', + BESU2X = 'BESU_2X', + BURROW0X = 'BURROW_0X', + CORDA4X = 'CORDA_4X', + FABRIC14X = 'FABRIC_14X', + FABRIC2 = 'FABRIC_2', + QUORUM2X = 'QUORUM_2X', + SAWTOOTH1X = 'SAWTOOTH_1X' +} + +/** + * + * @export + * @interface PluginImport + */ +export interface PluginImport { + /** + * + * @type {string} + * @memberof PluginImport + */ + packageName: string; + /** + * + * @type {PluginImportType} + * @memberof PluginImport + */ + type: PluginImportType; + /** + * + * @type {any} + * @memberof PluginImport + */ + options?: any | null; +} +/** + * + * @export + * @enum {string} + */ +export enum PluginImportType { + LOCAL = 'org.hyperledger.cactus.plugin_import_type.LOCAL', + REMOTE = 'org.hyperledger.cactus.plugin_import_type.REMOTE' +} + +/** + * + * @export + * @interface PluginInstance + */ +export interface PluginInstance { + /** + * + * @type {string} + * @memberof PluginInstance + */ + id: string; + /** + * + * @type {string} + * @memberof PluginInstance + */ + packageName: string; +} +/** + * + * @export + * @interface SetKeychainEntryRequest + */ +export interface SetKeychainEntryRequest { + /** + * The key for the entry to set on the keychain. + * @type {string} + * @memberof SetKeychainEntryRequest + */ + key: string; + /** + * The value that will be associated with the key on the keychain. + * @type {string} + * @memberof SetKeychainEntryRequest + */ + value: string; +} +/** + * + * @export + * @interface SetKeychainEntryResponse + */ +export interface SetKeychainEntryResponse { + /** + * The key that was used to set the value on the keychain. + * @type {string} + * @memberof SetKeychainEntryResponse + */ + key: string; +} + +/** + * DefaultApi - axios parameter creator + * @export + */ +export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusExporterMetricsV1: async (options: any = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + query.set(key, options.query[key]); + } + localVarUrlObj.search = (new URLSearchParams(query)).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * DefaultApi - functional programming interface + * @export + */ +export const DefaultApiFp = function(configuration?: Configuration) { + return { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getPrometheusExporterMetricsV1(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await DefaultApiAxiosParamCreator(configuration).getPrometheusExporterMetricsV1(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url}; + return axios.request(axiosRequestArgs); + }; + }, + } +}; + +/** + * DefaultApi - factory interface + * @export + */ +export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + return { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusExporterMetricsV1(options?: any): AxiosPromise { + return DefaultApiFp(configuration).getPrometheusExporterMetricsV1(options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * DefaultApi - object-oriented interface + * @export + * @class DefaultApi + * @extends {BaseAPI} + */ +export class DefaultApi extends BaseAPI { + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getPrometheusExporterMetricsV1(options?: any) { + return DefaultApiFp(this.configuration).getPrometheusExporterMetricsV1(options).then((request) => request(this.axios, this.basePath)); + } +} + + diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts new file mode 100644 index 00000000000..85dd928e538 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/base.ts @@ -0,0 +1,71 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import { Configuration } from "./configuration"; +// Some imports not used depending on template conditions +// @ts-ignore +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; + +export const BASE_PATH = "https://www.cactus.stream".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: any; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath || this.basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + name: "RequiredError" = "RequiredError"; + constructor(public field: string, msg?: string) { + super(msg); + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts new file mode 100644 index 00000000000..00e20b62215 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/configuration.ts @@ -0,0 +1,76 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + baseOptions?: any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.baseOptions = param.baseOptions; + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts new file mode 100644 index 00000000000..81e16776d62 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/generated/openapi/typescript-axios/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Keychain Memory + * Contains/describes the Hyperledger Cactus Keychain Memory plugin. + * + * The version of the OpenAPI document: 0.2.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; + diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts new file mode 100644 index 00000000000..c1bff16ad5b --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1.ts @@ -0,0 +1,81 @@ +import { Express, Request, Response } from "express"; + +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, +} from "@hyperledger/cactus-core-api/"; + +import OAS from "../../json/openapi.json"; + +import { registerWebServiceEndpoint } from "@hyperledger/cactus-core"; + +import { PluginKeychainMemory } from "../plugin-keychain-memory"; + +export interface IGetPrometheusExporterMetricsEndpointV1Options { + logLevel?: LogLevelDesc; + plugin: PluginKeychainMemory; +} + +export class GetPrometheusExporterMetricsEndpointV1 + implements IWebServiceEndpoint { + private readonly log: Logger; + + constructor( + public readonly opts: IGetPrometheusExporterMetricsEndpointV1Options, + ) { + const fnTag = "GetPrometheusExporterMetricsEndpointV1#constructor()"; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.plugin, `${fnTag} options.plugin`); + + this.log = LoggerProvider.getOrCreate({ + label: "get-prometheus-exporter-metrics-v1", + level: opts.logLevel || "INFO", + }); + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics" + ].get["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics" + ].get["x-hyperledger-cactus"].http.verbLowerCase; + } + + public registerExpress(app: Express): IWebServiceEndpoint { + registerWebServiceEndpoint(app, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = "GetPrometheusExporterMetrics#handleRequest()"; + const verbUpper = this.getVerbLowerCase().toUpperCase(); + this.log.debug(`${verbUpper} ${this.getPath()}`); + + try { + const resBody = await this.opts.plugin.getPrometheusExporterMetrics(); + res.status(200); + res.send(resBody); + } catch (ex) { + this.log.error(`${fnTag} failed to serve request`, ex); + res.status(500); + res.statusMessage = ex.message; + res.json({ error: ex.stack }); + } + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts index 1751771ae15..9ee54f69bed 100644 --- a/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/plugin-keychain-memory.ts @@ -7,12 +7,22 @@ import { import { ICactusPluginOptions, PluginAspect, + IWebServiceEndpoint, } from "@hyperledger/cactus-core-api"; +import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter"; +import { Express } from "express"; + +import { + IGetPrometheusExporterMetricsEndpointV1Options, + GetPrometheusExporterMetricsEndpointV1, +} from "./get-prometheus-exporter-metrics/get-prometheus-exporter-metrics-endpoint-v1"; + export interface IPluginKeychainMemoryOptions extends ICactusPluginOptions { logLevel?: LogLevelDesc; backend?: Map; keychainId: string; + prometheusExporter?: PrometheusExporter; } export class PluginKeychainMemory { @@ -21,6 +31,7 @@ export class PluginKeychainMemory { private readonly backend: Map; private readonly log: Logger; private readonly instanceId: string; + public prometheusExporter: PrometheusExporter; public get className(): string { return PluginKeychainMemory.CLASS_NAME; @@ -41,6 +52,13 @@ export class PluginKeychainMemory { this.log = LoggerProvider.getOrCreate({ level, label }); this.instanceId = this.opts.instanceId; + this.prometheusExporter = + opts.prometheusExporter || + new PrometheusExporter({ pollingIntervalInMin: 1 }); + Checks.truthy( + this.prometheusExporter, + `${fnTag} options.prometheusExporter`, + ); this.log.info(`Created ${this.className}. KeychainID=${opts.keychainId}`); this.log.warn( @@ -49,6 +67,40 @@ export class PluginKeychainMemory { ); } + public getPrometheusExporter(): PrometheusExporter { + return this.prometheusExporter; + } + + public async getPrometheusExporterMetrics(): Promise { + const res: string = await this.prometheusExporter.getPrometheusMetrics(); + this.log.debug(`getPrometheusExporterMetrics() response: %o`, res); + return res; + } + + public async installWebServices( + expressApp: Express, + ): Promise { + const { log } = this; + + log.info(`Installing web services for plugin ${this.getPackageName()}...`); + + const endpoints: IWebServiceEndpoint[] = []; + { + const opts: IGetPrometheusExporterMetricsEndpointV1Options = { + plugin: this, + logLevel: this.opts.logLevel, + }; + const endpoint = new GetPrometheusExporterMetricsEndpointV1(opts); + endpoint.registerExpress(expressApp); + endpoints.push(endpoint); + } + + const pkg = this.getPackageName(); + log.info(`Installed web services for plugin ${pkg} OK`, { endpoints }); + + return endpoints; + } + public getInstanceId(): string { return this.instanceId; } @@ -75,9 +127,11 @@ export class PluginKeychainMemory { async set(key: string, value: T): Promise { this.backend.set(key, value); + this.prometheusExporter.setTotalKeyCounter(this.backend.size); } async delete(key: string): Promise { this.backend.delete(key); + this.prometheusExporter.setTotalKeyCounter(this.backend.size); } } diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts new file mode 100644 index 00000000000..b2f231dd62b --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/data-fetcher.ts @@ -0,0 +1,9 @@ +import { Keys } from "./response.type"; + +import { totalKeyCount } from "./metrics"; + +export async function collectMetrics(keys: Keys) { + totalKeyCount + .labels("cactus_keychain_memory_total_key_count") + .set(keys.counter); +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts new file mode 100644 index 00000000000..fccefd1c559 --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/metrics.ts @@ -0,0 +1,7 @@ +import { Gauge } from "prom-client"; + +export const totalKeyCount = new Gauge({ + name: "cactus_keychain_memory_total_key_count", + help: "Total keys present in vault", + labelNames: ["type"], +}); diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts new file mode 100644 index 00000000000..fcae7ef07ad --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/prometheus-exporter.ts @@ -0,0 +1,41 @@ +import promClient from "prom-client"; +import { Keys } from "./response.type"; +import { totalKeyCount } from "./metrics"; + +export const K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT = + "cactus_keychain_memory_total_key_count"; + +export interface IPrometheusExporterOptions { + pollingIntervalInMin?: number; +} + +export class PrometheusExporter { + public readonly metricsPollingIntervalInMin: number; + public readonly keys: Keys = { counter: 0 }; + + constructor( + public readonly prometheusExporterOptions: IPrometheusExporterOptions, + ) { + this.metricsPollingIntervalInMin = + prometheusExporterOptions.pollingIntervalInMin || 1; + } + + public setTotalKeyCounter(keyCount: number): void { + totalKeyCount + .labels(K_CACTUS_KEYCHAIN_MEMORY_TOTAL_KEY_COUNT) + .set(keyCount); + } + + public async getPrometheusMetrics(): Promise { + const result = await promClient.register.getSingleMetricAsString( + "cactus_keychain_memory_total_key_count", + ); + return result; + } + + public startMetricsCollection(): void { + const Registry = promClient.Registry; + const register = new Registry(); + promClient.collectDefaultMetrics({ register }); + } +} diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts new file mode 100644 index 00000000000..6228b9c5f6c --- /dev/null +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/prometheus-exporter/response.type.ts @@ -0,0 +1,3 @@ +export type Keys = { + counter: number; +}; diff --git a/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts b/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts index eb339c2fe51..1017146dca5 100755 --- a/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts +++ b/packages/cactus-plugin-keychain-memory/src/main/typescript/public-api.ts @@ -1,3 +1,4 @@ +export * from "./generated/openapi/typescript-axios/index"; import { IPluginFactoryOptions } from "@hyperledger/cactus-core-api"; export { diff --git a/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts b/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts index c1ade2e9ec0..e12895d1ee6 100644 --- a/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts +++ b/packages/cactus-plugin-keychain-memory/src/test/typescript/unit/plugin-keychain-memory.test.ts @@ -1,11 +1,20 @@ import test, { Test } from "tape-promise/tape"; +import express from "express"; +import bodyParser from "body-parser"; +import http from "http"; +import { AddressInfo } from "net"; + +import { IListenOptions, Servers } from "@hyperledger/cactus-common"; + import { v4 as uuidv4 } from "uuid"; import { IPluginKeychainMemoryOptions, PluginKeychainMemory, } from "../../../main/typescript"; +import { DefaultApi as KeychainMemoryApi } from "../../../main/typescript/public-api"; + test("PluginKeychainMemory", (t1: Test) => { t1.doesNotThrow( () => new PluginKeychainMemory({ instanceId: "a", keychainId: "a" }), @@ -53,6 +62,26 @@ test("PluginKeychainMemory", (t1: Test) => { keychainId: uuidv4(), }; const plugin = new PluginKeychainMemory(options); + + const expressApp = express(); + expressApp.use(bodyParser.json({ limit: "250mb" })); + const server = http.createServer(expressApp); + const listenOptions: IListenOptions = { + hostname: "0.0.0.0", + port: 0, + server, + }; + const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo; + test.onFinish(async () => await Servers.shutdown(server)); + const { address, port } = addressInfo; + const apiHost = `http://${address}:${port}`; + t.comment( + `Metrics URL: ${apiHost}/api/v1/plugins/@hyperledger/cactus-plugin-keychain-memory/get-prometheus-exporter-metrics`, + ); + const apiClient = new KeychainMemoryApi({ basePath: apiHost }); + + await plugin.installWebServices(expressApp); + t.equal(plugin.getKeychainId(), options.keychainId, "Keychain ID set OK"); t.equal(plugin.getInstanceId(), options.instanceId, "Instance ID set OK"); @@ -78,6 +107,20 @@ test("PluginKeychainMemory", (t1: Test) => { const valueAfterDelete = await plugin.get(key); t.notok(valueAfterDelete, "valueAfterDelete falsy OK"); + { + const res = await apiClient.getPrometheusExporterMetricsV1(); + const promMetricsOutput = + "# HELP cactus_keychain_memory_total_key_count Total keys present in vault\n" + + "# TYPE cactus_keychain_memory_total_key_count gauge\n" + + 'cactus_keychain_memory_total_key_count{type="cactus_keychain_memory_total_key_count"} 0'; + t.ok(res); + t.ok(res.data); + t.equal(res.status, 200); + t.true( + res.data.includes(promMetricsOutput), + "Total Key Count 0 recorded as expected. RESULT OK", + ); + } t.end(); });