@kapeta/local-cluster-service 0.6.0 → 0.7.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/.eslintrc.cjs +17 -0
- package/.github/workflows/main.yml +22 -22
- package/.prettierignore +4 -0
- package/.vscode/launch.json +2 -4
- package/CHANGELOG.md +14 -0
- package/definitions.d.ts +17 -35
- package/dist/cjs/index.d.ts +27 -0
- package/dist/cjs/index.js +126 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/src/assetManager.d.ts +31 -0
- package/dist/cjs/src/assetManager.js +153 -0
- package/dist/cjs/src/assets/routes.d.ts +3 -0
- package/dist/cjs/src/assets/routes.js +117 -0
- package/dist/cjs/src/clusterService.d.ts +40 -0
- package/dist/cjs/src/clusterService.js +114 -0
- package/dist/cjs/src/codeGeneratorManager.d.ts +8 -0
- package/dist/cjs/src/codeGeneratorManager.js +53 -0
- package/dist/cjs/src/config/routes.d.ts +3 -0
- package/dist/cjs/src/config/routes.js +126 -0
- package/dist/cjs/src/configManager.d.ts +36 -0
- package/dist/cjs/src/configManager.js +110 -0
- package/dist/cjs/src/containerManager.d.ts +89 -0
- package/dist/cjs/src/containerManager.js +365 -0
- package/dist/cjs/src/filesystem/routes.d.ts +3 -0
- package/dist/cjs/src/filesystem/routes.js +69 -0
- package/dist/cjs/src/filesystemManager.d.ts +15 -0
- package/dist/cjs/src/filesystemManager.js +87 -0
- package/dist/cjs/src/identities/routes.d.ts +3 -0
- package/dist/cjs/src/identities/routes.js +18 -0
- package/dist/cjs/src/instanceManager.d.ts +56 -0
- package/dist/cjs/src/instanceManager.js +424 -0
- package/dist/cjs/src/instances/routes.d.ts +3 -0
- package/dist/cjs/src/instances/routes.js +134 -0
- package/dist/cjs/src/middleware/cors.d.ts +2 -0
- package/dist/cjs/src/middleware/cors.js +10 -0
- package/dist/cjs/src/middleware/kapeta.d.ts +11 -0
- package/dist/cjs/src/middleware/kapeta.js +17 -0
- package/dist/cjs/src/middleware/stringBody.d.ts +5 -0
- package/dist/cjs/src/middleware/stringBody.js +14 -0
- package/dist/cjs/src/networkManager.d.ts +32 -0
- package/dist/cjs/src/networkManager.js +109 -0
- package/dist/cjs/src/operatorManager.d.ts +36 -0
- package/dist/cjs/src/operatorManager.js +165 -0
- package/dist/cjs/src/progressListener.d.ts +20 -0
- package/dist/cjs/src/progressListener.js +91 -0
- package/dist/cjs/src/providerManager.d.ts +9 -0
- package/dist/cjs/src/providerManager.js +51 -0
- package/dist/cjs/src/providers/routes.d.ts +3 -0
- package/dist/cjs/src/providers/routes.js +42 -0
- package/dist/cjs/src/proxy/routes.d.ts +3 -0
- package/dist/cjs/src/proxy/routes.js +111 -0
- package/dist/cjs/src/proxy/types/rest.d.ts +4 -0
- package/dist/cjs/src/proxy/types/rest.js +114 -0
- package/dist/cjs/src/proxy/types/web.d.ts +4 -0
- package/dist/cjs/src/proxy/types/web.js +53 -0
- package/dist/cjs/src/repositoryManager.d.ts +17 -0
- package/dist/cjs/src/repositoryManager.js +215 -0
- package/dist/cjs/src/serviceManager.d.ts +29 -0
- package/dist/cjs/src/serviceManager.js +99 -0
- package/dist/cjs/src/socketManager.d.ts +14 -0
- package/dist/cjs/src/socketManager.js +53 -0
- package/dist/cjs/src/storageService.d.ts +17 -0
- package/dist/cjs/src/storageService.js +74 -0
- package/dist/cjs/src/traffic/routes.d.ts +3 -0
- package/dist/cjs/src/traffic/routes.js +18 -0
- package/dist/cjs/src/types.d.ts +88 -0
- package/dist/cjs/src/types.js +2 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +29 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +468 -0
- package/dist/cjs/src/utils/LogData.d.ts +19 -0
- package/dist/cjs/src/utils/LogData.js +43 -0
- package/dist/cjs/src/utils/pathTemplateParser.d.ts +26 -0
- package/dist/cjs/src/utils/pathTemplateParser.js +121 -0
- package/dist/cjs/src/utils/utils.d.ts +1 -0
- package/dist/cjs/src/utils/utils.js +18 -0
- package/dist/cjs/start.d.ts +1 -0
- package/dist/cjs/start.js +12 -0
- package/dist/esm/index.d.ts +27 -0
- package/dist/esm/index.js +121 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/src/assetManager.d.ts +31 -0
- package/{src → dist/esm/src}/assetManager.js +22 -60
- package/dist/esm/src/assets/routes.d.ts +3 -0
- package/{src → dist/esm/src}/assets/routes.js +21 -36
- package/dist/esm/src/clusterService.d.ts +40 -0
- package/{src → dist/esm/src}/clusterService.js +14 -37
- package/dist/esm/src/codeGeneratorManager.d.ts +8 -0
- package/{src → dist/esm/src}/codeGeneratorManager.js +15 -24
- package/dist/esm/src/config/routes.d.ts +3 -0
- package/dist/esm/src/config/routes.js +121 -0
- package/dist/esm/src/configManager.d.ts +36 -0
- package/{src → dist/esm/src}/configManager.js +11 -40
- package/dist/esm/src/containerManager.d.ts +89 -0
- package/{src → dist/esm/src}/containerManager.js +81 -182
- package/dist/esm/src/filesystem/routes.d.ts +3 -0
- package/dist/esm/src/filesystem/routes.js +64 -0
- package/dist/esm/src/filesystemManager.d.ts +15 -0
- package/{src → dist/esm/src}/filesystemManager.js +20 -28
- package/dist/esm/src/identities/routes.d.ts +3 -0
- package/dist/esm/src/identities/routes.js +13 -0
- package/dist/esm/src/instanceManager.d.ts +56 -0
- package/{src → dist/esm/src}/instanceManager.js +94 -175
- package/dist/esm/src/instances/routes.d.ts +3 -0
- package/{src → dist/esm/src}/instances/routes.js +31 -70
- package/dist/esm/src/middleware/cors.d.ts +2 -0
- package/{src → dist/esm/src}/middleware/cors.js +2 -3
- package/dist/esm/src/middleware/kapeta.d.ts +11 -0
- package/{src → dist/esm/src}/middleware/kapeta.js +3 -7
- package/dist/esm/src/middleware/stringBody.d.ts +5 -0
- package/{src → dist/esm/src}/middleware/stringBody.js +2 -3
- package/dist/esm/src/networkManager.d.ts +32 -0
- package/{src → dist/esm/src}/networkManager.js +16 -33
- package/dist/esm/src/operatorManager.d.ts +36 -0
- package/{src → dist/esm/src}/operatorManager.js +35 -91
- package/dist/esm/src/progressListener.d.ts +20 -0
- package/dist/esm/src/progressListener.js +88 -0
- package/dist/esm/src/providerManager.d.ts +9 -0
- package/dist/esm/src/providerManager.js +45 -0
- package/dist/esm/src/providers/routes.d.ts +3 -0
- package/{src → dist/esm/src}/providers/routes.js +10 -16
- package/dist/esm/src/proxy/routes.d.ts +3 -0
- package/dist/esm/src/proxy/routes.js +106 -0
- package/dist/esm/src/proxy/types/rest.d.ts +4 -0
- package/dist/esm/src/proxy/types/rest.js +107 -0
- package/dist/esm/src/proxy/types/web.d.ts +4 -0
- package/{src → dist/esm/src}/proxy/types/web.js +13 -35
- package/dist/esm/src/repositoryManager.d.ts +17 -0
- package/dist/esm/src/repositoryManager.js +209 -0
- package/dist/esm/src/serviceManager.d.ts +29 -0
- package/{src → dist/esm/src}/serviceManager.js +12 -42
- package/dist/esm/src/socketManager.d.ts +14 -0
- package/{src → dist/esm/src}/socketManager.js +19 -23
- package/dist/esm/src/storageService.d.ts +17 -0
- package/{src → dist/esm/src}/storageService.js +8 -27
- package/dist/esm/src/traffic/routes.d.ts +3 -0
- package/{src → dist/esm/src}/traffic/routes.js +4 -9
- package/dist/esm/src/types.d.ts +88 -0
- package/dist/esm/src/types.js +1 -0
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +29 -0
- package/{src → dist/esm/src}/utils/BlockInstanceRunner.js +137 -256
- package/dist/esm/src/utils/LogData.d.ts +19 -0
- package/{src → dist/esm/src}/utils/LogData.js +11 -22
- package/dist/esm/src/utils/pathTemplateParser.d.ts +26 -0
- package/{src → dist/esm/src}/utils/pathTemplateParser.js +21 -40
- package/dist/esm/src/utils/utils.d.ts +1 -0
- package/dist/esm/src/utils/utils.js +11 -0
- package/dist/esm/start.d.ts +1 -0
- package/dist/esm/start.js +7 -0
- package/index.ts +147 -0
- package/package.json +106 -74
- package/src/assetManager.ts +191 -0
- package/src/assets/routes.ts +132 -0
- package/src/clusterService.ts +134 -0
- package/src/codeGeneratorManager.ts +57 -0
- package/src/config/routes.ts +159 -0
- package/src/configManager.ts +148 -0
- package/src/containerManager.ts +466 -0
- package/src/filesystem/routes.ts +74 -0
- package/src/filesystemManager.ts +93 -0
- package/src/identities/routes.ts +20 -0
- package/src/instanceManager.ts +503 -0
- package/src/instances/routes.ts +164 -0
- package/src/middleware/cors.ts +9 -0
- package/src/middleware/kapeta.ts +27 -0
- package/src/middleware/stringBody.ts +16 -0
- package/src/networkManager.ts +137 -0
- package/src/operatorManager.ts +221 -0
- package/src/progressListener.ts +102 -0
- package/src/{providerManager.js → providerManager.ts} +15 -31
- package/src/providers/routes.ts +46 -0
- package/src/proxy/routes.ts +148 -0
- package/src/proxy/types/{rest.js → rest.ts} +30 -30
- package/src/proxy/types/web.ts +60 -0
- package/src/{repositoryManager.js → repositoryManager.ts} +45 -73
- package/src/serviceManager.ts +120 -0
- package/src/socketManager.ts +57 -0
- package/src/storageService.ts +88 -0
- package/src/traffic/routes.ts +18 -0
- package/src/types.ts +97 -0
- package/src/utils/BlockInstanceRunner.ts +555 -0
- package/src/utils/LogData.ts +47 -0
- package/src/utils/pathTemplateParser.ts +138 -0
- package/src/utils/utils.ts +12 -0
- package/start.ts +8 -0
- package/tsconfig.json +13 -0
- package/index.js +0 -127
- package/src/config/routes.js +0 -160
- package/src/filesystem/routes.js +0 -74
- package/src/identities/routes.js +0 -19
- package/src/progressListener.js +0 -82
- package/src/proxy/routes.js +0 -126
- package/src/utils/utils.js +0 -13
- package/start.js +0 -7
@@ -1,23 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
const EventEmitter = require("events");
|
12
|
-
const md5 = require('md5');
|
13
|
-
const {execSync} = require("child_process");
|
14
|
-
const clusterService = require("../clusterService");
|
15
|
-
|
1
|
+
import FS from 'node:fs';
|
2
|
+
import ClusterConfig from '@kapeta/local-cluster-config';
|
3
|
+
import { readYML } from './utils';
|
4
|
+
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
5
|
+
import { serviceManager } from '../serviceManager';
|
6
|
+
import { containerManager } from '../containerManager';
|
7
|
+
import { LogData } from './LogData';
|
8
|
+
import EventEmitter from 'events';
|
9
|
+
import md5 from 'md5';
|
10
|
+
import { clusterService } from '../clusterService';
|
16
11
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
17
|
-
const KAPETA_SYSTEM_ID =
|
18
|
-
const KAPETA_BLOCK_REF =
|
19
|
-
const KAPETA_INSTANCE_ID =
|
20
|
-
const KAPETA_LOCAL_CLUSTER_PORT =
|
12
|
+
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
13
|
+
const KAPETA_BLOCK_REF = 'KAPETA_BLOCK_REF';
|
14
|
+
const KAPETA_INSTANCE_ID = 'KAPETA_INSTANCE_ID';
|
15
|
+
const KAPETA_LOCAL_CLUSTER_PORT = 'KAPETA_LOCAL_CLUSTER_PORT';
|
21
16
|
/**
|
22
17
|
* Needed when running local docker containers as part of plan
|
23
18
|
* @type {string[]}
|
@@ -26,27 +21,22 @@ const DOCKER_ENV_VARS = [
|
|
26
21
|
`KAPETA_LOCAL_SERVER=0.0.0.0`,
|
27
22
|
`KAPETA_LOCAL_CLUSTER_HOST=host.docker.internal`,
|
28
23
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
29
|
-
]
|
30
|
-
|
31
|
-
|
24
|
+
];
|
32
25
|
function getProvider(uri) {
|
33
|
-
return ClusterConfig.getProviderDefinitions().find(provider => {
|
34
|
-
const ref = `${provider.definition.metadata.name}:${provider.version}
|
26
|
+
return ClusterConfig.getProviderDefinitions().find((provider) => {
|
27
|
+
const ref = `${provider.definition.metadata.name}:${provider.version}`;
|
35
28
|
return parseKapetaUri(ref).id === uri.id;
|
36
29
|
});
|
37
30
|
}
|
38
|
-
|
39
31
|
function getProviderPorts(assetVersion) {
|
40
|
-
return assetVersion.definition?.spec?.providers
|
41
|
-
|
42
|
-
|
32
|
+
return (assetVersion.definition?.spec?.providers
|
33
|
+
?.map((provider) => {
|
34
|
+
return provider.spec?.port?.type;
|
35
|
+
})
|
36
|
+
.filter((t) => !!t) ?? []);
|
43
37
|
}
|
44
|
-
|
45
|
-
|
46
|
-
/**
|
47
|
-
* @param {string} [planReference]
|
48
|
-
* @param {BlockInstanceInfo[]} [instances]
|
49
|
-
*/
|
38
|
+
export class BlockInstanceRunner {
|
39
|
+
_systemId;
|
50
40
|
constructor(planReference) {
|
51
41
|
/**
|
52
42
|
*
|
@@ -55,206 +45,145 @@ class BlockInstanceRunner {
|
|
55
45
|
*/
|
56
46
|
this._systemId = planReference ?? '';
|
57
47
|
}
|
58
|
-
|
59
|
-
|
60
|
-
|
61
48
|
/**
|
62
49
|
* Start a block
|
63
50
|
*
|
64
|
-
* @param {string} blockRef
|
65
|
-
* @param {string} instanceId
|
66
|
-
* @param {any} configuration
|
67
|
-
* @returns {Promise<ProcessInfo>}
|
68
51
|
*/
|
69
52
|
async start(blockRef, instanceId, configuration) {
|
70
53
|
return this._execute({
|
71
54
|
ref: blockRef,
|
72
55
|
id: instanceId,
|
73
|
-
configuration
|
56
|
+
configuration,
|
74
57
|
});
|
75
58
|
}
|
76
|
-
|
77
|
-
/**
|
78
|
-
*
|
79
|
-
* @param {BlockInstanceInfo} blockInstance
|
80
|
-
* @return {Promise<ProcessInfo>}
|
81
|
-
* @private
|
82
|
-
*/
|
83
59
|
async _execute(blockInstance) {
|
84
60
|
const env = {};
|
85
|
-
|
86
61
|
if (this._systemId) {
|
87
62
|
env[KAPETA_SYSTEM_ID] = this._systemId;
|
88
63
|
}
|
89
|
-
|
90
64
|
if (blockInstance.ref) {
|
91
65
|
env[KAPETA_BLOCK_REF] = blockInstance.ref;
|
92
66
|
}
|
93
|
-
|
94
67
|
if (blockInstance.id) {
|
95
68
|
env[KAPETA_INSTANCE_ID] = blockInstance.id;
|
96
69
|
}
|
97
|
-
|
98
70
|
const blockUri = parseKapetaUri(blockInstance.ref);
|
99
|
-
|
100
71
|
if (!blockUri.version) {
|
101
72
|
blockUri.version = 'local';
|
102
73
|
}
|
103
|
-
|
104
|
-
|
105
|
-
const ref = `${definitions.definition.metadata.name}:${definitions.version}`
|
74
|
+
const assetVersion = ClusterConfig.getDefinitions().find((definitions) => {
|
75
|
+
const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
|
106
76
|
return parseKapetaUri(ref).id === blockUri.id;
|
107
77
|
});
|
108
|
-
|
109
78
|
if (!assetVersion) {
|
110
79
|
throw new Error(`Block definition not found: ${blockUri.id}`);
|
111
80
|
}
|
112
|
-
|
113
81
|
const kindUri = parseKapetaUri(assetVersion.definition.kind);
|
114
|
-
|
115
82
|
const providerVersion = getProvider(kindUri);
|
116
|
-
|
117
83
|
if (!providerVersion) {
|
118
84
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
119
85
|
}
|
120
|
-
|
121
|
-
/**
|
122
|
-
* @type {ProcessDetails}
|
123
|
-
*/
|
124
86
|
let processDetails;
|
125
|
-
|
126
87
|
if (providerVersion.definition.kind === KIND_BLOCK_TYPE_OPERATOR) {
|
127
88
|
processDetails = await this._startOperatorProcess(blockInstance, blockUri, providerVersion, env);
|
128
|
-
}
|
89
|
+
}
|
90
|
+
else {
|
129
91
|
//We need a port type to know how to connect to the block consistently
|
130
92
|
const portTypes = getProviderPorts(assetVersion);
|
131
|
-
|
132
93
|
if (blockUri.version === 'local') {
|
133
94
|
processDetails = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
|
134
|
-
}
|
95
|
+
}
|
96
|
+
else {
|
135
97
|
processDetails = await this._startDockerProcess(blockInstance, blockUri, env);
|
136
98
|
}
|
137
|
-
|
138
99
|
if (portTypes.length > 0) {
|
139
100
|
processDetails.portType = portTypes[0];
|
140
101
|
}
|
141
102
|
}
|
142
|
-
|
143
103
|
return {
|
104
|
+
name: blockUri.id,
|
144
105
|
...blockInstance,
|
145
|
-
...processDetails
|
106
|
+
...processDetails,
|
146
107
|
};
|
147
108
|
}
|
148
|
-
|
149
|
-
|
150
109
|
/**
|
151
110
|
* Starts local process
|
152
|
-
* @param {BlockInstanceInfo} blockInstance
|
153
|
-
* @param {BlockInfo} blockInfo
|
154
|
-
* @param {EnvironmentVariables} env
|
155
|
-
* @param assetVersion
|
156
|
-
* @return {ProcessDetails}
|
157
|
-
* @private
|
158
111
|
*/
|
159
112
|
async _startLocalProcess(blockInstance, blockInfo, env, assetVersion) {
|
160
|
-
const baseDir = ClusterConfig.getRepositoryAssetPath(
|
161
|
-
blockInfo.handle,
|
162
|
-
blockInfo.name,
|
163
|
-
blockInfo.version
|
164
|
-
);
|
165
|
-
|
113
|
+
const baseDir = ClusterConfig.getRepositoryAssetPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
166
114
|
if (!FS.existsSync(baseDir)) {
|
167
|
-
throw new Error(
|
168
|
-
`
|
169
|
-
`Make sure you've run "blockctl registry link" in your local directory to connect it to Kapeta`
|
170
|
-
);
|
115
|
+
throw new Error(`Local block not registered correctly - expected symlink here: ${baseDir}.\n` +
|
116
|
+
`Make sure you've run "blockctl registry link" in your local directory to connect it to Kapeta`);
|
171
117
|
}
|
172
|
-
|
173
118
|
if (!assetVersion.definition.spec?.target?.kind) {
|
174
119
|
throw new Error('Missing target kind in block definition');
|
175
120
|
}
|
176
|
-
|
177
121
|
const kindUri = parseKapetaUri(assetVersion.definition.spec?.target?.kind);
|
178
|
-
|
179
122
|
const targetVersion = getProvider(kindUri);
|
180
|
-
|
181
123
|
if (!targetVersion) {
|
182
124
|
throw new Error(`Target not found: ${kindUri.id}`);
|
183
125
|
}
|
184
|
-
|
185
126
|
const localContainer = targetVersion.definition.spec.local;
|
186
|
-
|
187
127
|
if (!localContainer) {
|
188
128
|
throw new Error(`Missing local container information from target: ${kindUri.id}`);
|
189
129
|
}
|
190
|
-
|
191
130
|
const dockerImage = localContainer.image;
|
192
131
|
if (!dockerImage) {
|
193
132
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
194
133
|
}
|
195
|
-
|
196
134
|
const containerName = `kapeta-block-instance-${blockInstance.id}`;
|
197
135
|
const logs = new LogData();
|
198
136
|
logs.addLog(`Starting block ${blockInstance.ref}`);
|
199
|
-
let container = await containerManager.getContainerByName(containerName);
|
137
|
+
let container = (await containerManager.getContainerByName(containerName)) ?? null;
|
200
138
|
console.log('Starting dev container', containerName);
|
201
|
-
|
202
139
|
if (container) {
|
203
140
|
console.log(`Container already exists. Deleting...`);
|
204
141
|
try {
|
205
142
|
await container.delete({
|
206
|
-
force: true
|
207
|
-
})
|
208
|
-
}
|
143
|
+
force: true,
|
144
|
+
});
|
145
|
+
}
|
146
|
+
catch (e) {
|
209
147
|
throw new Error('Failed to delete existing container: ' + e.message);
|
210
148
|
}
|
211
149
|
container = null;
|
212
150
|
}
|
213
|
-
|
214
151
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
215
152
|
console.log('Creating new dev container', containerName, dockerImage);
|
216
153
|
await containerManager.pull(dockerImage);
|
217
|
-
|
218
154
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
219
155
|
const dockerOpts = localContainer.options ?? {};
|
220
156
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
221
157
|
const workingDir = localContainer.workingDir ? localContainer.workingDir : '/workspace';
|
222
|
-
|
223
158
|
const ExposedPorts = {};
|
224
159
|
const addonEnv = {};
|
225
160
|
const PortBindings = {};
|
226
|
-
|
227
161
|
const portTypes = getProviderPorts(assetVersion);
|
228
162
|
let port = 80;
|
229
|
-
const promises = portTypes
|
230
|
-
.
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
{
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
];
|
243
|
-
});
|
244
|
-
|
163
|
+
const promises = portTypes.map(async (portType) => {
|
164
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
165
|
+
const thisPort = port++; //TODO: Not sure how we should handle multiple ports or non-HTTP ports
|
166
|
+
const dockerPort = `${thisPort}/tcp`;
|
167
|
+
ExposedPorts[dockerPort] = {};
|
168
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = '' + thisPort;
|
169
|
+
PortBindings[dockerPort] = [
|
170
|
+
{
|
171
|
+
HostIp: '127.0.0.1',
|
172
|
+
HostPort: `${publicPort}`,
|
173
|
+
},
|
174
|
+
];
|
175
|
+
});
|
245
176
|
await Promise.all(promises);
|
246
|
-
|
247
177
|
let HealthCheck = undefined;
|
248
178
|
if (localContainer.healthcheck) {
|
249
|
-
HealthCheck = containerManager.toDockerHealth({cmd: localContainer.healthcheck});
|
179
|
+
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
250
180
|
}
|
251
|
-
|
252
181
|
container = await containerManager.startContainer({
|
253
182
|
Image: dockerImage,
|
254
183
|
name: containerName,
|
255
184
|
WorkingDir: workingDir,
|
256
185
|
Labels: {
|
257
|
-
|
186
|
+
instance: blockInstance.id,
|
258
187
|
},
|
259
188
|
HealthCheck,
|
260
189
|
ExposedPorts,
|
@@ -264,118 +193,88 @@ class BlockInstanceRunner {
|
|
264
193
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
265
194
|
...Object.entries({
|
266
195
|
...env,
|
267
|
-
...addonEnv
|
268
|
-
}).map(([key, value]) => `${key}=${value}`)
|
196
|
+
...addonEnv,
|
197
|
+
}).map(([key, value]) => `${key}=${value}`),
|
269
198
|
],
|
270
199
|
HostConfig: {
|
271
200
|
Binds: [
|
272
201
|
`${ClusterConfig.getKapetaBasedir()}:${homeDir}/.kapeta`,
|
273
|
-
`${baseDir}:${workingDir}
|
202
|
+
`${baseDir}:${workingDir}`, //We mount
|
274
203
|
],
|
275
|
-
PortBindings
|
204
|
+
PortBindings,
|
276
205
|
},
|
277
|
-
...dockerOpts
|
206
|
+
...dockerOpts,
|
278
207
|
});
|
279
|
-
|
280
208
|
try {
|
281
209
|
if (HealthCheck) {
|
282
210
|
await containerManager.waitForHealthy(container);
|
283
|
-
}
|
211
|
+
}
|
212
|
+
else {
|
284
213
|
await containerManager.waitForReady(container);
|
285
214
|
}
|
286
|
-
}
|
215
|
+
}
|
216
|
+
catch (e) {
|
287
217
|
logs.addLog(e.message, 'ERROR');
|
288
218
|
}
|
289
|
-
|
290
219
|
return this._handleContainer(container, logs);
|
291
220
|
}
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
* @param container
|
296
|
-
* @param logs
|
297
|
-
* @param deleteOnExit
|
298
|
-
* @return {Promise<ProcessDetails>}
|
299
|
-
* @private
|
300
|
-
*/
|
301
|
-
async _handleContainer(container, logs , deleteOnExit = false) {
|
302
|
-
const logStream = await container.logs({
|
221
|
+
async _handleContainer(container, logs, deleteOnExit = false) {
|
222
|
+
let localContainer = container;
|
223
|
+
const logStream = (await container.logs({
|
303
224
|
follow: true,
|
304
225
|
stdout: true,
|
305
226
|
stderr: true,
|
306
|
-
tail: LogData.MAX_LINES
|
307
|
-
})
|
308
|
-
|
227
|
+
tail: LogData.MAX_LINES,
|
228
|
+
}));
|
309
229
|
const outputEvents = new EventEmitter();
|
310
230
|
logStream.on('data', (data) => {
|
311
231
|
logs.addLog(data.toString());
|
312
232
|
outputEvents.emit('data', data);
|
313
233
|
});
|
314
|
-
|
315
234
|
logStream.on('error', (data) => {
|
316
235
|
logs.addLog(data.toString());
|
317
236
|
outputEvents.emit('data', data);
|
318
237
|
});
|
319
|
-
|
320
238
|
logStream.on('close', async () => {
|
321
239
|
const status = await container.status();
|
240
|
+
const data = status.data;
|
322
241
|
if (deleteOnExit) {
|
323
242
|
try {
|
324
|
-
await container.delete()
|
325
|
-
}
|
243
|
+
await container.delete();
|
244
|
+
}
|
245
|
+
catch (e) { }
|
326
246
|
}
|
327
|
-
outputEvents.emit('exit',
|
247
|
+
outputEvents.emit('exit', data?.State?.ExitCode ?? 0);
|
328
248
|
});
|
329
|
-
/**
|
330
|
-
*
|
331
|
-
* @type {ProcessDetails}
|
332
|
-
*/
|
333
249
|
return {
|
334
250
|
type: 'docker',
|
335
251
|
pid: container.id,
|
336
252
|
output: outputEvents,
|
337
253
|
stop: async () => {
|
338
|
-
if (!
|
254
|
+
if (!localContainer) {
|
339
255
|
return;
|
340
256
|
}
|
341
|
-
|
342
257
|
try {
|
343
|
-
await
|
258
|
+
await localContainer.stop();
|
344
259
|
if (deleteOnExit) {
|
345
|
-
await
|
260
|
+
await localContainer.delete();
|
346
261
|
}
|
347
|
-
}
|
348
|
-
|
262
|
+
}
|
263
|
+
catch (e) { }
|
264
|
+
localContainer = null;
|
349
265
|
},
|
350
266
|
logs: () => {
|
351
267
|
return logs.getLogs();
|
352
|
-
}
|
268
|
+
},
|
353
269
|
};
|
354
270
|
}
|
355
|
-
|
356
|
-
|
357
|
-
/**
|
358
|
-
* Starts local process using docker
|
359
|
-
* @param {BlockInstanceInfo} blockInstance
|
360
|
-
* @param {BlockInfo} blockInfo
|
361
|
-
* @param {EnvironmentVariables} env
|
362
|
-
* @return {Promise<ProcessDetails>}
|
363
|
-
* @private
|
364
|
-
*/
|
365
271
|
async _startDockerProcess(blockInstance, blockInfo, env) {
|
366
|
-
const {versionFile} = ClusterConfig.getRepositoryAssetInfoPath(
|
367
|
-
blockInfo.handle,
|
368
|
-
blockInfo.name,
|
369
|
-
blockInfo.version
|
370
|
-
);
|
371
|
-
|
272
|
+
const { versionFile } = ClusterConfig.getRepositoryAssetInfoPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
372
273
|
const versionYml = versionFile;
|
373
274
|
if (!FS.existsSync(versionYml)) {
|
374
275
|
throw new Error(`Did not find version info at the expected path: ${versionYml}`);
|
375
276
|
}
|
376
|
-
|
377
277
|
const versionInfo = readYML(versionYml);
|
378
|
-
|
379
278
|
if (versionInfo?.artifact?.type !== 'docker') {
|
380
279
|
throw new Error(`Unsupported artifact type: ${versionInfo?.artifact?.type}`);
|
381
280
|
}
|
@@ -383,49 +282,45 @@ class BlockInstanceRunner {
|
|
383
282
|
if (!dockerImage) {
|
384
283
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
385
284
|
}
|
386
|
-
|
387
285
|
const containerName = `kapeta-block-instance-${blockInstance.id}`;
|
388
286
|
const logs = new LogData();
|
389
287
|
let container = await containerManager.getContainerByName(containerName);
|
390
|
-
|
391
288
|
if (container) {
|
392
|
-
|
289
|
+
const containerData = container.data;
|
290
|
+
if (containerData.State === 'running') {
|
393
291
|
logs.addLog(`Found existing running container for block: ${containerName}`);
|
394
|
-
}
|
292
|
+
}
|
293
|
+
else {
|
395
294
|
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
396
295
|
await container.start();
|
397
296
|
}
|
398
|
-
}
|
297
|
+
}
|
298
|
+
else {
|
399
299
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
400
300
|
container = await containerManager.startContainer({
|
401
301
|
Image: dockerImage,
|
402
302
|
name: containerName,
|
403
303
|
Labels: {
|
404
|
-
|
304
|
+
instance: blockInstance.id,
|
405
305
|
},
|
406
306
|
Env: [
|
407
307
|
...DOCKER_ENV_VARS,
|
408
308
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
409
|
-
...Object.entries(env).map(([key, value]) => `${key}=${value}`)
|
309
|
+
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
410
310
|
],
|
411
311
|
HostConfig: {
|
412
|
-
Binds: [
|
413
|
-
|
414
|
-
],
|
415
|
-
|
416
|
-
}
|
312
|
+
Binds: [`${ClusterConfig.getKapetaBasedir()}:${ClusterConfig.getKapetaBasedir()}`],
|
313
|
+
},
|
417
314
|
});
|
418
|
-
|
419
315
|
try {
|
420
316
|
await containerManager.waitForReady(container);
|
421
|
-
}
|
317
|
+
}
|
318
|
+
catch (e) {
|
422
319
|
logs.addLog(e.message, 'ERROR');
|
423
320
|
}
|
424
321
|
}
|
425
|
-
|
426
322
|
return this._handleContainer(container, logs);
|
427
323
|
}
|
428
|
-
|
429
324
|
/**
|
430
325
|
*
|
431
326
|
* @param blockInstance
|
@@ -436,98 +331,87 @@ class BlockInstanceRunner {
|
|
436
331
|
* @private
|
437
332
|
*/
|
438
333
|
async _startOperatorProcess(blockInstance, blockUri, providerDefinition, env) {
|
439
|
-
const {assetFile} = ClusterConfig.getRepositoryAssetInfoPath(
|
440
|
-
blockUri.handle,
|
441
|
-
blockUri.name,
|
442
|
-
blockUri.version
|
443
|
-
);
|
444
|
-
|
334
|
+
const { assetFile } = ClusterConfig.getRepositoryAssetInfoPath(blockUri.handle, blockUri.name, blockUri.version);
|
445
335
|
const kapetaYmlPath = assetFile;
|
446
336
|
if (!FS.existsSync(kapetaYmlPath)) {
|
447
337
|
throw new Error(`Did not find kapeta.yml at the expected path: ${kapetaYmlPath}`);
|
448
338
|
}
|
449
|
-
|
450
339
|
const spec = providerDefinition.definition.spec;
|
451
340
|
const providerRef = `${providerDefinition.definition.metadata.name}:${providerDefinition.version}`;
|
452
|
-
|
453
341
|
if (!spec?.local?.image) {
|
454
342
|
throw new Error(`Provider did not have local image: ${providerRef}`);
|
455
343
|
}
|
456
|
-
|
457
344
|
const dockerImage = spec?.local?.image;
|
458
|
-
|
459
345
|
try {
|
460
346
|
await containerManager.pull(dockerImage);
|
461
|
-
}
|
347
|
+
}
|
348
|
+
catch (e) {
|
462
349
|
console.warn('Failed to pull image. Continuing...', e);
|
463
350
|
}
|
464
|
-
|
465
351
|
const containerName = `kapeta-block-instance-${md5(blockInstance.id)}`;
|
466
352
|
const logs = new LogData();
|
467
|
-
let container = await containerManager.getContainerByName(containerName);
|
468
|
-
|
353
|
+
let container = (await containerManager.getContainerByName(containerName)) ?? null;
|
469
354
|
if (container) {
|
470
|
-
|
355
|
+
const containerData = container.data;
|
356
|
+
if (containerData.State === 'running') {
|
471
357
|
logs.addLog(`Found existing running container for block: ${containerName}`);
|
472
|
-
}
|
473
|
-
|
474
|
-
|
358
|
+
}
|
359
|
+
else {
|
360
|
+
if (containerData.State?.ExitCode > 0) {
|
361
|
+
logs.addLog(`Container exited with code: ${containerData.State.ExitCode}. Deleting...`);
|
475
362
|
try {
|
476
|
-
await container.delete()
|
477
|
-
}
|
363
|
+
await container.delete();
|
364
|
+
}
|
365
|
+
catch (e) { }
|
478
366
|
container = null;
|
479
|
-
}
|
367
|
+
}
|
368
|
+
else {
|
480
369
|
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
481
370
|
try {
|
482
371
|
await container.start();
|
483
|
-
}
|
372
|
+
}
|
373
|
+
catch (e) {
|
484
374
|
console.warn('Failed to start container. Deleting...', e);
|
485
375
|
try {
|
486
|
-
await container.delete()
|
487
|
-
}
|
376
|
+
await container.delete();
|
377
|
+
}
|
378
|
+
catch (e) { }
|
488
379
|
container = null;
|
489
380
|
}
|
490
381
|
}
|
491
382
|
}
|
492
383
|
}
|
493
|
-
|
494
384
|
if (!container) {
|
495
385
|
const ExposedPorts = {};
|
496
386
|
const addonEnv = {};
|
497
387
|
const PortBindings = {};
|
498
388
|
let HealthCheck = undefined;
|
499
389
|
let Mounts = [];
|
500
|
-
const promises = Object.entries(spec.local.ports)
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
});
|
513
|
-
|
390
|
+
const promises = Object.entries(spec.local.ports).map(async ([portType, value]) => {
|
391
|
+
const dockerPort = `${value.port}/${value.type}`;
|
392
|
+
ExposedPorts[dockerPort] = {};
|
393
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = value.port;
|
394
|
+
const publicPort = await serviceManager.ensureServicePort(this._systemId, blockInstance.id, portType);
|
395
|
+
PortBindings[dockerPort] = [
|
396
|
+
{
|
397
|
+
HostIp: '127.0.0.1',
|
398
|
+
HostPort: `${publicPort}`,
|
399
|
+
},
|
400
|
+
];
|
401
|
+
});
|
514
402
|
await Promise.all(promises);
|
515
|
-
|
516
403
|
if (spec.local?.env) {
|
517
404
|
Object.entries(spec.local.env).forEach(([key, value]) => {
|
518
405
|
addonEnv[key] = value;
|
519
406
|
});
|
520
407
|
}
|
521
|
-
|
522
408
|
if (spec.local?.mounts) {
|
523
409
|
const mounts = containerManager.createMounts(blockUri.id, spec.local.mounts);
|
524
410
|
Mounts = containerManager.toDockerMounts(mounts);
|
525
411
|
}
|
526
|
-
|
527
412
|
if (spec.local?.health) {
|
528
413
|
HealthCheck = containerManager.toDockerHealth(spec.local?.health);
|
529
414
|
}
|
530
|
-
|
531
415
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
532
416
|
container = await containerManager.startContainer({
|
533
417
|
Image: dockerImage,
|
@@ -537,13 +421,13 @@ class BlockInstanceRunner {
|
|
537
421
|
HostConfig: {
|
538
422
|
Binds: [
|
539
423
|
`${kapetaYmlPath}:/kapeta.yml:ro`,
|
540
|
-
`${ClusterConfig.getKapetaBasedir()}:${ClusterConfig.getKapetaBasedir()}
|
424
|
+
`${ClusterConfig.getKapetaBasedir()}:${ClusterConfig.getKapetaBasedir()}`,
|
541
425
|
],
|
542
426
|
PortBindings,
|
543
|
-
Mounts
|
427
|
+
Mounts,
|
544
428
|
},
|
545
429
|
Labels: {
|
546
|
-
|
430
|
+
instance: blockInstance.id,
|
547
431
|
},
|
548
432
|
Env: [
|
549
433
|
`KAPETA_INSTANCE_NAME=${blockInstance.ref}`,
|
@@ -551,30 +435,27 @@ class BlockInstanceRunner {
|
|
551
435
|
...DOCKER_ENV_VARS,
|
552
436
|
...Object.entries({
|
553
437
|
...env,
|
554
|
-
...addonEnv
|
555
|
-
}).map(([key, value]) => `${key}=${value}`)
|
556
|
-
]
|
438
|
+
...addonEnv,
|
439
|
+
}).map(([key, value]) => `${key}=${value}`),
|
440
|
+
],
|
557
441
|
});
|
558
|
-
|
559
442
|
try {
|
560
443
|
if (HealthCheck) {
|
561
444
|
await containerManager.waitForHealthy(container);
|
562
|
-
}
|
445
|
+
}
|
446
|
+
else {
|
563
447
|
await containerManager.waitForReady(container);
|
564
448
|
}
|
565
|
-
}
|
449
|
+
}
|
450
|
+
catch (e) {
|
566
451
|
logs.addLog(e.message, 'ERROR');
|
567
452
|
}
|
568
453
|
}
|
569
|
-
|
570
454
|
const out = await this._handleContainer(container, logs, true);
|
571
455
|
const portTypes = spec.local.ports ? Object.keys(spec.local.ports) : [];
|
572
456
|
if (portTypes.length > 0) {
|
573
457
|
out.portType = portTypes[0];
|
574
458
|
}
|
575
|
-
|
576
459
|
return out;
|
577
460
|
}
|
578
461
|
}
|
579
|
-
|
580
|
-
module.exports = BlockInstanceRunner;
|