@kapeta/local-cluster-service 0.16.8 → 0.18.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 (96) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cjs/index.js +6 -2
  3. package/dist/cjs/src/assetManager.d.ts +2 -2
  4. package/dist/cjs/src/assetManager.js +16 -16
  5. package/dist/cjs/src/assets/routes.js +2 -2
  6. package/dist/cjs/src/authManager.d.ts +12 -0
  7. package/dist/cjs/src/authManager.js +60 -0
  8. package/dist/cjs/src/codeGeneratorManager.d.ts +1 -1
  9. package/dist/cjs/src/codeGeneratorManager.js +3 -3
  10. package/dist/cjs/src/configManager.js +2 -2
  11. package/dist/cjs/src/definitionsManager.d.ts +7 -6
  12. package/dist/cjs/src/definitionsManager.js +102 -18
  13. package/dist/cjs/src/instanceManager.d.ts +1 -1
  14. package/dist/cjs/src/instanceManager.js +4 -4
  15. package/dist/cjs/src/instances/routes.js +2 -2
  16. package/dist/cjs/src/operatorManager.d.ts +1 -1
  17. package/dist/cjs/src/operatorManager.js +7 -9
  18. package/dist/cjs/src/providerManager.d.ts +2 -1
  19. package/dist/cjs/src/providerManager.js +23 -15
  20. package/dist/cjs/src/repositoryManager.d.ts +2 -2
  21. package/dist/cjs/src/repositoryManager.js +8 -9
  22. package/dist/cjs/src/socketManager.js +6 -0
  23. package/dist/cjs/src/utils/BlockInstanceRunner.js +6 -8
  24. package/dist/cjs/src/utils/DefaultProviderInstaller.d.ts +11 -0
  25. package/dist/cjs/src/utils/DefaultProviderInstaller.js +129 -0
  26. package/dist/esm/index.js +67 -58
  27. package/dist/esm/src/RepositoryWatcher.js +40 -33
  28. package/dist/esm/src/api.js +14 -9
  29. package/dist/esm/src/assetManager.d.ts +2 -2
  30. package/dist/esm/src/assetManager.js +73 -67
  31. package/dist/esm/src/assets/routes.js +23 -18
  32. package/dist/esm/src/attachments/routes.js +14 -9
  33. package/dist/esm/src/authManager.d.ts +12 -0
  34. package/dist/esm/src/authManager.js +60 -0
  35. package/dist/esm/src/cacheManager.js +13 -5
  36. package/dist/esm/src/clusterService.js +6 -3
  37. package/dist/esm/src/codeGeneratorManager.d.ts +1 -1
  38. package/dist/esm/src/codeGeneratorManager.js +20 -14
  39. package/dist/esm/src/config/routes.js +30 -25
  40. package/dist/esm/src/configManager.js +29 -26
  41. package/dist/esm/src/containerManager.js +48 -39
  42. package/dist/esm/src/definitionsManager.d.ts +7 -6
  43. package/dist/esm/src/definitionsManager.js +114 -24
  44. package/dist/esm/src/filesystem/routes.js +21 -16
  45. package/dist/esm/src/filesystemManager.js +23 -17
  46. package/dist/esm/src/identities/routes.js +13 -8
  47. package/dist/esm/src/instanceManager.d.ts +1 -1
  48. package/dist/esm/src/instanceManager.js +165 -158
  49. package/dist/esm/src/instances/routes.js +39 -34
  50. package/dist/esm/src/middleware/cors.js +5 -1
  51. package/dist/esm/src/middleware/kapeta.js +8 -4
  52. package/dist/esm/src/middleware/stringBody.js +5 -1
  53. package/dist/esm/src/networkManager.js +15 -9
  54. package/dist/esm/src/operatorManager.d.ts +1 -1
  55. package/dist/esm/src/operatorManager.js +48 -44
  56. package/dist/esm/src/progressListener.js +16 -12
  57. package/dist/esm/src/providerManager.d.ts +2 -1
  58. package/dist/esm/src/providerManager.js +43 -29
  59. package/dist/esm/src/providers/routes.js +14 -9
  60. package/dist/esm/src/proxy/routes.js +26 -21
  61. package/dist/esm/src/proxy/types/rest.js +29 -22
  62. package/dist/esm/src/proxy/types/web.js +18 -11
  63. package/dist/esm/src/repositoryManager.d.ts +2 -2
  64. package/dist/esm/src/repositoryManager.js +33 -28
  65. package/dist/esm/src/serviceManager.js +25 -19
  66. package/dist/esm/src/socketManager.js +31 -18
  67. package/dist/esm/src/storageService.js +18 -12
  68. package/dist/esm/src/taskManager.js +12 -8
  69. package/dist/esm/src/tasks/routes.js +14 -9
  70. package/dist/esm/src/traffic/routes.js +12 -7
  71. package/dist/esm/src/types.js +11 -8
  72. package/dist/esm/src/utils/BlockInstanceRunner.js +60 -55
  73. package/dist/esm/src/utils/DefaultProviderInstaller.d.ts +11 -0
  74. package/dist/esm/src/utils/DefaultProviderInstaller.js +129 -0
  75. package/dist/esm/src/utils/LogData.js +5 -1
  76. package/dist/esm/src/utils/commandLineUtils.js +12 -7
  77. package/dist/esm/src/utils/pathTemplateParser.js +7 -2
  78. package/dist/esm/src/utils/utils.js +30 -17
  79. package/dist/esm/start.js +7 -2
  80. package/index.ts +7 -2
  81. package/package.json +10 -4
  82. package/src/assetManager.ts +18 -16
  83. package/src/assets/routes.ts +2 -2
  84. package/src/authManager.ts +62 -0
  85. package/src/codeGeneratorManager.ts +3 -3
  86. package/src/configManager.ts +2 -2
  87. package/src/definitionsManager.ts +132 -17
  88. package/src/instanceManager.ts +5 -5
  89. package/src/instances/routes.ts +2 -2
  90. package/src/operatorManager.ts +7 -12
  91. package/src/providerManager.ts +27 -19
  92. package/src/repositoryManager.ts +8 -11
  93. package/src/socketManager.ts +6 -0
  94. package/src/utils/BlockInstanceRunner.ts +6 -8
  95. package/src/utils/DefaultProviderInstaller.ts +141 -0
  96. package/tsconfig.json +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.16.8",
