@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
@@ -4,6 +4,7 @@ import { serviceManager } from '../serviceManager';
|
|
4
4
|
import { corsHandler } from '../middleware/cors';
|
5
5
|
import { kapetaHeaders } from '../middleware/kapeta';
|
6
6
|
import { stringBody } from '../middleware/stringBody';
|
7
|
+
import { DesiredInstanceStatus, InstanceOwner, InstanceType } from '../types';
|
7
8
|
const router = Router();
|
8
9
|
router.use('/', corsHandler);
|
9
10
|
router.use('/', kapetaHeaders);
|
@@ -23,10 +24,10 @@ router.get('/:systemId/instances', (req, res) => {
|
|
23
24
|
* Start all instances in a plan
|
24
25
|
*/
|
25
26
|
router.post('/:systemId/start', async (req, res) => {
|
26
|
-
const
|
27
|
+
const instances = await instanceManager.startAllForPlan(req.params.systemId);
|
27
28
|
res.status(202).send({
|
28
29
|
ok: true,
|
29
|
-
processes:
|
30
|
+
processes: instances.map((p) => {
|
30
31
|
return { pid: p.pid, type: p.type };
|
31
32
|
}),
|
32
33
|
});
|
@@ -44,7 +45,7 @@ router.post('/:systemId/stop', async (req, res) => {
|
|
44
45
|
* Start single instance in a plan
|
45
46
|
*/
|
46
47
|
router.post('/:systemId/:instanceId/start', async (req, res) => {
|
47
|
-
const process = await instanceManager.
|
48
|
+
const process = await instanceManager.start(req.params.systemId, req.params.instanceId);
|
48
49
|
res.status(202).send({
|
49
50
|
ok: true,
|
50
51
|
pid: process.pid,
|
@@ -55,20 +56,20 @@ router.post('/:systemId/:instanceId/start', async (req, res) => {
|
|
55
56
|
* Stop single instance in a plan
|
56
57
|
*/
|
57
58
|
router.post('/:systemId/:instanceId/stop', async (req, res) => {
|
58
|
-
await instanceManager.
|
59
|
+
await instanceManager.stop(req.params.systemId, req.params.instanceId);
|
59
60
|
res.status(202).send({ ok: true });
|
60
61
|
});
|
61
62
|
/**
|
62
63
|
* Get logs for instance in a plan
|
63
64
|
*/
|
64
65
|
router.get('/:systemId/:instanceId/logs', (req, res) => {
|
65
|
-
const
|
66
|
-
if (!
|
66
|
+
const instanceInfo = instanceManager.getInstance(req.params.systemId, req.params.instanceId);
|
67
|
+
if (!instanceInfo) {
|
67
68
|
res.status(404).send({ ok: false });
|
68
69
|
return;
|
69
70
|
}
|
70
71
|
res.status(202).send({
|
71
|
-
logs:
|
72
|
+
logs: instanceInfo.internal?.logs() ?? [],
|
72
73
|
});
|
73
74
|
});
|
74
75
|
/**
|
@@ -101,7 +102,7 @@ router.use('/', (req, res, next) => {
|
|
101
102
|
next();
|
102
103
|
});
|
103
104
|
/**
|
104
|
-
* Updates the full configuration for a given
|
105
|
+
* Updates the full configuration for a given instance.
|
105
106
|
*/
|
106
107
|
router.put('/', async (req, res) => {
|
107
108
|
let instance = req.stringBody ? JSON.parse(req.stringBody) : null;
|
@@ -111,19 +112,27 @@ router.put('/', async (req, res) => {
|
|
111
112
|
if (oldInstance) {
|
112
113
|
instance.pid = oldInstance.pid;
|
113
114
|
}
|
114
|
-
instance.type =
|
115
|
+
instance.type = InstanceType.DOCKER;
|
115
116
|
}
|
116
|
-
else
|
117
|
-
instance
|
117
|
+
else {
|
118
|
+
// Coming from user starting the instance outside of kapeta
|
119
|
+
instance.type = InstanceType.LOCAL;
|
120
|
+
instance.owner = InstanceOwner.EXTERNAL;
|
121
|
+
instance.desiredStatus = DesiredInstanceStatus.EXTERNAL;
|
122
|
+
}
|
123
|
+
try {
|
124
|
+
await instanceManager.registerInstanceFromSDK(req.kapeta.systemId, req.kapeta.instanceId, instance);
|
125
|
+
res.status(202).send({ ok: true });
|
126
|
+
}
|
127
|
+
catch (e) {
|
128
|
+
res.status(400).send({ error: e.message });
|
118
129
|
}
|
119
|
-
await instanceManager.registerInstance(req.kapeta.systemId, req.kapeta.instanceId, instance);
|
120
|
-
res.status(202).send({ ok: true });
|
121
130
|
});
|
122
131
|
/**
|
123
132
|
* Delete instance
|
124
133
|
*/
|
125
134
|
router.delete('/', async (req, res) => {
|
126
|
-
await instanceManager.
|
135
|
+
await instanceManager.markAsStopped(req.kapeta.systemId, req.kapeta.instanceId);
|
127
136
|
res.status(202).send({ ok: true });
|
128
137
|
});
|
129
138
|
export default router;
|
@@ -1,8 +1,15 @@
|
|
1
|
+
import { normalizeKapetaUri } from '../utils/utils';
|
1
2
|
export function kapetaHeaders(req, res, next) {
|
2
3
|
let blockRef = req.headers['x-kapeta-block'];
|
3
4
|
let systemId = req.headers['x-kapeta-system'];
|
4
5
|
let instanceId = req.headers['x-kapeta-instance'];
|
5
6
|
let environment = req.headers['x-kapeta-environment'];
|
7
|
+
if (blockRef) {
|
8
|
+
blockRef = normalizeKapetaUri(blockRef);
|
9
|
+
}
|
10
|
+
if (systemId) {
|
11
|
+
systemId = normalizeKapetaUri(systemId);
|
12
|
+
}
|
6
13
|
req.kapeta = {
|
7
14
|
blockRef,
|
8
15
|
instanceId,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import uuid from 'node-uuid';
|
2
|
+
import { normalizeKapetaUri } from './utils/utils';
|
2
3
|
class NetworkManager {
|
3
4
|
_connections;
|
4
5
|
_sources;
|
@@ -17,6 +18,7 @@ class NetworkManager {
|
|
17
18
|
this._targets = {};
|
18
19
|
}
|
19
20
|
_ensureSystem(systemId) {
|
21
|
+
systemId = normalizeKapetaUri(systemId);
|
20
22
|
if (!this._connections[systemId]) {
|
21
23
|
this._connections[systemId] = {};
|
22
24
|
}
|
@@ -28,6 +30,7 @@ class NetworkManager {
|
|
28
30
|
}
|
29
31
|
}
|
30
32
|
_ensureConnection(systemId, connectionId) {
|
33
|
+
systemId = normalizeKapetaUri(systemId);
|
31
34
|
this._ensureSystem(systemId);
|
32
35
|
if (!this._connections[systemId][connectionId]) {
|
33
36
|
this._connections[systemId][connectionId] = [];
|
@@ -35,6 +38,7 @@ class NetworkManager {
|
|
35
38
|
return this._connections[systemId][connectionId];
|
36
39
|
}
|
37
40
|
_ensureSource(systemId, sourceBlockInstanceId) {
|
41
|
+
systemId = normalizeKapetaUri(systemId);
|
38
42
|
this._ensureSystem(systemId);
|
39
43
|
if (!this._sources[systemId][sourceBlockInstanceId]) {
|
40
44
|
this._sources[systemId][sourceBlockInstanceId] = [];
|
@@ -42,6 +46,7 @@ class NetworkManager {
|
|
42
46
|
return this._sources[systemId][sourceBlockInstanceId];
|
43
47
|
}
|
44
48
|
_ensureTarget(systemId, targetBlockInstanceId) {
|
49
|
+
systemId = normalizeKapetaUri(systemId);
|
45
50
|
this._ensureSystem(systemId);
|
46
51
|
if (!this._targets[systemId][targetBlockInstanceId]) {
|
47
52
|
this._targets[systemId][targetBlockInstanceId] = [];
|
@@ -49,6 +54,7 @@ class NetworkManager {
|
|
49
54
|
return this._targets[systemId][targetBlockInstanceId];
|
50
55
|
}
|
51
56
|
addRequest(systemId, connection, request, consumerMethodId, providerMethodId) {
|
57
|
+
systemId = normalizeKapetaUri(systemId);
|
52
58
|
const traffic = new Traffic(connection, request, consumerMethodId, providerMethodId);
|
53
59
|
this._ensureConnection(systemId, traffic.connectionId).push(traffic);
|
54
60
|
this._ensureSource(systemId, connection.provider.blockId).push(traffic);
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
2
1
|
import Path from 'path';
|
3
2
|
import md5 from 'md5';
|
4
3
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
@@ -6,6 +5,8 @@ import { serviceManager } from './serviceManager';
|
|
6
5
|
import { storageService } from './storageService';
|
7
6
|
import { containerManager } from './containerManager';
|
8
7
|
import FSExtra from 'fs-extra';
|
8
|
+
import { definitionsManager } from './definitionsManager';
|
9
|
+
import { normalizeKapetaUri } from './utils/utils';
|
9
10
|
const KIND_OPERATOR = 'core/resource-type-operator';
|
10
11
|
class Operator {
|
11
12
|
_data;
|
@@ -36,7 +37,7 @@ class OperatorManager {
|
|
36
37
|
* @return {Operator}
|
37
38
|
*/
|
38
39
|
getOperator(resourceType, version) {
|
39
|
-
const operators =
|
40
|
+
const operators = definitionsManager.getDefinitions(KIND_OPERATOR);
|
40
41
|
const operator = operators.find((operator) => operator.definition &&
|
41
42
|
operator.definition.metadata &&
|
42
43
|
operator.definition.metadata.name &&
|
@@ -54,7 +55,8 @@ class OperatorManager {
|
|
54
55
|
* Get information about a specific consumed resource
|
55
56
|
*/
|
56
57
|
async getConsumerResourceInfo(systemId, fromServiceId, resourceType, portType, name, environment) {
|
57
|
-
|
58
|
+
systemId = normalizeKapetaUri(systemId);
|
59
|
+
const plans = definitionsManager.getDefinitions('core/plan');
|
58
60
|
const planUri = parseKapetaUri(systemId);
|
59
61
|
const currentPlan = plans.find((plan) => plan.definition.metadata.name === planUri.fullName && plan.version === planUri.version);
|
60
62
|
if (!currentPlan) {
|
@@ -65,7 +67,9 @@ class OperatorManager {
|
|
65
67
|
throw new Error(`Unknown instance: ${fromServiceId} in plan ${systemId}`);
|
66
68
|
}
|
67
69
|
const blockUri = parseKapetaUri(currentInstance.block.ref);
|
68
|
-
const blockDefinition =
|
70
|
+
const blockDefinition = definitionsManager
|
71
|
+
.getDefinitions()
|
72
|
+
.find((definition) => definition.version === blockUri.version && definition.definition.metadata.name === blockUri.fullName);
|
69
73
|
if (!blockDefinition) {
|
70
74
|
throw new Error(`Unknown block: ${currentInstance.block.ref} in plan ${systemId}`);
|
71
75
|
}
|
@@ -1,14 +1,14 @@
|
|
1
1
|
import Path from 'path';
|
2
2
|
import FSExtra from 'fs-extra';
|
3
3
|
import { repositoryManager } from './repositoryManager';
|
4
|
-
import
|
4
|
+
import { definitionsManager } from './definitionsManager';
|
5
5
|
class ProviderManager {
|
6
6
|
_webAssetCache;
|
7
7
|
constructor() {
|
8
8
|
this._webAssetCache = {};
|
9
9
|
}
|
10
10
|
getWebProviders() {
|
11
|
-
return
|
11
|
+
return definitionsManager.getProviderDefinitions().filter((providerDefinition) => providerDefinition.hasWeb);
|
12
12
|
}
|
13
13
|
async getAsset(handle, name, version, sourceMap = false) {
|
14
14
|
const fullName = `${handle}/${name}`;
|
@@ -31,7 +31,7 @@ class ProviderManager {
|
|
31
31
|
return null;
|
32
32
|
}
|
33
33
|
}
|
34
|
-
const providerDefinitions =
|
34
|
+
const providerDefinitions = definitionsManager.getProviderDefinitions();
|
35
35
|
if (providerDefinitions.length > 0) {
|
36
36
|
console.log('## Loaded the following providers ##');
|
37
37
|
providerDefinitions.forEach((providerDefinition) => {
|
@@ -8,6 +8,7 @@ import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
|
8
8
|
import { socketManager } from './socketManager';
|
9
9
|
import { progressListener } from './progressListener';
|
10
10
|
import { Actions, Config, RegistryService } from '@kapeta/nodejs-registry-utils';
|
11
|
+
import { definitionsManager } from './definitionsManager';
|
11
12
|
const INSTALL_ATTEMPTED = {};
|
12
13
|
class RepositoryManager {
|
13
14
|
changeEventsEnabled;
|
@@ -83,6 +84,7 @@ class RepositoryManager {
|
|
83
84
|
};
|
84
85
|
allDefinitions = newDefinitions;
|
85
86
|
socketManager.emit(`assets`, 'changed', payload);
|
87
|
+
definitionsManager.clearCache();
|
86
88
|
});
|
87
89
|
}
|
88
90
|
catch (e) {
|
@@ -173,7 +175,7 @@ class RepositoryManager {
|
|
173
175
|
//TODO: Get dependencies for local asset
|
174
176
|
return;
|
175
177
|
}
|
176
|
-
const definitions =
|
178
|
+
const definitions = definitionsManager.getDefinitions();
|
177
179
|
const installedAsset = definitions.find((d) => d.definition.metadata.name === fullName && d.version === version);
|
178
180
|
if (installedAsset && this._cache[ref] === true) {
|
179
181
|
return;
|
@@ -204,8 +206,10 @@ class RepositoryManager {
|
|
204
206
|
else {
|
205
207
|
//Ensure dependencies are installed
|
206
208
|
const refs = assetVersion.dependencies.map((dep) => dep.name);
|
207
|
-
|
208
|
-
|
209
|
+
if (refs.length > 0) {
|
210
|
+
console.log(`Auto-installing dependencies: ${refs.join(', ')}`);
|
211
|
+
await this._install(refs);
|
212
|
+
}
|
209
213
|
}
|
210
214
|
}
|
211
215
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import _ from 'lodash';
|
2
2
|
import { clusterService } from './clusterService';
|
3
3
|
import { storageService } from './storageService';
|
4
|
+
import { normalizeKapetaUri } from './utils/utils';
|
4
5
|
const DEFAULT_PORT_TYPE = 'rest';
|
5
6
|
class ServiceManager {
|
6
7
|
_systems;
|
@@ -35,6 +36,7 @@ class ServiceManager {
|
|
35
36
|
return `http://${host}:${port}/${path}`;
|
36
37
|
}
|
37
38
|
_ensureSystem(systemId) {
|
39
|
+
systemId = normalizeKapetaUri(systemId);
|
38
40
|
if (!this._systems[systemId]) {
|
39
41
|
this._systems[systemId] = {};
|
40
42
|
}
|
@@ -48,6 +50,7 @@ class ServiceManager {
|
|
48
50
|
return system[serviceId];
|
49
51
|
}
|
50
52
|
async ensureServicePort(systemId, blockInstanceId, portType = DEFAULT_PORT_TYPE) {
|
53
|
+
systemId = normalizeKapetaUri(systemId);
|
51
54
|
if (!portType) {
|
52
55
|
portType = DEFAULT_PORT_TYPE;
|
53
56
|
}
|
@@ -70,6 +73,7 @@ class ServiceManager {
|
|
70
73
|
*
|
71
74
|
*/
|
72
75
|
getConsumerAddress(systemId, consumerInstanceId, consumerResourceName, portType, environmentType) {
|
76
|
+
systemId = normalizeKapetaUri(systemId);
|
73
77
|
const port = clusterService.getClusterServicePort();
|
74
78
|
const path = clusterService.getProxyPath(systemId, consumerInstanceId, consumerResourceName, portType);
|
75
79
|
return this._forLocal(port, path, environmentType);
|
@@ -83,6 +87,7 @@ class ServiceManager {
|
|
83
87
|
*
|
84
88
|
*/
|
85
89
|
async getProviderAddress(systemId, providerInstanceId, portType) {
|
90
|
+
systemId = normalizeKapetaUri(systemId);
|
86
91
|
const port = await this.ensureServicePort(systemId, providerInstanceId, portType);
|
87
92
|
return this._forLocal(port);
|
88
93
|
}
|
package/dist/esm/src/types.d.ts
CHANGED
@@ -24,29 +24,55 @@ export interface BlockProcessParams {
|
|
24
24
|
ref: string;
|
25
25
|
configuration?: AnyMap;
|
26
26
|
}
|
27
|
-
export
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
export declare enum InstanceType {
|
28
|
+
DOCKER = "docker",
|
29
|
+
LOCAL = "local",
|
30
|
+
UNKNOWN = "unknown"
|
31
|
+
}
|
32
|
+
export declare enum InstanceOwner {
|
33
|
+
INTERNAL = "internal",
|
34
|
+
EXTERNAL = "external"
|
35
|
+
}
|
36
|
+
export declare enum InstanceStatus {
|
37
|
+
STOPPED = "stopped",
|
38
|
+
STARTING = "starting",
|
39
|
+
BUSY = "busy",
|
40
|
+
READY = "ready",
|
41
|
+
STOPPING = "stopping",
|
42
|
+
UNHEALTHY = "unhealthy",
|
43
|
+
FAILED = "failed"
|
44
|
+
}
|
45
|
+
export declare enum DesiredInstanceStatus {
|
46
|
+
STOP = "stop",
|
47
|
+
RUN = "run",
|
48
|
+
EXTERNAL = "external"
|
49
|
+
}
|
50
|
+
export type ProcessInfo = {
|
51
|
+
type: InstanceType;
|
52
|
+
pid?: number | string | null;
|
32
53
|
output: EventEmitter;
|
54
|
+
portType?: string;
|
33
55
|
logs: () => LogEntry[];
|
34
56
|
stop: () => Promise<void> | void;
|
35
|
-
}
|
36
|
-
export interface ProcessInfo extends ProcessDetails {
|
37
|
-
id: string;
|
38
|
-
ref: string;
|
39
|
-
name: string;
|
40
|
-
}
|
57
|
+
};
|
41
58
|
export type InstanceInfo = {
|
42
59
|
systemId: string;
|
43
60
|
instanceId: string;
|
61
|
+
ref: string;
|
62
|
+
name: string;
|
63
|
+
type: InstanceType;
|
64
|
+
owner: InstanceOwner;
|
65
|
+
status: InstanceStatus;
|
66
|
+
desiredStatus: DesiredInstanceStatus;
|
44
67
|
address?: string;
|
68
|
+
startedAt?: number;
|
45
69
|
health?: string | null;
|
46
|
-
status: string;
|
47
70
|
pid?: number | string | null;
|
48
|
-
type: ProcessType;
|
49
71
|
portType?: string;
|
72
|
+
internal?: {
|
73
|
+
output: EventEmitter;
|
74
|
+
logs: () => LogEntry[];
|
75
|
+
};
|
50
76
|
};
|
51
77
|
interface ResourceRef {
|
52
78
|
blockId: string;
|
package/dist/esm/src/types.js
CHANGED
@@ -1 +1,27 @@
|
|
1
|
-
export
|
1
|
+
export var InstanceType;
|
2
|
+
(function (InstanceType) {
|
3
|
+
InstanceType["DOCKER"] = "docker";
|
4
|
+
InstanceType["LOCAL"] = "local";
|
5
|
+
InstanceType["UNKNOWN"] = "unknown";
|
6
|
+
})(InstanceType || (InstanceType = {}));
|
7
|
+
export var InstanceOwner;
|
8
|
+
(function (InstanceOwner) {
|
9
|
+
InstanceOwner["INTERNAL"] = "internal";
|
10
|
+
InstanceOwner["EXTERNAL"] = "external";
|
11
|
+
})(InstanceOwner || (InstanceOwner = {}));
|
12
|
+
export var InstanceStatus;
|
13
|
+
(function (InstanceStatus) {
|
14
|
+
InstanceStatus["STOPPED"] = "stopped";
|
15
|
+
InstanceStatus["STARTING"] = "starting";
|
16
|
+
InstanceStatus["BUSY"] = "busy";
|
17
|
+
InstanceStatus["READY"] = "ready";
|
18
|
+
InstanceStatus["STOPPING"] = "stopping";
|
19
|
+
InstanceStatus["UNHEALTHY"] = "unhealthy";
|
20
|
+
InstanceStatus["FAILED"] = "failed";
|
21
|
+
})(InstanceStatus || (InstanceStatus = {}));
|
22
|
+
export var DesiredInstanceStatus;
|
23
|
+
(function (DesiredInstanceStatus) {
|
24
|
+
DesiredInstanceStatus["STOP"] = "stop";
|
25
|
+
DesiredInstanceStatus["RUN"] = "run";
|
26
|
+
DesiredInstanceStatus["EXTERNAL"] = "external";
|
27
|
+
})(DesiredInstanceStatus || (DesiredInstanceStatus = {}));
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { DefinitionInfo } from '@kapeta/local-cluster-config';
|
2
2
|
import { KapetaURI } from '@kapeta/nodejs-utils';
|
3
|
-
import { AnyMap, BlockProcessParams,
|
3
|
+
import { AnyMap, BlockProcessParams, ProcessInfo, StringMap } from '../types';
|
4
4
|
export declare class BlockInstanceRunner {
|
5
5
|
private readonly _systemId;
|
6
|
-
constructor(
|
6
|
+
constructor(systemId: string);
|
7
7
|
/**
|
8
8
|
* Start a block
|
9
9
|
*
|
@@ -25,5 +25,5 @@ export declare class BlockInstanceRunner {
|
|
25
25
|
* @return {Promise<ProcessDetails>}
|
26
26
|
* @private
|
27
27
|
*/
|
28
|
-
_startOperatorProcess(blockInstance: BlockProcessParams, blockUri: KapetaURI, providerDefinition: DefinitionInfo, env: StringMap): Promise<
|
28
|
+
_startOperatorProcess(blockInstance: BlockProcessParams, blockUri: KapetaURI, providerDefinition: DefinitionInfo, env: StringMap): Promise<ProcessInfo>;
|
29
29
|
}
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import FS from 'node:fs';
|
2
2
|
import ClusterConfig from '@kapeta/local-cluster-config';
|
3
|
-
import { getBindHost, readYML } from './utils';
|
3
|
+
import { getBindHost, getBlockInstanceContainerName, normalizeKapetaUri, readYML } from './utils';
|
4
4
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
5
5
|
import { serviceManager } from '../serviceManager';
|
6
6
|
import { containerManager, 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';
|
10
|
+
import { InstanceType } from '../types';
|
11
|
+
import { definitionsManager } from '../definitionsManager';
|
11
12
|
const KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
12
13
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
13
14
|
const KAPETA_BLOCK_REF = 'KAPETA_BLOCK_REF';
|
@@ -22,7 +23,7 @@ const DOCKER_ENV_VARS = [
|
|
22
23
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
23
24
|
];
|
24
25
|
function getProvider(uri) {
|
25
|
-
return
|
26
|
+
return definitionsManager.getProviderDefinitions().find((provider) => {
|
26
27
|
const ref = `${provider.definition.metadata.name}:${provider.version}`;
|
27
28
|
return parseKapetaUri(ref).id === uri.id;
|
28
29
|
});
|
@@ -36,13 +37,13 @@ function getProviderPorts(assetVersion) {
|
|
36
37
|
}
|
37
38
|
export class BlockInstanceRunner {
|
38
39
|
_systemId;
|
39
|
-
constructor(
|
40
|
+
constructor(systemId) {
|
40
41
|
/**
|
41
42
|
*
|
42
43
|
* @type {string}
|
43
44
|
* @private
|
44
45
|
*/
|
45
|
-
this._systemId =
|
46
|
+
this._systemId = normalizeKapetaUri(systemId);
|
46
47
|
}
|
47
48
|
/**
|
48
49
|
* Start a block
|
@@ -70,7 +71,7 @@ export class BlockInstanceRunner {
|
|
70
71
|
if (!blockUri.version) {
|
71
72
|
blockUri.version = 'local';
|
72
73
|
}
|
73
|
-
const assetVersion =
|
74
|
+
const assetVersion = definitionsManager.getDefinitions().find((definitions) => {
|
74
75
|
const ref = `${definitions.definition.metadata.name}:${definitions.version}`;
|
75
76
|
return parseKapetaUri(ref).id === blockUri.id;
|
76
77
|
});
|
@@ -82,28 +83,24 @@ export class BlockInstanceRunner {
|
|
82
83
|
if (!providerVersion) {
|
83
84
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
84
85
|
}
|
85
|
-
let
|
86
|
+
let processInfo;
|
86
87
|
if (providerVersion.definition.kind === KIND_BLOCK_TYPE_OPERATOR) {
|
87
|
-
|
88
|
+
processInfo = await this._startOperatorProcess(blockInstance, blockUri, providerVersion, env);
|
88
89
|
}
|
89
90
|
else {
|
90
91
|
//We need a port type to know how to connect to the block consistently
|
91
92
|
const portTypes = getProviderPorts(assetVersion);
|
92
93
|
if (blockUri.version === 'local') {
|
93
|
-
|
94
|
+
processInfo = await this._startLocalProcess(blockInstance, blockUri, env, assetVersion);
|
94
95
|
}
|
95
96
|
else {
|
96
|
-
|
97
|
+
processInfo = await this._startDockerProcess(blockInstance, blockUri, env);
|
97
98
|
}
|
98
99
|
if (portTypes.length > 0) {
|
99
|
-
|
100
|
+
processInfo.portType = portTypes[0];
|
100
101
|
}
|
101
102
|
}
|
102
|
-
return
|
103
|
-
name: blockUri.id,
|
104
|
-
...blockInstance,
|
105
|
-
...processDetails,
|
106
|
-
};
|
103
|
+
return processInfo;
|
107
104
|
}
|
108
105
|
/**
|
109
106
|
* Starts local process
|
@@ -130,13 +127,14 @@ export class BlockInstanceRunner {
|
|
130
127
|
if (!dockerImage) {
|
131
128
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
132
129
|
}
|
133
|
-
const containerName =
|
130
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
134
131
|
const logs = new LogData();
|
135
132
|
logs.addLog(`Starting block ${blockInstance.ref}`);
|
136
|
-
|
133
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
134
|
+
let container = containerInfo?.native;
|
137
135
|
console.log('Starting dev container', containerName);
|
138
136
|
if (container) {
|
139
|
-
console.log(`
|
137
|
+
console.log(`Dev container already exists. Deleting...`);
|
140
138
|
try {
|
141
139
|
await container.delete({
|
142
140
|
force: true,
|
@@ -145,7 +143,7 @@ export class BlockInstanceRunner {
|
|
145
143
|
catch (e) {
|
146
144
|
throw new Error('Failed to delete existing container: ' + e.message);
|
147
145
|
}
|
148
|
-
container =
|
146
|
+
container = undefined;
|
149
147
|
}
|
150
148
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
151
149
|
console.log('Creating new dev container', containerName, dockerImage);
|
@@ -178,6 +176,7 @@ export class BlockInstanceRunner {
|
|
178
176
|
if (localContainer.healthcheck) {
|
179
177
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
180
178
|
}
|
179
|
+
console.log('Starting dev container', containerName, dockerImage);
|
181
180
|
container = await containerManager.startContainer({
|
182
181
|
Image: dockerImage,
|
183
182
|
name: containerName,
|
@@ -247,7 +246,7 @@ export class BlockInstanceRunner {
|
|
247
246
|
outputEvents.emit('exit', data?.State?.ExitCode ?? 0);
|
248
247
|
});
|
249
248
|
return {
|
250
|
-
type:
|
249
|
+
type: InstanceType.DOCKER,
|
251
250
|
pid: container.id,
|
252
251
|
output: outputEvents,
|
253
252
|
stop: async () => {
|
@@ -282,9 +281,10 @@ export class BlockInstanceRunner {
|
|
282
281
|
if (!dockerImage) {
|
283
282
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
284
283
|
}
|
285
|
-
const containerName =
|
284
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
286
285
|
const logs = new LogData();
|
287
|
-
|
286
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
287
|
+
let container = containerInfo?.native;
|
288
288
|
// For windows we need to default to root
|
289
289
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
290
290
|
if (container) {
|
@@ -311,9 +311,7 @@ export class BlockInstanceRunner {
|
|
311
311
|
...Object.entries(env).map(([key, value]) => `${key}=${value}`),
|
312
312
|
],
|
313
313
|
HostConfig: {
|
314
|
-
Binds: [
|
315
|
-
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
|
316
|
-
],
|
314
|
+
Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
|
317
315
|
},
|
318
316
|
});
|
319
317
|
try {
|
@@ -352,9 +350,10 @@ export class BlockInstanceRunner {
|
|
352
350
|
catch (e) {
|
353
351
|
console.warn('Failed to pull image. Continuing...', e);
|
354
352
|
}
|
355
|
-
const containerName =
|
353
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
356
354
|
const logs = new LogData();
|
357
|
-
|
355
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
356
|
+
let container = containerInfo?.native;
|
358
357
|
if (container) {
|
359
358
|
const containerData = container.data;
|
360
359
|
if (containerData.State === 'running') {
|
@@ -367,7 +366,7 @@ export class BlockInstanceRunner {
|
|
367
366
|
await container.delete();
|
368
367
|
}
|
369
368
|
catch (e) { }
|
370
|
-
container =
|
369
|
+
container = undefined;
|
371
370
|
}
|
372
371
|
else {
|
373
372
|
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
@@ -380,7 +379,7 @@ export class BlockInstanceRunner {
|
|
380
379
|
await container.delete();
|
381
380
|
}
|
382
381
|
catch (e) { }
|
383
|
-
container =
|
382
|
+
container = undefined;
|
384
383
|
}
|
385
384
|
}
|
386
385
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
export declare function getBlockInstanceContainerName(instanceId: string): string;
|
2
|
+
export declare function normalizeKapetaUri(uri: string): string;
|
1
3
|
export declare function readYML(path: string): any;
|
2
4
|
export declare function isWindows(): boolean;
|
3
5
|
export declare function isMac(): boolean;
|
@@ -1,5 +1,19 @@
|
|
1
1
|
import FS from 'node:fs';
|
2
2
|
import YAML from 'yaml';
|
3
|
+
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
4
|
+
export function getBlockInstanceContainerName(instanceId) {
|
5
|
+
return `kapeta-block-instance-${instanceId}`;
|
6
|
+
}
|
7
|
+
export function normalizeKapetaUri(uri) {
|
8
|
+
if (!uri) {
|
9
|
+
return '';
|
10
|
+
}
|
11
|
+
const uriObj = parseKapetaUri(uri);
|
12
|
+
if (!uriObj.version) {
|
13
|
+
return `kapeta://${parseKapetaUri(uri).fullName}`;
|
14
|
+
}
|
15
|
+
return `kapeta://${parseKapetaUri(uri).id}`;
|
16
|
+
}
|
3
17
|
export function readYML(path) {
|
4
18
|
const rawYaml = FS.readFileSync(path);
|
5
19
|
try {
|
@@ -19,7 +33,7 @@ export function isLinux() {
|
|
19
33
|
return !isWindows() && !isMac();
|
20
34
|
}
|
21
35
|
export function getBindHost(preferredHost = '127.0.0.1') {
|
22
|
-
// On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
|
36
|
+
// On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
|
23
37
|
// TODO: This might pose a security risk - so we should authenticate all requests using a shared secret/nonce that we pass around.
|
24
38
|
return isLinux() ? '0.0.0.0' : preferredHost;
|
25
39
|
}
|