@kapeta/local-cluster-service 0.34.2 → 0.36.0
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/.github/workflows/check-license.yml +0 -1
- package/CHANGELOG.md +14 -0
- package/dist/cjs/src/config/routes.js +9 -0
- package/dist/cjs/src/containerManager.d.ts +2 -8
- package/dist/cjs/src/containerManager.js +7 -7
- package/dist/cjs/src/instanceManager.d.ts +8 -3
- package/dist/cjs/src/instanceManager.js +147 -25
- package/dist/cjs/src/operatorManager.d.ts +9 -9
- package/dist/cjs/src/operatorManager.js +21 -26
- package/dist/cjs/src/serviceManager.d.ts +1 -0
- package/dist/cjs/src/serviceManager.js +9 -9
- package/dist/cjs/src/types.d.ts +40 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +2 -13
- package/dist/cjs/src/utils/BlockInstanceRunner.js +91 -79
- package/dist/cjs/src/utils/utils.d.ts +6 -2
- package/dist/cjs/src/utils/utils.js +35 -2
- package/dist/esm/src/config/routes.js +9 -0
- package/dist/esm/src/containerManager.d.ts +2 -8
- package/dist/esm/src/containerManager.js +7 -7
- package/dist/esm/src/instanceManager.d.ts +8 -3
- package/dist/esm/src/instanceManager.js +147 -25
- package/dist/esm/src/operatorManager.d.ts +9 -9
- package/dist/esm/src/operatorManager.js +21 -26
- package/dist/esm/src/serviceManager.d.ts +1 -0
- package/dist/esm/src/serviceManager.js +9 -9
- package/dist/esm/src/types.d.ts +40 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +2 -13
- package/dist/esm/src/utils/BlockInstanceRunner.js +91 -79
- package/dist/esm/src/utils/utils.d.ts +6 -2
- package/dist/esm/src/utils/utils.js +35 -2
- package/package.json +1 -1
- package/src/config/routes.ts +15 -0
- package/src/containerManager.ts +8 -15
- package/src/instanceManager.ts +218 -34
- package/src/operatorManager.ts +26 -31
- package/src/serviceManager.ts +11 -8
- package/src/types.ts +36 -0
- package/src/utils/BlockInstanceRunner.ts +119 -92
- package/src/utils/utils.ts +40 -3
package/dist/cjs/src/types.d.ts
CHANGED
@@ -56,6 +56,31 @@ export type ProcessInfo = {
|
|
56
56
|
pid?: number | string | null;
|
57
57
|
portType?: string;
|
58
58
|
};
|
59
|
+
export interface Health {
|
60
|
+
cmd: string;
|
61
|
+
interval?: number;
|
62
|
+
timeout?: number;
|
63
|
+
retries?: number;
|
64
|
+
}
|
65
|
+
export type PortInfo = {
|
66
|
+
port: number;
|
67
|
+
type: 'tcp' | 'udp';
|
68
|
+
} | number | string;
|
69
|
+
export type LocalImageOptions<Credentials = AnyMap, Options = AnyMap> = {
|
70
|
+
image: string;
|
71
|
+
ports: {
|
72
|
+
[key: string]: PortInfo;
|
73
|
+
};
|
74
|
+
credentials?: Credentials;
|
75
|
+
options?: Options;
|
76
|
+
cmd?: string;
|
77
|
+
env?: AnyMap;
|
78
|
+
health?: Health;
|
79
|
+
singleton?: boolean;
|
80
|
+
mounts?: {
|
81
|
+
[key: string]: string;
|
82
|
+
};
|
83
|
+
};
|
59
84
|
export type InstanceInfo = {
|
60
85
|
systemId: string;
|
61
86
|
instanceId: string;
|
@@ -73,6 +98,21 @@ export type InstanceInfo = {
|
|
73
98
|
portType?: string;
|
74
99
|
};
|
75
100
|
export type ProxyRequestHandler = (req: StringBodyRequest, res: express.Response, info: ProxyRequestInfo) => void;
|
101
|
+
export interface OperatorInstancePort {
|
102
|
+
protocol: string;
|
103
|
+
port: number;
|
104
|
+
}
|
105
|
+
export interface OperatorInstanceInfo {
|
106
|
+
hostname: string;
|
107
|
+
ports: {
|
108
|
+
[portType: string]: OperatorInstancePort;
|
109
|
+
};
|
110
|
+
path?: string;
|
111
|
+
query?: string;
|
112
|
+
hash?: string;
|
113
|
+
options?: AnyMap;
|
114
|
+
credentials?: AnyMap;
|
115
|
+
}
|
76
116
|
export interface OperatorInfo {
|
77
117
|
host: string;
|
78
118
|
port: string;
|
@@ -2,9 +2,7 @@
|
|
2
2
|
* Copyright 2023 Kapeta Inc.
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
|
-
import {
|
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,16 +18,7 @@ export declare class BlockInstanceRunner {
|
|
20
18
|
*/
|
21
19
|
private _startLocalProcess;
|
22
20
|
private _startDockerProcess;
|
23
|
-
|
24
|
-
*
|
25
|
-
* @param blockInstance
|
26
|
-
* @param blockUri
|
27
|
-
* @param providerDefinition
|
28
|
-
* @param {{[key:string]:string}} env
|
29
|
-
* @return {Promise<ProcessDetails>}
|
30
|
-
* @private
|
31
|
-
*/
|
32
|
-
_startOperatorProcess(blockInstance: BlockProcessParams, blockUri: KapetaURI, providerDefinition: DefinitionInfo, env: StringMap): Promise<ProcessInfo>;
|
21
|
+
private _startOperatorProcess;
|
33
22
|
private getDockerPortBindings;
|
34
23
|
private ensureContainer;
|
35
24
|
private _handleContainer;
|
@@ -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';
|
@@ -155,7 +156,7 @@ class BlockInstanceRunner {
|
|
155
156
|
if (!dockerImage) {
|
156
157
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
157
158
|
}
|
158
|
-
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
159
|
+
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, targetKindUri.id);
|
159
160
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
160
161
|
const dockerOpts = localContainer.options ?? {};
|
161
162
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
@@ -241,7 +242,7 @@ class BlockInstanceRunner {
|
|
241
242
|
throw new Error(`Block type not found: ${kindUri.id}`);
|
242
243
|
}
|
243
244
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion, providerVersion);
|
244
|
-
const containerName = (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id);
|
245
|
+
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, kindUri.id);
|
245
246
|
// For windows we need to default to root
|
246
247
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
|
247
248
|
const systemUri = (0, nodejs_utils_1.parseKapetaUri)(this._systemId);
|
@@ -268,15 +269,6 @@ class BlockInstanceRunner {
|
|
268
269
|
},
|
269
270
|
});
|
270
271
|
}
|
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
272
|
async _startOperatorProcess(blockInstance, blockUri, providerDefinition, env) {
|
281
273
|
const { assetFile } = local_cluster_config_1.default.getRepositoryAssetInfoPath(blockUri.handle, blockUri.name, blockUri.version);
|
282
274
|
const kapetaYmlPath = assetFile;
|
@@ -288,79 +280,99 @@ class BlockInstanceRunner {
|
|
288
280
|
if (!spec?.local?.image) {
|
289
281
|
throw new Error(`Provider did not have local image: ${providerRef}`);
|
290
282
|
}
|
291
|
-
const
|
292
|
-
|
293
|
-
const
|
294
|
-
const
|
295
|
-
const
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
let HealthCheck = undefined;
|
300
|
-
let Mounts = [];
|
301
|
-
const localPorts = spec.local.ports;
|
302
|
-
const promises = Object.entries(localPorts).map(async ([portType, value]) => {
|
303
|
-
const dockerPort = `${value.port}/${value.type}`;
|
304
|
-
ExposedPorts[dockerPort] = {};
|
305
|
-
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
306
|
-
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
307
|
-
PortBindings[dockerPort] = [
|
308
|
-
{
|
309
|
-
HostIp: bindHost,
|
310
|
-
HostPort: `${publicPort}`,
|
311
|
-
},
|
312
|
-
];
|
313
|
-
});
|
314
|
-
await Promise.all(promises);
|
315
|
-
if (spec.local?.env) {
|
316
|
-
Object.entries(spec.local.env).forEach(([key, value]) => {
|
317
|
-
addonEnv[key] = value;
|
318
|
-
});
|
319
|
-
}
|
320
|
-
if (spec.local?.mounts) {
|
321
|
-
const mounts = await containerManager_1.containerManager.createMounts(this._systemId, blockUri.id, spec.local.mounts);
|
322
|
-
Mounts = containerManager_1.containerManager.toDockerMounts(mounts);
|
323
|
-
}
|
324
|
-
if (spec.local?.health) {
|
325
|
-
HealthCheck = containerManager_1.containerManager.toDockerHealth(spec.local?.health);
|
283
|
+
const local = spec.local;
|
284
|
+
const dockerImage = local.image;
|
285
|
+
const operatorUri = local.singleton ? (0, nodejs_utils_1.parseKapetaUri)(providerRef) : blockUri;
|
286
|
+
const operatorId = local.singleton ? providerRef : blockInstance.id;
|
287
|
+
const operatorRef = local.singleton ? providerRef : blockInstance.ref;
|
288
|
+
if (local.singleton && env) {
|
289
|
+
env[KAPETA_BLOCK_REF] = operatorRef;
|
290
|
+
env[KAPETA_INSTANCE_ID] = operatorId;
|
326
291
|
}
|
327
|
-
|
328
|
-
const
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
292
|
+
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, providerRef);
|
293
|
+
const task = taskManager_1.taskManager.add(`container:start:${containerName}`, async () => {
|
294
|
+
const logs = new LogData_1.LogData();
|
295
|
+
const bindHost = (0, utils_1.getBindHost)();
|
296
|
+
const ExposedPorts = {};
|
297
|
+
const addonEnv = {};
|
298
|
+
const PortBindings = {};
|
299
|
+
let HealthCheck = undefined;
|
300
|
+
let Mounts = [];
|
301
|
+
const localPorts = local.ports ?? {};
|
302
|
+
const labels = {};
|
303
|
+
const promises = Object.entries(localPorts).map(async ([portType, value]) => {
|
304
|
+
const portInfo = (0, utils_1.toPortInfo)(value);
|
305
|
+
const dockerPort = `${portInfo.port}/${portInfo.type}`;
|
306
|
+
ExposedPorts[dockerPort] = {};
|
307
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = `${portInfo.port}`;
|
308
|
+
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, operatorId, portType);
|
309
|
+
PortBindings[dockerPort] = [
|
310
|
+
{
|
311
|
+
HostIp: bindHost,
|
312
|
+
HostPort: `${publicPort}`,
|
313
|
+
},
|
314
|
+
];
|
315
|
+
labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + publicPort] = portType;
|
316
|
+
});
|
317
|
+
await Promise.all(promises);
|
318
|
+
if (local.env) {
|
319
|
+
Object.entries(local.env).forEach(([key, value]) => {
|
320
|
+
addonEnv[key] = value;
|
321
|
+
});
|
322
|
+
}
|
323
|
+
if (local.mounts) {
|
324
|
+
Mounts = await containerManager_1.containerManager.createVolumes(this._systemId, operatorUri.id, local.mounts);
|
325
|
+
}
|
326
|
+
if (local.health) {
|
327
|
+
HealthCheck = containerManager_1.containerManager.toDockerHealth(local.health);
|
328
|
+
}
|
329
|
+
// For windows we need to default to root
|
330
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : local_cluster_config_1.default.getKapetaBasedir();
|
331
|
+
const Binds = local.singleton
|
332
|
+
? [`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`]
|
333
|
+
: [
|
338
334
|
`${(0, containerManager_1.toLocalBindVolume)(kapetaYmlPath)}:/kapeta.yml:ro`,
|
339
335
|
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`,
|
336
|
+
];
|
337
|
+
const systemUri = (0, nodejs_utils_1.parseKapetaUri)(this._systemId);
|
338
|
+
console.log(`Ensuring container for operator block: ${containerName} [singleton: ${!!local.singleton}]`);
|
339
|
+
logs.addLog(`Ensuring container for operator block: ${containerName}`);
|
340
|
+
const out = await this.ensureContainer({
|
341
|
+
Image: dockerImage,
|
342
|
+
name: containerName,
|
343
|
+
ExposedPorts,
|
344
|
+
HealthCheck,
|
345
|
+
HostConfig: {
|
346
|
+
Binds,
|
347
|
+
PortBindings,
|
348
|
+
Mounts,
|
349
|
+
},
|
350
|
+
Labels: {
|
351
|
+
...labels,
|
352
|
+
instance: operatorId,
|
353
|
+
[containerManager_1.COMPOSE_LABEL_PROJECT]: systemUri.id.replace(/[^a-z0-9]/gi, '_'),
|
354
|
+
[containerManager_1.COMPOSE_LABEL_SERVICE]: operatorUri.id.replace(/[^a-z0-9]/gi, '_'),
|
355
|
+
},
|
356
|
+
Env: [
|
357
|
+
`KAPETA_INSTANCE_NAME=${operatorRef}`,
|
358
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
359
|
+
...DOCKER_ENV_VARS,
|
360
|
+
...Object.entries({
|
361
|
+
...env,
|
362
|
+
...addonEnv,
|
363
|
+
}).map(([key, value]) => `${key}=${value}`),
|
340
364
|
],
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
}
|
349
|
-
|
350
|
-
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
351
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
352
|
-
...DOCKER_ENV_VARS,
|
353
|
-
...Object.entries({
|
354
|
-
...env,
|
355
|
-
...addonEnv,
|
356
|
-
}).map(([key, value]) => `${key}=${value}`),
|
357
|
-
],
|
365
|
+
});
|
366
|
+
const portTypes = local.ports ? Object.keys(local.ports) : [];
|
367
|
+
if (portTypes.length > 0) {
|
368
|
+
out.portType = portTypes[0];
|
369
|
+
}
|
370
|
+
return out;
|
371
|
+
}, {
|
372
|
+
name: `Starting container for ${providerRef}`,
|
373
|
+
systemId: this._systemId,
|
358
374
|
});
|
359
|
-
|
360
|
-
if (portTypes.length > 0) {
|
361
|
-
out.portType = portTypes[0];
|
362
|
-
}
|
363
|
-
return out;
|
375
|
+
return task.wait();
|
364
376
|
}
|
365
377
|
async getDockerPortBindings(blockInstance, assetVersion, providerVersion) {
|
366
378
|
const bindHost = (0, utils_1.getBindHost)();
|
@@ -3,8 +3,12 @@
|
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
5
|
import { EntityList } from '@kapeta/schemas';
|
6
|
-
import { AnyMap } from '../types';
|
7
|
-
export declare function getBlockInstanceContainerName(systemId: string, instanceId: string): string
|
6
|
+
import { AnyMap, PortInfo } from '../types';
|
7
|
+
export declare function getBlockInstanceContainerName(systemId: string, instanceId: string, blockType?: string): Promise<string>;
|
8
|
+
export declare function toPortInfo(port: PortInfo): {
|
9
|
+
port: number;
|
10
|
+
type: string;
|
11
|
+
};
|
8
12
|
export declare function getRemoteUrl(id: string, defautValue: string): any;
|
9
13
|
export declare function readYML(path: string): any;
|
10
14
|
export declare function isWindows(): boolean;
|
@@ -7,16 +7,49 @@ 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.getResolvedConfiguration = exports.getBindHost = exports.isLinux = exports.isMac = exports.isWindows = exports.readYML = exports.getRemoteUrl = exports.getBlockInstanceContainerName = void 0;
|
10
|
+
exports.getResolvedConfiguration = exports.getBindHost = exports.isLinux = exports.isMac = exports.isWindows = exports.readYML = exports.getRemoteUrl = exports.toPortInfo = exports.getBlockInstanceContainerName = void 0;
|
11
11
|
const node_fs_1 = __importDefault(require("node:fs"));
|
12
12
|
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
|
-
|
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)(systemId + blockType)}`;
|
39
|
+
}
|
17
40
|
return `kapeta-block-instance-${(0, md5_1.default)(systemId + instanceId)}`;
|
18
41
|
}
|
19
42
|
exports.getBlockInstanceContainerName = getBlockInstanceContainerName;
|
43
|
+
function toPortInfo(port) {
|
44
|
+
if (typeof port === 'number' || typeof port === 'string') {
|
45
|
+
return { port: parseInt(`${port}`), type: 'tcp' };
|
46
|
+
}
|
47
|
+
if (!port.type) {
|
48
|
+
port.type = 'tcp';
|
49
|
+
}
|
50
|
+
return port;
|
51
|
+
}
|
52
|
+
exports.toPortInfo = toPortInfo;
|
20
53
|
function getRemoteUrl(id, defautValue) {
|
21
54
|
const remoteConfig = local_cluster_config_1.default.getClusterConfig().remote;
|
22
55
|
return remoteConfig?.[id] ?? defautValue;
|
@@ -148,4 +148,13 @@ router.get('/consumes/resource/:resourceType/:portType/:name', async (req, res)
|
|
148
148
|
router.get('/consumes/:resourceName/:type', (req, res) => {
|
149
149
|
res.send(serviceManager_1.serviceManager.getConsumerAddress(req.kapeta.systemId, req.kapeta.instanceId, req.params.resourceName, req.params.type, req.kapeta.environment));
|
150
150
|
});
|
151
|
+
/**
|
152
|
+
* Used by services to information about a block operator
|
153
|
+
*
|
154
|
+
* If the remote service is not already running it will be started
|
155
|
+
*/
|
156
|
+
router.get('/operator/:instanceId', async (req, res) => {
|
157
|
+
const operatorInfo = await instanceManager_1.instanceManager.getInstanceOperator(req.kapeta.systemId, req.params.instanceId, req.kapeta.environment);
|
158
|
+
res.send(operatorInfo);
|
159
|
+
});
|
151
160
|
exports.default = router;
|
@@ -5,7 +5,7 @@
|
|
5
5
|
/// <reference types="node" />
|
6
6
|
import FSExtra from 'fs-extra';
|
7
7
|
import Docker from 'dockerode';
|
8
|
-
import { InstanceInfo, LogEntry } from './types';
|
8
|
+
import { Health, InstanceInfo, LogEntry } from './types';
|
9
9
|
type StringMap = {
|
10
10
|
[key: string]: string;
|
11
11
|
};
|
@@ -26,12 +26,6 @@ export interface DockerMounts {
|
|
26
26
|
}
|
27
27
|
export type DockerContainerStatus = 'created' | 'running' | 'paused' | 'restarting' | 'removing' | 'exited' | 'dead';
|
28
28
|
export type DockerContainerHealth = 'starting' | 'healthy' | 'unhealthy' | 'none';
|
29
|
-
interface Health {
|
30
|
-
cmd: string;
|
31
|
-
interval?: number;
|
32
|
-
timeout?: number;
|
33
|
-
retries?: number;
|
34
|
-
}
|
35
29
|
export declare const CONTAINER_LABEL_PORT_PREFIX = "kapeta_port-";
|
36
30
|
export declare const COMPOSE_LABEL_PROJECT = "com.docker.compose.project";
|
37
31
|
export declare const COMPOSE_LABEL_SERVICE = "com.docker.compose.service";
|
@@ -50,7 +44,7 @@ declare class ContainerManager {
|
|
50
44
|
isAlive(): boolean;
|
51
45
|
getMountPoint(systemId: string, ref: string, mountName: string): string;
|
52
46
|
createMounts(systemId: string, kind: string, mountOpts: StringMap | null | undefined): Promise<StringMap>;
|
53
|
-
createVolumes(systemId: string,
|
47
|
+
createVolumes(systemId: string, serviceId: string, mountOpts: StringMap | null | undefined): Promise<DockerMounts[]>;
|
54
48
|
ping(): Promise<void>;
|
55
49
|
docker(): Docker;
|
56
50
|
getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
|
@@ -168,12 +168,12 @@ class ContainerManager {
|
|
168
168
|
}
|
169
169
|
return mounts;
|
170
170
|
}
|
171
|
-
async createVolumes(systemId,
|
171
|
+
async createVolumes(systemId, serviceId, mountOpts) {
|
172
172
|
const Mounts = [];
|
173
173
|
if (mountOpts) {
|
174
174
|
const mountOptList = Object.entries(mountOpts);
|
175
175
|
for (const [mountName, containerPath] of mountOptList) {
|
176
|
-
const volumeName = `${systemId}_${
|
176
|
+
const volumeName = `${systemId}_${serviceId}_${mountName}`.replace(/[^a-z0-9]/gi, '_');
|
177
177
|
Mounts.push({
|
178
178
|
Target: containerPath,
|
179
179
|
Source: volumeName,
|
@@ -182,7 +182,7 @@ class ContainerManager {
|
|
182
182
|
Consistency: 'consistent',
|
183
183
|
Labels: {
|
184
184
|
[exports.COMPOSE_LABEL_PROJECT]: systemId.replace(/[^a-z0-9]/gi, '_'),
|
185
|
-
[exports.COMPOSE_LABEL_SERVICE]:
|
185
|
+
[exports.COMPOSE_LABEL_SERVICE]: serviceId.replace(/[^a-z0-9]/gi, '_'),
|
186
186
|
},
|
187
187
|
});
|
188
188
|
}
|
@@ -533,7 +533,7 @@ class ContainerManager {
|
|
533
533
|
return new ContainerInfo(dockerContainer);
|
534
534
|
}
|
535
535
|
async getLogs(instance) {
|
536
|
-
const containerName = (0, utils_1.getBlockInstanceContainerName)(instance.systemId, instance.instanceId);
|
536
|
+
const containerName = await (0, utils_1.getBlockInstanceContainerName)(instance.systemId, instance.instanceId);
|
537
537
|
const containerInfo = await this.getContainerByName(containerName);
|
538
538
|
if (!containerInfo) {
|
539
539
|
return [
|
@@ -548,7 +548,7 @@ class ContainerManager {
|
|
548
548
|
return containerInfo.getLogs();
|
549
549
|
}
|
550
550
|
async stopLogListening(systemId, instanceId) {
|
551
|
-
const containerName = (0, utils_1.getBlockInstanceContainerName)(systemId, instanceId);
|
551
|
+
const containerName = await (0, utils_1.getBlockInstanceContainerName)(systemId, instanceId);
|
552
552
|
if (this.logStreams[containerName]) {
|
553
553
|
if (this.logStreams[containerName]?.timer) {
|
554
554
|
clearTimeout(this.logStreams[containerName].timer);
|
@@ -566,7 +566,7 @@ class ContainerManager {
|
|
566
566
|
}
|
567
567
|
}
|
568
568
|
async ensureLogListening(systemId, instanceId, handler) {
|
569
|
-
const containerName = (0, utils_1.getBlockInstanceContainerName)(systemId, instanceId);
|
569
|
+
const containerName = await (0, utils_1.getBlockInstanceContainerName)(systemId, instanceId);
|
570
570
|
try {
|
571
571
|
if (this.logStreams[containerName]?.stream) {
|
572
572
|
// Already listening - will shut itself down
|
@@ -791,7 +791,7 @@ class ContainerInfo {
|
|
791
791
|
if (!name.startsWith(exports.CONTAINER_LABEL_PORT_PREFIX)) {
|
792
792
|
return;
|
793
793
|
}
|
794
|
-
const hostPort = name.
|
794
|
+
const hostPort = name.substring(exports.CONTAINER_LABEL_PORT_PREFIX.length);
|
795
795
|
portTypes[hostPort] = portType;
|
796
796
|
});
|
797
797
|
lodash_1.default.forEach(inspectResult.HostConfig.PortBindings, (portBindings, containerPortSpec) => {
|
@@ -2,7 +2,7 @@
|
|
2
2
|
* Copyright 2023 Kapeta Inc.
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
|
-
import { InstanceInfo, LogEntry } from './types';
|
5
|
+
import { EnvironmentType, InstanceInfo, LogEntry, OperatorInstanceInfo } from './types';
|
6
6
|
import { Task } from './taskManager';
|
7
7
|
export declare class InstanceManager {
|
8
8
|
private _interval;
|
@@ -24,10 +24,11 @@ export declare class InstanceManager {
|
|
24
24
|
private getHealthUrl;
|
25
25
|
markAsStopped(systemId: string, instanceId: string): Promise<void>;
|
26
26
|
startAllForPlan(systemId: string): Promise<Task<InstanceInfo[]>>;
|
27
|
+
stopAllForPlan(systemId: string): Task<void>;
|
28
|
+
getInstanceOperator(systemId: string, instanceId: string, environment?: EnvironmentType): Promise<OperatorInstanceInfo>;
|
27
29
|
stop(systemId: string, instanceId: string): Promise<void>;
|
28
30
|
private stopInner;
|
29
|
-
|
30
|
-
start(systemId: string, instanceId: string): Promise<InstanceInfo | Task<InstanceInfo>>;
|
31
|
+
start(systemId: string, instanceId: string, checkForSingleton?: boolean): Promise<InstanceInfo | Task<InstanceInfo>>;
|
31
32
|
/**
|
32
33
|
* Stops an instance but does not remove it from the list of active instances
|
33
34
|
*
|
@@ -42,5 +43,9 @@ export declare class InstanceManager {
|
|
42
43
|
private checkInstances;
|
43
44
|
private getExternalStatus;
|
44
45
|
private requestInstanceStatus;
|
46
|
+
private isSingletonOperator;
|
47
|
+
private getKindForAssetRef;
|
48
|
+
private isUsingKind;
|
49
|
+
private getAllInstancesForKind;
|
45
50
|
}
|
46
51
|
export declare const instanceManager: InstanceManager;
|