@kapeta/local-cluster-service 0.16.8 → 0.18.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 +20 -0
- package/dist/cjs/index.js +6 -2
- package/dist/cjs/src/assetManager.d.ts +2 -2
- package/dist/cjs/src/assetManager.js +16 -16
- package/dist/cjs/src/assets/routes.js +2 -2
- package/dist/cjs/src/authManager.d.ts +12 -0
- package/dist/cjs/src/authManager.js +60 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +1 -1
- package/dist/cjs/src/codeGeneratorManager.js +3 -3
- package/dist/cjs/src/configManager.js +2 -2
- package/dist/cjs/src/definitionsManager.d.ts +7 -6
- package/dist/cjs/src/definitionsManager.js +102 -18
- package/dist/cjs/src/instanceManager.d.ts +1 -1
- package/dist/cjs/src/instanceManager.js +4 -4
- package/dist/cjs/src/instances/routes.js +2 -2
- package/dist/cjs/src/operatorManager.d.ts +1 -1
- package/dist/cjs/src/operatorManager.js +7 -9
- package/dist/cjs/src/providerManager.d.ts +2 -1
- package/dist/cjs/src/providerManager.js +23 -15
- package/dist/cjs/src/repositoryManager.d.ts +2 -2
- package/dist/cjs/src/repositoryManager.js +8 -9
- package/dist/cjs/src/socketManager.js +6 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +6 -8
- package/dist/cjs/src/utils/DefaultProviderInstaller.d.ts +11 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.js +129 -0
- package/dist/esm/index.js +67 -58
- package/dist/esm/src/RepositoryWatcher.js +40 -33
- package/dist/esm/src/api.js +14 -9
- package/dist/esm/src/assetManager.d.ts +2 -2
- package/dist/esm/src/assetManager.js +73 -67
- package/dist/esm/src/assets/routes.js +23 -18
- package/dist/esm/src/attachments/routes.js +14 -9
- package/dist/esm/src/authManager.d.ts +12 -0
- package/dist/esm/src/authManager.js +60 -0
- package/dist/esm/src/cacheManager.js +13 -5
- package/dist/esm/src/clusterService.js +6 -3
- package/dist/esm/src/codeGeneratorManager.d.ts +1 -1
- package/dist/esm/src/codeGeneratorManager.js +20 -14
- 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.d.ts +7 -6
- package/dist/esm/src/definitionsManager.js +114 -24
- 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.d.ts +1 -1
- package/dist/esm/src/instanceManager.js +165 -158
- package/dist/esm/src/instances/routes.js +39 -34
- 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.d.ts +1 -1
- package/dist/esm/src/operatorManager.js +48 -44
- package/dist/esm/src/progressListener.js +16 -12
- package/dist/esm/src/providerManager.d.ts +2 -1
- package/dist/esm/src/providerManager.js +43 -29
- 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.d.ts +2 -2
- package/dist/esm/src/repositoryManager.js +33 -28
- 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 +60 -55
- 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 +7 -2
- package/package.json +10 -4
- package/src/assetManager.ts +18 -16
- package/src/assets/routes.ts +2 -2
- package/src/authManager.ts +62 -0
- package/src/codeGeneratorManager.ts +3 -3
- package/src/configManager.ts +2 -2
- package/src/definitionsManager.ts +132 -17
- package/src/instanceManager.ts +5 -5
- package/src/instances/routes.ts +2 -2
- package/src/operatorManager.ts +7 -12
- package/src/providerManager.ts +27 -19
- package/src/repositoryManager.ts +8 -11
- package/src/socketManager.ts +6 -0
- package/src/utils/BlockInstanceRunner.ts +6 -8
- package/src/utils/DefaultProviderInstaller.ts +141 -0
- package/tsconfig.json +3 -2
@@ -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';
|
@@ -21,10 +27,11 @@ const DOCKER_ENV_VARS = [
|
|
21
27
|
`KAPETA_LOCAL_CLUSTER_HOST=host.docker.internal`,
|
22
28
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
23
29
|
];
|
24
|
-
function getProvider(uri) {
|
25
|
-
|
30
|
+
async function getProvider(uri) {
|
31
|
+
const providers = await definitionsManager_1.definitionsManager.getProviderDefinitions();
|
32
|
+
return providers.find((provider) => {
|
26
33
|
const ref = `${provider.definition.metadata.name}:${provider.version}`;
|
27
|
-
return parseKapetaUri(ref).id === uri.id;
|
34
|
+
return (0, nodejs_utils_1.parseKapetaUri)(ref).id === uri.id;
|
28
35
|
});
|
29
36
|
}
|
30
37
|
function getProviderPorts(assetVersion) {
|
@@ -34,7 +41,7 @@ function getProviderPorts(assetVersion) {
|
|
34
41
|
})
|
35
42
|
.filter((t) => !!t) ?? []);
|
36
43
|
}
|
37
|
-
|
44
|
+
class BlockInstanceRunner {
|
38
45
|
_systemId;
|
39
46
|
constructor(systemId) {
|
40
47
|
/**
|
@@ -42,7 +49,7 @@ export class BlockInstanceRunner {
|
|
42
49
|
* @type {string}
|
43
50
|
* @private
|
44
51
|
*/
|
45
|
-
this._systemId = normalizeKapetaUri(systemId);
|
52
|
+
this._systemId = (0, utils_1.normalizeKapetaUri)(systemId);
|
46
53
|
}
|
47
54
|
/**
|
48
55
|
* Start a block
|
@@ -66,19 +73,16 @@ export class BlockInstanceRunner {
|
|
66
73
|
if (blockInstance.id) {
|
67
74
|
env[KAPETA_INSTANCE_ID] = blockInstance.id;
|
68
75
|
}
|
69
|
-
const blockUri = parseKapetaUri(blockInstance.ref);
|
76
|
+
const blockUri = (0, nodejs_utils_1.parseKapetaUri)(blockInstance.ref);
|
70
77
|
if (!blockUri.version) {
|
71
78
|
blockUri.version = 'local';
|
72
79
|
}
|
73
|
-
const assetVersion = definitionsManager.
|
74
|
-
const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
|
75
|
-
return parseKapetaUri(ref).id === blockUri.id;
|
76
|
-
});
|
80
|
+
const assetVersion = await definitionsManager_1.definitionsManager.getDefinition(blockUri.id);
|
77
81
|
if (!assetVersion) {
|
78
82
|
throw new Error(`Block definition not found: ${blockUri.id}`);
|
79
83
|
}
|
80
|
-
const kindUri = parseKapetaUri(assetVersion.definition.kind);
|
81
|
-
const providerVersion = getProvider(kindUri);
|
84
|
+
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.kind);
|
85
|
+
const providerVersion = await getProvider(kindUri);
|
82
86
|
if (!providerVersion) {
|
83
87
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
84
88
|
}
|
@@ -105,16 +109,16 @@ export class BlockInstanceRunner {
|
|
105
109
|
* Starts local process
|
106
110
|
*/
|
107
111
|
async _startLocalProcess(blockInstance, blockInfo, env, assetVersion) {
|
108
|
-
const baseDir =
|
109
|
-
if (!
|
112
|
+
const baseDir = local_cluster_config_1.default.getRepositoryAssetPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
113
|
+
if (!node_fs_1.default.existsSync(baseDir)) {
|
110
114
|
throw new Error(`Local block not registered correctly - expected symlink here: ${baseDir}.\n` +
|
111
115
|
`Make sure you've run "blockctl registry link" in your local directory to connect it to Kapeta`);
|
112
116
|
}
|
113
117
|
if (!assetVersion.definition.spec?.target?.kind) {
|
114
118
|
throw new Error('Missing target kind in block definition');
|
115
119
|
}
|
116
|
-
const kindUri = parseKapetaUri(assetVersion.definition.spec?.target?.kind);
|
117
|
-
const targetVersion = getProvider(kindUri);
|
120
|
+
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.spec?.target?.kind);
|
121
|
+
const targetVersion = await getProvider(kindUri);
|
118
122
|
if (!targetVersion) {
|
119
123
|
throw new Error(`Target not found: ${kindUri.id}`);
|
120
124
|
}
|
@@ -126,7 +130,7 @@ export class BlockInstanceRunner {
|
|
126
130
|
if (!dockerImage) {
|
127
131
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
128
132
|
}
|
129
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
133
|
+
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
130
134
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
131
135
|
const dockerOpts = localContainer.options ?? {};
|
132
136
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
@@ -134,7 +138,7 @@ export class BlockInstanceRunner {
|
|
134
138
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
135
139
|
let HealthCheck = undefined;
|
136
140
|
if (localContainer.healthcheck) {
|
137
|
-
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
141
|
+
HealthCheck = containerManager_1.containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
138
142
|
}
|
139
143
|
return this.ensureContainer({
|
140
144
|
Image: dockerImage,
|
@@ -148,7 +152,7 @@ export class BlockInstanceRunner {
|
|
148
152
|
Cmd: startCmd ? startCmd.split(/\s+/g) : [],
|
149
153
|
Env: [
|
150
154
|
...DOCKER_ENV_VARS,
|
151
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
155
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
152
156
|
...Object.entries({
|
153
157
|
...env,
|
154
158
|
...addonEnv,
|
@@ -156,8 +160,8 @@ export class BlockInstanceRunner {
|
|
156
160
|
],
|
157
161
|
HostConfig: {
|
158
162
|
Binds: [
|
159
|
-
`${toLocalBindVolume(
|
160
|
-
`${toLocalBindVolume(baseDir)}:${workingDir}`,
|
163
|
+
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${homeDir}/.kapeta`,
|
164
|
+
`${(0, containerManager_1.toLocalBindVolume)(baseDir)}:${workingDir}`,
|
161
165
|
],
|
162
166
|
PortBindings,
|
163
167
|
},
|
@@ -165,12 +169,12 @@ export class BlockInstanceRunner {
|
|
165
169
|
});
|
166
170
|
}
|
167
171
|
async _startDockerProcess(blockInstance, blockInfo, env, assetVersion) {
|
168
|
-
const { versionFile } =
|
172
|
+
const { versionFile } = local_cluster_config_1.default.getRepositoryAssetInfoPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
169
173
|
const versionYml = versionFile;
|
170
|
-
if (!
|
174
|
+
if (!node_fs_1.default.existsSync(versionYml)) {
|
171
175
|
throw new Error(`Did not find version info at the expected path: ${versionYml}`);
|
172
176
|
}
|
173
|
-
const versionInfo = readYML(versionYml);
|
177
|
+
const versionInfo = (0, utils_1.readYML)(versionYml);
|
174
178
|
if (versionInfo?.artifact?.type !== 'docker') {
|
175
179
|
throw new Error(`Unsupported artifact type: ${versionInfo?.artifact?.type}`);
|
176
180
|
}
|
@@ -179,9 +183,9 @@ export class BlockInstanceRunner {
|
|
179
183
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
180
184
|
}
|
181
185
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
182
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
186
|
+
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
183
187
|
// For windows we need to default to root
|
184
|
-
const innerHome = process.platform === 'win32' ? '/root/.kapeta' :
|
188
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
|
185
189
|
return this.ensureContainer({
|
186
190
|
Image: dockerImage,
|
187
191
|
name: containerName,
|
@@ -191,14 +195,14 @@ export class BlockInstanceRunner {
|
|
191
195
|
},
|
192
196
|
Env: [
|
193
197
|
...DOCKER_ENV_VARS,
|
194
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
198
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
195
199
|
...Object.entries({
|
196
200
|
...env,
|
197
201
|
...addonEnv,
|
198
202
|
}).map(([key, value]) => `${key}=${value}`),
|
199
203
|
],
|
200
204
|
HostConfig: {
|
201
|
-
Binds: [`${toLocalBindVolume(
|
205
|
+
Binds: [`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`],
|
202
206
|
PortBindings,
|
203
207
|
},
|
204
208
|
});
|
@@ -213,9 +217,9 @@ export class BlockInstanceRunner {
|
|
213
217
|
* @private
|
214
218
|
*/
|
215
219
|
async _startOperatorProcess(blockInstance, blockUri, providerDefinition, env) {
|
216
|
-
const { assetFile } =
|
220
|
+
const { assetFile } = local_cluster_config_1.default.getRepositoryAssetInfoPath(blockUri.handle, blockUri.name, blockUri.version);
|
217
221
|
const kapetaYmlPath = assetFile;
|
218
|
-
if (!
|
222
|
+
if (!node_fs_1.default.existsSync(kapetaYmlPath)) {
|
219
223
|
throw new Error(`Did not find kapeta.yml at the expected path: ${kapetaYmlPath}`);
|
220
224
|
}
|
221
225
|
const spec = providerDefinition.definition.spec;
|
@@ -225,9 +229,9 @@ export class BlockInstanceRunner {
|
|
225
229
|
}
|
226
230
|
const dockerImage = spec?.local?.image;
|
227
231
|
//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();
|
232
|
+
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
233
|
+
const logs = new LogData_1.LogData();
|
234
|
+
const bindHost = (0, utils_1.getBindHost)();
|
231
235
|
const ExposedPorts = {};
|
232
236
|
const addonEnv = {};
|
233
237
|
const PortBindings = {};
|
@@ -237,7 +241,7 @@ export class BlockInstanceRunner {
|
|
237
241
|
const dockerPort = `${value.port}/${value.type}`;
|
238
242
|
ExposedPorts[dockerPort] = {};
|
239
243
|
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
240
|
-
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
244
|
+
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
241
245
|
PortBindings[dockerPort] = [
|
242
246
|
{
|
243
247
|
HostIp: bindHost,
|
@@ -252,14 +256,14 @@ export class BlockInstanceRunner {
|
|
252
256
|
});
|
253
257
|
}
|
254
258
|
if (spec.local?.mounts) {
|
255
|
-
const mounts = await containerManager.createMounts(this._systemId, blockUri.id, spec.local.mounts);
|
256
|
-
Mounts = containerManager.toDockerMounts(mounts);
|
259
|
+
const mounts = await containerManager_1.containerManager.createMounts(this._systemId, blockUri.id, spec.local.mounts);
|
260
|
+
Mounts = containerManager_1.containerManager.toDockerMounts(mounts);
|
257
261
|
}
|
258
262
|
if (spec.local?.health) {
|
259
|
-
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
263
|
+
HealthCheck = containerManager_1.containerManager.toDockerHealth(spec.local?.health);
|
260
264
|
}
|
261
265
|
// For windows we need to default to root
|
262
|
-
const innerHome = process.platform === 'win32' ? '/root/.kapeta' :
|
266
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
|
263
267
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
264
268
|
const out = await this.ensureContainer({
|
265
269
|
Image: dockerImage,
|
@@ -268,8 +272,8 @@ export class BlockInstanceRunner {
|
|
268
272
|
HealthCheck,
|
269
273
|
HostConfig: {
|
270
274
|
Binds: [
|
271
|
-
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
272
|
-
`${toLocalBindVolume(
|
275
|
+
`${(0, containerManager_1.toLocalBindVolume)(kapetaYmlPath)}:/kapeta.yml:ro`,
|
276
|
+
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`,
|
273
277
|
],
|
274
278
|
PortBindings,
|
275
279
|
Mounts,
|
@@ -279,7 +283,7 @@ export class BlockInstanceRunner {
|
|
279
283
|
},
|
280
284
|
Env: [
|
281
285
|
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
282
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
286
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
283
287
|
...DOCKER_ENV_VARS,
|
284
288
|
...Object.entries({
|
285
289
|
...env,
|
@@ -294,14 +298,14 @@ export class BlockInstanceRunner {
|
|
294
298
|
return out;
|
295
299
|
}
|
296
300
|
async getDockerPortBindings(blockInstance, assetVersion) {
|
297
|
-
const bindHost = getBindHost();
|
301
|
+
const bindHost = (0, utils_1.getBindHost)();
|
298
302
|
const ExposedPorts = {};
|
299
303
|
const addonEnv = {};
|
300
304
|
const PortBindings = {};
|
301
305
|
const portTypes = getProviderPorts(assetVersion);
|
302
306
|
let port = 80;
|
303
307
|
const promises = portTypes.map(async (portType) => {
|
304
|
-
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
308
|
+
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
305
309
|
const thisPort = port++; //TODO: Not sure how we should handle multiple ports or non-HTTP ports
|
306
310
|
const dockerPort = `${thisPort}/tcp`;
|
307
311
|
ExposedPorts[dockerPort] = {};
|
@@ -317,13 +321,14 @@ export class BlockInstanceRunner {
|
|
317
321
|
return { PortBindings, ExposedPorts, addonEnv };
|
318
322
|
}
|
319
323
|
async ensureContainer(opts) {
|
320
|
-
const container = await containerManager.ensureContainer(opts);
|
324
|
+
const container = await containerManager_1.containerManager.ensureContainer(opts);
|
321
325
|
return this._handleContainer(container);
|
322
326
|
}
|
323
327
|
async _handleContainer(container) {
|
324
328
|
return {
|
325
|
-
type: InstanceType.DOCKER,
|
329
|
+
type: types_1.InstanceType.DOCKER,
|
326
330
|
pid: container.id,
|
327
331
|
};
|
328
332
|
}
|
329
333
|
}
|
334
|
+
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();
|
@@ -1,5 +1,8 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.LogData = void 0;
|
1
4
|
const MAX_LINES = 1000;
|
2
|
-
|
5
|
+
class LogData {
|
3
6
|
static MAX_LINES = MAX_LINES;
|
4
7
|
entries = [];
|
5
8
|
constructor() { }
|
@@ -36,3 +39,4 @@ export class LogData {
|
|
36
39
|
.join('\n');
|
37
40
|
}
|
38
41
|
}
|
42
|
+
exports.LogData = LogData;
|
@@ -1,14 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ensureCLI = exports.hasCLI = void 0;
|
4
|
+
const nodejs_process_1 = require("@kapeta/nodejs-process");
|
5
|
+
const taskManager_1 = require("../taskManager");
|
6
|
+
async function hasCLI() {
|
7
|
+
return (0, nodejs_process_1.hasApp)('kap');
|
5
8
|
}
|
6
|
-
|
9
|
+
exports.hasCLI = hasCLI;
|
10
|
+
async function ensureCLI() {
|
7
11
|
if (await hasCLI()) {
|
8
12
|
return null;
|
9
13
|
}
|
10
|
-
return taskManager.add(`cli:install`, () => {
|
11
|
-
const process = spawn('npm', ['install', '-g', '@kapeta/kap'], {
|
14
|
+
return taskManager_1.taskManager.add(`cli:install`, () => {
|
15
|
+
const process = (0, nodejs_process_1.spawn)('npm', ['install', '-g', '@kapeta/kap'], {
|
12
16
|
shell: true,
|
13
17
|
});
|
14
18
|
return process.wait();
|
@@ -16,3 +20,4 @@ export async function ensureCLI() {
|
|
16
20
|
name: `Installing Kapeta CLI`,
|
17
21
|
});
|
18
22
|
}
|
23
|
+
exports.ensureCLI = ensureCLI;
|
@@ -1,3 +1,6 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.pathTemplateParser = exports.PathTemplate = void 0;
|
1
4
|
const TYPE_VARIABLE = 'variable';
|
2
5
|
const TYPE_PATH = 'path';
|
3
6
|
/**
|
@@ -11,7 +14,7 @@ const TYPE_PATH = 'path';
|
|
11
14
|
* /foo/{bar:[0-9]+}/baz
|
12
15
|
*
|
13
16
|
*/
|
14
|
-
|
17
|
+
class PathTemplate {
|
15
18
|
_path;
|
16
19
|
_parts = [];
|
17
20
|
constructor(pathTemplate) {
|
@@ -108,9 +111,11 @@ export class PathTemplate {
|
|
108
111
|
return 'tmpl: ' + this.path;
|
109
112
|
}
|
110
113
|
}
|
114
|
+
exports.PathTemplate = PathTemplate;
|
111
115
|
/**
|
112
116
|
* Parses a path into a RESTPath
|
113
117
|
*/
|
114
|
-
|
118
|
+
function pathTemplateParser(path) {
|
115
119
|
return new PathTemplate(path);
|
116
120
|
}
|
121
|
+
exports.pathTemplateParser = pathTemplateParser;
|
@@ -1,40 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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.getBindHost = exports.isLinux = exports.isMac = exports.isWindows = exports.readYML = exports.normalizeKapetaUri = exports.getBlockInstanceContainerName = void 0;
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
8
|
+
const yaml_1 = __importDefault(require("yaml"));
|
9
|
+
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
10
|
+
const md5_1 = __importDefault(require("md5"));
|
11
|
+
function getBlockInstanceContainerName(systemId, instanceId) {
|
12
|
+
return `kapeta-block-instance-${(0, md5_1.default)(systemId + instanceId)}`;
|
7
13
|
}
|
8
|
-
|
14
|
+
exports.getBlockInstanceContainerName = getBlockInstanceContainerName;
|
15
|
+
function normalizeKapetaUri(uri) {
|
9
16
|
if (!uri) {
|
10
17
|
return '';
|
11
18
|
}
|
12
|
-
const uriObj = parseKapetaUri(uri);
|
19
|
+
const uriObj = (0, nodejs_utils_1.parseKapetaUri)(uri);
|
13
20
|
if (!uriObj.version) {
|
14
|
-
return `kapeta://${parseKapetaUri(uri).fullName}`;
|
21
|
+
return `kapeta://${(0, nodejs_utils_1.parseKapetaUri)(uri).fullName}`;
|
15
22
|
}
|
16
|
-
return `kapeta://${parseKapetaUri(uri).id}`;
|
23
|
+
return `kapeta://${(0, nodejs_utils_1.parseKapetaUri)(uri).id}`;
|
17
24
|
}
|
18
|
-
|
19
|
-
|
25
|
+
exports.normalizeKapetaUri = normalizeKapetaUri;
|
26
|
+
function readYML(path) {
|
27
|
+
const rawYaml = node_fs_1.default.readFileSync(path);
|
20
28
|
try {
|
21
|
-
return
|
29
|
+
return yaml_1.default.parse(rawYaml.toString());
|
22
30
|
}
|
23
31
|
catch (err) {
|
24
32
|
throw new Error(`Failed to parse plan YAML: ${err}`);
|
25
33
|
}
|
26
34
|
}
|
27
|
-
|
35
|
+
exports.readYML = readYML;
|
36
|
+
function isWindows() {
|
28
37
|
return 'win32' === process.platform;
|
29
38
|
}
|
30
|
-
|
39
|
+
exports.isWindows = isWindows;
|
40
|
+
function isMac() {
|
31
41
|
return 'darwin' === process.platform;
|
32
42
|
}
|
33
|
-
|
43
|
+
exports.isMac = isMac;
|
44
|
+
function isLinux() {
|
34
45
|
return !isWindows() && !isMac();
|
35
46
|
}
|
36
|
-
|
47
|
+
exports.isLinux = isLinux;
|
48
|
+
function getBindHost(preferredHost = '127.0.0.1') {
|
37
49
|
// On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
|
38
50
|
// TODO: This might pose a security risk - so we should authenticate all requests using a shared secret/nonce that we pass around.
|
39
51
|
return isLinux() ? '0.0.0.0' : preferredHost;
|
40
52
|
}
|
53
|
+
exports.getBindHost = getBindHost;
|
package/dist/esm/start.js
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
|
2
|
-
|
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
|
3
8
|
.start()
|
4
9
|
.then(({ host, port }) => console.log('Listening on port %s:%s', host, port))
|
5
10
|
.catch((e) => {
|
package/index.ts
CHANGED
@@ -22,6 +22,8 @@ import { getBindHost } from './src/utils/utils';
|
|
22
22
|
import request from 'request';
|
23
23
|
import { repositoryManager } from './src/repositoryManager';
|
24
24
|
import { ensureCLI } from './src/utils/commandLineUtils';
|
25
|
+
import { defaultProviderInstaller } from './src/utils/DefaultProviderInstaller';
|
26
|
+
import { authManager } from './src/authManager';
|
25
27
|
|
26
28
|
export type LocalClusterService = HTTP.Server & { host?: string; port?: number };
|
27
29
|
|
@@ -122,6 +124,8 @@ export default {
|
|
122
124
|
);
|
123
125
|
}
|
124
126
|
|
127
|
+
await defaultProviderInstaller.checkForDefault();
|
128
|
+
|
125
129
|
const clusterPort = storageService.get('cluster', 'port');
|
126
130
|
if (clusterPort) {
|
127
131
|
clusterService.setClusterServicePort(clusterPort);
|
@@ -144,6 +148,7 @@ export default {
|
|
144
148
|
}
|
145
149
|
|
146
150
|
await clusterService.init();
|
151
|
+
await authManager.listenForChanges();
|
147
152
|
|
148
153
|
currentServer = createServer();
|
149
154
|
|
@@ -174,7 +179,7 @@ export default {
|
|
174
179
|
|
175
180
|
const bindHost = getBindHost(host);
|
176
181
|
|
177
|
-
currentServer.listen(port, bindHost, () => {
|
182
|
+
currentServer.listen(port, bindHost, async () => {
|
178
183
|
try {
|
179
184
|
ensureCLI().catch((e: any) => console.error('Failed to install CLI.', e));
|
180
185
|
} catch (e: any) {
|
@@ -183,7 +188,7 @@ export default {
|
|
183
188
|
|
184
189
|
try {
|
185
190
|
// Start installation process for all default providers
|
186
|
-
repositoryManager.ensureDefaultProviders();
|
191
|
+
await repositoryManager.ensureDefaultProviders();
|
187
192
|
} catch (e: any) {
|
188
193
|
console.error('Failed to install default providers.', e);
|
189
194
|
}
|