@kapeta/local-cluster-service 0.8.2 → 0.9.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 +14 -0
- package/definitions.d.ts +1 -1
- package/dist/cjs/index.js +3 -3
- package/dist/cjs/src/assetManager.js +7 -4
- package/dist/cjs/src/attachments/routes.js +4 -4
- package/dist/cjs/src/clusterService.js +2 -0
- package/dist/cjs/src/codeGeneratorManager.js +3 -3
- package/dist/cjs/src/config/routes.js +1 -1
- package/dist/cjs/src/configManager.js +13 -1
- package/dist/cjs/src/containerManager.d.ts +22 -2
- package/dist/cjs/src/containerManager.js +42 -15
- package/dist/cjs/src/definitionsManager.d.ts +11 -0
- package/dist/cjs/src/definitionsManager.js +44 -0
- package/dist/cjs/src/filesystemManager.js +0 -2
- package/dist/cjs/src/instanceManager.d.ts +23 -47
- package/dist/cjs/src/instanceManager.js +416 -235
- package/dist/cjs/src/instances/routes.js +23 -14
- package/dist/cjs/src/middleware/kapeta.js +7 -0
- package/dist/cjs/src/networkManager.js +6 -0
- package/dist/cjs/src/operatorManager.js +8 -4
- package/dist/cjs/src/providerManager.js +3 -3
- package/dist/cjs/src/repositoryManager.js +7 -3
- package/dist/cjs/src/serviceManager.js +5 -0
- package/dist/cjs/src/types.d.ts +39 -13
- package/dist/cjs/src/types.js +28 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +3 -3
- package/dist/cjs/src/utils/BlockInstanceRunner.js +28 -29
- package/dist/cjs/src/utils/utils.d.ts +2 -0
- package/dist/cjs/src/utils/utils.js +18 -2
- package/dist/esm/index.js +4 -4
- package/dist/esm/src/assetManager.js +7 -4
- package/dist/esm/src/attachments/routes.js +5 -5
- package/dist/esm/src/clusterService.js +2 -0
- package/dist/esm/src/codeGeneratorManager.js +3 -3
- package/dist/esm/src/config/routes.js +1 -1
- package/dist/esm/src/configManager.js +13 -1
- package/dist/esm/src/containerManager.d.ts +22 -2
- package/dist/esm/src/containerManager.js +41 -14
- package/dist/esm/src/definitionsManager.d.ts +11 -0
- package/dist/esm/src/definitionsManager.js +38 -0
- package/dist/esm/src/filesystemManager.js +0 -2
- package/dist/esm/src/instanceManager.d.ts +23 -47
- package/dist/esm/src/instanceManager.js +416 -236
- package/dist/esm/src/instances/routes.js +23 -14
- package/dist/esm/src/middleware/kapeta.js +7 -0
- package/dist/esm/src/networkManager.js +6 -0
- package/dist/esm/src/operatorManager.js +8 -4
- package/dist/esm/src/providerManager.js +3 -3
- package/dist/esm/src/repositoryManager.js +7 -3
- package/dist/esm/src/serviceManager.js +5 -0
- package/dist/esm/src/types.d.ts +39 -13
- package/dist/esm/src/types.js +27 -1
- package/dist/esm/src/utils/BlockInstanceRunner.d.ts +3 -3
- package/dist/esm/src/utils/BlockInstanceRunner.js +29 -30
- package/dist/esm/src/utils/utils.d.ts +2 -0
- package/dist/esm/src/utils/utils.js +15 -1
- package/index.ts +10 -8
- package/package.json +2 -1
- package/src/assetManager.ts +7 -4
- package/src/attachments/routes.ts +8 -8
- package/src/clusterService.ts +3 -0
- package/src/codeGeneratorManager.ts +3 -2
- package/src/config/routes.ts +1 -1
- package/src/configManager.ts +13 -1
- package/src/containerManager.ts +63 -16
- package/src/definitionsManager.ts +54 -0
- package/src/filesystemManager.ts +0 -2
- package/src/identities/routes.ts +2 -3
- package/src/instanceManager.ts +495 -266
- package/src/instances/routes.ts +23 -17
- package/src/middleware/kapeta.ts +10 -0
- package/src/networkManager.ts +6 -0
- package/src/operatorManager.ts +11 -6
- package/src/providerManager.ts +3 -2
- package/src/repositoryManager.ts +14 -10
- package/src/serviceManager.ts +6 -0
- package/src/storageService.ts +1 -1
- package/src/types.ts +44 -14
- package/src/utils/BlockInstanceRunner.ts +34 -34
- package/src/utils/utils.ts +20 -2
package/src/instances/routes.ts
CHANGED
@@ -5,7 +5,7 @@ import { corsHandler } from '../middleware/cors';
|
|
5
5
|
import { NextFunction, Request, Response } from 'express';
|
6
6
|
import { kapetaHeaders, KapetaRequest } from '../middleware/kapeta';
|
7
7
|
import { stringBody } from '../middleware/stringBody';
|
8
|
-
import {
|
8
|
+
import { DesiredInstanceStatus, InstanceInfo, InstanceOwner, InstanceType, KapetaBodyRequest } from '../types';
|
9
9
|
|
10
10
|
const router = Router();
|
11
11
|
router.use('/', corsHandler);
|
@@ -28,11 +28,11 @@ router.get('/:systemId/instances', (req: Request, res: Response) => {
|
|
28
28
|
* Start all instances in a plan
|
29
29
|
*/
|
30
30
|
router.post('/:systemId/start', async (req: Request, res: Response) => {
|
31
|
-
const
|
31
|
+
const instances = await instanceManager.startAllForPlan(req.params.systemId);
|
32
32
|
|
33
33
|
res.status(202).send({
|
34
34
|
ok: true,
|
35
|
-
processes:
|
35
|
+
processes: instances.map((p) => {
|
36
36
|
return { pid: p.pid, type: p.type };
|
37
37
|
}),
|
38
38
|
});
|
@@ -53,7 +53,7 @@ router.post('/:systemId/stop', async (req: Request, res: Response) => {
|
|
53
53
|
* Start single instance in a plan
|
54
54
|
*/
|
55
55
|
router.post('/:systemId/:instanceId/start', async (req: Request, res: Response) => {
|
56
|
-
const process = await instanceManager.
|
56
|
+
const process = await instanceManager.start(req.params.systemId, req.params.instanceId);
|
57
57
|
|
58
58
|
res.status(202).send({
|
59
59
|
ok: true,
|
@@ -66,7 +66,7 @@ router.post('/:systemId/:instanceId/start', async (req: Request, res: Response)
|
|
66
66
|
* Stop single instance in a plan
|
67
67
|
*/
|
68
68
|
router.post('/:systemId/:instanceId/stop', async (req: Request, res: Response) => {
|
69
|
-
await instanceManager.
|
69
|
+
await instanceManager.stop(req.params.systemId, req.params.instanceId);
|
70
70
|
|
71
71
|
res.status(202).send({ ok: true });
|
72
72
|
});
|
@@ -75,14 +75,14 @@ router.post('/:systemId/:instanceId/stop', async (req: Request, res: Response) =
|
|
75
75
|
* Get logs for instance in a plan
|
76
76
|
*/
|
77
77
|
router.get('/:systemId/:instanceId/logs', (req: Request, res: Response) => {
|
78
|
-
const
|
79
|
-
if (!
|
78
|
+
const instanceInfo = instanceManager.getInstance(req.params.systemId, req.params.instanceId);
|
79
|
+
if (!instanceInfo) {
|
80
80
|
res.status(404).send({ ok: false });
|
81
81
|
return;
|
82
82
|
}
|
83
83
|
|
84
84
|
res.status(202).send({
|
85
|
-
logs:
|
85
|
+
logs: instanceInfo.internal?.logs() ?? [],
|
86
86
|
});
|
87
87
|
});
|
88
88
|
|
@@ -132,31 +132,37 @@ router.use('/', (req: KapetaBodyRequest, res: Response, next: NextFunction) => {
|
|
132
132
|
});
|
133
133
|
|
134
134
|
/**
|
135
|
-
* Updates the full configuration for a given
|
135
|
+
* Updates the full configuration for a given instance.
|
136
136
|
*/
|
137
137
|
router.put('/', async (req: KapetaBodyRequest, res: Response) => {
|
138
|
-
let instance = req.stringBody ? JSON.parse(req.stringBody) : null;
|
138
|
+
let instance: InstanceInfo = req.stringBody ? JSON.parse(req.stringBody) : null;
|
139
139
|
if (req.kapeta!.environment === 'docker') {
|
140
140
|
//A bit hacky but we want to avoid overwriting the docker PID with a process PID
|
141
141
|
const oldInstance = instanceManager.getInstance(req.kapeta!.systemId, req.kapeta!.instanceId);
|
142
142
|
if (oldInstance) {
|
143
143
|
instance.pid = oldInstance.pid;
|
144
144
|
}
|
145
|
-
instance.type =
|
146
|
-
} else
|
147
|
-
instance
|
145
|
+
instance.type = InstanceType.DOCKER;
|
146
|
+
} else {
|
147
|
+
// Coming from user starting the instance outside of kapeta
|
148
|
+
instance.type = InstanceType.LOCAL;
|
149
|
+
instance.owner = InstanceOwner.EXTERNAL;
|
150
|
+
instance.desiredStatus = DesiredInstanceStatus.EXTERNAL;
|
148
151
|
}
|
149
152
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
+
try {
|
154
|
+
await instanceManager.registerInstanceFromSDK(req.kapeta!.systemId, req.kapeta!.instanceId, instance);
|
155
|
+
res.status(202).send({ ok: true });
|
156
|
+
} catch (e: any) {
|
157
|
+
res.status(400).send({ error: e.message });
|
158
|
+
}
|
153
159
|
});
|
154
160
|
|
155
161
|
/**
|
156
162
|
* Delete instance
|
157
163
|
*/
|
158
164
|
router.delete('/', async (req: KapetaRequest, res: Response) => {
|
159
|
-
await instanceManager.
|
165
|
+
await instanceManager.markAsStopped(req.kapeta!.systemId, req.kapeta!.instanceId);
|
160
166
|
|
161
167
|
res.status(202).send({ ok: true });
|
162
168
|
});
|
package/src/middleware/kapeta.ts
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import { NextFunction, Request, Response } from 'express';
|
2
2
|
import { EnvironmentType } from '../types';
|
3
|
+
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
4
|
+
import { normalizeKapetaUri } from '../utils/utils';
|
3
5
|
|
4
6
|
export interface KapetaRequest extends Request {
|
5
7
|
kapeta?: {
|
@@ -16,6 +18,14 @@ export function kapetaHeaders(req: KapetaRequest, res: Response, next: NextFunct
|
|
16
18
|
let instanceId: string = req.headers['x-kapeta-instance'] as string;
|
17
19
|
let environment: string = req.headers['x-kapeta-environment'] as string;
|
18
20
|
|
21
|
+
if (blockRef) {
|
22
|
+
blockRef = normalizeKapetaUri(blockRef);
|
23
|
+
}
|
24
|
+
|
25
|
+
if (systemId) {
|
26
|
+
systemId = normalizeKapetaUri(systemId);
|
27
|
+
}
|
28
|
+
|
19
29
|
req.kapeta = {
|
20
30
|
blockRef,
|
21
31
|
instanceId,
|
package/src/networkManager.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import uuid from 'node-uuid';
|
2
2
|
import { Connection, SimpleRequest, SimpleResponse } from './types';
|
3
3
|
import express from 'express';
|
4
|
+
import { normalizeKapetaUri } from './utils/utils';
|
4
5
|
|
5
6
|
class NetworkManager {
|
6
7
|
private _connections: { [systemId: string]: { [connectionId: string]: Traffic[] } };
|
@@ -23,6 +24,7 @@ class NetworkManager {
|
|
23
24
|
}
|
24
25
|
|
25
26
|
_ensureSystem(systemId: string) {
|
27
|
+
systemId = normalizeKapetaUri(systemId);
|
26
28
|
if (!this._connections[systemId]) {
|
27
29
|
this._connections[systemId] = {};
|
28
30
|
}
|
@@ -37,6 +39,7 @@ class NetworkManager {
|
|
37
39
|
}
|
38
40
|
|
39
41
|
_ensureConnection(systemId: string, connectionId: string) {
|
42
|
+
systemId = normalizeKapetaUri(systemId);
|
40
43
|
this._ensureSystem(systemId);
|
41
44
|
|
42
45
|
if (!this._connections[systemId][connectionId]) {
|
@@ -47,6 +50,7 @@ class NetworkManager {
|
|
47
50
|
}
|
48
51
|
|
49
52
|
_ensureSource(systemId: string, sourceBlockInstanceId: string) {
|
53
|
+
systemId = normalizeKapetaUri(systemId);
|
50
54
|
this._ensureSystem(systemId);
|
51
55
|
|
52
56
|
if (!this._sources[systemId][sourceBlockInstanceId]) {
|
@@ -57,6 +61,7 @@ class NetworkManager {
|
|
57
61
|
}
|
58
62
|
|
59
63
|
_ensureTarget(systemId: string, targetBlockInstanceId: string) {
|
64
|
+
systemId = normalizeKapetaUri(systemId);
|
60
65
|
this._ensureSystem(systemId);
|
61
66
|
|
62
67
|
if (!this._targets[systemId][targetBlockInstanceId]) {
|
@@ -73,6 +78,7 @@ class NetworkManager {
|
|
73
78
|
consumerMethodId?: string,
|
74
79
|
providerMethodId?: string
|
75
80
|
) {
|
81
|
+
systemId = normalizeKapetaUri(systemId);
|
76
82
|
const traffic = new Traffic(connection, request, consumerMethodId, providerMethodId);
|
77
83
|
|
78
84
|
this._ensureConnection(systemId, traffic.connectionId).push(traffic);
|
package/src/operatorManager.ts
CHANGED
@@ -8,6 +8,8 @@ import { ContainerInfo, containerManager } from './containerManager';
|
|
8
8
|
import FSExtra from 'fs-extra';
|
9
9
|
import { AnyMap, EnvironmentType, OperatorInfo } from './types';
|
10
10
|
import { BlockInstance, Resource } from '@kapeta/schemas';
|
11
|
+
import { definitionsManager } from './definitionsManager';
|
12
|
+
import { normalizeKapetaUri } from './utils/utils';
|
11
13
|
|
12
14
|
const KIND_OPERATOR = 'core/resource-type-operator';
|
13
15
|
|
@@ -47,7 +49,7 @@ class OperatorManager {
|
|
47
49
|
* @return {Operator}
|
48
50
|
*/
|
49
51
|
getOperator(resourceType: string, version: string) {
|
50
|
-
const operators =
|
52
|
+
const operators = definitionsManager.getDefinitions(KIND_OPERATOR);
|
51
53
|
|
52
54
|
const operator: DefinitionInfo | undefined = operators.find(
|
53
55
|
(operator) =>
|
@@ -80,7 +82,8 @@ class OperatorManager {
|
|
80
82
|
name: string,
|
81
83
|
environment?: EnvironmentType
|
82
84
|
): Promise<OperatorInfo> {
|
83
|
-
|
85
|
+
systemId = normalizeKapetaUri(systemId);
|
86
|
+
const plans = definitionsManager.getDefinitions('core/plan');
|
84
87
|
|
85
88
|
const planUri = parseKapetaUri(systemId);
|
86
89
|
const currentPlan = plans.find(
|
@@ -98,10 +101,12 @@ class OperatorManager {
|
|
98
101
|
}
|
99
102
|
|
100
103
|
const blockUri = parseKapetaUri(currentInstance.block.ref);
|
101
|
-
const blockDefinition =
|
102
|
-
(
|
103
|
-
|
104
|
-
|
104
|
+
const blockDefinition = definitionsManager
|
105
|
+
.getDefinitions()
|
106
|
+
.find(
|
107
|
+
(definition) =>
|
108
|
+
definition.version === blockUri.version && definition.definition.metadata.name === blockUri.fullName
|
109
|
+
);
|
105
110
|
|
106
111
|
if (!blockDefinition) {
|
107
112
|
throw new Error(`Unknown block: ${currentInstance.block.ref} in plan ${systemId}`);
|
package/src/providerManager.ts
CHANGED
@@ -3,6 +3,7 @@ import FSExtra from 'fs-extra';
|
|
3
3
|
import { repositoryManager } from './repositoryManager';
|
4
4
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
5
5
|
import { StringMap } from './types';
|
6
|
+
import { definitionsManager } from './definitionsManager';
|
6
7
|
|
7
8
|
class ProviderManager {
|
8
9
|
private _webAssetCache: StringMap;
|
@@ -11,7 +12,7 @@ class ProviderManager {
|
|
11
12
|
}
|
12
13
|
|
13
14
|
getWebProviders() {
|
14
|
-
return
|
15
|
+
return definitionsManager.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
|
15
16
|
}
|
16
17
|
|
17
18
|
async getAsset(handle: string, name: string, version: string, sourceMap: boolean = false) {
|
@@ -42,7 +43,7 @@ class ProviderManager {
|
|
42
43
|
}
|
43
44
|
}
|
44
45
|
|
45
|
-
const providerDefinitions =
|
46
|
+
const providerDefinitions = definitionsManager.getProviderDefinitions();
|
46
47
|
|
47
48
|
if (providerDefinitions.length > 0) {
|
48
49
|
console.log('## Loaded the following providers ##');
|
package/src/repositoryManager.ts
CHANGED
@@ -9,6 +9,7 @@ import { socketManager } from './socketManager';
|
|
9
9
|
import { progressListener } from './progressListener';
|
10
10
|
import { Dependency } from '@kapeta/schemas';
|
11
11
|
import { Actions, Config, RegistryService } from '@kapeta/nodejs-registry-utils';
|
12
|
+
import { definitionsManager } from './definitionsManager';
|
12
13
|
|
13
14
|
const INSTALL_ATTEMPTED: { [p: string]: boolean } = {};
|
14
15
|
|
@@ -41,23 +42,23 @@ class RepositoryManager {
|
|
41
42
|
|
42
43
|
console.log('Watching local repository for provider changes: %s', baseDir);
|
43
44
|
try {
|
44
|
-
this.watcher = watch(baseDir, (filename:string) => {
|
45
|
+
this.watcher = watch(baseDir, (filename: string) => {
|
45
46
|
if (!filename) {
|
46
47
|
return;
|
47
48
|
}
|
48
|
-
|
49
|
+
|
49
50
|
const [handle, name, version] = filename.toString().split(/\//g);
|
50
51
|
if (!name || !version) {
|
51
52
|
return;
|
52
53
|
}
|
53
|
-
|
54
|
+
|
54
55
|
if (!this.changeEventsEnabled) {
|
55
56
|
return;
|
56
57
|
}
|
57
|
-
|
58
|
+
|
58
59
|
const ymlPath = Path.join(baseDir, handle, name, version, 'kapeta.yml');
|
59
60
|
const newDefinitions = ClusterConfiguration.getDefinitions();
|
60
|
-
|
61
|
+
|
61
62
|
const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
|
62
63
|
let currentDefinition = allDefinitions.find((d) => d.ymlPath === ymlPath);
|
63
64
|
const ymlExists = FS.existsSync(ymlPath);
|
@@ -85,15 +86,16 @@ class RepositoryManager {
|
|
85
86
|
return;
|
86
87
|
}
|
87
88
|
}
|
88
|
-
|
89
|
+
|
89
90
|
const payload = {
|
90
91
|
type,
|
91
92
|
definition: currentDefinition?.definition,
|
92
93
|
asset: { handle, name, version },
|
93
94
|
};
|
94
|
-
|
95
|
+
|
95
96
|
allDefinitions = newDefinitions;
|
96
97
|
socketManager.emit(`assets`, 'changed', payload);
|
98
|
+
definitionsManager.clearCache();
|
97
99
|
});
|
98
100
|
} catch (e) {
|
99
101
|
// Fallback to run without watch mode due to potential platform issues.
|
@@ -186,7 +188,7 @@ class RepositoryManager {
|
|
186
188
|
return;
|
187
189
|
}
|
188
190
|
|
189
|
-
const definitions =
|
191
|
+
const definitions = definitionsManager.getDefinitions();
|
190
192
|
const installedAsset = definitions.find(
|
191
193
|
(d) => d.definition.metadata.name === fullName && d.version === version
|
192
194
|
);
|
@@ -221,8 +223,10 @@ class RepositoryManager {
|
|
221
223
|
} else {
|
222
224
|
//Ensure dependencies are installed
|
223
225
|
const refs = assetVersion.dependencies.map((dep: Dependency) => dep.name);
|
224
|
-
|
225
|
-
|
226
|
+
if (refs.length > 0) {
|
227
|
+
console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
|
228
|
+
await this._install(refs);
|
229
|
+
}
|
226
230
|
}
|
227
231
|
}
|
228
232
|
}
|
package/src/serviceManager.ts
CHANGED
@@ -2,6 +2,7 @@ import _ from 'lodash';
|
|
2
2
|
import { clusterService } from './clusterService';
|
3
3
|
import { storageService } from './storageService';
|
4
4
|
import { EnvironmentType } from './types';
|
5
|
+
import { normalizeKapetaUri } from './utils/utils';
|
5
6
|
|
6
7
|
const DEFAULT_PORT_TYPE = 'rest';
|
7
8
|
|
@@ -42,6 +43,8 @@ class ServiceManager {
|
|
42
43
|
}
|
43
44
|
|
44
45
|
_ensureSystem(systemId: string) {
|
46
|
+
systemId = normalizeKapetaUri(systemId);
|
47
|
+
|
45
48
|
if (!this._systems[systemId]) {
|
46
49
|
this._systems[systemId] = {};
|
47
50
|
}
|
@@ -60,6 +63,7 @@ class ServiceManager {
|
|
60
63
|
}
|
61
64
|
|
62
65
|
async ensureServicePort(systemId: string, blockInstanceId: string, portType: string = DEFAULT_PORT_TYPE) {
|
66
|
+
systemId = normalizeKapetaUri(systemId);
|
63
67
|
if (!portType) {
|
64
68
|
portType = DEFAULT_PORT_TYPE;
|
65
69
|
}
|
@@ -94,6 +98,7 @@ class ServiceManager {
|
|
94
98
|
portType: string,
|
95
99
|
environmentType?: EnvironmentType
|
96
100
|
): string {
|
101
|
+
systemId = normalizeKapetaUri(systemId);
|
97
102
|
const port = clusterService.getClusterServicePort();
|
98
103
|
const path = clusterService.getProxyPath(systemId, consumerInstanceId, consumerResourceName, portType);
|
99
104
|
return this._forLocal(port, path, environmentType);
|
@@ -108,6 +113,7 @@ class ServiceManager {
|
|
108
113
|
*
|
109
114
|
*/
|
110
115
|
async getProviderAddress(systemId: string, providerInstanceId: string, portType: string): Promise<string> {
|
116
|
+
systemId = normalizeKapetaUri(systemId);
|
111
117
|
const port = await this.ensureServicePort(systemId, providerInstanceId, portType);
|
112
118
|
return this._forLocal(port);
|
113
119
|
}
|
package/src/storageService.ts
CHANGED
@@ -53,7 +53,7 @@ class StorageService {
|
|
53
53
|
this._writeConfig();
|
54
54
|
}
|
55
55
|
|
56
|
-
get<T = any>(section: string, property?: string, defaultValue?:T): T|undefined {
|
56
|
+
get<T = any>(section: string, property?: string, defaultValue?: T): T | undefined {
|
57
57
|
if (!property) {
|
58
58
|
return this.section(section);
|
59
59
|
}
|
package/src/types.ts
CHANGED
@@ -10,6 +10,7 @@ export type AnyMap = { [key: string]: any };
|
|
10
10
|
export type LogLevel = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'FATAL';
|
11
11
|
export type LogSource = 'stdout' | 'stderr';
|
12
12
|
export type EnvironmentType = 'docker' | 'process';
|
13
|
+
|
13
14
|
export interface LogEntry {
|
14
15
|
source: LogSource;
|
15
16
|
level: LogLevel;
|
@@ -23,32 +24,61 @@ export interface BlockProcessParams {
|
|
23
24
|
configuration?: AnyMap;
|
24
25
|
}
|
25
26
|
|
26
|
-
export
|
27
|
+
export enum InstanceType {
|
28
|
+
DOCKER = 'docker',
|
29
|
+
LOCAL = 'local',
|
30
|
+
UNKNOWN = 'unknown',
|
31
|
+
}
|
32
|
+
export enum InstanceOwner {
|
33
|
+
INTERNAL = 'internal',
|
34
|
+
EXTERNAL = 'external',
|
35
|
+
}
|
27
36
|
|
28
|
-
export
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
export enum InstanceStatus {
|
38
|
+
STOPPED = 'stopped',
|
39
|
+
STARTING = 'starting',
|
40
|
+
BUSY = 'busy',
|
41
|
+
READY = 'ready',
|
42
|
+
STOPPING = 'stopping',
|
43
|
+
UNHEALTHY = 'unhealthy',
|
44
|
+
FAILED = 'failed',
|
35
45
|
}
|
36
46
|
|
37
|
-
export
|
38
|
-
|
39
|
-
|
40
|
-
|
47
|
+
export enum DesiredInstanceStatus {
|
48
|
+
STOP = 'stop',
|
49
|
+
RUN = 'run',
|
50
|
+
EXTERNAL = 'external',
|
41
51
|
}
|
42
52
|
|
53
|
+
export type ProcessInfo = {
|
54
|
+
type: InstanceType;
|
55
|
+
pid?: number | string | null;
|
56
|
+
output: EventEmitter;
|
57
|
+
portType?: string;
|
58
|
+
logs: () => LogEntry[];
|
59
|
+
stop: () => Promise<void> | void;
|
60
|
+
};
|
61
|
+
|
43
62
|
export type InstanceInfo = {
|
44
63
|
systemId: string;
|
45
64
|
instanceId: string;
|
65
|
+
ref: string;
|
66
|
+
name: string;
|
67
|
+
type: InstanceType;
|
68
|
+
owner: InstanceOwner;
|
69
|
+
status: InstanceStatus;
|
70
|
+
desiredStatus: DesiredInstanceStatus;
|
46
71
|
address?: string;
|
72
|
+
|
73
|
+
startedAt?: number;
|
47
74
|
health?: string | null;
|
48
|
-
status: string;
|
49
75
|
pid?: number | string | null;
|
50
|
-
type: ProcessType;
|
51
76
|
portType?: string;
|
77
|
+
|
78
|
+
internal?: {
|
79
|
+
output: EventEmitter;
|
80
|
+
logs: () => LogEntry[];
|
81
|
+
};
|
52
82
|
};
|
53
83
|
|
54
84
|
interface ResourceRef {
|
@@ -1,15 +1,15 @@
|
|
1
1
|
import FS from 'node:fs';
|
2
2
|
import ClusterConfig, { DefinitionInfo } from '@kapeta/local-cluster-config';
|
3
|
-
import { getBindHost, readYML } from './utils';
|
3
|
+
import { getBindHost, getBlockInstanceContainerName, normalizeKapetaUri, readYML } from './utils';
|
4
4
|
import { KapetaURI, parseKapetaUri } from '@kapeta/nodejs-utils';
|
5
5
|
import { serviceManager } from '../serviceManager';
|
6
6
|
import { containerManager, DockerMounts, toLocalBindVolume } from '../containerManager';
|
7
7
|
import { LogData } from './LogData';
|
8
8
|
import EventEmitter from 'events';
|
9
|
-
import md5 from 'md5';
|
10
9
|
import { clusterService } from '../clusterService';
|
11
|
-
import { AnyMap, BlockProcessParams,
|
10
|
+
import { AnyMap, BlockProcessParams, ProcessInfo, InstanceType, StringMap } from '../types';
|
12
11
|
import { Container } from 'node-docker-api/lib/container';
|
12
|
+
import { definitionsManager } from '../definitionsManager';
|
13
13
|
|
14
14
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
15
15
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
@@ -27,7 +27,7 @@ const DOCKER_ENV_VARS = [
|
|
27
27
|
];
|
28
28
|
|
29
29
|
function getProvider(uri: KapetaURI) {
|
30
|
-
return
|
30
|
+
return definitionsManager.getProviderDefinitions().find((provider) => {
|
31
31
|
const ref = `${provider.definition.metadata.name}:${provider.version}`;
|
32
32
|
return parseKapetaUri(ref).id === uri.id;
|
33
33
|
});
|
@@ -46,13 +46,13 @@ function getProviderPorts(assetVersion: DefinitionInfo): string[] {
|
|
46
46
|
export class BlockInstanceRunner {
|
47
47
|
private readonly _systemId: string;
|
48
48
|
|
49
|
-
constructor(
|
49
|
+
constructor(systemId: string) {
|
50
50
|
/**
|
51
51
|
*
|
52
52
|
* @type {string}
|
53
53
|
* @private
|
54
54
|
*/
|
55
|
-
this._systemId =
|
55
|
+
this._systemId = normalizeKapetaUri(systemId);
|
56
56
|
}
|
57
57
|
|
58
58
|
/**
|
@@ -88,7 +88,7 @@ export class BlockInstanceRunner {
|
|
88
88
|
blockUri.version = 'local';
|
89
89
|
}
|
90
90
|
|
91
|
-
const assetVersion =
|
91
|
+
const assetVersion = definitionsManager.getDefinitions().find((definitions) => {
|
92
92
|
const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
|
93
93
|
return parseKapetaUri(ref).id === blockUri.id;
|
94
94
|
});
|
@@ -105,30 +105,26 @@ export class BlockInstanceRunner {
|
|
105
105
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
106
106
|
}
|
107
107
|
|
108
|
-
let
|
108
|
+
let processInfo: ProcessInfo;
|
109
109
|
|
110
110
|
if (providerVersion.definition.kind === KIND_BLOCK_TYPE_OPERATOR) {
|
111
|
-
|
111
|
+
processInfo = await this._startOperatorProcess(blockInstance, blockUri, providerVersion, env);
|
112
112
|
} else {
|
113
113
|
//We need a port type to know how to connect to the block consistently
|
114
114
|
const portTypes = getProviderPorts(assetVersion);
|
115
115
|
|
116
116
|
if (blockUri.version === 'local') {
|
117
|
-
|
117
|
+
processInfo = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
|
118
118
|
} else {
|
119
|
-
|
119
|
+
processInfo = await this._startDockerProcess(blockInstance, blockUri, env);
|
120
120
|
}
|
121
121
|
|
122
122
|
if (portTypes.length > 0) {
|
123
|
-
|
123
|
+
processInfo.portType = portTypes[0];
|
124
124
|
}
|
125
125
|
}
|
126
126
|
|
127
|
-
return
|
128
|
-
name: blockUri.id,
|
129
|
-
...blockInstance,
|
130
|
-
...processDetails,
|
131
|
-
};
|
127
|
+
return processInfo;
|
132
128
|
}
|
133
129
|
|
134
130
|
/**
|
@@ -139,7 +135,7 @@ export class BlockInstanceRunner {
|
|
139
135
|
blockInfo: KapetaURI,
|
140
136
|
env: StringMap,
|
141
137
|
assetVersion: DefinitionInfo
|
142
|
-
): Promise<
|
138
|
+
): Promise<ProcessInfo> {
|
143
139
|
const baseDir = ClusterConfig.getRepositoryAssetPath(blockInfo.handle, blockInfo.name, blockInfo.version);
|
144
140
|
|
145
141
|
if (!FS.existsSync(baseDir)) {
|
@@ -172,14 +168,16 @@ export class BlockInstanceRunner {
|
|
172
168
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
173
169
|
}
|
174
170
|
|
175
|
-
const containerName =
|
171
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
176
172
|
const logs = new LogData();
|
177
173
|
logs.addLog(`Starting block ${blockInstance.ref}`);
|
178
|
-
|
174
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
175
|
+
let container = containerInfo?.native;
|
176
|
+
|
179
177
|
console.log('Starting dev container', containerName);
|
180
178
|
|
181
179
|
if (container) {
|
182
|
-
console.log(`
|
180
|
+
console.log(`Dev container already exists. Deleting...`);
|
183
181
|
try {
|
184
182
|
await container.delete({
|
185
183
|
force: true,
|
@@ -187,7 +185,7 @@ export class BlockInstanceRunner {
|
|
187
185
|
} catch (e: any) {
|
188
186
|
throw new Error('Failed to delete existing container: ' + e.message);
|
189
187
|
}
|
190
|
-
container =
|
188
|
+
container = undefined;
|
191
189
|
}
|
192
190
|
|
193
191
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
@@ -216,7 +214,7 @@ export class BlockInstanceRunner {
|
|
216
214
|
|
217
215
|
PortBindings[dockerPort] = [
|
218
216
|
{
|
219
|
-
HostIp: bindHost,
|
217
|
+
HostIp: bindHost,
|
220
218
|
HostPort: `${publicPort}`,
|
221
219
|
},
|
222
220
|
];
|
@@ -229,6 +227,7 @@ export class BlockInstanceRunner {
|
|
229
227
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
230
228
|
}
|
231
229
|
|
230
|
+
console.log('Starting dev container', containerName, dockerImage);
|
232
231
|
container = await containerManager.startContainer({
|
233
232
|
Image: dockerImage,
|
234
233
|
name: containerName,
|
@@ -274,7 +273,7 @@ export class BlockInstanceRunner {
|
|
274
273
|
container: Container,
|
275
274
|
logs: LogData,
|
276
275
|
deleteOnExit: boolean = false
|
277
|
-
): Promise<
|
276
|
+
): Promise<ProcessInfo> {
|
278
277
|
let localContainer: Container | null = container;
|
279
278
|
const logStream = (await container.logs({
|
280
279
|
follow: true,
|
@@ -306,7 +305,7 @@ export class BlockInstanceRunner {
|
|
306
305
|
});
|
307
306
|
|
308
307
|
return {
|
309
|
-
type:
|
308
|
+
type: InstanceType.DOCKER,
|
310
309
|
pid: container.id,
|
311
310
|
output: outputEvents,
|
312
311
|
stop: async () => {
|
@@ -350,9 +349,10 @@ export class BlockInstanceRunner {
|
|
350
349
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
351
350
|
}
|
352
351
|
|
353
|
-
const containerName =
|
352
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
354
353
|
const logs = new LogData();
|
355
|
-
|
354
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
355
|
+
let container = containerInfo?.native;
|
356
356
|
|
357
357
|
// For windows we need to default to root
|
358
358
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
@@ -380,9 +380,7 @@ export class BlockInstanceRunner {
|
|
380
380
|
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
381
381
|
],
|
382
382
|
HostConfig: {
|
383
|
-
Binds: [
|
384
|
-
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
385
|
-
],
|
383
|
+
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
386
384
|
},
|
387
385
|
});
|
388
386
|
|
@@ -437,9 +435,11 @@ export class BlockInstanceRunner {
|
|
437
435
|
console.warn('Failed to pull image. Continuing...', e);
|
438
436
|
}
|
439
437
|
|
440
|
-
const containerName =
|
438
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
441
439
|
const logs = new LogData();
|
442
|
-
|
440
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
441
|
+
let container = containerInfo?.native;
|
442
|
+
|
443
443
|
if (container) {
|
444
444
|
const containerData = container.data as any;
|
445
445
|
if (containerData.State === 'running') {
|
@@ -450,7 +450,7 @@ export class BlockInstanceRunner {
|
|
450
450
|
try {
|
451
451
|
await container.delete();
|
452
452
|
} catch (e) {}
|
453
|
-
container =
|
453
|
+
container = undefined;
|
454
454
|
} else {
|
455
455
|
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
456
456
|
try {
|
@@ -460,7 +460,7 @@ export class BlockInstanceRunner {
|
|
460
460
|
try {
|
461
461
|
await container.delete();
|
462
462
|
} catch (e) {}
|
463
|
-
container =
|
463
|
+
container = undefined;
|
464
464
|
}
|
465
465
|
}
|
466
466
|
}
|