@kapeta/local-cluster-service 0.10.0 → 0.11.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 +14 -0
- package/dist/cjs/src/containerManager.d.ts +6 -4
- package/dist/cjs/src/containerManager.js +100 -45
- package/dist/cjs/src/definitionsManager.d.ts +1 -0
- package/dist/cjs/src/definitionsManager.js +7 -0
- package/dist/cjs/src/instanceManager.d.ts +2 -1
- package/dist/cjs/src/instanceManager.js +29 -46
- package/dist/cjs/src/instances/routes.js +10 -4
- package/dist/cjs/src/operatorManager.js +8 -6
- package/dist/cjs/src/repositoryManager.js +4 -4
- package/dist/cjs/src/types.d.ts +0 -9
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +3 -2
- package/dist/cjs/src/utils/BlockInstanceRunner.js +49 -95
- package/dist/cjs/src/utils/utils.d.ts +1 -1
- package/dist/cjs/src/utils/utils.js +3 -2
- package/dist/esm/src/containerManager.d.ts +6 -4
- package/dist/esm/src/containerManager.js +100 -45
- package/dist/esm/src/definitionsManager.d.ts +1 -0
- package/dist/esm/src/definitionsManager.js +7 -0
- package/dist/esm/src/instanceManager.d.ts +2 -1
- package/dist/esm/src/instanceManager.js +29 -46
- package/dist/esm/src/instances/routes.js +10 -4
- package/dist/esm/src/operatorManager.js +8 -6
- package/dist/esm/src/repositoryManager.js +4 -4
- package/dist/esm/src/types.d.ts +0 -9
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +3 -2
- package/dist/esm/src/utils/BlockInstanceRunner.js +49 -95
- package/dist/esm/src/utils/utils.d.ts +1 -1
- package/dist/esm/src/utils/utils.js +3 -2
- package/package.json +1 -1
- package/src/containerManager.ts +126 -49
- package/src/definitionsManager.ts +8 -0
- package/src/instanceManager.ts +35 -50
- package/src/instances/routes.ts +9 -4
- package/src/operatorManager.ts +9 -8
- package/src/repositoryManager.ts +5 -5
- package/src/types.ts +0 -7
- package/src/utils/BlockInstanceRunner.ts +74 -109
- package/src/utils/LogData.ts +1 -0
- package/src/utils/utils.ts +3 -2
package/src/instanceManager.ts
CHANGED
@@ -67,6 +67,37 @@ export class InstanceManager {
|
|
67
67
|
return this._instances.find((i) => i.systemId === systemId && i.instanceId === instanceId);
|
68
68
|
}
|
69
69
|
|
70
|
+
|
71
|
+
public async getLogs(systemId: string, instanceId: string):Promise<LogEntry[]> {
|
72
|
+
const instance = this.getInstance(systemId, instanceId);
|
73
|
+
if (!instance) {
|
74
|
+
throw new Error(`Instance ${systemId}/${instanceId} not found`);
|
75
|
+
}
|
76
|
+
|
77
|
+
switch (instance.type) {
|
78
|
+
case InstanceType.DOCKER:
|
79
|
+
return await containerManager.getLogs(instance);
|
80
|
+
|
81
|
+
case InstanceType.UNKNOWN:
|
82
|
+
return [{
|
83
|
+
level: 'INFO',
|
84
|
+
message: 'Instance is starting...',
|
85
|
+
time: Date.now(),
|
86
|
+
source: 'stdout',
|
87
|
+
}];
|
88
|
+
|
89
|
+
case InstanceType.LOCAL:
|
90
|
+
return [{
|
91
|
+
level: 'INFO',
|
92
|
+
message: 'Instance started outside Kapeta - logs not available...',
|
93
|
+
time: Date.now(),
|
94
|
+
source: 'stdout',
|
95
|
+
}];
|
96
|
+
}
|
97
|
+
|
98
|
+
return [];
|
99
|
+
}
|
100
|
+
|
70
101
|
public async saveInternalInstance(instance: InstanceInfo) {
|
71
102
|
instance.systemId = normalizeKapetaUri(instance.systemId);
|
72
103
|
if (instance.ref) {
|
@@ -143,7 +174,6 @@ export class InstanceManager {
|
|
143
174
|
|
144
175
|
instance.desiredStatus = info.desiredStatus;
|
145
176
|
instance.owner = info.owner;
|
146
|
-
instance.internal = undefined;
|
147
177
|
instance.status = InstanceStatus.STARTING;
|
148
178
|
instance.startedAt = Date.now();
|
149
179
|
}
|
@@ -260,7 +290,7 @@ export class InstanceManager {
|
|
260
290
|
|
261
291
|
try {
|
262
292
|
if (instance.type === 'docker') {
|
263
|
-
const containerName = getBlockInstanceContainerName(instance.instanceId);
|
293
|
+
const containerName = getBlockInstanceContainerName(instance.systemId, instance.instanceId);
|
264
294
|
const container = await containerManager.getContainerByName(containerName);
|
265
295
|
if (container) {
|
266
296
|
try {
|
@@ -350,7 +380,7 @@ export class InstanceManager {
|
|
350
380
|
name: blockAsset.data.metadata.name,
|
351
381
|
desiredStatus: DesiredInstanceStatus.RUN,
|
352
382
|
owner: InstanceOwner.INTERNAL,
|
353
|
-
type: InstanceType.UNKNOWN,
|
383
|
+
type: existingInstance?.type ?? InstanceType.UNKNOWN,
|
354
384
|
status: InstanceStatus.STARTING,
|
355
385
|
startedAt: Date.now(),
|
356
386
|
};
|
@@ -374,45 +404,6 @@ export class InstanceManager {
|
|
374
404
|
const startTime = Date.now();
|
375
405
|
try {
|
376
406
|
const processInfo = await runner.start(blockRef, instanceId, instanceConfig);
|
377
|
-
//emit stdout/stderr via sockets
|
378
|
-
processInfo.output.on('data', (data: Buffer) => {
|
379
|
-
const payload = {
|
380
|
-
source: 'stdout',
|
381
|
-
level: 'INFO',
|
382
|
-
message: data.toString(),
|
383
|
-
time: Date.now(),
|
384
|
-
};
|
385
|
-
this.emitInstanceEvent(systemId, instanceId, EVENT_INSTANCE_LOG, payload);
|
386
|
-
});
|
387
|
-
|
388
|
-
processInfo.output.on('exit', (exitCode: number) => {
|
389
|
-
const timeRunning = Date.now() - startTime;
|
390
|
-
const instance = this.getInstance(systemId, instanceId);
|
391
|
-
if (instance?.status === InstanceStatus.READY) {
|
392
|
-
//It's already been running
|
393
|
-
return;
|
394
|
-
}
|
395
|
-
|
396
|
-
if (exitCode === 143 || exitCode === 137) {
|
397
|
-
//Process got SIGTERM (143) or SIGKILL (137)
|
398
|
-
//TODO: Windows?
|
399
|
-
return;
|
400
|
-
}
|
401
|
-
|
402
|
-
if (exitCode !== 0 || timeRunning < MIN_TIME_RUNNING) {
|
403
|
-
const instance = this.getInstance(systemId, instanceId);
|
404
|
-
if (instance) {
|
405
|
-
instance.status = InstanceStatus.FAILED;
|
406
|
-
this.save();
|
407
|
-
}
|
408
|
-
|
409
|
-
this.emitSystemEvent(systemId, EVENT_INSTANCE_EXITED, {
|
410
|
-
error: 'Failed to start instance',
|
411
|
-
status: EVENT_INSTANCE_EXITED,
|
412
|
-
instanceId: blockInstance.id,
|
413
|
-
});
|
414
|
-
}
|
415
|
-
});
|
416
407
|
|
417
408
|
instance.status = InstanceStatus.READY;
|
418
409
|
|
@@ -423,10 +414,6 @@ export class InstanceManager {
|
|
423
414
|
health: null,
|
424
415
|
portType: processInfo.portType,
|
425
416
|
status: InstanceStatus.READY,
|
426
|
-
internal: {
|
427
|
-
logs: processInfo.logs,
|
428
|
-
output: processInfo.output,
|
429
|
-
},
|
430
417
|
});
|
431
418
|
} catch (e: any) {
|
432
419
|
console.warn('Failed to start instance', e);
|
@@ -482,9 +469,7 @@ export class InstanceManager {
|
|
482
469
|
storageService.put(
|
483
470
|
'instances',
|
484
471
|
this._instances.map((instance) => {
|
485
|
-
|
486
|
-
delete copy.internal;
|
487
|
-
return copy;
|
472
|
+
return { ...instance };
|
488
473
|
})
|
489
474
|
);
|
490
475
|
} catch (e) {
|
@@ -612,7 +597,7 @@ export class InstanceManager {
|
|
612
597
|
|
613
598
|
private async getExternalStatus(instance: InstanceInfo): Promise<InstanceStatus> {
|
614
599
|
if (instance.type === InstanceType.DOCKER) {
|
615
|
-
const containerName = getBlockInstanceContainerName(instance.instanceId);
|
600
|
+
const containerName = getBlockInstanceContainerName(instance.systemId, instance.instanceId);
|
616
601
|
const container = await containerManager.getContainerByName(containerName);
|
617
602
|
if (!container) {
|
618
603
|
// If the container doesn't exist, we consider the instance stopped
|
package/src/instances/routes.ts
CHANGED
@@ -74,16 +74,21 @@ router.post('/:systemId/:instanceId/stop', async (req: Request, res: Response) =
|
|
74
74
|
/**
|
75
75
|
* Get logs for instance in a plan
|
76
76
|
*/
|
77
|
-
router.get('/:systemId/:instanceId/logs', (req: Request, res: Response) => {
|
77
|
+
router.get('/:systemId/:instanceId/logs', async (req: Request, res: Response) => {
|
78
78
|
const instanceInfo = instanceManager.getInstance(req.params.systemId, req.params.instanceId);
|
79
79
|
if (!instanceInfo) {
|
80
80
|
res.status(404).send({ ok: false });
|
81
81
|
return;
|
82
82
|
}
|
83
83
|
|
84
|
-
|
85
|
-
logs
|
86
|
-
|
84
|
+
try {
|
85
|
+
const logs = await instanceManager.getLogs(req.params.systemId, req.params.instanceId);
|
86
|
+
res.status(200).send({
|
87
|
+
logs,
|
88
|
+
});
|
89
|
+
} catch (e:any) {
|
90
|
+
res.status(500).send({ ok: false, error: e.message });
|
91
|
+
}
|
87
92
|
});
|
88
93
|
|
89
94
|
/**
|
package/src/operatorManager.ts
CHANGED
@@ -162,16 +162,12 @@ class OperatorManager {
|
|
162
162
|
|
163
163
|
portTypes.sort();
|
164
164
|
|
165
|
-
const containerBaseName = 'kapeta-resource';
|
166
|
-
|
167
|
-
const nameParts = [resourceType.toLowerCase()];
|
168
|
-
|
169
165
|
const ports: AnyMap = {};
|
170
166
|
|
171
167
|
for (let i = 0; i < portTypes.length; i++) {
|
172
168
|
const portType = portTypes[i];
|
173
169
|
let containerPortInfo = operatorData.ports[portType];
|
174
|
-
const hostPort = await serviceManager.ensureServicePort(resourceType, portType);
|
170
|
+
const hostPort = await serviceManager.ensureServicePort(systemId, resourceType, portType);
|
175
171
|
|
176
172
|
if (typeof containerPortInfo === 'number' || typeof containerPortInfo === 'string') {
|
177
173
|
containerPortInfo = { port: containerPortInfo, type: 'tcp' };
|
@@ -182,7 +178,6 @@ class OperatorManager {
|
|
182
178
|
}
|
183
179
|
|
184
180
|
const portId = containerPortInfo.port + '/' + containerPortInfo.type;
|
185
|
-
nameParts.push(portType + '-' + portId + '-' + hostPort);
|
186
181
|
|
187
182
|
ports[portId] = {
|
188
183
|
type: portType,
|
@@ -190,9 +185,15 @@ class OperatorManager {
|
|
190
185
|
};
|
191
186
|
}
|
192
187
|
|
193
|
-
const mounts = containerManager.createMounts(resourceType, operatorData.mounts);
|
188
|
+
const mounts = await containerManager.createMounts(systemId, resourceType, operatorData.mounts);
|
189
|
+
|
190
|
+
const nameParts = [
|
191
|
+
systemId,
|
192
|
+
resourceType.toLowerCase(),
|
193
|
+
version
|
194
|
+
];
|
194
195
|
|
195
|
-
const containerName =
|
196
|
+
const containerName = `kapeta-resource-${md5(nameParts.join('_'))}`;
|
196
197
|
|
197
198
|
const PortBindings: { [key: string]: any } = {};
|
198
199
|
const Env: string[] = [];
|
package/src/repositoryManager.ts
CHANGED
@@ -2,7 +2,7 @@ import FS from 'node:fs';
|
|
2
2
|
import os from 'node:os';
|
3
3
|
import Path from 'node:path';
|
4
4
|
import watch from 'recursive-watch';
|
5
|
-
import FSExtra
|
5
|
+
import FSExtra from 'fs-extra';
|
6
6
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
7
7
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
8
8
|
import { socketManager } from './socketManager';
|
@@ -119,9 +119,11 @@ class RepositoryManager {
|
|
119
119
|
this._installQueue.push(async () => {
|
120
120
|
try {
|
121
121
|
const normalizedRefs = refs.map((ref) => parseKapetaUri(ref).id);
|
122
|
-
const filteredRefs = normalizedRefs
|
123
|
-
|
122
|
+
const filteredRefs = normalizedRefs
|
123
|
+
.filter((ref) => !INSTALL_ATTEMPTED[ref])
|
124
|
+
.filter((ref) => !definitionsManager.exists(ref));
|
124
125
|
if (filteredRefs.length > 0) {
|
126
|
+
console.log(`Auto-installing dependencies: ${filteredRefs.join(', ')}`);
|
125
127
|
filteredRefs.forEach((ref) => (INSTALL_ATTEMPTED[ref] = true));
|
126
128
|
//Auto-install missing asset
|
127
129
|
try {
|
@@ -218,13 +220,11 @@ class RepositoryManager {
|
|
218
220
|
|
219
221
|
this._cache[ref] = true;
|
220
222
|
if (!installedAsset) {
|
221
|
-
console.log(`Auto-installing missing asset: ${ref}`);
|
222
223
|
await this._install([ref]);
|
223
224
|
} else {
|
224
225
|
//Ensure dependencies are installed
|
225
226
|
const refs = assetVersion.dependencies.map((dep: Dependency) => dep.name);
|
226
227
|
if (refs.length > 0) {
|
227
|
-
console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
|
228
228
|
await this._install(refs);
|
229
229
|
}
|
230
230
|
}
|
package/src/types.ts
CHANGED
@@ -53,10 +53,7 @@ export enum DesiredInstanceStatus {
|
|
53
53
|
export type ProcessInfo = {
|
54
54
|
type: InstanceType;
|
55
55
|
pid?: number | string | null;
|
56
|
-
output: EventEmitter;
|
57
56
|
portType?: string;
|
58
|
-
logs: () => LogEntry[];
|
59
|
-
stop: () => Promise<void> | void;
|
60
57
|
};
|
61
58
|
|
62
59
|
export type InstanceInfo = {
|
@@ -75,10 +72,6 @@ export type InstanceInfo = {
|
|
75
72
|
pid?: number | string | null;
|
76
73
|
portType?: string;
|
77
74
|
|
78
|
-
internal?: {
|
79
|
-
output: EventEmitter;
|
80
|
-
logs: () => LogEntry[];
|
81
|
-
};
|
82
75
|
};
|
83
76
|
|
84
77
|
interface ResourceRef {
|
@@ -117,7 +117,7 @@ export class BlockInstanceRunner {
|
|
117
117
|
if (blockUri.version === 'local') {
|
118
118
|
processInfo = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
|
119
119
|
} else {
|
120
|
-
processInfo = await this._startDockerProcess(blockInstance, blockUri, env);
|
120
|
+
processInfo = await this._startDockerProcess(blockInstance, blockUri, env, assetVersion);
|
121
121
|
}
|
122
122
|
|
123
123
|
if (portTypes.length > 0) {
|
@@ -169,37 +169,17 @@ export class BlockInstanceRunner {
|
|
169
169
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
170
170
|
}
|
171
171
|
|
172
|
-
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
173
|
-
|
172
|
+
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
174
173
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
175
174
|
const dockerOpts = localContainer.options ?? {};
|
176
175
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
177
176
|
const workingDir = localContainer.workingDir ? localContainer.workingDir : '/workspace';
|
178
177
|
|
179
|
-
const
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
const portTypes = getProviderPorts(assetVersion);
|
186
|
-
let port = 80;
|
187
|
-
const promises = portTypes.map(async (portType) => {
|
188
|
-
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
189
|
-
const thisPort = port++; //TODO: Not sure how we should handle multiple ports or non-HTTP ports
|
190
|
-
const dockerPort = `${thisPort}/tcp`;
|
191
|
-
ExposedPorts[dockerPort] = {};
|
192
|
-
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = '' + thisPort;
|
193
|
-
|
194
|
-
PortBindings[dockerPort] = [
|
195
|
-
{
|
196
|
-
HostIp: bindHost,
|
197
|
-
HostPort: `${publicPort}`,
|
198
|
-
},
|
199
|
-
];
|
200
|
-
});
|
201
|
-
|
202
|
-
await Promise.all(promises);
|
178
|
+
const {
|
179
|
+
PortBindings,
|
180
|
+
ExposedPorts,
|
181
|
+
addonEnv
|
182
|
+
} = await this.getDockerPortBindings(blockInstance, assetVersion);
|
203
183
|
|
204
184
|
let HealthCheck = undefined;
|
205
185
|
if (localContainer.healthcheck) {
|
@@ -235,83 +215,7 @@ export class BlockInstanceRunner {
|
|
235
215
|
});
|
236
216
|
}
|
237
217
|
|
238
|
-
private async
|
239
|
-
const logs = new LogData();
|
240
|
-
|
241
|
-
const container = await containerManager.ensureContainer(opts);
|
242
|
-
|
243
|
-
try {
|
244
|
-
if (opts.HealthCheck) {
|
245
|
-
await containerManager.waitForHealthy(container);
|
246
|
-
} else {
|
247
|
-
await containerManager.waitForReady(container);
|
248
|
-
}
|
249
|
-
} catch (e: any) {
|
250
|
-
logs.addLog(e.message, 'ERROR');
|
251
|
-
}
|
252
|
-
|
253
|
-
return this._handleContainer(container, logs);
|
254
|
-
}
|
255
|
-
|
256
|
-
private async _handleContainer(
|
257
|
-
container: Container,
|
258
|
-
logs: LogData,
|
259
|
-
deleteOnExit: boolean = false
|
260
|
-
): Promise<ProcessInfo> {
|
261
|
-
let localContainer: Container | null = container;
|
262
|
-
const logStream = (await container.logs({
|
263
|
-
follow: true,
|
264
|
-
stdout: true,
|
265
|
-
stderr: true,
|
266
|
-
tail: LogData.MAX_LINES,
|
267
|
-
})) as EventEmitter;
|
268
|
-
|
269
|
-
const outputEvents = new EventEmitter();
|
270
|
-
logStream.on('data', (data) => {
|
271
|
-
logs.addLog(data.toString());
|
272
|
-
outputEvents.emit('data', data);
|
273
|
-
});
|
274
|
-
|
275
|
-
logStream.on('error', (data) => {
|
276
|
-
logs.addLog(data.toString());
|
277
|
-
outputEvents.emit('data', data);
|
278
|
-
});
|
279
|
-
|
280
|
-
logStream.on('close', async () => {
|
281
|
-
const status = await container.status();
|
282
|
-
const data = status.data as any;
|
283
|
-
if (deleteOnExit) {
|
284
|
-
try {
|
285
|
-
await containerManager.remove(container);
|
286
|
-
} catch (e: any) {}
|
287
|
-
}
|
288
|
-
outputEvents.emit('exit', data?.State?.ExitCode ?? 0);
|
289
|
-
});
|
290
|
-
|
291
|
-
return {
|
292
|
-
type: InstanceType.DOCKER,
|
293
|
-
pid: container.id,
|
294
|
-
output: outputEvents,
|
295
|
-
stop: async () => {
|
296
|
-
if (!localContainer) {
|
297
|
-
return;
|
298
|
-
}
|
299
|
-
|
300
|
-
try {
|
301
|
-
await localContainer.stop();
|
302
|
-
if (deleteOnExit) {
|
303
|
-
await containerManager.remove(localContainer);
|
304
|
-
}
|
305
|
-
} catch (e) {}
|
306
|
-
localContainer = null;
|
307
|
-
},
|
308
|
-
logs: () => {
|
309
|
-
return logs.getLogs();
|
310
|
-
},
|
311
|
-
};
|
312
|
-
}
|
313
|
-
|
314
|
-
private async _startDockerProcess(blockInstance: BlockProcessParams, blockInfo: KapetaURI, env: StringMap) {
|
218
|
+
private async _startDockerProcess(blockInstance: BlockProcessParams, blockInfo: KapetaURI, env: StringMap, assetVersion: DefinitionInfo) {
|
315
219
|
const { versionFile } = ClusterConfig.getRepositoryAssetInfoPath(
|
316
220
|
blockInfo.handle,
|
317
221
|
blockInfo.name,
|
@@ -333,8 +237,13 @@ export class BlockInstanceRunner {
|
|
333
237
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
334
238
|
}
|
335
239
|
|
336
|
-
const
|
337
|
-
|
240
|
+
const {
|
241
|
+
PortBindings,
|
242
|
+
ExposedPorts,
|
243
|
+
addonEnv
|
244
|
+
} = await this.getDockerPortBindings(blockInstance, assetVersion);
|
245
|
+
|
246
|
+
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
338
247
|
|
339
248
|
// For windows we need to default to root
|
340
249
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
@@ -342,16 +251,22 @@ export class BlockInstanceRunner {
|
|
342
251
|
return this.ensureContainer({
|
343
252
|
Image: dockerImage,
|
344
253
|
name: containerName,
|
254
|
+
ExposedPorts,
|
345
255
|
Labels: {
|
346
256
|
instance: blockInstance.id,
|
347
257
|
},
|
348
258
|
Env: [
|
349
259
|
...DOCKER_ENV_VARS,
|
350
260
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
351
|
-
...Object.entries(
|
261
|
+
...Object.entries({
|
262
|
+
...env,
|
263
|
+
...addonEnv
|
264
|
+
}).map(([key, value]) => `${key}=${value}`),
|
265
|
+
|
352
266
|
],
|
353
267
|
HostConfig: {
|
354
268
|
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
269
|
+
PortBindings,
|
355
270
|
},
|
356
271
|
});
|
357
272
|
}
|
@@ -391,7 +306,8 @@ export class BlockInstanceRunner {
|
|
391
306
|
|
392
307
|
const dockerImage = spec?.local?.image;
|
393
308
|
|
394
|
-
|
309
|
+
//We only want 1 operator per operator type - across all local systems
|
310
|
+
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
395
311
|
const logs = new LogData();
|
396
312
|
|
397
313
|
const bindHost = getBindHost();
|
@@ -425,7 +341,7 @@ export class BlockInstanceRunner {
|
|
425
341
|
}
|
426
342
|
|
427
343
|
if (spec.local?.mounts) {
|
428
|
-
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
344
|
+
const mounts = await containerManager.createMounts(this._systemId, blockUri.id, spec.local.mounts);
|
429
345
|
Mounts = containerManager.toDockerMounts(mounts);
|
430
346
|
}
|
431
347
|
|
@@ -471,4 +387,53 @@ export class BlockInstanceRunner {
|
|
471
387
|
|
472
388
|
return out;
|
473
389
|
}
|
390
|
+
|
391
|
+
|
392
|
+
private async getDockerPortBindings(blockInstance: BlockProcessParams, assetVersion: DefinitionInfo) {
|
393
|
+
const bindHost = getBindHost();
|
394
|
+
const ExposedPorts: AnyMap = {};
|
395
|
+
const addonEnv: StringMap = {};
|
396
|
+
const PortBindings: AnyMap = {};
|
397
|
+
|
398
|
+
const portTypes = getProviderPorts(assetVersion);
|
399
|
+
let port = 80;
|
400
|
+
const promises = portTypes.map(async (portType) => {
|
401
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
402
|
+
const thisPort = port++; //TODO: Not sure how we should handle multiple ports or non-HTTP ports
|
403
|
+
const dockerPort = `${thisPort}/tcp`;
|
404
|
+
ExposedPorts[dockerPort] = {};
|
405
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = '' + thisPort;
|
406
|
+
|
407
|
+
PortBindings[dockerPort] = [
|
408
|
+
{
|
409
|
+
HostIp: bindHost,
|
410
|
+
HostPort: `${publicPort}`,
|
411
|
+
},
|
412
|
+
];
|
413
|
+
});
|
414
|
+
|
415
|
+
|
416
|
+
await Promise.all(promises);
|
417
|
+
|
418
|
+
return {PortBindings,ExposedPorts, addonEnv};
|
419
|
+
}
|
420
|
+
|
421
|
+
private async ensureContainer(opts: any) {
|
422
|
+
const container = await containerManager.ensureContainer(opts);
|
423
|
+
|
424
|
+
await containerManager.waitForReady(container);
|
425
|
+
|
426
|
+
return this._handleContainer(container);
|
427
|
+
|
428
|
+
}
|
429
|
+
|
430
|
+
private async _handleContainer(
|
431
|
+
container: Container
|
432
|
+
): Promise<ProcessInfo> {
|
433
|
+
|
434
|
+
return {
|
435
|
+
type: InstanceType.DOCKER,
|
436
|
+
pid: container.id
|
437
|
+
};
|
438
|
+
}
|
474
439
|
}
|
package/src/utils/LogData.ts
CHANGED
package/src/utils/utils.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import FS from 'node:fs';
|
2
2
|
import YAML from 'yaml';
|
3
3
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
4
|
+
import md5 from "md5";
|
4
5
|
|
5
|
-
export function getBlockInstanceContainerName(instanceId: string) {
|
6
|
-
return `kapeta-block-instance-${instanceId}`;
|
6
|
+
export function getBlockInstanceContainerName(systemId:string, instanceId: string) {
|
7
|
+
return `kapeta-block-instance-${md5(systemId + instanceId)}`;
|
7
8
|
}
|
8
9
|
|
9
10
|
export function normalizeKapetaUri(uri: string) {
|