@kapeta/local-cluster-service 0.17.0 → 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.
- package/CHANGELOG.md +7 -0
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/src/assetManager.d.ts +2 -2
- package/dist/cjs/src/assetManager.js +16 -16
- package/dist/cjs/src/assets/routes.js +2 -2
- package/dist/cjs/src/authManager.d.ts +12 -0
- package/dist/cjs/src/authManager.js +60 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +1 -1
- package/dist/cjs/src/codeGeneratorManager.js +3 -3
- package/dist/cjs/src/configManager.js +2 -2
- package/dist/cjs/src/definitionsManager.d.ts +7 -6
- package/dist/cjs/src/definitionsManager.js +102 -18
- package/dist/cjs/src/instanceManager.d.ts +1 -1
- package/dist/cjs/src/instanceManager.js +4 -4
- package/dist/cjs/src/instances/routes.js +2 -2
- package/dist/cjs/src/operatorManager.d.ts +1 -1
- package/dist/cjs/src/operatorManager.js +7 -9
- package/dist/cjs/src/providerManager.d.ts +2 -1
- package/dist/cjs/src/providerManager.js +23 -15
- package/dist/cjs/src/repositoryManager.d.ts +2 -2
- package/dist/cjs/src/repositoryManager.js +8 -9
- package/dist/cjs/src/utils/BlockInstanceRunner.js +6 -8
- package/dist/esm/index.js +4 -2
- package/dist/esm/src/assetManager.d.ts +2 -2
- package/dist/esm/src/assetManager.js +16 -16
- package/dist/esm/src/assets/routes.js +2 -2
- package/dist/esm/src/authManager.d.ts +12 -0
- package/dist/esm/src/authManager.js +60 -0
- package/dist/esm/src/codeGeneratorManager.d.ts +1 -1
- package/dist/esm/src/codeGeneratorManager.js +3 -3
- package/dist/esm/src/configManager.js +2 -2
- package/dist/esm/src/definitionsManager.d.ts +7 -6
- package/dist/esm/src/definitionsManager.js +102 -18
- package/dist/esm/src/instanceManager.d.ts +1 -1
- package/dist/esm/src/instanceManager.js +4 -4
- package/dist/esm/src/instances/routes.js +2 -2
- package/dist/esm/src/operatorManager.d.ts +1 -1
- package/dist/esm/src/operatorManager.js +7 -9
- package/dist/esm/src/providerManager.d.ts +2 -1
- package/dist/esm/src/providerManager.js +23 -15
- package/dist/esm/src/repositoryManager.d.ts +2 -2
- package/dist/esm/src/repositoryManager.js +8 -9
- package/dist/esm/src/utils/BlockInstanceRunner.js +6 -8
- package/index.ts +4 -2
- package/package.json +1 -1
- package/src/assetManager.ts +18 -16
- package/src/assets/routes.ts +2 -2
- package/src/authManager.ts +62 -0
- package/src/codeGeneratorManager.ts +3 -3
- package/src/configManager.ts +2 -2
- package/src/definitionsManager.ts +132 -17
- package/src/instanceManager.ts +4 -4
- package/src/instances/routes.ts +2 -2
- package/src/operatorManager.ts +7 -12
- package/src/providerManager.ts +27 -19
- package/src/repositoryManager.ts +8 -11
- package/src/utils/BlockInstanceRunner.ts +6 -8
@@ -1,5 +1,6 @@
|
|
1
|
+
import { DefinitionInfo } from '@kapeta/local-cluster-config';
|
1
2
|
declare class ProviderManager {
|
2
|
-
getWebProviders():
|
3
|
+
getWebProviders(): Promise<DefinitionInfo[]>;
|
3
4
|
getProviderWebJS(handle: string, name: string, version: string, sourceMap?: boolean): Promise<unknown>;
|
4
5
|
}
|
5
6
|
export declare const providerManager: ProviderManager;
|
@@ -11,8 +11,9 @@ const cacheManager_1 = require("./cacheManager");
|
|
11
11
|
const request_1 = __importDefault(require("request"));
|
12
12
|
const PROVIDER_FILE_BASE = 'https://providers.kapeta.com/files';
|
13
13
|
class ProviderManager {
|
14
|
-
getWebProviders() {
|
15
|
-
|
14
|
+
async getWebProviders() {
|
15
|
+
const providers = await definitionsManager_1.definitionsManager.getProviderDefinitions();
|
16
|
+
return providers.filter((providerDefinition) => providerDefinition.hasWeb);
|
16
17
|
}
|
17
18
|
async getProviderWebJS(handle, name, version, sourceMap = false) {
|
18
19
|
const fullName = `${handle}/${name}`;
|
@@ -22,7 +23,8 @@ class ProviderManager {
|
|
22
23
|
if (file && (await fs_extra_1.default.pathExists(file))) {
|
23
24
|
return fs_extra_1.default.readFile(file, 'utf8');
|
24
25
|
}
|
25
|
-
const
|
26
|
+
const providers = await this.getWebProviders();
|
27
|
+
const installedProvider = providers.find((providerDefinition) => {
|
26
28
|
return providerDefinition.definition.metadata.name === fullName && providerDefinition.version === version;
|
27
29
|
});
|
28
30
|
if (installedProvider) {
|
@@ -57,16 +59,22 @@ class ProviderManager {
|
|
57
59
|
});
|
58
60
|
}
|
59
61
|
}
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
providerDefinitions.
|
64
|
-
console.log('
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
}
|
69
|
-
|
70
|
-
|
71
|
-
|
62
|
+
definitionsManager_1.definitionsManager
|
63
|
+
.getProviderDefinitions()
|
64
|
+
.then((providerDefinitions) => {
|
65
|
+
if (providerDefinitions.length > 0) {
|
66
|
+
console.log('## Loaded the following providers ##');
|
67
|
+
providerDefinitions.forEach((providerDefinition) => {
|
68
|
+
console.log(' - %s[%s:%s]', providerDefinition.definition.kind, providerDefinition.definition.metadata.name, providerDefinition.version);
|
69
|
+
console.log(' from %s', providerDefinition.path);
|
70
|
+
});
|
71
|
+
console.log('##');
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
console.log('## No providers found ##');
|
75
|
+
}
|
76
|
+
})
|
77
|
+
.catch((e) => {
|
78
|
+
console.error('Failed to load providers', e);
|
79
|
+
});
|
72
80
|
exports.providerManager = new ProviderManager();
|
@@ -12,8 +12,8 @@ declare class RepositoryManager {
|
|
12
12
|
*/
|
13
13
|
setSourceOfChangeFor(file: string, source: SourceOfChange): Promise<void>;
|
14
14
|
clearSourceOfChangeFor(file: string): Promise<void>;
|
15
|
-
ensureDefaultProviders(): void
|
16
|
-
private
|
15
|
+
ensureDefaultProviders(): Promise<void>;
|
16
|
+
private scheduleInstallation;
|
17
17
|
ensureAsset(handle: string, name: string, version: string, wait?: boolean): Promise<undefined | Task[]>;
|
18
18
|
}
|
19
19
|
export declare const repositoryManager: RepositoryManager;
|
@@ -53,18 +53,18 @@ class RepositoryManager {
|
|
53
53
|
clearSourceOfChangeFor(file) {
|
54
54
|
return this.watcher.clearSourceOfChangeFor(file);
|
55
55
|
}
|
56
|
-
ensureDefaultProviders() {
|
56
|
+
async ensureDefaultProviders() {
|
57
57
|
socketManager_1.socketManager.emitGlobal(EVENT_DEFAULT_PROVIDERS_START, { providers: DEFAULT_PROVIDERS });
|
58
|
-
const tasks = this.
|
58
|
+
const tasks = await this.scheduleInstallation(DEFAULT_PROVIDERS);
|
59
59
|
Promise.allSettled(tasks.map((t) => t.wait())).then(() => {
|
60
60
|
socketManager_1.socketManager.emitGlobal(EVENT_DEFAULT_PROVIDERS_END, {});
|
61
61
|
});
|
62
62
|
}
|
63
|
-
|
63
|
+
async scheduleInstallation(refs) {
|
64
64
|
//We make sure to only install one asset at a time - otherwise unexpected things might happen
|
65
65
|
const createInstaller = (ref) => {
|
66
66
|
return async () => {
|
67
|
-
if (definitionsManager_1.definitionsManager.exists(ref)) {
|
67
|
+
if (await definitionsManager_1.definitionsManager.exists(ref)) {
|
68
68
|
return;
|
69
69
|
}
|
70
70
|
//console.log(`Installing asset: ${ref}`);
|
@@ -89,7 +89,7 @@ class RepositoryManager {
|
|
89
89
|
continue;
|
90
90
|
}
|
91
91
|
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
92
|
-
if (definitionsManager_1.definitionsManager.exists(ref)) {
|
92
|
+
if (await definitionsManager_1.definitionsManager.exists(ref)) {
|
93
93
|
continue;
|
94
94
|
}
|
95
95
|
const task = taskManager_1.taskManager.add(`asset:install:${ref}`, createInstaller(ref), {
|
@@ -107,8 +107,7 @@ class RepositoryManager {
|
|
107
107
|
//TODO: Get dependencies for local asset
|
108
108
|
return;
|
109
109
|
}
|
110
|
-
const
|
111
|
-
const installedAsset = definitions.find((d) => d.definition.metadata.name === fullName && d.version === version);
|
110
|
+
const installedAsset = await definitionsManager_1.definitionsManager.getDefinition(`${fullName}:${version}`);
|
112
111
|
let assetVersion;
|
113
112
|
try {
|
114
113
|
assetVersion = await this._registryService.getVersion(fullName, version);
|
@@ -125,13 +124,13 @@ class RepositoryManager {
|
|
125
124
|
}
|
126
125
|
let tasks = undefined;
|
127
126
|
if (!installedAsset) {
|
128
|
-
tasks = this.
|
127
|
+
tasks = await this.scheduleInstallation([ref]);
|
129
128
|
}
|
130
129
|
else {
|
131
130
|
//Ensure dependencies are installed
|
132
131
|
const refs = assetVersion.dependencies.map((dep) => dep.name);
|
133
132
|
if (refs.length > 0) {
|
134
|
-
tasks = this.
|
133
|
+
tasks = await this.scheduleInstallation(refs);
|
135
134
|
}
|
136
135
|
}
|
137
136
|
if (tasks && wait) {
|
@@ -27,8 +27,9 @@ const DOCKER_ENV_VARS = [
|
|
27
27
|
`KAPETA_LOCAL_CLUSTER_HOST=host.docker.internal`,
|
28
28
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
29
29
|
];
|
30
|
-
function getProvider(uri) {
|
31
|
-
|
30
|
+
async function getProvider(uri) {
|
31
|
+
const providers = await definitionsManager_1.definitionsManager.getProviderDefinitions();
|
32
|
+
return providers.find((provider) => {
|
32
33
|
const ref = `${provider.definition.metadata.name}:${provider.version}`;
|
33
34
|
return (0, nodejs_utils_1.parseKapetaUri)(ref).id === uri.id;
|
34
35
|
});
|
@@ -76,15 +77,12 @@ class BlockInstanceRunner {
|
|
76
77
|
if (!blockUri.version) {
|
77
78
|
blockUri.version = 'local';
|
78
79
|
}
|
79
|
-
const assetVersion = definitionsManager_1.definitionsManager.
|
80
|
-
const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
|
81
|
-
return (0, nodejs_utils_1.parseKapetaUri)(ref).id === blockUri.id;
|
82
|
-
});
|
80
|
+
const assetVersion = await definitionsManager_1.definitionsManager.getDefinition(blockUri.id);
|
83
81
|
if (!assetVersion) {
|
84
82
|
throw new Error(`Block definition not found: ${blockUri.id}`);
|
85
83
|
}
|
86
84
|
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.kind);
|
87
|
-
const providerVersion = getProvider(kindUri);
|
85
|
+
const providerVersion = await getProvider(kindUri);
|
88
86
|
if (!providerVersion) {
|
89
87
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
90
88
|
}
|
@@ -120,7 +118,7 @@ class BlockInstanceRunner {
|
|
120
118
|
throw new Error('Missing target kind in block definition');
|
121
119
|
}
|
122
120
|
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.spec?.target?.kind);
|
123
|
-
const targetVersion = getProvider(kindUri);
|
121
|
+
const targetVersion = await getProvider(kindUri);
|
124
122
|
if (!targetVersion) {
|
125
123
|
throw new Error(`Target not found: ${kindUri.id}`);
|
126
124
|
}
|
package/index.ts
CHANGED
@@ -23,6 +23,7 @@ import request from 'request';
|
|
23
23
|
import { repositoryManager } from './src/repositoryManager';
|
24
24
|
import { ensureCLI } from './src/utils/commandLineUtils';
|
25
25
|
import { defaultProviderInstaller } from './src/utils/DefaultProviderInstaller';
|
26
|
+
import { authManager } from './src/authManager';
|
26
27
|
|
27
28
|
export type LocalClusterService = HTTP.Server & { host?: string; port?: number };
|
28
29
|
|
@@ -147,6 +148,7 @@ export default {
|
|
147
148
|
}
|
148
149
|
|
149
150
|
await clusterService.init();
|
151
|
+
await authManager.listenForChanges();
|
150
152
|
|
151
153
|
currentServer = createServer();
|
152
154
|
|
@@ -177,7 +179,7 @@ export default {
|
|
177
179
|
|
178
180
|
const bindHost = getBindHost(host);
|
179
181
|
|
180
|
-
currentServer.listen(port, bindHost, () => {
|
182
|
+
currentServer.listen(port, bindHost, async () => {
|
181
183
|
try {
|
182
184
|
ensureCLI().catch((e: any) => console.error('Failed to install CLI.', e));
|
183
185
|
} catch (e: any) {
|
@@ -186,7 +188,7 @@ export default {
|
|
186
188
|
|
187
189
|
try {
|
188
190
|
// Start installation process for all default providers
|
189
|
-
repositoryManager.ensureDefaultProviders();
|
191
|
+
await repositoryManager.ensureDefaultProviders();
|
190
192
|
} catch (e: any) {
|
191
193
|
console.error('Failed to install default providers.', e);
|
192
194
|
}
|
package/package.json
CHANGED
package/src/assetManager.ts
CHANGED
@@ -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
|
-
|
114
|
-
|
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
|
-
|
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
|
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
|
-
|
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}`,
|
package/src/assets/routes.ts
CHANGED
@@ -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
|
);
|
package/src/configManager.ts
CHANGED
@@ -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
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
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
|
-
|
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
|
17
|
-
|
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
|
-
|
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
|
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', () =>
|
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
|
-
|
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
|
}
|
package/src/instanceManager.ts
CHANGED
@@ -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();
|
package/src/instances/routes.ts
CHANGED
@@ -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
|
/**
|