@kapeta/local-cluster-service 0.35.0 → 0.36.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.
@@ -5,7 +5,8 @@
5
5
  import { DefinitionInfo } from '@kapeta/local-cluster-config';
6
6
  import { ContainerInfo } from './containerManager';
7
7
  import { EnvironmentType, LocalImageOptions, OperatorInfo } from './types';
8
- export declare const KIND_OPERATOR = "core/resource-type-operator";
8
+ export declare const KIND_RESOURCE_OPERATOR = "core/resource-type-operator";
9
+ export declare const KIND_BLOCK_OPERATOR = "core/block-type-operator";
9
10
  declare class Operator {
10
11
  private readonly _data;
11
12
  constructor(data: DefinitionInfo);
@@ -21,7 +22,7 @@ declare class OperatorManager {
21
22
  /**
22
23
  * Get operator definition for resource type
23
24
  */
24
- getOperator(resourceType: string, version: string): Promise<Operator>;
25
+ getOperator(fullName: string, version: string): Promise<Operator>;
25
26
  /**
26
27
  * Get information about a specific consumed resource
27
28
  */
@@ -29,12 +30,11 @@ declare class OperatorManager {
29
30
  /**
30
31
  * Ensure we have a running operator of given type
31
32
  *
32
- * @param {string} systemId
33
- * @param {string} resourceType
34
- * @param {string} version
35
- * @return {Promise<ContainerInfo>}
33
+ * @param systemId the plan ref
34
+ * @param kind the full name - e.g. myhandle/rabbitmq
35
+ * @param version the version of the operator
36
36
  */
37
- ensureResource(systemId: string, resourceType: string, version: string): Promise<ContainerInfo>;
37
+ ensureOperator(systemId: string, kind: string, version: string): Promise<ContainerInfo>;
38
38
  }
39
39
  export declare const operatorManager: OperatorManager;
40
40
  export {};
@@ -7,7 +7,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
8
8
  };
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.operatorManager = exports.KIND_OPERATOR = void 0;
10
+ exports.operatorManager = exports.KIND_BLOCK_OPERATOR = exports.KIND_RESOURCE_OPERATOR = void 0;
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const md5_1 = __importDefault(require("md5"));
13
13
  const serviceManager_1 = require("./serviceManager");
@@ -20,7 +20,8 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
20
20
  const lodash_1 = __importDefault(require("lodash"));
21
21
  const async_lock_1 = __importDefault(require("async-lock"));
22
22
  const taskManager_1 = require("./taskManager");
23
- exports.KIND_OPERATOR = 'core/resource-type-operator';
23
+ exports.KIND_RESOURCE_OPERATOR = 'core/resource-type-operator';
24
+ exports.KIND_BLOCK_OPERATOR = 'core/block-type-operator';
24
25
  const KIND_PLAN = 'core/plan';
25
26
  class Operator {
26
27
  _data;
@@ -50,18 +51,18 @@ class OperatorManager {
50
51
  /**
51
52
  * Get operator definition for resource type
52
53
  */
53
- async getOperator(resourceType, version) {
54
- const operators = await definitionsManager_1.definitionsManager.getDefinitions(exports.KIND_OPERATOR);
54
+ async getOperator(fullName, version) {
55
+ const operators = await definitionsManager_1.definitionsManager.getDefinitions([exports.KIND_RESOURCE_OPERATOR, exports.KIND_BLOCK_OPERATOR]);
55
56
  const operator = operators.find((operator) => operator.definition &&
56
57
  operator.definition.metadata &&
57
58
  operator.definition.metadata.name &&
58
- operator.definition.metadata.name.toLowerCase() === resourceType.toLowerCase() &&
59
+ operator.definition.metadata.name.toLowerCase() === fullName.toLowerCase() &&
59
60
  operator.version === version);
60
61
  if (!operator) {
61
- throw new Error(`Unknown resource type: ${resourceType}:${version}`);
62
+ throw new Error(`Unknown operator type: ${fullName}:${version}`);
62
63
  }
63
64
  if (!operator.definition.spec || !operator.definition.spec.local) {
64
- throw new Error(`Operator missing local definition: ${resourceType}:${version}`);
65
+ throw new Error(`Operator missing local definition: ${fullName}:${version}`);
65
66
  }
66
67
  return new Operator(operator);
67
68
  }
@@ -96,7 +97,7 @@ class OperatorManager {
96
97
  const kindUri = (0, nodejs_utils_1.parseKapetaUri)(blockResource.kind);
97
98
  const operator = await this.getOperator(resourceType, kindUri.version);
98
99
  const credentials = operator.getCredentials();
99
- const container = await this.ensureResource(systemId, resourceType, kindUri.version);
100
+ const container = await this.ensureOperator(systemId, resourceType, kindUri.version);
100
101
  const portInfo = await container.getPort(portType);
101
102
  if (!portInfo) {
102
103
  throw new Error('Unknown resource port type : ' + resourceType + '#' + portType);
@@ -119,16 +120,15 @@ class OperatorManager {
119
120
  /**
120
121
  * Ensure we have a running operator of given type
121
122
  *
122
- * @param {string} systemId
123
- * @param {string} resourceType
124
- * @param {string} version
125
- * @return {Promise<ContainerInfo>}
123
+ * @param systemId the plan ref
124
+ * @param kind the full name - e.g. myhandle/rabbitmq
125
+ * @param version the version of the operator
126
126
  */
127
- async ensureResource(systemId, resourceType, version) {
127
+ async ensureOperator(systemId, kind, version) {
128
128
  systemId = (0, nodejs_utils_1.normalizeKapetaUri)(systemId);
129
- const key = `${systemId}#${resourceType}:${version}`;
129
+ const key = `${systemId}#${kind}:${version}`;
130
130
  return await this.operatorLock.acquire(key, async () => {
131
- const operator = await this.getOperator(resourceType, version);
131
+ const operator = await this.getOperator(kind, version);
132
132
  const operatorData = operator.getLocalData();
133
133
  const portTypes = Object.keys(operatorData.ports);
134
134
  portTypes.sort();
@@ -136,7 +136,7 @@ class OperatorManager {
136
136
  for (let i = 0; i < portTypes.length; i++) {
137
137
  const portType = portTypes[i];
138
138
  let containerPortInfo = operatorData.ports[portType];
139
- const hostPort = await serviceManager_1.serviceManager.ensureServicePort(systemId, resourceType, portType);
139
+ const hostPort = await serviceManager_1.serviceManager.ensureServicePort(systemId, kind, portType);
140
140
  const portInfo = (0, utils_1.toPortInfo)(containerPortInfo);
141
141
  const portId = portInfo.port + '/' + portInfo.type;
142
142
  ports[portId] = {
@@ -144,7 +144,7 @@ class OperatorManager {
144
144
  hostPort,
145
145
  };
146
146
  }
147
- const nameParts = [systemId, resourceType.toLowerCase(), version];
147
+ const nameParts = [systemId, kind.toLowerCase(), version];
148
148
  const containerName = `kapeta-resource-${(0, md5_1.default)(nameParts.join('_'))}`;
149
149
  const PortBindings = {};
150
150
  const Env = [];
@@ -152,7 +152,7 @@ class OperatorManager {
152
152
  const Labels = {
153
153
  kapeta: 'true',
154
154
  [containerManager_1.COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
155
- [containerManager_1.COMPOSE_LABEL_SERVICE]: [resourceType, version].join('_').replace(/[^a-z0-9]/gi, '_'),
155
+ [containerManager_1.COMPOSE_LABEL_SERVICE]: [kind, version].join('_').replace(/[^a-z0-9]/gi, '_'),
156
156
  };
157
157
  const operatorMetadata = operator.getDefinitionInfo().definition.metadata;
158
158
  const bindHost = (0, utils_1.getBindHost)();
@@ -167,7 +167,7 @@ class OperatorManager {
167
167
  ];
168
168
  Labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
169
169
  });
170
- const Mounts = await containerManager_1.containerManager.createVolumes(systemId, resourceType, operatorData.mounts);
170
+ const Mounts = await containerManager_1.containerManager.createVolumes(systemId, kind, operatorData.mounts);
171
171
  lodash_1.default.forEach(operatorData.env, (value, name) => {
172
172
  Env.push(name + '=' + value);
173
173
  });
@@ -76,6 +76,7 @@ export type LocalImageOptions<Credentials = AnyMap, Options = AnyMap> = {
76
76
  cmd?: string;
77
77
  env?: AnyMap;
78
78
  health?: Health;
79
+ singleton?: boolean;
79
80
  mounts?: {
80
81
  [key: string]: string;
81
82
  };
@@ -2,9 +2,7 @@
2
2
  * Copyright 2023 Kapeta Inc.
3
3
  * SPDX-License-Identifier: BUSL-1.1
4
4
  */
5
- import { DefinitionInfo } from '@kapeta/local-cluster-config';
6
- import { KapetaURI } from '@kapeta/nodejs-utils';
7
- import { AnyMap, BlockProcessParams, ProcessInfo, StringMap } from '../types';
5
+ import { AnyMap, ProcessInfo } from '../types';
8
6
  export declare function resolvePortType(portType: string): string;
9
7
  export declare class BlockInstanceRunner {
10
8
  private readonly _systemId;
@@ -20,17 +18,11 @@ export declare class BlockInstanceRunner {
20
18
  */
21
19
  private _startLocalProcess;
22
20
  private _startDockerProcess;
21
+ private _startOperatorProcess;
23
22
  /**
24
- *
25
- * @param blockInstance
26
- * @param blockUri
27
- * @param providerDefinition
28
- * @param {{[key:string]:string}} env
29
- * @return {Promise<ProcessDetails>}
30
- * @private
23
+ * Get the port bindings for a non-operator block
31
24
  */
32
- _startOperatorProcess(blockInstance: BlockProcessParams, blockUri: KapetaURI, providerDefinition: DefinitionInfo, env: StringMap): Promise<ProcessInfo>;
33
- private getDockerPortBindings;
25
+ private getServiceBlockPortBindings;
34
26
  private ensureContainer;
35
27
  private _handleContainer;
36
28
  }
@@ -19,6 +19,7 @@ const clusterService_1 = require("../clusterService");
19
19
  const types_1 = require("../types");
20
20
  const definitionsManager_1 = require("../definitionsManager");
21
21
  const node_os_1 = __importDefault(require("node:os"));
22
+ const taskManager_1 = require("../taskManager");
22
23
  const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
23
24
  const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
24
25
  const KAPETA_BLOCK_REF = 'KAPETA_BLOCK_REF';
@@ -40,16 +41,23 @@ async function getProvider(uri) {
40
41
  });
41
42
  }
42
43
  function resolvePortType(portType) {
43
- if (serviceManager_1.HTTP_PORTS.includes(portType)) {
44
+ if (portType && serviceManager_1.HTTP_PORTS.includes(portType.toLowerCase())) {
44
45
  return serviceManager_1.HTTP_PORT_TYPE;
45
46
  }
46
47
  return portType;
47
48
  }
48
49
  exports.resolvePortType = resolvePortType;
49
- function getProviderPorts(assetVersion, providerVersion) {
50
+ /**
51
+ * Get the port types for a non-operator block instance
52
+ */
53
+ function getServiceProviderPorts(assetVersion, providerVersion) {
50
54
  const out = assetVersion.definition?.spec?.providers
55
+ ?.filter((provider) => {
56
+ // We only support HTTP provider ports for now. Need to figure out how to handle other types
57
+ return serviceManager_1.HTTP_PORTS.includes(provider.spec?.port?.type?.toLowerCase());
58
+ })
51
59
  ?.map((provider) => {
52
- return resolvePortType(provider.spec?.port?.type);
60
+ return resolvePortType(provider.spec?.port?.type?.toLowerCase());
53
61
  })
54
62
  .filter((t) => !!t) ?? [];
55
63
  if (out.length === 0) {
@@ -112,7 +120,7 @@ class BlockInstanceRunner {
112
120
  }
113
121
  else {
114
122
  //We need a port type to know how to connect to the block consistently
115
- const portTypes = getProviderPorts(assetVersion, providerVersion);
123
+ const portTypes = getServiceProviderPorts(assetVersion, providerVersion);
116
124
  if (blockUri.version === 'local') {
117
125
  processInfo = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
118
126
  }
@@ -155,7 +163,7 @@ class BlockInstanceRunner {
155
163
  if (!dockerImage) {
156
164
  throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
157
165
  }
158
- const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
166
+ const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, targetKindUri.id);
159
167
  const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
160
168
  const dockerOpts = localContainer.options ?? {};
161
169
  const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
@@ -168,7 +176,7 @@ class BlockInstanceRunner {
168
176
  delete localContainer.HostConfig;
169
177
  delete localContainer.Labels;
170
178
  delete localContainer.Env;
171
- const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion, providerVersion);
179
+ const { PortBindings, ExposedPorts, addonEnv } = await this.getServiceBlockPortBindings(blockInstance, assetVersion, providerVersion);
172
180
  let HealthCheck = undefined;
173
181
  if (localContainer.healthcheck) {
174
182
  HealthCheck = containerManager_1.containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
@@ -240,8 +248,8 @@ class BlockInstanceRunner {
240
248
  if (!providerVersion) {
241
249
  throw new Error(`Block type not found: ${kindUri.id}`);
242
250
  }
243
- const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion, providerVersion);
244
- const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
251
+ const { PortBindings, ExposedPorts, addonEnv } = await this.getServiceBlockPortBindings(blockInstance, assetVersion, providerVersion);
252
+ const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, kindUri.id);
245
253
  // For windows we need to default to root
246
254
  const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
247
255
  const systemUri = (0, nodejs_utils_1.parseKapetaUri)(this._systemId);
@@ -268,15 +276,6 @@ class BlockInstanceRunner {
268
276
  },
269
277
  });
270
278
  }
271
- /**
272
- *
273
- * @param blockInstance
274
- * @param blockUri
275
- * @param providerDefinition
276
- * @param {{[key:string]:string}} env
277
- * @return {Promise<ProcessDetails>}
278
- * @private
279
- */
280
279
  async _startOperatorProcess(blockInstance, blockUri, providerDefinition, env) {
281
280
  const { assetFile } = local_cluster_config_1.default.getRepositoryAssetInfoPath(blockUri.handle, blockUri.name, blockUri.version);
282
281
  const kapetaYmlPath = assetFile;
@@ -290,88 +289,107 @@ class BlockInstanceRunner {
290
289
  }
291
290
  const local = spec.local;
292
291
  const dockerImage = local.image;
293
- //We only want 1 operator per operator type - across all local systems
294
- const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
295
- const logs = new LogData_1.LogData();
296
- const bindHost = (0, utils_1.getBindHost)();
297
- const ExposedPorts = {};
298
- const addonEnv = {};
299
- const PortBindings = {};
300
- let HealthCheck = undefined;
301
- let Mounts = [];
302
- const localPorts = local.ports ?? {};
303
- const labels = {};
304
- const promises = Object.entries(localPorts).map(async ([portType, value]) => {
305
- const portInfo = (0, utils_1.toPortInfo)(value);
306
- const dockerPort = `${portInfo.port}/${portInfo.type}`;
307
- ExposedPorts[dockerPort] = {};
308
- addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = `${portInfo.port}`;
309
- const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
310
- PortBindings[dockerPort] = [
311
- {
312
- HostIp: bindHost,
313
- HostPort: `${publicPort}`,
314
- },
315
- ];
316
- labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + publicPort] = portType;
317
- });
318
- await Promise.all(promises);
319
- if (local.env) {
320
- Object.entries(local.env).forEach(([key, value]) => {
321
- addonEnv[key] = value;
322
- });
323
- }
324
- if (local.mounts) {
325
- Mounts = await containerManager_1.containerManager.createVolumes(this._systemId, blockUri.id, local.mounts);
292
+ const operatorUri = local.singleton ? (0, nodejs_utils_1.parseKapetaUri)(providerRef) : blockUri;
293
+ const operatorId = local.singleton ? providerRef : blockInstance.id;
294
+ const operatorRef = local.singleton ? providerRef : blockInstance.ref;
295
+ if (local.singleton && env) {
296
+ env[KAPETA_BLOCK_REF] = operatorRef;
297
+ env[KAPETA_INSTANCE_ID] = operatorId;
326
298
  }
327
- if (local.health) {
328
- HealthCheck = containerManager_1.containerManager.toDockerHealth(local.health);
329
- }
330
- // For windows we need to default to root
331
- const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
332
- const systemUri = (0, nodejs_utils_1.parseKapetaUri)(this._systemId);
333
- logs.addLog(`Creating new container for block: ${containerName}`);
334
- const out = await this.ensureContainer({
335
- Image: dockerImage,
336
- name: containerName,
337
- ExposedPorts,
338
- HealthCheck,
339
- HostConfig: {
340
- Binds: [
299
+ const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, providerRef);
300
+ const task = taskManager_1.taskManager.add(`container:start:${containerName}`, async () => {
301
+ const logs = new LogData_1.LogData();
302
+ const bindHost = (0, utils_1.getBindHost)();
303
+ const ExposedPorts = {};
304
+ const addonEnv = {};
305
+ const PortBindings = {};
306
+ let HealthCheck = undefined;
307
+ let Mounts = [];
308
+ const localPorts = local.ports ?? {};
309
+ const labels = {};
310
+ const promises = Object.entries(localPorts).map(async ([portType, value]) => {
311
+ const portInfo = (0, utils_1.toPortInfo)(value);
312
+ const dockerPort = `${portInfo.port}/${portInfo.type}`;
313
+ ExposedPorts[dockerPort] = {};
314
+ addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = `${portInfo.port}`;
315
+ const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, operatorId, portType);
316
+ PortBindings[dockerPort] = [
317
+ {
318
+ HostIp: bindHost,
319
+ HostPort: `${publicPort}`,
320
+ },
321
+ ];
322
+ labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + publicPort] = portType;
323
+ });
324
+ await Promise.all(promises);
325
+ if (local.env) {
326
+ Object.entries(local.env).forEach(([key, value]) => {
327
+ addonEnv[key] = value;
328
+ });
329
+ }
330
+ if (local.mounts) {
331
+ Mounts = await containerManager_1.containerManager.createVolumes(this._systemId, operatorUri.id, local.mounts);
332
+ }
333
+ if (local.health) {
334
+ HealthCheck = containerManager_1.containerManager.toDockerHealth(local.health);
335
+ }
336
+ // For windows we need to default to root
337
+ const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
338
+ const Binds = local.singleton
339
+ ? [`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`]
340
+ : [
341
341
  `${(0, containerManager_1.toLocalBindVolume)(kapetaYmlPath)}:/kapeta.yml:ro`,
342
342
  `${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`,
343
+ ];
344
+ const systemUri = (0, nodejs_utils_1.parseKapetaUri)(this._systemId);
345
+ console.log(`Ensuring container for operator block: ${containerName} [singleton: ${!!local.singleton}]`);
346
+ logs.addLog(`Ensuring container for operator block: ${containerName}`);
347
+ const out = await this.ensureContainer({
348
+ Image: dockerImage,
349
+ name: containerName,
350
+ ExposedPorts,
351
+ HealthCheck,
352
+ HostConfig: {
353
+ Binds,
354
+ PortBindings,
355
+ Mounts,
356
+ },
357
+ Labels: {
358
+ ...labels,
359
+ instance: operatorId,
360
+ [containerManager_1.COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
361
+ [containerManager_1.COMPOSE_LABEL_SERVICE]: operatorUri.id.replace(/[^a-z0-9]/gi, '_'),
362
+ },
363
+ Env: [
364
+ `KAPETA_INSTANCE_NAME=${operatorRef}`,
365
+ `KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
366
+ ...DOCKER_ENV_VARS,
367
+ ...Object.entries({
368
+ ...env,
369
+ ...addonEnv,
370
+ }).map(([key, value]) => `${key}=${value}`),
343
371
  ],
344
- PortBindings,
345
- Mounts,
346
- },
347
- Labels: {
348
- ...labels,
349
- instance: blockInstance.id,
350
- [containerManager_1.COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
351
- [containerManager_1.COMPOSE_LABEL_SERVICE]: blockUri.id.replace(/[^a-z0-9]/gi, '_'),
352
- },
353
- Env: [
354
- `KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
355
- `KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
356
- ...DOCKER_ENV_VARS,
357
- ...Object.entries({
358
- ...env,
359
- ...addonEnv,
360
- }).map(([key, value]) => `${key}=${value}`),
361
- ],
372
+ });
373
+ const portTypes = local.ports ? Object.keys(local.ports) : [];
374
+ if (portTypes.length > 0) {
375
+ out.portType = portTypes[0];
376
+ }
377
+ return out;
378
+ }, {
379
+ name: `Starting container for ${providerRef}`,
380
+ systemId: this._systemId,
362
381
  });
363
- const portTypes = local.ports ? Object.keys(local.ports) : [];
364
- if (portTypes.length > 0) {
365
- out.portType = portTypes[0];
366
- }
367
- return out;
382
+ return task.wait();
368
383
  }
369
- async getDockerPortBindings(blockInstance, assetVersion, providerVersion) {
384
+ /**
385
+ * Get the port bindings for a non-operator block
386
+ */
387
+ async getServiceBlockPortBindings(blockInstance, assetVersion, providerVersion) {
370
388
  const bindHost = (0, utils_1.getBindHost)();
371
389
  const ExposedPorts = {};
372
390
  const addonEnv = {};
373
391
  const PortBindings = {};
374
- const portTypes = getProviderPorts(assetVersion, providerVersion);
392
+ const portTypes = getServiceProviderPorts(assetVersion, providerVersion);
375
393
  let port = 80;
376
394
  const promises = portTypes.map(async (portType) => {
377
395
  const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { EntityList } from '@kapeta/schemas';
6
6
  import { AnyMap, PortInfo } from '../types';
7
- export declare function getBlockInstanceContainerName(systemId: string, instanceId: string): string;
7
+ export declare function getBlockInstanceContainerName(systemId: string, instanceId: string, blockType?: string): Promise<string>;
8
8
  export declare function toPortInfo(port: PortInfo): {
9
9
  port: number;
10
10
  type: string;
@@ -13,8 +13,31 @@ const yaml_1 = __importDefault(require("yaml"));
13
13
  const md5_1 = __importDefault(require("md5"));
14
14
  const lodash_1 = __importDefault(require("lodash"));
15
15
  const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
16
- function getBlockInstanceContainerName(systemId, instanceId) {
17
- return `kapeta-block-instance-${(0, md5_1.default)(systemId + instanceId)}`;
16
+ const definitionsManager_1 = require("../definitionsManager");
17
+ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
18
+ const operatorManager_1 = require("../operatorManager");
19
+ const assetManager_1 = require("../assetManager");
20
+ async function getBlockInstanceContainerName(systemId, instanceId, blockType) {
21
+ if (!blockType) {
22
+ const instance = await assetManager_1.assetManager.getBlockInstance(systemId, instanceId);
23
+ if (!instance) {
24
+ throw new Error(`Instance ${instanceId} not found in plan ${systemId}`);
25
+ }
26
+ const block = await assetManager_1.assetManager.getAsset(instance.block.ref);
27
+ if (!block) {
28
+ throw new Error(`Block ${instance.block.ref} not found`);
29
+ }
30
+ blockType = block.data.kind;
31
+ }
32
+ const typeDefinition = await definitionsManager_1.definitionsManager.getDefinition(blockType);
33
+ if (!typeDefinition) {
34
+ throw new Error(`Block type ${blockType} not found`);
35
+ }
36
+ if ((0, nodejs_utils_1.parseKapetaUri)(typeDefinition.definition.kind).fullName === operatorManager_1.KIND_BLOCK_OPERATOR &&
37
+ typeDefinition.definition.spec?.local?.singleton) {
38
+ return `kapeta-instance-operator-${(0, md5_1.default)((0, nodejs_utils_1.normalizeKapetaUri)(systemId) + (0, nodejs_utils_1.normalizeKapetaUri)(blockType))}`;
39
+ }
40
+ return `kapeta-block-instance-${(0, md5_1.default)((0, nodejs_utils_1.normalizeKapetaUri)(systemId) + instanceId)}`;
18
41
  }
19
42
  exports.getBlockInstanceContainerName = getBlockInstanceContainerName;
20
43
  function toPortInfo(port) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.35.0",
3
+ "version": "0.36.1",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -694,7 +694,7 @@ class ContainerManager {
694
694
  }
695
695
 
696
696
  async getLogs(instance: InstanceInfo): Promise<LogEntry[]> {
697
- const containerName = getBlockInstanceContainerName(instance.systemId, instance.instanceId);
697
+ const containerName = await getBlockInstanceContainerName(instance.systemId, instance.instanceId);
698
698
  const containerInfo = await this.getContainerByName(containerName);
699
699
  if (!containerInfo) {
700
700
  return [
@@ -711,7 +711,7 @@ class ContainerManager {
711
711
  }
712
712
 
713
713
  async stopLogListening(systemId: string, instanceId: string) {
714
- const containerName = getBlockInstanceContainerName(systemId, instanceId);
714
+ const containerName = await getBlockInstanceContainerName(systemId, instanceId);
715
715
  if (this.logStreams[containerName]) {
716
716
  if (this.logStreams[containerName]?.timer) {
717
717
  clearTimeout(this.logStreams[containerName].timer);
@@ -729,7 +729,7 @@ class ContainerManager {
729
729
  }
730
730
 
731
731
  async ensureLogListening(systemId: string, instanceId: string, handler: (log: LogEntry) => void) {
732
- const containerName = getBlockInstanceContainerName(systemId, instanceId);
732
+ const containerName = await getBlockInstanceContainerName(systemId, instanceId);
733
733
  try {
734
734
  if (this.logStreams[containerName]?.stream) {
735
735
  // Already listening - will shut itself down