@kapeta/local-cluster-service 0.6.0 → 0.7.0
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 +215 -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/dist/esm/src/config/routes.js +121 -0
- 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 +94 -175
- 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 +209 -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} +45 -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/config/routes.js +0 -160
- 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,19 @@
|
|
1
|
+
import { LogEntry, LogLevel, LogSource } from '../types';
|
2
|
+
export declare class LogData {
|
3
|
+
static readonly MAX_LINES = 1000;
|
4
|
+
private readonly entries;
|
5
|
+
constructor();
|
6
|
+
/**
|
7
|
+
*
|
8
|
+
* @param {string} msg
|
9
|
+
* @param {string} [level]
|
10
|
+
* @param {string} [source]
|
11
|
+
*/
|
12
|
+
addLog(msg: string, level?: LogLevel, source?: LogSource): void;
|
13
|
+
/**
|
14
|
+
*
|
15
|
+
* @return {LogEntry[]}
|
16
|
+
*/
|
17
|
+
getLogs(): LogEntry[];
|
18
|
+
toString(): string;
|
19
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.LogData = void 0;
|
4
|
+
const MAX_LINES = 1000;
|
5
|
+
class LogData {
|
6
|
+
static MAX_LINES = MAX_LINES;
|
7
|
+
entries = [];
|
8
|
+
constructor() { }
|
9
|
+
/**
|
10
|
+
*
|
11
|
+
* @param {string} msg
|
12
|
+
* @param {string} [level]
|
13
|
+
* @param {string} [source]
|
14
|
+
*/
|
15
|
+
addLog(msg, level = 'INFO', source = 'stdout') {
|
16
|
+
while (this.entries.length > MAX_LINES) {
|
17
|
+
this.entries.shift();
|
18
|
+
}
|
19
|
+
if (!msg.endsWith('\n')) {
|
20
|
+
msg += '\n';
|
21
|
+
}
|
22
|
+
this.entries.push({
|
23
|
+
time: Date.now(),
|
24
|
+
message: msg,
|
25
|
+
level,
|
26
|
+
source,
|
27
|
+
});
|
28
|
+
}
|
29
|
+
/**
|
30
|
+
*
|
31
|
+
* @return {LogEntry[]}
|
32
|
+
*/
|
33
|
+
getLogs() {
|
34
|
+
return this.entries;
|
35
|
+
}
|
36
|
+
toString() {
|
37
|
+
return this.getLogs()
|
38
|
+
.map((entry) => entry.message)
|
39
|
+
.join('\n');
|
40
|
+
}
|
41
|
+
}
|
42
|
+
exports.LogData = LogData;
|
43
|
+
module.exports = LogData;
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { StringMap } from '../types';
|
2
|
+
/**
|
3
|
+
* A path template is a string that can be used to match a path and extract variables from it.
|
4
|
+
*
|
5
|
+
* E.g. /foo/{bar}/baz
|
6
|
+
*
|
7
|
+
* Would match /foo/123/baz and extract bar=123
|
8
|
+
*
|
9
|
+
* You can also specify a regex for the variable:
|
10
|
+
* /foo/{bar:[0-9]+}/baz
|
11
|
+
*
|
12
|
+
*/
|
13
|
+
export declare class PathTemplate {
|
14
|
+
private _path;
|
15
|
+
private _parts;
|
16
|
+
constructor(pathTemplate: string);
|
17
|
+
get path(): string;
|
18
|
+
matches(path: string): boolean;
|
19
|
+
parse(path: string): StringMap | null;
|
20
|
+
create(variables: StringMap): string;
|
21
|
+
toString(): string;
|
22
|
+
}
|
23
|
+
/**
|
24
|
+
* Parses a path into a RESTPath
|
25
|
+
*/
|
26
|
+
export declare function pathTemplateParser(path: string): PathTemplate;
|
@@ -0,0 +1,121 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.pathTemplateParser = exports.PathTemplate = void 0;
|
4
|
+
const TYPE_VARIABLE = 'variable';
|
5
|
+
const TYPE_PATH = 'path';
|
6
|
+
/**
|
7
|
+
* A path template is a string that can be used to match a path and extract variables from it.
|
8
|
+
*
|
9
|
+
* E.g. /foo/{bar}/baz
|
10
|
+
*
|
11
|
+
* Would match /foo/123/baz and extract bar=123
|
12
|
+
*
|
13
|
+
* You can also specify a regex for the variable:
|
14
|
+
* /foo/{bar:[0-9]+}/baz
|
15
|
+
*
|
16
|
+
*/
|
17
|
+
class PathTemplate {
|
18
|
+
_path;
|
19
|
+
_parts = [];
|
20
|
+
constructor(pathTemplate) {
|
21
|
+
if (!pathTemplate.startsWith('/')) {
|
22
|
+
pathTemplate = '/' + pathTemplate;
|
23
|
+
}
|
24
|
+
this._path = pathTemplate;
|
25
|
+
const variableRegex = /{([^}]+)}/g;
|
26
|
+
let match, offset = 0;
|
27
|
+
this._parts = [];
|
28
|
+
while ((match = variableRegex.exec(pathTemplate)) !== null) {
|
29
|
+
if (match.index > offset) {
|
30
|
+
this._parts.push({
|
31
|
+
type: TYPE_PATH,
|
32
|
+
value: pathTemplate.substring(offset, match.index),
|
33
|
+
});
|
34
|
+
}
|
35
|
+
let regex;
|
36
|
+
let value = match[1];
|
37
|
+
[value, regex] = value.split(/:/, 2);
|
38
|
+
if (regex) {
|
39
|
+
regex = new RegExp('^' + regex);
|
40
|
+
}
|
41
|
+
else {
|
42
|
+
regex = /^[^\/]+/;
|
43
|
+
}
|
44
|
+
this._parts.push({
|
45
|
+
type: TYPE_VARIABLE,
|
46
|
+
value,
|
47
|
+
regex,
|
48
|
+
});
|
49
|
+
offset = match.index + match[0].length;
|
50
|
+
}
|
51
|
+
if (offset < pathTemplate.length) {
|
52
|
+
this._parts.push({
|
53
|
+
type: TYPE_PATH,
|
54
|
+
value: pathTemplate.substring(offset),
|
55
|
+
});
|
56
|
+
}
|
57
|
+
}
|
58
|
+
get path() {
|
59
|
+
return this._path;
|
60
|
+
}
|
61
|
+
matches(path) {
|
62
|
+
return this.parse(path) !== null;
|
63
|
+
}
|
64
|
+
parse(path) {
|
65
|
+
if (!path.startsWith('/')) {
|
66
|
+
path = '/' + path;
|
67
|
+
}
|
68
|
+
const values = {};
|
69
|
+
for (let i = 0; i < this._parts.length; i++) {
|
70
|
+
const part = this._parts[i];
|
71
|
+
switch (part.type) {
|
72
|
+
case TYPE_PATH:
|
73
|
+
if (!path.startsWith(part.value)) {
|
74
|
+
return null;
|
75
|
+
}
|
76
|
+
path = path.substring(part.value.length);
|
77
|
+
break;
|
78
|
+
case TYPE_VARIABLE:
|
79
|
+
if (!part.regex?.test(path)) {
|
80
|
+
return null;
|
81
|
+
}
|
82
|
+
const newPath = path.replace(part.regex, '');
|
83
|
+
const value = path.substr(0, path.length - newPath.length);
|
84
|
+
values[part.value] = value;
|
85
|
+
path = newPath;
|
86
|
+
break;
|
87
|
+
}
|
88
|
+
}
|
89
|
+
if (path && path !== '/') {
|
90
|
+
//We did not match all of it
|
91
|
+
return null;
|
92
|
+
}
|
93
|
+
return values;
|
94
|
+
}
|
95
|
+
create(variables) {
|
96
|
+
return this._parts
|
97
|
+
.map((part) => {
|
98
|
+
switch (part.type) {
|
99
|
+
case TYPE_PATH:
|
100
|
+
return part.value;
|
101
|
+
case TYPE_VARIABLE:
|
102
|
+
if (variables[part.value] === undefined || variables[part.value] === null) {
|
103
|
+
return '';
|
104
|
+
}
|
105
|
+
return variables[part.value];
|
106
|
+
}
|
107
|
+
})
|
108
|
+
.join('');
|
109
|
+
}
|
110
|
+
toString() {
|
111
|
+
return 'tmpl: ' + this.path;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
exports.PathTemplate = PathTemplate;
|
115
|
+
/**
|
116
|
+
* Parses a path into a RESTPath
|
117
|
+
*/
|
118
|
+
function pathTemplateParser(path) {
|
119
|
+
return new PathTemplate(path);
|
120
|
+
}
|
121
|
+
exports.pathTemplateParser = pathTemplateParser;
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function readYML(path: string): any;
|
@@ -0,0 +1,18 @@
|
|
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.readYML = void 0;
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
8
|
+
const yaml_1 = __importDefault(require("yaml"));
|
9
|
+
function readYML(path) {
|
10
|
+
const rawYaml = node_fs_1.default.readFileSync(path);
|
11
|
+
try {
|
12
|
+
return yaml_1.default.parse(rawYaml.toString());
|
13
|
+
}
|
14
|
+
catch (err) {
|
15
|
+
throw new Error('Failed to parse plan YAML: ' + err);
|
16
|
+
}
|
17
|
+
}
|
18
|
+
exports.readYML = readYML;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,12 @@
|
|
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 index_1 = __importDefault(require("./index"));
|
7
|
+
index_1.default
|
8
|
+
.start()
|
9
|
+
.then(({ host, port }) => console.log('Listening on port %s:%s', host, port))
|
10
|
+
.catch((e) => {
|
11
|
+
console.error('Failed to start local cluster due to an error:\n\t - %s', e.toString());
|
12
|
+
});
|
@@ -0,0 +1,27 @@
|
|
1
|
+
/// <reference types="node" />
|
2
|
+
import HTTP from 'http';
|
3
|
+
export type LocalClusterService = HTTP.Server & {
|
4
|
+
host?: string;
|
5
|
+
port?: number;
|
6
|
+
};
|
7
|
+
export type StartResult = {
|
8
|
+
host: string;
|
9
|
+
port: number;
|
10
|
+
dockerStatus: boolean;
|
11
|
+
};
|
12
|
+
declare const _default: {
|
13
|
+
isRunning: () => boolean;
|
14
|
+
getCurrentPort: () => number | undefined;
|
15
|
+
/**
|
16
|
+
* Starts the local cluster service.
|
17
|
+
* resolves when listening is done with port number. Rejects if listening failed.
|
18
|
+
*/
|
19
|
+
start: () => Promise<StartResult>;
|
20
|
+
/**
|
21
|
+
* Stops any currently running cluster services.
|
22
|
+
* @return {Promise<boolean>} Returns true if the service was stopped - false if no service was running.
|
23
|
+
*/
|
24
|
+
stop: () => Promise<unknown>;
|
25
|
+
getServices: () => any;
|
26
|
+
};
|
27
|
+
export default _default;
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import { clusterService } from './src/clusterService';
|
2
|
+
import { storageService } from './src/storageService';
|
3
|
+
import { serviceManager } from './src/serviceManager';
|
4
|
+
import { socketManager } from './src/socketManager';
|
5
|
+
import { containerManager } from './src/containerManager';
|
6
|
+
import express from 'express';
|
7
|
+
import HTTP from 'http';
|
8
|
+
import { Server } from 'socket.io';
|
9
|
+
import TrafficRoutes from './src/traffic/routes';
|
10
|
+
import ProxyRoutes from './src/proxy/routes';
|
11
|
+
import ConfigRoutes from './src/config/routes';
|
12
|
+
import InstancesRoutes from './src/instances/routes';
|
13
|
+
import IdentitiesRoutes from './src/identities/routes';
|
14
|
+
import FilesystemRoutes from './src/filesystem/routes';
|
15
|
+
import AssetsRoutes from './src/assets/routes';
|
16
|
+
import ProviderRoutes from './src/providers/routes';
|
17
|
+
let currentServer = null;
|
18
|
+
function createServer() {
|
19
|
+
const app = express();
|
20
|
+
app.use('/traffic', TrafficRoutes);
|
21
|
+
app.use('/proxy', ProxyRoutes);
|
22
|
+
app.use('/config', ConfigRoutes);
|
23
|
+
app.use('/instances', InstancesRoutes);
|
24
|
+
app.use('/identities', IdentitiesRoutes);
|
25
|
+
app.use('/files', FilesystemRoutes);
|
26
|
+
app.use('/assets', AssetsRoutes);
|
27
|
+
app.use('/providers', ProviderRoutes);
|
28
|
+
app.use('/', (err, req, res) => {
|
29
|
+
console.error('Request failed: %s %s', req.method, req.originalUrl, err);
|
30
|
+
res.status(500).send({
|
31
|
+
ok: false,
|
32
|
+
error: err.error ?? err.message,
|
33
|
+
});
|
34
|
+
});
|
35
|
+
const server = HTTP.createServer(app);
|
36
|
+
//socket
|
37
|
+
const io = new Server(server, {
|
38
|
+
cors: {
|
39
|
+
//TODO: This should'nt be hardcoded but also shouldn't be "*"
|
40
|
+
origin: 'http://localhost:8080',
|
41
|
+
},
|
42
|
+
});
|
43
|
+
socketManager.setIo(io);
|
44
|
+
return server;
|
45
|
+
}
|
46
|
+
export default {
|
47
|
+
isRunning: function () {
|
48
|
+
return !!currentServer;
|
49
|
+
},
|
50
|
+
getCurrentPort: function () {
|
51
|
+
if (!currentServer) {
|
52
|
+
return -1;
|
53
|
+
}
|
54
|
+
return currentServer.port;
|
55
|
+
},
|
56
|
+
/**
|
57
|
+
* Starts the local cluster service.
|
58
|
+
* resolves when listening is done with port number. Rejects if listening failed.
|
59
|
+
*/
|
60
|
+
start: async function () {
|
61
|
+
if (currentServer) {
|
62
|
+
throw new Error('Server already started');
|
63
|
+
}
|
64
|
+
try {
|
65
|
+
await containerManager.initialize();
|
66
|
+
}
|
67
|
+
catch (e) {
|
68
|
+
console.error('Could not ping docker runtime: ' + e.toString() + '. Make sure docker is running and working.');
|
69
|
+
}
|
70
|
+
const clusterPort = storageService.get('cluster', 'port');
|
71
|
+
if (clusterPort) {
|
72
|
+
clusterService.setClusterServicePort(clusterPort);
|
73
|
+
}
|
74
|
+
const clusterHost = storageService.get('cluster', 'host');
|
75
|
+
if (clusterHost) {
|
76
|
+
clusterService.setClusterServiceHost(clusterHost);
|
77
|
+
}
|
78
|
+
await clusterService.init();
|
79
|
+
currentServer = createServer();
|
80
|
+
const port = clusterService.getClusterServicePort();
|
81
|
+
const host = clusterService.getClusterServiceHost();
|
82
|
+
if (clusterPort !== port) {
|
83
|
+
storageService.put('cluster', 'port', port);
|
84
|
+
}
|
85
|
+
if (clusterHost !== host) {
|
86
|
+
storageService.put('cluster', 'host', host);
|
87
|
+
}
|
88
|
+
return new Promise((resolve, reject) => {
|
89
|
+
if (!currentServer) {
|
90
|
+
reject(new Error(`Current server wasn't set`));
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
currentServer.once('error', (err) => {
|
94
|
+
if (currentServer) {
|
95
|
+
currentServer.close();
|
96
|
+
currentServer = null;
|
97
|
+
}
|
98
|
+
reject(err);
|
99
|
+
});
|
100
|
+
currentServer.listen(port, host, () => resolve({ host, port, dockerStatus: containerManager.isAlive() }));
|
101
|
+
currentServer.host = host;
|
102
|
+
currentServer.port = port;
|
103
|
+
});
|
104
|
+
},
|
105
|
+
/**
|
106
|
+
* Stops any currently running cluster services.
|
107
|
+
* @return {Promise<boolean>} Returns true if the service was stopped - false if no service was running.
|
108
|
+
*/
|
109
|
+
stop: function () {
|
110
|
+
if (currentServer) {
|
111
|
+
return new Promise(function (resolve) {
|
112
|
+
if (currentServer) {
|
113
|
+
currentServer.close(() => resolve(true));
|
114
|
+
currentServer = null;
|
115
|
+
}
|
116
|
+
});
|
117
|
+
}
|
118
|
+
return Promise.resolve(false);
|
119
|
+
},
|
120
|
+
getServices: () => serviceManager.getServices(),
|
121
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
{"type":"module"}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import { Definition } from '@kapeta/local-cluster-config';
|
2
|
+
import { BlockDefinition } from '@kapeta/schemas';
|
3
|
+
export interface EnrichedAsset {
|
4
|
+
ref: string;
|
5
|
+
editable: boolean;
|
6
|
+
exists: boolean;
|
7
|
+
version: string;
|
8
|
+
kind: string;
|
9
|
+
data: Definition;
|
10
|
+
path: string;
|
11
|
+
ymlPath: string;
|
12
|
+
}
|
13
|
+
declare class AssetManager {
|
14
|
+
private cache;
|
15
|
+
constructor();
|
16
|
+
/**
|
17
|
+
*
|
18
|
+
* @param {string[]} [assetKinds]
|
19
|
+
* @returns {{path: *, ref: string, data: *, editable: boolean, kind: *, exists: boolean}[]}
|
20
|
+
*/
|
21
|
+
getAssets(assetKinds?: string[]): EnrichedAsset[];
|
22
|
+
getPlans(): EnrichedAsset[];
|
23
|
+
getPlan(ref: string, noCache?: boolean): Promise<Definition>;
|
24
|
+
getAsset(ref: string, noCache?: boolean): Promise<EnrichedAsset | undefined>;
|
25
|
+
createAsset(path: string, yaml: BlockDefinition): Promise<EnrichedAsset[]>;
|
26
|
+
updateAsset(ref: string, yaml: BlockDefinition): Promise<void>;
|
27
|
+
importFile(filePath: string): Promise<EnrichedAsset[]>;
|
28
|
+
unregisterAsset(ref: string): Promise<void>;
|
29
|
+
}
|
30
|
+
export declare const assetManager: AssetManager;
|
31
|
+
export {};
|
@@ -1,19 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
import Path from 'node:path';
|
2
|
+
import FS from 'node:fs';
|
3
|
+
import FSExtra from 'fs-extra';
|
4
|
+
import YAML from 'yaml';
|
5
|
+
import NodeCache from 'node-cache';
|
6
|
+
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
7
|
+
import { codeGeneratorManager } from './codeGeneratorManager';
|
8
|
+
import { progressListener } from './progressListener';
|
9
|
+
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
10
|
+
import { repositoryManager } from './repositoryManager';
|
11
|
+
import { Actions } from '@kapeta/nodejs-registry-utils';
|
13
12
|
function enrichAsset(asset) {
|
14
13
|
return {
|
15
14
|
ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
|
16
|
-
editable: asset.version === 'local',
|
15
|
+
editable: asset.version === 'local',
|
17
16
|
exists: true,
|
18
17
|
version: asset.version,
|
19
18
|
kind: asset.definition.kind,
|
@@ -22,29 +21,25 @@ function enrichAsset(asset) {
|
|
22
21
|
ymlPath: asset.ymlPath,
|
23
22
|
};
|
24
23
|
}
|
25
|
-
|
26
24
|
function compareRefs(a, b) {
|
27
25
|
const [aProtocol, aId] = parseRef(a);
|
28
26
|
const [bProtocol, bId] = parseRef(b);
|
29
|
-
|
30
27
|
return aProtocol === bProtocol && aId === bId;
|
31
28
|
}
|
32
29
|
function parseRef(ref) {
|
33
30
|
let out = ref.split(/:\/\//, 2);
|
34
|
-
|
35
31
|
if (out.length === 1) {
|
36
32
|
return ['kapeta', ref.toLowerCase()];
|
37
33
|
}
|
38
34
|
return [out[0].toLowerCase(), out[1].toLowerCase()];
|
39
35
|
}
|
40
|
-
|
41
36
|
class AssetManager {
|
37
|
+
cache;
|
42
38
|
constructor() {
|
43
39
|
this.cache = new NodeCache({
|
44
40
|
stdTTL: 60 * 60, // 1 hour
|
45
41
|
});
|
46
42
|
}
|
47
|
-
|
48
43
|
/**
|
49
44
|
*
|
50
45
|
* @param {string[]} [assetKinds]
|
@@ -61,117 +56,85 @@ class AssetManager {
|
|
61
56
|
});
|
62
57
|
assetKinds.push('core/plan');
|
63
58
|
}
|
64
|
-
|
65
59
|
const assets = ClusterConfiguration.getDefinitions(assetKinds);
|
66
|
-
|
67
60
|
return assets.map(enrichAsset);
|
68
61
|
}
|
69
|
-
|
70
62
|
getPlans() {
|
71
63
|
return this.getAssets(['core/plan']);
|
72
64
|
}
|
73
|
-
|
74
65
|
async getPlan(ref, noCache = false) {
|
75
66
|
const asset = await this.getAsset(ref, noCache);
|
76
|
-
|
77
|
-
if ('core/plan' !== asset.kind) {
|
67
|
+
if ('core/plan' !== asset?.kind) {
|
78
68
|
throw new Error('Asset was not a plan: ' + ref);
|
79
69
|
}
|
80
|
-
|
81
70
|
return asset.data;
|
82
71
|
}
|
83
|
-
|
84
72
|
async getAsset(ref, noCache = false) {
|
85
73
|
const cacheKey = `getAsset:${ref}`;
|
86
|
-
if (noCache
|
74
|
+
if (!noCache && this.cache.has(cacheKey)) {
|
87
75
|
return this.cache.get(cacheKey);
|
88
76
|
}
|
89
77
|
const uri = parseKapetaUri(ref);
|
90
78
|
await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version);
|
91
|
-
|
92
79
|
let asset = ClusterConfiguration.getDefinitions()
|
93
80
|
.map(enrichAsset)
|
94
81
|
.find((a) => parseKapetaUri(a.ref).equals(uri));
|
95
|
-
|
96
82
|
if (!asset) {
|
97
83
|
throw new Error('Asset not found: ' + ref);
|
98
84
|
}
|
99
85
|
this.cache.set(cacheKey, asset);
|
100
86
|
return asset;
|
101
87
|
}
|
102
|
-
|
103
88
|
async createAsset(path, yaml) {
|
104
89
|
if (FS.existsSync(path)) {
|
105
90
|
throw new Error('File already exists: ' + path);
|
106
91
|
}
|
107
|
-
|
108
92
|
const dirName = Path.dirname(path);
|
109
93
|
if (!FS.existsSync(dirName)) {
|
110
94
|
FSExtra.mkdirpSync(dirName);
|
111
95
|
}
|
112
|
-
|
113
96
|
FS.writeFileSync(path, YAML.stringify(yaml));
|
114
|
-
|
115
97
|
const asset = await this.importFile(path);
|
116
|
-
|
117
98
|
if (codeGeneratorManager.canGenerateCode(yaml)) {
|
118
99
|
await codeGeneratorManager.generate(path, yaml);
|
119
100
|
}
|
120
101
|
this.cache.flushAll();
|
121
102
|
return asset;
|
122
103
|
}
|
123
|
-
|
124
104
|
async updateAsset(ref, yaml) {
|
125
105
|
const asset = await this.getAsset(ref, true);
|
126
106
|
if (!asset) {
|
127
107
|
throw new Error('Attempted to update unknown asset: ' + ref);
|
128
108
|
}
|
129
|
-
|
130
109
|
if (!asset.editable) {
|
131
110
|
throw new Error('Attempted to update read-only asset: ' + ref);
|
132
111
|
}
|
133
|
-
|
134
112
|
if (!asset.ymlPath) {
|
135
113
|
throw new Error('Attempted to update corrupted asset: ' + ref);
|
136
114
|
}
|
137
|
-
|
138
115
|
FS.writeFileSync(asset.ymlPath, YAML.stringify(yaml));
|
139
116
|
this.cache.flushAll();
|
140
117
|
if (codeGeneratorManager.canGenerateCode(yaml)) {
|
141
118
|
await codeGeneratorManager.generate(asset.ymlPath, yaml);
|
142
|
-
}
|
143
|
-
|
144
|
-
|
145
|
-
yaml.kind ? yaml.kind : 'unknown yaml'
|
146
|
-
);
|
119
|
+
}
|
120
|
+
else {
|
121
|
+
console.log('Could not generate code for %s', yaml.kind ? yaml.kind : 'unknown yaml');
|
147
122
|
}
|
148
123
|
}
|
149
|
-
|
150
124
|
async importFile(filePath) {
|
151
125
|
if (filePath.startsWith('file://')) {
|
152
126
|
filePath = filePath.substring('file://'.length);
|
153
127
|
}
|
154
|
-
|
155
128
|
if (!FS.existsSync(filePath)) {
|
156
129
|
throw new Error('File not found: ' + filePath);
|
157
130
|
}
|
158
|
-
|
159
|
-
const assetInfos = YAML.parseAllDocuments(
|
160
|
-
FS.readFileSync(filePath).toString()
|
161
|
-
).map((doc) => doc.toJSON());
|
162
|
-
|
131
|
+
const assetInfos = YAML.parseAllDocuments(FS.readFileSync(filePath).toString()).map((doc) => doc.toJSON());
|
163
132
|
await Actions.link(progressListener, Path.dirname(filePath));
|
164
|
-
|
165
133
|
const version = 'local';
|
166
|
-
const refs = assetInfos.map(
|
167
|
-
(assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`
|
168
|
-
);
|
134
|
+
const refs = assetInfos.map((assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`);
|
169
135
|
this.cache.flushAll();
|
170
|
-
return this.getAssets().filter((a) =>
|
171
|
-
refs.some((ref) => compareRefs(ref, a.ref))
|
172
|
-
);
|
136
|
+
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
173
137
|
}
|
174
|
-
|
175
138
|
async unregisterAsset(ref) {
|
176
139
|
const asset = await this.getAsset(ref, true);
|
177
140
|
if (!asset) {
|
@@ -181,5 +144,4 @@ class AssetManager {
|
|
181
144
|
await Actions.uninstall(progressListener, [asset.ref]);
|
182
145
|
}
|
183
146
|
}
|
184
|
-
|
185
|
-
module.exports = new AssetManager();
|
147
|
+
export const assetManager = new AssetManager();
|