@kapeta/local-cluster-service 0.8.3 → 0.9.1
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/dist/cjs/src/assetManager.js +7 -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 +25 -2
- package/dist/cjs/src/containerManager.js +51 -16
- 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 +34 -32
- package/dist/cjs/src/utils/utils.d.ts +2 -0
- package/dist/cjs/src/utils/utils.js +17 -1
- package/dist/esm/src/assetManager.js +7 -4
- 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 +25 -2
- package/dist/esm/src/containerManager.js +50 -15
- 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 +35 -33
- package/dist/esm/src/utils/utils.d.ts +2 -0
- package/dist/esm/src/utils/utils.js +14 -0
- package/package.json +2 -1
- package/src/assetManager.ts +7 -4
- 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 +72 -16
- package/src/definitionsManager.ts +54 -0
- package/src/filesystemManager.ts +0 -2
- 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 +7 -3
- package/src/serviceManager.ts +6 -0
- package/src/types.ts +44 -14
- package/src/utils/BlockInstanceRunner.ts +39 -36
- package/src/utils/utils.ts +18 -0
@@ -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,22 +127,24 @@ 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
|
-
let
|
133
|
+
let containerInfo = await containerManager.getContainerByName(containerName);
|
134
|
+
let container = containerInfo?.native;
|
137
135
|
console.log('Starting dev container', containerName);
|
138
|
-
if (
|
139
|
-
console.log(`
|
136
|
+
if (containerInfo) {
|
137
|
+
console.log(`Dev container already exists. Deleting...`);
|
140
138
|
try {
|
141
|
-
await
|
139
|
+
await containerInfo.remove({
|
142
140
|
force: true,
|
143
141
|
});
|
144
142
|
}
|
145
143
|
catch (e) {
|
146
144
|
throw new Error('Failed to delete existing container: ' + e.message);
|
147
145
|
}
|
148
|
-
container =
|
146
|
+
container = undefined;
|
147
|
+
containerInfo = undefined;
|
149
148
|
}
|
150
149
|
logs.addLog(`Creating new container for block: ${containerName}`);
|
151
150
|
console.log('Creating new dev container', containerName, dockerImage);
|
@@ -178,6 +177,7 @@ export class BlockInstanceRunner {
|
|
178
177
|
if (localContainer.healthcheck) {
|
179
178
|
HealthCheck = containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
180
179
|
}
|
180
|
+
console.log('Starting dev container', containerName, dockerImage);
|
181
181
|
container = await containerManager.startContainer({
|
182
182
|
Image: dockerImage,
|
183
183
|
name: containerName,
|
@@ -240,14 +240,14 @@ export class BlockInstanceRunner {
|
|
240
240
|
const data = status.data;
|
241
241
|
if (deleteOnExit) {
|
242
242
|
try {
|
243
|
-
await
|
243
|
+
await containerManager.remove(container);
|
244
244
|
}
|
245
245
|
catch (e) { }
|
246
246
|
}
|
247
247
|
outputEvents.emit('exit', data?.State?.ExitCode ?? 0);
|
248
248
|
});
|
249
249
|
return {
|
250
|
-
type:
|
250
|
+
type: InstanceType.DOCKER,
|
251
251
|
pid: container.id,
|
252
252
|
output: outputEvents,
|
253
253
|
stop: async () => {
|
@@ -257,7 +257,7 @@ export class BlockInstanceRunner {
|
|
257
257
|
try {
|
258
258
|
await localContainer.stop();
|
259
259
|
if (deleteOnExit) {
|
260
|
-
await
|
260
|
+
await containerManager.remove(localContainer);
|
261
261
|
}
|
262
262
|
}
|
263
263
|
catch (e) { }
|
@@ -282,9 +282,10 @@ export class BlockInstanceRunner {
|
|
282
282
|
if (!dockerImage) {
|
283
283
|
throw new Error(`Missing docker image information: ${JSON.stringify(versionInfo?.artifact?.details)}`);
|
284
284
|
}
|
285
|
-
const containerName =
|
285
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
286
286
|
const logs = new LogData();
|
287
|
-
|
287
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
288
|
+
let container = containerInfo?.native;
|
288
289
|
// For windows we need to default to root
|
289
290
|
const innerHome = process.platform === 'win32' ? '/root/.kapeta' : ClusterConfig.getKapetaBasedir();
|
290
291
|
if (container) {
|
@@ -350,9 +351,10 @@ export class BlockInstanceRunner {
|
|
350
351
|
catch (e) {
|
351
352
|
console.warn('Failed to pull image. Continuing...', e);
|
352
353
|
}
|
353
|
-
const containerName =
|
354
|
+
const containerName = getBlockInstanceContainerName(blockInstance.id);
|
354
355
|
const logs = new LogData();
|
355
|
-
|
356
|
+
const containerInfo = await containerManager.getContainerByName(containerName);
|
357
|
+
let container = containerInfo?.native;
|
356
358
|
if (container) {
|
357
359
|
const containerData = container.data;
|
358
360
|
if (containerData.State === 'running') {
|
@@ -362,10 +364,10 @@ export class BlockInstanceRunner {
|
|
362
364
|
if (containerData.State?.ExitCode > 0) {
|
363
365
|
logs.addLog(`Container exited with code: ${containerData.State.ExitCode}. Deleting...`);
|
364
366
|
try {
|
365
|
-
await
|
367
|
+
await containerManager.remove(container);
|
366
368
|
}
|
367
369
|
catch (e) { }
|
368
|
-
container =
|
370
|
+
container = undefined;
|
369
371
|
}
|
370
372
|
else {
|
371
373
|
logs.addLog(`Found existing container for block: ${containerName}. Starting now`);
|
@@ -375,10 +377,10 @@ export class BlockInstanceRunner {
|
|
375
377
|
catch (e) {
|
376
378
|
console.warn('Failed to start container. Deleting...', e);
|
377
379
|
try {
|
378
|
-
await
|
380
|
+
await containerManager.remove(container);
|
379
381
|
}
|
380
382
|
catch (e) { }
|
381
|
-
container =
|
383
|
+
container = undefined;
|
382
384
|
}
|
383
385
|
}
|
384
386
|
}
|
@@ -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 {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@kapeta/local-cluster-service",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.9.1",
|
4
4
|
"description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
|
5
5
|
"type": "commonjs",
|
6
6
|
"exports": {
|
@@ -67,6 +67,7 @@
|
|
67
67
|
"yaml": "^1.6.0"
|
68
68
|
},
|
69
69
|
"devDependencies": {
|
70
|
+
"@kapeta/eslint-config": "^0.6.1",
|
70
71
|
"@kapeta/prettier-config": "^0.6.0",
|
71
72
|
"@tsconfig/node18": "^18.2.0",
|
72
73
|
"@types/express": "^4.17.17",
|