@kapeta/local-cluster-service 0.9.0 → 0.10.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 +7 -8
- package/dist/cjs/src/containerManager.js +78 -65
- package/dist/cjs/src/instanceManager.js +4 -2
- package/dist/cjs/src/operatorManager.js +40 -25
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +1 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +79 -170
- package/dist/esm/src/containerManager.d.ts +7 -8
- package/dist/esm/src/containerManager.js +77 -64
- package/dist/esm/src/instanceManager.js +4 -2
- package/dist/esm/src/operatorManager.js +42 -27
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.js +79 -170
- package/package.json +1 -1
- package/src/containerManager.ts +76 -71
- package/src/instanceManager.ts +8 -2
- package/src/operatorManager.ts +52 -26
- package/src/utils/BlockInstanceRunner.ts +88 -177
@@ -7,9 +7,10 @@ import { containerManager, DockerMounts, toLocalBindVolume } from '../containerM
|
|
7
7
|
import { LogData } from './LogData';
|
8
8
|
import EventEmitter from 'events';
|
9
9
|
import { clusterService } from '../clusterService';
|
10
|
-
import { AnyMap, BlockProcessParams,
|
10
|
+
import { AnyMap, BlockProcessParams, InstanceType, ProcessInfo, StringMap } from '../types';
|
11
11
|
import { Container } from 'node-docker-api/lib/container';
|
12
12
|
import { definitionsManager } from '../definitionsManager';
|
13
|
+
import md5 from 'md5';
|
13
14
|
|
14
15
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
15
16
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
@@ -169,28 +170,6 @@ export class BlockInstanceRunner {
|
|
169
170
|
}
|
170
171
|
|
171
172
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
172
|
-
const logs = new LogData();
|
173
|
-
logs.addLog(`Starting block ${blockInstance.ref}`);
|
174
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
175
|
-
let container = containerInfo?.native;
|
176
|
-
|
177
|
-
console.log('Starting dev container', containerName);
|
178
|
-
|
179
|
-
if (container) {
|
180
|
-
console.log(`Dev container already exists. Deleting...`);
|
181
|
-
try {
|
182
|
-
await container.delete({
|
183
|
-
force: true,
|
184
|
-
});
|
185
|
-
} catch (e: any) {
|
186
|
-
throw new Error('Failed to delete existing container: ' + e.message);
|
187
|
-
}
|
188
|
-
container = undefined;
|
189
|
-
}
|
190
|
-
|
191
|
-
logs.addLog(`Creating new container for block: ${containerName}`);
|
192
|
-
console.log('Creating new dev container', containerName, dockerImage);
|
193
|
-
await containerManager.pull(dockerImage);
|
194
173
|
|
195
174
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
196
175
|
const dockerOpts = localContainer.options ?? {};
|
@@ -227,8 +206,7 @@ export class BlockInstanceRunner {
|
|
227
206
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
228
207
|
}
|
229
208
|
|
230
|
-
|
231
|
-
container = await containerManager.startContainer({
|
209
|
+
return this.ensureContainer({
|
232
210
|
Image: dockerImage,
|
233
211
|
name: containerName,
|
234
212
|
WorkingDir: workingDir,
|
@@ -255,9 +233,15 @@ export class BlockInstanceRunner {
|
|
255
233
|
},
|
256
234
|
...dockerOpts,
|
257
235
|
});
|
236
|
+
}
|
237
|
+
|
238
|
+
private async ensureContainer(opts: any) {
|
239
|
+
const logs = new LogData();
|
240
|
+
|
241
|
+
const container = await containerManager.ensureContainer(opts);
|
258
242
|
|
259
243
|
try {
|
260
|
-
if (HealthCheck) {
|
244
|
+
if (opts.HealthCheck) {
|
261
245
|
await containerManager.waitForHealthy(container);
|
262
246
|
} else {
|
263
247
|
await containerManager.waitForReady(container);
|
@@ -298,7 +282,7 @@ export class BlockInstanceRunner {
|
|
298
282
|
const data = status.data as any;
|
299
283
|
if (deleteOnExit) {
|
300
284
|
try {
|
301
|
-
await
|
285
|
+
await containerManager.remove(container);
|
302
286
|
} catch (e: any) {}
|
303
287
|
}
|
304
288
|
outputEvents.emit('exit', data?.State?.ExitCode ?? 0);
|
@@ -316,7 +300,7 @@ export class BlockInstanceRunner {
|
|
316
300
|
try {
|
317
301
|
await localContainer.stop();
|
318
302
|
if (deleteOnExit) {
|
319
|
-
await
|
303
|
+
await containerManager.remove(localContainer);
|
320
304
|
}
|
321
305
|
} catch (e) {}
|
322
306
|
localContainer = null;
|
@@ -351,47 +335,25 @@ export class BlockInstanceRunner {
|
|
351
335
|
|
352
336
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
353
337
|
const logs = new LogData();
|
354
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
355
|
-
let container = containerInfo?.native;
|
356
338
|
|
357
339
|
// For windows we need to default to root
|
358
340
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
359
341
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
instance: blockInstance.id,
|
376
|
-
},
|
377
|
-
Env: [
|
378
|
-
...DOCKER_ENV_VARS,
|
379
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
380
|
-
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
381
|
-
],
|
382
|
-
HostConfig: {
|
383
|
-
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
384
|
-
},
|
385
|
-
});
|
386
|
-
|
387
|
-
try {
|
388
|
-
await containerManager.waitForReady(container);
|
389
|
-
} catch (e: any) {
|
390
|
-
logs.addLog(e.message, 'ERROR');
|
391
|
-
}
|
392
|
-
}
|
393
|
-
|
394
|
-
return this._handleContainer(container, logs);
|
342
|
+
return this.ensureContainer({
|
343
|
+
Image: dockerImage,
|
344
|
+
name: containerName,
|
345
|
+
Labels: {
|
346
|
+
instance: blockInstance.id,
|
347
|
+
},
|
348
|
+
Env: [
|
349
|
+
...DOCKER_ENV_VARS,
|
350
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
351
|
+
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
352
|
+
],
|
353
|
+
HostConfig: {
|
354
|
+
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
355
|
+
},
|
356
|
+
});
|
395
357
|
}
|
396
358
|
|
397
359
|
/**
|
@@ -429,130 +391,79 @@ export class BlockInstanceRunner {
|
|
429
391
|
|
430
392
|
const dockerImage = spec?.local?.image;
|
431
393
|
|
432
|
-
try {
|
433
|
-
await containerManager.pull(dockerImage);
|
434
|
-
} catch (e) {
|
435
|
-
console.warn('Failed to pull image. Continuing...', e);
|
436
|
-
}
|
437
|
-
|
438
394
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
439
395
|
const logs = new LogData();
|
440
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
441
|
-
let container = containerInfo?.native;
|
442
|
-
|
443
|
-
if (container) {
|
444
|
-
const containerData = container.data as any;
|
445
|
-
if (containerData.State === 'running') {
|
446
|
-
logs.addLog(`Found existing running container for block: ${containerName}`);
|
447
|
-
} else {
|
448
|
-
if (containerData.State?.ExitCode > 0) {
|
449
|
-
logs.addLog(`Container exited with code: ${containerData.State.ExitCode}. Deleting...`);
|
450
|
-
try {
|
451
|
-
await container.delete();
|
452
|
-
} catch (e) {}
|
453
|
-
container = undefined;
|
454
|
-
} else {
|
455
|
-
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
456
|
-
try {
|
457
|
-
await container.start();
|
458
|
-
} catch (e) {
|
459
|
-
console.warn('Failed to start container. Deleting...', e);
|
460
|
-
try {
|
461
|
-
await container.delete();
|
462
|
-
} catch (e) {}
|
463
|
-
container = undefined;
|
464
|
-
}
|
465
|
-
}
|
466
|
-
}
|
467
|
-
}
|
468
396
|
|
469
397
|
const bindHost = getBindHost();
|
470
398
|
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
{
|
489
|
-
HostIp: bindHost,
|
490
|
-
HostPort: `${publicPort}`,
|
491
|
-
},
|
492
|
-
];
|
493
|
-
}
|
494
|
-
);
|
495
|
-
|
496
|
-
await Promise.all(promises);
|
497
|
-
|
498
|
-
if (spec.local?.env) {
|
499
|
-
Object.entries(spec.local.env).forEach(([key, value]) => {
|
500
|
-
addonEnv[key] = value as string;
|
501
|
-
});
|
502
|
-
}
|
503
|
-
|
504
|
-
if (spec.local?.mounts) {
|
505
|
-
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
506
|
-
Mounts = containerManager.toDockerMounts(mounts);
|
399
|
+
const ExposedPorts: AnyMap = {};
|
400
|
+
const addonEnv: StringMap = {};
|
401
|
+
const PortBindings: AnyMap = {};
|
402
|
+
let HealthCheck = undefined;
|
403
|
+
let Mounts: DockerMounts[] = [];
|
404
|
+
const promises = Object.entries(spec.local.ports as { [p: string]: { port: string; type: string } }).map(
|
405
|
+
async ([portType, value]) => {
|
406
|
+
const dockerPort = `${value.port}/${value.type}`;
|
407
|
+
ExposedPorts[dockerPort] = {};
|
408
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
409
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
410
|
+
PortBindings[dockerPort] = [
|
411
|
+
{
|
412
|
+
HostIp: bindHost,
|
413
|
+
HostPort: `${publicPort}`,
|
414
|
+
},
|
415
|
+
];
|
507
416
|
}
|
417
|
+
);
|
508
418
|
|
509
|
-
|
510
|
-
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
511
|
-
}
|
419
|
+
await Promise.all(promises);
|
512
420
|
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
logs.addLog(`Creating new container for block: ${containerName}`);
|
517
|
-
container = await containerManager.startContainer({
|
518
|
-
Image: dockerImage,
|
519
|
-
name: containerName,
|
520
|
-
ExposedPorts,
|
521
|
-
HealthCheck,
|
522
|
-
HostConfig: {
|
523
|
-
Binds: [
|
524
|
-
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
525
|
-
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
526
|
-
],
|
527
|
-
PortBindings,
|
528
|
-
Mounts,
|
529
|
-
},
|
530
|
-
Labels: {
|
531
|
-
instance: blockInstance.id,
|
532
|
-
},
|
533
|
-
Env: [
|
534
|
-
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
535
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
536
|
-
...DOCKER_ENV_VARS,
|
537
|
-
...Object.entries({
|
538
|
-
...env,
|
539
|
-
...addonEnv,
|
540
|
-
}).map(([key, value]) => `${key}=${value}`),
|
541
|
-
],
|
421
|
+
if (spec.local?.env) {
|
422
|
+
Object.entries(spec.local.env).forEach(([key, value]) => {
|
423
|
+
addonEnv[key] = value as string;
|
542
424
|
});
|
425
|
+
}
|
543
426
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
} else {
|
548
|
-
await containerManager.waitForReady(container);
|
549
|
-
}
|
550
|
-
} catch (e: any) {
|
551
|
-
logs.addLog(e.message, 'ERROR');
|
552
|
-
}
|
427
|
+
if (spec.local?.mounts) {
|
428
|
+
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
429
|
+
Mounts = containerManager.toDockerMounts(mounts);
|
553
430
|
}
|
554
431
|
|
555
|
-
|
432
|
+
if (spec.local?.health) {
|
433
|
+
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
434
|
+
}
|
435
|
+
|
436
|
+
// For windows we need to default to root
|
437
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
438
|
+
|
439
|
+
logs.addLog(`Creating new container for block: ${containerName}`);
|
440
|
+
const out = await this.ensureContainer({
|
441
|
+
Image: dockerImage,
|
442
|
+
name: containerName,
|
443
|
+
ExposedPorts,
|
444
|
+
HealthCheck,
|
445
|
+
HostConfig: {
|
446
|
+
Binds: [
|
447
|
+
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
448
|
+
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
449
|
+
],
|
450
|
+
PortBindings,
|
451
|
+
Mounts,
|
452
|
+
},
|
453
|
+
Labels: {
|
454
|
+
instance: blockInstance.id,
|
455
|
+
},
|
456
|
+
Env: [
|
457
|
+
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
458
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
459
|
+
...DOCKER_ENV_VARS,
|
460
|
+
...Object.entries({
|
461
|
+
...env,
|
462
|
+
...addonEnv,
|
463
|
+
}).map(([key, value]) => `${key}=${value}`),
|
464
|
+
],
|
465
|
+
});
|
466
|
+
|
556
467
|
const portTypes = spec.local.ports ? Object.keys(spec.local.ports) : [];
|
557
468
|
if (portTypes.length > 0) {
|
558
469
|
out.portType = portTypes[0];
|