@kapeta/local-cluster-service 0.11.1 → 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 +14 -0
- package/definitions.d.ts +7 -0
- package/dist/cjs/src/config/routes.js +1 -1
- package/dist/cjs/src/containerManager.d.ts +3 -2
- package/dist/cjs/src/containerManager.js +127 -34
- package/dist/cjs/src/definitionsManager.d.ts +1 -0
- package/dist/cjs/src/definitionsManager.js +7 -4
- package/dist/cjs/src/instanceManager.d.ts +8 -1
- package/dist/cjs/src/instanceManager.js +56 -21
- package/dist/cjs/src/instances/routes.js +2 -0
- package/dist/cjs/src/operatorManager.d.ts +2 -0
- package/dist/cjs/src/operatorManager.js +70 -67
- package/dist/cjs/src/socketManager.d.ts +1 -0
- package/dist/cjs/src/socketManager.js +3 -0
- package/dist/cjs/src/types.d.ts +1 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +2 -3
- package/dist/esm/src/config/routes.js +1 -1
- package/dist/esm/src/containerManager.d.ts +3 -2
- package/dist/esm/src/containerManager.js +128 -35
- package/dist/esm/src/definitionsManager.d.ts +1 -0
- package/dist/esm/src/definitionsManager.js +8 -5
- package/dist/esm/src/instanceManager.d.ts +8 -1
- package/dist/esm/src/instanceManager.js +56 -21
- package/dist/esm/src/instances/routes.js +2 -0
- package/dist/esm/src/operatorManager.d.ts +2 -0
- package/dist/esm/src/operatorManager.js +68 -65
- package/dist/esm/src/socketManager.d.ts +1 -0
- package/dist/esm/src/socketManager.js +3 -0
- package/dist/esm/src/types.d.ts +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.js +2 -3
- package/dist/esm/src/utils/utils.js +1 -1
- package/package.json +1 -1
- package/src/config/routes.ts +1 -1
- package/src/containerManager.ts +181 -60
- package/src/definitionsManager.ts +9 -5
- package/src/instanceManager.ts +82 -42
- package/src/instances/routes.ts +3 -1
- package/src/operatorManager.ts +73 -69
- package/src/socketManager.ts +4 -0
- package/src/types.ts +1 -1
- package/src/utils/BlockInstanceRunner.ts +12 -24
- package/src/utils/utils.ts +2 -2
package/src/operatorManager.ts
CHANGED
@@ -11,9 +11,9 @@ import { BlockInstance, Resource } from '@kapeta/schemas';
|
|
11
11
|
import { definitionsManager } from './definitionsManager';
|
12
12
|
import { getBindHost, normalizeKapetaUri } from './utils/utils';
|
13
13
|
import _ from 'lodash';
|
14
|
-
import
|
14
|
+
import AsyncLock from 'async-lock';
|
15
15
|
|
16
|
-
const KIND_OPERATOR = 'core/resource-type-operator';
|
16
|
+
export const KIND_OPERATOR = 'core/resource-type-operator';
|
17
17
|
|
18
18
|
class Operator {
|
19
19
|
private _data: any;
|
@@ -33,6 +33,8 @@ class Operator {
|
|
33
33
|
class OperatorManager {
|
34
34
|
private _mountDir: string;
|
35
35
|
|
36
|
+
private operatorLock: AsyncLock = new AsyncLock();
|
37
|
+
|
36
38
|
constructor() {
|
37
39
|
this._mountDir = Path.join(storageService.getKapetaBasedir(), 'mounts');
|
38
40
|
|
@@ -154,98 +156,100 @@ class OperatorManager {
|
|
154
156
|
* @return {Promise<ContainerInfo>}
|
155
157
|
*/
|
156
158
|
async ensureResource(systemId: string, resourceType: string, version: string): Promise<ContainerInfo> {
|
157
|
-
|
159
|
+
systemId = normalizeKapetaUri(systemId);
|
160
|
+
const key = `${systemId}#${resourceType}:${version}`;
|
161
|
+
return await this.operatorLock.acquire(key, async () => {
|
162
|
+
const operator = this.getOperator(resourceType, version);
|
158
163
|
|
159
|
-
|
164
|
+
const operatorData = operator.getData();
|
160
165
|
|
161
|
-
|
166
|
+
const portTypes = Object.keys(operatorData.ports);
|
162
167
|
|
163
|
-
|
168
|
+
portTypes.sort();
|
164
169
|
|
165
|
-
|
170
|
+
const ports: AnyMap = {};
|
166
171
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
172
|
+
for (let i = 0; i < portTypes.length; i++) {
|
173
|
+
const portType = portTypes[i];
|
174
|
+
let containerPortInfo = operatorData.ports[portType];
|
175
|
+
const hostPort = await serviceManager.ensureServicePort(systemId, resourceType, portType);
|
171
176
|
|
172
|
-
|
173
|
-
|
174
|
-
|
177
|
+
if (typeof containerPortInfo === 'number' || typeof containerPortInfo === 'string') {
|
178
|
+
containerPortInfo = { port: containerPortInfo, type: 'tcp' };
|
179
|
+
}
|
180
|
+
|
181
|
+
if (!containerPortInfo.type) {
|
182
|
+
containerPortInfo.type = 'tcp';
|
183
|
+
}
|
184
|
+
|
185
|
+
const portId = containerPortInfo.port + '/' + containerPortInfo.type;
|
175
186
|
|
176
|
-
|
177
|
-
|
187
|
+
ports[portId] = {
|
188
|
+
type: portType,
|
189
|
+
hostPort,
|
190
|
+
};
|
178
191
|
}
|
179
192
|
|
180
|
-
const
|
193
|
+
const mounts = await containerManager.createMounts(systemId, resourceType, operatorData.mounts);
|
181
194
|
|
182
|
-
|
183
|
-
type: portType,
|
184
|
-
hostPort,
|
185
|
-
};
|
186
|
-
}
|
195
|
+
const nameParts = [systemId, resourceType.toLowerCase(), version];
|
187
196
|
|
188
|
-
|
197
|
+
const containerName = `kapeta-resource-${md5(nameParts.join('_'))}`;
|
189
198
|
|
190
|
-
|
191
|
-
|
192
|
-
resourceType.toLowerCase(),
|
193
|
-
version
|
194
|
-
];
|
199
|
+
const PortBindings: { [key: string]: any } = {};
|
200
|
+
const Env: string[] = [];
|
195
201
|
|
196
|
-
|
202
|
+
const Labels: StringMap = {
|
203
|
+
kapeta: 'true',
|
204
|
+
};
|
197
205
|
|
198
|
-
|
199
|
-
const Env: string[] = [];
|
206
|
+
const bindHost = getBindHost();
|
200
207
|
|
201
|
-
|
202
|
-
kapeta: 'true',
|
203
|
-
};
|
208
|
+
const ExposedPorts: { [key: string]: any } = {};
|
204
209
|
|
205
|
-
|
210
|
+
_.forEach(ports, (portInfo: any, containerPort) => {
|
211
|
+
ExposedPorts['' + containerPort] = {};
|
212
|
+
PortBindings['' + containerPort] = [
|
213
|
+
{
|
214
|
+
HostPort: '' + portInfo.hostPort,
|
215
|
+
HostIp: bindHost,
|
216
|
+
},
|
217
|
+
];
|
206
218
|
|
207
|
-
|
219
|
+
Labels[CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
|
220
|
+
});
|
208
221
|
|
209
|
-
|
210
|
-
ExposedPorts['' + containerPort] = {};
|
211
|
-
PortBindings['' + containerPort] = [
|
212
|
-
{
|
213
|
-
HostPort: '' + portInfo.hostPort,
|
214
|
-
HostIp: bindHost,
|
215
|
-
},
|
216
|
-
];
|
222
|
+
const Mounts = containerManager.toDockerMounts(mounts);
|
217
223
|
|
218
|
-
|
219
|
-
|
224
|
+
_.forEach(operatorData.env, (value, name) => {
|
225
|
+
Env.push(name + '=' + value);
|
226
|
+
});
|
220
227
|
|
221
|
-
|
228
|
+
let HealthCheck = undefined;
|
222
229
|
|
223
|
-
|
224
|
-
|
225
|
-
|
230
|
+
if (operatorData.health) {
|
231
|
+
HealthCheck = containerManager.toDockerHealth(operatorData.health);
|
232
|
+
}
|
226
233
|
|
227
|
-
|
234
|
+
const container = await containerManager.ensureContainer({
|
235
|
+
name: containerName,
|
236
|
+
Image: operatorData.image,
|
237
|
+
Hostname: containerName + '.kapeta',
|
238
|
+
Labels,
|
239
|
+
Cmd: operatorData.cmd,
|
240
|
+
ExposedPorts,
|
241
|
+
Env,
|
242
|
+
HealthCheck,
|
243
|
+
HostConfig: {
|
244
|
+
PortBindings,
|
245
|
+
Mounts,
|
246
|
+
},
|
247
|
+
});
|
228
248
|
|
229
|
-
|
230
|
-
HealthCheck = containerManager.toDockerHealth(operatorData.health);
|
231
|
-
}
|
249
|
+
await containerManager.waitForReady(container);
|
232
250
|
|
233
|
-
|
234
|
-
name: containerName,
|
235
|
-
Image: operatorData.image,
|
236
|
-
Hostname: containerName + '.kapeta',
|
237
|
-
Labels,
|
238
|
-
Cmd: operatorData.cmd,
|
239
|
-
ExposedPorts,
|
240
|
-
Env,
|
241
|
-
HealthCheck,
|
242
|
-
HostConfig: {
|
243
|
-
PortBindings,
|
244
|
-
Mounts,
|
245
|
-
},
|
251
|
+
return new ContainerInfo(container);
|
246
252
|
});
|
247
|
-
|
248
|
-
return new ContainerInfo(container);
|
249
253
|
}
|
250
254
|
}
|
251
255
|
|
package/src/socketManager.ts
CHANGED
@@ -31,6 +31,10 @@ export class SocketManager {
|
|
31
31
|
this.io.to(context).emit(type, { context, payload });
|
32
32
|
}
|
33
33
|
|
34
|
+
emitGlobal(type: string, payload: any) {
|
35
|
+
this.io.emit(type, { payload });
|
36
|
+
}
|
37
|
+
|
34
38
|
_bindIO() {
|
35
39
|
this.io.on('connection', (socket) => this._handleSocketCreated(socket));
|
36
40
|
}
|
package/src/types.ts
CHANGED
@@ -64,6 +64,7 @@ export type InstanceInfo = {
|
|
64
64
|
type: InstanceType;
|
65
65
|
owner: InstanceOwner;
|
66
66
|
status: InstanceStatus;
|
67
|
+
errorMessage?: string;
|
67
68
|
desiredStatus: DesiredInstanceStatus;
|
68
69
|
address?: string;
|
69
70
|
|
@@ -71,7 +72,6 @@ export type InstanceInfo = {
|
|
71
72
|
health?: string | null;
|
72
73
|
pid?: number | string | null;
|
73
74
|
portType?: string;
|
74
|
-
|
75
75
|
};
|
76
76
|
|
77
77
|
interface ResourceRef {
|
@@ -175,11 +175,7 @@ export class BlockInstanceRunner {
|
|
175
175
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
176
176
|
const workingDir = localContainer.workingDir ? localContainer.workingDir : '/workspace';
|
177
177
|
|
178
|
-
const {
|
179
|
-
PortBindings,
|
180
|
-
ExposedPorts,
|
181
|
-
addonEnv
|
182
|
-
} = await this.getDockerPortBindings(blockInstance, assetVersion);
|
178
|
+
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
183
179
|
|
184
180
|
let HealthCheck = undefined;
|
185
181
|
if (localContainer.healthcheck) {
|
@@ -215,7 +211,12 @@ export class BlockInstanceRunner {
|
|
215
211
|
});
|
216
212
|
}
|
217
213
|
|
218
|
-
private async _startDockerProcess(
|
214
|
+
private async _startDockerProcess(
|
215
|
+
blockInstance: BlockProcessParams,
|
216
|
+
blockInfo: KapetaURI,
|
217
|
+
env: StringMap,
|
218
|
+
assetVersion: DefinitionInfo
|
219
|
+
) {
|
219
220
|
const { versionFile } = ClusterConfig.getRepositoryAssetInfoPath(
|
220
221
|
blockInfo.handle,
|
221
222
|
blockInfo.name,
|
@@ -237,11 +238,7 @@ export class BlockInstanceRunner {
|
|
237
238
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
238
239
|
}
|
239
240
|
|
240
|
-
const {
|
241
|
-
PortBindings,
|
242
|
-
ExposedPorts,
|
243
|
-
addonEnv
|
244
|
-
} = await this.getDockerPortBindings(blockInstance, assetVersion);
|
241
|
+
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
245
242
|
|
246
243
|
const containerName = getBlockInstanceContainerName(this._systemId, blockInstance.id);
|
247
244
|
|
@@ -260,9 +257,8 @@ export class BlockInstanceRunner {
|
|
260
257
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
261
258
|
...Object.entries({
|
262
259
|
...env,
|
263
|
-
...addonEnv
|
260
|
+
...addonEnv,
|
264
261
|
}).map(([key, value]) => `${key}=${value}`),
|
265
|
-
|
266
262
|
],
|
267
263
|
HostConfig: {
|
268
264
|
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
@@ -388,7 +384,6 @@ export class BlockInstanceRunner {
|
|
388
384
|
return out;
|
389
385
|
}
|
390
386
|
|
391
|
-
|
392
387
|
private async getDockerPortBindings(blockInstance: BlockProcessParams, assetVersion: DefinitionInfo) {
|
393
388
|
const bindHost = getBindHost();
|
394
389
|
const ExposedPorts: AnyMap = {};
|
@@ -412,28 +407,21 @@ export class BlockInstanceRunner {
|
|
412
407
|
];
|
413
408
|
});
|
414
409
|
|
415
|
-
|
416
410
|
await Promise.all(promises);
|
417
411
|
|
418
|
-
return {PortBindings,ExposedPorts, addonEnv};
|
412
|
+
return { PortBindings, ExposedPorts, addonEnv };
|
419
413
|
}
|
420
414
|
|
421
415
|
private async ensureContainer(opts: any) {
|
422
416
|
const container = await containerManager.ensureContainer(opts);
|
423
417
|
|
424
|
-
await containerManager.waitForReady(container);
|
425
|
-
|
426
418
|
return this._handleContainer(container);
|
427
|
-
|
428
419
|
}
|
429
420
|
|
430
|
-
private async _handleContainer(
|
431
|
-
container: Container
|
432
|
-
): Promise<ProcessInfo> {
|
433
|
-
|
421
|
+
private async _handleContainer(container: Container): Promise<ProcessInfo> {
|
434
422
|
return {
|
435
423
|
type: InstanceType.DOCKER,
|
436
|
-
pid: container.id
|
424
|
+
pid: container.id,
|
437
425
|
};
|
438
426
|
}
|
439
427
|
}
|
package/src/utils/utils.ts
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import FS from 'node:fs';
|
2
2
|
import YAML from 'yaml';
|
3
3
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
4
|
-
import md5 from
|
4
|
+
import md5 from 'md5';
|
5
5
|
|
6
|
-
export function getBlockInstanceContainerName(systemId:string, instanceId: string) {
|
6
|
+
export function getBlockInstanceContainerName(systemId: string, instanceId: string) {
|
7
7
|
return `kapeta-block-instance-${md5(systemId + instanceId)}`;
|
8
8
|
}
|
9
9
|
|