@kapeta/local-cluster-service 0.8.3 → 0.9.1

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 (71) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/src/assetManager.js +7 -4
  3. package/dist/cjs/src/clusterService.js +2 -0
  4. package/dist/cjs/src/codeGeneratorManager.js +3 -3
  5. package/dist/cjs/src/config/routes.js +1 -1
  6. package/dist/cjs/src/configManager.js +13 -1
  7. package/dist/cjs/src/containerManager.d.ts +25 -2
  8. package/dist/cjs/src/containerManager.js +51 -16
  9. package/dist/cjs/src/definitionsManager.d.ts +11 -0
  10. package/dist/cjs/src/definitionsManager.js +44 -0
  11. package/dist/cjs/src/filesystemManager.js +0 -2
  12. package/dist/cjs/src/instanceManager.d.ts +23 -47
  13. package/dist/cjs/src/instanceManager.js +416 -235
  14. package/dist/cjs/src/instances/routes.js +23 -14
  15. package/dist/cjs/src/middleware/kapeta.js +7 -0
  16. package/dist/cjs/src/networkManager.js +6 -0
  17. package/dist/cjs/src/operatorManager.js +8 -4
  18. package/dist/cjs/src/providerManager.js +3 -3
  19. package/dist/cjs/src/repositoryManager.js +7 -3
  20. package/dist/cjs/src/serviceManager.js +5 -0
  21. package/dist/cjs/src/types.d.ts +39 -13
  22. package/dist/cjs/src/types.js +28 -0
  23. package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +3 -3
  24. package/dist/cjs/src/utils/BlockInstanceRunner.js +34 -32
  25. package/dist/cjs/src/utils/utils.d.ts +2 -0
  26. package/dist/cjs/src/utils/utils.js +17 -1
  27. package/dist/esm/src/assetManager.js +7 -4
  28. package/dist/esm/src/clusterService.js +2 -0
  29. package/dist/esm/src/codeGeneratorManager.js +3 -3
  30. package/dist/esm/src/config/routes.js +1 -1
  31. package/dist/esm/src/configManager.js +13 -1
  32. package/dist/esm/src/containerManager.d.ts +25 -2
  33. package/dist/esm/src/containerManager.js +50 -15
  34. package/dist/esm/src/definitionsManager.d.ts +11 -0
  35. package/dist/esm/src/definitionsManager.js +38 -0
  36. package/dist/esm/src/filesystemManager.js +0 -2
  37. package/dist/esm/src/instanceManager.d.ts +23 -47
  38. package/dist/esm/src/instanceManager.js +416 -236
  39. package/dist/esm/src/instances/routes.js +23 -14
  40. package/dist/esm/src/middleware/kapeta.js +7 -0
  41. package/dist/esm/src/networkManager.js +6 -0
  42. package/dist/esm/src/operatorManager.js +8 -4
  43. package/dist/esm/src/providerManager.js +3 -3
  44. package/dist/esm/src/repositoryManager.js +7 -3
  45. package/dist/esm/src/serviceManager.js +5 -0
  46. package/dist/esm/src/types.d.ts +39 -13
  47. package/dist/esm/src/types.js +27 -1
  48. package/dist/esm/src/utils/BlockInstanceRunner.d.ts +3 -3
  49. package/dist/esm/src/utils/BlockInstanceRunner.js +35 -33
  50. package/dist/esm/src/utils/utils.d.ts +2 -0
  51. package/dist/esm/src/utils/utils.js +14 -0
  52. package/package.json +2 -1
  53. package/src/assetManager.ts +7 -4
  54. package/src/clusterService.ts +3 -0
  55. package/src/codeGeneratorManager.ts +3 -2
  56. package/src/config/routes.ts +1 -1
  57. package/src/configManager.ts +13 -1
  58. package/src/containerManager.ts +72 -16
  59. package/src/definitionsManager.ts +54 -0
  60. package/src/filesystemManager.ts +0 -2
  61. package/src/instanceManager.ts +495 -266
  62. package/src/instances/routes.ts +23 -17
  63. package/src/middleware/kapeta.ts +10 -0
  64. package/src/networkManager.ts +6 -0
  65. package/src/operatorManager.ts +11 -6
  66. package/src/providerManager.ts +3 -2
  67. package/src/repositoryManager.ts +7 -3
  68. package/src/serviceManager.ts +6 -0
  69. package/src/types.ts +44 -14
  70. package/src/utils/BlockInstanceRunner.ts +39 -36
  71. package/src/utils/utils.ts +18 -0
