@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
@@ -6,9 +6,9 @@ import FSExtra from 'fs-extra';
|
|
6
6
|
import { Docker } from 'node-docker-api';
|
7
7
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
8
8
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
9
|
-
import
|
10
|
-
import
|
11
|
-
const
|
9
|
+
import uuid from 'node-uuid';
|
10
|
+
import md5 from 'md5';
|
11
|
+
export const CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
|
12
12
|
const NANO_SECOND = 1000000;
|
13
13
|
const HEALTH_CHECK_INTERVAL = 3000;
|
14
14
|
const HEALTH_CHECK_MAX = 20;
|
@@ -141,22 +141,19 @@ class ContainerManager {
|
|
141
141
|
if (!tag) {
|
142
142
|
tag = 'latest';
|
143
143
|
}
|
144
|
-
if (
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
return;
|
149
|
-
}
|
150
|
-
}
|
151
|
-
const imageTagList = (await this.docker().image.list())
|
152
|
-
.map((image) => image.data)
|
153
|
-
.filter((imageData) => !!imageData.RepoTags)
|
154
|
-
.map((imageData) => imageData.RepoTags);
|
155
|
-
if (imageTagList.some((imageTags) => imageTags.indexOf(image) > -1)) {
|
156
|
-
console.log('Image found: %s', image);
|
157
|
-
return;
|
144
|
+
if (IMAGE_PULL_CACHE[image]) {
|
145
|
+
const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
|
146
|
+
if (timeSince < cacheForMS) {
|
147
|
+
return false;
|
158
148
|
}
|
159
|
-
|
149
|
+
}
|
150
|
+
const imageTagList = (await this.docker().image.list())
|
151
|
+
.map((image) => image.data)
|
152
|
+
.filter((imageData) => !!imageData.RepoTags)
|
153
|
+
.map((imageData) => imageData.RepoTags);
|
154
|
+
if (imageTagList.some((imageTags) => imageTags.indexOf(image) > -1)) {
|
155
|
+
console.log('Image found: %s', image);
|
156
|
+
return false;
|
160
157
|
}
|
161
158
|
console.log('Pulling image: %s', image);
|
162
159
|
await this.docker()
|
@@ -167,6 +164,7 @@ class ContainerManager {
|
|
167
164
|
.then((stream) => promisifyStream(stream));
|
168
165
|
IMAGE_PULL_CACHE[image] = Date.now();
|
169
166
|
console.log('Image pulled: %s', image);
|
167
|
+
return true;
|
170
168
|
}
|
171
169
|
toDockerMounts(mounts) {
|
172
170
|
const Mounts = [];
|
@@ -189,51 +187,58 @@ class ContainerManager {
|
|
189
187
|
Retries: health.retries || 10,
|
190
188
|
};
|
191
189
|
}
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
const Labels = {
|
196
|
-
kapeta: 'true',
|
197
|
-
};
|
198
|
-
await this.pull(image);
|
199
|
-
const bindHost = getBindHost();
|
200
|
-
const ExposedPorts = {};
|
201
|
-
_.forEach(opts.ports, (portInfo, containerPort) => {
|
202
|
-
ExposedPorts['' + containerPort] = {};
|
203
|
-
PortBindings['' + containerPort] = [
|
204
|
-
{
|
205
|
-
HostPort: '' + portInfo.hostPort,
|
206
|
-
HostIp: bindHost,
|
207
|
-
},
|
208
|
-
];
|
209
|
-
Labels[LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
|
210
|
-
});
|
211
|
-
const Mounts = this.toDockerMounts(opts.mounts);
|
212
|
-
_.forEach(opts.env, (value, name) => {
|
213
|
-
Env.push(name + '=' + value);
|
214
|
-
});
|
215
|
-
let HealthCheck = undefined;
|
216
|
-
if (opts.health) {
|
217
|
-
HealthCheck = this.toDockerHealth(opts.health);
|
218
|
-
}
|
219
|
-
const dockerContainer = await this.startContainer({
|
220
|
-
name: name,
|
221
|
-
Image: image,
|
222
|
-
Hostname: name + '.kapeta',
|
223
|
-
Labels,
|
224
|
-
Cmd: opts.cmd,
|
225
|
-
ExposedPorts,
|
226
|
-
Env,
|
227
|
-
HealthCheck,
|
228
|
-
HostConfig: {
|
229
|
-
PortBindings,
|
230
|
-
Mounts,
|
231
|
-
},
|
232
|
-
});
|
233
|
-
if (opts.health) {
|
234
|
-
await this.waitForHealthy(dockerContainer);
|
190
|
+
applyHash(dockerOpts) {
|
191
|
+
if (dockerOpts?.Labels?.HASH) {
|
192
|
+
delete dockerOpts.Labels.HASH;
|
235
193
|
}
|
236
|
-
|
194
|
+
const hash = md5(JSON.stringify(dockerOpts));
|
195
|
+
if (!dockerOpts.Labels) {
|
196
|
+
dockerOpts.Labels = {};
|
197
|
+
}
|
198
|
+
dockerOpts.Labels.HASH = hash;
|
199
|
+
}
|
200
|
+
async ensureContainer(opts) {
|
201
|
+
let imagePulled = false;
|
202
|
+
try {
|
203
|
+
imagePulled = await this.pull(opts.Image);
|
204
|
+
}
|
205
|
+
catch (e) {
|
206
|
+
console.warn('Failed to pull image. Continuing...', e);
|
207
|
+
}
|
208
|
+
this.applyHash(opts);
|
209
|
+
if (!opts.name) {
|
210
|
+
console.log('Starting unnamed container: %s', opts.Image);
|
211
|
+
return this.startContainer(opts);
|
212
|
+
}
|
213
|
+
const containerInfo = await this.getContainerByName(opts.name);
|
214
|
+
if (imagePulled) {
|
215
|
+
console.log('New version of image was pulled: %s', opts.Image);
|
216
|
+
}
|
217
|
+
else {
|
218
|
+
// If image was pulled always recreate
|
219
|
+
if (!containerInfo) {
|
220
|
+
console.log('Starting new container: %s', opts.name);
|
221
|
+
return this.startContainer(opts);
|
222
|
+
}
|
223
|
+
const containerData = containerInfo.native.data;
|
224
|
+
if (containerData?.Labels?.HASH === opts.Labels.HASH) {
|
225
|
+
if (!(await containerInfo.isRunning())) {
|
226
|
+
console.log('Starting previously created container: %s', opts.name);
|
227
|
+
await containerInfo.start();
|
228
|
+
}
|
229
|
+
else {
|
230
|
+
console.log('Previously created container already running: %s', opts.name);
|
231
|
+
}
|
232
|
+
return containerInfo.native;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
if (containerInfo) {
|
236
|
+
// Remove the container and start a new one
|
237
|
+
console.log('Replacing previously created container: %s', opts.name);
|
238
|
+
await containerInfo.remove({ force: true });
|
239
|
+
}
|
240
|
+
console.log('Starting new container: %s', opts.name);
|
241
|
+
return this.startContainer(opts);
|
237
242
|
}
|
238
243
|
async startContainer(opts) {
|
239
244
|
const extraHosts = getExtraHosts(this._version);
|
@@ -411,10 +416,10 @@ export class ContainerInfo {
|
|
411
416
|
const portTypes = {};
|
412
417
|
const ports = {};
|
413
418
|
_.forEach(inspectResult.Config.Labels, (portType, name) => {
|
414
|
-
if (!name.startsWith(
|
419
|
+
if (!name.startsWith(CONTAINER_LABEL_PORT_PREFIX)) {
|
415
420
|
return;
|
416
421
|
}
|
417
|
-
const hostPort = name.substr(
|
422
|
+
const hostPort = name.substr(CONTAINER_LABEL_PORT_PREFIX.length);
|
418
423
|
portTypes[hostPort] = portType;
|
419
424
|
});
|
420
425
|
_.forEach(inspectResult.HostConfig.PortBindings, (portBindings, containerPortSpec) => {
|
@@ -447,7 +447,8 @@ export class InstanceManager {
|
|
447
447
|
changed = true;
|
448
448
|
}
|
449
449
|
}
|
450
|
-
if (instance.desiredStatus === DesiredInstanceStatus.RUN &&
|
450
|
+
if (instance.desiredStatus === DesiredInstanceStatus.RUN &&
|
451
|
+
[InstanceStatus.STOPPED, InstanceStatus.FAILED, InstanceStatus.STOPPING].includes(newStatus)) {
|
451
452
|
//If the instance is stopped but we want it to run, start it
|
452
453
|
try {
|
453
454
|
await this.start(instance.systemId, instance.instanceId);
|
@@ -457,7 +458,8 @@ export class InstanceManager {
|
|
457
458
|
}
|
458
459
|
return;
|
459
460
|
}
|
460
|
-
if (instance.desiredStatus === DesiredInstanceStatus.STOP &&
|
461
|
+
if (instance.desiredStatus === DesiredInstanceStatus.STOP &&
|
462
|
+
[InstanceStatus.READY, InstanceStatus.STARTING, InstanceStatus.UNHEALTHY].includes(newStatus)) {
|
461
463
|
//If the instance is running but we want it to stop, stop it
|
462
464
|
try {
|
463
465
|
await this.stop(instance.systemId, instance.instanceId);
|
@@ -3,10 +3,11 @@ import md5 from 'md5';
|
|
3
3
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
4
4
|
import { serviceManager } from './serviceManager';
|
5
5
|
import { storageService } from './storageService';
|
6
|
-
import { containerManager } from './containerManager';
|
6
|
+
import { CONTAINER_LABEL_PORT_PREFIX, ContainerInfo, containerManager } from './containerManager';
|
7
7
|
import FSExtra from 'fs-extra';
|
8
8
|
import { definitionsManager } from './definitionsManager';
|
9
|
-
import { normalizeKapetaUri } from './utils/utils';
|
9
|
+
import { getBindHost, normalizeKapetaUri } from './utils/utils';
|
10
|
+
import _ from 'lodash';
|
10
11
|
const KIND_OPERATOR = 'core/resource-type-operator';
|
11
12
|
class Operator {
|
12
13
|
_data;
|
@@ -132,32 +133,46 @@ class OperatorManager {
|
|
132
133
|
}
|
133
134
|
const mounts = containerManager.createMounts(resourceType, operatorData.mounts);
|
134
135
|
const containerName = containerBaseName + '-' + md5(nameParts.join('_'));
|
135
|
-
|
136
|
-
const
|
137
|
-
|
138
|
-
|
139
|
-
}
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
136
|
+
const PortBindings = {};
|
137
|
+
const Env = [];
|
138
|
+
const Labels = {
|
139
|
+
kapeta: 'true',
|
140
|
+
};
|
141
|
+
const bindHost = getBindHost();
|
142
|
+
const ExposedPorts = {};
|
143
|
+
_.forEach(ports, (portInfo, containerPort) => {
|
144
|
+
ExposedPorts['' + containerPort] = {};
|
145
|
+
PortBindings['' + containerPort] = [
|
146
|
+
{
|
147
|
+
HostPort: '' + portInfo.hostPort,
|
148
|
+
HostIp: bindHost,
|
149
|
+
},
|
150
|
+
];
|
151
|
+
Labels[CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
|
152
|
+
});
|
153
|
+
const Mounts = containerManager.toDockerMounts(mounts);
|
154
|
+
_.forEach(operatorData.env, (value, name) => {
|
155
|
+
Env.push(name + '=' + value);
|
156
|
+
});
|
157
|
+
let HealthCheck = undefined;
|
158
|
+
if (operatorData.health) {
|
159
|
+
HealthCheck = containerManager.toDockerHealth(operatorData.health);
|
159
160
|
}
|
160
|
-
|
161
|
+
const container = await containerManager.ensureContainer({
|
162
|
+
name: containerName,
|
163
|
+
Image: operatorData.image,
|
164
|
+
Hostname: containerName + '.kapeta',
|
165
|
+
Labels,
|
166
|
+
Cmd: operatorData.cmd,
|
167
|
+
ExposedPorts,
|
168
|
+
Env,
|
169
|
+
HealthCheck,
|
170
|
+
HostConfig: {
|
171
|
+
PortBindings,
|
172
|
+
Mounts,
|
173
|
+
},
|
174
|
+
});
|
175
|
+
return new ContainerInfo(container);
|
161
176
|
}
|
162
177
|
}
|
163
178
|
export const operatorManager = new OperatorManager();
|
@@ -128,27 +128,6 @@ export class BlockInstanceRunner {
|
|
128
128
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
129
129
|
}
|
130
130
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
131
|
-
const logs = new LogData();
|
132
|
-
logs.addLog(`Starting block ${blockInstance.ref}`);
|
133
|
-
let containerInfo = await containerManager.getContainerByName(containerName);
|
134
|
-
let container = containerInfo?.native;
|
135
|
-
console.log('Starting dev container', containerName);
|
136
|
-
if (containerInfo) {
|
137
|
-
console.log(`Dev container already exists. Deleting...`);
|
138
|
-
try {
|
139
|
-
await containerInfo.remove({
|
140
|
-
force: true,
|
141
|
-
});
|
142
|
-
}
|
143
|
-
catch (e) {
|
144
|
-
throw new Error('Failed to delete existing container: ' + e.message);
|
145
|
-
}
|
146
|
-
container = undefined;
|
147
|
-
containerInfo = undefined;
|
148
|
-
}
|
149
|
-
logs.addLog(`Creating new container for block: ${containerName}`);
|
150
|
-
console.log('Creating new dev container', containerName, dockerImage);
|
151
|
-
await containerManager.pull(dockerImage);
|
152
131
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
153
132
|
const dockerOpts = localContainer.options ?? {};
|
154
133
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
@@ -177,8 +156,7 @@ export class BlockInstanceRunner {
|
|
177
156
|
if (localContainer.healthcheck) {
|
178
157
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
179
158
|
}
|
180
|
-
|
181
|
-
container = await containerManager.startContainer({
|
159
|
+
return this.ensureContainer({
|
182
160
|
Image: dockerImage,
|
183
161
|
name: containerName,
|
184
162
|
WorkingDir: workingDir,
|
@@ -205,8 +183,12 @@ export class BlockInstanceRunner {
|
|
205
183
|
},
|
206
184
|
...dockerOpts,
|
207
185
|
});
|
186
|
+
}
|
187
|
+
async ensureContainer(opts) {
|
188
|
+
const logs = new LogData();
|
189
|
+
const container = await containerManager.ensureContainer(opts);
|
208
190
|
try {
|
209
|
-
if (HealthCheck) {
|
191
|
+
if (opts.HealthCheck) {
|
210
192
|
await containerManager.waitForHealthy(container);
|
211
193
|
}
|
212
194
|
else {
|
@@ -284,45 +266,23 @@ export class BlockInstanceRunner {
|
|
284
266
|
}
|
285
267
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
286
268
|
const logs = new LogData();
|
287
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
288
|
-
let container = containerInfo?.native;
|
289
269
|
// For windows we need to default to root
|
290
270
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
Labels: {
|
307
|
-
instance: blockInstance.id,
|
308
|
-
},
|
309
|
-
Env: [
|
310
|
-
...DOCKER_ENV_VARS,
|
311
|
-
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
312
|
-
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
313
|
-
],
|
314
|
-
HostConfig: {
|
315
|
-
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
316
|
-
},
|
317
|
-
});
|
318
|
-
try {
|
319
|
-
await containerManager.waitForReady(container);
|
320
|
-
}
|
321
|
-
catch (e) {
|
322
|
-
logs.addLog(e.message, 'ERROR');
|
323
|
-
}
|
324
|
-
}
|
325
|
-
return this._handleContainer(container, logs);
|
271
|
+
return this.ensureContainer({
|
272
|
+
Image: dockerImage,
|
273
|
+
name: containerName,
|
274
|
+
Labels: {
|
275
|
+
instance: blockInstance.id,
|
276
|
+
},
|
277
|
+
Env: [
|
278
|
+
...DOCKER_ENV_VARS,
|
279
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
280
|
+
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
281
|
+
],
|
282
|
+
HostConfig: {
|
283
|
+
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
284
|
+
},
|
285
|
+
});
|
326
286
|
}
|
327
287
|
/**
|
328
288
|
*
|
@@ -345,120 +305,68 @@ export class BlockInstanceRunner {
|
|
345
305
|
throw new Error(`Provider did not have local image: ${providerRef}`);
|
346
306
|
}
|
347
307
|
const dockerImage = spec?.local?.image;
|
348
|
-
try {
|
349
|
-
await containerManager.pull(dockerImage);
|
350
|
-
}
|
351
|
-
catch (e) {
|
352
|
-
console.warn('Failed to pull image. Continuing...', e);
|
353
|
-
}
|
354
308
|
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
355
309
|
const logs = new LogData();
|
356
|
-
const containerInfo = await containerManager.getContainerByName(containerName);
|
357
|
-
let container = containerInfo?.native;
|
358
|
-
if (container) {
|
359
|
-
const containerData = container.data;
|
360
|
-
if (containerData.State === 'running') {
|
361
|
-
logs.addLog(`Found existing running container for block: ${containerName}`);
|
362
|
-
}
|
363
|
-
else {
|
364
|
-
if (containerData.State?.ExitCode > 0) {
|
365
|
-
logs.addLog(`Container exited with code: ${containerData.State.ExitCode}. Deleting...`);
|
366
|
-
try {
|
367
|
-
await containerManager.remove(container);
|
368
|
-
}
|
369
|
-
catch (e) { }
|
370
|
-
container = undefined;
|
371
|
-
}
|
372
|
-
else {
|
373
|
-
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
374
|
-
try {
|
375
|
-
await container.start();
|
376
|
-
}
|
377
|
-
catch (e) {
|
378
|
-
console.warn('Failed to start container. Deleting...', e);
|
379
|
-
try {
|
380
|
-
await containerManager.remove(container);
|
381
|
-
}
|
382
|
-
catch (e) { }
|
383
|
-
container = undefined;
|
384
|
-
}
|
385
|
-
}
|
386
|
-
}
|
387
|
-
}
|
388
310
|
const bindHost = getBindHost();
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
const
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
HostPort: `${publicPort}`,
|
404
|
-
},
|
405
|
-
];
|
406
|
-
});
|
407
|
-
await Promise.all(promises);
|
408
|
-
if (spec.local?.env) {
|
409
|
-
Object.entries(spec.local.env).forEach(([key, value]) => {
|
410
|
-
addonEnv[key] = value;
|
411
|
-
});
|
412
|
-
}
|
413
|
-
if (spec.local?.mounts) {
|
414
|
-
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
415
|
-
Mounts = containerManager.toDockerMounts(mounts);
|
416
|
-
}
|
417
|
-
if (spec.local?.health) {
|
418
|
-
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
419
|
-
}
|
420
|
-
// For windows we need to default to root
|
421
|
-
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
422
|
-
logs.addLog(`Creating new container for block: ${containerName}`);
|
423
|
-
container = await containerManager.startContainer({
|
424
|
-
Image: dockerImage,
|
425
|
-
name: containerName,
|
426
|
-
ExposedPorts,
|
427
|
-
HealthCheck,
|
428
|
-
HostConfig: {
|
429
|
-
Binds: [
|
430
|
-
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
431
|
-
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
432
|
-
],
|
433
|
-
PortBindings,
|
434
|
-
Mounts,
|
435
|
-
},
|
436
|
-
Labels: {
|
437
|
-
instance: blockInstance.id,
|
311
|
+
const ExposedPorts = {};
|
312
|
+
const addonEnv = {};
|
313
|
+
const PortBindings = {};
|
314
|
+
let HealthCheck = undefined;
|
315
|
+
let Mounts = [];
|
316
|
+
const promises = Object.entries(spec.local.ports).map(async ([portType, value]) => {
|
317
|
+
const dockerPort = `${value.port}/${value.type}`;
|
318
|
+
ExposedPorts[dockerPort] = {};
|
319
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
320
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
321
|
+
PortBindings[dockerPort] = [
|
322
|
+
{
|
323
|
+
HostIp: bindHost,
|
324
|
+
HostPort: `${publicPort}`,
|
438
325
|
},
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
...addonEnv,
|
446
|
-
}).map(([key, value]) => `${key}=${value}`),
|
447
|
-
],
|
326
|
+
];
|
327
|
+
});
|
328
|
+
await Promise.all(promises);
|
329
|
+
if (spec.local?.env) {
|
330
|
+
Object.entries(spec.local.env).forEach(([key, value]) => {
|
331
|
+
addonEnv[key] = value;
|
448
332
|
});
|
449
|
-
try {
|
450
|
-
if (HealthCheck) {
|
451
|
-
await containerManager.waitForHealthy(container);
|
452
|
-
}
|
453
|
-
else {
|
454
|
-
await containerManager.waitForReady(container);
|
455
|
-
}
|
456
|
-
}
|
457
|
-
catch (e) {
|
458
|
-
logs.addLog(e.message, 'ERROR');
|
459
|
-
}
|
460
333
|
}
|
461
|
-
|
334
|
+
if (spec.local?.mounts) {
|
335
|
+
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
336
|
+
Mounts = containerManager.toDockerMounts(mounts);
|
337
|
+
}
|
338
|
+
if (spec.local?.health) {
|
339
|
+
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
340
|
+
}
|
341
|
+
// For windows we need to default to root
|
342
|
+
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
343
|
+
logs.addLog(`Creating new container for block: ${containerName}`);
|
344
|
+
const out = await this.ensureContainer({
|
345
|
+
Image: dockerImage,
|
346
|
+
name: containerName,
|
347
|
+
ExposedPorts,
|
348
|
+
HealthCheck,
|
349
|
+
HostConfig: {
|
350
|
+
Binds: [
|
351
|
+
`${toLocalBindVolume(kapetaYmlPath)}:/kapeta.yml:ro`,
|
352
|
+
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
353
|
+
],
|
354
|
+
PortBindings,
|
355
|
+
Mounts,
|
356
|
+
},
|
357
|
+
Labels: {
|
358
|
+
instance: blockInstance.id,
|
359
|
+
},
|
360
|
+
Env: [
|
361
|
+
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
362
|
+
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
363
|
+
...DOCKER_ENV_VARS,
|
364
|
+
...Object.entries({
|
365
|
+
...env,
|
366
|
+
...addonEnv,
|
367
|
+
}).map(([key, value]) => `${key}=${value}`),
|
368
|
+
],
|
369
|
+
});
|
462
370
|
const portTypes = spec.local.ports ? Object.keys(spec.local.ports) : [];
|
463
371
|
if (portTypes.length > 0) {
|
464
372
|
out.portType = portTypes[0];
|