@kapeta/local-cluster-service 0.35.0 → 0.36.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 +7 -0
- package/dist/cjs/src/containerManager.js +3 -3
- package/dist/cjs/src/instanceManager.d.ts +7 -3
- package/dist/cjs/src/instanceManager.js +143 -63
- package/dist/cjs/src/operatorManager.d.ts +7 -7
- package/dist/cjs/src/operatorManager.js +19 -19
- package/dist/cjs/src/types.d.ts +1 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +2 -13
- package/dist/cjs/src/utils/BlockInstanceRunner.js +89 -81
- package/dist/cjs/src/utils/utils.d.ts +1 -1
- package/dist/cjs/src/utils/utils.js +24 -1
- package/dist/esm/src/containerManager.js +3 -3
- package/dist/esm/src/instanceManager.d.ts +7 -3
- package/dist/esm/src/instanceManager.js +143 -63
- package/dist/esm/src/operatorManager.d.ts +7 -7
- package/dist/esm/src/operatorManager.js +19 -19
- package/dist/esm/src/types.d.ts +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +2 -13
- package/dist/esm/src/utils/BlockInstanceRunner.js +89 -81
- package/dist/esm/src/utils/utils.d.ts +1 -1
- package/dist/esm/src/utils/utils.js +24 -1
- package/package.json +1 -1
- package/src/containerManager.ts +3 -3
- package/src/instanceManager.ts +193 -77
- package/src/operatorManager.ts +21 -18
- package/src/types.ts +1 -0
- package/src/utils/BlockInstanceRunner.ts +114 -94
- package/src/utils/utils.ts +27 -1
@@ -22,6 +22,7 @@ import { AnyMap, BlockProcessParams, InstanceType, LocalImageOptions, ProcessInf
|
|
22
22
|
import { definitionsManager } from '../definitionsManager';
|
23
23
|
import Docker from 'dockerode';
|
24
24
|
import OS from 'node:os';
|
25
|
+
import { taskManager } from '../taskManager';
|
25
26
|
|
26
27
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
27
28
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
@@ -201,7 +202,7 @@ export class BlockInstanceRunner {
|
|
201
202
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
202
203
|
}
|
203
204
|
|
204
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
205
|
+
const containerName = await getBlockInstanceContainerName(this._systemId, blockInstance.id, targetKindUri.id);
|
205
206
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
206
207
|
const dockerOpts = localContainer.options ?? {};
|
207
208
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
@@ -322,7 +323,7 @@ export class BlockInstanceRunner {
|
|
322
323
|
providerVersion
|
323
324
|
);
|
324
325
|
|
325
|
-
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
326
|
+
const containerName = await getBlockInstanceContainerName(this._systemId, blockInstance.id, kindUri.id);
|
326
327
|
|
327
328
|
// For windows we need to default to root
|
328
329
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
@@ -352,16 +353,7 @@ export class BlockInstanceRunner {
|
|
352
353
|
});
|
353
354
|
}
|
354
355
|
|
355
|
-
|
356
|
-
*
|
357
|
-
* @param blockInstance
|
358
|
-
* @param blockUri
|
359
|
-
* @param providerDefinition
|
360
|
-
* @param {{[key:string]:string}} env
|
361
|
-
* @return {Promise<ProcessDetails>}
|
362
|
-
* @private
|
363
|
-
*/
|
364
|
-
async _startOperatorProcess(
|
356
|
+
private async _startOperatorProcess(
|
365
357
|
blockInstance: BlockProcessParams,
|
366
358
|
blockUri: KapetaURI,
|
367
359
|
providerDefinition: DefinitionInfo,
|
@@ -388,93 +380,121 @@ export class BlockInstanceRunner {
|
|
388
380
|
const local = spec.local as LocalImageOptions;
|
389
381
|
|
390
382
|
const dockerImage = local.image;
|
383
|
+
const operatorUri = local.singleton ? parseKapetaUri(providerRef) : blockUri;
|
384
|
+
const operatorId = local.singleton ? providerRef : blockInstance.id;
|
385
|
+
const operatorRef = local.singleton ? providerRef : blockInstance.ref;
|
391
386
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
const bindHost = getBindHost();
|
397
|
-
|
398
|
-
const ExposedPorts: AnyMap = {};
|
399
|
-
const addonEnv: StringMap = {};
|
400
|
-
const PortBindings: AnyMap = {};
|
401
|
-
let HealthCheck = undefined;
|
402
|
-
let Mounts: DockerMounts[] = [];
|
403
|
-
const localPorts = local.ports ?? {};
|
404
|
-
const labels: { [key: string]: string } = {};
|
405
|
-
const promises = Object.entries(localPorts).map(async ([portType, value]) => {
|
406
|
-
const portInfo = toPortInfo(value);
|
407
|
-
const dockerPort = `${portInfo.port}/${portInfo.type}`;
|
408
|
-
ExposedPorts[dockerPort] = {};
|
409
|
-
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = `${portInfo.port}`;
|
410
|
-
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
411
|
-
PortBindings[dockerPort] = [
|
412
|
-
{
|
413
|
-
HostIp: bindHost,
|
414
|
-
HostPort: `${publicPort}`,
|
415
|
-
},
|
416
|
-
];
|
417
|
-
|
418
|
-
labels[CONTAINER_LABEL_PORT_PREFIX + publicPort] = portType;
|
419
|
-
});
|
420
|
-
|
421
|
-
await Promise.all(promises);
|
422
|
-
|
423
|
-
if (local.env) {
|
424
|
-
Object.entries(local.env).forEach(([key, value]) => {
|
425
|
-
addonEnv[key] = value as string;
|
426
|
-
});
|
427
|
-
}
|
428
|
-
|
429
|
-
if (local.mounts) {
|
430
|
-
Mounts = await containerManager.createVolumes(this._systemId, blockUri.id, local.mounts);
|
387
|
+
if (local.singleton && env) {
|
388
|
+
env[KAPETA_BLOCK_REF] = operatorRef;
|
389
|
+
env[KAPETA_INSTANCE_ID] = operatorId;
|
431
390
|
}
|
432
391
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
392
|
+
const containerName = await getBlockInstanceContainerName(this._systemId, blockInstance.id, providerRef);
|
393
|
+
|
394
|
+
const task = taskManager.add(
|
395
|
+
`container:start:${containerName}`,
|
396
|
+
async () => {
|
397
|
+
const logs = new LogData();
|
398
|
+
|
399
|
+
const bindHost = getBindHost();
|
400
|
+
|
401
|
+
const ExposedPorts: AnyMap = {};
|
402
|
+
const addonEnv: StringMap = {};
|
403
|
+
const PortBindings: AnyMap = {};
|
404
|
+
let HealthCheck = undefined;
|
405
|
+
let Mounts: DockerMounts[] = [];
|
406
|
+
const localPorts = local.ports ?? {};
|
407
|
+
const labels: { [key: string]: string } = {};
|
408
|
+
const promises = Object.entries(localPorts).map(async ([portType, value]) => {
|
409
|
+
const portInfo = toPortInfo(value);
|
410
|
+
const dockerPort = `${portInfo.port}/${portInfo.type}`;
|
411
|
+
ExposedPorts[dockerPort] = {};
|
412
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = `${portInfo.port}`;
|
413
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, operatorId, portType);
|
414
|
+
PortBindings[dockerPort] = [
|
415
|
+
{
|
416
|
+
HostIp: bindHost,
|
417
|
+
HostPort: `${publicPort}`,
|
418
|
+
},
|
419
|
+
];
|
420
|
+
|
421
|
+
labels[CONTAINER_LABEL_PORT_PREFIX + publicPort] = portType;
|
422
|
+
});
|
423
|
+
|
424
|
+
await Promise.all(promises);
|
425
|
+
|
426
|
+
if (local.env) {
|
427
|
+
Object.entries(local.env).forEach(([key, value]) => {
|
428
|
+
addonEnv[key] = value as string;
|
429
|
+
});
|
430
|
+
}
|
431
|
+
|
432
|
+
if (local.mounts) {
|
433
|
+
Mounts = await containerManager.createVolumes(this._systemId, operatorUri.id, local.mounts);
|
434
|
+
}
|
435
|
+
|
436
|
+
if (local.health) {
|
437
|
+
HealthCheck = containerManager.toDockerHealth(local.health);
|
438
|
+
}
|
439
|
+
|
440
|
+
// For windows we need to default to root
|
441
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
442
|
+
|
443
|
+
const Binds = local.singleton
|
444
|
+
? [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`]
|
445
|
+
: [
|
446
|
+
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
447
|
+
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
448
|
+
];
|
449
|
+
|
450
|
+
const systemUri = parseKapetaUri(this._systemId);
|
451
|
+
|
452
|
+
console.log(
|
453
|
+
`Ensuring container for operator block: ${containerName} [singleton: ${!!local.singleton}]`
|
454
|
+
);
|
455
|
+
|
456
|
+
logs.addLog(`Ensuring container for operator block: ${containerName}`);
|
457
|
+
const out = await this.ensureContainer({
|
458
|
+
Image: dockerImage,
|
459
|
+
name: containerName,
|
460
|
+
ExposedPorts,
|
461
|
+
HealthCheck,
|
462
|
+
HostConfig: {
|
463
|
+
Binds,
|
464
|
+
PortBindings,
|
465
|
+
Mounts,
|
466
|
+
},
|
467
|
+
Labels: {
|
468
|
+
...labels,
|
469
|
+
instance: operatorId,
|
470
|
+
[COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
|
471
|
+
[COMPOSE_LABEL_SERVICE]: operatorUri.id.replace(/[^a-z0-9]/gi, '_'),
|
472
|
+
},
|
473
|
+
Env: [
|
474
|
+
`KAPETA_INSTANCE_NAME=${operatorRef}`,
|
475
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
476
|
+
...DOCKER_ENV_VARS,
|
477
|
+
...Object.entries({
|
478
|
+
...env,
|
479
|
+
...addonEnv,
|
480
|
+
}).map(([key, value]) => `${key}=${value}`),
|
481
|
+
],
|
482
|
+
});
|
483
|
+
|
484
|
+
const portTypes = local.ports ? Object.keys(local.ports) : [];
|
485
|
+
if (portTypes.length > 0) {
|
486
|
+
out.portType = portTypes[0];
|
487
|
+
}
|
488
|
+
|
489
|
+
return out;
|
460
490
|
},
|
461
|
-
|
462
|
-
`
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
...env,
|
467
|
-
...addonEnv,
|
468
|
-
}).map(([key, value]) => `${key}=${value}`),
|
469
|
-
],
|
470
|
-
});
|
471
|
-
|
472
|
-
const portTypes = local.ports ? Object.keys(local.ports) : [];
|
473
|
-
if (portTypes.length > 0) {
|
474
|
-
out.portType = portTypes[0];
|
475
|
-
}
|
491
|
+
{
|
492
|
+
name: `Starting container for ${providerRef}`,
|
493
|
+
systemId: this._systemId,
|
494
|
+
}
|
495
|
+
);
|
476
496
|
|
477
|
-
return
|
497
|
+
return task.wait();
|
478
498
|
}
|
479
499
|
|
480
500
|
private async getDockerPortBindings(
|
package/src/utils/utils.ts
CHANGED
@@ -10,8 +10,34 @@ import { EntityList } from '@kapeta/schemas';
|
|
10
10
|
import _ from 'lodash';
|
11
11
|
import { AnyMap, PortInfo } from '../types';
|
12
12
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
13
|
+
import { definitionsManager } from '../definitionsManager';
|
14
|
+
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
15
|
+
import { KIND_BLOCK_OPERATOR } from '../operatorManager';
|
16
|
+
import { assetManager } from '../assetManager';
|
17
|
+
|
18
|
+
export async function getBlockInstanceContainerName(systemId: string, instanceId: string, blockType?: string) {
|
19
|
+
if (!blockType) {
|
20
|
+
const instance = await assetManager.getBlockInstance(systemId, instanceId);
|
21
|
+
if (!instance) {
|
22
|
+
throw new Error(`Instance ${instanceId} not found in plan ${systemId}`);
|
23
|
+
}
|
24
|
+
const block = await assetManager.getAsset(instance.block.ref);
|
25
|
+
if (!block) {
|
26
|
+
throw new Error(`Block ${instance.block.ref} not found`);
|
27
|
+
}
|
28
|
+
blockType = block.data.kind;
|
29
|
+
}
|
30
|
+
const typeDefinition = await definitionsManager.getDefinition(blockType);
|
31
|
+
if (!typeDefinition) {
|
32
|
+
throw new Error(`Block type ${blockType} not found`);
|
33
|
+
}
|
34
|
+
if (
|
35
|
+
parseKapetaUri(typeDefinition.definition.kind).fullName === KIND_BLOCK_OPERATOR &&
|
36
|
+
typeDefinition.definition.spec?.local?.singleton
|
37
|
+
) {
|
38
|
+
return `kapeta-instance-operator-${md5(systemId + blockType)}`;
|
39
|
+
}
|
13
40
|
|
14
|
-
export function getBlockInstanceContainerName(systemId: string, instanceId: string) {
|
15
41
|
return `kapeta-block-instance-${md5(systemId + instanceId)}`;
|
16
42
|
}
|
17
43
|
|