3
+ "version": "0.18.0",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -34,8 +34,8 @@
34
34
  "dev": "nodemon -e js,ts,json ./start.ts",
35
35
  "test": "echo its fine",
36
36
  "clean": "rm -rf ./dist",
37
- "build:esm": "tsc --module esnext --outDir ./dist/esm && echo '{\"type\":\"module\"}' > ./dist/esm/package.json",
38
- "build:cjs": "tsc --module commonjs --outDir ./dist/cjs && echo '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json",
37
+ "build:esm": "tsc --module nodenext --moduleResolution nodenext --outDir ./dist/esm && echo '{\"type\":\"module\"}' > ./dist/esm/package.json",
38
+ "build:cjs": "tsc --outDir ./dist/cjs && echo '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json",
39
39
  "build": "npm run clean && npm run build:esm && npm run build:cjs",
40
40
  "format": "prettier --write .",
41
41
  "lint": "tsc --noEmit && eslint src/**/*.ts",
@@ -57,7 +57,8 @@
57
57
  "express": "4.17.1",
58
58
  "express-promise-router": "^4.1.1",
59
59
  "fs-extra": "^11.1.0",
60
- "glob": "7.1.6",
60
+ "glob": "^7.1.6",
61
+ "gunzip-maybe": "^1.4.2",
61
62
  "lodash": "^4.17.15",
62
63
  "md5": "2.2.1",
63
64
  "node-cache": "^5.1.2",
@@ -66,6 +67,7 @@
66
67
  "request": "2.88.2",
67
68
  "request-promise": "4.2.6",
68
69
  "socket.io": "^4.5.2",
70
+ "tar-stream": "^3.1.6",
69
71
  "typescript": "^5.1.6",
70
72
  "yaml": "^1.6.0"
71
73
  },
@@ -76,10 +78,14 @@
76
78
  "@types/async-lock": "^1.4.0",
77
79
  "@types/express": "^4.17.17",
78
80
  "@types/fs-extra": "^11.0.1",
81
+ "@types/glob": "^8.1.0",
82
+ "@types/gunzip-maybe": "^1.4.0",
79
83
  "@types/lodash": "^4.14.195",
