@kapeta/local-cluster-service 0.36.1 → 0.38.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 (54) hide show
  1. package/.vscode/launch.json +9 -5
  2. package/CHANGELOG.md +21 -0
  3. package/dist/cjs/src/assetManager.d.ts +2 -1
  4. package/dist/cjs/src/assetManager.js +7 -4
  5. package/dist/cjs/src/containerManager.d.ts +6 -3
  6. package/dist/cjs/src/containerManager.js +96 -18
  7. package/dist/cjs/src/instanceManager.d.ts +16 -0
  8. package/dist/cjs/src/instanceManager.js +78 -14
  9. package/dist/cjs/src/operatorManager.d.ts +3 -4
  10. package/dist/cjs/src/operatorManager.js +3 -4
  11. package/dist/cjs/src/progressListener.d.ts +8 -1
  12. package/dist/cjs/src/progressListener.js +12 -1
  13. package/dist/cjs/src/repositoryManager.js +3 -2
  14. package/dist/cjs/src/taskManager.d.ts +2 -0
  15. package/dist/cjs/src/taskManager.js +9 -0
  16. package/dist/cjs/src/types.d.ts +4 -19
  17. package/dist/cjs/src/types.js +5 -1
  18. package/dist/cjs/src/utils/BlockInstanceRunner.js +16 -5
  19. package/dist/cjs/src/utils/commandLineUtils.d.ts +2 -1
  20. package/dist/cjs/src/utils/commandLineUtils.js +7 -1
  21. package/dist/cjs/src/utils/utils.d.ts +3 -3
  22. package/dist/cjs/src/utils/utils.js +4 -3
  23. package/dist/esm/src/assetManager.d.ts +2 -1
  24. package/dist/esm/src/assetManager.js +7 -4
  25. package/dist/esm/src/containerManager.d.ts +6 -3
  26. package/dist/esm/src/containerManager.js +96 -18
  27. package/dist/esm/src/instanceManager.d.ts +16 -0
  28. package/dist/esm/src/instanceManager.js +78 -14
  29. package/dist/esm/src/operatorManager.d.ts +3 -4
  30. package/dist/esm/src/operatorManager.js +3 -4
  31. package/dist/esm/src/progressListener.d.ts +8 -1
  32. package/dist/esm/src/progressListener.js +12 -1
  33. package/dist/esm/src/repositoryManager.js +3 -2
  34. package/dist/esm/src/taskManager.d.ts +2 -0
  35. package/dist/esm/src/taskManager.js +9 -0
  36. package/dist/esm/src/types.d.ts +4 -19
  37. package/dist/esm/src/types.js +5 -1
  38. package/dist/esm/src/utils/BlockInstanceRunner.js +16 -5
  39. package/dist/esm/src/utils/commandLineUtils.d.ts +2 -1
  40. package/dist/esm/src/utils/commandLineUtils.js +7 -1
  41. package/dist/esm/src/utils/utils.d.ts +3 -3
  42. package/dist/esm/src/utils/utils.js +4 -3
  43. package/package.json +17 -16
  44. package/src/assetManager.ts +9 -7
  45. package/src/containerManager.ts +110 -23
  46. package/src/instanceManager.ts +87 -16
  47. package/src/operatorManager.ts +11 -6
  48. package/src/progressListener.ts +15 -1
  49. package/src/repositoryManager.ts +5 -3
  50. package/src/taskManager.ts +11 -0
  51. package/src/types.ts +5 -19
  52. package/src/utils/BlockInstanceRunner.ts +21 -8
  53. package/src/utils/commandLineUtils.ts +10 -2
  54. package/src/utils/utils.ts +5 -6
