@kapeta/local-cluster-service 0.32.0 → 0.32.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.32.2](https://github.com/kapetacom/local-cluster-service/compare/v0.32.1...v0.32.2) (2023-12-25)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Use volumes instead of host mounts for faster speeds ([#108](https://github.com/kapetacom/local-cluster-service/issues/108)) ([eac48ea](https://github.com/kapetacom/local-cluster-service/commit/eac48ea767dfc8773a7d0990106fe1f3f29bfec4))
7
+
8
+ ## [0.32.1](https://github.com/kapetacom/local-cluster-service/compare/v0.32.0...v0.32.1) (2023-12-23)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Several smaller fixes ([4036345](https://github.com/kapetacom/local-cluster-service/commit/40363457597d36c97481e94e646a6b45d113bb09))
14
+
1
15
  # [0.32.0](https://github.com/kapetacom/local-cluster-service/compare/v0.31.0...v0.32.0) (2023-12-20)
2
16
 
3
17
 
@@ -20,6 +20,24 @@ const cacheManager_1 = require("./cacheManager");
20
20
  const node_events_1 = require("node:events");
21
21
  const assetManager_1 = require("./assetManager");
22
22
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
23
+ let definitions;
24
+ let definitionTimeout;
25
+ function getDefinitionsDebounced() {
26
+ if (definitionTimeout) {
27
+ clearTimeout(definitionTimeout);
28
+ definitionTimeout = undefined;
29
+ }
30
+ if (!definitions) {
31
+ definitions = local_cluster_config_1.default.getDefinitions();
32
+ }
33
+ else {
34
+ definitionTimeout = setTimeout(() => {
35
+ definitionTimeout = undefined;
36
+ definitions = undefined;
37
+ }, 500);
38
+ }
39
+ return definitions;
40
+ }
23
41
  class RepositoryWatcher extends node_events_1.EventEmitter {
24
42
  watcher;
25
43
  disabled = false;
@@ -186,7 +204,7 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
186
204
  }
187
205
  async checkForChange(assetIdentity, sourceOfChange) {
188
206
  const ymlPath = node_path_1.default.join(this.getRepositoryPath(assetIdentity), 'kapeta.yml');
189
- const newDefinitions = local_cluster_config_1.default.getDefinitions();
207
+ const newDefinitions = getDefinitionsDebounced();
190
208
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
191
209
  let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
192
210
  const ymlExists = await this.exists(ymlPath);
@@ -265,11 +283,17 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
265
283
  }
266
284
  catch (e) { }
267
285
  if (symbolicLink) {
268
- const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
269
- if (await this.exists(realPath)) {
270
- //console.log('Watching symlink target %s => %s', path, realPath);
271
- this.watcher?.add(realPath);
272
- this.symbolicLinks[path] = realPath;
286
+ try {
287
+ const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
288
+ if (await this.exists(realPath)) {
289
+ //console.log('Watching symlink target %s => %s', path, realPath);
290
+ this.watcher?.add(realPath);
291
+ this.symbolicLinks[path] = realPath;
292
+ }
293
+ }
294
+ catch (e) {
295
+ // Remove the symlink - it's broken
296
+ await fs_extra_1.default.remove(path);
273
297
  }
274
298
  }
275
299
  }
@@ -24,10 +24,13 @@ const node_os_1 = __importDefault(require("node:os"));
24
24
  const CACHE_TTL = 60 * 60 * 1000; // 1 hour
25
25
  const UPGRADE_CHECK_INTERVAL = 10 * 60 * 1000; // 10 minutes
26
26
  const toKey = (ref) => `assetManager:asset:${ref}`;
27
+ function filterExists(asset) {
28
+ return fs_extra_1.default.existsSync(asset.path);
29
+ }
27
30
  function enrichAsset(asset) {
28
31
  return {
29
32
  ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
30
- editable: asset.version === 'local',
33
+ editable: asset.version === 'local', //Only local versions are editable
31
34
  exists: true,
32
35
  version: asset.version,
33
36
  kind: asset.definition.kind,
@@ -81,7 +84,7 @@ class AssetManager {
81
84
  assetKinds.push('core/plan');
82
85
  }
83
86
  const assets = await definitionsManager_1.definitionsManager.getDefinitions(assetKinds);
84
- return assets.map(enrichAsset);
87
+ return assets.filter(filterExists).map(enrichAsset);
85
88
  }
86
89
  async getPlans() {
87
90
  return this.getAssets(['core/plan']);
@@ -22,6 +22,7 @@ export interface DockerMounts {
22
22
  Type: string;
23
23
  ReadOnly: boolean;
24
24
  Consistency: string;
25
+ Labels?: StringMap;
25
26
  }
26
27
  export type DockerContainerStatus = 'created' | 'running' | 'paused' | 'restarting' | 'removing' | 'exited' | 'dead';
27
28
  export type DockerContainerHealth = 'starting' | 'healthy' | 'unhealthy' | 'none';
@@ -48,6 +49,7 @@ declare class ContainerManager {
48
49
  isAlive(): boolean;
49
50
  getMountPoint(systemId: string, ref: string, mountName: string): string;
50
51
  createMounts(systemId: string, kind: string, mountOpts: StringMap | null | undefined): Promise<StringMap>;
52
+ createVolumes(systemId: string, kind: string, mountOpts: StringMap | null | undefined): Promise<DockerMounts[]>;
51
53
  ping(): Promise<void>;
52
54
  docker(): Docker;
53
55
  getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
@@ -165,6 +165,27 @@ class ContainerManager {
165
165
  }
166
166
  return mounts;
167
167
  }
168
+ async createVolumes(systemId, kind, mountOpts) {
169
+ const Mounts = [];
170
+ if (mountOpts) {
171
+ const mountOptList = Object.entries(mountOpts);
172
+ for (const [mountName, containerPath] of mountOptList) {
173
+ const volumeName = `${systemId}_${kind}_${mountName}`.replace(/[^a-z0-9]/gi, '_');
174
+ Mounts.push({
175
+ Target: containerPath,
176
+ Source: volumeName,
177
+ Type: 'volume',
178
+ ReadOnly: false,
179
+ Consistency: 'consistent',
180
+ Labels: {
181
+ [exports.COMPOSE_LABEL_PROJECT]: systemId.replace(/[^a-z0-9]/gi, '_'),
182
+ [exports.COMPOSE_LABEL_SERVICE]: kind.replace(/[^a-z0-9]/gi, '_'),
183
+ },
184
+ });
185
+ }
186
+ }
187
+ return Mounts;
188
+ }
168
189
  async ping() {
169
190
  try {
170
191
  const pingResult = await this.docker().ping();
@@ -131,9 +131,9 @@ class DefinitionsManager {
131
131
  const definitions = await this.getDefinitions();
132
132
  return definitions.find((d) => {
133
133
  if (!uri.version) {
134
- return d.definition.metadata.name === uri.fullName;
134
+ return d.definition.metadata.name.toLowerCase() === uri.fullName.toLowerCase();
135
135
  }
136
- return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
136
+ return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).equals(uri);
137
137
  });
138
138
  }
139
139
  async getLatestDefinition(name) {
@@ -25,7 +25,7 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
25
25
  const definitionsManager_1 = require("./definitionsManager");
26
26
  const taskManager_1 = require("./taskManager");
27
27
  const CHECK_INTERVAL = 5000;
28
- const DEFAULT_HEALTH_PORT_TYPE = 'rest';
28
+ const DEFAULT_HEALTH_PORT_TYPE = 'http';
29
29
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
30
30
  class InstanceManager {
31
31
  _interval = undefined;
@@ -198,7 +198,7 @@ class InstanceManager {
198
198
  }
199
199
  getHealthUrl(info, address) {
200
200
  let healthUrl = null;
201
- let health = info.health;
201
+ let health = info.health ?? '/.kapeta/health';
202
202
  if (health) {
203
203
  if (health.startsWith('/')) {
204
204
  health = health.substring(1);
@@ -146,7 +146,6 @@ class OperatorManager {
146
146
  hostPort,
147
147
  };
148
148
  }
149
- const mounts = await containerManager_1.containerManager.createMounts(systemId, resourceType, operatorData.mounts);
150
149
  const nameParts = [systemId, resourceType.toLowerCase(), version];
151
150
  const containerName = `kapeta-resource-${(0, md5_1.default)(nameParts.join('_'))}`;
152
151
  const PortBindings = {};
@@ -170,7 +169,7 @@ class OperatorManager {
170
169
  ];
171
170
  Labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
172
171
  });
173
- const Mounts = containerManager_1.containerManager.toDockerMounts(mounts);
172
+ const Mounts = await containerManager_1.containerManager.createVolumes(systemId, resourceType, operatorData.mounts);
174
173
  lodash_1.default.forEach(operatorData.env, (value, name) => {
175
174
  Env.push(name + '=' + value);
176
175
  });
@@ -183,7 +183,7 @@ class RepositoryManager extends node_events_1.EventEmitter {
183
183
  if (await definitionsManager_1.definitionsManager.exists(ref)) {
184
184
  return;
185
185
  }
186
- throw new Error(`Failed to install asset: ${ref}`);
186
+ throw new Error(`Failed to find asset after installation: ${ref}. Please try again`);
187
187
  };
188
188
  };
189
189
  const tasks = [];
@@ -20,6 +20,24 @@ const cacheManager_1 = require("./cacheManager");
20
20
  const node_events_1 = require("node:events");
21
21
  const assetManager_1 = require("./assetManager");
22
22
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
23
+ let definitions;
24
+ let definitionTimeout;
25
+ function getDefinitionsDebounced() {
26
+ if (definitionTimeout) {
27
+ clearTimeout(definitionTimeout);
28
+ definitionTimeout = undefined;
29
+ }
30
+ if (!definitions) {
31
+ definitions = local_cluster_config_1.default.getDefinitions();
32
+ }
33
+ else {
34
+ definitionTimeout = setTimeout(() => {
35
+ definitionTimeout = undefined;
36
+ definitions = undefined;
37
+ }, 500);
38
+ }
39
+ return definitions;
40
+ }
23
41
  class RepositoryWatcher extends node_events_1.EventEmitter {
24
42
  watcher;
25
43
  disabled = false;
@@ -186,7 +204,7 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
186
204
  }
187
205
  async checkForChange(assetIdentity, sourceOfChange) {
188
206
  const ymlPath = node_path_1.default.join(this.getRepositoryPath(assetIdentity), 'kapeta.yml');
189
- const newDefinitions = local_cluster_config_1.default.getDefinitions();
207
+ const newDefinitions = getDefinitionsDebounced();
190
208
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
191
209
  let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
192
210
  const ymlExists = await this.exists(ymlPath);
@@ -265,11 +283,17 @@ class RepositoryWatcher extends node_events_1.EventEmitter {
265
283
  }
266
284
  catch (e) { }
267
285
  if (symbolicLink) {
268
- const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
269
- if (await this.exists(realPath)) {
270
- //console.log('Watching symlink target %s => %s', path, realPath);
271
- this.watcher?.add(realPath);
272
- this.symbolicLinks[path] = realPath;
286
+ try {
287
+ const realPath = node_path_1.default.join(await fs_extra_1.default.realpath(path), 'kapeta.yml');
288
+ if (await this.exists(realPath)) {
289
+ //console.log('Watching symlink target %s => %s', path, realPath);
290
+ this.watcher?.add(realPath);
291
+ this.symbolicLinks[path] = realPath;
292
+ }
293
+ }
294
+ catch (e) {
295
+ // Remove the symlink - it's broken
296
+ await fs_extra_1.default.remove(path);
273
297
  }
274
298
  }
275
299
  }
@@ -24,10 +24,13 @@ const node_os_1 = __importDefault(require("node:os"));
24
24
  const CACHE_TTL = 60 * 60 * 1000; // 1 hour
25
25
  const UPGRADE_CHECK_INTERVAL = 10 * 60 * 1000; // 10 minutes
26
26
  const toKey = (ref) => `assetManager:asset:${ref}`;
27
+ function filterExists(asset) {
28
+ return fs_extra_1.default.existsSync(asset.path);
29
+ }
27
30
  function enrichAsset(asset) {
28
31
  return {
29
32
  ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
30
- editable: asset.version === 'local',
33
+ editable: asset.version === 'local', //Only local versions are editable
31
34
  exists: true,
32
35
  version: asset.version,
33
36
  kind: asset.definition.kind,
@@ -81,7 +84,7 @@ class AssetManager {
81
84
  assetKinds.push('core/plan');
82
85
  }
83
86
  const assets = await definitionsManager_1.definitionsManager.getDefinitions(assetKinds);
84
- return assets.map(enrichAsset);
87
+ return assets.filter(filterExists).map(enrichAsset);
85
88
  }
86
89
  async getPlans() {
87
90
  return this.getAssets(['core/plan']);
@@ -22,6 +22,7 @@ export interface DockerMounts {
22
22
  Type: string;
23
23
  ReadOnly: boolean;
24
24
  Consistency: string;
25
+ Labels?: StringMap;
25
26
  }
26
27
  export type DockerContainerStatus = 'created' | 'running' | 'paused' | 'restarting' | 'removing' | 'exited' | 'dead';
27
28
  export type DockerContainerHealth = 'starting' | 'healthy' | 'unhealthy' | 'none';
@@ -48,6 +49,7 @@ declare class ContainerManager {
48
49
  isAlive(): boolean;
49
50
  getMountPoint(systemId: string, ref: string, mountName: string): string;
50
51
  createMounts(systemId: string, kind: string, mountOpts: StringMap | null | undefined): Promise<StringMap>;
52
+ createVolumes(systemId: string, kind: string, mountOpts: StringMap | null | undefined): Promise<DockerMounts[]>;
51
53
  ping(): Promise<void>;
52
54
  docker(): Docker;
53
55
  getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
@@ -165,6 +165,27 @@ class ContainerManager {
165
165
  }
166
166
  return mounts;
167
167
  }
168
+ async createVolumes(systemId, kind, mountOpts) {
169
+ const Mounts = [];
170
+ if (mountOpts) {
171
+ const mountOptList = Object.entries(mountOpts);
172
+ for (const [mountName, containerPath] of mountOptList) {
173
+ const volumeName = `${systemId}_${kind}_${mountName}`.replace(/[^a-z0-9]/gi, '_');
174
+ Mounts.push({
175
+ Target: containerPath,
176
+ Source: volumeName,
177
+ Type: 'volume',
178
+ ReadOnly: false,
179
+ Consistency: 'consistent',
180
+ Labels: {
181
+ [exports.COMPOSE_LABEL_PROJECT]: systemId.replace(/[^a-z0-9]/gi, '_'),
182
+ [exports.COMPOSE_LABEL_SERVICE]: kind.replace(/[^a-z0-9]/gi, '_'),
183
+ },
184
+ });
185
+ }
186
+ }
187
+ return Mounts;
188
+ }
168
189
  async ping() {
169
190
  try {
170
191
  const pingResult = await this.docker().ping();
@@ -131,9 +131,9 @@ class DefinitionsManager {
131
131
  const definitions = await this.getDefinitions();
132
132
  return definitions.find((d) => {
133
133
  if (!uri.version) {
134
- return d.definition.metadata.name === uri.fullName;
134
+ return d.definition.metadata.name.toLowerCase() === uri.fullName.toLowerCase();
135
135
  }
136
- return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
136
+ return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).equals(uri);
137
137
  });
138
138
  }
139
139
  async getLatestDefinition(name) {
@@ -25,7 +25,7 @@ const nodejs_utils_1 = require("@kapeta/nodejs-utils");
25
25
  const definitionsManager_1 = require("./definitionsManager");
26
26
  const taskManager_1 = require("./taskManager");
27
27
  const CHECK_INTERVAL = 5000;
28
- const DEFAULT_HEALTH_PORT_TYPE = 'rest';
28
+ const DEFAULT_HEALTH_PORT_TYPE = 'http';
29
29
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
30
30
  class InstanceManager {
31
31
  _interval = undefined;
@@ -198,7 +198,7 @@ class InstanceManager {
198
198
  }
199
199
  getHealthUrl(info, address) {
200
200
  let healthUrl = null;
201
- let health = info.health;
201
+ let health = info.health ?? '/.kapeta/health';
202
202
  if (health) {
203
203
  if (health.startsWith('/')) {
204
204
  health = health.substring(1);
@@ -146,7 +146,6 @@ class OperatorManager {
146
146
  hostPort,
147
147
  };
148
148
  }
149
- const mounts = await containerManager_1.containerManager.createMounts(systemId, resourceType, operatorData.mounts);
150
149
  const nameParts = [systemId, resourceType.toLowerCase(), version];
151
150
  const containerName = `kapeta-resource-${(0, md5_1.default)(nameParts.join('_'))}`;
152
151
  const PortBindings = {};
@@ -170,7 +169,7 @@ class OperatorManager {
170
169
  ];
171
170
  Labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
172
171
  });
173
- const Mounts = containerManager_1.containerManager.toDockerMounts(mounts);
172
+ const Mounts = await containerManager_1.containerManager.createVolumes(systemId, resourceType, operatorData.mounts);
174
173
  lodash_1.default.forEach(operatorData.env, (value, name) => {
175
174
  Env.push(name + '=' + value);
176
175
  });
@@ -183,7 +183,7 @@ class RepositoryManager extends node_events_1.EventEmitter {
183
183
  if (await definitionsManager_1.definitionsManager.exists(ref)) {
184
184
  return;
185
185
  }
186
- throw new Error(`Failed to install asset: ${ref}`);
186
+ throw new Error(`Failed to find asset after installation: ${ref}. Please try again`);
187
187
  };
188
188
  };
189
189
  const tasks = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.32.0",
3
+ "version": "0.32.2",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -15,6 +15,7 @@ import { SourceOfChange, WatchEventName } from './types';
15
15
  import { cacheManager } from './cacheManager';
16
16
  import { EventEmitter } from 'node:events';
17
17
  import { assetManager } from './assetManager';
18
+ import { definitionsManager } from './definitionsManager';
18
19
 
19
20
  interface AssetIdentity {
20
21
  handle: string;
@@ -22,6 +23,27 @@ interface AssetIdentity {
22
23
  version: string;
23
24
  }
24
25
  const KAPETA_YML_RX = /^kapeta.ya?ml$/;
26
+
27
+ let definitions: DefinitionInfo[] | undefined;
28
+ let definitionTimeout: NodeJS.Timeout | undefined;
29
+
30
+ function getDefinitionsDebounced() {
31
+ if (definitionTimeout) {
32
+ clearTimeout(definitionTimeout);
33
+ definitionTimeout = undefined;
34
+ }
35
+ if (!definitions) {
36
+ definitions = ClusterConfiguration.getDefinitions();
37
+ } else {
38
+ definitionTimeout = setTimeout(() => {
39
+ definitionTimeout = undefined;
40
+ definitions = undefined;
41
+ }, 500);
42
+ }
43
+
44
+ return definitions;
45
+ }
46
+
25
47
  export class RepositoryWatcher extends EventEmitter {
26
48
  private watcher?: FSWatcher;
27
49
  private disabled: boolean = false;
@@ -208,7 +230,8 @@ export class RepositoryWatcher extends EventEmitter {
208
230
 
209
231
  private async checkForChange(assetIdentity: AssetIdentity, sourceOfChange: SourceOfChange) {
210
232
  const ymlPath = Path.join(this.getRepositoryPath(assetIdentity), 'kapeta.yml');
211
- const newDefinitions = ClusterConfiguration.getDefinitions();
233
+ const newDefinitions = getDefinitionsDebounced();
234
+
212
235
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
213
236
  let currentDefinition = this.allDefinitions.find((d) => d.ymlPath === ymlPath);
214
237
  const ymlExists = await this.exists(ymlPath);
@@ -290,11 +313,16 @@ export class RepositoryWatcher extends EventEmitter {
290
313
  } catch (e) {}
291
314
 
292
315
  if (symbolicLink) {
293
- const realPath = Path.join(await FS.realpath(path), 'kapeta.yml');
294
- if (await this.exists(realPath)) {
295
- //console.log('Watching symlink target %s => %s', path, realPath);
296
- this.watcher?.add(realPath);
297
- this.symbolicLinks[path] = realPath;
316
+ try {
317
+ const realPath = Path.join(await FS.realpath(path), 'kapeta.yml');
318
+ if (await this.exists(realPath)) {
319
+ //console.log('Watching symlink target %s => %s', path, realPath);
320
+ this.watcher?.add(realPath);
321
+ this.symbolicLinks[path] = realPath;
322
+ }
323
+ } catch (e) {
324
+ // Remove the symlink - it's broken
325
+ await FS.remove(path);
298
326
  }
299
327
  }
300
328
  } catch (e) {
@@ -36,6 +36,10 @@ export interface EnrichedAsset {
36
36
  ymlPath: string;
37
37
  }
38
38
 
39
+ function filterExists(asset: DefinitionInfo): boolean {
40
+ return FS.existsSync(asset.path);
41
+ }
42
+
39
43
  function enrichAsset(asset: DefinitionInfo): EnrichedAsset {
40
44
  return {
41
45
  ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
@@ -101,7 +105,7 @@ class AssetManager {
101
105
 
102
106
  const assets = await definitionsManager.getDefinitions(assetKinds);
103
107
 
104
- return assets.map(enrichAsset);
108
+ return assets.filter(filterExists).map(enrichAsset);
105
109
  }
106
110
 
107
111
  async getPlans(): Promise<EnrichedAsset[]> {
@@ -37,6 +37,7 @@ export interface DockerMounts {
37
37
  Type: string;
38
38
  ReadOnly: boolean;
39
39
  Consistency: string;
40
+ Labels?: StringMap;
40
41
  }
41
42
 
42
43
  interface JSONProgress {
@@ -249,6 +250,35 @@ class ContainerManager {
249
250
  return mounts;
250
251
  }
251
252
 
253
+ async createVolumes(
254
+ systemId: string,
255
+ kind: string,
256
+ mountOpts: StringMap | null | undefined
257
+ ): Promise<DockerMounts[]> {
258
+ const Mounts: DockerMounts[] = [];
259
+
260
+ if (mountOpts) {
261
+ const mountOptList = Object.entries(mountOpts);
262
+ for (const [mountName, containerPath] of mountOptList) {
263
+ const volumeName = `${systemId}_${kind}_${mountName}`.replace(/[^a-z0-9]/gi, '_');
264
+
265
+ Mounts.push({
266
+ Target: containerPath,
267
+ Source: volumeName,
268
+ Type: 'volume',
269
+ ReadOnly: false,
270
+ Consistency: 'consistent',
271
+ Labels: {
272
+ [COMPOSE_LABEL_PROJECT]: systemId.replace(/[^a-z0-9]/gi, '_'),
273
+ [COMPOSE_LABEL_SERVICE]: kind.replace(/[^a-z0-9]/gi, '_'),
274
+ },
275
+ });
276
+ }
277
+ }
278
+
279
+ return Mounts;
280
+ }
281
+
252
282
  async ping() {
253
283
  try {
254
284
  const pingResult = await this.docker().ping();
@@ -164,9 +164,9 @@ class DefinitionsManager {
164
164
  const definitions = await this.getDefinitions();
165
165
  return definitions.find((d) => {
166
166
  if (!uri.version) {
167
- return d.definition.metadata.name === uri.fullName;
167
+ return d.definition.metadata.name.toLowerCase() === uri.fullName.toLowerCase();
168
168
  }
169
- return parseKapetaUri(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
169
+ return parseKapetaUri(`${d.definition.metadata.name}:${d.version}`).equals(uri);
170
170
  });
171
171
  }
172
172
 
@@ -27,7 +27,7 @@ import { definitionsManager } from './definitionsManager';
27
27
  import { Task, taskManager } from './taskManager';
28
28
 
29
29
  const CHECK_INTERVAL = 5000;
30
- const DEFAULT_HEALTH_PORT_TYPE = 'rest';
30
+ const DEFAULT_HEALTH_PORT_TYPE = 'http';
31
31
 
32
32
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
33
33
 
@@ -264,7 +264,7 @@ export class InstanceManager {
264
264
 
265
265
  private getHealthUrl(info: Omit<InstanceInfo, 'systemId' | 'instanceId'>, address: string) {
266
266
  let healthUrl = null;
267
- let health = info.health;
267
+ let health = info.health ?? '/.kapeta/health';
268
268
  if (health) {
269
269
  if (health.startsWith('/')) {
270
270
  health = health.substring(1);
@@ -201,8 +201,6 @@ class OperatorManager {
201
201
  };
202
202
  }
203
203
 
204
- const mounts = await containerManager.createMounts(systemId, resourceType, operatorData.mounts);
205
-
206
204
  const nameParts = [systemId, resourceType.toLowerCase(), version];
207
205
 
208
206
  const containerName = `kapeta-resource-${md5(nameParts.join('_'))}`;
@@ -236,7 +234,7 @@ class OperatorManager {
236
234
  Labels[CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
237
235
  });
238
236
 
239
- const Mounts = containerManager.toDockerMounts(mounts);
237
+ const Mounts = await containerManager.createVolumes(systemId, resourceType, operatorData.mounts);
240
238
 
241
239
  _.forEach(operatorData.env, (value, name) => {
242
240
  Env.push(name + '=' + value);
@@ -209,7 +209,7 @@ class RepositoryManager extends EventEmitter {
209
209
  if (await definitionsManager.exists(ref)) {
210
210
  return;
211
211
  }
212
- throw new Error(`Failed to install asset: ${ref}`);
212
+ throw new Error(`Failed to find asset after installation: ${ref}. Please try again`);
213
213
  };
214
214
  };
215
215