80
84
  "@types/md5": "^2.3.2",
85
+ "@types/node": "^20.5.8",
81
86
  "@types/node-uuid": "^0.0.29",
82
87
  "@types/request": "^2.48.8",
88
+ "@types/tar-stream": "^2.2.2",
83
89
  "eslint": "^8.42.0",
84
90
  "eslint-config-prettier": "^8.8.0",
85
91
  "nodemon": "^2.0.2",
@@ -64,9 +64,9 @@ class AssetManager {
64
64
  * @param {string[]} [assetKinds]
65
65
  * @returns {{path: *, ref: string, data: *, editable: boolean, kind: *, exists: boolean}[]}
66
66
  */
67
- getAssets(assetKinds?: string[]): EnrichedAsset[] {
67
+ async getAssets(assetKinds?: string[]): Promise<EnrichedAsset[]> {
68
68
  if (!assetKinds) {
69
- const blockTypeProviders = definitionsManager.getDefinitions([
69
+ const blockTypeProviders = await definitionsManager.getDefinitions([
70
70
  'core/block-type',
71
71
  'core/block-type-operator',
72
72
  ]);
@@ -76,12 +76,12 @@ class AssetManager {
76
76
  assetKinds.push('core/plan');
77
77
  }
78
78
 
79
- const assets = definitionsManager.getDefinitions(assetKinds);
79
+ const assets = await definitionsManager.getDefinitions(assetKinds);
80
80
 
81
81
  return assets.map(enrichAsset);
82
82
  }
83
83
 
84
- getPlans(): EnrichedAsset[] {
84
+ async getPlans(): Promise<EnrichedAsset[]> {
85
85
  return this.getAssets(['core/plan']);
86
86
  }
87
87
 
@@ -110,18 +110,18 @@ class AssetManager {
110
110
  await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, true);
111
111
  }
112
112
 
113
- let asset = definitionsManager
114
- .getDefinitions()
115
- .map(enrichAsset)
116
- .find((a) => parseKapetaUri(a.ref).equals(uri));
117
- if (autoFetch && !asset) {
113
+ const definitionInfo = await definitionsManager.getDefinition(ref);
114
+ if (autoFetch && !definitionInfo) {
118
115
  throw new Error('Asset not found: ' + ref);
119
116
  }
120
- if (asset) {
117
+
118
+ if (definitionInfo) {
119
+ const asset = enrichAsset(definitionInfo);
121
120
  cacheManager.set(cacheKey, asset, CACHE_TTL);
121
+ return asset;
122
122
  }
123
123
 
124
- return asset;
124
+ return undefined;
125
125
  }
126
126
 
127
127
  async createAsset(
@@ -151,7 +151,7 @@ class AssetManager {
151
151
 
152
152
  const ref = `kapeta://${yaml.metadata.name}:local`;
153
153
 
154
- this.maybeGenerateCode(ref, path, yaml);
154
+ await this.maybeGenerateCode(ref, path, yaml);
155
155
 
156
156
  return asset;
157
157
  }
@@ -178,7 +178,7 @@ class AssetManager {
178
178
  cacheManager.remove(toKey(ref));
179
179
  definitionsManager.clearCache();
180
180
 
181
- this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
181
+ await this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
182
182
  }
183
183
 
184
184
  async importFile(filePath: string) {
@@ -206,7 +206,9 @@ class AssetManager {
206
206
 
207
207
  definitionsManager.clearCache();
208
208
 
209
- return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
209
+ const assets = await this.getAssets();
210
+
211
+ return assets.filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
210
212
  }
211
213
 
212
214
  async unregisterAsset(ref: string) {
@@ -236,9 +238,9 @@ class AssetManager {
236
238
  return await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
237
239
  }
238
240
 
239
- private maybeGenerateCode(ref: string, ymlPath: string, block: BlockDefinition) {
241
+ private async maybeGenerateCode(ref: string, ymlPath: string, block: BlockDefinition) {
240
242
  ref = normalizeKapetaUri(ref);
241
- if (codeGeneratorManager.canGenerateCode(block)) {
243
+ if (await codeGeneratorManager.canGenerateCode(block)) {
242
244
  const assetTitle = block.metadata.title ? block.metadata.title : parseKapetaUri(block.metadata.name).name;
243
245
  taskManager.add(
244
246
  `codegen:${ref}`,
@@ -31,8 +31,8 @@ router.use('/', stringBody);
31
31
  /**
32
32
  * Get all local assets available
33
33
  */
34
- router.get('/', (req: Request, res: Response) => {
35
- res.send(assetManager.getAssets([]));
34
+ router.get('/', async (req: Request, res: Response) => {
35
+ res.send(await assetManager.getAssets([]));
36
36
  });
37
37
 
38
38
  /**
@@ -0,0 +1,62 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import Path from 'node:path';
3
+ import chokidar, { FSWatcher } from 'chokidar';
4
+ import ClusterConfiguration from '@kapeta/local-cluster-config';
5
+ import { WatchEventName } from './types';
6
+ import { definitionsManager } from './definitionsManager';
7
+ import { KapetaAPI } from '@kapeta/nodejs-api-client';
8
+ import { socketManager } from './socketManager';
9
+
10
+ class AuthManager extends EventEmitter {
11
+ private watcher?: FSWatcher;
12
+
13
+ private hadToken: boolean;
14
+
15
+ constructor() {
16
+ super();
17
+ this.hadToken = this.hasToken();
18
+ }
19
+
20
+ public listenForChanges() {
21
+ const parentDir = Path.dirname(ClusterConfiguration.getKapetaBasedir());
22
+ //We watch the parent dir to catch changes to the base dir itself
23
+ this.watcher = chokidar.watch(parentDir, {
24
+ followSymlinks: false,
25
+ ignorePermissionErrors: true,
26
+ disableGlobbing: true,
27
+ persistent: true,
28
+ ignoreInitial: true,
29
+ depth: 1,
30
+ ignored: (path) => {
31
+ return !path.startsWith(ClusterConfiguration.getKapetaBasedir());
32
+ },
33
+ });
34
+ this.watcher.add(ClusterConfiguration.getKapetaBasedir());
35
+ this.watcher.on('all', this.handleFileChange.bind(this));
36
+ this.watcher.on('error', (error) => {
37
+ console.log('Error watching repository', error);
38
+ });
39
+ this.watcher.on('ready', () => {
40
+ console.log('Watching for auth changes: %s', ClusterConfiguration.getKapetaBasedir());
41
+ });
42
+ }
43
+
44
+ private hasToken() {
45
+ const api = new KapetaAPI();
46
+ return api.hasToken();
47
+ }
48
+
49
+ private async handleFileChange(eventName: WatchEventName, path: string) {
50
+ const hasTokenNow = this.hasToken();
51
+ if (this.hadToken !== hasTokenNow) {
52
+ socketManager.emitGlobal('auth-change', {});
53
+ if (hasTokenNow) {
54
+ // Clear the cache in case we need to rewrite the sample plan
55
+ definitionsManager.clearCache();
56
+ }
57
+ this.hadToken = hasTokenNow;
58
+ }
59
+ }
60
+ }
61
+
62
+ export const authManager = new AuthManager();
@@ -10,7 +10,7 @@ const BLOCK_TYPE_KIND = 'core/block-type';
10
10
  class CodeGeneratorManager {
11
11
  async reload() {
12
12
  Targets.reset();
13
- const languageTargets = definitionsManager.getDefinitions(TARGET_KIND);
13
+ const languageTargets = await definitionsManager.getDefinitions(TARGET_KIND);
14
14
  for (const languageTarget of languageTargets) {
15
15
  const key = `${languageTarget.definition.metadata.name}:${languageTarget.version}`;
16
16
  try {
@@ -26,13 +26,13 @@ class CodeGeneratorManager {
26
26
  }
27
27
  }
28
28
 
29
- canGenerateCode(yamlContent: BlockDefinition): boolean {
29
+ async canGenerateCode(yamlContent: BlockDefinition): Promise<boolean> {
30
30
  if (!yamlContent.spec.target?.kind) {
31
31
  //Not all block types have targets
32
32
  return false;
33
33
  }
34
34
 
35
- const blockTypes = definitionsManager.getDefinitions(BLOCK_TYPE_KIND);
35
+ const blockTypes = await definitionsManager.getDefinitions(BLOCK_TYPE_KIND);
36
36
  const blockTypeKinds = blockTypes.map(
37
37
  (blockType) => blockType.definition.metadata.name.toLowerCase() + ':' + blockType.version
38
38
  );
@@ -80,7 +80,7 @@ class ConfigManager {
80
80
  if (systemId) {
81
81
  systemId = normalizeKapetaUri(systemId);
82
82
  }
83
- const planAssets = assetManager.getPlans();
83
+ const planAssets = await assetManager.getPlans();
84
84
 
85
85
  const blockUri = parseKapetaUri(blockRef);
86
86
 
@@ -132,7 +132,7 @@ class ConfigManager {
132
132
  async verifyIdentity(blockRef: string, systemId: string, instanceId: string) {
133
133
  blockRef = normalizeKapetaUri(blockRef);
134
134
  systemId = normalizeKapetaUri(systemId);
135
- const planAssets = assetManager.getPlans();
135
+ const planAssets = await assetManager.getPlans();
136
136
  const systemUri = systemId ? parseKapetaUri(systemId) : null;
137
137
  const blockUri = parseKapetaUri(blockRef);
138
138
  let found = false;
@@ -1,39 +1,154 @@
1
1
  import ClusterConfiguration, { DefinitionInfo } from '@kapeta/local-cluster-config';
2
2
  import { parseKapetaUri } from '@kapeta/nodejs-utils';
3
3
  import { cacheManager, doCached } from './cacheManager';
4
+ import { KapetaAPI } from '@kapeta/nodejs-api-client';
5
+ import { Plan } from '@kapeta/schemas';
6
+ import FS from 'fs-extra';
7
+ import { normalizeKapetaUri } from './utils/utils';
8
+ import YAML from 'yaml';
9
+ import { Actions } from '@kapeta/nodejs-registry-utils';
10
+ import { ProgressListener } from './progressListener';
11
+ import Path from 'path';
12
+
13
+ export const SAMPLE_PLAN_NAME = 'kapeta/sample-nodejs-plan';
14
+
15
+ function applyHandleChange(definition: DefinitionInfo, targetHandle: string) {
16
+ const originalUri = parseKapetaUri(definition.definition.metadata.name);
17
+ definition.definition.metadata.name = `${targetHandle}/${originalUri.name}`;
18
+ return definition;
19
+ }
20
+
21
+ function normalizeFilters(kindFilter?: string | string[]) {
22
+ let resolvedFilters: string[] = [];
23
+
24
+ if (kindFilter) {
25
+ if (Array.isArray(kindFilter)) {
26
+ resolvedFilters = [...kindFilter];
27
+ } else {
28
+ resolvedFilters = [kindFilter];
29
+ }
30
+ }
31
+
32
+ return resolvedFilters.map((k) => k.toLowerCase());
33
+ }
4
34
 
5
35
  class DefinitionsManager {
6
- private getHash(kindFilter?: string | string[]) {
7
- if (kindFilter) {
8
- if (Array.isArray(kindFilter)) {
9
- return kindFilter.join(',');
36
+ private async resolveDefinitionsAndSamples() {
37
+ const definitions = ClusterConfiguration.getDefinitions();
38
+ const samplePlan = definitions.find(
39
+ (d) => d.version === 'local' && d.definition.metadata.name === SAMPLE_PLAN_NAME
40
+ );
41
+
42
+ if (!samplePlan) {
43
+ return definitions;
44
+ }
45
+
46
+ // We will only rewrite the sample plan once since we change the handle to be the users handle
47
+ const api = new KapetaAPI();
48
+ if (!api.hasToken()) {
49
+ // Not logged in yet, so we can't rewrite the sample plan
50
+ return definitions;
51
+ }
52
+ const profile = await api.getCurrentIdentity();
53
+ if (!profile) {
54
+ // Not logged in yet, so we can't rewrite the sample plan
55
+ return definitions;
56
+ }
57
+
58
+ console.log('Rewriting sample plan to use handle %s', profile.handle);
59
+
60
+ applyHandleChange(samplePlan, profile.handle);
61
+
62
+ const planDef = samplePlan.definition as Plan;
63
+
64
+ const blockRefs = new Set<string>();
65
+
66
+ planDef.spec.blocks.forEach((b) => {
67
+ const blockUri = parseKapetaUri(b.block.ref);
68
+ if (blockUri.version === 'local') {
69
+ blockRefs.add(blockUri.id);
70
+ b.block.ref = normalizeKapetaUri(`${profile.handle}/${blockUri.name}:local`);
10
71
  }
11
- return kindFilter;
72
+ });
73
+
74
+ // Rewrite all blocks that are referenced by the sample plan
75
+ const rewrittenBlocks = Array.from(blockRefs)
76
+ .map((ref) =>
77
+ definitions.find(
78
+ (d) => normalizeKapetaUri(d.definition.metadata.name + ':' + d.version) === normalizeKapetaUri(ref)
79
+ )
80
+ )
81
+ .filter((d) => d !== undefined)
82
+ .map((d) => applyHandleChange(d!, profile.handle));
83
+
84
+ // Persist the rewritten assets
85
+ const progressListener = new ProgressListener();
86
+ const rewrittenAssets = [samplePlan, ...rewrittenBlocks];
87
+ const originalRefs = [`${SAMPLE_PLAN_NAME}:local`, ...Array.from(blockRefs)];
88
+
89
+ // Store the original paths on the assets - we'll need them later
90
+ for (const asset of rewrittenAssets) {
91
+ asset.path = await FS.readlink(asset.path);
92
+ asset.ymlPath = Path.join(asset.path, Path.basename(asset.ymlPath));
93
+ }
94
+
95
+ // Uninstall the original assets
96
+ // This removes the symlinks
97
+ console.log('Uninstalling original assets', originalRefs);
98
+ try {
99
+ await Actions.uninstall(progressListener, originalRefs);
100
+ } catch (err) {
101
+ console.warn('Failed to uninstall original assets', err);
12
102
  }
13
- return 'none';
103
+
104
+ for (const asset of rewrittenAssets) {
105
+ console.log('Updating %s ', asset.ymlPath);
106
+ await FS.writeFile(asset.ymlPath, YAML.stringify(asset.definition));
107
+
108
+ console.log('Linking %s ', asset.path);
109
+ await Actions.link(progressListener, asset.path);
110
+ }
111
+
112
+ console.log('Rewrite done for sample plan');
113
+
114
+ // Return the rewritten definitions
115
+ return ClusterConfiguration.getDefinitions();
14
116
  }
15
117
 
16
- private getFullKey(kindFilter?: string | string[]) {
17
- return `definitionsManager:${this.getHash(kindFilter)}`;
118
+ private applyFilters(definitions: DefinitionInfo[], kindFilter: string[]): DefinitionInfo[] {
119
+ if (kindFilter.length === 0) {
120
+ return definitions;
121
+ }
122
+
123
+ return definitions.filter((d) => {
124
+ return kindFilter.includes(d.definition.kind.toLowerCase());
125
+ });
18
126
  }
19
127
 
20
- public getDefinitions(kindFilter?: string | string[]): DefinitionInfo[] {
21
- const key = this.getFullKey(kindFilter);
128
+ public async getDefinitions(kindFilter?: string | string[]): Promise<DefinitionInfo[]> {
129
+ kindFilter = normalizeFilters(kindFilter);
130
+
131
+ const definitions = await doCached<Promise<DefinitionInfo[]>>('definitionsManager:all', () =>
132
+ this.resolveDefinitionsAndSamples()
133
+ );
22
134
 
23
- return doCached<DefinitionInfo[]>(key, () => ClusterConfiguration.getDefinitions(kindFilter));
135
+ return this.applyFilters(definitions, kindFilter);
24
136
  }
25
137
 
26
- public exists(ref: string) {
27
- return !!this.getDefinition(ref);
138
+ public async exists(ref: string) {
139
+ return !!(await this.getDefinition(ref));
28
140
  }
29
141
 
30
- public getProviderDefinitions(): DefinitionInfo[] {
31
- return doCached<DefinitionInfo[]>('providers', () => ClusterConfiguration.getProviderDefinitions());
142
+ public async getProviderDefinitions(): Promise<DefinitionInfo[]> {
143
+ return doCached<DefinitionInfo[]>('definitionsManager:providers', () =>
144
+ ClusterConfiguration.getProviderDefinitions()
145
+ );
32
146
  }
33
147
 
34
- public getDefinition(ref: string) {
148
+ public async getDefinition(ref: string) {
35
149
  const uri = parseKapetaUri(ref);
36
- return this.getDefinitions().find((d) => {
150
+ const definitions = await this.getDefinitions();
151
+ return definitions.find((d) => {
37
152
  if (!uri.version) {
38
153
  return d.definition.metadata.name === uri.fullName;
39
154
  }
@@ -22,7 +22,7 @@ const DEFAULT_HEALTH_PORT_TYPE = 'rest';
22
22
  const MIN_TIME_RUNNING = 30000; //If something didnt run for more than 30 secs - it failed
23
23
 
24
24
  export class InstanceManager {
25
- private _interval: NodeJS.Timer | undefined = undefined;
25
+ private _interval: any = undefined;
26
26
 
27
27
  private readonly _instances: InstanceInfo[] = [];
28
28
 
@@ -54,14 +54,14 @@ export class InstanceManager {
54
54
  return [...this._instances];
55
55
  }
56
56
 
57
- public getInstancesForPlan(systemId: string) {
57
+ public async getInstancesForPlan(systemId: string) {
58
58
  if (!this._instances) {
59
59
  return [];
60
60
  }
61
61
 
62
62
  systemId = normalizeKapetaUri(systemId);
63
63
 
64
- const planInfo = definitionsManager.getDefinition(systemId);
64
+ const planInfo = await definitionsManager.getDefinition(systemId);
65
65
 
66
66
  if (!planInfo) {
67
67
  return [];
@@ -458,9 +458,9 @@ export class InstanceManager {
458
458
 
459
459
  const blockSpec = blockAsset.data.spec as BlockDefinitionSpec;
460
460
  if (blockSpec.consumers) {
461
- const promises = blockSpec.consumers.map((consumer) => {
461
+ const promises = blockSpec.consumers.map(async (consumer) => {
462
462
  const consumerUri = parseKapetaUri(consumer.kind);
463
- const asset = definitionsManager.getDefinition(consumer.kind);
463
+ const asset = await definitionsManager.getDefinition(consumer.kind);
464
464
  if (!asset) {
465
465
  // Definition not found
466
466
  return Promise.resolve();
@@ -21,8 +21,8 @@ router.get('/', (req: Request, res: Response) => {
21
21
  /**
22
22
  * Get all instances
23
23
  */
24
- router.get('/:systemId/instances', (req: Request, res: Response) => {
25
- res.send(instanceManager.getInstancesForPlan(req.params.systemId));
24
+ router.get('/:systemId/instances', async (req: Request, res: Response) => {
25
+ res.send(await instanceManager.getInstancesForPlan(req.params.systemId));
26
26
  });
27
27
 
28
28
  /**
@@ -15,6 +15,7 @@ import AsyncLock from 'async-lock';
15
15
  import { taskManager } from './taskManager';
16
16
 
17
17
  export const KIND_OPERATOR = 'core/resource-type-operator';
18
+ const KIND_PLAN = 'core/plan';
18
19
 
19
20
  class Operator {
20
21
  private readonly _data: DefinitionInfo;
@@ -57,8 +58,8 @@ class OperatorManager {
57
58
  * @param {string} version
58
59
  * @return {Operator}
59
60
  */
60
- getOperator(resourceType: string, version: string) {
61
- const operators = definitionsManager.getDefinitions(KIND_OPERATOR);
61
+ async getOperator(resourceType: string, version: string) {
62
+ const operators = await definitionsManager.getDefinitions(KIND_OPERATOR);
62
63
 
63
64
  const operator: DefinitionInfo | undefined = operators.find(
64
65
  (operator) =>
@@ -92,7 +93,7 @@ class OperatorManager {
92
93
  environment?: EnvironmentType
93
94
  ): Promise<OperatorInfo> {
94
95
  systemId = normalizeKapetaUri(systemId);
95
- const plans = definitionsManager.getDefinitions('core/plan');
96
+ const plans = await definitionsManager.getDefinitions(KIND_PLAN);
96
97
 
97
98
  const planUri = parseKapetaUri(systemId);
98
99
  const currentPlan = plans.find(
@@ -109,13 +110,7 @@ class OperatorManager {
109
110
  throw new Error(`Unknown instance: ${fromServiceId} in plan ${systemId}`);
110
111
  }
111
112
 
112
- const blockUri = parseKapetaUri(currentInstance.block.ref);
113
- const blockDefinition = definitionsManager
114
- .getDefinitions()
115
- .find(
116
- (definition) =>
117
- definition.version === blockUri.version && definition.definition.metadata.name === blockUri.fullName
118
- );
113
+ const blockDefinition = await definitionsManager.getDefinition(currentInstance.block.ref);
119
114
 
120
115
  if (!blockDefinition) {
121
116
  throw new Error(`Unknown block: ${currentInstance.block.ref} in plan ${systemId}`);
@@ -129,7 +124,7 @@ class OperatorManager {
129
124
  }
130
125
 
131
126
  const kindUri = parseKapetaUri(blockResource.kind);
132
- const operator = this.getOperator(resourceType, kindUri.version);
127
+ const operator = await this.getOperator(resourceType, kindUri.version);
133
128
  const credentials = operator.getCredentials();
134
129
  const container = await this.ensureResource(systemId, resourceType, kindUri.version);
135
130
  const portInfo = await container.getPort(portType);
@@ -164,7 +159,7 @@ class OperatorManager {
164
159
  systemId = normalizeKapetaUri(systemId);
165
160
  const key = `${systemId}#${resourceType}:${version}`;
166
161
  return await this.operatorLock.acquire(key, async () => {
167
- const operator = this.getOperator(resourceType, version);
162
+ const operator = await this.getOperator(resourceType, version);
168
163
 
169
164
  const operatorData = operator.getLocalData();
170
165
 
@@ -3,12 +3,14 @@ import FSExtra from 'fs-extra';
3
3
  import { definitionsManager } from './definitionsManager';
4
4
  import { cacheManager } from './cacheManager';
5
5
  import request from 'request';
6
+ import { DefinitionInfo } from '@kapeta/local-cluster-config';
6
7
 
7
8
  const PROVIDER_FILE_BASE = 'https://providers.kapeta.com/files';
8
9
 
9
10
  class ProviderManager {
10
- getWebProviders() {
11
- return definitionsManager.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
11
+ async getWebProviders(): Promise<DefinitionInfo[]> {
12
+ const providers = await definitionsManager.getProviderDefinitions();
13
+ return providers.filter((providerDefinition) => providerDefinition.hasWeb);
12
14
  }
13
15
 
14
16
  async getProviderWebJS(handle: string, name: string, version: string, sourceMap: boolean = false) {
@@ -22,7 +24,8 @@ class ProviderManager {
22
24
  return FSExtra.readFile(file, 'utf8');
23
25
  }
24
26
 
25
- const installedProvider = this.getWebProviders().find((providerDefinition) => {
27
+ const providers = await this.getWebProviders();
28
+ const installedProvider = providers.find((providerDefinition) => {
26
29
  return providerDefinition.definition.metadata.name === fullName && providerDefinition.version === version;
27
30
  });
28
31
 
@@ -63,22 +66,27 @@ class ProviderManager {
63
66
  }
64
67
  }
65
68
 
66
- const providerDefinitions = definitionsManager.getProviderDefinitions();
67
-
68
- if (providerDefinitions.length > 0) {
69
- console.log('## Loaded the following providers ##');
70
- providerDefinitions.forEach((providerDefinition) => {
71
- console.log(
72
- ' - %s[%s:%s]',
73
- providerDefinition.definition.kind,
74
- providerDefinition.definition.metadata.name,
75
- providerDefinition.version
76
- );
77
- console.log(' from %s', providerDefinition.path);
69
+ definitionsManager
70
+ .getProviderDefinitions()
71
+ .then((providerDefinitions) => {
72
+ if (providerDefinitions.length > 0) {
73
+ console.log('## Loaded the following providers ##');
74
+ providerDefinitions.forEach((providerDefinition) => {
75
+ console.log(
76
+ ' - %s[%s:%s]',
77
+ providerDefinition.definition.kind,
78
+ providerDefinition.definition.metadata.name,
79
+ providerDefinition.version
80
+ );
81
+ console.log(' from %s', providerDefinition.path);
82
+ });
83
+ console.log('##');
84
+ } else {
85
+ console.log('## No providers found ##');
86
+ }
87
+ })
88
+ .catch((e) => {
89
+ console.error('Failed to load providers', e);
78
90
  });
79
- console.log('##');
80
- } else {
81
- console.log('## No providers found ##');
82
- }
83
91
 
84
92
  export const providerManager = new ProviderManager();