@@ -1,15 +1,19 @@
1
1
  {
2
- // Use IntelliSense to learn about possible attributes.
3
- // Hover to view descriptions of existing attributes.
4
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
2
  "version": "0.2.0",
6
3
  "configurations": [
7
4
  {
8
5
  "type": "node",
9
6
  "request": "launch",
10
- "name": "Launch Program",
7
+ "name": "Debug Node.js (npm run dev)",
8
+ "runtimeExecutable": "npm",
9
+ "runtimeArgs": ["run-script", "dev"],
10
+ "restart": true,
11
+ "console": "integratedTerminal",
12
+ "internalConsoleOptions": "neverOpen",
11
13
  "skipFiles": ["<node_internals>/**"],
12
- "program": "${workspaceFolder}/start.js"
14
+ "env": {
15
+ "NODE_ENV": "development"
16
+ }
13
17
  }
14
18
  ]
15
19
  }
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ # [0.38.0](https://github.com/kapetacom/local-cluster-service/compare/v0.37.0...v0.38.0) (2024-02-24)
2
+
3
+
4
+ ### Features
5
+
6
+ * Add support for running local dockerfiles ([2ee08c5](https://github.com/kapetacom/local-cluster-service/commit/2ee08c58eb19666834262d8011c8f901957b5f63))
7
+
8
+ # [0.37.0](https://github.com/kapetacom/local-cluster-service/compare/v0.36.1...v0.37.0) (2024-02-23)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Self review ([50bd377](https://github.com/kapetacom/local-cluster-service/commit/50bd377c41f132fd3f61afb1fc74b823bf60729f))
14
+ * Start debugger as "npm run dev" ([44b745a](https://github.com/kapetacom/local-cluster-service/commit/44b745af75e333056f7b187680f43c786461eb1d))
15
+
16
+
17
+ ### Features
18
+
19
+ * Add block-type-executabla ([7426433](https://github.com/kapetacom/local-cluster-service/commit/742643358022c0eb3b6065a42abba00e27dfc2e8))
20
+ * Do not attempt to start instances of kind 'core/block-type-executable' ([9239eaf](https://github.com/kapetacom/local-cluster-service/commit/9239eafc117c98fa215b67e2dd99f5d8f18c2881))
21
+
1
22
  ## [0.36.1](https://github.com/kapetacom/local-cluster-service/compare/v0.36.0...v0.36.1) (2024-02-07)
2
23
 
3
24
 
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { Definition } from '@kapeta/local-cluster-config';
6
6
  import { BlockDefinition, BlockInstance, Plan } from '@kapeta/schemas';
7
+ import { Task } from './taskManager';
7
8
  import { SourceOfChange } from './types';
8
9
  export interface EnrichedAsset {
9
10
  ref: string;
@@ -31,7 +32,7 @@ declare class AssetManager {
31
32
  updateAsset(ref: string, yaml: Definition, sourceOfChange?: SourceOfChange): Promise<void>;
32
33
  importFile(filePath: string): Promise<EnrichedAsset[]>;
33
34
  unregisterAsset(ref: string): Promise<void>;
34
- installAsset(ref: string, wait?: boolean): Promise<import("./taskManager").Task<void>[] | undefined>;
35
+ installAsset(ref: string, wait?: boolean): Promise<Task<void>[] | undefined>;
35
36
  private cleanupUnusedProviders;
36
37
  private upgradeAllProviders;
37
38
  private maybeGenerateCode;
@@ -18,6 +18,7 @@ const repositoryManager_1 = require("./repositoryManager");
18
18
  const nodejs_registry_utils_1 = require("@kapeta/nodejs-registry-utils");
19
19
  const definitionsManager_1 = require("./definitionsManager");
20
20
  const taskManager_1 = require("./taskManager");
21
+ const types_1 = require("./types");
21
22
  const cacheManager_1 = require("./cacheManager");
22
23
  const node_uuid_1 = __importDefault(require("node-uuid"));
23
24
  const node_os_1 = __importDefault(require("node:os"));
@@ -75,8 +76,9 @@ class AssetManager {
75
76
  async getAssets(assetKinds) {
76
77
  if (!assetKinds) {
77
78
  const blockTypeProviders = await definitionsManager_1.definitionsManager.getDefinitions([
78
- 'core/block-type',
79
- 'core/block-type-operator',
79
+ types_1.KIND_BLOCK_TYPE,
80
+ types_1.KIND_BLOCK_TYPE_OPERATOR,
81
+ types_1.KIND_BLOCK_TYPE_EXECUTABLE,
80
82
  ]);
81
83
  assetKinds = blockTypeProviders.map((p) => {
82
84
  return `${p.definition.metadata.name}:${p.version}`;
@@ -231,11 +233,12 @@ class AssetManager {
231
233
  return;
232
234
  }
233
235
  console.log('Installing updates', refs);
234
- const updateAll = async () => {
236
+ const updateAll = async (task) => {
237
+ const progressListener = new progressListener_1.TaskProgressListener(task);
235
238
  try {
236
239
  //We change to a temp dir to avoid issues with the current working directory
237
240
  process.chdir(node_os_1.default.tmpdir());
238
- await nodejs_registry_utils_1.Actions.install(new progressListener_1.ProgressListener(), refs, {});
241
+ await nodejs_registry_utils_1.Actions.install(progressListener, refs, {});
239
242
  await this.cleanupUnusedProviders();
240
243
  }
241
244
  catch (e) {
@@ -5,7 +5,9 @@
5
5
  /// <reference types="node" />
6
6
  import FSExtra from 'fs-extra';
7
7
  import Docker from 'dockerode';
8
- import { Health, InstanceInfo, LogEntry } from './types';
8
+ import { InstanceInfo, LogEntry } from './types';
9
+ import { Task } from './taskManager';
10
+ import { LocalInstanceHealth } from '@kapeta/schemas';
9
11
  type StringMap = {
10
12
  [key: string]: string;
11
13
  };
@@ -50,11 +52,11 @@ declare class ContainerManager {
50
52
  getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
51
53
  pull(image: string): Promise<boolean>;
52
54
  toDockerMounts(mounts: StringMap): DockerMounts[];
53
- toDockerHealth(health: Health): {
55
+ toDockerHealth(health: LocalInstanceHealth): {
54
56
  Test: string[];
55
57
  Interval: number;
56
58
  Timeout: number;
57
- Retries: number;
59
+ Retries: any;
58
60
  };
59
61
  private applyHash;
60
62
  ensureContainer(opts: any): Promise<Docker.Container>;
@@ -74,6 +76,7 @@ declare class ContainerManager {
74
76
  getLogs(instance: InstanceInfo): Promise<LogEntry[]>;
75
77
  stopLogListening(systemId: string, instanceId: string): Promise<void>;
76
78
  ensureLogListening(systemId: string, instanceId: string, handler: (log: LogEntry) => void): Promise<void>;
79
+ buildDockerImage(dockerFile: string, imageName: string): Task<void>;
77
80
  }
78
81
  declare class ClosableLogStream {
79
82
  private readonly stream;
@@ -207,14 +207,8 @@ class ContainerManager {
207
207
  return this._docker;
208
208
  }
209
209
  async getContainerByName(containerName) {
210
- const containers = await this.docker().listContainers({ all: true });
211
- const out = containers.find((container) => {
212
- return container.Names.indexOf(`/${containerName}`) > -1;
213
- });
214
- if (out) {
215
- return this.get(out.Id);
216
- }
217
- return undefined;
210
+ // The container can be fetched by name or by id using the same API call
211
+ return this.get(containerName);
218
212
  }
219
213
  async pull(image) {
220
214
  let [imageName, tag] = image.split(/:/);
@@ -279,6 +273,10 @@ class ContainerManager {
279
273
  };
280
274
  }
281
275
  const chunk = chunks[data.id];
276
+ if (data.stream) {
277
+ // Emit raw output to the task log
278
+ task.addLog(data.stream);
279
+ }
282
280
  switch (data.status) {
283
281
  case DockerPullEventTypes.PreparingPhase:
284
282
  case DockerPullEventTypes.WaitingPhase:
@@ -520,7 +518,7 @@ class ContainerManager {
520
518
  async get(name) {
521
519
  let dockerContainer = null;
522
520
  try {
523
- dockerContainer = await this.docker().getContainer(name);
521
+ dockerContainer = this.docker().getContainer(name);
524
522
  await dockerContainer.stats();
525
523
  }
526
524
  catch (err) {
@@ -545,7 +543,7 @@ class ContainerManager {
545
543
  },
546
544
  ];
547
545
  }
548
- return containerInfo.getLogs();
546
+ return await containerInfo.getLogs();
549
547
  }
550
548
  async stopLogListening(systemId, instanceId) {
551
549
  const containerName = await (0, utils_1.getBlockInstanceContainerName)(systemId, instanceId);
@@ -616,6 +614,28 @@ class ContainerManager {
616
614
  // Ignore
617
615
  }
618
616
  }
617
+ buildDockerImage(dockerFile, imageName) {
618
+ const taskName = `Building docker image: ${imageName}`;
619
+ const processor = async (task) => {
620
+ const timeStarted = Date.now();
621
+ const stream = await this.docker().buildImage({
622
+ context: path_1.default.dirname(dockerFile),
623
+ src: [path_1.default.basename(dockerFile)],
624
+ }, {
625
+ t: imageName,
626
+ dockerfile: path_1.default.basename(dockerFile),
627
+ });
628
+ await processJsonStream(`image:build:${imageName}`, stream, (data) => {
629
+ if (data.stream) {
630
+ // Emit raw output to the task log
631
+ task.addLog(data.stream);
632
+ }
633
+ });
634
+ };
635
+ return taskManager_1.taskManager.add(`docker:image:build:${imageName}`, processor, {
636
+ name: taskName,
637
+ });
638
+ }
619
639
  }
620
640
  function readLogBuffer(logBuffer) {
621
641
  const out = [];
@@ -830,15 +850,73 @@ class ContainerInfo {
830
850
  timestamps: true,
831
851
  });
832
852
  const out = readLogBuffer(logs);
833
- if (out.length === 0) {
834
- out.push({
835
- time: Date.now(),
836
- message: 'No logs found for container',
837
- level: 'INFO',
838
- source: 'stdout',
839
- });
853
+ if (out.length > 0) {
854
+ return out;
840
855
  }
841
- return out;
856
+ const status = await this.status();
857
+ const healthLogs = status?.Health?.Log
858
+ ? status?.Health?.Log.map((log) => {
859
+ return {
860
+ source: 'stdout',
861
+ level: log.ExitCode === 0 ? 'INFO' : 'ERROR',
862
+ time: Date.now(),
863
+ message: 'Health check: ' + log.Output,
864
+ };
865
+ })
866
+ : [];
867
+ if (status?.Running) {
868
+ return [
869
+ {
870
+ source: 'stdout',
871
+ level: 'INFO',
872
+ time: Date.now(),
873
+ message: 'Container is starting...',
874
+ },
875
+ ...healthLogs,
876
+ ];
877
+ }
878
+ if (status?.Restarting) {
879
+ return [
880
+ {
881
+ source: 'stdout',
882
+ level: 'INFO',
883
+ time: Date.now(),
884
+ message: 'Container is restarting...',
885
+ },
886
+ ...healthLogs,
887
+ ];
888
+ }
889
+ if (status?.Paused) {
890
+ return [
891
+ {
892
+ source: 'stdout',
893
+ level: 'INFO',
894
+ time: Date.now(),
895
+ message: 'Container is paused...',
896
+ },
897
+ ...healthLogs,
898
+ ];
899
+ }
900
+ if (status?.Error) {
901
+ return [
902
+ {
903
+ source: 'stderr',
904
+ level: 'ERROR',
905
+ time: Date.now(),
906
+ message: 'Container failed to start:\n' + status.Error,
907
+ },
908
+ ...healthLogs,
909
+ ];
910
+ }
911
+ return [
912
+ {
913
+ source: 'stdout',
914
+ level: 'INFO',
915
+ time: Date.now(),
916
+ message: 'Container not running',
917
+ ...healthLogs,
918
+ },
919
+ ];
842
920
  }
843
921
  }
844
922
  exports.ContainerInfo = ContainerInfo;
@@ -45,7 +45,23 @@ export declare class InstanceManager {
45
45
  private requestInstanceStatus;
46
46
  private isSingletonOperator;
47
47
  private getKindForAssetRef;
48
+ /**
49
+ * Get the kind of an asset. Use the maxDepth parameter to specify how deep to look for the
50
+ * kind. For example, if maxDepth is 2, the method will look for the kind of the asset and then
51
+ * the kind of the kind.
52
+ * @param assetRef The asset reference
53
+ * @param maxDepth The maximum depth to look for the kind
54
+ * @returns The kind of the asset or null if not found
55
+ */
56
+ private getDeepKindForAssetRef;
48
57
  private isUsingKind;
49
58
  private getAllInstancesForKind;
59
+ /**
60
+ * Get the ids for all block instances except the ones of the specified kind
61
+ * @param systemId The plan reference id
62
+ * @param kind The kind to exclude. Can be a string or an array of strings
63
+ * @returns An array of block instance ids
64
+ */
65
+ private getAllInstancesExceptKind;
50
66
  }
51
67
  export declare const instanceManager: InstanceManager;
@@ -212,7 +212,9 @@ class InstanceManager {
212
212
  systemId = (0, nodejs_utils_1.normalizeKapetaUri)(systemId);
213
213
  const instance = lodash_1.default.find(this._instances, { systemId, instanceId });
214
214
  if (instance && instance.owner === types_1.InstanceOwner.EXTERNAL && instance.status !== types_1.InstanceStatus.STOPPED) {
215
- instance.status = types_1.InstanceStatus.STOPPED;
215
+ if (instance.status != types_1.InstanceStatus.FAILED) {
216
+ instance.status = types_1.InstanceStatus.STOPPED;
217
+ }
216
218
  instance.pid = null;
217
219
  instance.health = null;
218
220
  socketManager_1.socketManager.emitSystemEvent(systemId, socketManager_1.EVENT_STATUS_CHANGED, instance);
@@ -230,11 +232,12 @@ class InstanceManager {
230
232
  throw new Error(`No blocks found in plan: ${systemId}`);
231
233
  }
232
234
  return taskManager_1.taskManager.add(`plan:start:${systemId}`, async () => {
233
- let promises = [];
234
- let errors = [];
235
- for (let blockInstance of Object.values(plan.spec.blocks)) {
235
+ const promises = [];
236
+ const errors = [];
237
+ const instanceIds = await this.getAllInstancesExceptKind(systemId, types_1.KIND_BLOCK_TYPE_EXECUTABLE);
238
+ for (const instanceId of instanceIds) {
236
239
  try {
237
- promises.push(this.start(systemId, blockInstance.id).then((taskOrInstance) => {
240
+ promises.push(this.start(systemId, instanceId).then((taskOrInstance) => {
238
241
  if (taskOrInstance instanceof taskManager_1.Task) {
239
242
  return taskOrInstance.wait();
240
243
  }
@@ -449,7 +452,7 @@ class InstanceManager {
449
452
  // Definition not found
450
453
  return Promise.resolve();
451
454
  }
452
- if (operatorManager_1.KIND_RESOURCE_OPERATOR.toLowerCase() !== asset.definition.kind.toLowerCase()) {
455
+ if (types_1.KIND_RESOURCE_OPERATOR.toLowerCase() !== asset.definition.kind.toLowerCase()) {
453
456
  // Not an operator
454
457
  return Promise.resolve();
455
458
  }
@@ -500,8 +503,7 @@ class InstanceManager {
500
503
  ];
501
504
  const out = await this.saveInternalInstance({
502
505
  ...instance,
503
- type: types_1.InstanceType.UNKNOWN,
504
- pid: null,
506
+ type: types_1.InstanceType.DOCKER,
505
507
  health: null,
506
508
  portType: DEFAULT_HEALTH_PORT_TYPE,
507
509
  status: types_1.InstanceStatus.FAILED,
@@ -621,9 +623,8 @@ class InstanceManager {
621
623
  }
622
624
  if (instance.status !== newStatus) {
623
625
  const oldStatus = instance.status;
624
- const skipUpdate = (newStatus === types_1.InstanceStatus.STOPPED && instance.status === types_1.InstanceStatus.FAILED) ||
625
- ([types_1.InstanceStatus.READY, types_1.InstanceStatus.UNHEALTHY].includes(newStatus) &&
626
- instance.status === types_1.InstanceStatus.STOPPING) ||
626
+ const skipUpdate = ([types_1.InstanceStatus.READY, types_1.InstanceStatus.UNHEALTHY].includes(newStatus) &&
627
+ instance.status === types_1.InstanceStatus.STOPPING) ||
627
628
  (newStatus === types_1.InstanceStatus.STOPPED &&
628
629
  instance.status === types_1.InstanceStatus.STARTING &&
629
630
  instance.desiredStatus === types_1.DesiredInstanceStatus.RUN);
@@ -636,7 +637,7 @@ class InstanceManager {
636
637
  }
637
638
  }
638
639
  if (instance.desiredStatus === types_1.DesiredInstanceStatus.RUN &&
639
- [types_1.InstanceStatus.STOPPED, types_1.InstanceStatus.FAILED, types_1.InstanceStatus.STOPPING].includes(newStatus)) {
640
+ [types_1.InstanceStatus.STOPPED, types_1.InstanceStatus.STOPPING].includes(newStatus)) {
640
641
  //If the instance is stopped but we want it to run, start it
641
642
  try {
642
643
  await this.start(instance.systemId, instance.instanceId);
@@ -707,10 +708,17 @@ class InstanceManager {
707
708
  return types_1.InstanceStatus.READY;
708
709
  }
709
710
  if (statusType === 'created') {
711
+ if (state.ExitCode !== 0) {
712
+ // Failed during creation
713
+ return types_1.InstanceStatus.FAILED;
714
+ }
710
715
  return types_1.InstanceStatus.STARTING;
711
716
  }
712
717
  if (statusType === 'exited' || statusType === 'dead') {
713
- return types_1.InstanceStatus.STOPPED;
718
+ if (state.ExitCode === 0) {
719
+ return types_1.InstanceStatus.STOPPED;
720
+ }
721
+ return types_1.InstanceStatus.FAILED;
714
722
  }
715
723
  if (statusType === 'removing') {
716
724
  return types_1.InstanceStatus.BUSY;
@@ -776,7 +784,7 @@ class InstanceManager {
776
784
  if (!provider) {
777
785
  return false;
778
786
  }
779
- if ((0, nodejs_utils_1.parseKapetaUri)(provider.kind).fullName === operatorManager_1.KIND_BLOCK_OPERATOR) {
787
+ if ((0, nodejs_utils_1.parseKapetaUri)(provider.kind).fullName === types_1.KIND_BLOCK_TYPE_OPERATOR) {
780
788
  const localConfig = provider.data.spec.local;
781
789
  return localConfig.singleton ?? false;
782
790
  }
@@ -789,6 +797,36 @@ class InstanceManager {
789
797
  }
790
798
  return block.data.kind;
791
799
  }
800
+ /**
801
+ * Get the kind of an asset. Use the maxDepth parameter to specify how deep to look for the
802
+ * kind. For example, if maxDepth is 2, the method will look for the kind of the asset and then
803
+ * the kind of the kind.
804
+ * @param assetRef The asset reference
805
+ * @param maxDepth The maximum depth to look for the kind
806
+ * @returns The kind of the asset or null if not found
807
+ */
808
+ async getDeepKindForAssetRef(assetRef, maxDepth) {
809
+ if (maxDepth <= 0) {
810
+ return null;
811
+ }
812
+ try {
813
+ const asset = await assetManager_1.assetManager.getAsset(assetRef);
814
+ if (!asset || !asset.data.kind) {
815
+ return null;
816
+ }
817
+ if (maxDepth === 1) {
818
+ return asset.data.kind;
819
+ }
820
+ else {
821
+ // Recurse with the kind of the current block and one less depth
822
+ return await this.getDeepKindForAssetRef(asset.data.kind, maxDepth - 1);
823
+ }
824
+ }
825
+ catch (error) {
826
+ console.error('Error fetching kind for assetRef:', assetRef, error);
827
+ return null;
828
+ }
829
+ }
792
830
  async isUsingKind(ref, kind) {
793
831
  const assetKind = await this.getKindForAssetRef(ref);
794
832
  if (!assetKind) {
@@ -809,6 +847,32 @@ class InstanceManager {
809
847
  }
810
848
  return out;
811
849
  }
850
+ /**
851
+ * Get the ids for all block instances except the ones of the specified kind
852
+ * @param systemId The plan reference id
853
+ * @param kind The kind to exclude. Can be a string or an array of strings
854
+ * @returns An array of block instance ids
855
+ */
856
+ async getAllInstancesExceptKind(systemId, kind) {
857
+ const plan = await assetManager_1.assetManager.getPlan(systemId);
858
+ if (!plan?.spec?.blocks) {
859
+ return [];
860
+ }
861
+ const out = [];
862
+ const excludedKinds = kind instanceof Array ? kind : [kind];
863
+ for (const block of plan.spec.blocks) {
864
+ const blockKindOfKind = await this.getDeepKindForAssetRef(block.block.ref, 2);
865
+ if (!blockKindOfKind) {
866
+ continue;
867
+ }
868
+ const shouldIncludeBlock = excludedKinds.some((excludedKind) => excludedKind === (0, nodejs_utils_1.parseKapetaUri)(blockKindOfKind).fullName) ===
869
+ false;
870
+ if (shouldIncludeBlock) {
871
+ out.push(block.id);
872
+ }
873
+ }
874
+ return out;
875
+ }
812
876
  }
813
877
  exports.InstanceManager = InstanceManager;
814
878
  exports.instanceManager = new InstanceManager();
@@ -4,13 +4,12 @@
4
4
  */
5
5
  import { DefinitionInfo } from '@kapeta/local-cluster-config';
6
6
  import { ContainerInfo } from './containerManager';
7
- import { EnvironmentType, LocalImageOptions, OperatorInfo } from './types';
8
- export declare const KIND_RESOURCE_OPERATOR = "core/resource-type-operator";
9
- export declare const KIND_BLOCK_OPERATOR = "core/block-type-operator";
7
+ import { EnvironmentType, OperatorInfo } from './types';
8
+ import { LocalInstance } from '@kapeta/schemas';
10
9
  declare class Operator {
11
10
  private readonly _data;
12
11
  constructor(data: DefinitionInfo);
13
- getLocalData(): LocalImageOptions;
12
+ getLocalData(): LocalInstance;
14
13
  getDefinitionInfo(): DefinitionInfo;
15
14
  getCredentials(): any;
16
15
  }
@@ -7,21 +7,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7
7
  return (mod && mod.__esModule) ? mod : { "default": mod };
8
8
  };
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.operatorManager = exports.KIND_BLOCK_OPERATOR = exports.KIND_RESOURCE_OPERATOR = void 0;
10
+ exports.operatorManager = void 0;
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const md5_1 = __importDefault(require("md5"));
13
13
  const serviceManager_1 = require("./serviceManager");
14
14
  const storageService_1 = require("./storageService");
15
15
  const containerManager_1 = require("./containerManager");
16
16
  const fs_extra_1 = __importDefault(require("fs-extra"));
17
+ const types_1 = require("./types");
17
18
  const definitionsManager_1 = require("./definitionsManager");
18
19
  const utils_1 = require("./utils/utils");
19
20
  const nodejs_utils_1 = require("@kapeta/nodejs-utils");
20
21
  const lodash_1 = __importDefault(require("lodash"));
21
22
  const async_lock_1 = __importDefault(require("async-lock"));
22
23
  const taskManager_1 = require("./taskManager");
23
- exports.KIND_RESOURCE_OPERATOR = 'core/resource-type-operator';
24
- exports.KIND_BLOCK_OPERATOR = 'core/block-type-operator';
25
24
  const KIND_PLAN = 'core/plan';
26
25
  class Operator {
27
26
  _data;
@@ -52,7 +51,7 @@ class OperatorManager {
52
51
  * Get operator definition for resource type
53
52
  */
54
53
  async getOperator(fullName, version) {
55
- const operators = await definitionsManager_1.definitionsManager.getDefinitions([exports.KIND_RESOURCE_OPERATOR, exports.KIND_BLOCK_OPERATOR]);
54
+ const operators = await definitionsManager_1.definitionsManager.getDefinitions([types_1.KIND_RESOURCE_OPERATOR, types_1.KIND_BLOCK_TYPE_OPERATOR]);
56
55
  const operator = operators.find((operator) => operator.definition &&
57
56
  operator.definition.metadata &&
58
57
  operator.definition.metadata.name &&
@@ -3,11 +3,13 @@
3
3
  * SPDX-License-Identifier: BUSL-1.1
4
4
  */
5
5
  /// <reference types="node" />
6
+ import { LogEntry } from './types';
7
+ import { Task } from './taskManager';
6
8
  export declare class ProgressListener {
7
9
  private readonly systemId;
8
10
  private readonly instanceId;
9
11
  constructor(systemId?: string, instanceId?: string);
10
- private emitLog;
12
+ protected emitLog(payload: Omit<LogEntry, 'time' | 'source'>): void;
11
13
  run(command: string, directory?: string): Promise<{
12
14
  exit: number;
13
15
  signal: NodeJS.Signals | null;
@@ -22,3 +24,8 @@ export declare class ProgressListener {
22
24
  info(msg: string, ...args: any[]): void;
23
25
  debug(msg: string, ...args: any[]): void;
24
26
  }
27
+ export declare class TaskProgressListener extends ProgressListener {
28
+ private readonly task;
29
+ constructor(task: Task);
30
+ protected emitLog(payload: Omit<LogEntry, 'time' | 'source'>): void;
31
+ }
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: BUSL-1.1
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ProgressListener = void 0;
7
+ exports.TaskProgressListener = exports.ProgressListener = void 0;
8
8
  const nodejs_process_1 = require("@kapeta/nodejs-process");
9
9
  const socketManager_1 = require("./socketManager");
10
10
  const node_util_1 = require("node:util");
@@ -120,3 +120,14 @@ class ProgressListener {
120
120
  }
121
121
  }
122
122
  exports.ProgressListener = ProgressListener;
123
+ class TaskProgressListener extends ProgressListener {
124
+ task;
125
+ constructor(task) {
126
+ super();
127
+ this.task = task;
128
+ }
129
+ emitLog(payload) {
130
+ this.task.addLog(payload.message, payload.level);
131
+ }
132
+ }
133
+ exports.TaskProgressListener = TaskProgressListener;
@@ -164,16 +164,17 @@ class RepositoryManager extends node_events_1.EventEmitter {
164
164
  async scheduleInstallation(refs) {
165
165
  //We make sure to only install one asset at a time - otherwise unexpected things might happen
166
166
  const createInstaller = (ref) => {
167
- return async () => {
167
+ return async (task) => {
168
168
  if (await definitionsManager_1.definitionsManager.exists(ref)) {
169
169
  return;
170
170
  }
171
+ const progressListener = new progressListener_1.TaskProgressListener(task);
171
172
  //console.log(`Installing asset: ${ref}`);
172
173
  //Auto-install missing asset
173
174
  try {
174
175
  //We change to a temp dir to avoid issues with the current working directory
175
176
  process.chdir(node_os_1.default.tmpdir());
176
- await nodejs_registry_utils_1.Actions.install(new progressListener_1.ProgressListener(), [ref], {});
177
+ await nodejs_registry_utils_1.Actions.install(progressListener, [ref], {});
177
178
  }
178
179
  catch (e) {
179
180
  console.error(`Failed to install asset: ${ref}`, e);
@@ -2,6 +2,7 @@
2
2
  * Copyright 2023 Kapeta Inc.
3
3
  * SPDX-License-Identifier: BUSL-1.1
4
4
  */
5
+ import { LogLevel } from './types';
5
6
  export type TaskRunner<T> = (task: Task<T>) => Promise<T>;
6
7
  export declare enum TaskStatus {
7
8
  PENDING = "PENDING",
@@ -44,6 +45,7 @@ export declare class Task<T = void> implements TaskData<T> {
44
45
  set errorMessage(errorMessage: string | undefined);
45
46
  set metadata(metadata: TaskMetadata);
46
47
  emitUpdate(): void;
48
+ addLog(log: string, level?: LogLevel): void;
47
49
  wait(): Promise<T>;
48
50
  toData(): {
49
51
  id: string;
@@ -12,6 +12,7 @@ const socketManager_1 = require("./socketManager");
12
12
  const EVENT_TASK_UPDATED = 'task-updated';
13
13
  const EVENT_TASK_ADDED = 'task-added';
14
14
  const EVENT_TASK_REMOVED = 'task-removed';
15
+ const EVENT_TASK_LOG = 'task-log';
15
16
  var TaskStatus;
16
17
  (function (TaskStatus) {
17
18
  TaskStatus["PENDING"] = "PENDING";
@@ -54,6 +55,14 @@ class Task {
54
55
  emitUpdate() {
55
56
  socketManager_1.socketManager.emitGlobal(EVENT_TASK_UPDATED, this.toData());
56
57
  }
58
+ addLog(log, level = 'INFO') {
59
+ socketManager_1.socketManager.emitGlobal(EVENT_TASK_LOG, {
60
+ id: this.id,
61
+ message: log,
62
+ level,
63
+ time: Date.now(),
64
+ });
65
+ }
57
66
  async wait() {
58
67
  return this.future.promise;
59
68
  }