@kapeta/local-cluster-service 0.37.0 → 0.39.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/index.js +4 -1
  3. package/dist/cjs/src/assetManager.d.ts +2 -1
  4. package/dist/cjs/src/assetManager.js +3 -2
  5. package/dist/cjs/src/config/routes.js +2 -2
  6. package/dist/cjs/src/containerManager.d.ts +6 -3
  7. package/dist/cjs/src/containerManager.js +101 -21
  8. package/dist/cjs/src/instanceManager.d.ts +4 -2
  9. package/dist/cjs/src/instanceManager.js +71 -32
  10. package/dist/cjs/src/operatorManager.d.ts +6 -3
  11. package/dist/cjs/src/operatorManager.js +32 -23
  12. package/dist/cjs/src/progressListener.d.ts +8 -1
  13. package/dist/cjs/src/progressListener.js +12 -1
  14. package/dist/cjs/src/repositoryManager.js +3 -2
  15. package/dist/cjs/src/serviceManager.d.ts +0 -1
  16. package/dist/cjs/src/serviceManager.js +2 -8
  17. package/dist/cjs/src/taskManager.d.ts +2 -0
  18. package/dist/cjs/src/taskManager.js +9 -0
  19. package/dist/cjs/src/types.d.ts +1 -48
  20. package/dist/cjs/src/types.js +2 -1
  21. package/dist/cjs/src/utils/BlockInstanceRunner.js +45 -33
  22. package/dist/cjs/src/utils/InternalConfigProvider.d.ts +38 -0
  23. package/dist/cjs/src/utils/InternalConfigProvider.js +146 -0
  24. package/dist/cjs/src/utils/commandLineUtils.d.ts +2 -1
  25. package/dist/cjs/src/utils/commandLineUtils.js +7 -1
  26. package/dist/cjs/src/utils/utils.d.ts +26 -4
  27. package/dist/cjs/src/utils/utils.js +48 -8
  28. package/dist/esm/index.js +4 -1
  29. package/dist/esm/src/assetManager.d.ts +2 -1
  30. package/dist/esm/src/assetManager.js +3 -2
  31. package/dist/esm/src/config/routes.js +2 -2
  32. package/dist/esm/src/containerManager.d.ts +6 -3
  33. package/dist/esm/src/containerManager.js +101 -21
  34. package/dist/esm/src/instanceManager.d.ts +4 -2
  35. package/dist/esm/src/instanceManager.js +71 -32
  36. package/dist/esm/src/operatorManager.d.ts +6 -3
  37. package/dist/esm/src/operatorManager.js +32 -23
  38. package/dist/esm/src/progressListener.d.ts +8 -1
  39. package/dist/esm/src/progressListener.js +12 -1
  40. package/dist/esm/src/repositoryManager.js +3 -2
  41. package/dist/esm/src/serviceManager.d.ts +0 -1
  42. package/dist/esm/src/serviceManager.js +2 -8
  43. package/dist/esm/src/taskManager.d.ts +2 -0
  44. package/dist/esm/src/taskManager.js +9 -0
  45. package/dist/esm/src/types.d.ts +1 -48
  46. package/dist/esm/src/types.js +2 -1
  47. package/dist/esm/src/utils/BlockInstanceRunner.js +45 -33
  48. package/dist/esm/src/utils/InternalConfigProvider.d.ts +38 -0
  49. package/dist/esm/src/utils/InternalConfigProvider.js +146 -0
  50. package/dist/esm/src/utils/commandLineUtils.d.ts +2 -1
  51. package/dist/esm/src/utils/commandLineUtils.js +7 -1
  52. package/dist/esm/src/utils/utils.d.ts +26 -4
  53. package/dist/esm/src/utils/utils.js +48 -8
  54. package/index.ts +5 -2
  55. package/package.json +16 -14
  56. package/src/assetManager.ts +5 -4
  57. package/src/config/routes.ts +4 -2
  58. package/src/containerManager.ts +115 -26
  59. package/src/instanceManager.ts +86 -44
  60. package/src/operatorManager.ts +48 -40
  61. package/src/progressListener.ts +15 -1
  62. package/src/repositoryManager.ts +5 -3
  63. package/src/serviceManager.ts +3 -11
  64. package/src/taskManager.ts +11 -0
  65. package/src/types.ts +2 -50
  66. package/src/utils/BlockInstanceRunner.ts +60 -44
  67. package/src/utils/InternalConfigProvider.ts +214 -0
  68. package/src/utils/commandLineUtils.ts +10 -2
  69. package/src/utils/utils.ts +53 -10