@@ -5,7 +5,7 @@ import { corsHandler } from '../middleware/cors';
5
5
  import { NextFunction, Request, Response } from 'express';
6
6
  import { kapetaHeaders, KapetaRequest } from '../middleware/kapeta';
7
7
  import { stringBody } from '../middleware/stringBody';
8
- import { EnvironmentType, KapetaBodyRequest } from '../types';
8
+ import { DesiredInstanceStatus, InstanceInfo, InstanceOwner, InstanceType, KapetaBodyRequest } from '../types';
9
9
 
10
10
  const router = Router();
11
11
  router.use('/', corsHandler);
@@ -28,11 +28,11 @@ router.get('/:systemId/instances', (req: Request, res: Response) => {
28
28
  * Start all instances in a plan
29
29
  */
30
30
  router.post('/:systemId/start', async (req: Request, res: Response) => {
31
- const processes = await instanceManager.createProcessesForPlan(req.params.systemId);
31
+ const instances = await instanceManager.startAllForPlan(req.params.systemId);
32
32
 
33
33
  res.status(202).send({
34
34
  ok: true,
35
- processes: processes.map((p) => {
35
+ processes: instances.map((p) => {
36
36
  return { pid: p.pid, type: p.type };
37
37
  }),
38
38
  });
@@ -53,7 +53,7 @@ router.post('/:systemId/stop', async (req: Request, res: Response) => {
53
53
  * Start single instance in a plan
54
54
  */
55
55
  router.post('/:systemId/:instanceId/start', async (req: Request, res: Response) => {
56
- const process = await instanceManager.createProcess(req.params.systemId, req.params.instanceId);
56
+ const process = await instanceManager.start(req.params.systemId, req.params.instanceId);
57
57
 
58
58
  res.status(202).send({
59
59
  ok: true,
@@ -66,7 +66,7 @@ router.post('/:systemId/:instanceId/start', async (req: Request, res: Response)
66
66
  * Stop single instance in a plan
67
67
  */
68
68
  router.post('/:systemId/:instanceId/stop', async (req: Request, res: Response) => {
69
- await instanceManager.stopProcess(req.params.systemId, req.params.instanceId);
69
+ await instanceManager.stop(req.params.systemId, req.params.instanceId);
70
70
 
71
71
  res.status(202).send({ ok: true });
72
72
  });
@@ -75,14 +75,14 @@ router.post('/:systemId/:instanceId/stop', async (req: Request, res: Response) =
75
75
  * Get logs for instance in a plan
76
76
  */
77
77
  router.get('/:systemId/:instanceId/logs', (req: Request, res: Response) => {
78
- const processInfo = instanceManager.getProcessForInstance(req.params.systemId, req.params.instanceId);
79
- if (!processInfo) {
78
+ const instanceInfo = instanceManager.getInstance(req.params.systemId, req.params.instanceId);
79
+ if (!instanceInfo) {
80
80
  res.status(404).send({ ok: false });
81
81
  return;
82
82
  }
83
83
 
84
84
  res.status(202).send({
85
- logs: processInfo.logs(),
85
+ logs: instanceInfo.internal?.logs() ?? [],
86
86
  });
87
87
  });
88
88
 
@@ -132,31 +132,37 @@ router.use('/', (req: KapetaBodyRequest, res: Response, next: NextFunction) => {
132
132
  });
133
133
 
134
134
  /**
135
- * Updates the full configuration for a given service.
135
+ * Updates the full configuration for a given instance.
136
136
  */
137
137
  router.put('/', async (req: KapetaBodyRequest, res: Response) => {
138
- let instance = req.stringBody ? JSON.parse(req.stringBody) : null;
138
+ let instance: InstanceInfo = req.stringBody ? JSON.parse(req.stringBody) : null;
139
139
  if (req.kapeta!.environment === 'docker') {
140
140
  //A bit hacky but we want to avoid overwriting the docker PID with a process PID
141
141
  const oldInstance = instanceManager.getInstance(req.kapeta!.systemId, req.kapeta!.instanceId);
142
142
  if (oldInstance) {
143
143
  instance.pid = oldInstance.pid;
144
144
  }
145
- instance.type = 'docker';
146
- } else if (req.kapeta!.environment === 'process') {
147
- instance.type = 'process';
145
+ instance.type = InstanceType.DOCKER;
146
+ } else {
147
+ // Coming from user starting the instance outside of kapeta
148
+ instance.type = InstanceType.LOCAL;
149
+ instance.owner = InstanceOwner.EXTERNAL;
150
+ instance.desiredStatus = DesiredInstanceStatus.EXTERNAL;
148
151
  }
149
152
 
150
- await instanceManager.registerInstance(req.kapeta!.systemId, req.kapeta!.instanceId, instance);
151
-
152
- res.status(202).send({ ok: true });
153
+ try {
154
+ await instanceManager.registerInstanceFromSDK(req.kapeta!.systemId, req.kapeta!.instanceId, instance);
155
+ res.status(202).send({ ok: true });
156
+ } catch (e: any) {
157
+ res.status(400).send({ error: e.message });
158
+ }
153
159
  });
154
160
 
155
161
  /**
156
162
  * Delete instance
157
163
  */
158
164
  router.delete('/', async (req: KapetaRequest, res: Response) => {
159
- await instanceManager.setInstanceAsStopped(req.kapeta!.systemId, req.kapeta!.instanceId);
165
+ await instanceManager.markAsStopped(req.kapeta!.systemId, req.kapeta!.instanceId);
160
166
 
161
167
  res.status(202).send({ ok: true });
162
168
  });
@@ -1,5 +1,7 @@
1
1
  import { NextFunction, Request, Response } from 'express';
2
2
  import { EnvironmentType } from '../types';
3
+ import { parseKapetaUri } from '@kapeta/nodejs-utils';
4
+ import { normalizeKapetaUri } from '../utils/utils';
3
5
 
4
6
  export interface KapetaRequest extends Request {
5
7
  kapeta?: {
@@ -16,6 +18,14 @@ export function kapetaHeaders(req: KapetaRequest, res: Response, next: NextFunct
16
18
  let instanceId: string = req.headers['x-kapeta-instance'] as string;
17
19
  let environment: string = req.headers['x-kapeta-environment'] as string;
18
20
 
21
+ if (blockRef) {
22
+ blockRef = normalizeKapetaUri(blockRef);
23
+ }
24
+
25
+ if (systemId) {
26
+ systemId = normalizeKapetaUri(systemId);
27
+ }
28
+
19
29
  req.kapeta = {
20
30
  blockRef,
21
31
  instanceId,
@@ -1,6 +1,7 @@
1
1
  import uuid from 'node-uuid';
2
2
  import { Connection, SimpleRequest, SimpleResponse } from './types';
3
3
  import express from 'express';
4
+ import { normalizeKapetaUri } from './utils/utils';
4
5
 
5
6
  class NetworkManager {
6
7
  private _connections: { [systemId: string]: { [connectionId: string]: Traffic[] } };
@@ -23,6 +24,7 @@ class NetworkManager {
23
24
  }
24
25
 
25
26
  _ensureSystem(systemId: string) {
27
+ systemId = normalizeKapetaUri(systemId);
26
28
  if (!this._connections[systemId]) {
27
29
  this._connections[systemId] = {};
28
30
  }
@@ -37,6 +39,7 @@ class NetworkManager {
37
39
  }
38
40
 
39
41
  _ensureConnection(systemId: string, connectionId: string) {
42
+ systemId = normalizeKapetaUri(systemId);
40
43
  this._ensureSystem(systemId);
41
44
 
42
45
  if (!this._connections[systemId][connectionId]) {
@@ -47,6 +50,7 @@ class NetworkManager {
47
50
  }
48
51
 
49
52
  _ensureSource(systemId: string, sourceBlockInstanceId: string) {
53
+ systemId = normalizeKapetaUri(systemId);
50
54
  this._ensureSystem(systemId);
51
55
 
52
56
  if (!this._sources[systemId][sourceBlockInstanceId]) {
@@ -57,6 +61,7 @@ class NetworkManager {
57
61
  }
58
62
 
59
63
  _ensureTarget(systemId: string, targetBlockInstanceId: string) {
64
+ systemId = normalizeKapetaUri(systemId);
60
65
  this._ensureSystem(systemId);
61
66
 
62
67
  if (!this._targets[systemId][targetBlockInstanceId]) {
@@ -73,6 +78,7 @@ class NetworkManager {
73
78
  consumerMethodId?: string,
74
79
  providerMethodId?: string
75
80
  ) {
81
+ systemId = normalizeKapetaUri(systemId);
76
82
  const traffic = new Traffic(connection, request, consumerMethodId, providerMethodId);
77
83
 
78
84
  this._ensureConnection(systemId, traffic.connectionId).push(traffic);
@@ -8,6 +8,8 @@ import { ContainerInfo, containerManager } from './containerManager';
8
8
  import FSExtra from 'fs-extra';
9
9
  import { AnyMap, EnvironmentType, OperatorInfo } from './types';
10
10
  import { BlockInstance, Resource } from '@kapeta/schemas';
11
+ import { definitionsManager } from './definitionsManager';
12
+ import { normalizeKapetaUri } from './utils/utils';
11
13
 
12
14
  const KIND_OPERATOR = 'core/resource-type-operator';
13
15
 
@@ -47,7 +49,7 @@ class OperatorManager {
47
49
  * @return {Operator}
48
50
  */
49
51
  getOperator(resourceType: string, version: string) {
50
- const operators = ClusterConfiguration.getDefinitions(KIND_OPERATOR);
52
+ const operators = definitionsManager.getDefinitions(KIND_OPERATOR);
51
53
 
52
54
  const operator: DefinitionInfo | undefined = operators.find(
53
55
  (operator) =>
@@ -80,7 +82,8 @@ class OperatorManager {
80
82
  name: string,
81
83
  environment?: EnvironmentType
82
84
  ): Promise<OperatorInfo> {
83
- const plans = ClusterConfiguration.getDefinitions('core/plan');
85
+ systemId = normalizeKapetaUri(systemId);
86
+ const plans = definitionsManager.getDefinitions('core/plan');
84
87
 
85
88
  const planUri = parseKapetaUri(systemId);
86
89
  const currentPlan = plans.find(
@@ -98,10 +101,12 @@ class OperatorManager {
98
101
  }
99
102
 
100
103
  const blockUri = parseKapetaUri(currentInstance.block.ref);
101
- const blockDefinition = ClusterConfiguration.getDefinitions().find(
102
- (definition) =>
103
- definition.version === blockUri.version && definition.definition.metadata.name === blockUri.fullName
104
- );
104
+ const blockDefinition = definitionsManager
105
+ .getDefinitions()
106
+ .find(
107
+ (definition) =>
108
+ definition.version === blockUri.version && definition.definition.metadata.name === blockUri.fullName
109
+ );
105
110
 
106
111
  if (!blockDefinition) {
107
112
  throw new Error(`Unknown block: ${currentInstance.block.ref} in plan ${systemId}`);
@@ -3,6 +3,7 @@ import FSExtra from 'fs-extra';
3
3
  import { repositoryManager } from './repositoryManager';
4
4
  import ClusterConfiguration from '@kapeta/local-cluster-config';
5
5
  import { StringMap } from './types';
6
+ import { definitionsManager } from './definitionsManager';
6
7
 
7
8
  class ProviderManager {
8
9
  private _webAssetCache: StringMap;
@@ -11,7 +12,7 @@ class ProviderManager {
11
12
  }
12
13
 
13
14
  getWebProviders() {
14
- return ClusterConfiguration.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
15
+ return definitionsManager.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
15
16
  }
16
17
 
17
18
  async getAsset(handle: string, name: string, version: string, sourceMap: boolean = false) {
@@ -42,7 +43,7 @@ class ProviderManager {
42
43
  }
43
44
  }
44
45
 
45
- const providerDefinitions = ClusterConfiguration.getProviderDefinitions();
46
+ const providerDefinitions = definitionsManager.getProviderDefinitions();
46
47
 
47
48
  if (providerDefinitions.length > 0) {
48
49
  console.log('## Loaded the following providers ##');
@@ -9,6 +9,7 @@ import { socketManager } from './socketManager';
9
9
  import { progressListener } from './progressListener';
10
10
  import { Dependency } from '@kapeta/schemas';
11
11
  import { Actions, Config, RegistryService } from '@kapeta/nodejs-registry-utils';
12
+ import { definitionsManager } from './definitionsManager';
12
13
 
13
14
  const INSTALL_ATTEMPTED: { [p: string]: boolean } = {};
14
15
 
@@ -94,6 +95,7 @@ class RepositoryManager {
94
95
 
95
96
  allDefinitions = newDefinitions;
96
97
  socketManager.emit(`assets`, 'changed', payload);
98
+ definitionsManager.clearCache();
97
99
  });
98
100
  } catch (e) {
99
101
  // Fallback to run without watch mode due to potential platform issues.
@@ -186,7 +188,7 @@ class RepositoryManager {
186
188
  return;
187
189
  }
188
190
 
189
- const definitions = ClusterConfiguration.getDefinitions();
191
+ const definitions = definitionsManager.getDefinitions();
190
192
  const installedAsset = definitions.find(
191
193
  (d) => d.definition.metadata.name === fullName && d.version === version
192
194
  );
@@ -221,8 +223,10 @@ class RepositoryManager {
221
223
  } else {
222
224
  //Ensure dependencies are installed
223
225
  const refs = assetVersion.dependencies.map((dep: Dependency) => dep.name);
224
- console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
225
- await this._install(refs);
226
+ if (refs.length > 0) {
227
+ console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
228
+ await this._install(refs);
229
+ }
226
230
  }
227
231
  }
228
232
  }
@@ -2,6 +2,7 @@ import _ from 'lodash';
2
2
  import { clusterService } from './clusterService';
3
3
  import { storageService } from './storageService';
4
4
  import { EnvironmentType } from './types';
5
+ import { normalizeKapetaUri } from './utils/utils';
5
6
 
6
7
  const DEFAULT_PORT_TYPE = 'rest';
7
8
 
@@ -42,6 +43,8 @@ class ServiceManager {
42
43
  }
43
44
 
44
45
  _ensureSystem(systemId: string) {
46
+ systemId = normalizeKapetaUri(systemId);
47
+
45
48
  if (!this._systems[systemId]) {
46
49
  this._systems[systemId] = {};
47
50
  }
@@ -60,6 +63,7 @@ class ServiceManager {
60
63
  }
61
64
 
62
65
  async ensureServicePort(systemId: string, blockInstanceId: string, portType: string = DEFAULT_PORT_TYPE) {
66
+ systemId = normalizeKapetaUri(systemId);
63
67
  if (!portType) {
64
68
  portType = DEFAULT_PORT_TYPE;
65
69
  }
@@ -94,6 +98,7 @@ class ServiceManager {
94
98
  portType: string,
95
99
  environmentType?: EnvironmentType
96
100
  ): string {
101
+ systemId = normalizeKapetaUri(systemId);
97
102
  const port = clusterService.getClusterServicePort();
98
103
  const path = clusterService.getProxyPath(systemId, consumerInstanceId, consumerResourceName, portType);
99
104
  return this._forLocal(port, path, environmentType);
@@ -108,6 +113,7 @@ class ServiceManager {
108
113
  *
109
114
  */
110
115
  async getProviderAddress(systemId: string, providerInstanceId: string, portType: string): Promise<string> {
116
+ systemId = normalizeKapetaUri(systemId);
111
117
  const port = await this.ensureServicePort(systemId, providerInstanceId, portType);
112
118
  return this._forLocal(port);
113
119
  }
package/src/types.ts CHANGED
@@ -10,6 +10,7 @@ export type AnyMap = { [key: string]: any };
10
10
  export type LogLevel = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'FATAL';
11
11
  export type LogSource = 'stdout' | 'stderr';
12
12
  export type EnvironmentType = 'docker' | 'process';
13
+
13
14
  export interface LogEntry {
14
15
  source: LogSource;
15
16
  level: LogLevel;
@@ -23,32 +24,61 @@ export interface BlockProcessParams {
23
24
  configuration?: AnyMap;
24
25
  }
25
26
 
26
- export type ProcessType = 'docker' | 'local';
27
+ export enum InstanceType {
28
+ DOCKER = 'docker',
29
+ LOCAL = 'local',
30
+ UNKNOWN = 'unknown',
31
+ }
32
+ export enum InstanceOwner {
33
+ INTERNAL = 'internal',
34
+ EXTERNAL = 'external',
35
+ }
27
36
 
28
- export interface ProcessDetails {
29
- pid: number | string;
30
- type: ProcessType;
31
- portType?: string;
32
- output: EventEmitter;
33
- logs: () => LogEntry[];
34
- stop: () => Promise<void> | void;
37
+ export enum InstanceStatus {
38
+ STOPPED = 'stopped',
39
+ STARTING = 'starting',
40
+ BUSY = 'busy',
41
+ READY = 'ready',
42
+ STOPPING = 'stopping',
43
+ UNHEALTHY = 'unhealthy',
44
+ FAILED = 'failed',
35
45
  }
36
46
 
37
- export interface ProcessInfo extends ProcessDetails {
38
- id: string;
39
- ref: string;
40
- name: string;
47
+ export enum DesiredInstanceStatus {
48
+ STOP = 'stop',
49
+ RUN = 'run',
50
+ EXTERNAL = 'external',
41
51
  }
42
52
 
53
+ export type ProcessInfo = {
54
+ type: InstanceType;
55
+ pid?: number | string | null;
56
+ output: EventEmitter;
57
+ portType?: string;
58
+ logs: () => LogEntry[];
59
+ stop: () => Promise<void> | void;
60
+ };
61
+
43
62
  export type InstanceInfo = {
44
63
  systemId: string;
45
64
  instanceId: string;
65
+ ref: string;
66
+ name: string;
67
+ type: InstanceType;
68
+ owner: InstanceOwner;
69
+ status: InstanceStatus;
70
+ desiredStatus: DesiredInstanceStatus;
46
71
  address?: string;
72
+
73
+ startedAt?: number;
47
74
  health?: string | null;
48
- status: string;
49
75
  pid?: number | string | null;
50
- type: ProcessType;
51
76
  portType?: string;
77
+
78
+ internal?: {
79
+ output: EventEmitter;
80
+ logs: () => LogEntry[];
81
+ };
52
82
  };
53
83
 
54
84
  interface ResourceRef {
@@ -1,15 +1,15 @@
1
1
  import FS from 'node:fs';
2
2
  import ClusterConfig, { DefinitionInfo } from '@kapeta/local-cluster-config';
3
- import { getBindHost, readYML } from './utils';
3
+ import { getBindHost, getBlockInstanceContainerName, normalizeKapetaUri, readYML } from './utils';
4
4
  import { KapetaURI, parseKapetaUri } from '@kapeta/nodejs-utils';
5
5
  import { serviceManager } from '../serviceManager';
6
6
  import { containerManager, DockerMounts, toLocalBindVolume } from '../containerManager';
7
7
  import { LogData } from './LogData';
8
8
  import EventEmitter from 'events';
9
- import md5 from 'md5';
10
9
  import { clusterService } from '../clusterService';
11
- import { AnyMap, BlockProcessParams, ProcessDetails, ProcessInfo, StringMap } from '../types';
10
+ import { AnyMap, BlockProcessParams, ProcessInfo, InstanceType, StringMap } from '../types';
12
11
  import { Container } from 'node-docker-api/lib/container';
12
+ import { definitionsManager } from '../definitionsManager';
13
13
 
14
14
  const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
15
15
  const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
@@ -27,7 +27,7 @@ const DOCKER_ENV_VARS = [
27
27
  ];
28
28
 
29
29
  function getProvider(uri: KapetaURI) {
30
- return ClusterConfig.getProviderDefinitions().find((provider) => {
30
+ return definitionsManager.getProviderDefinitions().find((provider) => {
31
31
  const ref = `${provider.definition.metadata.name}:${provider.version}`;
32
32
  return parseKapetaUri(ref).id === uri.id;
33
33
  });
@@ -46,13 +46,13 @@ function getProviderPorts(assetVersion: DefinitionInfo): string[] {
46
46
  export class BlockInstanceRunner {
47
47
  private readonly _systemId: string;
48
48
 
49
- constructor(planReference: string) {
49
+ constructor(systemId: string) {
50
50
  /**
51
51
  *
52
52
  * @type {string}
53
53
  * @private
54
54
  */
55
- this._systemId = planReference ?? '';
55
+ this._systemId = normalizeKapetaUri(systemId);
56
56
  }
57
57
 
58
58
  /**
@@ -88,7 +88,7 @@ export class BlockInstanceRunner {
88
88
  blockUri.version = 'local';
89
89
  }
90
90
 
91
- const assetVersion = ClusterConfig.getDefinitions().find((definitions) => {
91
+ const assetVersion = definitionsManager.getDefinitions().find((definitions) => {
92
92
  const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
93
93
  return parseKapetaUri(ref).id === blockUri.id;
94
94
  });
@@ -105,30 +105,26 @@ export class BlockInstanceRunner {
105
105
  throw new Error(`Kind not found: ${kindUri.id}`);
106
106
  }
107
107
 
108
- let processDetails: ProcessDetails;
108
+ let processInfo: ProcessInfo;
109
109
 
110
110
  if (providerVersion.definition.kind === KIND_BLOCK_TYPE_OPERATOR) {
111
- processDetails = await this._startOperatorProcess(blockInstance, blockUri, providerVersion, env);
111
+ processInfo = await this._startOperatorProcess(blockInstance, blockUri, providerVersion, env);
112
112
  } else {
113
113
  //We need a port type to know how to connect to the block consistently
114
114
  const portTypes = getProviderPorts(assetVersion);
115
115
 
116
116
  if (blockUri.version === 'local') {
117
- processDetails = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
117
+ processInfo = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
118
118
  } else {
119
- processDetails = await this._startDockerProcess(blockInstance, blockUri, env);
119
+ processInfo = await this._startDockerProcess(blockInstance, blockUri, env);
120
120
  }
121
121
 
122
122
  if (portTypes.length > 0) {
123
- processDetails.portType = portTypes[0];
123
+ processInfo.portType = portTypes[0];
124
124
  }
125
125
  }
126
126
 
127
- return {
128
- name: blockUri.id,
129
- ...blockInstance,
130
- ...processDetails,
131
- };
127
+ return processInfo;
132
128
  }
133
129
 
134
130
  /**
@@ -139,7 +135,7 @@ export class BlockInstanceRunner {
139
135
  blockInfo: KapetaURI,
140
136
  env: StringMap,
141
137
  assetVersion: DefinitionInfo
142
- ): Promise<ProcessDetails> {
138
+ ): Promise<ProcessInfo> {
143
139
  const baseDir = ClusterConfig.getRepositoryAssetPath(blockInfo.handle, blockInfo.name, blockInfo.version);
144
140
 
145
141
  if (!FS.existsSync(baseDir)) {
@@ -172,22 +168,25 @@ export class BlockInstanceRunner {
172
168
  throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
173
169
  }
174
170
 
175
- const containerName = `kapeta-block-instance-${blockInstance.id}`;
171
+ const containerName = getBlockInstanceContainerName(blockInstance.id);
176
172
  const logs = new LogData();
177
173
  logs.addLog(`Starting block ${blockInstance.ref}`);
178
- let container: Container | null = (await containerManager.getContainerByName(containerName)) ?? null;
174
+ let containerInfo = await containerManager.getContainerByName(containerName);
175
+ let container = containerInfo?.native;
176
+
179
177
  console.log('Starting dev container', containerName);
180
178
 
181
- if (container) {
182
- console.log(`Container already exists. Deleting...`);
179
+ if (containerInfo) {
180
+ console.log(`Dev container already exists. Deleting...`);
183
181
  try {
184
- await container.delete({
182
+ await containerInfo.remove({
185
183
  force: true,
186
184
  });
187
185
  } catch (e: any) {
188
186
  throw new Error('Failed to delete existing container: ' + e.message);
189
187
  }
190
- container = null;
188
+ container = undefined;
189
+ containerInfo = undefined;
191
190
  }
192
191
 
193
192
  logs.addLog(`Creating new container for block: ${containerName}`);
@@ -229,6 +228,7 @@ export class BlockInstanceRunner {
229
228
  HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
230
229
  }
231
230
 
231
+ console.log('Starting dev container', containerName, dockerImage);
232
232
  container = await containerManager.startContainer({
233
233
  Image: dockerImage,
234
234
  name: containerName,
@@ -274,7 +274,7 @@ export class BlockInstanceRunner {
274
274
  container: Container,
275
275
  logs: LogData,
276
276
  deleteOnExit: boolean = false
277
- ): Promise<ProcessDetails> {
277
+ ): Promise<ProcessInfo> {
278
278
  let localContainer: Container | null = container;
279
279
  const logStream = (await container.logs({
280
280
  follow: true,
@@ -299,14 +299,14 @@ export class BlockInstanceRunner {
299
299
  const data = status.data as any;
300
300
  if (deleteOnExit) {
301
301
  try {
302
- await container.delete();
302
+ await containerManager.remove(container);
303
303
  } catch (e: any) {}
304
304
  }
305
305
  outputEvents.emit('exit', data?.State?.ExitCode ?? 0);
306
306
  });
307
307
 
308
308
  return {
309
- type: 'docker',
309
+ type: InstanceType.DOCKER,
310
310
  pid: container.id,
311
311
  output: outputEvents,
312
312
  stop: async () => {
@@ -317,7 +317,7 @@ export class BlockInstanceRunner {
317
317
  try {
318
318
  await localContainer.stop();
319
319
  if (deleteOnExit) {
320
- await localContainer.delete();
320
+ await containerManager.remove(localContainer);
321
321
  }
322
322
  } catch (e) {}
323
323
  localContainer = null;
@@ -350,9 +350,10 @@ export class BlockInstanceRunner {
350
350
  throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
351
351
  }
352
352
 
353
- const containerName = `kapeta-block-instance-${blockInstance.id}`;
353
+ const containerName = getBlockInstanceContainerName(blockInstance.id);
354
354
  const logs = new LogData();
355
- let container = await containerManager.getContainerByName(containerName);
355
+ const containerInfo = await containerManager.getContainerByName(containerName);
356
+ let container = containerInfo?.native;
356
357
 
357
358
  // For windows we need to default to root
358
359
  const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
@@ -435,9 +436,11 @@ export class BlockInstanceRunner {
435
436
  console.warn('Failed to pull image. Continuing...', e);
436
437
  }
437
438
 
438
- const containerName = `kapeta-block-instance-${md5(blockInstance.id)}`;
439
+ const containerName = getBlockInstanceContainerName(blockInstance.id);
439
440
  const logs = new LogData();
440
- let container: Container | null = (await containerManager.getContainerByName(containerName)) ?? null;
441
+ const containerInfo = await containerManager.getContainerByName(containerName);
442
+ let container = containerInfo?.native;
443
+
441
444
  if (container) {
442
445
  const containerData = container.data as any;
443
446
  if (containerData.State === 'running') {
@@ -446,9 +449,9 @@ export class BlockInstanceRunner {
446
449
  if (containerData.State?.ExitCode > 0) {
447
450
  logs.addLog(`Container exited with code: ${containerData.State.ExitCode}. Deleting...`);
448
451
  try {
449
- await container.delete();
452
+ await containerManager.remove(container);
450
453
  } catch (e) {}
451
- container = null;
454
+ container = undefined;
452
455
  } else {
453
456
  logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
454
457
  try {
@@ -456,9 +459,9 @@ export class BlockInstanceRunner {
456
459
  } catch (e) {
457
460
  console.warn('Failed to start container. Deleting...', e);
458
461
  try {
459
- await container.delete();
462
+ await containerManager.remove(container);
460
463
  } catch (e) {}
461
- container = null;
464
+ container = undefined;
462
465
  }
463
466
  }
464
467
  }
@@ -1,5 +1,23 @@
1
1
  import FS from 'node:fs';
2
2
  import YAML from 'yaml';
3
+ import { parseKapetaUri } from '@kapeta/nodejs-utils';
4
+
5
+ export function getBlockInstanceContainerName(instanceId: string) {
6
+ return `kapeta-block-instance-${instanceId}`;
7
+ }
8
+
9
+ export function normalizeKapetaUri(uri: string) {
10
+ if (!uri) {
11
+ return '';
12
+ }
13
+
14
+ const uriObj = parseKapetaUri(uri);
15
+ if (!uriObj.version) {
16
+ return `kapeta://${parseKapetaUri(uri).fullName}`;
17
+ }
18
+
19
+ return `kapeta://${parseKapetaUri(uri).id}`;
20
+ }
3
21
 
4
22
  export function readYML(path: string) {
5
23
  const rawYaml = FS.readFileSync(path);