@kapeta/local-cluster-service 0.11.1 → 0.12.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/CHANGELOG.md +7 -0
- package/definitions.d.ts +7 -0
- package/dist/cjs/src/config/routes.js +1 -1
- package/dist/cjs/src/containerManager.d.ts +2 -1
- package/dist/cjs/src/containerManager.js +125 -21
- 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 +48 -19
- package/dist/cjs/src/operatorManager.d.ts +2 -0
- package/dist/cjs/src/operatorManager.js +69 -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 -2
- package/dist/esm/src/config/routes.js +1 -1
- package/dist/esm/src/containerManager.d.ts +2 -1
- package/dist/esm/src/containerManager.js +126 -22
- 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 +48 -19
- package/dist/esm/src/operatorManager.d.ts +2 -0
- package/dist/esm/src/operatorManager.js +67 -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 -2
- 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 +178 -43
- package/src/definitionsManager.ts +9 -5
- package/src/instanceManager.ts +70 -40
- package/src/instances/routes.ts +1 -1
- package/src/operatorManager.ts +72 -70
- package/src/socketManager.ts +4 -0
- package/src/types.ts +1 -1
- package/src/utils/BlockInstanceRunner.ts +12 -22
- 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,98 @@ 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
|
+
}
|
175
180
|
|
176
|
-
|
177
|
-
|
178
|
-
|
181
|
+
if (!containerPortInfo.type) {
|
182
|
+
containerPortInfo.type = 'tcp';
|
183
|
+
}
|
179
184
|
|
180
|
-
|
185
|
+
const portId = containerPortInfo.port + '/' + containerPortInfo.type;
|
181
186
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
+
ports[portId] = {
|
188
|
+
type: portType,
|
189
|
+
hostPort,
|
190
|
+
};
|
191
|
+
}
|
187
192
|
|
188
|
-
|
193
|
+
const mounts = await containerManager.createMounts(systemId, resourceType, operatorData.mounts);
|
189
194
|
|
190
|
-
|
191
|
-
systemId,
|
192
|
-
resourceType.toLowerCase(),
|
193
|
-
version
|
194
|
-
];
|
195
|
+
const nameParts = [systemId, resourceType.toLowerCase(), version];
|
195
196
|
|
196
|
-
|
197
|
+
const containerName = `kapeta-resource-${md5(nameParts.join('_'))}`;
|
197
198
|
|
198
|
-
|
199
|
-
|
199
|
+
const PortBindings: { [key: string]: any } = {};
|
200
|
+
const Env: string[] = [];
|
200
201
|
|
201
|
-
|
202
|
-
|
203
|
-
|
202
|
+
const Labels: StringMap = {
|
203
|
+
kapeta: 'true',
|
204
|
+
};
|
204
205
|
|
205
|
-
|
206
|
+
const bindHost = getBindHost();
|
206
207
|
|
207
|
-
|
208
|
+
const ExposedPorts: { [key: string]: any } = {};
|
208
209
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
210
|
+
_.forEach(ports, (portInfo: any, containerPort) => {
|
211
|
+
ExposedPorts['' + containerPort] = {};
|
212
|
+
PortBindings['' + containerPort] = [
|
213
|
+
{
|
214
|
+
HostPort: '' + portInfo.hostPort,
|
215
|
+
HostIp: bindHost,
|
216
|
+
},
|
217
|
+
];
|
217
218
|
|
218
|
-
|
219
|
-
|
219
|
+
Labels[CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
|
220
|
+
});
|
220
221
|
|
221
|
-
|
222
|
+
const Mounts = containerManager.toDockerMounts(mounts);
|
222
223
|
|
223
|
-
|
224
|
-
|
225
|
-
|
224
|
+
_.forEach(operatorData.env, (value, name) => {
|
225
|
+
Env.push(name + '=' + value);
|
226
|
+
});
|
226
227
|
|
227
|
-
|
228
|
+
let HealthCheck = undefined;
|
228
229
|
|
229
|
-
|
230
|
-
|
231
|
-
|
230
|
+
if (operatorData.health) {
|
231
|
+
HealthCheck = containerManager.toDockerHealth(operatorData.health);
|
232
|
+
}
|
232
233
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
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
|
+
});
|
247
248
|
|
248
|
-
|
249
|
+
return new ContainerInfo(container);
|
250
|
+
});
|
249
251
|
}
|
250
252
|
}
|
251
253
|
|
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,10 +407,9 @@ 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) {
|
@@ -424,16 +418,12 @@ export class BlockInstanceRunner {
|
|
424
418
|
await containerManager.waitForReady(container);
|
425
419
|
|
426
420
|
return this._handleContainer(container);
|
427
|
-
|
428
421
|
}
|
429
422
|
|
430
|
-
private async _handleContainer(
|
431
|
-
container: Container
|
432
|
-
): Promise<ProcessInfo> {
|
433
|
-
|
423
|
+
private async _handleContainer(container: Container): Promise<ProcessInfo> {
|
434
424
|
return {
|
435
425
|
type: InstanceType.DOCKER,
|
436
|
-
pid: container.id
|
426
|
+
pid: container.id,
|
437
427
|
};
|
438
428
|
}
|
439
429
|
}
|
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
|
|