@kapeta/local-cluster-service 0.12.0 → 0.12.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [0.12.1](https://github.com/kapetacom/local-cluster-service/compare/v0.12.0...v0.12.1) (2023-08-02)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Adjustments to make starting plans locally smoother ([fc353ad](https://github.com/kapetacom/local-cluster-service/commit/fc353adde350b7e9d4c7eb9347c4cfa0c3a6aa58))
7
+
1
8
  # [0.12.0](https://github.com/kapetacom/local-cluster-service/compare/v0.11.1...v0.12.0) (2023-07-31)
2
9
 
3
10
 
@@ -59,7 +59,7 @@ declare class ContainerManager {
59
59
  ping(): Promise<void>;
60
60
  docker(): Docker;
61
61
  getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
62
- pull(image: string, cacheForMS?: number): Promise<boolean>;
62
+ pull(image: string): Promise<boolean>;
63
63
  toDockerMounts(mounts: StringMap): DockerMounts[];
64
64
  toDockerHealth(health: Health): {
65
65
  Test: string[];
@@ -22,8 +22,6 @@ exports.CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
22
22
  const NANO_SECOND = 1000000;
23
23
  const HEALTH_CHECK_INTERVAL = 3000;
24
24
  const HEALTH_CHECK_MAX = 20;
25
- const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
26
- const IMAGE_PULL_CACHE = {};
27
25
  exports.HEALTH_CHECK_TIMEOUT = HEALTH_CHECK_INTERVAL * HEALTH_CHECK_MAX * 2;
28
26
  const promisifyStream = (stream, handler) => new Promise((resolve, reject) => {
29
27
  stream.on('data', handler);
@@ -151,17 +149,11 @@ class ContainerManager {
151
149
  }
152
150
  return undefined;
153
151
  }
154
- async pull(image, cacheForMS = IMAGE_PULL_CACHE_TTL) {
152
+ async pull(image) {
155
153
  let [imageName, tag] = image.split(/:/);
156
154
  if (!tag) {
157
155
  tag = 'latest';
158
156
  }
159
- if (IMAGE_PULL_CACHE[image]) {
160
- const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
161
- if (timeSince < cacheForMS) {
162
- return false;
163
- }
164
- }
165
157
  const imageTagList = (await this.docker().image.list())
166
158
  .map((image) => image.data)
167
159
  .filter((imageData) => !!imageData.RepoTags)
@@ -171,7 +163,7 @@ class ContainerManager {
171
163
  return false;
172
164
  }
173
165
  const timeStarted = Date.now();
174
- socketManager_1.socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 0 });
166
+ socketManager_1.socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: -1 });
175
167
  const api = new nodejs_api_client_1.KapetaAPI();
176
168
  const accessToken = await api.getAccessToken();
177
169
  const auth = image.startsWith('docker.kapeta.com/')
@@ -283,7 +275,6 @@ class ContainerManager {
283
275
  lastEmitted = Date.now();
284
276
  //console.log('Pulling image %s: %s % [done: %s, total: %s]', image, Math.round(percent), totals.done, totals.total);
285
277
  });
286
- IMAGE_PULL_CACHE[image] = Date.now();
287
278
  socketManager_1.socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 100, timeTaken: Date.now() - timeStarted });
288
279
  return true;
289
280
  }
@@ -319,9 +310,7 @@ class ContainerManager {
319
310
  dockerOpts.Labels.HASH = hash;
320
311
  }
321
312
  async ensureContainer(opts) {
322
- const container = await this.createOrUpdateContainer(opts);
323
- await this.waitForReady(container);
324
- return container;
313
+ return await this.createOrUpdateContainer(opts);
325
314
  }
326
315
  async createOrUpdateContainer(opts) {
327
316
  let imagePulled = await this.pull(opts.Image);
@@ -55,7 +55,13 @@ class InstanceManager {
55
55
  return [];
56
56
  }
57
57
  systemId = (0, utils_1.normalizeKapetaUri)(systemId);
58
- return this._instances.filter((instance) => instance.systemId === systemId);
58
+ const planInfo = definitionsManager_1.definitionsManager.getDefinition(systemId);
59
+ if (!planInfo) {
60
+ return [];
61
+ }
62
+ const plan = planInfo.definition;
63
+ const instanceIds = plan.spec.blocks.map((block) => block.id);
64
+ return this._instances.filter((instance) => instance.systemId === systemId && instanceIds.includes(instance.instanceId));
59
65
  }