@@ -28,17 +28,20 @@ import {
28
28
  KIND_BLOCK_TYPE_EXECUTABLE,
29
29
  KIND_BLOCK_TYPE_OPERATOR,
30
30
  KIND_RESOURCE_OPERATOR,
31
- LocalImageOptions,
32
31
  LogEntry,
33
- OperatorInstanceInfo,
34
- OperatorInstancePort,
35
32
  } from './types';
36
- import { BlockDefinitionSpec, BlockInstance, Plan } from '@kapeta/schemas';
37
- import { getBlockInstanceContainerName, getResolvedConfiguration } from './utils/utils';
33
+ import { BlockDefinitionSpec, LocalInstance, Plan } from '@kapeta/schemas';
34
+ import {
35
+ getBlockInstanceContainerName,
36
+ getOperatorInstancePorts,
37
+ getRemoteHostForEnvironment,
38
+ getResolvedConfiguration,
39
+ } from './utils/utils';
38
40
  import { operatorManager } from './operatorManager';
39
41
  import { normalizeKapetaUri, parseKapetaUri } from '@kapeta/nodejs-utils';
40
42
  import { definitionsManager } from './definitionsManager';
41
43
  import { Task, taskManager } from './taskManager';
44
+ import { InstanceOperator, InstanceOperatorPort } from '@kapeta/sdk-config';
42
45
 
43
46
  const CHECK_INTERVAL = 5000;
44
47
  const DEFAULT_HEALTH_PORT_TYPE = 'http';
@@ -118,6 +121,10 @@ export class InstanceManager {
118
121
  return result;
119
122
  }
120
123
 
