@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.
Files changed (40) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/src/containerManager.d.ts +6 -4
  3. package/dist/cjs/src/containerManager.js +100 -45
  4. package/dist/cjs/src/definitionsManager.d.ts +1 -0
  5. package/dist/cjs/src/definitionsManager.js +7 -0
  6. package/dist/cjs/src/instanceManager.d.ts +2 -1
  7. package/dist/cjs/src/instanceManager.js +29 -46
  8. package/dist/cjs/src/instances/routes.js +10 -4
  9. package/dist/cjs/src/operatorManager.js +8 -6
  10. package/dist/cjs/src/repositoryManager.js +4 -4
  11. package/dist/cjs/src/types.d.ts +0 -9
  12. package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +3 -2
  13. package/dist/cjs/src/utils/BlockInstanceRunner.js +49 -95
  14. package/dist/cjs/src/utils/utils.d.ts +1 -1
  15. package/dist/cjs/src/utils/utils.js +3 -2
  16. package/dist/esm/src/containerManager.d.ts +6 -4
  17. package/dist/esm/src/containerManager.js +100 -45
  18. package/dist/esm/src/definitionsManager.d.ts +1 -0
  19. package/dist/esm/src/definitionsManager.js +7 -0
  20. package/dist/esm/src/instanceManager.d.ts +2 -1
  21. package/dist/esm/src/instanceManager.js +29 -46
  22. package/dist/esm/src/instances/routes.js +10 -4
  23. package/dist/esm/src/operatorManager.js +8 -6
  24. package/dist/esm/src/repositoryManager.js +4 -4
  25. package/dist/esm/src/types.d.ts +0 -9
  26. package/dist/esm/src/utils/BlockInstanceRunner.d.ts +3 -2
  27. package/dist/esm/src/utils/BlockInstanceRunner.js +49 -95
  28. package/dist/esm/src/utils/utils.d.ts +1 -1
  29. package/dist/esm/src/utils/utils.js +3 -2
  30. package/package.json +1 -1
  31. package/src/containerManager.ts +126 -49
  32. package/src/definitionsManager.ts +8 -0
  33. package/src/instanceManager.ts +35 -50
  34. package/src/instances/routes.ts +9 -4
  35. package/src/operatorManager.ts +9 -8
  36. package/src/repositoryManager.ts +5 -5
  37. package/src/types.ts +0 -7
  38. package/src/utils/BlockInstanceRunner.ts +74 -109
  39. package/src/utils/LogData.ts +1 -0
  40. package/src/utils/utils.ts +3 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [0.11.0](https://github.com/kapetacom/local-cluster-service/compare/v0.10.1...v0.11.0) (2023-07-31)
2
+
3
+
4
+ ### Features
5
+
6
+ * Always get logs from docker ([#53](https://github.com/kapetacom/local-cluster-service/issues/53)) ([5cab8cb](https://github.com/kapetacom/local-cluster-service/commit/5cab8cbf18b38edf99d538e1819e135f0a5bd7e3))
7
+
8
+ ## [0.10.1](https://github.com/kapetacom/local-cluster-service/compare/v0.10.0...v0.10.1) (2023-07-27)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Include port bindings for non-local containers ([#51](https://github.com/kapetacom/local-cluster-service/issues/51)) ([64fd440](https://github.com/kapetacom/local-cluster-service/commit/64fd4409ea9e2dda8e2438d0ec85a8f5a2092b1e))
14
+
1
15
  # [0.10.0](https://github.com/kapetacom/local-cluster-service/compare/v0.9.1...v0.10.0) (2023-07-26)
2
16
 
3
17
 
@@ -1,5 +1,6 @@
1
1
  import { Docker } from 'node-docker-api';
2
2
  import { Container } from 'node-docker-api/lib/container';
3
+ import { InstanceInfo, LogEntry } from "./types";
3
4
  type StringMap = {
4
5
  [key: string]: string;
5
6
  };
@@ -52,8 +53,8 @@ declare class ContainerManager {
52
53
  initialize(): Promise<void>;
53
54
  checkAlive(): Promise<boolean>;
54
55
  isAlive(): boolean;
55
- getMountPoint(kind: string, mountName: string): string;
56
- createMounts(kind: string, mountOpts: StringMap): StringMap;
56
+ getMountPoint(systemId: string, ref: string, mountName: string): string;
57
+ createMounts(systemId: string, kind: string, mountOpts: StringMap | null | undefined): Promise<StringMap>;
57
58
  ping(): Promise<void>;
58
59
  docker(): Docker;
59
60
  getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
@@ -67,11 +68,10 @@ declare class ContainerManager {
67
68
  };
68
69
  private applyHash;
69
70
  ensureContainer(opts: any): Promise<Container>;
71
+ private createOrUpdateContainer;
70
72
  startContainer(opts: any): Promise<Container>;
71
73
  waitForReady(container: Container, attempt?: number): Promise<void>;
72
- waitForHealthy(container: Container, attempt?: number): Promise<void>;
73
74
  _isReady(container: Container): Promise<any>;
74
- _isHealthy(container: Container): Promise<boolean>;
75
75
  remove(container: Container, opts?: {
76
76
  force?: boolean;
77
77
  }): Promise<void>;
@@ -81,6 +81,7 @@ declare class ContainerManager {
81
81
  * @return {Promise<ContainerInfo>}
82
82
  */
83
83
  get(name: string): Promise<ContainerInfo | null>;
84
+ getLogs(instance: InstanceInfo): Promise<LogEntry[]>;
84
85
  }
85
86
  export declare class ContainerInfo {
86
87
  private readonly _container;
@@ -105,6 +106,7 @@ export declare class ContainerInfo {
105
106
  inspect(): Promise<any>;
106
107
  status(): Promise<DockerState>;
107
108
  getPorts(): Promise<PortMap | false>;
109
+ getLogs(): Promise<LogEntry[]>;
108
110
  }
109
111
  export declare function getExtraHosts(dockerVersion: string): string[] | undefined;
110
112
  /**
@@ -14,6 +14,7 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
14
14
  const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
15
15
  const node_uuid_1 = __importDefault(require("node-uuid"));
16
16
  const md5_1 = __importDefault(require("md5"));
17
+ const utils_1 = require("./utils/utils");
17
18
  exports.CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
18
19
  const NANO_SECOND = 1000000;
19
20
  const HEALTH_CHECK_INTERVAL = 3000;
@@ -21,8 +22,8 @@ const HEALTH_CHECK_MAX = 20;
21
22
  const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
22
23
  const IMAGE_PULL_CACHE = {};
23
24
  exports.HEALTH_CHECK_TIMEOUT = HEALTH_CHECK_INTERVAL * HEALTH_CHECK_MAX * 2;
24
- const promisifyStream = (stream) => new Promise((resolve, reject) => {
25
- stream.on('data', (d) => console.log(d.toString()));
25
+ const promisifyStream = (stream, handler) => new Promise((resolve, reject) => {
26
+ stream.on('data', handler);
26
27
  stream.on('end', resolve);
27
28
  stream.on('error', reject);
28
29
  });
@@ -101,17 +102,21 @@ class ContainerManager {
101
102
  isAlive() {
102
103
  return this._alive;
103
104
  }
104
- getMountPoint(kind, mountName) {
105
- const kindUri = (0, nodejs_utils_1.parseKapetaUri)(kind);
106
- return path_1.default.join(this._mountDir, kindUri.handle, kindUri.name, mountName);
105
+ getMountPoint(systemId, ref, mountName) {
106
+ const kindUri = (0, nodejs_utils_1.parseKapetaUri)(ref);
107
+ const systemUri = (0, nodejs_utils_1.parseKapetaUri)(systemId);
108
+ return path_1.default.join(this._mountDir, systemUri.handle, systemUri.name, systemUri.version, kindUri.handle, kindUri.name, kindUri.version, mountName);
107
109
  }
108
- createMounts(kind, mountOpts) {
110
+ async createMounts(systemId, kind, mountOpts) {
109
111
  const mounts = {};
110
- lodash_1.default.forEach(mountOpts, (containerPath, mountName) => {
111
- const hostPath = this.getMountPoint(kind, mountName);
112
- fs_extra_1.default.mkdirpSync(hostPath);
113
- mounts[containerPath] = hostPath;
114
- });
112
+ if (mountOpts) {
113
+ const mountOptList = Object.entries(mountOpts);
114
+ for (const [mountName, containerPath] of mountOptList) {
115
+ const hostPath = this.getMountPoint(systemId, kind, mountName);
116
+ await fs_extra_1.default.mkdirp(hostPath);
117
+ mounts[containerPath] = hostPath;
118
+ }
119
+ }
115
120
  return mounts;
116
121
  }
117
122
  async ping() {
@@ -162,12 +167,14 @@ class ContainerManager {
162
167
  return false;
163
168
  }
164
169
  console.log('Pulling image: %s', image);
165
- await this.docker()
170
+ const stream = await this.docker()
166
171
  .image.create({}, {
167
172
  fromImage: imageName,
168
173
  tag: tag,
169
- })
170
- .then((stream) => promisifyStream(stream));
174
+ });
175
+ await promisifyStream(stream, (chunk) => {
176
+ console.log('Data from docker: "%s"', chunk.toString());
177
+ });
171
178
  IMAGE_PULL_CACHE[image] = Date.now();
172
179
  console.log('Image pulled: %s', image);
173
180
  return true;
@@ -204,6 +211,11 @@ class ContainerManager {
204
211
  dockerOpts.Labels.HASH = hash;
205
212
  }
206
213
  async ensureContainer(opts) {
214
+ const container = await this.createOrUpdateContainer(opts);
215
+ await this.waitForReady(container);
216
+ return container;
217
+ }
218
+ async createOrUpdateContainer(opts) {
207
219
  let imagePulled = false;
208
220
  try {
209
221
  imagePulled = await this.pull(opts.Image);
@@ -283,28 +295,6 @@ class ContainerManager {
283
295
  }, HEALTH_CHECK_INTERVAL);
284
296
  });
285
297
  }
286
- async waitForHealthy(container, attempt) {
287
- if (!attempt) {
288
- attempt = 0;
289
- }
290
- if (attempt >= HEALTH_CHECK_MAX) {
291
- throw new Error('Container did not become healthy within the timeout');
292
- }
293
- if (await this._isHealthy(container)) {
294
- return;
295
- }
296
- return new Promise((resolve, reject) => {
297
- setTimeout(async () => {
298
- try {
299
- await this.waitForHealthy(container, (attempt ?? 0) + 1);
300
- resolve();
301
- }
302
- catch (err) {
303
- reject(err);
304
- }
305
- }, HEALTH_CHECK_INTERVAL);
306
- });
307
- }
308
298
  async _isReady(container) {
309
299
  let info;
310
300
  try {
@@ -318,16 +308,12 @@ class ContainerManager {
318
308
  if (state?.Status === 'exited' || state?.Status === 'removing' || state?.Status === 'dead') {
319
309
  throw new Error('Container exited unexpectedly');
320
310
  }
321
- return infoData?.State?.Running ?? false;
322
- }
323
- async _isHealthy(container) {
324
- try {
325
- const info = await container.status();
326
- const infoData = info?.data;
327
- return infoData?.State?.Health?.Status === 'healthy';
311
+ if (infoData?.State?.Health) {
312
+ // If container has health info - wait for it to become healthy
313
+ return infoData.State.Health.Status === 'healthy';
328
314
  }
329
- catch (err) {
330
- return false;
315
+ else {
316
+ return infoData?.State?.Running ?? false;
331
317
  }
332
318
  }
333
319
  async remove(container, opts) {
@@ -357,6 +343,19 @@ class ContainerManager {
357
343
  }
358
344
  return new ContainerInfo(dockerContainer);
359
345
  }
346
+ async getLogs(instance) {
347
+ const containerName = (0, utils_1.getBlockInstanceContainerName)(instance.systemId, instance.instanceId);
348
+ const containerInfo = await this.getContainerByName(containerName);
349
+ if (!containerInfo) {
350
+ return [{
351
+ source: "stdout",
352
+ level: "ERROR",
353
+ time: Date.now(),
354
+ message: "Container not found"
355
+ }];
356
+ }
357
+ return containerInfo.getLogs();
358
+ }
360
359
  }
361
360
  class ContainerInfo {
362
361
  _container;
@@ -440,6 +439,62 @@ class ContainerInfo {
440
439
  });
441
440
  return ports;
442
441
  }
442
+ async getLogs() {
443
+ const logStream = await this.native.logs({
444
+ stdout: true,
445
+ stderr: true,
446
+ follow: false,
447
+ tail: 100,
448
+ timestamps: true,
449
+ });
450
+ const out = [];
451
+ await promisifyStream(logStream, (data) => {
452
+ const buf = data;
453
+ let offset = 0;
454
+ while (offset < buf.length) {
455
+ try {
456
+ // Read the docker log format - explained here:
457
+ // https://docs.docker.com/engine/api/v1.41/#operation/ContainerAttach
458
+ // or here : https://ahmet.im/blog/docker-logs-api-binary-format-explained/
459
+ // First byte is stream type
460
+ const streamTypeInt = buf.readInt8(offset);
461
+ const streamType = streamTypeInt === 1 ? 'stdout' : 'stderr';
462
+ // Bytes 4-8 is frame size
463
+ const messageLength = buf.readInt32BE(offset + 4);
464
+ // After that is the message - with the message length
465
+ const dataWithoutStreamType = buf.subarray(offset + 8, offset + 8 + messageLength);
466
+ const raw = dataWithoutStreamType.toString();
467
+ // Split the message into date and message
468
+ const firstSpaceIx = raw.indexOf(' ');
469
+ const dateString = raw.substring(0, firstSpaceIx);
470
+ const line = raw.substring(firstSpaceIx + 1);
471
+ offset = offset + messageLength + 8;
472
+ if (!dateString) {
473
+ continue;
474
+ }
475
+ out.push({
476
+ time: new Date(dateString).getTime(),
477
+ message: line,
478
+ level: 'INFO',
479
+ source: streamType,
480
+ });
481
+ }
482
+ catch (err) {
483
+ console.error('Error parsing log entry', err);
484
+ offset = buf.length;
485
+ }
486
+ }
487
+ });
488
+ if (out.length === 0) {
489
+ out.push({
490
+ time: Date.now(),
491
+ message: 'No logs found for container',
492
+ level: 'INFO',
493
+ source: 'stdout',
494
+ });
495
+ }
496
+ return out;
497
+ }
443
498
  }
444
499
  exports.ContainerInfo = ContainerInfo;
445
500
  function getExtraHosts(dockerVersion) {
@@ -5,6 +5,7 @@ declare class DefinitionsManager {
5
5
  clearCache(): void;
6
6
  private doCached;
7
7
  getDefinitions(kindFilter?: string | string[]): DefinitionInfo[];
8
+ exists(ref: string): boolean;
8
9
  getProviderDefinitions(): DefinitionInfo[];
9
10
  }
10
11
  export declare const definitionsManager: DefinitionsManager;
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.definitionsManager = void 0;
7
7
  const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
8
+ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
8
9
  const CACHE_TTL = 60 * 1000; // 1 min
9
10
  class DefinitionsManager {
10
11
  cache = {};
@@ -37,6 +38,12 @@ class DefinitionsManager {
37
38
  const key = this.getKey(kindFilter);
38
39
  return this.doCached(key, () => local_cluster_config_1.default.getDefinitions(kindFilter));
39
40
  }
41
+ exists(ref) {
42
+ const uri = (0, nodejs_utils_1.parseKapetaUri)(ref);
43
+ return !!this.getDefinitions().find((d) => {
44
+ return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
45
+ });
46
+ }
40
47
  getProviderDefinitions() {
41
48
  return this.doCached('providers', () => local_cluster_config_1.default.getProviderDefinitions());
42
49
  }
@@ -1,4 +1,4 @@
1
- import { InstanceInfo } from './types';
1
+ import { InstanceInfo, LogEntry } from './types';
2
2
  export declare class InstanceManager {
3
3
  private _interval;
4
4
  private readonly _instances;
@@ -7,6 +7,7 @@ export declare class InstanceManager {
7
7
  getInstances(): InstanceInfo[];
8
8
  getInstancesForPlan(systemId: string): InstanceInfo[];
9
9
  getInstance(systemId: string, instanceId: string): InstanceInfo | undefined;
10
+ getLogs(systemId: string, instanceId: string): Promise<LogEntry[]>;
10
11
  saveInternalInstance(instance: InstanceInfo): Promise<InstanceInfo>;
11
12
  /**
12
13
  * Method is called when instance is started from the Kapeta SDKs (e.g. NodeJS SDK)
@@ -56,6 +56,31 @@ class InstanceManager {
56
56
  systemId = (0, utils_1.normalizeKapetaUri)(systemId);
57
57
  return this._instances.find((i) => i.systemId === systemId && i.instanceId === instanceId);
58
58
  }
59
+ async getLogs(systemId, instanceId) {
60
+ const instance = this.getInstance(systemId, instanceId);
61
+ if (!instance) {
62
+ throw new Error(`Instance ${systemId}/${instanceId} not found`);
63
+ }
64
+ switch (instance.type) {
65
+ case types_1.InstanceType.DOCKER:
66
+ return await containerManager_1.containerManager.getLogs(instance);
67
+ case types_1.InstanceType.UNKNOWN:
68
+ return [{
69
+ level: 'INFO',
70
+ message: 'Instance is starting...',
71
+ time: Date.now(),
72
+ source: 'stdout',
73
+ }];
74
+ case types_1.InstanceType.LOCAL:
75
+ return [{
76
+ level: 'INFO',
77
+ message: 'Instance started outside Kapeta - logs not available...',
78
+ time: Date.now(),
79
+ source: 'stdout',
80
+ }];
81
+ }
82
+ return [];
83
+ }
59
84
  async saveInternalInstance(instance) {
60
85
  instance.systemId = (0, utils_1.normalizeKapetaUri)(instance.systemId);
61
86
  if (instance.ref) {
@@ -106,7 +131,6 @@ class InstanceManager {
106
131
  }
107
132
  instance.desiredStatus = info.desiredStatus;
108
133
  instance.owner = info.owner;
109
- instance.internal = undefined;
110
134
  instance.status = types_1.InstanceStatus.STARTING;
111
135
  instance.startedAt = Date.now();
112
136
  }
@@ -205,7 +229,7 @@ class InstanceManager {
205
229
  this.save();
206
230
  try {
207
231
  if (instance.type === 'docker') {
208
- const containerName = (0, utils_1.getBlockInstanceContainerName)(instance.instanceId);
232
+ const containerName = (0, utils_1.getBlockInstanceContainerName)(instance.systemId, instance.instanceId);
209
233
  const container = await containerManager_1.containerManager.getContainerByName(containerName);
210
234
  if (container) {
211
235
  try {
@@ -281,7 +305,7 @@ class InstanceManager {
281
305
  name: blockAsset.data.metadata.name,
282
306
  desiredStatus: types_1.DesiredInstanceStatus.RUN,
283
307
  owner: types_1.InstanceOwner.INTERNAL,
284
- type: types_1.InstanceType.UNKNOWN,
308
+ type: existingInstance?.type ?? types_1.InstanceType.UNKNOWN,
285
309
  status: types_1.InstanceStatus.STARTING,
286
310
  startedAt: Date.now(),
287
311
  };
@@ -301,41 +325,6 @@ class InstanceManager {
301
325
  const startTime = Date.now();
302
326
  try {
303
327
  const processInfo = await runner.start(blockRef, instanceId, instanceConfig);
304
- //emit stdout/stderr via sockets
305
- processInfo.output.on('data', (data) => {
306
- const payload = {
307
- source: 'stdout',
308
- level: 'INFO',
309
- message: data.toString(),
310
- time: Date.now(),
311
- };
312
- this.emitInstanceEvent(systemId, instanceId, EVENT_INSTANCE_LOG, payload);
313
- });
314
- processInfo.output.on('exit', (exitCode) => {
315
- const timeRunning = Date.now() - startTime;
316
- const instance = this.getInstance(systemId, instanceId);
317
- if (instance?.status === types_1.InstanceStatus.READY) {
318
- //It's already been running
319
- return;
320
- }
321
- if (exitCode === 143 || exitCode === 137) {
322
- //Process got SIGTERM (143) or SIGKILL (137)
323
- //TODO: Windows?
324
- return;
325
- }
326
- if (exitCode !== 0 || timeRunning < MIN_TIME_RUNNING) {
327
- const instance = this.getInstance(systemId, instanceId);
328
- if (instance) {
329
- instance.status = types_1.InstanceStatus.FAILED;
330
- this.save();
331
- }
332
- this.emitSystemEvent(systemId, EVENT_INSTANCE_EXITED, {
333
- error: 'Failed to start instance',
334
- status: EVENT_INSTANCE_EXITED,
335
- instanceId: blockInstance.id,
336
- });
337
- }
338
- });
339
328
  instance.status = types_1.InstanceStatus.READY;
340
329
  return this.saveInternalInstance({
341
330
  ...instance,
@@ -344,10 +333,6 @@ class InstanceManager {
344
333
  health: null,
345
334
  portType: processInfo.portType,
346
335
  status: types_1.InstanceStatus.READY,
347
- internal: {
348
- logs: processInfo.logs,
349
- output: processInfo.output,
350
- },
351
336
  });
352
337
  }
353
338
  catch (e) {
@@ -393,9 +378,7 @@ class InstanceManager {
393
378
  save() {
394
379
  try {
395
380
  storageService_1.storageService.put('instances', this._instances.map((instance) => {
396
- const copy = { ...instance };
397
- delete copy.internal;
398
- return copy;
381
+ return { ...instance };
399
382
  }));
400
383
  }
401
384
  catch (e) {
@@ -497,7 +480,7 @@ class InstanceManager {
497
480
  }
498
481
  async getExternalStatus(instance) {
499
482
  if (instance.type === types_1.InstanceType.DOCKER) {
500
- const containerName = (0, utils_1.getBlockInstanceContainerName)(instance.instanceId);
483
+ const containerName = (0, utils_1.getBlockInstanceContainerName)(instance.systemId, instance.instanceId);
501
484
  const container = await containerManager_1.containerManager.getContainerByName(containerName);
502
485
  if (!container) {
503
486
  // If the container doesn't exist, we consider the instance stopped
@@ -67,15 +67,21 @@ router.post('/:systemId/:instanceId/stop', async (req, res) => {
67
67
  /**
68
68
  * Get logs for instance in a plan
69
69
  */
70
- router.get('/:systemId/:instanceId/logs', (req, res) => {
70
+ router.get('/:systemId/:instanceId/logs', async (req, res) => {
71
71
  const instanceInfo = instanceManager_1.instanceManager.getInstance(req.params.systemId, req.params.instanceId);
72
72
  if (!instanceInfo) {
73
73
  res.status(404).send({ ok: false });
74
74
  return;
75
75
  }
76
- res.status(202).send({
77
- logs: instanceInfo.internal?.logs() ?? [],
78
- });
76
+ try {
77
+ const logs = await instanceManager_1.instanceManager.getLogs(req.params.systemId, req.params.instanceId);
78
+ res.status(200).send({
79
+ logs,
80
+ });
81
+ }
82
+ catch (e) {
83
+ res.status(500).send({ ok: false, error: e.message });
84
+ }
79
85
  });
80
86
  /**
81
87
  * Get public address for instance in a plan if available
@@ -117,13 +117,11 @@ class OperatorManager {
117
117
  const operatorData = operator.getData();
118
118
  const portTypes = Object.keys(operatorData.ports);
119
119
  portTypes.sort();
120
- const containerBaseName = 'kapeta-resource';
121
- const nameParts = [resourceType.toLowerCase()];
122
120
  const ports = {};
123
121
  for (let i = 0; i < portTypes.length; i++) {
124
122
  const portType = portTypes[i];
125
123
  let containerPortInfo = operatorData.ports[portType];
126
- const hostPort = await serviceManager_1.serviceManager.ensureServicePort(resourceType, portType);
124
+ const hostPort = await serviceManager_1.serviceManager.ensureServicePort(systemId, resourceType, portType);
127
125
  if (typeof containerPortInfo === 'number' || typeof containerPortInfo === 'string') {
128
126
  containerPortInfo = { port: containerPortInfo, type: 'tcp' };
129
127
  }
@@ -131,14 +129,18 @@ class OperatorManager {
131
129
  containerPortInfo.type = 'tcp';
132
130
  }
133
131
  const portId = containerPortInfo.port + '/' + containerPortInfo.type;
134
- nameParts.push(portType + '-' + portId + '-' + hostPort);
135
132
  ports[portId] = {
136
133
  type: portType,
137
134
  hostPort,
138
135
  };
139
136
  }
140
- const mounts = containerManager_1.containerManager.createMounts(resourceType, operatorData.mounts);
141
- const containerName = containerBaseName + '-' + (0, md5_1.default)(nameParts.join('_'));
137
+ const mounts = await containerManager_1.containerManager.createMounts(systemId, resourceType, operatorData.mounts);
138
+ const nameParts = [
139
+ systemId,
140
+ resourceType.toLowerCase(),
141
+ version
142
+ ];
143
+ const containerName = `kapeta-resource-${(0, md5_1.default)(nameParts.join('_'))}`;
142
144
  const PortBindings = {};
143
145
  const Env = [];
144
146
  const Labels = {
@@ -113,9 +113,11 @@ class RepositoryManager {
113
113
  this._installQueue.push(async () => {
114
114
  try {
115
115
  const normalizedRefs = refs.map((ref) => (0, nodejs_utils_1.parseKapetaUri)(ref).id);
116
- const filteredRefs = normalizedRefs.filter((ref) => !INSTALL_ATTEMPTED[ref]);
117
- console.log(filteredRefs);
116
+ const filteredRefs = normalizedRefs
117
+ .filter((ref) => !INSTALL_ATTEMPTED[ref])
118
+ .filter((ref) => !definitionsManager_1.definitionsManager.exists(ref));
118
119
  if (filteredRefs.length > 0) {
120
+ console.log(`Auto-installing dependencies: ${filteredRefs.join(', ')}`);
119
121
  filteredRefs.forEach((ref) => (INSTALL_ATTEMPTED[ref] = true));
120
122
  //Auto-install missing asset
121
123
  try {
@@ -206,14 +208,12 @@ class RepositoryManager {
206
208
  }
207
209
  this._cache[ref] = true;
208
210
  if (!installedAsset) {
209
- console.log(`Auto-installing missing asset: ${ref}`);
210
211
  await this._install([ref]);
211
212
  }
212
213
  else {
213
214
  //Ensure dependencies are installed
214
215
  const refs = assetVersion.dependencies.map((dep) => dep.name);
215
216
  if (refs.length > 0) {
216
- console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
217
217
  await this._install(refs);
218
218
  }
219
219
  }
@@ -1,5 +1,3 @@
1
- /// <reference types="node" />
2
- import EventEmitter from 'events';
3
1
  import express from 'express';
4
2
  import { Resource } from '@kapeta/schemas';
5
3
  import { StringBodyRequest } from './middleware/stringBody';
@@ -50,10 +48,7 @@ export declare enum DesiredInstanceStatus {
50
48
  export type ProcessInfo = {
51
49
  type: InstanceType;
52
50
  pid?: number | string | null;
53
- output: EventEmitter;
54
51
  portType?: string;
55
- logs: () => LogEntry[];
56
- stop: () => Promise<void> | void;
57
52
  };
58
53
  export type InstanceInfo = {
59
54
  systemId: string;
@@ -69,10 +64,6 @@ export type InstanceInfo = {
69
64
  health?: string | null;
70
65
  pid?: number | string | null;
71
66
  portType?: string;
72
- internal?: {
73
- output: EventEmitter;
74
- logs: () => LogEntry[];
75
- };
76
67
  };
77
68
  interface ResourceRef {
78
69
  blockId: string;
@@ -14,8 +14,6 @@ export declare class BlockInstanceRunner {
14
14
  * Starts local process
15
15
  */
16
16
  private _startLocalProcess;
17
- private ensureContainer;
18
- private _handleContainer;
19
17
  private _startDockerProcess;
20
18
  /**
21
19
  *
@@ -27,4 +25,7 @@ export declare class BlockInstanceRunner {
27
25
  * @private
28
26
  */
29
27
  _startOperatorProcess(blockInstance: BlockProcessParams, blockUri: KapetaURI, providerDefinition: DefinitionInfo, env: StringMap): Promise<ProcessInfo>;
28
+ private getDockerPortBindings;
29
+ private ensureContainer;
30
+ private _handleContainer;
30
31
  }