@kapeta/local-cluster-service 0.19.6 → 0.19.7
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 +7 -0
- package/dist/cjs/src/containerManager.d.ts +39 -32
- package/dist/cjs/src/containerManager.js +138 -108
- package/dist/cjs/src/instanceManager.js +28 -18
- package/dist/cjs/src/operatorManager.js +3 -0
- package/dist/cjs/src/taskManager.js +4 -1
- package/dist/cjs/src/utils/BlockInstanceRunner.js +9 -0
- package/dist/esm/src/containerManager.d.ts +39 -32
- package/dist/esm/src/containerManager.js +138 -108
- package/dist/esm/src/instanceManager.js +28 -18
- package/dist/esm/src/operatorManager.js +3 -0
- package/dist/esm/src/taskManager.js +4 -1
- package/dist/esm/src/utils/BlockInstanceRunner.js +9 -0
- package/package.json +5 -2
- package/src/containerManager.ts +188 -140
- package/src/instanceManager.ts +44 -20
- package/src/operatorManager.ts +11 -1
- package/src/taskManager.ts +4 -1
- package/src/utils/BlockInstanceRunner.ts +19 -3
package/src/instanceManager.ts
CHANGED
@@ -6,7 +6,12 @@ import { storageService } from './storageService';
|
|
6
6
|
import { EVENT_INSTANCE_CREATED, EVENT_INSTANCE_EXITED, EVENT_STATUS_CHANGED, socketManager } from './socketManager';
|
7
7
|
import { serviceManager } from './serviceManager';
|
8
8
|
import { assetManager } from './assetManager';
|
9
|
-
import {
|
9
|
+
import {
|
10
|
+
containerManager,
|
11
|
+
DockerContainerHealth,
|
12
|
+
DockerContainerStatus,
|
13
|
+
HEALTH_CHECK_TIMEOUT,
|
14
|
+
} from './containerManager';
|
10
15
|
import { configManager } from './configManager';
|
11
16
|
import { DesiredInstanceStatus, InstanceInfo, InstanceOwner, InstanceStatus, InstanceType, LogEntry } from './types';
|
12
17
|
import { BlockDefinitionSpec, BlockInstance, Plan } from '@kapeta/schemas';
|
@@ -336,6 +341,10 @@ export class InstanceManager {
|
|
336
341
|
return;
|
337
342
|
}
|
338
343
|
|
344
|
+
if (instance.status === InstanceStatus.STOPPING) {
|
345
|
+
return;
|
346
|
+
}
|
347
|
+
|
339
348
|
if (changeDesired && instance.desiredStatus !== DesiredInstanceStatus.EXTERNAL) {
|
340
349
|
instance.desiredStatus = DesiredInstanceStatus.STOP;
|
341
350
|
}
|
@@ -496,7 +505,7 @@ export class InstanceManager {
|
|
496
505
|
try {
|
497
506
|
const processInfo = await runner.start(blockRef, instanceId, instanceConfig);
|
498
507
|
|
499
|
-
instance.status = InstanceStatus.
|
508
|
+
instance.status = InstanceStatus.STARTING;
|
500
509
|
|
501
510
|
return this.saveInternalInstance({
|
502
511
|
...instance,
|
@@ -504,10 +513,10 @@ export class InstanceManager {
|
|
504
513
|
pid: processInfo.pid ?? -1,
|
505
514
|
health: null,
|
506
515
|
portType: processInfo.portType,
|
507
|
-
status: InstanceStatus.
|
516
|
+
status: InstanceStatus.STARTING,
|
508
517
|
});
|
509
518
|
} catch (e: any) {
|
510
|
-
console.warn('Failed to start instance: ', systemId, instanceId, blockRef, e
|
519
|
+
console.warn('Failed to start instance: ', systemId, instanceId, blockRef, e);
|
511
520
|
const logs: LogEntry[] = [
|
512
521
|
{
|
513
522
|
source: 'stdout',
|
@@ -686,7 +695,12 @@ export class InstanceManager {
|
|
686
695
|
try {
|
687
696
|
await this.start(instance.systemId, instance.instanceId);
|
688
697
|
} catch (e: any) {
|
689
|
-
console.warn(
|
698
|
+
console.warn(
|
699
|
+
'Failed to start previously stopped instance',
|
700
|
+
instance.systemId,
|
701
|
+
instance.instanceId,
|
702
|
+
e
|
703
|
+
);
|
690
704
|
}
|
691
705
|
return;
|
692
706
|
}
|
@@ -738,37 +752,47 @@ export class InstanceManager {
|
|
738
752
|
return InstanceStatus.STOPPED;
|
739
753
|
}
|
740
754
|
const state = await container.status();
|
755
|
+
if (!state) {
|
756
|
+
return InstanceStatus.STOPPED;
|
757
|
+
}
|
741
758
|
|
742
|
-
|
743
|
-
if (state.Health?.Status === 'healthy') {
|
744
|
-
return InstanceStatus.READY;
|
745
|
-
}
|
746
|
-
if (state.Health?.Status === 'starting') {
|
747
|
-
return InstanceStatus.STARTING;
|
748
|
-
}
|
749
|
-
if (state.Health?.Status === 'unhealthy') {
|
750
|
-
return InstanceStatus.UNHEALTHY;
|
751
|
-
}
|
759
|
+
const statusType = state.Status as DockerContainerStatus;
|
752
760
|
|
761
|
+
if (statusType === 'running') {
|
762
|
+
if (state.Health?.Status) {
|
763
|
+
const healthStatusType = state.Health.Status as DockerContainerHealth;
|
764
|
+
if (healthStatusType === 'healthy' || healthStatusType === 'none') {
|
765
|
+
return InstanceStatus.READY;
|
766
|
+
}
|
767
|
+
|
768
|
+
if (healthStatusType === 'starting') {
|
769
|
+
return InstanceStatus.STARTING;
|
770
|
+
}
|
771
|
+
|
772
|
+
if (healthStatusType === 'unhealthy') {
|
773
|
+
return InstanceStatus.UNHEALTHY;
|
774
|
+
}
|
775
|
+
}
|
753
776
|
return InstanceStatus.READY;
|
754
777
|
}
|
755
|
-
|
778
|
+
|
779
|
+
if (statusType === 'created') {
|
756
780
|
return InstanceStatus.STARTING;
|
757
781
|
}
|
758
782
|
|
759
|
-
if (
|
783
|
+
if (statusType === 'exited' || statusType === 'dead') {
|
760
784
|
return InstanceStatus.STOPPED;
|
761
785
|
}
|
762
786
|
|
763
|
-
if (
|
787
|
+
if (statusType === 'removing') {
|
764
788
|
return InstanceStatus.BUSY;
|
765
789
|
}
|
766
790
|
|
767
|
-
if (
|
791
|
+
if (statusType === 'restarting') {
|
768
792
|
return InstanceStatus.BUSY;
|
769
793
|
}
|
770
794
|
|
771
|
-
if (
|
795
|
+
if (statusType === 'paused') {
|
772
796
|
return InstanceStatus.BUSY;
|
773
797
|
}
|
774
798
|
|
package/src/operatorManager.ts
CHANGED
@@ -4,7 +4,13 @@ import md5 from 'md5';
|
|
4
4
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
5
5
|
import { serviceManager } from './serviceManager';
|
6
6
|
import { storageService } from './storageService';
|
7
|
-
import {
|
7
|
+
import {
|
8
|
+
COMPOSE_LABEL_PROJECT,
|
9
|
+
COMPOSE_LABEL_SERVICE,
|
10
|
+
CONTAINER_LABEL_PORT_PREFIX,
|
11
|
+
ContainerInfo,
|
12
|
+
containerManager,
|
13
|
+
} from './containerManager';
|
8
14
|
import FSExtra from 'fs-extra';
|
9
15
|
import { AnyMap, EnvironmentType, OperatorInfo, StringMap } from './types';
|
10
16
|
import { BlockInstance, Resource } from '@kapeta/schemas';
|
@@ -199,8 +205,12 @@ class OperatorManager {
|
|
199
205
|
const PortBindings: { [key: string]: any } = {};
|
200
206
|
const Env: string[] = [];
|
201
207
|
|
208
|
+
const systemUri = parseKapetaUri(systemId);
|
209
|
+
|
202
210
|
const Labels: StringMap = {
|
203
211
|
kapeta: 'true',
|
212
|
+
[COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
|
213
|
+
[COMPOSE_LABEL_SERVICE]: [resourceType, version].join('_').replace(/[^a-z0-9]/gi, '_'),
|
204
214
|
};
|
205
215
|
|
206
216
|
const operatorMetadata = operator.getDefinitionInfo().definition.metadata;
|
package/src/taskManager.ts
CHANGED
@@ -139,7 +139,9 @@ class TaskManager {
|
|
139
139
|
|
140
140
|
socketManager.emitGlobal(EVENT_TASK_ADDED, task.toData());
|
141
141
|
|
142
|
-
this.invokeTask(task).catch(() => {
|
142
|
+
this.invokeTask(task).catch((err) => {
|
143
|
+
console.warn(`Task ${task.id} failed`, err);
|
144
|
+
});
|
143
145
|
|
144
146
|
return task;
|
145
147
|
}
|
@@ -205,6 +207,7 @@ class TaskManager {
|
|
205
207
|
task.future.resolve(result);
|
206
208
|
task.emitUpdate();
|
207
209
|
} catch (e: any) {
|
210
|
+
console.warn(`Task ${task.id} failed while waiting for it to resolve`, e);
|
208
211
|
task.errorMessage = e.message;
|
209
212
|
task.status = TaskStatus.FAILED;
|
210
213
|
task.future.reject(e);
|
@@ -3,12 +3,18 @@ import ClusterConfig, { DefinitionInfo } from '@kapeta/local-cluster-config';
|
|
3
3
|
import { getBindHost, getBlockInstanceContainerName, normalizeKapetaUri, readYML } from './utils';
|
4
4
|
import { KapetaURI, parseKapetaUri } from '@kapeta/nodejs-utils';
|
5
5
|
import { serviceManager } from '../serviceManager';
|
6
|
-
import {
|
6
|
+
import {
|
7
|
+
COMPOSE_LABEL_PROJECT,
|
8
|
+
COMPOSE_LABEL_SERVICE,
|
9
|
+
containerManager,
|
10
|
+
DockerMounts,
|
11
|
+
toLocalBindVolume,
|
12
|
+
} from '../containerManager';
|
7
13
|
import { LogData } from './LogData';
|
8
14
|
import { clusterService } from '../clusterService';
|
9
15
|
import { AnyMap, BlockProcessParams, InstanceType, ProcessInfo, StringMap } from '../types';
|
10
|
-
import { Container } from 'node-docker-api/lib/container';
|
11
16
|
import { definitionsManager } from '../definitionsManager';
|
17
|
+
import Docker from 'dockerode';
|
12
18
|
|
13
19
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
14
20
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
@@ -185,6 +191,8 @@ export class BlockInstanceRunner {
|
|
185
191
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
186
192
|
}
|
187
193
|
|
194
|
+
const systemUri = parseKapetaUri(this._systemId);
|
195
|
+
|
188
196
|
return this.ensureContainer({
|
189
197
|
...dockerOpts,
|
190
198
|
Image: dockerImage,
|
@@ -193,6 +201,8 @@ export class BlockInstanceRunner {
|
|
193
201
|
Labels: {
|
194
202
|
...customLabels,
|
195
203
|
instance: blockInstance.id,
|
204
|
+
[COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
|
205
|
+
[COMPOSE_LABEL_SERVICE]: blockInfo.id.replace(/[^a-z0-9]/gi, '_'),
|
196
206
|
},
|
197
207
|
HealthCheck,
|
198
208
|
ExposedPorts,
|
@@ -250,6 +260,7 @@ export class BlockInstanceRunner {
|
|
250
260
|
|
251
261
|
// For windows we need to default to root
|
252
262
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
263
|
+
const systemUri = parseKapetaUri(this._systemId);
|
253
264
|
|
254
265
|
return this.ensureContainer({
|
255
266
|
Image: dockerImage,
|
@@ -257,6 +268,8 @@ export class BlockInstanceRunner {
|
|
257
268
|
ExposedPorts,
|
258
269
|
Labels: {
|
259
270
|
instance: blockInstance.id,
|
271
|
+
[COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
|
272
|
+
[COMPOSE_LABEL_SERVICE]: blockInfo.id.replace(/[^a-z0-9]/gi, '_'),
|
260
273
|
},
|
261
274
|
Env: [
|
262
275
|
...DOCKER_ENV_VARS,
|
@@ -354,6 +367,7 @@ export class BlockInstanceRunner {
|
|
354
367
|
// For windows we need to default to root
|
355
368
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
356
369
|
|
370
|
+
const systemUri = parseKapetaUri(this._systemId);
|
357
371
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
358
372
|
const out = await this.ensureContainer({
|
359
373
|
Image: dockerImage,
|
@@ -370,6 +384,8 @@ export class BlockInstanceRunner {
|
|
370
384
|
},
|
371
385
|
Labels: {
|
372
386
|
instance: blockInstance.id,
|
387
|
+
[COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
|
388
|
+
[COMPOSE_LABEL_SERVICE]: blockUri.id.replace(/[^a-z0-9]/gi, '_'),
|
373
389
|
},
|
374
390
|
Env: [
|
375
391
|
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
@@ -424,7 +440,7 @@ export class BlockInstanceRunner {
|
|
424
440
|
return this._handleContainer(container);
|
425
441
|
}
|
426
442
|
|
427
|
-
private async _handleContainer(container: Container): Promise<ProcessInfo> {
|
443
|
+
private async _handleContainer(container: Docker.Container): Promise<ProcessInfo> {
|
428
444
|
return {
|
429
445
|
type: InstanceType.DOCKER,
|
430
446
|
pid: container.id,
|