60
66
  getInstance(systemId, instanceId) {
61
67
  systemId = (0, utils_1.normalizeKapetaUri)(systemId);
@@ -393,7 +399,7 @@ class InstanceManager {
393
399
  ];
394
400
  const out = await this.saveInternalInstance({
395
401
  ...instance,
396
- type: types_1.InstanceType.LOCAL,
402
+ type: types_1.InstanceType.UNKNOWN,
397
403
  pid: null,
398
404
  health: null,
399
405
  portType: DEFAULT_HEALTH_PORT_TYPE,
@@ -122,8 +122,10 @@ router.put('/', async (req, res) => {
122
122
  const oldInstance = instanceManager_1.instanceManager.getInstance(req.kapeta.systemId, req.kapeta.instanceId);
123
123
  if (oldInstance) {
124
124
  instance.pid = oldInstance.pid;
125
+ instance.desiredStatus = oldInstance.desiredStatus;
125
126
  }
126
127
  instance.type = types_1.InstanceType.DOCKER;
128
+ instance.owner = types_1.InstanceOwner.INTERNAL;
127
129
  }
128
130
  else {
129
131
  // Coming from user starting the instance outside of kapeta
@@ -181,6 +181,7 @@ class OperatorManager {
181
181
  Mounts,
182
182
  },
183
183
  });
184
+ await containerManager_1.containerManager.waitForReady(container);
184
185
  return new containerManager_1.ContainerInfo(container);
185
186
  });
186
187
  }
@@ -324,7 +324,6 @@ class BlockInstanceRunner {
324
324
  }
325
325
  async ensureContainer(opts) {
326
326
  const container = await containerManager_1.containerManager.ensureContainer(opts);
327
- await containerManager_1.containerManager.waitForReady(container);
328
327
  return this._handleContainer(container);
329
328
  }
330
329
  async _handleContainer(container) {
@@ -59,7 +59,7 @@ declare class ContainerManager {
59
59
  ping(): Promise<void>;
60
60
  docker(): Docker;
61
61
  getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
62
- pull(image: string, cacheForMS?: number): Promise<boolean>;
62
+ pull(image: string): Promise<boolean>;
63
63
  toDockerMounts(mounts: StringMap): DockerMounts[];
64
64
  toDockerHealth(health: Health): {
65
65
  Test: string[];
@@ -16,8 +16,6 @@ export const CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
16
16
  const NANO_SECOND = 1000000;
17
17
  const HEALTH_CHECK_INTERVAL = 3000;
18
18
  const HEALTH_CHECK_MAX = 20;
19
- const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
20
- const IMAGE_PULL_CACHE = {};
21
19
  export const HEALTH_CHECK_TIMEOUT = HEALTH_CHECK_INTERVAL * HEALTH_CHECK_MAX * 2;
22
20
  const promisifyStream = (stream, handler) => new Promise((resolve, reject) => {
23
21
  stream.on('data', handler);
@@ -145,17 +143,11 @@ class ContainerManager {
145
143
  }
146
144
  return undefined;
147
145
  }
148
- async pull(image, cacheForMS = IMAGE_PULL_CACHE_TTL) {
146
+ async pull(image) {
149
147
  let [imageName, tag] = image.split(/:/);
150
148
  if (!tag) {
151
149
  tag = 'latest';
152
150
  }
153
- if (IMAGE_PULL_CACHE[image]) {
154
- const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
155
- if (timeSince < cacheForMS) {
156
- return false;
157
- }
158
- }
159
151
  const imageTagList = (await this.docker().image.list())
160
152
  .map((image) => image.data)
161
153
  .filter((imageData) => !!imageData.RepoTags)
@@ -165,7 +157,7 @@ class ContainerManager {
165
157
  return false;
166
158
  }
167
159
  const timeStarted = Date.now();
168
- socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 0 });
160
+ socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: -1 });
169
161
  const api = new KapetaAPI();
170
162
  const accessToken = await api.getAccessToken();
171
163
  const auth = image.startsWith('docker.kapeta.com/')
@@ -277,7 +269,6 @@ class ContainerManager {
277
269
  lastEmitted = Date.now();
278
270
  //console.log('Pulling image %s: %s % [done: %s, total: %s]', image, Math.round(percent), totals.done, totals.total);
279
271
  });
280
- IMAGE_PULL_CACHE[image] = Date.now();
281
272
  socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 100, timeTaken: Date.now() - timeStarted });
