@kapeta/local-cluster-service 0.9.1 → 0.10.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/dist/cjs/src/containerManager.d.ts +4 -8
- package/dist/cjs/src/containerManager.js +69 -64
- package/dist/cjs/src/instanceManager.js +4 -2
- package/dist/cjs/src/operatorManager.js +40 -25
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +1 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +77 -169
- package/dist/esm/src/containerManager.d.ts +4 -8
- package/dist/esm/src/containerManager.js +69 -64
- package/dist/esm/src/instanceManager.js +4 -2
- package/dist/esm/src/operatorManager.js +42 -27
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.js +77 -169
- package/package.json +1 -1
- package/src/containerManager.ts +69 -73
- package/src/instanceManager.ts +8 -2
- package/src/operatorManager.ts +52 -26
- package/src/utils/BlockInstanceRunner.ts +86 -176
package/src/containerManager.ts
CHANGED
@@ -7,8 +7,8 @@ import { Docker } from 'node-docker-api';
|
|
7
7
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
8
8
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
9
9
|
import { Container } from 'node-docker-api/lib/container';
|
10
|
-
import
|
11
|
-
import
|
10
|
+
import uuid from 'node-uuid';
|
11
|
+
import md5 from 'md5';
|
12
12
|
|
13
13
|
type StringMap = { [key: string]: string };
|
14
14
|
|
@@ -54,7 +54,7 @@ interface Health {
|
|
54
54
|
retries?: number;
|
55
55
|
}
|
56
56
|
|
57
|
-
const
|
57
|
+
export const CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
|
58
58
|
const NANO_SECOND = 1000000;
|
59
59
|
const HEALTH_CHECK_INTERVAL = 3000;
|
60
60
|
const HEALTH_CHECK_MAX = 20;
|
@@ -206,24 +206,21 @@ class ContainerManager {
|
|
206
206
|
tag = 'latest';
|
207
207
|
}
|
208
208
|
|
209
|
-
if (
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
return;
|
214
|
-
}
|
209
|
+
if (IMAGE_PULL_CACHE[image]) {
|
210
|
+
const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
|
211
|
+
if (timeSince < cacheForMS) {
|
212
|
+
return false;
|
215
213
|
}
|
214
|
+
}
|
216
215
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
216
|
+
const imageTagList = (await this.docker().image.list())
|
217
|
+
.map((image) => image.data as any)
|
218
|
+
.filter((imageData) => !!imageData.RepoTags)
|
219
|
+
.map((imageData) => imageData.RepoTags as string[]);
|
221
220
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
}
|
226
|
-
console.log('Image not found: %s', image);
|
221
|
+
if (imageTagList.some((imageTags) => imageTags.indexOf(image) > -1)) {
|
222
|
+
console.log('Image found: %s', image);
|
223
|
+
return false;
|
227
224
|
}
|
228
225
|
|
229
226
|
console.log('Pulling image: %s', image);
|
@@ -240,6 +237,8 @@ class ContainerManager {
|
|
240
237
|
IMAGE_PULL_CACHE[image] = Date.now();
|
241
238
|
|
242
239
|
console.log('Image pulled: %s', image);
|
240
|
+
|
241
|
+
return true;
|
243
242
|
}
|
244
243
|
|
245
244
|
toDockerMounts(mounts: StringMap) {
|
@@ -266,66 +265,63 @@ class ContainerManager {
|
|
266
265
|
};
|
267
266
|
}
|
268
267
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
): Promise<ContainerInfo> {
|
274
|
-
const PortBindings: { [key: string]: any } = {};
|
275
|
-
const Env: string[] = [];
|
276
|
-
const Labels: StringMap = {
|
277
|
-
kapeta: 'true',
|
278
|
-
};
|
279
|
-
|
280
|
-
await this.pull(image);
|
281
|
-
|
282
|
-
const bindHost = getBindHost();
|
268
|
+
private applyHash(dockerOpts: any) {
|
269
|
+
if (dockerOpts?.Labels?.HASH) {
|
270
|
+
delete dockerOpts.Labels.HASH;
|
271
|
+
}
|
283
272
|
|
284
|
-
const
|
273
|
+
const hash = md5(JSON.stringify(dockerOpts));
|
285
274
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
HostIp: bindHost,
|
292
|
-
},
|
293
|
-
];
|
275
|
+
if (!dockerOpts.Labels) {
|
276
|
+
dockerOpts.Labels = {};
|
277
|
+
}
|
278
|
+
dockerOpts.Labels.HASH = hash;
|
279
|
+
}
|
294
280
|
|
295
|
-
|
296
|
-
|
281
|
+
async ensureContainer(opts: any) {
|
282
|
+
let imagePulled = false;
|
283
|
+
try {
|
284
|
+
imagePulled = await this.pull(opts.Image);
|
285
|
+
} catch (e) {
|
286
|
+
console.warn('Failed to pull image. Continuing...', e);
|
287
|
+
}
|
297
288
|
|
298
|
-
|
289
|
+
this.applyHash(opts);
|
290
|
+
if (!opts.name) {
|
291
|
+
console.log('Starting unnamed container: %s', opts.Image);
|
292
|
+
return this.startContainer(opts);
|
293
|
+
}
|
294
|
+
const containerInfo = await this.getContainerByName(opts.name);
|
295
|
+
if (imagePulled) {
|
296
|
+
console.log('New version of image was pulled: %s', opts.Image);
|
297
|
+
} else {
|
298
|
+
// If image was pulled always recreate
|
299
|
+
if (!containerInfo) {
|
300
|
+
console.log('Starting new container: %s', opts.name);
|
301
|
+
return this.startContainer(opts);
|
302
|
+
}
|
299
303
|
|
300
|
-
|
301
|
-
Env.push(name + '=' + value);
|
302
|
-
});
|
304
|
+
const containerData = containerInfo.native.data as any;
|
303
305
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
Cmd: opts.cmd,
|
315
|
-
ExposedPorts,
|
316
|
-
Env,
|
317
|
-
HealthCheck,
|
318
|
-
HostConfig: {
|
319
|
-
PortBindings,
|
320
|
-
Mounts,
|
321
|
-
},
|
322
|
-
});
|
306
|
+
if (containerData?.Labels?.HASH === opts.Labels.HASH) {
|
307
|
+
if (!(await containerInfo.isRunning())) {
|
308
|
+
console.log('Starting previously created container: %s', opts.name);
|
309
|
+
await containerInfo.start();
|
310
|
+
} else {
|
311
|
+
console.log('Previously created container already running: %s', opts.name);
|
312
|
+
}
|
313
|
+
return containerInfo.native;
|
314
|
+
}
|
315
|
+
}
|
323
316
|
|
324
|
-
if (
|
325
|
-
|
317
|
+
if (containerInfo) {
|
318
|
+
// Remove the container and start a new one
|
319
|
+
console.log('Replacing previously created container: %s', opts.name);
|
320
|
+
await containerInfo.remove({ force: true });
|
326
321
|
}
|
327
322
|
|
328
|
-
|
323
|
+
console.log('Starting new container: %s', opts.name);
|
324
|
+
return this.startContainer(opts);
|
329
325
|
}
|
330
326
|
|
331
327
|
async startContainer(opts: any) {
|
@@ -423,8 +419,8 @@ class ContainerManager {
|
|
423
419
|
}
|
424
420
|
}
|
425
421
|
|
426
|
-
async remove(container:Container, opts?: { force?: boolean }) {
|
427
|
-
const newName = 'deleting-' + uuid.v4()
|
422
|
+
async remove(container: Container, opts?: { force?: boolean }) {
|
423
|
+
const newName = 'deleting-' + uuid.v4();
|
428
424
|
const containerData = container.data as any;
|
429
425
|
// Rename the container first to avoid name conflicts if people start the same container
|
430
426
|
await container.rename({ name: newName });
|
@@ -537,11 +533,11 @@ export class ContainerInfo {
|
|
537
533
|
const ports: PortMap = {};
|
538
534
|
|
539
535
|
_.forEach(inspectResult.Config.Labels, (portType, name) => {
|
540
|
-
if (!name.startsWith(
|
536
|
+
if (!name.startsWith(CONTAINER_LABEL_PORT_PREFIX)) {
|
541
537
|
return;
|
542
538
|
}
|
543
539
|
|
544
|
-
const hostPort = name.substr(
|
540
|
+
const hostPort = name.substr(CONTAINER_LABEL_PORT_PREFIX.length);
|
545
541
|
|
546
542
|
portTypes[hostPort] = portType;
|
547
543
|
});
|
package/src/instanceManager.ts
CHANGED
@@ -559,7 +559,10 @@ export class InstanceManager {
|
|
559
559
|
}
|
560
560
|
}
|
561
561
|
|
562
|
-
if (
|
562
|
+
if (
|
563
|
+
instance.desiredStatus === DesiredInstanceStatus.RUN &&
|
564
|
+
[InstanceStatus.STOPPED, InstanceStatus.FAILED, InstanceStatus.STOPPING].includes(newStatus)
|
565
|
+
) {
|
563
566
|
//If the instance is stopped but we want it to run, start it
|
564
567
|
try {
|
565
568
|
await this.start(instance.systemId, instance.instanceId);
|
@@ -569,7 +572,10 @@ export class InstanceManager {
|
|
569
572
|
return;
|
570
573
|
}
|
571
574
|
|
572
|
-
if (
|
575
|
+
if (
|
576
|
+
instance.desiredStatus === DesiredInstanceStatus.STOP &&
|
577
|
+
[InstanceStatus.READY, InstanceStatus.STARTING, InstanceStatus.UNHEALTHY].includes(newStatus)
|
578
|
+
) {
|
573
579
|
//If the instance is running but we want it to stop, stop it
|
574
580
|
try {
|
575
581
|
await this.stop(instance.systemId, instance.instanceId);
|
package/src/operatorManager.ts
CHANGED
@@ -4,12 +4,14 @@ 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 { ContainerInfo, containerManager } from './containerManager';
|
7
|
+
import { CONTAINER_LABEL_PORT_PREFIX, ContainerInfo, containerManager } from './containerManager';
|
8
8
|
import FSExtra from 'fs-extra';
|
9
|
-
import { AnyMap, EnvironmentType, OperatorInfo } from './types';
|
9
|
+
import { AnyMap, EnvironmentType, OperatorInfo, StringMap } from './types';
|
10
10
|
import { BlockInstance, Resource } from '@kapeta/schemas';
|
11
11
|
import { definitionsManager } from './definitionsManager';
|
12
|
-
import { normalizeKapetaUri } from './utils/utils';
|
12
|
+
import { getBindHost, normalizeKapetaUri } from './utils/utils';
|
13
|
+
import _ from 'lodash';
|
14
|
+
import { Container } from 'node-docker-api/lib/container';
|
13
15
|
|
14
16
|
const KIND_OPERATOR = 'core/resource-type-operator';
|
15
17
|
|
@@ -191,34 +193,58 @@ class OperatorManager {
|
|
191
193
|
const mounts = containerManager.createMounts(resourceType, operatorData.mounts);
|
192
194
|
|
193
195
|
const containerName = containerBaseName + '-' + md5(nameParts.join('_'));
|
194
|
-
let container = await containerManager.get(containerName);
|
195
196
|
|
196
|
-
const
|
197
|
-
|
198
|
-
await container.start();
|
199
|
-
}
|
197
|
+
const PortBindings: { [key: string]: any } = {};
|
198
|
+
const Env: string[] = [];
|
200
199
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
ports,
|
205
|
-
health: operatorData.health,
|
206
|
-
env: operatorData.env,
|
207
|
-
cmd: operatorData.cmd,
|
208
|
-
});
|
209
|
-
}
|
200
|
+
const Labels: StringMap = {
|
201
|
+
kapeta: 'true',
|
202
|
+
};
|
210
203
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
}
|
217
|
-
|
218
|
-
|
204
|
+
const bindHost = getBindHost();
|
205
|
+
|
206
|
+
const ExposedPorts: { [key: string]: any } = {};
|
207
|
+
|
208
|
+
_.forEach(ports, (portInfo: any, containerPort) => {
|
209
|
+
ExposedPorts['' + containerPort] = {};
|
210
|
+
PortBindings['' + containerPort] = [
|
211
|
+
{
|
212
|
+
HostPort: '' + portInfo.hostPort,
|
213
|
+
HostIp: bindHost,
|
214
|
+
},
|
215
|
+
];
|
216
|
+
|
217
|
+
Labels[CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
|
218
|
+
});
|
219
|
+
|
220
|
+
const Mounts = containerManager.toDockerMounts(mounts);
|
221
|
+
|
222
|
+
_.forEach(operatorData.env, (value, name) => {
|
223
|
+
Env.push(name + '=' + value);
|
224
|
+
});
|
225
|
+
|
226
|
+
let HealthCheck = undefined;
|
227
|
+
|
228
|
+
if (operatorData.health) {
|
229
|
+
HealthCheck = containerManager.toDockerHealth(operatorData.health);
|
219
230
|
}
|
220
231
|
|
221
|
-
|
232
|
+
const container = await containerManager.ensureContainer({
|
233
|
+
name: containerName,
|
234
|
+
Image: operatorData.image,
|
235
|
+
Hostname: containerName + '.kapeta',
|
236
|
+
Labels,
|
237
|
+
Cmd: operatorData.cmd,
|
238
|
+
ExposedPorts,
|
239
|
+
Env,
|
240
|
+
HealthCheck,
|
241
|
+
HostConfig: {
|
242
|
+
PortBindings,
|
243
|
+
Mounts,
|
244
|
+
},
|
245
|
+
});
|
246
|
+
|
247
|
+
return new ContainerInfo(container);
|
222
248
|
}
|
223
249
|
}
|
224
250
|
|
@@ -7,9 +7,10 @@ import { containerManager, DockerMounts, toLocalBindVolume } from '../containerM
|
|
7
7
|
import { LogData } from './LogData';
|
8
8
|
import EventEmitter from 'events';
|
9
9
|
import { clusterService } from '../clusterService';
|
10
|
-
import { AnyMap, BlockProcessParams,
|
10
|
+
import { AnyMap, BlockProcessParams, InstanceType, ProcessInfo, StringMap } from '../types';
|
11
11
|
import { Container } from 'node-docker-api/lib/container';
|
12
12
|
import { definitionsManager } from '../definitionsManager';
|
13
|
+
import md5 from 'md5';
|
13
14
|
|
14
15
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
15
16
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
@@ -169,29 +170,6 @@ export class BlockInstanceRunner {
|
|
169
170
|
}
|
170
171
|
|
171
172
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
172
|
-
const logs = new LogData();
|
173
|
-
logs.addLog(`Starting block ${blockInstance.ref}`);
|
174
|
-
let containerInfo = await containerManager.getContainerByName(containerName);
|
175
|
-
let container = containerInfo?.native;
|
176
|
-
|
177
|
-
console.log('Starting dev container', containerName);
|
178
|
-
|
179
|
-
if (containerInfo) {
|
180
|
-
console.log(`Dev container already exists. Deleting...`);
|
181
|
-
try {
|
182
|
-
await containerInfo.remove({
|
183
|
-
force: true,
|
184
|
-
});
|
185
|
-
} catch (e: any) {
|
186
|
-
throw new Error('Failed to delete existing container: ' + e.message);
|
187
|
-
}
|
188
|
-
container = undefined;
|
189
|
-
containerInfo = undefined;
|
190
|
-
}
|
191
|
-
|
192
|
-
logs.addLog(`Creating new container for block: ${containerName}`);
|
193
|
-
console.log('Creating new dev container', containerName, dockerImage);
|
194
|
-
await containerManager.pull(dockerImage);
|
195
173
|
|
196
174
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
197
175
|
const dockerOpts = localContainer.options ?? {};
|
@@ -228,8 +206,7 @@ export class BlockInstanceRunner {
|
|
228
206
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
229
207
|
}
|
230
208
|
|
231
|
-
|
232
|
-
container = await containerManager.startContainer({
|
209
|
+
return this.ensureContainer({
|
233
210
|
Image: dockerImage,
|
234
211
|
name: containerName,
|
235
212
|
WorkingDir: workingDir,
|
@@ -256,9 +233,15 @@ export class BlockInstanceRunner {
|
|
256
233
|
},
|
257
234
|
...dockerOpts,
|
258
235
|
});
|
236
|
+
}
|
237
|
+
|
238
|
+
private async ensureContainer(opts: any) {
|
239
|
+
const logs = new LogData();
|
240
|
+
|
241
|
+
const container = await containerManager.ensureContainer(opts);
|
259
242
|
|
260
243
|
try {
|
261
|
-
if (HealthCheck) {
|
244
|
+
if (opts.HealthCheck) {
|
262
245
|
await containerManager.waitForHealthy(container);
|
263
246
|
} else {
|
264
247
|
await containerManager.waitForReady(container);
|
@@ -352,47 +335,25 @@ export class BlockInstanceRunner {
|
|
352
335
|
|
353
336
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
354
337
|
const logs = new LogData();
|
355
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
356
|
-
let container = containerInfo?.native;
|
357
338
|
|
358
339
|
// For windows we need to default to root
|
359
340
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
360
341
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
instance: blockInstance.id,
|
377
|
-
},
|
378
|
-
Env: [
|
379
|
-
...DOCKER_ENV_VARS,
|
380
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
381
|
-
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
382
|
-
],
|
383
|
-
HostConfig: {
|
384
|
-
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
385
|
-
},
|
386
|
-
});
|
387
|
-
|
388
|
-
try {
|
389
|
-
await containerManager.waitForReady(container);
|
390
|
-
} catch (e: any) {
|
391
|
-
logs.addLog(e.message, 'ERROR');
|
392
|
-
}
|
393
|
-
}
|
394
|
-
|
395
|
-
return this._handleContainer(container, logs);
|
342
|
+
return this.ensureContainer({
|
343
|
+
Image: dockerImage,
|
344
|
+
name: containerName,
|
345
|
+
Labels: {
|
346
|
+
instance: blockInstance.id,
|
347
|
+
},
|
348
|
+
Env: [
|
349
|
+
...DOCKER_ENV_VARS,
|
350
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
351
|
+
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
352
|
+
],
|
353
|
+
HostConfig: {
|
354
|
+
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
355
|
+
},
|
356
|
+
});
|
396
357
|
}
|
397
358
|
|
398
359
|
/**
|
@@ -430,130 +391,79 @@ export class BlockInstanceRunner {
|
|
430
391
|
|
431
392
|
const dockerImage = spec?.local?.image;
|
432
393
|
|
433
|
-
try {
|
434
|
-
await containerManager.pull(dockerImage);
|
435
|
-
} catch (e) {
|
436
|
-
console.warn('Failed to pull image. Continuing...', e);
|
437
|
-
}
|
438
|
-
|
439
394
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
440
395
|
const logs = new LogData();
|
441
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
442
|
-
let container = containerInfo?.native;
|
443
|
-
|
444
|
-
if (container) {
|
445
|
-
const containerData = container.data as any;
|
446
|
-
if (containerData.State === 'running') {
|
447
|
-
logs.addLog(`Found existing running container for block: ${containerName}`);
|
448
|
-
} else {
|
449
|
-
if (containerData.State?.ExitCode > 0) {
|
450
|
-
logs.addLog(`Container exited with code: ${containerData.State.ExitCode}. Deleting...`);
|
451
|
-
try {
|
452
|
-
await containerManager.remove(container);
|
453
|
-
} catch (e) {}
|
454
|
-
container = undefined;
|
455
|
-
} else {
|
456
|
-
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
457
|
-
try {
|
458
|
-
await container.start();
|
459
|
-
} catch (e) {
|
460
|
-
console.warn('Failed to start container. Deleting...', e);
|
461
|
-
try {
|
462
|
-
await containerManager.remove(container);
|
463
|
-
} catch (e) {}
|
464
|
-
container = undefined;
|
465
|
-
}
|
466
|
-
}
|
467
|
-
}
|
468
|
-
}
|
469
396
|
|
470
397
|
const bindHost = getBindHost();
|
471
398
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
{
|
490
|
-
HostIp: bindHost,
|
491
|
-
HostPort: `${publicPort}`,
|
492
|
-
},
|
493
|
-
];
|
494
|
-
}
|
495
|
-
);
|
496
|
-
|
497
|
-
await Promise.all(promises);
|
498
|
-
|
499
|
-
if (spec.local?.env) {
|
500
|
-
Object.entries(spec.local.env).forEach(([key, value]) => {
|
501
|
-
addonEnv[key] = value as string;
|
502
|
-
});
|
503
|
-
}
|
504
|
-
|
505
|
-
if (spec.local?.mounts) {
|
506
|
-
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
507
|
-
Mounts = containerManager.toDockerMounts(mounts);
|
399
|
+
const ExposedPorts: AnyMap = {};
|
400
|
+
const addonEnv: StringMap = {};
|
401
|
+
const PortBindings: AnyMap = {};
|
402
|
+
let HealthCheck = undefined;
|
403
|
+
let Mounts: DockerMounts[] = [];
|
404
|
+
const promises = Object.entries(spec.local.ports as { [p: string]: { port: string; type: string } }).map(
|
405
|
+
async ([portType, value]) => {
|
406
|
+
const dockerPort = `${value.port}/${value.type}`;
|
407
|
+
ExposedPorts[dockerPort] = {};
|
408
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
409
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
410
|
+
PortBindings[dockerPort] = [
|
411
|
+
{
|
412
|
+
HostIp: bindHost,
|
413
|
+
HostPort: `${publicPort}`,
|
414
|
+
},
|
415
|
+
];
|
508
416
|
}
|
417
|
+
);
|
509
418
|
|
510
|
-
|
511
|
-
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
512
|
-
}
|
419
|
+
await Promise.all(promises);
|
513
420
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
logs.addLog(`Creating new container for block: ${containerName}`);
|
518
|
-
container = await containerManager.startContainer({
|
519
|
-
Image: dockerImage,
|
520
|
-
name: containerName,
|
521
|
-
ExposedPorts,
|
522
|
-
HealthCheck,
|
523
|
-
HostConfig: {
|
524
|
-
Binds: [
|
525
|
-
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
526
|
-
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
527
|
-
],
|
528
|
-
PortBindings,
|
529
|
-
Mounts,
|
530
|
-
},
|
531
|
-
Labels: {
|
532
|
-
instance: blockInstance.id,
|
533
|
-
},
|
534
|
-
Env: [
|
535
|
-
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
536
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
537
|
-
...DOCKER_ENV_VARS,
|
538
|
-
...Object.entries({
|
539
|
-
...env,
|
540
|
-
...addonEnv,
|
541
|
-
}).map(([key, value]) => `${key}=${value}`),
|
542
|
-
],
|
421
|
+
if (spec.local?.env) {
|
422
|
+
Object.entries(spec.local.env).forEach(([key, value]) => {
|
423
|
+
addonEnv[key] = value as string;
|
543
424
|
});
|
425
|
+
}
|
544
426
|
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
} else {
|
549
|
-
await containerManager.waitForReady(container);
|
550
|
-
}
|
551
|
-
} catch (e: any) {
|
552
|
-
logs.addLog(e.message, 'ERROR');
|
553
|
-
}
|
427
|
+
if (spec.local?.mounts) {
|
428
|
+
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
429
|
+
Mounts = containerManager.toDockerMounts(mounts);
|
554
430
|
}
|
555
431
|
|
556
|
-
|
432
|
+
if (spec.local?.health) {
|
433
|
+
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
434
|
+
}
|
435
|
+
|
436
|
+
// For windows we need to default to root
|
437
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
438
|
+
|
439
|
+
logs.addLog(`Creating new container for block: ${containerName}`);
|
440
|
+
const out = await this.ensureContainer({
|
441
|
+
Image: dockerImage,
|
442
|
+
name: containerName,
|
443
|
+
ExposedPorts,
|
444
|
+
HealthCheck,
|
445
|
+
HostConfig: {
|
446
|
+
Binds: [
|
447
|
+
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
448
|
+
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
449
|
+
],
|
450
|
+
PortBindings,
|
451
|
+
Mounts,
|
452
|
+
},
|
453
|
+
Labels: {
|
454
|
+
instance: blockInstance.id,
|
455
|
+
},
|
456
|
+
Env: [
|
457
|
+
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
458
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
459
|
+
...DOCKER_ENV_VARS,
|
460
|
+
...Object.entries({
|
461
|
+
...env,
|
462
|
+
...addonEnv,
|
463
|
+
}).map(([key, value]) => `${key}=${value}`),
|
464
|
+
],
|
465
|
+
});
|
466
|
+
|
557
467
|
const portTypes = spec.local.ports ? Object.keys(spec.local.ports) : [];
|
558
468
|
if (portTypes.length > 0) {
|
559
469
|
out.portType = portTypes[0];
|