@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.
@@ -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, ProcessInfo, InstanceType, StringMap } from '../types';
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
- console.log('Starting dev container', containerName, dockerImage);
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 container.delete();
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 localContainer.delete();
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
- if (container) {
361
- const containerData = container.data as any;
362
- if (containerData.State === 'running') {
363
- logs.addLog(`Found existing running container for block: ${containerName}`);
364
- } else {
365
- logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
366
- await container.start();
367
- }
368
- } else {
369
- logs.addLog(`Creating new container for block: ${containerName}`);
370
-
371
- container = await containerManager.startContainer({
372
- Image: dockerImage,
373
- name: containerName,
374
- Labels: {
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
- if (!container) {
472
- const ExposedPorts: AnyMap = {};
473
- const addonEnv: StringMap = {};
474
- const PortBindings: AnyMap = {};
475
- let HealthCheck = undefined;
476
- let Mounts: DockerMounts[] = [];
477
- const promises = Object.entries(spec.local.ports as { [p: string]: { port: string; type: string } }).map(
478
- async ([portType, value]) => {
479
- const dockerPort = `${value.port}/${value.type}`;
480
- ExposedPorts[dockerPort] = {};
481
- addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
482
- const publicPort = await serviceManager.ensureServicePort(
483
- this._systemId,
484
- blockInstance.id,
485
- portType
486
- );
487
- PortBindings[dockerPort] = [
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
- if (spec.local?.health) {
510
- HealthCheck = containerManager.toDockerHealth(spec.local?.health);
511
- }
419
+ await Promise.all(promises);
512
420
 
513
- // For windows we need to default to root
514
- const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
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
- try {
545
- if (HealthCheck) {
546
- await containerManager.waitForHealthy(container);
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
- const out = await this._handleContainer(container, logs, true);
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];