@kapeta/local-cluster-service 0.0.0-96f91ef
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/.eslintrc.cjs +25 -0
- package/.github/workflows/check-license.yml +17 -0
- package/.github/workflows/main.yml +26 -0
- package/.prettierignore +4 -0
- package/.vscode/launch.json +19 -0
- package/CHANGELOG.md +920 -0
- package/LICENSE +38 -0
- package/README.md +36 -0
- package/definitions.d.ts +35 -0
- package/dist/cjs/index.d.ts +34 -0
- package/dist/cjs/index.js +263 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/RepositoryWatcher.d.ts +30 -0
- package/dist/cjs/src/RepositoryWatcher.js +332 -0
- package/dist/cjs/src/ai/aiClient.d.ts +20 -0
- package/dist/cjs/src/ai/aiClient.js +74 -0
- package/dist/cjs/src/ai/routes.d.ts +7 -0
- package/dist/cjs/src/ai/routes.js +37 -0
- package/dist/cjs/src/ai/transform.d.ts +11 -0
- package/dist/cjs/src/ai/transform.js +239 -0
- package/dist/cjs/src/ai/types.d.ts +40 -0
- package/dist/cjs/src/ai/types.js +2 -0
- package/dist/cjs/src/api.d.ts +7 -0
- package/dist/cjs/src/api.js +29 -0
- package/dist/cjs/src/assetManager.d.ts +41 -0
- package/dist/cjs/src/assetManager.js +274 -0
- package/dist/cjs/src/assets/routes.d.ts +7 -0
- package/dist/cjs/src/assets/routes.js +165 -0
- package/dist/cjs/src/attachments/routes.d.ts +7 -0
- package/dist/cjs/src/attachments/routes.js +72 -0
- package/dist/cjs/src/authManager.d.ts +16 -0
- package/dist/cjs/src/authManager.js +64 -0
- package/dist/cjs/src/cacheManager.d.ts +20 -0
- package/dist/cjs/src/cacheManager.js +51 -0
- package/dist/cjs/src/clusterService.d.ts +44 -0
- package/dist/cjs/src/clusterService.js +120 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +14 -0
- package/dist/cjs/src/codeGeneratorManager.js +93 -0
- package/dist/cjs/src/config/routes.d.ts +7 -0
- package/dist/cjs/src/config/routes.js +160 -0
- package/dist/cjs/src/configManager.d.ts +42 -0
- package/dist/cjs/src/configManager.js +136 -0
- package/dist/cjs/src/containerManager.d.ts +148 -0
- package/dist/cjs/src/containerManager.js +958 -0
- package/dist/cjs/src/definitionsManager.d.ts +20 -0
- package/dist/cjs/src/definitionsManager.js +171 -0
- package/dist/cjs/src/filesystem/routes.d.ts +7 -0
- package/dist/cjs/src/filesystem/routes.js +105 -0
- package/dist/cjs/src/filesystemManager.d.ts +27 -0
- package/dist/cjs/src/filesystemManager.js +118 -0
- package/dist/cjs/src/identities/routes.d.ts +7 -0
- package/dist/cjs/src/identities/routes.js +37 -0
- package/dist/cjs/src/instanceManager.d.ts +69 -0
- package/dist/cjs/src/instanceManager.js +910 -0
- package/dist/cjs/src/instances/routes.d.ts +7 -0
- package/dist/cjs/src/instances/routes.js +179 -0
- package/dist/cjs/src/middleware/cors.d.ts +6 -0
- package/dist/cjs/src/middleware/cors.js +14 -0
- package/dist/cjs/src/middleware/kapeta.d.ts +15 -0
- package/dist/cjs/src/middleware/kapeta.js +28 -0
- package/dist/cjs/src/middleware/stringBody.d.ts +9 -0
- package/dist/cjs/src/middleware/stringBody.js +18 -0
- package/dist/cjs/src/networkManager.d.ts +37 -0
- package/dist/cjs/src/networkManager.js +119 -0
- package/dist/cjs/src/operatorManager.d.ts +41 -0
- package/dist/cjs/src/operatorManager.js +211 -0
- package/dist/cjs/src/progressListener.d.ts +31 -0
- package/dist/cjs/src/progressListener.js +133 -0
- package/dist/cjs/src/providerManager.d.ts +11 -0
- package/dist/cjs/src/providerManager.js +84 -0
- package/dist/cjs/src/providers/routes.d.ts +7 -0
- package/dist/cjs/src/providers/routes.js +46 -0
- package/dist/cjs/src/proxy/routes.d.ts +7 -0
- package/dist/cjs/src/proxy/routes.js +115 -0
- package/dist/cjs/src/proxy/types/rest.d.ts +10 -0
- package/dist/cjs/src/proxy/types/rest.js +123 -0
- package/dist/cjs/src/proxy/types/web.d.ts +8 -0
- package/dist/cjs/src/proxy/types/web.js +61 -0
- package/dist/cjs/src/repositoryManager.d.ts +35 -0
- package/dist/cjs/src/repositoryManager.js +247 -0
- package/dist/cjs/src/serviceManager.d.ts +36 -0
- package/dist/cjs/src/serviceManager.js +106 -0
- package/dist/cjs/src/socketManager.d.ts +32 -0
- package/dist/cjs/src/socketManager.js +125 -0
- package/dist/cjs/src/storageService.d.ts +21 -0
- package/dist/cjs/src/storageService.js +81 -0
- package/dist/cjs/src/taskManager.d.ts +70 -0
- package/dist/cjs/src/taskManager.js +181 -0
- package/dist/cjs/src/tasks/routes.d.ts +7 -0
- package/dist/cjs/src/tasks/routes.js +39 -0
- package/dist/cjs/src/traffic/routes.d.ts +7 -0
- package/dist/cjs/src/traffic/routes.js +22 -0
- package/dist/cjs/src/types.d.ts +99 -0
- package/dist/cjs/src/types.js +39 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +28 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +432 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.d.ts +15 -0
- package/dist/cjs/src/utils/DefaultProviderInstaller.js +136 -0
- package/dist/cjs/src/utils/InternalConfigProvider.d.ts +38 -0
- package/dist/cjs/src/utils/InternalConfigProvider.js +146 -0
- package/dist/cjs/src/utils/LogData.d.ts +23 -0
- package/dist/cjs/src/utils/LogData.js +46 -0
- package/dist/cjs/src/utils/commandLineUtils.d.ts +8 -0
- package/dist/cjs/src/utils/commandLineUtils.js +39 -0
- package/dist/cjs/src/utils/pathTemplateParser.d.ts +30 -0
- package/dist/cjs/src/utils/pathTemplateParser.js +135 -0
- package/dist/cjs/src/utils/utils.d.ts +40 -0
- package/dist/cjs/src/utils/utils.js +148 -0
- package/dist/cjs/start.d.ts +5 -0
- package/dist/cjs/start.js +17 -0
- package/dist/cjs/test/proxy/types/rest.test.d.ts +5 -0
- package/dist/cjs/test/proxy/types/rest.test.js +48 -0
- package/dist/cjs/test/utils/pathTemplateParser.test.d.ts +5 -0
- package/dist/cjs/test/utils/pathTemplateParser.test.js +27 -0
- package/dist/esm/index.d.ts +34 -0
- package/dist/esm/index.js +263 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/src/RepositoryWatcher.d.ts +30 -0
- package/dist/esm/src/RepositoryWatcher.js +332 -0
- package/dist/esm/src/ai/aiClient.d.ts +20 -0
- package/dist/esm/src/ai/aiClient.js +74 -0
- package/dist/esm/src/ai/routes.d.ts +7 -0
- package/dist/esm/src/ai/routes.js +37 -0
- package/dist/esm/src/ai/transform.d.ts +11 -0
- package/dist/esm/src/ai/transform.js +239 -0
- package/dist/esm/src/ai/types.d.ts +40 -0
- package/dist/esm/src/ai/types.js +2 -0
- package/dist/esm/src/api.d.ts +7 -0
- package/dist/esm/src/api.js +29 -0
- package/dist/esm/src/assetManager.d.ts +41 -0
- package/dist/esm/src/assetManager.js +274 -0
- package/dist/esm/src/assets/routes.d.ts +7 -0
- package/dist/esm/src/assets/routes.js +165 -0
- package/dist/esm/src/attachments/routes.d.ts +7 -0
- package/dist/esm/src/attachments/routes.js +72 -0
- package/dist/esm/src/authManager.d.ts +16 -0
- package/dist/esm/src/authManager.js +64 -0
- package/dist/esm/src/cacheManager.d.ts +20 -0
- package/dist/esm/src/cacheManager.js +51 -0
- package/dist/esm/src/clusterService.d.ts +44 -0
- package/dist/esm/src/clusterService.js +120 -0
- package/dist/esm/src/codeGeneratorManager.d.ts +14 -0
- package/dist/esm/src/codeGeneratorManager.js +93 -0
- package/dist/esm/src/config/routes.d.ts +7 -0
- package/dist/esm/src/config/routes.js +160 -0
- package/dist/esm/src/configManager.d.ts +42 -0
- package/dist/esm/src/configManager.js +136 -0
- package/dist/esm/src/containerManager.d.ts +148 -0
- package/dist/esm/src/containerManager.js +958 -0
- package/dist/esm/src/definitionsManager.d.ts +20 -0
- package/dist/esm/src/definitionsManager.js +171 -0
- package/dist/esm/src/filesystem/routes.d.ts +7 -0
- package/dist/esm/src/filesystem/routes.js +105 -0
- package/dist/esm/src/filesystemManager.d.ts +27 -0
- package/dist/esm/src/filesystemManager.js +118 -0
- package/dist/esm/src/identities/routes.d.ts +7 -0
- package/dist/esm/src/identities/routes.js +37 -0
- package/dist/esm/src/instanceManager.d.ts +69 -0
- package/dist/esm/src/instanceManager.js +910 -0
- package/dist/esm/src/instances/routes.d.ts +7 -0
- package/dist/esm/src/instances/routes.js +179 -0
- package/dist/esm/src/middleware/cors.d.ts +6 -0
- package/dist/esm/src/middleware/cors.js +14 -0
- package/dist/esm/src/middleware/kapeta.d.ts +15 -0
- package/dist/esm/src/middleware/kapeta.js +28 -0
- package/dist/esm/src/middleware/stringBody.d.ts +9 -0
- package/dist/esm/src/middleware/stringBody.js +18 -0
- package/dist/esm/src/networkManager.d.ts +37 -0
- package/dist/esm/src/networkManager.js +119 -0
- package/dist/esm/src/operatorManager.d.ts +41 -0
- package/dist/esm/src/operatorManager.js +211 -0
- package/dist/esm/src/progressListener.d.ts +31 -0
- package/dist/esm/src/progressListener.js +133 -0
- package/dist/esm/src/providerManager.d.ts +11 -0
- package/dist/esm/src/providerManager.js +84 -0
- package/dist/esm/src/providers/routes.d.ts +7 -0
- package/dist/esm/src/providers/routes.js +46 -0
- package/dist/esm/src/proxy/routes.d.ts +7 -0
- package/dist/esm/src/proxy/routes.js +115 -0
- package/dist/esm/src/proxy/types/rest.d.ts +10 -0
- package/dist/esm/src/proxy/types/rest.js +123 -0
- package/dist/esm/src/proxy/types/web.d.ts +8 -0
- package/dist/esm/src/proxy/types/web.js +61 -0
- package/dist/esm/src/repositoryManager.d.ts +35 -0
- package/dist/esm/src/repositoryManager.js +247 -0
- package/dist/esm/src/serviceManager.d.ts +36 -0
- package/dist/esm/src/serviceManager.js +106 -0
- package/dist/esm/src/socketManager.d.ts +32 -0
- package/dist/esm/src/socketManager.js +125 -0
- package/dist/esm/src/storageService.d.ts +21 -0
- package/dist/esm/src/storageService.js +81 -0
- package/dist/esm/src/taskManager.d.ts +70 -0
- package/dist/esm/src/taskManager.js +181 -0
- package/dist/esm/src/tasks/routes.d.ts +7 -0
- package/dist/esm/src/tasks/routes.js +39 -0
- package/dist/esm/src/traffic/routes.d.ts +7 -0
- package/dist/esm/src/traffic/routes.js +22 -0
- package/dist/esm/src/types.d.ts +99 -0
- package/dist/esm/src/types.js +39 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +28 -0
- package/dist/esm/src/utils/BlockInstanceRunner.js +432 -0
- package/dist/esm/src/utils/DefaultProviderInstaller.d.ts +15 -0
- package/dist/esm/src/utils/DefaultProviderInstaller.js +136 -0
- package/dist/esm/src/utils/InternalConfigProvider.d.ts +38 -0
- package/dist/esm/src/utils/InternalConfigProvider.js +146 -0
- package/dist/esm/src/utils/LogData.d.ts +23 -0
- package/dist/esm/src/utils/LogData.js +46 -0
- package/dist/esm/src/utils/commandLineUtils.d.ts +8 -0
- package/dist/esm/src/utils/commandLineUtils.js +39 -0
- package/dist/esm/src/utils/pathTemplateParser.d.ts +30 -0
- package/dist/esm/src/utils/pathTemplateParser.js +135 -0
- package/dist/esm/src/utils/utils.d.ts +40 -0
- package/dist/esm/src/utils/utils.js +148 -0
- package/dist/esm/start.d.ts +5 -0
- package/dist/esm/start.js +17 -0
- package/dist/esm/test/proxy/types/rest.test.d.ts +5 -0
- package/dist/esm/test/proxy/types/rest.test.js +48 -0
- package/dist/esm/test/utils/pathTemplateParser.test.d.ts +5 -0
- package/dist/esm/test/utils/pathTemplateParser.test.js +27 -0
- package/index.ts +280 -0
- package/jest.config.js +8 -0
- package/package.json +134 -0
- package/src/RepositoryWatcher.ts +363 -0
- package/src/ai/aiClient.ts +93 -0
- package/src/ai/routes.ts +39 -0
- package/src/ai/transform.ts +275 -0
- package/src/ai/types.ts +45 -0
- package/src/api.ts +32 -0
- package/src/assetManager.ts +355 -0
- package/src/assets/routes.ts +183 -0
- package/src/attachments/routes.ts +79 -0
- package/src/authManager.ts +67 -0
- package/src/cacheManager.ts +59 -0
- package/src/clusterService.ts +142 -0
- package/src/codeGeneratorManager.ts +109 -0
- package/src/config/routes.ts +201 -0
- package/src/configManager.ts +180 -0
- package/src/containerManager.ts +1178 -0
- package/src/definitionsManager.ts +212 -0
- package/src/filesystem/routes.ts +123 -0
- package/src/filesystemManager.ts +133 -0
- package/src/identities/routes.ts +38 -0
- package/src/instanceManager.ts +1160 -0
- package/src/instances/routes.ts +203 -0
- package/src/middleware/cors.ts +14 -0
- package/src/middleware/kapeta.ts +41 -0
- package/src/middleware/stringBody.ts +21 -0
- package/src/networkManager.ts +148 -0
- package/src/operatorManager.ts +294 -0
- package/src/progressListener.ts +151 -0
- package/src/providerManager.ts +97 -0
- package/src/providers/routes.ts +51 -0
- package/src/proxy/routes.ts +153 -0
- package/src/proxy/types/rest.ts +172 -0
- package/src/proxy/types/web.ts +70 -0
- package/src/repositoryManager.ts +291 -0
- package/src/serviceManager.ts +133 -0
- package/src/socketManager.ts +138 -0
- package/src/storageService.ts +97 -0
- package/src/taskManager.ts +247 -0
- package/src/tasks/routes.ts +43 -0
- package/src/traffic/routes.ts +23 -0
- package/src/types.ts +112 -0
- package/src/utils/BlockInstanceRunner.ts +577 -0
- package/src/utils/DefaultProviderInstaller.ts +150 -0
- package/src/utils/InternalConfigProvider.ts +214 -0
- package/src/utils/LogData.ts +50 -0
- package/src/utils/commandLineUtils.ts +45 -0
- package/src/utils/pathTemplateParser.ts +157 -0
- package/src/utils/utils.ts +155 -0
- package/start.ts +14 -0
- package/test/proxy/types/rest.test.ts +54 -0
- package/test/utils/pathTemplateParser.test.ts +29 -0
- package/tsconfig.json +15 -0
@@ -0,0 +1,150 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import Path from 'node:path';
|
7
|
+
import OS from 'node:os';
|
8
|
+
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
9
|
+
import FS from 'fs-extra';
|
10
|
+
import request from 'request';
|
11
|
+
import { extract } from 'tar-stream';
|
12
|
+
import gunzip from 'gunzip-maybe';
|
13
|
+
import { filesystemManager } from '../filesystemManager';
|
14
|
+
import { Actions } from '@kapeta/nodejs-registry-utils';
|
15
|
+
import { ProgressListener } from '../progressListener';
|
16
|
+
import { glob } from 'glob';
|
17
|
+
|
18
|
+
const PROVIDERS_FILENAME =
|
19
|
+
ClusterConfiguration.getEnvironment() === 'staging'
|
20
|
+
? 'default-providers-staging.tar.gz'
|
21
|
+
: 'default-providers.tar.gz';
|
22
|
+
const DEFAULT_PROVIDERS_URL = `https://storage.googleapis.com/kapeta-production-cdn/archives/${PROVIDERS_FILENAME}`;
|
23
|
+
const DEFAULT_PROJECT_HOME_DIR = 'KapetaProjects';
|
24
|
+
|
25
|
+
const ARCHIVE_LOCAL_PREFIX = 'local';
|
26
|
+
|
27
|
+
class DefaultProviderInstaller {
|
28
|
+
private readonly progressListener = new ProgressListener();
|
29
|
+
|
30
|
+
public async checkForDefault() {
|
31
|
+
const definitions = ClusterConfiguration.getDefinitions();
|
32
|
+
if (definitions.length < 1) {
|
33
|
+
console.log('Installing default providers');
|
34
|
+
try {
|
35
|
+
await this.install();
|
36
|
+
} catch (e) {
|
37
|
+
console.warn('Failed to install defaults', e);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
private async install() {
|
43
|
+
await this.download();
|
44
|
+
await this.linkLocal();
|
45
|
+
}
|
46
|
+
|
47
|
+
private async linkLocal() {
|
48
|
+
const projectBase = await this.ensureDefaultProjectHome();
|
49
|
+
const folders = this.scanProjectBase(projectBase);
|
50
|
+
for (let folder of folders) {
|
51
|
+
console.log('Linking %s', folder);
|
52
|
+
await Actions.link(this.progressListener, folder);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
private scanProjectBase(projectBase: string) {
|
57
|
+
const assetFiles = glob.sync('*/**/kapeta.yml', { cwd: projectBase });
|
58
|
+
return assetFiles.map((assetFile) => {
|
59
|
+
return Path.dirname(Path.join(projectBase, assetFile));
|
60
|
+
});
|
61
|
+
}
|
62
|
+
|
63
|
+
private async ensureDefaultProjectHome(): Promise<string> {
|
64
|
+
const defaultProjectHome = Path.join(OS.homedir(), DEFAULT_PROJECT_HOME_DIR);
|
65
|
+
let projectBase = filesystemManager.getProjectRootFolder();
|
66
|
+
|
67
|
+
if (!projectBase) {
|
68
|
+
filesystemManager.setProjectRootFolder(defaultProjectHome);
|
69
|
+
projectBase = defaultProjectHome;
|
70
|
+
if (!(await FS.pathExists(projectBase))) {
|
71
|
+
await FS.mkdirp(projectBase);
|
72
|
+
}
|
73
|
+
}
|
74
|
+
return projectBase;
|
75
|
+
}
|
76
|
+
|
77
|
+
private async download() {
|
78
|
+
const projectBase: string = await this.ensureDefaultProjectHome();
|
79
|
+
const repoBase: string = ClusterConfiguration.getRepositoryBasedir();
|
80
|
+
|
81
|
+
return new Promise<void>((resolve, reject) => {
|
82
|
+
const extractor = extract();
|
83
|
+
const dirCache = new Set<string>();
|
84
|
+
extractor.on('entry', async function (header, stream, next) {
|
85
|
+
if (header.type !== 'file') {
|
86
|
+
stream.on('end', function () {
|
87
|
+
next(); // ready for next entry
|
88
|
+
});
|
89
|
+
stream.resume(); // just auto drain the stream
|
90
|
+
return;
|
91
|
+
}
|
92
|
+
|
93
|
+
// Local (editable) assets should be stored in the project folder
|
94
|
+
// - installed assets goes into the repository folder
|
95
|
+
const baseDir: string = header.name.startsWith(ARCHIVE_LOCAL_PREFIX) ? projectBase : repoBase;
|
96
|
+
|
97
|
+
const parts = header.name.split(/\//g);
|
98
|
+
parts.shift();
|
99
|
+
const filename = parts.join(Path.sep);
|
100
|
+
|
101
|
+
try {
|
102
|
+
const dirname = Path.join(baseDir, Path.dirname(filename));
|
103
|
+
if (!dirCache.has(dirname)) {
|
104
|
+
let dirExists = false;
|
105
|
+
try {
|
106
|
+
await FS.stat(dirname);
|
107
|
+
dirExists = true;
|
108
|
+
} catch (e) {}
|
109
|
+
if (!dirExists) {
|
110
|
+
await FS.mkdirp(dirname);
|
111
|
+
}
|
112
|
+
dirCache.add(dirname);
|
113
|
+
}
|
114
|
+
const fileTarget = Path.join(baseDir, filename);
|
115
|
+
stream.on('error', (err) => {
|
116
|
+
reject(err);
|
117
|
+
});
|
118
|
+
stream.on('end', next);
|
119
|
+
|
120
|
+
stream.pipe(
|
121
|
+
FS.createWriteStream(fileTarget, {
|
122
|
+
mode: header.mode,
|
123
|
+
})
|
124
|
+
);
|
125
|
+
} catch (e) {
|
126
|
+
reject(e);
|
127
|
+
}
|
128
|
+
});
|
129
|
+
|
130
|
+
extractor.on('finish', function () {
|
131
|
+
// all entries done - lets finalize it
|
132
|
+
console.log('Default providers installed');
|
133
|
+
resolve();
|
134
|
+
});
|
135
|
+
|
136
|
+
extractor.on('error', function (err) {
|
137
|
+
reject(err);
|
138
|
+
});
|
139
|
+
|
140
|
+
console.log('Downloading default providers from %s', DEFAULT_PROVIDERS_URL);
|
141
|
+
const response = request(DEFAULT_PROVIDERS_URL);
|
142
|
+
response.on('error', function (err) {
|
143
|
+
reject(err);
|
144
|
+
});
|
145
|
+
response.pipe(gunzip()).pipe(extractor);
|
146
|
+
});
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
export const defaultProviderInstaller = new DefaultProviderInstaller();
|
@@ -0,0 +1,214 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
import {
|
6
|
+
BlockInstanceDetails,
|
7
|
+
ConfigProvider,
|
8
|
+
DefaultCredentials,
|
9
|
+
DefaultResourceOptions,
|
10
|
+
InstanceOperator,
|
11
|
+
ResourceInfo,
|
12
|
+
} from '@kapeta/sdk-config';
|
13
|
+
import { Definition, DefinitionInfo } from '@kapeta/local-cluster-config';
|
14
|
+
import { normalizeKapetaUri } from '@kapeta/nodejs-utils';
|
15
|
+
import { BlockDefinition, Plan } from '@kapeta/schemas';
|
16
|
+
import { configManager } from '../configManager';
|
17
|
+
import { AnyMap, EnvironmentType } from '../types';
|
18
|
+
import _ from 'lodash';
|
19
|
+
import { serviceManager } from '../serviceManager';
|
20
|
+
import { operatorManager } from '../operatorManager';
|
21
|
+
import { instanceManager } from '../instanceManager';
|
22
|
+
import { definitionsManager } from '../definitionsManager';
|
23
|
+
import { getBindAddressForEnvironment } from './utils';
|
24
|
+
|
25
|
+
/**
|
26
|
+
* A configuration provider that does the same as the LocalConfigProvider
|
27
|
+
* but without calling the API of the local cluster service (since it's running in the same process)
|
28
|
+
*/
|
29
|
+
export class InternalConfigProvider implements ConfigProvider {
|
30
|
+
private readonly info: DefinitionInfo;
|
31
|
+
private readonly systemId: string;
|
32
|
+
private readonly instanceId: string;
|
33
|
+
private readonly config: AnyMap;
|
34
|
+
private readonly environment: EnvironmentType;
|
35
|
+
|
36
|
+
constructor(
|
37
|
+
systemId: string,
|
38
|
+
instanceId: string,
|
39
|
+
info: DefinitionInfo,
|
40
|
+
config: AnyMap,
|
41
|
+
environment: EnvironmentType = 'docker'
|
42
|
+
) {
|
43
|
+
this.info = info;
|
44
|
+
this.systemId = normalizeKapetaUri(systemId);
|
45
|
+
this.instanceId = instanceId;
|
46
|
+
this.config = config;
|
47
|
+
this.environment = environment;
|
48
|
+
}
|
49
|
+
|
50
|
+
getBlockDefinition() {
|
51
|
+
return this.info.definition;
|
52
|
+
}
|
53
|
+
getBlockReference(): string {
|
54
|
+
return normalizeKapetaUri(this.info.definition.metadata.name + ':' + this.info.version);
|
55
|
+
}
|
56
|
+
getSystemId(): string {
|
57
|
+
return this.systemId;
|
58
|
+
}
|
59
|
+
getInstanceId(): string {
|
60
|
+
return this.instanceId;
|
61
|
+
}
|
62
|
+
getServerPort(portType?: string | undefined): Promise<string> {
|
63
|
+
return serviceManager.ensureServicePort(this.systemId, this.instanceId, portType);
|
64
|
+
}
|
65
|
+
async getServiceAddress(serviceName: string, portType: string): Promise<string | null> {
|
66
|
+
return serviceManager.getConsumerAddress(
|
67
|
+
this.systemId,
|
68
|
+
this.instanceId,
|
69
|
+
serviceName,
|
70
|
+
portType,
|
71
|
+
this.environment
|
72
|
+
);
|
73
|
+
}
|
74
|
+
getResourceInfo<Options = DefaultResourceOptions, Credentials = DefaultCredentials>(
|
75
|
+
resourceType: string,
|
76
|
+
portType: string,
|
77
|
+
resourceName: string
|
78
|
+
): Promise<ResourceInfo<Options, Credentials> | null> {
|
79
|
+
return operatorManager.getConsumerResourceInfo(
|
80
|
+
this.systemId,
|
81
|
+
this.instanceId,
|
82
|
+
resourceType,
|
83
|
+
portType,
|
84
|
+
resourceName,
|
85
|
+
this.environment,
|
86
|
+
false
|
87
|
+
);
|
88
|
+
}
|
89
|
+
async getInstanceHost(instanceId: string): Promise<string | null> {
|
90
|
+
const instance = instanceManager.getInstance(this.systemId, instanceId);
|
91
|
+
return instance?.address ?? null;
|
92
|
+
}
|
93
|
+
async getServerHost(): Promise<string> {
|
94
|
+
return getBindAddressForEnvironment(this.environment);
|
95
|
+
}
|
96
|
+
getProviderId(): string {
|
97
|
+
return 'internal';
|
98
|
+
}
|
99
|
+
getOrDefault<T = any>(path: string, defaultValue: T): T {
|
100
|
+
return this.get(path) ?? defaultValue;
|
101
|
+
}
|
102
|
+
get<T = any>(path: string): T | undefined {
|
103
|
+
return _.get(this.config, path);
|
104
|
+
}
|
105
|
+
|
106
|
+
getInstanceOperator<Options = any, Credentials extends DefaultCredentials = DefaultCredentials>(
|
107
|
+
instanceId: string
|
108
|
+
): Promise<InstanceOperator<Options, Credentials> | null> {
|
109
|
+
return instanceManager.getInstanceOperator(this.systemId, instanceId, this.environment, false);
|
110
|
+
}
|
111
|
+
|
112
|
+
public async getInstanceForConsumer<BlockType = BlockDefinition>(
|
113
|
+
resourceName: string
|
114
|
+
): Promise<BlockInstanceDetails<BlockType> | null> {
|
115
|
+
const plan = await this.getPlan();
|
116
|
+
if (!plan) {
|
117
|
+
throw new Error('Could not find plan');
|
118
|
+
}
|
119
|
+
const instanceId = this.getInstanceId();
|
120
|
+
const connection = plan.spec.connections.find(
|
121
|
+
(connection) =>
|
122
|
+
connection.consumer.blockId === instanceId && connection.consumer.resourceName === resourceName
|
123
|
+
);
|
124
|
+
|
125
|
+
if (!connection) {
|
126
|
+
throw new Error(`Could not find connection for consumer ${resourceName}`);
|
127
|
+
}
|
128
|
+
|
129
|
+
const instance = plan.spec.blocks.find((b) => b.id === connection.provider.blockId);
|
130
|
+
|
131
|
+
if (!instance) {
|
132
|
+
throw new Error(`Could not find instance ${connection.provider.blockId} in plan`);
|
133
|
+
}
|
134
|
+
|
135
|
+
const block = await this.getBlock(instance.block.ref);
|
136
|
+
|
137
|
+
if (!block) {
|
138
|
+
throw new Error(`Could not find block ${instance.block.ref} in plan`);
|
139
|
+
}
|
140
|
+
|
141
|
+
return {
|
142
|
+
instanceId: connection.provider.blockId,
|
143
|
+
connections: [connection],
|
144
|
+
block: block as BlockType,
|
145
|
+
};
|
146
|
+
}
|
147
|
+
|
148
|
+
public async getInstancesForProvider<BlockType = BlockDefinition>(
|
149
|
+
resourceName: string
|
150
|
+
): Promise<BlockInstanceDetails<BlockType>[]> {
|
151
|
+
const plan = await this.getPlan();
|
152
|
+
if (!plan) {
|
153
|
+
throw new Error('Could not find plan');
|
154
|
+
}
|
155
|
+
const instanceId = this.getInstanceId();
|
156
|
+
|
157
|
+
const blockDetails: { [key: string]: BlockInstanceDetails<BlockType> } = {};
|
158
|
+
const connections = plan.spec.connections.filter(
|
159
|
+
(connection) =>
|
160
|
+
connection.provider.blockId === instanceId && connection.provider.resourceName === resourceName
|
161
|
+
);
|
162
|
+
|
163
|
+
for (const connection of connections) {
|
164
|
+
const blockInstanceId = connection.consumer.blockId;
|
165
|
+
if (blockDetails[blockInstanceId]) {
|
166
|
+
blockDetails[blockInstanceId].connections.push(connection);
|
167
|
+
continue;
|
168
|
+
}
|
169
|
+
|
170
|
+
const instance = plan.spec.blocks.find((b) => b.id === blockInstanceId);
|
171
|
+
if (!instance) {
|
172
|
+
throw new Error(`Could not find instance ${blockInstanceId} in plan`);
|
173
|
+
}
|
174
|
+
|
175
|
+
const block = await this.getBlock(instance.block.ref);
|
176
|
+
if (!block) {
|
177
|
+
throw new Error(`Could not find block ${instance.block.ref} in plan`);
|
178
|
+
}
|
179
|
+
|
180
|
+
blockDetails[blockInstanceId] = {
|
181
|
+
instanceId: blockInstanceId,
|
182
|
+
connections: [connection],
|
183
|
+
block: block as BlockType,
|
184
|
+
};
|
185
|
+
}
|
186
|
+
|
187
|
+
return Object.values(blockDetails);
|
188
|
+
}
|
189
|
+
|
190
|
+
async getBlock(ref: any): Promise<Definition> {
|
191
|
+
const definition = await definitionsManager.getDefinition(ref);
|
192
|
+
if (!definition) {
|
193
|
+
throw new Error(`Could not find definition for ${ref}`);
|
194
|
+
}
|
195
|
+
return definition.definition;
|
196
|
+
}
|
197
|
+
|
198
|
+
async getPlan(): Promise<Plan> {
|
199
|
+
const definition = await definitionsManager.getDefinition(this.systemId);
|
200
|
+
if (!definition) {
|
201
|
+
throw new Error(`Could not find plan ${this.systemId}`);
|
202
|
+
}
|
203
|
+
return definition.definition as Plan;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
export async function createInternalConfigProvider(
|
208
|
+
systemId: string,
|
209
|
+
instanceId: string,
|
210
|
+
info: DefinitionInfo
|
211
|
+
): Promise<InternalConfigProvider> {
|
212
|
+
const config = await configManager.getConfigForBlockInstance(systemId, instanceId);
|
213
|
+
return new InternalConfigProvider(systemId, instanceId, info, config);
|
214
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { LogEntry, LogLevel, LogSource } from '../types';
|
7
|
+
|
8
|
+
const MAX_LINES = 1000;
|
9
|
+
export class LogData {
|
10
|
+
public static readonly MAX_LINES = MAX_LINES;
|
11
|
+
private readonly entries: LogEntry[] = [];
|
12
|
+
constructor() {}
|
13
|
+
|
14
|
+
/**
|
15
|
+
*
|
16
|
+
* @param {string} msg
|
17
|
+
* @param {string} [level]
|
18
|
+
* @param {string} [source]
|
19
|
+
*/
|
20
|
+
addLog(msg: string, level: LogLevel = 'INFO', source: LogSource = 'stdout') {
|
21
|
+
while (this.entries.length > MAX_LINES) {
|
22
|
+
this.entries.shift();
|
23
|
+
}
|
24
|
+
|
25
|
+
if (!msg.endsWith('\n')) {
|
26
|
+
msg += '\n';
|
27
|
+
}
|
28
|
+
|
29
|
+
this.entries.push({
|
30
|
+
time: Date.now(),
|
31
|
+
message: msg,
|
32
|
+
level,
|
33
|
+
source,
|
34
|
+
});
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
*
|
39
|
+
* @return {LogEntry[]}
|
40
|
+
*/
|
41
|
+
getLogs() {
|
42
|
+
return this.entries;
|
43
|
+
}
|
44
|
+
|
45
|
+
toString() {
|
46
|
+
return this.getLogs()
|
47
|
+
.map((entry) => entry.message)
|
48
|
+
.join('\n');
|
49
|
+
}
|
50
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { spawn, hasApp } from '@kapeta/nodejs-process';
|
7
|
+
import { Task, taskManager } from '../taskManager';
|
8
|
+
|
9
|
+
export async function hasCLI() {
|
10
|
+
return hasApp('kap');
|
11
|
+
}
|
12
|
+
|
13
|
+
export async function ensureCLI() {
|
14
|
+
if (await hasCLI()) {
|
15
|
+
return null;
|
16
|
+
}
|
17
|
+
|
18
|
+
return taskManager.add(
|
19
|
+
`cli:install`,
|
20
|
+
(task: Task) => {
|
21
|
+
const process = spawn('npm', ['install', '-g', '@kapeta/kap'], {
|
22
|
+
shell: true,
|
23
|
+
});
|
24
|
+
|
25
|
+
process.process.stdout?.on('data', (data: any) => {
|
26
|
+
task.addLog(data.toString(), 'INFO');
|
27
|
+
});
|
28
|
+
|
29
|
+
process.process.stderr?.on('data', (data: any) => {
|
30
|
+
task.addLog(data.toString(), 'ERROR');
|
31
|
+
});
|
32
|
+
|
33
|
+
return process.wait();
|
34
|
+
},
|
35
|
+
{
|
36
|
+
name: `Installing Kapeta CLI`,
|
37
|
+
}
|
38
|
+
);
|
39
|
+
}
|
40
|
+
|
41
|
+
export function ensureCLICommands() {
|
42
|
+
console.log('Run `kap init` to ensure default commands are installed');
|
43
|
+
const process = spawn('kap', ['init'], { shell: true });
|
44
|
+
return process.wait();
|
45
|
+
}
|
@@ -0,0 +1,157 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
|
6
|
+
import { StringMap } from '../types';
|
7
|
+
|
8
|
+
const TYPE_VARIABLE = 'variable';
|
9
|
+
const TYPE_PATH = 'path';
|
10
|
+
|
11
|
+
function normalizePath(path: string) {
|
12
|
+
if (!path.startsWith('/')) {
|
13
|
+
path = '/' + path;
|
14
|
+
}
|
15
|
+
|
16
|
+
if (path.includes('#')) {
|
17
|
+
path = path.split('#')[0];
|
18
|
+
}
|
19
|
+
|
20
|
+
if (path.includes('?')) {
|
21
|
+
path = path.split('?')[0];
|
22
|
+
}
|
23
|
+
|
24
|
+
return path;
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* A path template is a string that can be used to match a path and extract variables from it.
|
29
|
+
*
|
30
|
+
* E.g. /foo/{bar}/baz
|
31
|
+
*
|
32
|
+
* Would match /foo/123/baz and extract bar=123
|
33
|
+
*
|
34
|
+
* You can also specify a regex for the variable:
|
35
|
+
* /foo/{bar:[0-9]+}/baz
|
36
|
+
*
|
37
|
+
*/
|
38
|
+
export class PathTemplate {
|
39
|
+
private _path: string;
|
40
|
+
private _parts: { type: 'variable' | 'path'; value: string; regex?: RegExp }[] = [];
|
41
|
+
|
42
|
+
constructor(pathTemplate: string) {
|
43
|
+
if (!pathTemplate.startsWith('/')) {
|
44
|
+
pathTemplate = '/' + pathTemplate;
|
45
|
+
}
|
46
|
+
this._path = pathTemplate;
|
47
|
+
|
48
|
+
const variableRegex = /{([^}]+)}/g;
|
49
|
+
let match,
|
50
|
+
offset = 0;
|
51
|
+
this._parts = [];
|
52
|
+
while ((match = variableRegex.exec(pathTemplate)) !== null) {
|
53
|
+
if (match.index > offset) {
|
54
|
+
this._parts.push({
|
55
|
+
type: TYPE_PATH,
|
56
|
+
value: pathTemplate.substring(offset, match.index),
|
57
|
+
});
|
58
|
+
}
|
59
|
+
|
60
|
+
let regex;
|
61
|
+
let value = match[1];
|
62
|
+
[value, regex] = value.split(/:/, 2);
|
63
|
+
|
64
|
+
if (regex) {
|
65
|
+
regex = new RegExp('^' + regex);
|
66
|
+
} else {
|
67
|
+
regex = /^[^\/]+/;
|
68
|
+
}
|
69
|
+
|
70
|
+
this._parts.push({
|
71
|
+
type: TYPE_VARIABLE,
|
72
|
+
value,
|
73
|
+
regex,
|
74
|
+
});
|
75
|
+
offset = match.index + match[0].length;
|
76
|
+
}
|
77
|
+
|
78
|
+
if (offset < pathTemplate.length) {
|
79
|
+
this._parts.push({
|
80
|
+
type: TYPE_PATH,
|
81
|
+
value: pathTemplate.substring(offset),
|
82
|
+
});
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
get path() {
|
87
|
+
return this._path;
|
88
|
+
}
|
89
|
+
|
90
|
+
matches(path: string) {
|
91
|
+
return this.parse(path) !== null;
|
92
|
+
}
|
93
|
+
|
94
|
+
parse(path: string) {
|
95
|
+
path = normalizePath(path);
|
96
|
+
|
97
|
+
const values: StringMap = {};
|
98
|
+
|
99
|
+
for (let i = 0; i < this._parts.length; i++) {
|
100
|
+
const part = this._parts[i];
|
101
|
+
switch (part.type) {
|
102
|
+
case TYPE_PATH:
|
103
|
+
if (!path.startsWith(part.value)) {
|
104
|
+
return null;
|
105
|
+
}
|
106
|
+
|
107
|
+
path = path.substring(part.value.length);
|
108
|
+
break;
|
109
|
+
case TYPE_VARIABLE:
|
110
|
+
if (!part.regex?.test(path)) {
|
111
|
+
return null;
|
112
|
+
}
|
113
|
+
|
114
|
+
const newPath = path.replace(part.regex, '');
|
115
|
+
const value = path.substr(0, path.length - newPath.length);
|
116
|
+
values[part.value] = value;
|
117
|
+
path = newPath;
|
118
|
+
break;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
if (path && path !== '/') {
|
123
|
+
//We did not match all of it
|
124
|
+
return null;
|
125
|
+
}
|
126
|
+
|
127
|
+
return values;
|
128
|
+
}
|
129
|
+
|
130
|
+
create(variables: StringMap) {
|
131
|
+
return this._parts
|
132
|
+
.map((part) => {
|
133
|
+
switch (part.type) {
|
134
|
+
case TYPE_PATH:
|
135
|
+
return part.value;
|
136
|
+
case TYPE_VARIABLE:
|
137
|
+
if (variables[part.value] === undefined || variables[part.value] === null) {
|
138
|
+
return '';
|
139
|
+
}
|
140
|
+
|
141
|
+
return variables[part.value];
|
142
|
+
}
|
143
|
+
})
|
144
|
+
.join('');
|
145
|
+
}
|
146
|
+
|
147
|
+
toString() {
|
148
|
+
return 'tmpl: ' + this.path;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* Parses a path into a RESTPath
|
154
|
+
*/
|
155
|
+
export function pathTemplateParser(path: string) {
|
156
|
+
return new PathTemplate(path);
|
157
|
+
}
|