124
+ private isLocked(systemId: string, instanceId: string) {
125
+ return this.instanceLocks.isBusy(`${systemId}/${instanceId}`);
126
+ }
127
+
121
128
  public async getLogs(systemId: string, instanceId: string): Promise<LogEntry[]> {
122
129
  const instance = this.getInstance(systemId, instanceId);
123
130
  if (!instance) {
@@ -293,7 +300,9 @@ export class InstanceManager {
293
300
  systemId = normalizeKapetaUri(systemId);
294
301
  const instance = _.find(this._instances, { systemId, instanceId });
295
302
  if (instance && instance.owner === InstanceOwner.EXTERNAL && instance.status !== InstanceStatus.STOPPED) {
296
- instance.status = InstanceStatus.STOPPED;
303
+ if (instance.status != InstanceStatus.FAILED) {
304
+ instance.status = InstanceStatus.STOPPED;
305
+ }
297
306
  instance.pid = null;
298
307
  instance.health = null;
299
308
  socketManager.emitSystemEvent(systemId, EVENT_STATUS_CHANGED, instance);
@@ -367,8 +376,9 @@ export class InstanceManager {
367
376
  public async getInstanceOperator(
368
377
  systemId: string,
369
378
  instanceId: string,
370
- environment?: EnvironmentType
371
- ): Promise<OperatorInstanceInfo> {
379
+ environment?: EnvironmentType,
380
+ ensureContainer: boolean = true
381
+ ): Promise<InstanceOperator<any, any>> {
372
382
  const blockInstance = await assetManager.getBlockInstance(systemId, instanceId);
373
383
  if (!blockInstance) {
374
384
  throw new Error(`Instance not found: ${systemId}/${instanceId}`);
@@ -381,36 +391,55 @@ export class InstanceManager {
381
391
 
382
392
  const operatorDefinition = await definitionsManager.getDefinition(block.kind);
383
393
 
384
- if (!operatorDefinition?.definition.spec.local) {
385
- throw new Error(`Operator block has no local definition: ${blockRef}`);
394
+ if (!operatorDefinition) {
395
+ throw new Error(`Operator not found: ${block.kind}`);
386
396
  }
387
397
 
388
- const localConfig = operatorDefinition.definition.spec.local as LocalImageOptions;
389
-
390
- let instance = await this.start(systemId, instanceId);
391
- if (instance instanceof Task) {
392
- instance = await instance.wait();
398
+ if (operatorDefinition.definition.kind !== KIND_BLOCK_TYPE_OPERATOR) {
399
+ throw new Error(`Block is not an operator: ${blockRef}`);
393
400
  }
394
401
 
395
- const container = await containerManager.get(instance.pid as string);
396
- if (!container) {
397
- throw new Error(`Container not found: ${instance.pid}`);
402
+ if (!operatorDefinition.definition.spec.local) {
403
+ throw new Error(`Operator block has no local definition: ${blockRef}`);
398
404
  }
399
405
 
400
- const portInfo = await container.getPorts();
401
- if (!portInfo) {
402
- throw new Error(`No ports found for instance: ${instanceId}`);
403
- }
406
+ const localConfig = operatorDefinition.definition.spec.local as LocalInstance;
407
+ const ports: { [key: string]: InstanceOperatorPort } = {};
404
408
 
405
- const hostname = serviceManager.getLocalHost(environment);
406
- const ports: { [key: string]: OperatorInstancePort } = {};
409
+ if (ensureContainer) {
410
+ let instance = await this.start(systemId, instanceId);
411
+ if (instance instanceof Task) {
412
+ instance = await instance.wait();
413
+ }
407
414
 
408
- Object.entries(portInfo).forEach(([key, value]) => {
409
- ports[key] = {
410
- protocol: value.protocol,
411
- port: parseInt(value.hostPort),
412
- };
413
- });
415
+ const container = await containerManager.get(instance.pid as string);
416
+ if (!container) {
417
+ throw new Error(`Container not found: ${instance.pid}`);
418
+ }
419
+
420
+ const portInfo = await container.getPorts();
421
+ if (!portInfo) {
422
+ throw new Error(`No ports found for instance: ${instanceId}`);
423
+ }
424
+
425
+ Object.entries(portInfo).forEach(([key, value]) => {
426
+ ports[key] = {
427
+ protocol: value.protocol as 'udp' | 'tcp',
428
+ port: parseInt(value.hostPort),
429
+ };
430
+ });
431
+ } else {
432
+ // If we're not ensuring the container is running we just get the ports from the local config
433
+ const instancePorts = await getOperatorInstancePorts(systemId, instanceId, localConfig);
434
+ instancePorts.forEach((port) => {
435
+ ports[port.portType] = {
436
+ protocol: port.protocol as 'udp' | 'tcp',
437
+ port: port.hostPort,
438
+ };
439
+ });
440
+ }
441
+
442
+ const hostname = getRemoteHostForEnvironment(environment);
414
443
 
415
444
  return {
416
445
  hostname,
@@ -471,6 +500,8 @@ export class InstanceManager {
471
500
  instance.desiredStatus = DesiredInstanceStatus.STOP;
472
501
  }
473
502
 
503
+ const wasFailed = instance.status === InstanceStatus.FAILED;
504
+
474
505
  instance.status = InstanceStatus.STOPPING;
475
506
 
476
507
  socketManager.emitSystemEvent(systemId, EVENT_STATUS_CHANGED, instance);
@@ -489,7 +520,11 @@ export class InstanceManager {
489
520
  const container = await containerManager.getContainerByName(containerName);
490
521
  if (container) {
491
522
  try {
492
- await container.stop();
523
+ if (wasFailed) {
524
+ await container.remove();
525
+ } else {
526
+ await container.stop();
527
+ }
493
528
  instance.status = InstanceStatus.STOPPED;
494
529
  socketManager.emitSystemEvent(systemId, EVENT_STATUS_CHANGED, instance);
495
530
  this.save();
@@ -555,7 +590,7 @@ export class InstanceManager {
555
590
  }
556
591
  }
557
592
 
558
- if (existingInstance?.pid) {
593
+ if (existingInstance && existingInstance.pid) {
559
594
  if (existingInstance.status === InstanceStatus.READY) {
560
595
  // Instance is already running
561
596
  return existingInstance;
@@ -623,18 +658,15 @@ export class InstanceManager {
623
658
  if (existingInstance) {
624
659
  // Check if the instance is already running - but after we've commmuicated the desired status
625
660
  const currentStatus = await this.requestInstanceStatus(existingInstance);
661
+
626
662
  if (currentStatus === InstanceStatus.READY) {
627
663
  // Instance is already running
628
664
  return existingInstance;
629
665
  }
630
666
  }
631
667
 
632
- const instanceConfig = await configManager.getConfigForSection(systemId, instanceId);
633
- const resolvedConfig = getResolvedConfiguration(
634
- blockSpec.configuration,
635
- instanceConfig,
636
- blockInstance.defaultConfiguration
637
- );
668
+ const resolvedConfig = await configManager.getConfigForBlockInstance(systemId, instanceId);
669
+
638
670
  const task = taskManager.add(
639
671
  `instance:start:${systemId}:${instanceId}`,
640
672
  async () => {
@@ -666,8 +698,7 @@ export class InstanceManager {
666
698
 
667
699
  const out = await this.saveInternalInstance({
668
700
  ...instance,
669
- type: InstanceType.UNKNOWN,
670
- pid: null,
701
+ type: InstanceType.DOCKER,
671
702
  health: null,
672
703
  portType: DEFAULT_HEALTH_PORT_TYPE,
673
704
  status: InstanceStatus.FAILED,
@@ -811,7 +842,6 @@ export class InstanceManager {
811
842
  if (instance.status !== newStatus) {
812
843
  const oldStatus = instance.status;
813
844
  const skipUpdate =
814
- (newStatus === InstanceStatus.STOPPED && instance.status === InstanceStatus.FAILED) ||
815
845
  ([InstanceStatus.READY, InstanceStatus.UNHEALTHY].includes(newStatus) &&
816
846
  instance.status === InstanceStatus.STOPPING) ||
817
847
  (newStatus === InstanceStatus.STOPPED &&
@@ -835,7 +865,7 @@ export class InstanceManager {
835
865
 
836
866
  if (
837
867
  instance.desiredStatus === DesiredInstanceStatus.RUN &&
838
- [InstanceStatus.STOPPED, InstanceStatus.FAILED, InstanceStatus.STOPPING].includes(newStatus)
868
+ [InstanceStatus.STOPPED, InstanceStatus.STOPPING].includes(newStatus)
839
869
  ) {
840
870
  //If the instance is stopped but we want it to run, start it
841
871
  try {
@@ -928,11 +958,23 @@ export class InstanceManager {
928
958
  }
929
959
 
930
960
  if (statusType === 'created') {
961
+ if (state.ExitCode !== undefined && state.ExitCode !== 0) {
962
+ // Failed during creation. Exit code is not always reliable though
963
+ if (state.Error) {
964
+ return InstanceStatus.FAILED;
965
+ } else {
966
+ return InstanceStatus.STOPPED;
967
+ }
968
+ }
931
969
  return InstanceStatus.STARTING;
932
970
  }
933
971
 
934
972
  if (statusType === 'exited' || statusType === 'dead') {
935
- return InstanceStatus.STOPPED;
973
+ if (!state.Error) {
974
+ // Exit code is not always reliable - if there is no error we assume it's stopped
975
+ return InstanceStatus.STOPPED;
976
+ }
977
+ return InstanceStatus.FAILED;
936
978
  }
937
979
 
938
980
  if (statusType === 'removing') {
@@ -1013,7 +1055,7 @@ export class InstanceManager {
1013
1055
  }
1014
1056
 
1015
1057
  if (parseKapetaUri(provider.kind).fullName === KIND_BLOCK_TYPE_OPERATOR) {
1016
- const localConfig = provider.data.spec.local as LocalImageOptions;
1058
+ const localConfig = provider.data.spec.local as LocalInstance;
1017
1059
  return localConfig.singleton ?? false;
1018
1060
  }
1019
1061
 
@@ -16,22 +16,15 @@ import {
16
16
  containerManager,
17
17
  } from './containerManager';
18
18
  import FSExtra from 'fs-extra';
19
- import {
20
- AnyMap,
21
- EnvironmentType,
22
- KIND_BLOCK_TYPE_OPERATOR,
23
- KIND_RESOURCE_OPERATOR,
24
- LocalImageOptions,
25
- OperatorInfo,
26
- StringMap,
27
- } from './types';
28
- import { BlockInstance, Resource } from '@kapeta/schemas';
19
+ import { AnyMap, EnvironmentType, KIND_BLOCK_TYPE_OPERATOR, KIND_RESOURCE_OPERATOR, StringMap } from './types';
20
+ import { BlockInstance, LocalInstance, Resource } from '@kapeta/schemas';
29
21
  import { definitionsManager } from './definitionsManager';
30
- import { getBindHost, toPortInfo } from './utils/utils';
22
+ import { getDockerHostIp, getRemoteHostForEnvironment, toPortInfo } from './utils/utils';
31
23
  import { parseKapetaUri, normalizeKapetaUri } from '@kapeta/nodejs-utils';
32
24
  import _ from 'lodash';
33
25
  import AsyncLock from 'async-lock';
34
26
  import { taskManager } from './taskManager';
27
+ import { ResourceInfo } from '@kapeta/sdk-config';
35
28
 
36
29
  const KIND_PLAN = 'core/plan';
37
30
 
@@ -42,7 +35,7 @@ class Operator {
42
35
  this._data = data;
43
36
  }
44
37
 
45
- getLocalData(): LocalImageOptions {
38
+ getLocalData(): LocalInstance {
46
39
  return this._data.definition.spec.local;
47
40
  }
48
41
 
@@ -105,8 +98,9 @@ class OperatorManager {
105
98
  resourceType: string,
106
99
  portType: string,
107
100
  name: string,
108
- environment?: EnvironmentType
109
- ): Promise<OperatorInfo> {
101
+ environment?: EnvironmentType,
102
+ ensureContainer: boolean = true
103
+ ): Promise<ResourceInfo<any, any>> {
110
104
  systemId = normalizeKapetaUri(systemId);
111
105
  const plans = await definitionsManager.getDefinitions(KIND_PLAN);
112
106
 
@@ -145,10 +139,13 @@ class OperatorManager {
145
139
  const kindUri = parseKapetaUri(blockResource.kind);
146
140
  const operator = await this.getOperator(resourceType, kindUri.version);
147
141
  const credentials = operator.getCredentials();
148
- const container = await this.ensureOperator(systemId, resourceType, kindUri.version);
149
- const portInfo = await container.getPort(portType);
142
+ if (ensureContainer) {
143
+ await this.ensureOperator(systemId, resourceType, kindUri.version);
144
+ }
145
+
146
+ const hostPort = await serviceManager.ensureServicePort(systemId, resourceType, portType);
150
147
 
151
- if (!portInfo) {
148
+ if (!hostPort) {
152
149
  throw new Error('Unknown resource port type : ' + resourceType + '#' + portType);
153
150
  }
154
151
 
@@ -156,10 +153,10 @@ class OperatorManager {
156
153
  const safeName = dbName.replace('_', '-');
157
154
 
158
155
  return {
159
- host: environment === 'docker' ? 'host.docker.internal' : '127.0.0.1',
160
- port: portInfo.hostPort,
156
+ host: getRemoteHostForEnvironment(environment),
157
+ port: hostPort,
161
158
  type: portType,
162
- protocol: portInfo.protocol,
159
+ protocol: 'tcp',
163
160
  options: {
164
161
  // expose as fullName since that is not operator specific, but unique
165
162
  fullName: safeName,
@@ -169,6 +166,34 @@ class OperatorManager {
169
166
  };
170
167
  }
171
168
 
169
+ async getOperatorPorts(systemId: string, kind: string, version: string) {
170
+ const operator = await this.getOperator(kind, version);
171
+
172
+ const operatorData = operator.getLocalData();
173
+
174
+ const portTypes = Object.keys(operatorData.ports);
175
+
176
+ portTypes.sort();
177
+
178
+ const ports: AnyMap = {};
179
+
180
+ for (let i = 0; i < portTypes.length; i++) {
181
+ const portType = portTypes[i];
182
+ let containerPortInfo = operatorData.ports[portType];
183
+ const hostPort = await serviceManager.ensureServicePort(systemId, kind, portType);
184
+ const portInfo = toPortInfo(containerPortInfo);
185
+ const portId = portInfo.port + '/' + portInfo.type;
186
+
187
+ ports[portId] = {
188
+ type: portType,
189
+ hostPort,
190
+ protocol: portInfo.type,
191
+ };
192
+ }
193
+
194
+ return ports;
195
+ }
196
+
172
197
  /**
173
198
  * Ensure we have a running operator of given type
174
199
  *
@@ -186,24 +211,7 @@ class OperatorManager {
186
211
 
187
212
  const operatorData = operator.getLocalData();
188
213
 
189
- const portTypes = Object.keys(operatorData.ports);
190
-
191
- portTypes.sort();
192
-
193
- const ports: AnyMap = {};
194
-
195
- for (let i = 0; i < portTypes.length; i++) {
196
- const portType = portTypes[i];
197
- let containerPortInfo = operatorData.ports[portType];
198
- const hostPort = await serviceManager.ensureServicePort(systemId, kind, portType);
199
- const portInfo = toPortInfo(containerPortInfo);
200
- const portId = portInfo.port + '/' + portInfo.type;
201
-
202
- ports[portId] = {
203
- type: portType,
204
- hostPort,
205
- };
206
- }
214
+ const ports = await this.getOperatorPorts(systemId, kind, version);
207
215
 
208
216
  const nameParts = [systemId, kind.toLowerCase(), version];
209
217
 
@@ -222,7 +230,7 @@ class OperatorManager {
222
230
 
223
231
  const operatorMetadata = operator.getDefinitionInfo().definition.metadata;
224
232
 
225
- const bindHost = getBindHost();
233
+ const hostIp = getDockerHostIp();
226
234
 
227
235
  const ExposedPorts: { [key: string]: any } = {};
228
236
 
@@ -231,7 +239,7 @@ class OperatorManager {
231
239
  PortBindings['' + containerPort] = [
232
240
  {
233
241
  HostPort: '' + portInfo.hostPort,
234
- HostIp: bindHost,
242
+ HostIp: hostIp,
235
243
  },
236
244
  ];
237
245
 
@@ -7,6 +7,7 @@ import { spawn } from '@kapeta/nodejs-process';
7
7
  import { socketManager } from './socketManager';
8
8
  import { LogEntry } from './types';
9
9
  import { format } from 'node:util';
10
+ import { Task } from './taskManager';
10
11
 
11
12
  export class ProgressListener {
12
13
  private readonly systemId: string | undefined;
@@ -17,7 +18,7 @@ export class ProgressListener {
17
18
  this.instanceId = instanceId;
18
19
  }
19
20
 
20
- private emitLog(payload: Omit<LogEntry, 'time' | 'source'>) {
21
+ protected emitLog(payload: Omit<LogEntry, 'time' | 'source'>) {
21
22
  const logEntry: LogEntry = {
22
23
  ...payload,
23
24
  source: 'stdout',
@@ -135,3 +136,16 @@ export class ProgressListener {
135
136
  });
136
137
  }
137
138
  }
139
+
140
+ export class TaskProgressListener extends ProgressListener {
141
+ private readonly task: Task;
142
+
143
+ constructor(task: Task) {
144
+ super();
145
+ this.task = task;
146
+ }
147
+
148
+ protected emitLog(payload: Omit<LogEntry, 'time' | 'source'>) {
149
+ this.task.addLog(payload.message, payload.level);
150
+ }
151
+ }
@@ -10,7 +10,7 @@ import { Actions, AssetVersion, Config, RegistryService } from '@kapeta/nodejs-r
10
10
  import { definitionsManager } from './definitionsManager';
11
11
  import { Task, taskManager } from './taskManager';
12
12
  import { normalizeKapetaUri, parseKapetaUri, parseVersion } from '@kapeta/nodejs-utils';
13
- import { ProgressListener } from './progressListener';
13
+ import { TaskProgressListener } from './progressListener';
14
14
  import { RepositoryWatcher } from './RepositoryWatcher';
15
15
  import { SourceOfChange } from './types';
16
16
  import { cacheManager } from './cacheManager';
@@ -191,16 +191,18 @@ class RepositoryManager extends EventEmitter {
191
191
  private async scheduleInstallation(refs: string[]): Promise<Task[]> {
192
192
  //We make sure to only install one asset at a time - otherwise unexpected things might happen
193
193
  const createInstaller = (ref: string) => {
194
- return async () => {
194
+ return async (task: Task) => {
195
195
  if (await definitionsManager.exists(ref)) {
196
196
  return;
197
197
  }
198
+
199
+ const progressListener = new TaskProgressListener(task);
198
200
  //console.log(`Installing asset: ${ref}`);
199
201
  //Auto-install missing asset
200
202
  try {
201
203
  //We change to a temp dir to avoid issues with the current working directory
202
204
  process.chdir(os.tmpdir());
203
- await Actions.install(new ProgressListener(), [ref], {});
205
+ await Actions.install(progressListener, [ref], {});
204
206
  } catch (e) {
205
207
  console.error(`Failed to install asset: ${ref}`, e);
206
208
  throw e;
@@ -6,9 +6,10 @@
6
6
  import _ from 'lodash';
7
7
  import { clusterService } from './clusterService';
8
8
  import { storageService } from './storageService';
9
- import { EnvironmentType } from './types';
9
+ import { DOCKER_HOST_INTERNAL, EnvironmentType } from './types';
10
10
  import { normalizeKapetaUri } from '@kapeta/nodejs-utils';
11
11
  import { resolvePortType } from './utils/BlockInstanceRunner';
12
+ import { getRemoteHostForEnvironment } from './utils/utils';
12
13
 
13
14
  export const HTTP_PORT_TYPE = 'http';
14
15
 
@@ -34,20 +35,11 @@ class ServiceManager {
34
35
  });
35
36
  }
36
37
 
37
- public getLocalHost(environmentType?: EnvironmentType) {
38
- if (environmentType === 'docker') {
39
- //We're inside a docker container, so we can use this special host name to access the host machine
40
- return 'host.docker.internal';
41
- }
42
-
43
- return clusterService.getClusterServiceHost();
44
- }
45
-
46
38
  _forLocal(port: string | number, path?: string, environmentType?: EnvironmentType) {
47
39
  if (!path) {
48
40
  path = '';
49
41
  }
50
- const hostname = this.getLocalHost(environmentType);
42
+ const hostname = getRemoteHostForEnvironment(environmentType);
51
43
 
52
44
  if (path.startsWith('/')) {
53
45
  path = path.substring(1);
@@ -7,10 +7,12 @@
7
7
  * Class that handles processing background tasks.
8
8
  */
9
9
  import { socketManager } from './socketManager';
10
+ import { LogLevel } from './types';
10
11
 
11
12
  const EVENT_TASK_UPDATED = 'task-updated';
12
13
  const EVENT_TASK_ADDED = 'task-added';
13
14
  const EVENT_TASK_REMOVED = 'task-removed';
15
+ const EVENT_TASK_LOG = 'task-log';
14
16
 
15
17
  export type TaskRunner<T> = (task: Task<T>) => Promise<T>;
16
18
 
@@ -94,6 +96,15 @@ export class Task<T = void> implements TaskData<T> {
94
96
  socketManager.emitGlobal(EVENT_TASK_UPDATED, this.toData());
95
97
  }
96
98
 
99
+ public addLog(log: string, level: LogLevel = 'INFO') {
100
+ socketManager.emitGlobal(EVENT_TASK_LOG, {
101
+ id: this.id,
102
+ message: log,
103
+ level,
104
+ time: Date.now(),
105
+ });
106
+ }
107
+
97
108
  async wait(): Promise<T> {
98
109
  return this.future.promise;
99
110
  }
package/src/types.ts CHANGED
@@ -21,6 +21,8 @@ export type LogLevel = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'FATAL';
21
21
  export type LogSource = 'stdout' | 'stderr';
22
22
  export type EnvironmentType = 'docker' | 'process';
23
23
 
24
+ export const DOCKER_HOST_INTERNAL = 'host.docker.internal';
25
+
24
26
  export interface LogEntry {
25
27
  source: LogSource;
26
28
  level: LogLevel;
@@ -66,27 +68,6 @@ export type ProcessInfo = {
66
68
  portType?: string;
67
69
  };
68
70
 
69
- export interface Health {
70
- cmd: string;
71
- interval?: number;
72
- timeout?: number;
73
- retries?: number;
74
- }
75
-
76
- export type PortInfo = { port: number; type: 'tcp' | 'udp' } | number | string;
77
-
78
- export type LocalImageOptions<Credentials = AnyMap, Options = AnyMap> = {
79
- image: string;
80
- ports: { [key: string]: PortInfo };
81
- credentials?: Credentials;
82
- options?: Options;
83
- cmd?: string;
84
- env?: AnyMap;
85
- health?: Health;
86
- singleton?: boolean;
87
- mounts?: { [key: string]: string };
88
- };
89
-
90
71
  export type InstanceInfo = {
91
72
  systemId: string;
92
73
  instanceId: string;
@@ -105,37 +86,8 @@ export type InstanceInfo = {
105
86
  portType?: string;
106
87
  };
107
88
 
108
- interface ResourceRef {
109
- blockId: string;
110
- resourceName: string;
111
- }
112
-
113
89
  export type ProxyRequestHandler = (req: StringBodyRequest, res: express.Response, info: ProxyRequestInfo) => void;
114
90
 
115
- export interface OperatorInstancePort {
116
- protocol: string;
117
- port: number;
118
- }
119
-
120
- export interface OperatorInstanceInfo {
121
- hostname: string;
122
- ports: { [portType: string]: OperatorInstancePort };
123
- path?: string;
124
- query?: string;
125
- hash?: string;
126
- options?: AnyMap;
127
- credentials?: AnyMap;
128
- }
129
-
130
- export interface OperatorInfo {
131
- host: string;
132
- port: string;
133
- type: string;
134
- protocol: string;
135
- options: AnyMap;
136
- credentials: AnyMap;
137
- }
138
-
139
91
  export interface ProxyRequestInfo {
140
92
  address: string;
141
93
  connection: Connection;