@kapeta/local-cluster-service 0.16.8 → 0.17.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/CHANGELOG.md +13 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/src/socketManager.js +6 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.d.ts +11 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.js +129 -0
- package/dist/esm/index.js +64 -57
- package/dist/esm/src/RepositoryWatcher.js +40 -33
- package/dist/esm/src/api.js +14 -9
- package/dist/esm/src/assetManager.js +62 -56
- package/dist/esm/src/assets/routes.js +22 -17
- package/dist/esm/src/attachments/routes.js +14 -9
- package/dist/esm/src/cacheManager.js +13 -5
- package/dist/esm/src/clusterService.js +6 -3
- package/dist/esm/src/codeGeneratorManager.js +19 -13
- package/dist/esm/src/config/routes.js +30 -25
- package/dist/esm/src/configManager.js +29 -26
- package/dist/esm/src/containerManager.js +48 -39
- package/dist/esm/src/definitionsManager.js +15 -9
- package/dist/esm/src/filesystem/routes.js +21 -16
- package/dist/esm/src/filesystemManager.js +23 -17
- package/dist/esm/src/identities/routes.js +13 -8
- package/dist/esm/src/instanceManager.js +163 -156
- package/dist/esm/src/instances/routes.js +38 -33
- package/dist/esm/src/middleware/cors.js +5 -1
- package/dist/esm/src/middleware/kapeta.js +8 -4
- package/dist/esm/src/middleware/stringBody.js +5 -1
- package/dist/esm/src/networkManager.js +15 -9
- package/dist/esm/src/operatorManager.js +45 -39
- package/dist/esm/src/progressListener.js +16 -12
- package/dist/esm/src/providerManager.js +22 -16
- package/dist/esm/src/providers/routes.js +14 -9
- package/dist/esm/src/proxy/routes.js +26 -21
- package/dist/esm/src/proxy/types/rest.js +29 -22
- package/dist/esm/src/proxy/types/web.js +18 -11
- package/dist/esm/src/repositoryManager.js +28 -22
- package/dist/esm/src/serviceManager.js +25 -19
- package/dist/esm/src/socketManager.js +31 -18
- package/dist/esm/src/storageService.js +18 -12
- package/dist/esm/src/taskManager.js +12 -8
- package/dist/esm/src/tasks/routes.js +14 -9
- package/dist/esm/src/traffic/routes.js +12 -7
- package/dist/esm/src/types.js +11 -8
- package/dist/esm/src/utils/BlockInstanceRunner.js +57 -50
- package/dist/esm/src/utils/DefaultProviderInstaller.d.ts +11 -0
- package/dist/esm/src/utils/DefaultProviderInstaller.js +129 -0
- package/dist/esm/src/utils/LogData.js +5 -1
- package/dist/esm/src/utils/commandLineUtils.js +12 -7
- package/dist/esm/src/utils/pathTemplateParser.js +7 -2
- package/dist/esm/src/utils/utils.js +30 -17
- package/dist/esm/start.js +7 -2
- package/index.ts +3 -0
- package/package.json +10 -4
- package/src/instanceManager.ts +1 -1
- package/src/socketManager.ts +6 -0
- package/src/utils/DefaultProviderInstaller.ts +141 -0
- package/tsconfig.json +3 -2
@@ -1,8 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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.storageService = void 0;
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
10
|
+
const yaml_1 = __importDefault(require("yaml"));
|
11
|
+
const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
|
6
12
|
/**
|
7
13
|
* Class that handles reading and writing from local configuration file.
|
8
14
|
*/
|
@@ -12,15 +18,15 @@ class StorageService {
|
|
12
18
|
this._data = this._readConfig();
|
13
19
|
}
|
14
20
|
getKapetaBasedir() {
|
15
|
-
return
|
21
|
+
return local_cluster_config_1.default.getKapetaBasedir();
|
16
22
|
}
|
17
23
|
_readConfig() {
|
18
|
-
return
|
24
|
+
return local_cluster_config_1.default.getClusterConfig();
|
19
25
|
}
|
20
26
|
_writeConfig() {
|
21
|
-
const configFile =
|
22
|
-
|
23
|
-
|
27
|
+
const configFile = local_cluster_config_1.default.getClusterConfigFile();
|
28
|
+
fs_extra_1.default.mkdirsSync(this.getKapetaBasedir());
|
29
|
+
fs_1.default.writeFileSync(configFile, yaml_1.default.stringify(this._data));
|
24
30
|
}
|
25
31
|
section(section, defaultValue) {
|
26
32
|
if (!defaultValue) {
|
@@ -33,7 +39,7 @@ class StorageService {
|
|
33
39
|
return this._data[section];
|
34
40
|
}
|
35
41
|
put(section, property, value) {
|
36
|
-
if (!
|
42
|
+
if (!lodash_1.default.isString(property)) {
|
37
43
|
this._data[section] = property;
|
38
44
|
this._writeConfig();
|
39
45
|
return;
|
@@ -68,4 +74,4 @@ class StorageService {
|
|
68
74
|
return out;
|
69
75
|
}
|
70
76
|
}
|
71
|
-
|
77
|
+
exports.storageService = new StorageService();
|
@@ -1,18 +1,21 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.taskManager = exports.Task = exports.TaskStatus = void 0;
|
1
4
|
/**
|
2
5
|
* Class that handles processing background tasks.
|
3
6
|
*/
|
4
|
-
|
7
|
+
const socketManager_1 = require("./socketManager");
|
5
8
|
const EVENT_TASK_UPDATED = 'task-updated';
|
6
9
|
const EVENT_TASK_ADDED = 'task-added';
|
7
10
|
const EVENT_TASK_REMOVED = 'task-removed';
|
8
|
-
|
11
|
+
var TaskStatus;
|
9
12
|
(function (TaskStatus) {
|
10
13
|
TaskStatus["PENDING"] = "PENDING";
|
11
14
|
TaskStatus["RUNNING"] = "RUNNING";
|
12
15
|
TaskStatus["COMPLETED"] = "COMPLETED";
|
13
16
|
TaskStatus["FAILED"] = "FAILED";
|
14
|
-
})(TaskStatus || (TaskStatus = {}));
|
15
|
-
|
17
|
+
})(TaskStatus || (exports.TaskStatus = TaskStatus = {}));
|
18
|
+
class Task {
|
16
19
|
data;
|
17
20
|
constructor(task) {
|
18
21
|
this.data = task;
|
@@ -45,7 +48,7 @@ export class Task {
|
|
45
48
|
this.data.metadata = metadata;
|
46
49
|
}
|
47
50
|
emitUpdate() {
|
48
|
-
socketManager.emitGlobal(EVENT_TASK_UPDATED, this.toData());
|
51
|
+
socketManager_1.socketManager.emitGlobal(EVENT_TASK_UPDATED, this.toData());
|
49
52
|
}
|
50
53
|
async wait() {
|
51
54
|
return this.future.promise;
|
@@ -54,6 +57,7 @@ export class Task {
|
|
54
57
|
return { ...this.data };
|
55
58
|
}
|
56
59
|
}
|
60
|
+
exports.Task = Task;
|
57
61
|
function createFuture() {
|
58
62
|
let resolve = () => { };
|
59
63
|
let reject = () => { };
|
@@ -85,7 +89,7 @@ class TaskManager {
|
|
85
89
|
run: runner,
|
86
90
|
});
|
87
91
|
this._tasks.push(task);
|
88
|
-
socketManager.emitGlobal(EVENT_TASK_ADDED, task.toData());
|
92
|
+
socketManager_1.socketManager.emitGlobal(EVENT_TASK_ADDED, task.toData());
|
89
93
|
this.invokeTask(task).catch(() => { });
|
90
94
|
return task;
|
91
95
|
}
|
@@ -119,7 +123,7 @@ class TaskManager {
|
|
119
123
|
throw new Error('Cannot remove a running task');
|
120
124
|
}
|
121
125
|
this._tasks = this._tasks.filter((t) => t.id !== taskId);
|
122
|
-
socketManager.emitGlobal(EVENT_TASK_REMOVED, task.toData());
|
126
|
+
socketManager_1.socketManager.emitGlobal(EVENT_TASK_REMOVED, task.toData());
|
123
127
|
}
|
124
128
|
list() {
|
125
129
|
return this._tasks.map((t) => t.toData());
|
@@ -158,4 +162,4 @@ class TaskManager {
|
|
158
162
|
}
|
159
163
|
}
|
160
164
|
}
|
161
|
-
|
165
|
+
exports.taskManager = new TaskManager();
|
@@ -1,16 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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 cors_1 = require("../middleware/cors");
|
8
|
+
const taskManager_1 = require("../taskManager");
|
9
|
+
const router = (0, express_promise_router_1.default)();
|
10
|
+
router.use('/', cors_1.corsHandler);
|
6
11
|
/**
|
7
12
|
* Get all current tasks
|
8
13
|
*/
|
9
14
|
router.get('/', (req, res) => {
|
10
|
-
res.send(taskManager.list());
|
15
|
+
res.send(taskManager_1.taskManager.list());
|
11
16
|
});
|
12
17
|
router.get('/:taskId', (req, res) => {
|
13
|
-
const task = taskManager.get(req.params.taskId);
|
18
|
+
const task = taskManager_1.taskManager.get(req.params.taskId);
|
14
19
|
if (!task) {
|
15
20
|
res.status(404).send({ error: 'Task not found' });
|
16
21
|
return;
|
@@ -19,7 +24,7 @@ router.get('/:taskId', (req, res) => {
|
|
19
24
|
});
|
20
25
|
router.delete('/:taskId', (req, res) => {
|
21
26
|
try {
|
22
|
-
taskManager.remove(req.params.taskId);
|
27
|
+
taskManager_1.taskManager.remove(req.params.taskId);
|
23
28
|
res.send({ ok: true });
|
24
29
|
}
|
25
30
|
catch (e) {
|
@@ -27,4 +32,4 @@ router.delete('/:taskId', (req, res) => {
|
|
27
32
|
return;
|
28
33
|
}
|
29
34
|
});
|
30
|
-
|
35
|
+
exports.default = router;
|
@@ -1,13 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
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 networkManager_1 = require("../networkManager");
|
8
|
+
const router = (0, express_promise_router_1.default)();
|
4
9
|
router.get('/:systemId/target/:connectionId/', (req, res) => {
|
5
|
-
res.send(networkManager.getTrafficForConnection(req.params.systemId, req.params.connectionId));
|
10
|
+
res.send(networkManager_1.networkManager.getTrafficForConnection(req.params.systemId, req.params.connectionId));
|
6
11
|
});
|
7
12
|
router.get('/:systemId/source/:blockInstanceId/', (req, res) => {
|
8
|
-
res.send(networkManager.getTrafficForSource(req.params.systemId, req.params.blockInstanceId));
|
13
|
+
res.send(networkManager_1.networkManager.getTrafficForSource(req.params.systemId, req.params.blockInstanceId));
|
9
14
|
});
|
10
15
|
router.get('/:systemId/target/:blockInstanceId/', (req, res) => {
|
11
|
-
res.send(networkManager.getTrafficForTarget(req.params.systemId, req.params.blockInstanceId));
|
16
|
+
res.send(networkManager_1.networkManager.getTrafficForTarget(req.params.systemId, req.params.blockInstanceId));
|
12
17
|
});
|
13
|
-
|
18
|
+
exports.default = router;
|
package/dist/esm/src/types.js
CHANGED
@@ -1,15 +1,18 @@
|
|
1
|
-
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.DesiredInstanceStatus = exports.InstanceStatus = exports.InstanceOwner = exports.InstanceType = void 0;
|
4
|
+
var InstanceType;
|
2
5
|
(function (InstanceType) {
|
3
6
|
InstanceType["DOCKER"] = "docker";
|
4
7
|
InstanceType["LOCAL"] = "local";
|
5
8
|
InstanceType["UNKNOWN"] = "unknown";
|
6
|
-
})(InstanceType || (InstanceType = {}));
|
7
|
-
|
9
|
+
})(InstanceType || (exports.InstanceType = InstanceType = {}));
|
10
|
+
var InstanceOwner;
|
8
11
|
(function (InstanceOwner) {
|
9
12
|
InstanceOwner["INTERNAL"] = "internal";
|
10
13
|
InstanceOwner["EXTERNAL"] = "external";
|
11
|
-
})(InstanceOwner || (InstanceOwner = {}));
|
12
|
-
|
14
|
+
})(InstanceOwner || (exports.InstanceOwner = InstanceOwner = {}));
|
15
|
+
var InstanceStatus;
|
13
16
|
(function (InstanceStatus) {
|
14
17
|
InstanceStatus["STOPPED"] = "stopped";
|
15
18
|
InstanceStatus["STARTING"] = "starting";
|
@@ -18,10 +21,10 @@ export var InstanceStatus;
|
|
18
21
|
InstanceStatus["STOPPING"] = "stopping";
|
19
22
|
InstanceStatus["UNHEALTHY"] = "unhealthy";
|
20
23
|
InstanceStatus["FAILED"] = "failed";
|
21
|
-
})(InstanceStatus || (InstanceStatus = {}));
|
22
|
-
|
24
|
+
})(InstanceStatus || (exports.InstanceStatus = InstanceStatus = {}));
|
25
|
+
var DesiredInstanceStatus;
|
23
26
|
(function (DesiredInstanceStatus) {
|
24
27
|
DesiredInstanceStatus["STOP"] = "stop";
|
25
28
|
DesiredInstanceStatus["RUN"] = "run";
|
26
29
|
DesiredInstanceStatus["EXTERNAL"] = "external";
|
27
|
-
})(DesiredInstanceStatus || (DesiredInstanceStatus = {}));
|
30
|
+
})(DesiredInstanceStatus || (exports.DesiredInstanceStatus = DesiredInstanceStatus = {}));
|
@@ -1,13 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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.BlockInstanceRunner = void 0;
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
8
|
+
const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
|
9
|
+
const utils_1 = require("./utils");
|
10
|
+
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
11
|
+
const serviceManager_1 = require("../serviceManager");
|
12
|
+
const containerManager_1 = require("../containerManager");
|
13
|
+
const LogData_1 = require("./LogData");
|
14
|
+
const clusterService_1 = require("../clusterService");
|
15
|
+
const types_1 = require("../types");
|
16
|
+
const definitionsManager_1 = require("../definitionsManager");
|
11
17
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
12
18
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
13
19
|
const KAPETA_BLOCK_REF = 'KAPETA_BLOCK_REF';
|
@@ -22,9 +28,9 @@ const DOCKER_ENV_VARS = [
|
|
22
28
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
23
29
|
];
|
24
30
|
function getProvider(uri) {
|
25
|
-
return definitionsManager.getProviderDefinitions().find((provider) => {
|
31
|
+
return definitionsManager_1.definitionsManager.getProviderDefinitions().find((provider) => {
|
26
32
|
const ref = `${provider.definition.metadata.name}:${provider.version}`;
|
27
|
-
return parseKapetaUri(ref).id === uri.id;
|
33
|
+
return (0, nodejs_utils_1.parseKapetaUri)(ref).id === uri.id;
|
28
34
|
});
|
29
35
|
}
|
30
36
|
function getProviderPorts(assetVersion) {
|
@@ -34,7 +40,7 @@ function getProviderPorts(assetVersion) {
|
|
34
40
|
})
|
35
41
|
.filter((t) => !!t) ?? []);
|
36
42
|
}
|
37
|
-
|
43
|
+
class BlockInstanceRunner {
|
38
44
|
_systemId;
|
39
45
|
constructor(systemId) {
|
40
46
|
/**
|
@@ -42,7 +48,7 @@ export class BlockInstanceRunner {
|
|
42
48
|
* @type {string}
|
43
49
|
* @private
|
44
50
|
*/
|
45
|
-
this._systemId = normalizeKapetaUri(systemId);
|
51
|
+
this._systemId = (0, utils_1.normalizeKapetaUri)(systemId);
|
46
52
|
}
|
47
53
|
/**
|
48
54
|
* Start a block
|
@@ -66,18 +72,18 @@ export class BlockInstanceRunner {
|
|
66
72
|
if (blockInstance.id) {
|
67
73
|
env[KAPETA_INSTANCE_ID] = blockInstance.id;
|
68
74
|
}
|
69
|
-
const blockUri = parseKapetaUri(blockInstance.ref);
|
75
|
+
const blockUri = (0, nodejs_utils_1.parseKapetaUri)(blockInstance.ref);
|
70
76
|
if (!blockUri.version) {
|
71
77
|
blockUri.version = 'local';
|
72
78
|
}
|
73
|
-
const assetVersion = definitionsManager.getDefinitions().find((definitions) => {
|
79
|
+
const assetVersion = definitionsManager_1.definitionsManager.getDefinitions().find((definitions) => {
|
74
80
|
const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
|
75
|
-
return parseKapetaUri(ref).id === blockUri.id;
|
81
|
+
return (0, nodejs_utils_1.parseKapetaUri)(ref).id === blockUri.id;
|
76
82
|
});
|
77
83
|
if (!assetVersion) {
|
78
84
|
throw new Error(`Block definition not found: ${blockUri.id}`);
|
79
85
|
}
|
80
|
-
const kindUri = parseKapetaUri(assetVersion.definition.kind);
|
86
|
+
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.kind);
|
81
87
|
const providerVersion = getProvider(kindUri);
|
82
88
|
if (!providerVersion) {
|
83
89
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
@@ -105,15 +111,15 @@ export class BlockInstanceRunner {
|
|
105
111
|
* Starts local process
|
106
112
|
*/
|
107
113
|
async _startLocalProcess(blockInstance, blockInfo, env, assetVersion) {
|
108
|
-
const baseDir =
|
109
|
-
if (!
|
114
|
+
const baseDir = local_cluster_config_1.default.getRepositoryAssetPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
115
|
+
if (!node_fs_1.default.existsSync(baseDir)) {
|
110
116
|
throw new Error(`Local block not registered correctly - expected symlink here: ${baseDir}.\n` +
|
111
117
|
`Make sure you've run "blockctl registry link" in your local directory to connect it to Kapeta`);
|
112
118
|
}
|
113
119
|
if (!assetVersion.definition.spec?.target?.kind) {
|
114
120
|
throw new Error('Missing target kind in block definition');
|
115
121
|
}
|
116
|
-
const kindUri = parseKapetaUri(assetVersion.definition.spec?.target?.kind);
|
122
|
+
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.spec?.target?.kind);
|
117
123
|
const targetVersion = getProvider(kindUri);
|
118
124
|
if (!targetVersion) {
|
119
125
|
throw new Error(`Target not found: ${kindUri.id}`);
|
@@ -126,7 +132,7 @@ export class BlockInstanceRunner {
|
|
126
132
|
if (!dockerImage) {
|
127
133
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
128
134
|
}
|
129
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
135
|
+
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
130
136
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
131
137
|
const dockerOpts = localContainer.options ?? {};
|
132
138
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
@@ -134,7 +140,7 @@ export class BlockInstanceRunner {
|
|
134
140
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
135
141
|
let HealthCheck = undefined;
|
136
142
|
if (localContainer.healthcheck) {
|
137
|
-
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
143
|
+
HealthCheck = containerManager_1.containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
138
144
|
}
|
139
145
|
return this.ensureContainer({
|
140
146
|
Image: dockerImage,
|
@@ -148,7 +154,7 @@ export class BlockInstanceRunner {
|
|
148
154
|
Cmd: startCmd ? startCmd.split(/\s+/g) : [],
|
149
155
|
Env: [
|
150
156
|
...DOCKER_ENV_VARS,
|
151
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
157
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
152
158
|
...Object.entries({
|
153
159
|
...env,
|
154
160
|
...addonEnv,
|
@@ -156,8 +162,8 @@ export class BlockInstanceRunner {
|
|
156
162
|
],
|
157
163
|
HostConfig: {
|
158
164
|
Binds: [
|
159
|
-
`${toLocalBindVolume(
|
160
|
-
`${toLocalBindVolume(baseDir)}:${workingDir}`,
|
165
|
+
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${homeDir}/.kapeta`,
|
166
|
+
`${(0, containerManager_1.toLocalBindVolume)(baseDir)}:${workingDir}`,
|
161
167
|
],
|
162
168
|
PortBindings,
|
163
169
|
},
|
@@ -165,12 +171,12 @@ export class BlockInstanceRunner {
|
|
165
171
|
});
|
166
172
|
}
|
167
173
|
async _startDockerProcess(blockInstance, blockInfo, env, assetVersion) {
|
168
|
-
const { versionFile } =
|
174
|
+
const { versionFile } = local_cluster_config_1.default.getRepositoryAssetInfoPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
169
175
|
const versionYml = versionFile;
|
170
|
-
if (!
|
176
|
+
if (!node_fs_1.default.existsSync(versionYml)) {
|
171
177
|
throw new Error(`Did not find version info at the expected path: ${versionYml}`);
|
172
178
|
}
|
173
|
-
const versionInfo = readYML(versionYml);
|
179
|
+
const versionInfo = (0, utils_1.readYML)(versionYml);
|
174
180
|
if (versionInfo?.artifact?.type !== 'docker') {
|
175
181
|
throw new Error(`Unsupported artifact type: ${versionInfo?.artifact?.type}`);
|
176
182
|
}
|
@@ -179,9 +185,9 @@ export class BlockInstanceRunner {
|
|
179
185
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
180
186
|
}
|
181
187
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
182
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
188
|
+
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
183
189
|
// For windows we need to default to root
|
184
|
-
const innerHome = process.platform === 'win32' ? '/root/.kapeta' :
|
190
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
|
185
191
|
return this.ensureContainer({
|
186
192
|
Image: dockerImage,
|
187
193
|
name: containerName,
|
@@ -191,14 +197,14 @@ export class BlockInstanceRunner {
|
|
191
197
|
},
|
192
198
|
Env: [
|
193
199
|
...DOCKER_ENV_VARS,
|
194
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
200
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
195
201
|
...Object.entries({
|
196
202
|
...env,
|
197
203
|
...addonEnv,
|
198
204
|
}).map(([key, value]) => `${key}=${value}`),
|
199
205
|
],
|
200
206
|
HostConfig: {
|
201
|
-
Binds: [`${toLocalBindVolume(
|
207
|
+
Binds: [`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`],
|
202
208
|
PortBindings,
|
203
209
|
},
|
204
210
|
});
|
@@ -213,9 +219,9 @@ export class BlockInstanceRunner {
|
|
213
219
|
* @private
|
214
220
|
*/
|
215
221
|
async _startOperatorProcess(blockInstance, blockUri, providerDefinition, env) {
|
216
|
-
const { assetFile } =
|
222
|
+
const { assetFile } = local_cluster_config_1.default.getRepositoryAssetInfoPath(blockUri.handle, blockUri.name, blockUri.version);
|
217
223
|
const kapetaYmlPath = assetFile;
|
218
|
-
if (!
|
224
|
+
if (!node_fs_1.default.existsSync(kapetaYmlPath)) {
|
219
225
|
throw new Error(`Did not find kapeta.yml at the expected path: ${kapetaYmlPath}`);
|
220
226
|
}
|
221
227
|
const spec = providerDefinition.definition.spec;
|
@@ -225,9 +231,9 @@ export class BlockInstanceRunner {
|
|
225
231
|
}
|
226
232
|
const dockerImage = spec?.local?.image;
|
227
233
|
//We only want 1 operator per operator type - across all local systems
|
228
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
229
|
-
const logs = new LogData();
|
230
|
-
const bindHost = getBindHost();
|
234
|
+
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
235
|
+
const logs = new LogData_1.LogData();
|
236
|
+
const bindHost = (0, utils_1.getBindHost)();
|
231
237
|
const ExposedPorts = {};
|
232
238
|
const addonEnv = {};
|
233
239
|
const PortBindings = {};
|
@@ -237,7 +243,7 @@ export class BlockInstanceRunner {
|
|
237
243
|
const dockerPort = `${value.port}/${value.type}`;
|
238
244
|
ExposedPorts[dockerPort] = {};
|
239
245
|
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
240
|
-
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
246
|
+
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
241
247
|
PortBindings[dockerPort] = [
|
242
248
|
{
|
243
249
|
HostIp: bindHost,
|
@@ -252,14 +258,14 @@ export class BlockInstanceRunner {
|
|
252
258
|
});
|
253
259
|
}
|
254
260
|
if (spec.local?.mounts) {
|
255
|
-
const mounts = await containerManager.createMounts(this._systemId, blockUri.id, spec.local.mounts);
|
256
|
-
Mounts = containerManager.toDockerMounts(mounts);
|
261
|
+
const mounts = await containerManager_1.containerManager.createMounts(this._systemId, blockUri.id, spec.local.mounts);
|
262
|
+
Mounts = containerManager_1.containerManager.toDockerMounts(mounts);
|
257
263
|
}
|
258
264
|
if (spec.local?.health) {
|
259
|
-
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
265
|
+
HealthCheck = containerManager_1.containerManager.toDockerHealth(spec.local?.health);
|
260
266
|
}
|
261
267
|
// For windows we need to default to root
|
262
|
-
const innerHome = process.platform === 'win32' ? '/root/.kapeta' :
|
268
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
|
263
269
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
264
270
|
const out = await this.ensureContainer({
|
265
271
|
Image: dockerImage,
|
@@ -268,8 +274,8 @@ export class BlockInstanceRunner {
|
|
268
274
|
HealthCheck,
|
269
275
|
HostConfig: {
|
270
276
|
Binds: [
|
271
|
-
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
272
|
-
`${toLocalBindVolume(
|
277
|
+
`${(0, containerManager_1.toLocalBindVolume)(kapetaYmlPath)}:/kapeta.yml:ro`,
|
278
|
+
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`,
|
273
279
|
],
|
274
280
|
PortBindings,
|
275
281
|
Mounts,
|
@@ -279,7 +285,7 @@ export class BlockInstanceRunner {
|
|
279
285
|
},
|
280
286
|
Env: [
|
281
287
|
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
282
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
288
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
283
289
|
...DOCKER_ENV_VARS,
|
284
290
|
...Object.entries({
|
285
291
|
...env,
|
@@ -294,14 +300,14 @@ export class BlockInstanceRunner {
|
|
294
300
|
return out;
|
295
301
|
}
|
296
302
|
async getDockerPortBindings(blockInstance, assetVersion) {
|
297
|
-
const bindHost = getBindHost();
|
303
|
+
const bindHost = (0, utils_1.getBindHost)();
|
298
304
|
const ExposedPorts = {};
|
299
305
|
const addonEnv = {};
|
300
306
|
const PortBindings = {};
|
301
307
|
const portTypes = getProviderPorts(assetVersion);
|
302
308
|
let port = 80;
|
303
309
|
const promises = portTypes.map(async (portType) => {
|
304
|
-
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
310
|
+
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
305
311
|
const thisPort = port++; //TODO: Not sure how we should handle multiple ports or non-HTTP ports
|
306
312
|
const dockerPort = `${thisPort}/tcp`;
|
307
313
|
ExposedPorts[dockerPort] = {};
|
@@ -317,13 +323,14 @@ export class BlockInstanceRunner {
|
|
317
323
|
return { PortBindings, ExposedPorts, addonEnv };
|
318
324
|
}
|
319
325
|
async ensureContainer(opts) {
|
320
|
-
const container = await containerManager.ensureContainer(opts);
|
326
|
+
const container = await containerManager_1.containerManager.ensureContainer(opts);
|
321
327
|
return this._handleContainer(container);
|
322
328
|
}
|
323
329
|
async _handleContainer(container) {
|
324
330
|
return {
|
325
|
-
type: InstanceType.DOCKER,
|
331
|
+
type: types_1.InstanceType.DOCKER,
|
326
332
|
pid: container.id,
|
327
333
|
};
|
328
334
|
}
|
329
335
|
}
|
336
|
+
exports.BlockInstanceRunner = BlockInstanceRunner;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
declare class DefaultProviderInstaller {
|
2
|
+
private readonly progressListener;
|
3
|
+
checkForDefault(): Promise<void>;
|
4
|
+
private install;
|
5
|
+
private linkLocal;
|
6
|
+
private scanProjectBase;
|
7
|
+
private ensureDefaultProjectHome;
|
8
|
+
private download;
|
9
|
+
}
|
10
|
+
export declare const defaultProviderInstaller: DefaultProviderInstaller;
|
11
|
+
export {};
|
@@ -0,0 +1,129 @@
|
|
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.defaultProviderInstaller = void 0;
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
9
|
+
const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
|
10
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
11
|
+
const request_1 = __importDefault(require("request"));
|
12
|
+
const tar_stream_1 = require("tar-stream");
|
13
|
+
const gunzip_maybe_1 = __importDefault(require("gunzip-maybe"));
|
14
|
+
const filesystemManager_1 = require("../filesystemManager");
|
15
|
+
const nodejs_registry_utils_1 = require("@kapeta/nodejs-registry-utils");
|
16
|
+
const progressListener_1 = require("../progressListener");
|
17
|
+
const glob_1 = require("glob");
|
18
|
+
const DEFAULT_PROVIDERS_URL = 'https://storage.googleapis.com/kapeta-production-cdn/archives/default-providers.tar.gz';
|
19
|
+
const DEFAULT_PROJECT_HOME_DIR = 'KapetaProjects';
|
20
|
+
const ARCHIVE_LOCAL_PREFIX = 'local';
|
21
|
+
class DefaultProviderInstaller {
|
22
|
+
progressListener = new progressListener_1.ProgressListener();
|
23
|
+
async checkForDefault() {
|
24
|
+
const definitions = local_cluster_config_1.default.getDefinitions();
|
25
|
+
if (definitions.length < 1) {
|
26
|
+
console.log('Installing default providers');
|
27
|
+
try {
|
28
|
+
await this.install();
|
29
|
+
}
|
30
|
+
catch (e) {
|
31
|
+
console.warn('Failed to install defaults', e);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
async install() {
|
36
|
+
await this.download();
|
37
|
+
await this.linkLocal();
|
38
|
+
}
|
39
|
+
async linkLocal() {
|
40
|
+
const projectBase = await this.ensureDefaultProjectHome();
|
41
|
+
const folders = this.scanProjectBase(projectBase);
|
42
|
+
for (let folder of folders) {
|
43
|
+
console.log('Linking %s', folder);
|
44
|
+
await nodejs_registry_utils_1.Actions.link(this.progressListener, folder);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
scanProjectBase(projectBase) {
|
48
|
+
const assetFiles = glob_1.glob.sync('*/**/kapeta.yml', { cwd: projectBase });
|
49
|
+
return assetFiles.map((assetFile) => {
|
50
|
+
return node_path_1.default.dirname(node_path_1.default.join(projectBase, assetFile));
|
51
|
+
});
|
52
|
+
}
|
53
|
+
async ensureDefaultProjectHome() {
|
54
|
+
const defaultProjectHome = node_path_1.default.join(node_os_1.default.homedir(), DEFAULT_PROJECT_HOME_DIR);
|
55
|
+
let projectBase = filesystemManager_1.filesystemManager.getProjectRootFolder();
|
56
|
+
if (!projectBase) {
|
57
|
+
filesystemManager_1.filesystemManager.setProjectRootFolder(defaultProjectHome);
|
58
|
+
projectBase = defaultProjectHome;
|
59
|
+
if (!(await fs_extra_1.default.pathExists(projectBase))) {
|
60
|
+
await fs_extra_1.default.mkdirp(projectBase);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return projectBase;
|
64
|
+
}
|
65
|
+
async download() {
|
66
|
+
const projectBase = await this.ensureDefaultProjectHome();
|
67
|
+
const repoBase = local_cluster_config_1.default.getRepositoryBasedir();
|
68
|
+
return new Promise((resolve, reject) => {
|
69
|
+
const extractor = (0, tar_stream_1.extract)();
|
70
|
+
const dirCache = new Set();
|
71
|
+
extractor.on('entry', async function (header, stream, next) {
|
72
|
+
if (header.type !== 'file') {
|
73
|
+
stream.on('end', function () {
|
74
|
+
next(); // ready for next entry
|
75
|
+
});
|
76
|
+
stream.resume(); // just auto drain the stream
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
// Local (editable) assets should be stored in the project folder
|
80
|
+
// - installed assets goes into the repository folder
|
81
|
+
const baseDir = header.name.startsWith(ARCHIVE_LOCAL_PREFIX) ? projectBase : repoBase;
|
82
|
+
const parts = header.name.split(/\//g);
|
83
|
+
parts.shift();
|
84
|
+
const filename = parts.join(node_path_1.default.sep);
|
85
|
+
try {
|
86
|
+
const dirname = node_path_1.default.join(baseDir, node_path_1.default.dirname(filename));
|
87
|
+
if (!dirCache.has(dirname)) {
|
88
|
+
let dirExists = false;
|
89
|
+
try {
|
90
|
+
await fs_extra_1.default.stat(dirname);
|
91
|
+
dirExists = true;
|
92
|
+
}
|
93
|
+
catch (e) { }
|
94
|
+
if (!dirExists) {
|
95
|
+
await fs_extra_1.default.mkdirp(dirname);
|
96
|
+
}
|
97
|
+
dirCache.add(dirname);
|
98
|
+
}
|
99
|
+
const fileTarget = node_path_1.default.join(baseDir, filename);
|
100
|
+
stream.on('error', (err) => {
|
101
|
+
reject(err);
|
102
|
+
});
|
103
|
+
stream.on('end', next);
|
104
|
+
stream.pipe(fs_extra_1.default.createWriteStream(fileTarget, {
|
105
|
+
mode: header.mode,
|
106
|
+
}));
|
107
|
+
}
|
108
|
+
catch (e) {
|
109
|
+
reject(e);
|
110
|
+
}
|
111
|
+
});
|
112
|
+
extractor.on('finish', function () {
|
113
|
+
// all entries done - lets finalize it
|
114
|
+
console.log('Default providers installed');
|
115
|
+
resolve();
|
116
|
+
});
|
117
|
+
extractor.on('error', function (err) {
|
118
|
+
reject(err);
|
119
|
+
});
|
120
|
+
console.log('Downloading default providers from %s', DEFAULT_PROVIDERS_URL);
|
121
|
+
const response = (0, request_1.default)(DEFAULT_PROVIDERS_URL);
|
122
|
+
response.on('error', function (err) {
|
123
|
+
reject(err);
|
124
|
+
});
|
125
|
+
response.pipe((0, gunzip_maybe_1.default)()).pipe(extractor);
|
126
|
+
});
|
127
|
+
}
|
128
|
+
}
|
129
|
+
exports.defaultProviderInstaller = new DefaultProviderInstaller();
|