282
273
  return true;
283
274
  }
@@ -313,9 +304,7 @@ class ContainerManager {
313
304
  dockerOpts.Labels.HASH = hash;
314
305
  }
315
306
  async ensureContainer(opts) {
316
- const container = await this.createOrUpdateContainer(opts);
317
- await this.waitForReady(container);
318
- return container;
307
+ return await this.createOrUpdateContainer(opts);
319
308
  }
320
309
  async createOrUpdateContainer(opts) {
321
310
  let imagePulled = await this.pull(opts.Image);
@@ -49,7 +49,13 @@ export class InstanceManager {
49
49
  return [];
50
50
  }
51
51
  systemId = normalizeKapetaUri(systemId);
52
- return this._instances.filter((instance) => instance.systemId === systemId);
52
+ const planInfo = definitionsManager.getDefinition(systemId);
53
+ if (!planInfo) {
54
+ return [];
55
+ }
56
+ const plan = planInfo.definition;
57
+ const instanceIds = plan.spec.blocks.map((block) => block.id);
58
+ return this._instances.filter((instance) => instance.systemId === systemId && instanceIds.includes(instance.instanceId));
53
59
  }
54
60
  getInstance(systemId, instanceId) {
55
61
  systemId = normalizeKapetaUri(systemId);
@@ -387,7 +393,7 @@ export class InstanceManager {
387
393
  ];
388
394
  const out = await this.saveInternalInstance({
389
395
  ...instance,
390
- type: InstanceType.LOCAL,
396
+ type: InstanceType.UNKNOWN,
391
397
  pid: null,
392
398
  health: null,
393
399
  portType: DEFAULT_HEALTH_PORT_TYPE,
@@ -117,8 +117,10 @@ router.put('/', async (req, res) => {
117
117
  const oldInstance = instanceManager.getInstance(req.kapeta.systemId, req.kapeta.instanceId);
118
118
  if (oldInstance) {
119
119
  instance.pid = oldInstance.pid;
120
+ instance.desiredStatus = oldInstance.desiredStatus;
120
121
  }
121
122
  instance.type = InstanceType.DOCKER;
123
+ instance.owner = InstanceOwner.INTERNAL;
122
124
  }
123
125
  else {
124
126
  // Coming from user starting the instance outside of kapeta
@@ -175,6 +175,7 @@ class OperatorManager {
175
175
  Mounts,
176
176
  },
177
177
  });
178
+ await containerManager.waitForReady(container);
178
179
  return new ContainerInfo(container);
179
180
  });
180
181
  }
@@ -318,7 +318,6 @@ export class BlockInstanceRunner {
318
318
  }
319
319
  async ensureContainer(opts) {
320
320
  const container = await containerManager.ensureContainer(opts);
321
- await containerManager.waitForReady(container);
322
321
  return this._handleContainer(container);
323
322
  }
324
323
  async _handleContainer(container) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -66,8 +66,7 @@ export const CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
66
66
  const NANO_SECOND = 1000000;
67
67
  const HEALTH_CHECK_INTERVAL = 3000;
68
68
  const HEALTH_CHECK_MAX = 20;
69
- const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
70
- const IMAGE_PULL_CACHE: { [key: string]: number } = {};
69
+
71
70
 
72
71
  export const HEALTH_CHECK_TIMEOUT = HEALTH_CHECK_INTERVAL * HEALTH_CHECK_MAX * 2;
73
72
 
@@ -223,19 +222,12 @@ class ContainerManager {
223
222
  return undefined;
224
223
  }
225
224
 
226
- async pull(image: string, cacheForMS: number = IMAGE_PULL_CACHE_TTL) {
225
+ async pull(image: string) {
227
226
  let [imageName, tag] = image.split(/:/);
228
227
  if (!tag) {
229
228
  tag = 'latest';
230
229
  }
231
230
 
232
- if (IMAGE_PULL_CACHE[image]) {
233
- const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
234
- if (timeSince < cacheForMS) {
235
- return false;
236
- }
237
- }
238
-
239
231
  const imageTagList = (await this.docker().image.list())
240
232
  .map((image) => image.data as any)
241
233
  .filter((imageData) => !!imageData.RepoTags)
@@ -247,7 +239,7 @@ class ContainerManager {
247
239
  }
248
240
 
249
241
  const timeStarted = Date.now();
250
- socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 0 });
242
+ socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: -1 });
251
243
 
