@kapeta/local-cluster-service 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +17 -0
- package/.github/workflows/main.yml +22 -22
- package/.prettierignore +4 -0
- package/.vscode/launch.json +2 -4
- package/CHANGELOG.md +14 -0
- package/definitions.d.ts +17 -35
- package/dist/cjs/index.d.ts +27 -0
- package/dist/cjs/index.js +126 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/assetManager.d.ts +31 -0
- package/dist/cjs/src/assetManager.js +153 -0
- package/dist/cjs/src/assets/routes.d.ts +3 -0
- package/dist/cjs/src/assets/routes.js +117 -0
- package/dist/cjs/src/clusterService.d.ts +40 -0
- package/dist/cjs/src/clusterService.js +114 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +8 -0
- package/dist/cjs/src/codeGeneratorManager.js +53 -0
- package/dist/cjs/src/config/routes.d.ts +3 -0
- package/dist/cjs/src/config/routes.js +126 -0
- package/dist/cjs/src/configManager.d.ts +36 -0
- package/dist/cjs/src/configManager.js +110 -0
- package/dist/cjs/src/containerManager.d.ts +89 -0
- package/dist/cjs/src/containerManager.js +365 -0
- package/dist/cjs/src/filesystem/routes.d.ts +3 -0
- package/dist/cjs/src/filesystem/routes.js +69 -0
- package/dist/cjs/src/filesystemManager.d.ts +15 -0
- package/dist/cjs/src/filesystemManager.js +87 -0
- package/dist/cjs/src/identities/routes.d.ts +3 -0
- package/dist/cjs/src/identities/routes.js +18 -0
- package/dist/cjs/src/instanceManager.d.ts +56 -0
- package/dist/cjs/src/instanceManager.js +424 -0
- package/dist/cjs/src/instances/routes.d.ts +3 -0
- package/dist/cjs/src/instances/routes.js +134 -0
- package/dist/cjs/src/middleware/cors.d.ts +2 -0
- package/dist/cjs/src/middleware/cors.js +10 -0
- package/dist/cjs/src/middleware/kapeta.d.ts +11 -0
- package/dist/cjs/src/middleware/kapeta.js +17 -0
- package/dist/cjs/src/middleware/stringBody.d.ts +5 -0
- package/dist/cjs/src/middleware/stringBody.js +14 -0
- package/dist/cjs/src/networkManager.d.ts +32 -0
- package/dist/cjs/src/networkManager.js +109 -0
- package/dist/cjs/src/operatorManager.d.ts +36 -0
- package/dist/cjs/src/operatorManager.js +165 -0
- package/dist/cjs/src/progressListener.d.ts +20 -0
- package/dist/cjs/src/progressListener.js +91 -0
- package/dist/cjs/src/providerManager.d.ts +9 -0
- package/dist/cjs/src/providerManager.js +51 -0
- package/dist/cjs/src/providers/routes.d.ts +3 -0
- package/dist/cjs/src/providers/routes.js +42 -0
- package/dist/cjs/src/proxy/routes.d.ts +3 -0
- package/dist/cjs/src/proxy/routes.js +111 -0
- package/dist/cjs/src/proxy/types/rest.d.ts +4 -0
- package/dist/cjs/src/proxy/types/rest.js +114 -0
- package/dist/cjs/src/proxy/types/web.d.ts +4 -0
- package/dist/cjs/src/proxy/types/web.js +53 -0
- package/dist/cjs/src/repositoryManager.d.ts +17 -0
- package/dist/cjs/src/repositoryManager.js +218 -0
- package/dist/cjs/src/serviceManager.d.ts +29 -0
- package/dist/cjs/src/serviceManager.js +99 -0
- package/dist/cjs/src/socketManager.d.ts +14 -0
- package/dist/cjs/src/socketManager.js +53 -0
- package/dist/cjs/src/storageService.d.ts +17 -0
- package/dist/cjs/src/storageService.js +74 -0
- package/dist/cjs/src/traffic/routes.d.ts +3 -0
- package/dist/cjs/src/traffic/routes.js +18 -0
- package/dist/cjs/src/types.d.ts +88 -0
- package/dist/cjs/src/types.js +2 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +29 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +468 -0
- package/dist/cjs/src/utils/LogData.d.ts +19 -0
- package/dist/cjs/src/utils/LogData.js +43 -0
- package/dist/cjs/src/utils/pathTemplateParser.d.ts +26 -0
- package/dist/cjs/src/utils/pathTemplateParser.js +121 -0
- package/dist/cjs/src/utils/utils.d.ts +1 -0
- package/dist/cjs/src/utils/utils.js +18 -0
- package/dist/cjs/start.d.ts +1 -0
- package/dist/cjs/start.js +12 -0
- package/dist/esm/index.d.ts +27 -0
- package/dist/esm/index.js +121 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/src/assetManager.d.ts +31 -0
- package/{src → dist/esm/src}/assetManager.js +22 -60
- package/dist/esm/src/assets/routes.d.ts +3 -0
- package/{src → dist/esm/src}/assets/routes.js +21 -36
- package/dist/esm/src/clusterService.d.ts +40 -0
- package/{src → dist/esm/src}/clusterService.js +14 -37
- package/dist/esm/src/codeGeneratorManager.d.ts +8 -0
- package/{src → dist/esm/src}/codeGeneratorManager.js +15 -24
- package/dist/esm/src/config/routes.d.ts +3 -0
- package/{src → dist/esm/src}/config/routes.js +40 -89
- package/dist/esm/src/configManager.d.ts +36 -0
- package/{src → dist/esm/src}/configManager.js +11 -40
- package/dist/esm/src/containerManager.d.ts +89 -0
- package/{src → dist/esm/src}/containerManager.js +81 -182
- package/dist/esm/src/filesystem/routes.d.ts +3 -0
- package/dist/esm/src/filesystem/routes.js +64 -0
- package/dist/esm/src/filesystemManager.d.ts +15 -0
- package/{src → dist/esm/src}/filesystemManager.js +20 -28
- package/dist/esm/src/identities/routes.d.ts +3 -0
- package/dist/esm/src/identities/routes.js +13 -0
- package/dist/esm/src/instanceManager.d.ts +56 -0
- package/{src → dist/esm/src}/instanceManager.js +88 -179
- package/dist/esm/src/instances/routes.d.ts +3 -0
- package/{src → dist/esm/src}/instances/routes.js +31 -70
- package/dist/esm/src/middleware/cors.d.ts +2 -0
- package/{src → dist/esm/src}/middleware/cors.js +2 -3
- package/dist/esm/src/middleware/kapeta.d.ts +11 -0
- package/{src → dist/esm/src}/middleware/kapeta.js +3 -7
- package/dist/esm/src/middleware/stringBody.d.ts +5 -0
- package/{src → dist/esm/src}/middleware/stringBody.js +2 -3
- package/dist/esm/src/networkManager.d.ts +32 -0
- package/{src → dist/esm/src}/networkManager.js +16 -33
- package/dist/esm/src/operatorManager.d.ts +36 -0
- package/{src → dist/esm/src}/operatorManager.js +35 -91
- package/dist/esm/src/progressListener.d.ts +20 -0
- package/dist/esm/src/progressListener.js +88 -0
- package/dist/esm/src/providerManager.d.ts +9 -0
- package/dist/esm/src/providerManager.js +45 -0
- package/dist/esm/src/providers/routes.d.ts +3 -0
- package/{src → dist/esm/src}/providers/routes.js +10 -16
- package/dist/esm/src/proxy/routes.d.ts +3 -0
- package/dist/esm/src/proxy/routes.js +106 -0
- package/dist/esm/src/proxy/types/rest.d.ts +4 -0
- package/dist/esm/src/proxy/types/rest.js +107 -0
- package/dist/esm/src/proxy/types/web.d.ts +4 -0
- package/{src → dist/esm/src}/proxy/types/web.js +13 -35
- package/dist/esm/src/repositoryManager.d.ts +17 -0
- package/dist/esm/src/repositoryManager.js +212 -0
- package/dist/esm/src/serviceManager.d.ts +29 -0
- package/{src → dist/esm/src}/serviceManager.js +12 -42
- package/dist/esm/src/socketManager.d.ts +14 -0
- package/{src → dist/esm/src}/socketManager.js +19 -23
- package/dist/esm/src/storageService.d.ts +17 -0
- package/{src → dist/esm/src}/storageService.js +8 -27
- package/dist/esm/src/traffic/routes.d.ts +3 -0
- package/{src → dist/esm/src}/traffic/routes.js +4 -9
- package/dist/esm/src/types.d.ts +88 -0
- package/dist/esm/src/types.js +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +29 -0
- package/{src → dist/esm/src}/utils/BlockInstanceRunner.js +137 -256
- package/dist/esm/src/utils/LogData.d.ts +19 -0
- package/{src → dist/esm/src}/utils/LogData.js +11 -22
- package/dist/esm/src/utils/pathTemplateParser.d.ts +26 -0
- package/{src → dist/esm/src}/utils/pathTemplateParser.js +21 -40
- package/dist/esm/src/utils/utils.d.ts +1 -0
- package/dist/esm/src/utils/utils.js +11 -0
- package/dist/esm/start.d.ts +1 -0
- package/dist/esm/start.js +7 -0
- package/index.ts +147 -0
- package/package.json +106 -74
- package/src/assetManager.ts +191 -0
- package/src/assets/routes.ts +132 -0
- package/src/clusterService.ts +134 -0
- package/src/codeGeneratorManager.ts +57 -0
- package/src/config/routes.ts +159 -0
- package/src/configManager.ts +148 -0
- package/src/containerManager.ts +466 -0
- package/src/filesystem/routes.ts +74 -0
- package/src/filesystemManager.ts +93 -0
- package/src/identities/routes.ts +20 -0
- package/src/instanceManager.ts +503 -0
- package/src/instances/routes.ts +164 -0
- package/src/middleware/cors.ts +9 -0
- package/src/middleware/kapeta.ts +27 -0
- package/src/middleware/stringBody.ts +16 -0
- package/src/networkManager.ts +137 -0
- package/src/operatorManager.ts +221 -0
- package/src/progressListener.ts +102 -0
- package/src/{providerManager.js → providerManager.ts} +15 -31
- package/src/providers/routes.ts +46 -0
- package/src/proxy/routes.ts +148 -0
- package/src/proxy/types/{rest.js → rest.ts} +30 -30
- package/src/proxy/types/web.ts +60 -0
- package/src/{repositoryManager.js → repositoryManager.ts} +49 -73
- package/src/serviceManager.ts +120 -0
- package/src/socketManager.ts +57 -0
- package/src/storageService.ts +88 -0
- package/src/traffic/routes.ts +18 -0
- package/src/types.ts +97 -0
- package/src/utils/BlockInstanceRunner.ts +555 -0
- package/src/utils/LogData.ts +47 -0
- package/src/utils/pathTemplateParser.ts +138 -0
- package/src/utils/utils.ts +12 -0
- package/start.ts +8 -0
- package/tsconfig.json +13 -0
- package/index.js +0 -127
- package/src/filesystem/routes.js +0 -74
- package/src/identities/routes.js +0 -19
- package/src/progressListener.js +0 -82
- package/src/proxy/routes.js +0 -126
- package/src/utils/utils.js +0 -13
- package/start.js +0 -7
@@ -0,0 +1,109 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.networkManager = void 0;
|
7
|
+
const node_uuid_1 = __importDefault(require("node-uuid"));
|
8
|
+
class NetworkManager {
|
9
|
+
_connections;
|
10
|
+
_sources;
|
11
|
+
_targets;
|
12
|
+
static toConnectionId(connection) {
|
13
|
+
return [
|
14
|
+
connection.provider.blockId,
|
15
|
+
connection.provider.resourceName,
|
16
|
+
connection.consumer.blockId,
|
17
|
+
connection.consumer.resourceName,
|
18
|
+
].join('_');
|
19
|
+
}
|
20
|
+
constructor() {
|
21
|
+
this._connections = {};
|
22
|
+
this._sources = {};
|
23
|
+
this._targets = {};
|
24
|
+
}
|
25
|
+
_ensureSystem(systemId) {
|
26
|
+
if (!this._connections[systemId]) {
|
27
|
+
this._connections[systemId] = {};
|
28
|
+
}
|
29
|
+
if (!this._sources[systemId]) {
|
30
|
+
this._sources[systemId] = {};
|
31
|
+
}
|
32
|
+
if (!this._targets[systemId]) {
|
33
|
+
this._targets[systemId] = {};
|
34
|
+
}
|
35
|
+
}
|
36
|
+
_ensureConnection(systemId, connectionId) {
|
37
|
+
this._ensureSystem(systemId);
|
38
|
+
if (!this._connections[systemId][connectionId]) {
|
39
|
+
this._connections[systemId][connectionId] = [];
|
40
|
+
}
|
41
|
+
return this._connections[systemId][connectionId];
|
42
|
+
}
|
43
|
+
_ensureSource(systemId, sourceBlockInstanceId) {
|
44
|
+
this._ensureSystem(systemId);
|
45
|
+
if (!this._sources[systemId][sourceBlockInstanceId]) {
|
46
|
+
this._sources[systemId][sourceBlockInstanceId] = [];
|
47
|
+
}
|
48
|
+
return this._sources[systemId][sourceBlockInstanceId];
|
49
|
+
}
|
50
|
+
_ensureTarget(systemId, targetBlockInstanceId) {
|
51
|
+
this._ensureSystem(systemId);
|
52
|
+
if (!this._targets[systemId][targetBlockInstanceId]) {
|
53
|
+
this._targets[systemId][targetBlockInstanceId] = [];
|
54
|
+
}
|
55
|
+
return this._targets[systemId][targetBlockInstanceId];
|
56
|
+
}
|
57
|
+
addRequest(systemId, connection, request, consumerMethodId, providerMethodId) {
|
58
|
+
const traffic = new Traffic(connection, request, consumerMethodId, providerMethodId);
|
59
|
+
this._ensureConnection(systemId, traffic.connectionId).push(traffic);
|
60
|
+
this._ensureSource(systemId, connection.provider.blockId).push(traffic);
|
61
|
+
this._ensureTarget(systemId, connection.consumer.blockId).push(traffic);
|
62
|
+
return traffic;
|
63
|
+
}
|
64
|
+
getTrafficForConnection(systemId, connectionId) {
|
65
|
+
return this._ensureConnection(systemId, connectionId);
|
66
|
+
}
|
67
|
+
getTrafficForSource(systemId, blockInstanceId) {
|
68
|
+
return this._ensureSource(systemId, blockInstanceId);
|
69
|
+
}
|
70
|
+
getTrafficForTarget(systemId, blockInstanceId) {
|
71
|
+
return this._ensureTarget(systemId, blockInstanceId);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
class Traffic {
|
75
|
+
id;
|
76
|
+
connectionId;
|
77
|
+
consumerMethodId;
|
78
|
+
providerMethodId;
|
79
|
+
created;
|
80
|
+
request;
|
81
|
+
ended;
|
82
|
+
error;
|
83
|
+
response;
|
84
|
+
constructor(connection, request, consumerMethodId, providerMethodId) {
|
85
|
+
this.id = node_uuid_1.default.v4();
|
86
|
+
this.connectionId = NetworkManager.toConnectionId(connection);
|
87
|
+
this.consumerMethodId = consumerMethodId;
|
88
|
+
this.providerMethodId = providerMethodId;
|
89
|
+
this.request = request;
|
90
|
+
this.response = null;
|
91
|
+
this.error = null;
|
92
|
+
this.ended = null;
|
93
|
+
this.created = new Date().getTime();
|
94
|
+
}
|
95
|
+
asError(err) {
|
96
|
+
this.ended = new Date().getTime();
|
97
|
+
this.response = {
|
98
|
+
code: 0,
|
99
|
+
headers: {},
|
100
|
+
body: null,
|
101
|
+
};
|
102
|
+
this.error = err + '';
|
103
|
+
}
|
104
|
+
withResponse(response) {
|
105
|
+
this.ended = new Date().getTime();
|
106
|
+
this.response = response;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
exports.networkManager = new NetworkManager();
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { ContainerInfo } from './containerManager';
|
2
|
+
import { EnvironmentType, OperatorInfo } from './types';
|
3
|
+
declare class Operator {
|
4
|
+
private _data;
|
5
|
+
constructor(data: any);
|
6
|
+
getData(): any;
|
7
|
+
getCredentials(): any;
|
8
|
+
}
|
9
|
+
declare class OperatorManager {
|
10
|
+
private _mountDir;
|
11
|
+
constructor();
|
12
|
+
_getMountPoint(operatorType: string, mountName: string): string;
|
13
|
+
/**
|
14
|
+
* Get operator definition for resource type
|
15
|
+
*
|
16
|
+
* @param {string} resourceType
|
17
|
+
* @param {string} version
|
18
|
+
* @return {Operator}
|
19
|
+
*/
|
20
|
+
getOperator(resourceType: string, version: string): Operator;
|
21
|
+
/**
|
22
|
+
* Get information about a specific consumed resource
|
23
|
+
*/
|
24
|
+
getConsumerResourceInfo(systemId: string, fromServiceId: string, resourceType: string, portType: string, name: string, environment?: EnvironmentType): Promise<OperatorInfo>;
|
25
|
+
/**
|
26
|
+
* Ensure we have a running operator of given type
|
27
|
+
*
|
28
|
+
* @param {string} systemId
|
29
|
+
* @param {string} resourceType
|
30
|
+
* @param {string} version
|
31
|
+
* @return {Promise<ContainerInfo>}
|
32
|
+
*/
|
33
|
+
ensureResource(systemId: string, resourceType: string, version: string): Promise<ContainerInfo>;
|
34
|
+
}
|
35
|
+
export declare const operatorManager: OperatorManager;
|
36
|
+
export {};
|
@@ -0,0 +1,165 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.operatorManager = void 0;
|
7
|
+
const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
|
8
|
+
const path_1 = __importDefault(require("path"));
|
9
|
+
const md5_1 = __importDefault(require("md5"));
|
10
|
+
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
11
|
+
const serviceManager_1 = require("./serviceManager");
|
12
|
+
const storageService_1 = require("./storageService");
|
13
|
+
const containerManager_1 = require("./containerManager");
|
14
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
15
|
+
const KIND_OPERATOR = 'core/resource-type-operator';
|
16
|
+
class Operator {
|
17
|
+
_data;
|
18
|
+
constructor(data) {
|
19
|
+
this._data = data;
|
20
|
+
}
|
21
|
+
getData() {
|
22
|
+
return this._data;
|
23
|
+
}
|
24
|
+
getCredentials() {
|
25
|
+
return this._data.credentials;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
class OperatorManager {
|
29
|
+
_mountDir;
|
30
|
+
constructor() {
|
31
|
+
this._mountDir = path_1.default.join(storageService_1.storageService.getKapetaBasedir(), 'mounts');
|
32
|
+
fs_extra_1.default.mkdirpSync(this._mountDir);
|
33
|
+
}
|
34
|
+
_getMountPoint(operatorType, mountName) {
|
35
|
+
return path_1.default.join(this._mountDir, operatorType, mountName);
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Get operator definition for resource type
|
39
|
+
*
|
40
|
+
* @param {string} resourceType
|
41
|
+
* @param {string} version
|
42
|
+
* @return {Operator}
|
43
|
+
*/
|
44
|
+
getOperator(resourceType, version) {
|
45
|
+
const operators = local_cluster_config_1.default.getDefinitions(KIND_OPERATOR);
|
46
|
+
const operator = operators.find((operator) => operator.definition &&
|
47
|
+
operator.definition.metadata &&
|
48
|
+
operator.definition.metadata.name &&
|
49
|
+
operator.definition.metadata.name.toLowerCase() === resourceType.toLowerCase() &&
|
50
|
+
operator.version === version);
|
51
|
+
if (!operator) {
|
52
|
+
throw new Error(`Unknown resource type: ${resourceType}:${version}`);
|
53
|
+
}
|
54
|
+
if (!operator.definition.spec || !operator.definition.spec.local) {
|
55
|
+
throw new Error(`Operator missing local definition: ${resourceType}:${version}`);
|
56
|
+
}
|
57
|
+
return new Operator(operator.definition.spec.local);
|
58
|
+
}
|
59
|
+
/**
|
60
|
+
* Get information about a specific consumed resource
|
61
|
+
*/
|
62
|
+
async getConsumerResourceInfo(systemId, fromServiceId, resourceType, portType, name, environment) {
|
63
|
+
const plans = local_cluster_config_1.default.getDefinitions('core/plan');
|
64
|
+
const planUri = (0, nodejs_utils_1.parseKapetaUri)(systemId);
|
65
|
+
const currentPlan = plans.find((plan) => plan.definition.metadata.name === planUri.fullName && plan.version === planUri.version);
|
66
|
+
if (!currentPlan) {
|
67
|
+
throw new Error(`Unknown plan: ${systemId}`);
|
68
|
+
}
|
69
|
+
const currentInstance = currentPlan.definition.spec.blocks?.find((instance) => instance.id === fromServiceId);
|
70
|
+
if (!currentInstance) {
|
71
|
+
throw new Error(`Unknown instance: ${fromServiceId} in plan ${systemId}`);
|
72
|
+
}
|
73
|
+
const blockUri = (0, nodejs_utils_1.parseKapetaUri)(currentInstance.block.ref);
|
74
|
+
const blockDefinition = local_cluster_config_1.default.getDefinitions().find((definition) => definition.version === blockUri.version && definition.definition.metadata.name === blockUri.fullName);
|
75
|
+
if (!blockDefinition) {
|
76
|
+
throw new Error(`Unknown block: ${currentInstance.block.ref} in plan ${systemId}`);
|
77
|
+
}
|
78
|
+
const blockResource = blockDefinition.definition.spec?.consumers?.find((resource) => resource.metadata.name === name);
|
79
|
+
if (!blockResource) {
|
80
|
+
throw new Error(`Unknown resource: ${name} in block ${currentInstance.block.ref} in plan ${systemId}`);
|
81
|
+
}
|
82
|
+
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(blockResource.kind);
|
83
|
+
const operator = this.getOperator(resourceType, kindUri.version);
|
84
|
+
const credentials = operator.getCredentials();
|
85
|
+
const container = await this.ensureResource(systemId, resourceType, kindUri.version);
|
86
|
+
const portInfo = await container.getPort(portType);
|
87
|
+
if (!portInfo) {
|
88
|
+
throw new Error('Unknown resource port type : ' + resourceType + '#' + portType);
|
89
|
+
}
|
90
|
+
const dbName = name + '_' + fromServiceId.replace(/[^a-z0-9]/gi, '');
|
91
|
+
return {
|
92
|
+
host: environment === 'docker' ? 'host.docker.internal' : '127.0.0.1',
|
93
|
+
port: portInfo.hostPort,
|
94
|
+
type: portType,
|
95
|
+
protocol: portInfo.protocol,
|
96
|
+
options: {
|
97
|
+
dbName,
|
98
|
+
},
|
99
|
+
credentials,
|
100
|
+
};
|
101
|
+
}
|
102
|
+
/**
|
103
|
+
* Ensure we have a running operator of given type
|
104
|
+
*
|
105
|
+
* @param {string} systemId
|
106
|
+
* @param {string} resourceType
|
107
|
+
* @param {string} version
|
108
|
+
* @return {Promise<ContainerInfo>}
|
109
|
+
*/
|
110
|
+
async ensureResource(systemId, resourceType, version) {
|
111
|
+
const operator = this.getOperator(resourceType, version);
|
112
|
+
const operatorData = operator.getData();
|
113
|
+
const portTypes = Object.keys(operatorData.ports);
|
114
|
+
portTypes.sort();
|
115
|
+
const containerBaseName = 'kapeta-resource';
|
116
|
+
const nameParts = [resourceType.toLowerCase()];
|
117
|
+
const ports = {};
|
118
|
+
for (let i = 0; i < portTypes.length; i++) {
|
119
|
+
const portType = portTypes[i];
|
120
|
+
let containerPortInfo = operatorData.ports[portType];
|
121
|
+
const hostPort = await serviceManager_1.serviceManager.ensureServicePort(resourceType, portType);
|
122
|
+
if (typeof containerPortInfo === 'number' || typeof containerPortInfo === 'string') {
|
123
|
+
containerPortInfo = { port: containerPortInfo, type: 'tcp' };
|
124
|
+
}
|
125
|
+
if (!containerPortInfo.type) {
|
126
|
+
containerPortInfo.type = 'tcp';
|
127
|
+
}
|
128
|
+
const portId = containerPortInfo.port + '/' + containerPortInfo.type;
|
129
|
+
nameParts.push(portType + '-' + portId + '-' + hostPort);
|
130
|
+
ports[portId] = {
|
131
|
+
type: portType,
|
132
|
+
hostPort,
|
133
|
+
};
|
134
|
+
}
|
135
|
+
const mounts = containerManager_1.containerManager.createMounts(resourceType, operatorData.mounts);
|
136
|
+
const containerName = containerBaseName + '-' + (0, md5_1.default)(nameParts.join('_'));
|
137
|
+
let container = await containerManager_1.containerManager.get(containerName);
|
138
|
+
const isRunning = container ? await container.isRunning() : false;
|
139
|
+
if (container && !isRunning) {
|
140
|
+
await container.start();
|
141
|
+
}
|
142
|
+
if (!container) {
|
143
|
+
container = await containerManager_1.containerManager.run(operatorData.image, containerName, {
|
144
|
+
mounts,
|
145
|
+
ports,
|
146
|
+
health: operatorData.health,
|
147
|
+
env: operatorData.env,
|
148
|
+
cmd: operatorData.cmd,
|
149
|
+
});
|
150
|
+
}
|
151
|
+
try {
|
152
|
+
if (operatorData.health) {
|
153
|
+
await containerManager_1.containerManager.waitForHealthy(container.native);
|
154
|
+
}
|
155
|
+
else {
|
156
|
+
await containerManager_1.containerManager.waitForReady(container.native);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
catch (e) {
|
160
|
+
console.error(e.message);
|
161
|
+
}
|
162
|
+
return container;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
exports.operatorManager = new OperatorManager();
|
@@ -0,0 +1,20 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import { SocketManager } from './socketManager';
|
3
|
+
declare class ProgressListener {
|
4
|
+
private socketManager;
|
5
|
+
constructor(socketManager: SocketManager);
|
6
|
+
run(command: string, directory?: string): Promise<{
|
7
|
+
exit: number;
|
8
|
+
signal: NodeJS.Signals | null;
|
9
|
+
}>;
|
10
|
+
progress(label: string, callback: () => void | Promise<void>): Promise<void>;
|
11
|
+
check(message: string, ok: boolean | Promise<boolean> | (() => Promise<boolean>)): Promise<void>;
|
12
|
+
start(label: string): void;
|
13
|
+
showValue(label: string, value: any): void;
|
14
|
+
error(msg: string, ...args: any[]): void;
|
15
|
+
warn(msg: string, ...args: any[]): void;
|
16
|
+
info(msg: string, ...args: any[]): void;
|
17
|
+
debug(msg: string, ...args: any[]): void;
|
18
|
+
}
|
19
|
+
export declare const progressListener: ProgressListener;
|
20
|
+
export {};
|
@@ -0,0 +1,91 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.progressListener = void 0;
|
4
|
+
const child_process_1 = require("child_process");
|
5
|
+
const socketManager_1 = require("./socketManager");
|
6
|
+
class ProgressListener {
|
7
|
+
socketManager;
|
8
|
+
constructor(socketManager) {
|
9
|
+
this.socketManager = socketManager;
|
10
|
+
}
|
11
|
+
run(command, directory) {
|
12
|
+
this.socketManager.emit(`install`, 'install:log', {
|
13
|
+
type: 'info',
|
14
|
+
message: `Running command "${command}"`,
|
15
|
+
});
|
16
|
+
return new Promise((resolve, reject) => {
|
17
|
+
const child = (0, child_process_1.spawn)(command, {
|
18
|
+
cwd: directory ? directory : process.cwd(),
|
19
|
+
detached: true,
|
20
|
+
shell: true,
|
21
|
+
});
|
22
|
+
child.stdout.on('data', (data) => {
|
23
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: data.toString() });
|
24
|
+
});
|
25
|
+
child.stderr.on('data', (data) => {
|
26
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: data.toString() });
|
27
|
+
});
|
28
|
+
child.on('exit', (exit, signal) => {
|
29
|
+
if (exit !== 0) {
|
30
|
+
this.socketManager.emit(`install`, 'install:log', {
|
31
|
+
type: 'info',
|
32
|
+
message: `"${command}" failed: "${exit}"`,
|
33
|
+
});
|
34
|
+
reject(new Error(`Command "${command}" exited with code ${exit}`));
|
35
|
+
}
|
36
|
+
else {
|
37
|
+
this.socketManager.emit(`install`, 'install:log', {
|
38
|
+
type: 'info',
|
39
|
+
message: `Command OK: "${command}"`,
|
40
|
+
});
|
41
|
+
resolve({ exit, signal });
|
42
|
+
}
|
43
|
+
});
|
44
|
+
child.on('error', (err) => {
|
45
|
+
this.socketManager.emit(`install`, 'install:log', {
|
46
|
+
type: 'info',
|
47
|
+
message: `"${command}" failed: "${err.message}"`,
|
48
|
+
});
|
49
|
+
reject(err);
|
50
|
+
});
|
51
|
+
});
|
52
|
+
}
|
53
|
+
async progress(label, callback) {
|
54
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: `${label}: started` });
|
55
|
+
try {
|
56
|
+
const result = await callback();
|
57
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: `${label}: done` });
|
58
|
+
return result;
|
59
|
+
}
|
60
|
+
catch (e) {
|
61
|
+
this.socketManager.emit(`install`, 'install:log', {
|
62
|
+
type: 'info',
|
63
|
+
message: `${label}: failed. ${e.message}`,
|
64
|
+
});
|
65
|
+
throw e;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
async check(message, ok) {
|
69
|
+
const wasOk = await ok;
|
70
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: `${message}: ${wasOk}` });
|
71
|
+
}
|
72
|
+
start(label) {
|
73
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: label });
|
74
|
+
}
|
75
|
+
showValue(label, value) {
|
76
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: `${label}: ${value}` });
|
77
|
+
}
|
78
|
+
error(msg, ...args) {
|
79
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'error', message: msg });
|
80
|
+
}
|
81
|
+
warn(msg, ...args) {
|
82
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'warn', message: msg });
|
83
|
+
}
|
84
|
+
info(msg, ...args) {
|
85
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'info', message: msg });
|
86
|
+
}
|
87
|
+
debug(msg, ...args) {
|
88
|
+
this.socketManager.emit(`install`, 'install:log', { type: 'debug', message: msg });
|
89
|
+
}
|
90
|
+
}
|
91
|
+
exports.progressListener = new ProgressListener(socketManager_1.socketManager);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
declare class ProviderManager {
|
3
|
+
private _webAssetCache;
|
4
|
+
constructor();
|
5
|
+
getWebProviders(): import("@kapeta/local-cluster-config").DefinitionInfo[];
|
6
|
+
getAsset(handle: string, name: string, version: string, sourceMap?: boolean): Promise<string | Buffer | null>;
|
7
|
+
}
|
8
|
+
export declare const providerManager: ProviderManager;
|
9
|
+
export {};
|
@@ -0,0 +1,51 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.providerManager = void 0;
|
7
|
+
const path_1 = __importDefault(require("path"));
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
9
|
+
const repositoryManager_1 = require("./repositoryManager");
|
10
|
+
const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
|
11
|
+
class ProviderManager {
|
12
|
+
_webAssetCache;
|
13
|
+
constructor() {
|
14
|
+
this._webAssetCache = {};
|
15
|
+
}
|
16
|
+
getWebProviders() {
|
17
|
+
return local_cluster_config_1.default.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
|
18
|
+
}
|
19
|
+
async getAsset(handle, name, version, sourceMap = false) {
|
20
|
+
const fullName = `${handle}/${name}`;
|
21
|
+
const id = `${handle}/${name}/${version}/web.js${sourceMap ? '.map' : ''}`;
|
22
|
+
if (this._webAssetCache[id] && (await fs_extra_1.default.pathExists(this._webAssetCache[id]))) {
|
23
|
+
return fs_extra_1.default.readFile(this._webAssetCache[id], 'utf8');
|
24
|
+
}
|
25
|
+
await repositoryManager_1.repositoryManager.ensureAsset(handle, name, version);
|
26
|
+
const installedProvider = this.getWebProviders().find((providerDefinition) => {
|
27
|
+
return providerDefinition.definition.metadata.name === fullName && providerDefinition.version === version;
|
28
|
+
});
|
29
|
+
if (installedProvider) {
|
30
|
+
//Check locally installed providers
|
31
|
+
const path = path_1.default.join(installedProvider.path, 'web', handle, `${name}.js${sourceMap ? '.map' : ''}`);
|
32
|
+
if (await fs_extra_1.default.pathExists(path)) {
|
33
|
+
this._webAssetCache[id] = path;
|
34
|
+
return fs_extra_1.default.readFile(path);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
return null;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
const providerDefinitions = local_cluster_config_1.default.getProviderDefinitions();
|
41
|
+
if (providerDefinitions.length > 0) {
|
42
|
+
console.log('## Loaded the following providers ##');
|
43
|
+
providerDefinitions.forEach((providerDefinition) => {
|
44
|
+
console.log(' - %s[%s:%s]', providerDefinition.definition.kind, providerDefinition.definition.metadata.name, providerDefinition.version);
|
45
|
+
console.log(' from %s', providerDefinition.path);
|
46
|
+
});
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
console.log('## No providers found ##');
|
50
|
+
}
|
51
|
+
exports.providerManager = new ProviderManager();
|
@@ -0,0 +1,42 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const express_promise_router_1 = __importDefault(require("express-promise-router"));
|
7
|
+
const providerManager_1 = require("../providerManager");
|
8
|
+
const cors_1 = require("../middleware/cors");
|
9
|
+
const router = (0, express_promise_router_1.default)();
|
10
|
+
router.use('/', cors_1.corsHandler);
|
11
|
+
router.get('/', async (req, res) => {
|
12
|
+
const result = await providerManager_1.providerManager.getWebProviders();
|
13
|
+
res.send(result);
|
14
|
+
});
|
15
|
+
router.get('/asset/:handle/:name/:version/web.js', async (req, res) => {
|
16
|
+
const { handle, name, version } = req.params;
|
17
|
+
let result = await providerManager_1.providerManager.getAsset(handle, name, version);
|
18
|
+
if (!result) {
|
19
|
+
res.status(404).send('');
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
if (version !== 'local') {
|
23
|
+
res.setHeader('Cache-Control', 'max-age=31536000, immutable');
|
24
|
+
}
|
25
|
+
res.send(result.toString().replace(`${name}.js.map`, 'web.js.map'));
|
26
|
+
}
|
27
|
+
});
|
28
|
+
router.get('/asset/:handle/:name/:version/web.js.map', async (req, res) => {
|
29
|
+
const { handle, name, version } = req.params;
|
30
|
+
const result = await providerManager_1.providerManager.getAsset(handle, name, version, true);
|
31
|
+
if (!result) {
|
32
|
+
res.status(404).send('');
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
// Only cache successful requests
|
36
|
+
if (version !== 'local') {
|
37
|
+
res.setHeader('Cache-Control', 'max-age=31536000, immutable');
|
38
|
+
}
|
39
|
+
res.send(result);
|
40
|
+
}
|
41
|
+
});
|
42
|
+
exports.default = router;
|
@@ -0,0 +1,111 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const express_promise_router_1 = __importDefault(require("express-promise-router"));
|
7
|
+
const rest_1 = require("./types/rest");
|
8
|
+
const web_1 = require("./types/web");
|
9
|
+
const stringBody_1 = require("../middleware/stringBody");
|
10
|
+
const serviceManager_1 = require("../serviceManager");
|
11
|
+
const clusterService_1 = require("../clusterService");
|
12
|
+
const assetManager_1 = require("../assetManager");
|
13
|
+
const lodash_1 = __importDefault(require("lodash"));
|
14
|
+
const router = (0, express_promise_router_1.default)();
|
15
|
+
/**
|
16
|
+
* @var {{[key:string]:ProxyRequestHandler}}
|
17
|
+
*/
|
18
|
+
const TYPE_HANDLERS = {
|
19
|
+
rest: rest_1.proxyRestRequest,
|
20
|
+
web: web_1.proxyWebRequest,
|
21
|
+
};
|
22
|
+
function getResource(resources, resourceName) {
|
23
|
+
return resources.find((resource) => {
|
24
|
+
return resource.metadata.name.toLowerCase() === resourceName.toLowerCase();
|
25
|
+
});
|
26
|
+
}
|
27
|
+
router.use('/:systemId/:consumerInstanceId/:consumerResourceName', stringBody_1.stringBody);
|
28
|
+
router.all('/:systemId/:consumerInstanceId/:consumerResourceName/:type/*', async (req, res) => {
|
29
|
+
try {
|
30
|
+
const typeHandler = TYPE_HANDLERS[req.params.type.toLowerCase()];
|
31
|
+
if (!typeHandler) {
|
32
|
+
res.status(401).send({ error: 'Unknown connection type: ' + req.params.type });
|
33
|
+
return;
|
34
|
+
}
|
35
|
+
const plan = await assetManager_1.assetManager.getPlan(req.params.systemId);
|
36
|
+
// We can find the connection by the consumer information alone since
|
37
|
+
// only 1 provider can be connected to a consumer resource at a time
|
38
|
+
const connection = lodash_1.default.find(plan.spec.connections, (connection) => {
|
39
|
+
return (connection.consumer.blockId.toLowerCase() === req.params.consumerInstanceId.toLowerCase() &&
|
40
|
+
connection.consumer.resourceName.toLowerCase() === req.params.consumerResourceName.toLowerCase());
|
41
|
+
});
|
42
|
+
if (!connection) {
|
43
|
+
res.status(401).send({
|
44
|
+
error: `No connection found for consumer "${req.params.consumerInstanceId}::${req.params.consumerResourceName}"`,
|
45
|
+
});
|
46
|
+
return;
|
47
|
+
}
|
48
|
+
const toBlockInstance = lodash_1.default.find(plan.spec.blocks, (blockInstance) => {
|
49
|
+
return blockInstance.id.toLowerCase() === connection.consumer.blockId.toLowerCase();
|
50
|
+
});
|
51
|
+
if (!toBlockInstance) {
|
52
|
+
res.status(401).send({ error: `Block instance not found "${req.params.consumerInstanceId}` });
|
53
|
+
return;
|
54
|
+
}
|
55
|
+
const toBlockAsset = await assetManager_1.assetManager.getAsset(toBlockInstance.block.ref);
|
56
|
+
if (!toBlockAsset) {
|
57
|
+
res.status(401).send({ error: `Block asset not found "${toBlockInstance.block.ref}` });
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
const consumerResource = getResource(toBlockAsset.data.spec.consumers, req.params.consumerResourceName);
|
61
|
+
if (!consumerResource) {
|
62
|
+
res.status(401).send({
|
63
|
+
error: `Block resource not found "${req.params.consumerInstanceId}::${req.params.consumerResourceName}`,
|
64
|
+
});
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
const basePath = clusterService_1.clusterService.getProxyPath(req.params.systemId, req.params.consumerInstanceId, req.params.consumerResourceName, req.params.type);
|
68
|
+
const fromBlockInstance = lodash_1.default.find(plan.spec.blocks, (blockInstance) => {
|
69
|
+
return blockInstance.id.toLowerCase() === connection.provider.blockId.toLowerCase();
|
70
|
+
});
|
71
|
+
if (!fromBlockInstance) {
|
72
|
+
res.status(401).send({ error: `Block instance not found "${connection.provider.blockId}` });
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
const fromBlockAsset = await assetManager_1.assetManager.getAsset(fromBlockInstance.block.ref);
|
76
|
+
if (!fromBlockAsset) {
|
77
|
+
res.status(401).send({ error: `Block asset not found "${fromBlockInstance.block.ref}` });
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
const providerResource = getResource(fromBlockAsset.data.spec.providers, connection.provider.resourceName);
|
81
|
+
if (!providerResource) {
|
82
|
+
res.status(401).send({
|
83
|
+
error: `Block resource not found "${connection.provider.blockId}::${connection.provider.resourceName}`,
|
84
|
+
});
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
//Get target address
|
88
|
+
let address = await serviceManager_1.serviceManager.getProviderAddress(req.params.systemId, connection.provider.blockId, req.params.type);
|
89
|
+
while (address.endsWith('/')) {
|
90
|
+
address = address.substring(0, address.length - 1);
|
91
|
+
}
|
92
|
+
/*
|
93
|
+
Get the path the consumer requested.
|
94
|
+
Note that this might not match the path the destination is expecting so we need to identify the method
|
95
|
+
that is being called and identify the destination path from the connection.
|
96
|
+
*/
|
97
|
+
const consumerPath = req.originalUrl.substring(basePath.length - 1);
|
98
|
+
typeHandler(req, res, {
|
99
|
+
consumerPath,
|
100
|
+
address,
|
101
|
+
consumerResource,
|
102
|
+
providerResource,
|
103
|
+
connection,
|
104
|
+
});
|
105
|
+
}
|
106
|
+
catch (err) {
|
107
|
+
console.warn('Failed to process proxy request', err);
|
108
|
+
res.status(400).send({ error: err.message });
|
109
|
+
}
|
110
|
+
});
|
111
|
+
exports.default = router;
|