252
244
  const api = new KapetaAPI();
253
245
  const accessToken = await api.getAccessToken();
@@ -390,8 +382,6 @@ class ContainerManager {
390
382
  //console.log('Pulling image %s: %s % [done: %s, total: %s]', image, Math.round(percent), totals.done, totals.total);
391
383
  });
392
384
 
393
- IMAGE_PULL_CACHE[image] = Date.now();
394
-
395
385
  socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 100, timeTaken: Date.now() - timeStarted });
396
386
 
397
387
  return true;
@@ -435,11 +425,7 @@ class ContainerManager {
435
425
  }
436
426
 
437
427
  public async ensureContainer(opts: any) {
438
- const container = await this.createOrUpdateContainer(opts);
439
-
440
- await this.waitForReady(container);
441
-
442
- return container;
428
+ return await this.createOrUpdateContainer(opts);
443
429
  }
444
430
 
445
431
  private async createOrUpdateContainer(opts: any) {
@@ -9,7 +9,7 @@ import { assetManager } from './assetManager';
9
9
  import { containerManager, HEALTH_CHECK_TIMEOUT } from './containerManager';
10
10
  import { configManager } from './configManager';
11
11
  import { DesiredInstanceStatus, InstanceInfo, InstanceOwner, InstanceStatus, InstanceType, LogEntry } from './types';
12
- import { BlockDefinitionSpec, BlockInstance } from '@kapeta/schemas';
12
+ import {BlockDefinitionSpec, BlockInstance, Plan} from '@kapeta/schemas';
13
13
  import { getBlockInstanceContainerName, normalizeKapetaUri } from './utils/utils';
14
14
  import { KIND_OPERATOR, operatorManager } from './operatorManager';
15
15
  import { parseKapetaUri } from '@kapeta/nodejs-utils';
@@ -64,7 +64,17 @@ export class InstanceManager {
64
64
 
65
65
  systemId = normalizeKapetaUri(systemId);
66
66
 
67
- return this._instances.filter((instance) => instance.systemId === systemId);
67
+ const planInfo = definitionsManager.getDefinition(systemId);
68
+
69
+ if (!planInfo) {
70
+ return [];
71
+ }
72
+
73
+ const plan = planInfo.definition as Plan;
74
+
75
+ const instanceIds = plan.spec.blocks.map((block) => block.id);
76
+
77
+ return this._instances.filter((instance) => instance.systemId === systemId && instanceIds.includes(instance.instanceId));
68
78
  }
69
79
 
70
80
  public getInstance(systemId: string, instanceId: string) {
@@ -482,7 +492,7 @@ export class InstanceManager {
482
492
 
483
493
  const out = await this.saveInternalInstance({
484
494
  ...instance,
485
- type: InstanceType.LOCAL,
495
+ type: InstanceType.UNKNOWN,
486
496
  pid: null,
487
497
  health: null,
488
498
  portType: DEFAULT_HEALTH_PORT_TYPE,
@@ -146,8 +146,10 @@ router.put('/', async (req: KapetaBodyRequest, res: Response) => {
146
146
  const oldInstance = instanceManager.getInstance(req.kapeta!.systemId, req.kapeta!.instanceId);
147
147
  if (oldInstance) {
148
148
  instance.pid = oldInstance.pid;
149
+ instance.desiredStatus = oldInstance.desiredStatus;
149
150
  }
150
151
  instance.type = InstanceType.DOCKER;
152
+ instance.owner = InstanceOwner.INTERNAL;
151
153
  } else {
152
154
  // Coming from user starting the instance outside of kapeta
153
155
  instance.type = InstanceType.LOCAL;
@@ -246,6 +246,8 @@ class OperatorManager {
246
246
  },
247
247
  });
248
248
 
249
+ await containerManager.waitForReady(container);
250
+
249
251
  return new ContainerInfo(container);
250
252
  });
251
253
  }
@@ -415,8 +415,6 @@ export class BlockInstanceRunner {
415
415
  private async ensureContainer(opts: any) {
416
416
  const container = await containerManager.ensureContainer(opts);
417
417
 
418
- await containerManager.waitForReady(container);
419
-
420
418
  return this._handleContainer(container);
421
419
  }
422
420