@kapeta/local-cluster-service 0.37.0 → 0.39.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/dist/cjs/index.js +4 -1
- package/dist/cjs/src/assetManager.d.ts +2 -1
- package/dist/cjs/src/assetManager.js +3 -2
- package/dist/cjs/src/config/routes.js +2 -2
- package/dist/cjs/src/containerManager.d.ts +6 -3
- package/dist/cjs/src/containerManager.js +101 -21
- package/dist/cjs/src/instanceManager.d.ts +4 -2
- package/dist/cjs/src/instanceManager.js +71 -32
- package/dist/cjs/src/operatorManager.d.ts +6 -3
- package/dist/cjs/src/operatorManager.js +32 -23
- package/dist/cjs/src/progressListener.d.ts +8 -1
- package/dist/cjs/src/progressListener.js +12 -1
- package/dist/cjs/src/repositoryManager.js +3 -2
- package/dist/cjs/src/serviceManager.d.ts +0 -1
- package/dist/cjs/src/serviceManager.js +2 -8
- package/dist/cjs/src/taskManager.d.ts +2 -0
- package/dist/cjs/src/taskManager.js +9 -0
- package/dist/cjs/src/types.d.ts +1 -48
- package/dist/cjs/src/types.js +2 -1
- package/dist/cjs/src/utils/BlockInstanceRunner.js +45 -33
- package/dist/cjs/src/utils/InternalConfigProvider.d.ts +38 -0
- package/dist/cjs/src/utils/InternalConfigProvider.js +146 -0
- package/dist/cjs/src/utils/commandLineUtils.d.ts +2 -1
- package/dist/cjs/src/utils/commandLineUtils.js +7 -1
- package/dist/cjs/src/utils/utils.d.ts +26 -4
- package/dist/cjs/src/utils/utils.js +48 -8
- package/dist/esm/index.js +4 -1
- package/dist/esm/src/assetManager.d.ts +2 -1
- package/dist/esm/src/assetManager.js +3 -2
- package/dist/esm/src/config/routes.js +2 -2
- package/dist/esm/src/containerManager.d.ts +6 -3
- package/dist/esm/src/containerManager.js +101 -21
- package/dist/esm/src/instanceManager.d.ts +4 -2
- package/dist/esm/src/instanceManager.js +71 -32
- package/dist/esm/src/operatorManager.d.ts +6 -3
- package/dist/esm/src/operatorManager.js +32 -23
- package/dist/esm/src/progressListener.d.ts +8 -1
- package/dist/esm/src/progressListener.js +12 -1
- package/dist/esm/src/repositoryManager.js +3 -2
- package/dist/esm/src/serviceManager.d.ts +0 -1
- package/dist/esm/src/serviceManager.js +2 -8
- package/dist/esm/src/taskManager.d.ts +2 -0
- package/dist/esm/src/taskManager.js +9 -0
- package/dist/esm/src/types.d.ts +1 -48
- package/dist/esm/src/types.js +2 -1
- package/dist/esm/src/utils/BlockInstanceRunner.js +45 -33
- package/dist/esm/src/utils/InternalConfigProvider.d.ts +38 -0
- package/dist/esm/src/utils/InternalConfigProvider.js +146 -0
- package/dist/esm/src/utils/commandLineUtils.d.ts +2 -1
- package/dist/esm/src/utils/commandLineUtils.js +7 -1
- package/dist/esm/src/utils/utils.d.ts +26 -4
- package/dist/esm/src/utils/utils.js +48 -8
- package/index.ts +5 -2
- package/package.json +16 -14
- package/src/assetManager.ts +5 -4
- package/src/config/routes.ts +4 -2
- package/src/containerManager.ts +115 -26
- package/src/instanceManager.ts +86 -44
- package/src/operatorManager.ts +48 -40
- package/src/progressListener.ts +15 -1
- package/src/repositoryManager.ts +5 -3
- package/src/serviceManager.ts +3 -11
- package/src/taskManager.ts +11 -0
- package/src/types.ts +2 -50
- package/src/utils/BlockInstanceRunner.ts +60 -44
- package/src/utils/InternalConfigProvider.ts +214 -0
- package/src/utils/commandLineUtils.ts +10 -2
- package/src/utils/utils.ts +53 -10
@@ -3,11 +3,13 @@
|
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
5
|
/// <reference types="node" />
|
6
|
+
import { LogEntry } from './types';
|
7
|
+
import { Task } from './taskManager';
|
6
8
|
export declare class ProgressListener {
|
7
9
|
private readonly systemId;
|
8
10
|
private readonly instanceId;
|
9
11
|
constructor(systemId?: string, instanceId?: string);
|
10
|
-
|
12
|
+
protected emitLog(payload: Omit<LogEntry, 'time' | 'source'>): void;
|
11
13
|
run(command: string, directory?: string): Promise<{
|
12
14
|
exit: number;
|
13
15
|
signal: NodeJS.Signals | null;
|
@@ -22,3 +24,8 @@ export declare class ProgressListener {
|
|
22
24
|
info(msg: string, ...args: any[]): void;
|
23
25
|
debug(msg: string, ...args: any[]): void;
|
24
26
|
}
|
27
|
+
export declare class TaskProgressListener extends ProgressListener {
|
28
|
+
private readonly task;
|
29
|
+
constructor(task: Task);
|
30
|
+
protected emitLog(payload: Omit<LogEntry, 'time' | 'source'>): void;
|
31
|
+
}
|
@@ -4,7 +4,7 @@
|
|
4
4
|
* SPDX-License-Identifier: BUSL-1.1
|
5
5
|
*/
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
-
exports.ProgressListener = void 0;
|
7
|
+
exports.TaskProgressListener = exports.ProgressListener = void 0;
|
8
8
|
const nodejs_process_1 = require("@kapeta/nodejs-process");
|
9
9
|
const socketManager_1 = require("./socketManager");
|
10
10
|
const node_util_1 = require("node:util");
|
@@ -120,3 +120,14 @@ class ProgressListener {
|
|
120
120
|
}
|
121
121
|
}
|
122
122
|
exports.ProgressListener = ProgressListener;
|
123
|
+
class TaskProgressListener extends ProgressListener {
|
124
|
+
task;
|
125
|
+
constructor(task) {
|
126
|
+
super();
|
127
|
+
this.task = task;
|
128
|
+
}
|
129
|
+
emitLog(payload) {
|
130
|
+
this.task.addLog(payload.message, payload.level);
|
131
|
+
}
|
132
|
+
}
|
133
|
+
exports.TaskProgressListener = TaskProgressListener;
|
@@ -164,16 +164,17 @@ class RepositoryManager extends node_events_1.EventEmitter {
|
|
164
164
|
async scheduleInstallation(refs) {
|
165
165
|
//We make sure to only install one asset at a time - otherwise unexpected things might happen
|
166
166
|
const createInstaller = (ref) => {
|
167
|
-
return async () => {
|
167
|
+
return async (task) => {
|
168
168
|
if (await definitionsManager_1.definitionsManager.exists(ref)) {
|
169
169
|
return;
|
170
170
|
}
|
171
|
+
const progressListener = new progressListener_1.TaskProgressListener(task);
|
171
172
|
//console.log(`Installing asset: ${ref}`);
|
172
173
|
//Auto-install missing asset
|
173
174
|
try {
|
174
175
|
//We change to a temp dir to avoid issues with the current working directory
|
175
176
|
process.chdir(node_os_1.default.tmpdir());
|
176
|
-
await nodejs_registry_utils_1.Actions.install(
|
177
|
+
await nodejs_registry_utils_1.Actions.install(progressListener, [ref], {});
|
177
178
|
}
|
178
179
|
catch (e) {
|
179
180
|
console.error(`Failed to install asset: ${ref}`, e);
|
@@ -9,7 +9,6 @@ export declare const HTTP_PORTS: string[];
|
|
9
9
|
declare class ServiceManager {
|
10
10
|
private _systems;
|
11
11
|
constructor();
|
12
|
-
getLocalHost(environmentType?: EnvironmentType): string;
|
13
12
|
_forLocal(port: string | number, path?: string, environmentType?: EnvironmentType): string;
|
14
13
|
_ensureSystem(systemId: string): any;
|
15
14
|
_ensureService(systemId: string, serviceId: string): any;
|
@@ -13,6 +13,7 @@ const clusterService_1 = require("./clusterService");
|
|
13
13
|
const storageService_1 = require("./storageService");
|
14
14
|
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
15
15
|
const BlockInstanceRunner_1 = require("./utils/BlockInstanceRunner");
|
16
|
+
const utils_1 = require("./utils/utils");
|
16
17
|
exports.HTTP_PORT_TYPE = 'http';
|
17
18
|
exports.DEFAULT_PORT_TYPE = exports.HTTP_PORT_TYPE;
|
18
19
|
exports.HTTP_PORTS = [exports.HTTP_PORT_TYPE, 'web', 'rest'];
|
@@ -31,18 +32,11 @@ class ServiceManager {
|
|
31
32
|
});
|
32
33
|
});
|
33
34
|
}
|
34
|
-
getLocalHost(environmentType) {
|
35
|
-
if (environmentType === 'docker') {
|
36
|
-
//We're inside a docker container, so we can use this special host name to access the host machine
|
37
|
-
return 'host.docker.internal';
|
38
|
-
}
|
39
|
-
return clusterService_1.clusterService.getClusterServiceHost();
|
40
|
-
}
|
41
35
|
_forLocal(port, path, environmentType) {
|
42
36
|
if (!path) {
|
43
37
|
path = '';
|
44
38
|
}
|
45
|
-
const hostname =
|
39
|
+
const hostname = (0, utils_1.getRemoteHostForEnvironment)(environmentType);
|
46
40
|
if (path.startsWith('/')) {
|
47
41
|
path = path.substring(1);
|
48
42
|
}
|
@@ -2,6 +2,7 @@
|
|
2
2
|
* Copyright 2023 Kapeta Inc.
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
|
+
import { LogLevel } from './types';
|
5
6
|
export type TaskRunner<T> = (task: Task<T>) => Promise<T>;
|
6
7
|
export declare enum TaskStatus {
|
7
8
|
PENDING = "PENDING",
|
@@ -44,6 +45,7 @@ export declare class Task<T = void> implements TaskData<T> {
|
|
44
45
|
set errorMessage(errorMessage: string | undefined);
|
45
46
|
set metadata(metadata: TaskMetadata);
|
46
47
|
emitUpdate(): void;
|
48
|
+
addLog(log: string, level?: LogLevel): void;
|
47
49
|
wait(): Promise<T>;
|
48
50
|
toData(): {
|
49
51
|
id: string;
|
@@ -12,6 +12,7 @@ const socketManager_1 = require("./socketManager");
|
|
12
12
|
const EVENT_TASK_UPDATED = 'task-updated';
|
13
13
|
const EVENT_TASK_ADDED = 'task-added';
|
14
14
|
const EVENT_TASK_REMOVED = 'task-removed';
|
15
|
+
const EVENT_TASK_LOG = 'task-log';
|
15
16
|
var TaskStatus;
|
16
17
|
(function (TaskStatus) {
|
17
18
|
TaskStatus["PENDING"] = "PENDING";
|
@@ -54,6 +55,14 @@ class Task {
|
|
54
55
|
emitUpdate() {
|
55
56
|
socketManager_1.socketManager.emitGlobal(EVENT_TASK_UPDATED, this.toData());
|
56
57
|
}
|
58
|
+
addLog(log, level = 'INFO') {
|
59
|
+
socketManager_1.socketManager.emitGlobal(EVENT_TASK_LOG, {
|
60
|
+
id: this.id,
|
61
|
+
message: log,
|
62
|
+
level,
|
63
|
+
time: Date.now(),
|
64
|
+
});
|
65
|
+
}
|
57
66
|
async wait() {
|
58
67
|
return this.future.promise;
|
59
68
|
}
|
package/dist/cjs/src/types.d.ts
CHANGED
@@ -21,6 +21,7 @@ export type WatchEventName = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir
|
|
21
21
|
export type LogLevel = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'FATAL';
|
22
22
|
export type LogSource = 'stdout' | 'stderr';
|
23
23
|
export type EnvironmentType = 'docker' | 'process';
|
24
|
+
export declare const DOCKER_HOST_INTERNAL = "host.docker.internal";
|
24
25
|
export interface LogEntry {
|
25
26
|
source: LogSource;
|
26
27
|
level: LogLevel;
|
@@ -60,31 +61,6 @@ export type ProcessInfo = {
|
|
60
61
|
pid?: number | string | null;
|
61
62
|
portType?: string;
|
62
63
|
};
|
63
|
-
export interface Health {
|
64
|
-
cmd: string;
|
65
|
-
interval?: number;
|
66
|
-
timeout?: number;
|
67
|
-
retries?: number;
|
68
|
-
}
|
69
|
-
export type PortInfo = {
|
70
|
-
port: number;
|
71
|
-
type: 'tcp' | 'udp';
|
72
|
-
} | number | string;
|
73
|
-
export type LocalImageOptions<Credentials = AnyMap, Options = AnyMap> = {
|
74
|
-
image: string;
|
75
|
-
ports: {
|
76
|
-
[key: string]: PortInfo;
|
77
|
-
};
|
78
|
-
credentials?: Credentials;
|
79
|
-
options?: Options;
|
80
|
-
cmd?: string;
|
81
|
-
env?: AnyMap;
|
82
|
-
health?: Health;
|
83
|
-
singleton?: boolean;
|
84
|
-
mounts?: {
|
85
|
-
[key: string]: string;
|
86
|
-
};
|
87
|
-
};
|
88
64
|
export type InstanceInfo = {
|
89
65
|
systemId: string;
|
90
66
|
instanceId: string;
|
@@ -102,29 +78,6 @@ export type InstanceInfo = {
|
|
102
78
|
portType?: string;
|
103
79
|
};
|
104
80
|
export type ProxyRequestHandler = (req: StringBodyRequest, res: express.Response, info: ProxyRequestInfo) => void;
|
105
|
-
export interface OperatorInstancePort {
|
106
|
-
protocol: string;
|
107
|
-
port: number;
|
108
|
-
}
|
109
|
-
export interface OperatorInstanceInfo {
|
110
|
-
hostname: string;
|
111
|
-
ports: {
|
112
|
-
[portType: string]: OperatorInstancePort;
|
113
|
-
};
|
114
|
-
path?: string;
|
115
|
-
query?: string;
|
116
|
-
hash?: string;
|
117
|
-
options?: AnyMap;
|
118
|
-
credentials?: AnyMap;
|
119
|
-
}
|
120
|
-
export interface OperatorInfo {
|
121
|
-
host: string;
|
122
|
-
port: string;
|
123
|
-
type: string;
|
124
|
-
protocol: string;
|
125
|
-
options: AnyMap;
|
126
|
-
credentials: AnyMap;
|
127
|
-
}
|
128
81
|
export interface ProxyRequestInfo {
|
129
82
|
address: string;
|
130
83
|
connection: Connection;
|
package/dist/cjs/src/types.js
CHANGED
@@ -4,11 +4,12 @@
|
|
4
4
|
* SPDX-License-Identifier: BUSL-1.1
|
5
5
|
*/
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
-
exports.DesiredInstanceStatus = exports.InstanceStatus = exports.InstanceOwner = exports.InstanceType = exports.KIND_BLOCK_TYPE_EXECUTABLE = exports.KIND_BLOCK_TYPE_OPERATOR = exports.KIND_BLOCK_TYPE = exports.KIND_RESOURCE_OPERATOR = void 0;
|
7
|
+
exports.DesiredInstanceStatus = exports.InstanceStatus = exports.InstanceOwner = exports.InstanceType = exports.DOCKER_HOST_INTERNAL = exports.KIND_BLOCK_TYPE_EXECUTABLE = exports.KIND_BLOCK_TYPE_OPERATOR = exports.KIND_BLOCK_TYPE = exports.KIND_RESOURCE_OPERATOR = void 0;
|
8
8
|
exports.KIND_RESOURCE_OPERATOR = 'core/resource-type-operator';
|
9
9
|
exports.KIND_BLOCK_TYPE = 'core/block-type';
|
10
10
|
exports.KIND_BLOCK_TYPE_OPERATOR = 'core/block-type-operator';
|
11
11
|
exports.KIND_BLOCK_TYPE_EXECUTABLE = 'core/block-type-executable';
|
12
|
+
exports.DOCKER_HOST_INTERNAL = 'host.docker.internal';
|
12
13
|
var InstanceType;
|
13
14
|
(function (InstanceType) {
|
14
15
|
InstanceType["DOCKER"] = "docker";
|
@@ -19,7 +19,10 @@ const clusterService_1 = require("../clusterService");
|
|
19
19
|
const types_1 = require("../types");
|
20
20
|
const definitionsManager_1 = require("../definitionsManager");
|
21
21
|
const node_os_1 = __importDefault(require("node:os"));
|
22
|
+
const node_path_1 = __importDefault(require("node:path"));
|
22
23
|
const taskManager_1 = require("../taskManager");
|
24
|
+
const InternalConfigProvider_1 = require("./InternalConfigProvider");
|
25
|
+
const config_mapper_1 = require("@kapeta/config-mapper");
|
23
26
|
const KAPETA_SYSTEM_ID = 'KAPETA_SYSTEM_ID';
|
24
27
|
const KAPETA_BLOCK_REF = 'KAPETA_BLOCK_REF';
|
25
28
|
const KAPETA_INSTANCE_ID = 'KAPETA_INSTANCE_ID';
|
@@ -29,7 +32,7 @@ const KAPETA_INSTANCE_ID = 'KAPETA_INSTANCE_ID';
|
|
29
32
|
*/
|
30
33
|
const DOCKER_ENV_VARS = [
|
31
34
|
`KAPETA_LOCAL_SERVER=0.0.0.0`,
|
32
|
-
`KAPETA_LOCAL_CLUSTER_HOST
|
35
|
+
`KAPETA_LOCAL_CLUSTER_HOST=${types_1.DOCKER_HOST_INTERNAL}`,
|
33
36
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
34
37
|
];
|
35
38
|
async function getProvider(uri) {
|
@@ -90,16 +93,6 @@ class BlockInstanceRunner {
|
|
90
93
|
});
|
91
94
|
}
|
92
95
|
async _execute(blockInstance) {
|
93
|
-
const env = {};
|
94
|
-
if (this._systemId) {
|
95
|
-
env[KAPETA_SYSTEM_ID] = this._systemId;
|
96
|
-
}
|
97
|
-
if (blockInstance.ref) {
|
98
|
-
env[KAPETA_BLOCK_REF] = blockInstance.ref;
|
99
|
-
}
|
100
|
-
if (blockInstance.id) {
|
101
|
-
env[KAPETA_INSTANCE_ID] = blockInstance.id;
|
102
|
-
}
|
103
96
|
const blockUri = (0, nodejs_utils_1.parseKapetaUri)(blockInstance.ref);
|
104
97
|
if (!blockUri.version) {
|
105
98
|
blockUri.version = 'local';
|
@@ -113,18 +106,25 @@ class BlockInstanceRunner {
|
|
113
106
|
if (!providerVersion) {
|
114
107
|
throw new Error(`Kind not found: ${kindUri.id}`);
|
115
108
|
}
|
109
|
+
const baseDir = local_cluster_config_1.default.getRepositoryAssetPath(blockUri.handle, blockUri.name, blockUri.version);
|
110
|
+
const realBaseDir = await fs_extra_1.default.realpath(baseDir);
|
111
|
+
const internalConfigProvider = await (0, InternalConfigProvider_1.createInternalConfigProvider)(this._systemId, blockInstance.id, assetVersion);
|
112
|
+
// Resolve the environment variables
|
113
|
+
const envVars = await (0, config_mapper_1.resolveKapetaVariables)(realBaseDir, internalConfigProvider);
|
114
|
+
// Write out the config templates if they exist
|
115
|
+
await (0, config_mapper_1.writeConfigTemplates)(envVars, realBaseDir);
|
116
116
|
let processInfo;
|
117
117
|
if (providerVersion.definition.kind === types_1.KIND_BLOCK_TYPE_OPERATOR) {
|
118
|
-
processInfo = await this._startOperatorProcess(blockInstance, blockUri, providerVersion,
|
118
|
+
processInfo = await this._startOperatorProcess(blockInstance, blockUri, providerVersion, envVars);
|
119
119
|
}
|
120
120
|
else {
|
121
121
|
//We need a port type to know how to connect to the block consistently
|
122
122
|
const portTypes = getServiceProviderPorts(assetVersion, providerVersion);
|
123
123
|
if (blockUri.version === 'local') {
|
124
|
-
processInfo = await this._startLocalProcess(blockInstance, blockUri,
|
124
|
+
processInfo = await this._startLocalProcess(blockInstance, blockUri, envVars, assetVersion);
|
125
125
|
}
|
126
126
|
else {
|
127
|
-
processInfo = await this._startDockerProcess(blockInstance, blockUri,
|
127
|
+
processInfo = await this._startDockerProcess(blockInstance, blockUri, envVars, assetVersion);
|
128
128
|
}
|
129
129
|
if (portTypes.length > 0) {
|
130
130
|
processInfo.portType = portTypes[0];
|
@@ -144,6 +144,7 @@ class BlockInstanceRunner {
|
|
144
144
|
if (!assetVersion.definition.spec?.target?.kind) {
|
145
145
|
throw new Error('Missing target kind in block definition');
|
146
146
|
}
|
147
|
+
const realLocalPath = await fs_extra_1.default.realpath(baseDir);
|
147
148
|
const kindUri = (0, nodejs_utils_1.parseKapetaUri)(assetVersion.definition.kind);
|
148
149
|
const providerVersion = await getProvider(kindUri);
|
149
150
|
if (!providerVersion) {
|
@@ -158,10 +159,21 @@ class BlockInstanceRunner {
|
|
158
159
|
if (!localContainer) {
|
159
160
|
throw new Error(`Missing local container information from target: ${targetKindUri.id}`);
|
160
161
|
}
|
161
|
-
|
162
|
-
|
162
|
+
let dockerImage = localContainer.image;
|
163
|
+
const isDockerImage = !localContainer.type || localContainer.type.toLowerCase() === 'docker';
|
164
|
+
const isDockerFile = Boolean(localContainer.type && localContainer.type.toLowerCase() === 'dockerfile');
|
165
|
+
if (isDockerImage && !dockerImage) {
|
163
166
|
throw new Error(`Missing docker image information: ${JSON.stringify(localContainer)}`);
|
164
167
|
}
|
168
|
+
if (isDockerFile) {
|
169
|
+
dockerImage = blockInfo.fullName + ':local';
|
170
|
+
const dockerFile = node_path_1.default.join(realLocalPath, localContainer.file ?? 'Dockerfile');
|
171
|
+
if (!fs_extra_1.default.existsSync(dockerFile)) {
|
172
|
+
throw new Error(`Dockerfile not found at: ${dockerFile}`);
|
173
|
+
}
|
174
|
+
const task = containerManager_1.containerManager.buildDockerImage(dockerFile, blockInfo.fullName + ':local');
|
175
|
+
await task.wait();
|
176
|
+
}
|
165
177
|
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, targetKindUri.id);
|
166
178
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
167
179
|
const dockerOpts = localContainer.options ?? {};
|
@@ -180,10 +192,13 @@ class BlockInstanceRunner {
|
|
180
192
|
if (localContainer.healthcheck) {
|
181
193
|
HealthCheck = containerManager_1.containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
182
194
|
}
|
183
|
-
const
|
184
|
-
|
185
|
-
|
186
|
-
|
195
|
+
const Mounts = isDockerImage
|
196
|
+
? // For docker images we mount the local directory to the working directory
|
197
|
+
containerManager_1.containerManager.toDockerMounts({
|
198
|
+
[workingDir]: (0, containerManager_1.toLocalBindVolume)(realLocalPath),
|
199
|
+
})
|
200
|
+
: // For dockerfiles we don't mount anything
|
201
|
+
[];
|
187
202
|
const systemUri = (0, nodejs_utils_1.parseKapetaUri)(this._systemId);
|
188
203
|
return this.ensureContainer({
|
189
204
|
...dockerOpts,
|
@@ -298,29 +313,26 @@ class BlockInstanceRunner {
|
|
298
313
|
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, providerRef);
|
299
314
|
const task = taskManager_1.taskManager.add(`container:start:${containerName}`, async () => {
|
300
315
|
const logs = new LogData_1.LogData();
|
301
|
-
const
|
316
|
+
const hostIp = (0, utils_1.getDockerHostIp)();
|
302
317
|
const ExposedPorts = {};
|
303
318
|
const addonEnv = {};
|
304
319
|
const PortBindings = {};
|
305
320
|
let HealthCheck = undefined;
|
306
321
|
let Mounts = [];
|
307
|
-
const
|
322
|
+
const instancePorts = await (0, utils_1.getOperatorInstancePorts)(this._systemId, operatorId, local);
|
308
323
|
const labels = {};
|
309
|
-
|
310
|
-
const
|
311
|
-
const dockerPort = `${portInfo.port}/${portInfo.type}`;
|
324
|
+
instancePorts.forEach((portInfo) => {
|
325
|
+
const dockerPort = `${portInfo.port}/${portInfo.protocol}`;
|
312
326
|
ExposedPorts[dockerPort] = {};
|
313
|
-
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = `${portInfo.port}`;
|
314
|
-
const publicPort = await serviceManager_1.serviceManager.ensureServicePort(this._systemId, operatorId, portType);
|
327
|
+
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portInfo.portType.toUpperCase()}`] = `${portInfo.port}`;
|
315
328
|
PortBindings[dockerPort] = [
|
316
329
|
{
|
317
|
-
HostIp:
|
318
|
-
HostPort: `${
|
330
|
+
HostIp: hostIp,
|
331
|
+
HostPort: `${portInfo.hostPort}`,
|
319
332
|
},
|
320
333
|
];
|
321
|
-
labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX +
|
334
|
+
labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.portType;
|
322
335
|
});
|
323
|
-
await Promise.all(promises);
|
324
336
|
if (local.env) {
|
325
337
|
Object.entries(local.env).forEach(([key, value]) => {
|
326
338
|
addonEnv[key] = value;
|
@@ -384,7 +396,7 @@ class BlockInstanceRunner {
|
|
384
396
|
* Get the port bindings for a non-operator block
|
385
397
|
*/
|
386
398
|
async getServiceBlockPortBindings(blockInstance, assetVersion, providerVersion) {
|
387
|
-
const
|
399
|
+
const hostIp = (0, utils_1.getDockerHostIp)();
|
388
400
|
const ExposedPorts = {};
|
389
401
|
const addonEnv = {};
|
390
402
|
const PortBindings = {};
|
@@ -398,7 +410,7 @@ class BlockInstanceRunner {
|
|
398
410
|
addonEnv[`KAPETA_LOCAL_SERVER_PORT_${portType.toUpperCase()}`] = '' + thisPort;
|
399
411
|
PortBindings[dockerPort] = [
|
400
412
|
{
|
401
|
-
HostIp:
|
413
|
+
HostIp: hostIp,
|
402
414
|
HostPort: `${publicPort}`,
|
403
415
|
},
|
404
416
|
];
|
@@ -0,0 +1,38 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Kapeta Inc.
|
3
|
+
* SPDX-License-Identifier: BUSL-1.1
|
4
|
+
*/
|
5
|
+
import { BlockInstanceDetails, ConfigProvider, DefaultCredentials, DefaultResourceOptions, InstanceOperator, ResourceInfo } from '@kapeta/sdk-config';
|
6
|
+
import { Definition, DefinitionInfo } from '@kapeta/local-cluster-config';
|
7
|
+
import { BlockDefinition, Plan } from '@kapeta/schemas';
|
8
|
+
import { AnyMap, EnvironmentType } from '../types';
|
9
|
+
/**
|
10
|
+
* A configuration provider that does the same as the LocalConfigProvider
|
11
|
+
* but without calling the API of the local cluster service (since it's running in the same process)
|
12
|
+
*/
|
13
|
+
export declare class InternalConfigProvider implements ConfigProvider {
|
14
|
+
private readonly info;
|
15
|
+
private readonly systemId;
|
16
|
+
private readonly instanceId;
|
17
|
+
private readonly config;
|
18
|
+
private readonly environment;
|
19
|
+
constructor(systemId: string, instanceId: string, info: DefinitionInfo, config: AnyMap, environment?: EnvironmentType);
|
20
|
+
getBlockDefinition(): Definition;
|
21
|
+
getBlockReference(): string;
|
22
|
+
getSystemId(): string;
|
23
|
+
getInstanceId(): string;
|
24
|
+
getServerPort(portType?: string | undefined): Promise<string>;
|
25
|
+
getServiceAddress(serviceName: string, portType: string): Promise<string | null>;
|
26
|
+
getResourceInfo<Options = DefaultResourceOptions, Credentials = DefaultCredentials>(resourceType: string, portType: string, resourceName: string): Promise<ResourceInfo<Options, Credentials> | null>;
|
27
|
+
getInstanceHost(instanceId: string): Promise<string | null>;
|
28
|
+
getServerHost(): Promise<string>;
|
29
|
+
getProviderId(): string;
|
30
|
+
getOrDefault<T = any>(path: string, defaultValue: T): T;
|
31
|
+
get<T = any>(path: string): T | undefined;
|
32
|
+
getInstanceOperator<Options = any, Credentials extends DefaultCredentials = DefaultCredentials>(instanceId: string): Promise<InstanceOperator<Options, Credentials> | null>;
|
33
|
+
getInstanceForConsumer<BlockType = BlockDefinition>(resourceName: string): Promise<BlockInstanceDetails<BlockType> | null>;
|
34
|
+
getInstancesForProvider<BlockType = BlockDefinition>(resourceName: string): Promise<BlockInstanceDetails<BlockType>[]>;
|
35
|
+
getBlock(ref: any): Promise<Definition>;
|
36
|
+
getPlan(): Promise<Plan>;
|
37
|
+
}
|
38
|
+
export declare function createInternalConfigProvider(systemId: string, instanceId: string, info: DefinitionInfo): Promise<InternalConfigProvider>;
|
@@ -0,0 +1,146 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.createInternalConfigProvider = exports.InternalConfigProvider = void 0;
|
7
|
+
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
8
|
+
const configManager_1 = require("../configManager");
|
9
|
+
const lodash_1 = __importDefault(require("lodash"));
|
10
|
+
const serviceManager_1 = require("../serviceManager");
|
11
|
+
const operatorManager_1 = require("../operatorManager");
|
12
|
+
const instanceManager_1 = require("../instanceManager");
|
13
|
+
const definitionsManager_1 = require("../definitionsManager");
|
14
|
+
const utils_1 = require("./utils");
|
15
|
+
/**
|
16
|
+
* A configuration provider that does the same as the LocalConfigProvider
|
17
|
+
* but without calling the API of the local cluster service (since it's running in the same process)
|
18
|
+
*/
|
19
|
+
class InternalConfigProvider {
|
20
|
+
info;
|
21
|
+
systemId;
|
22
|
+
instanceId;
|
23
|
+
config;
|
24
|
+
environment;
|
25
|
+
constructor(systemId, instanceId, info, config, environment = 'docker') {
|
26
|
+
this.info = info;
|
27
|
+
this.systemId = (0, nodejs_utils_1.normalizeKapetaUri)(systemId);
|
28
|
+
this.instanceId = instanceId;
|
29
|
+
this.config = config;
|
30
|
+
this.environment = environment;
|
31
|
+
}
|
32
|
+
getBlockDefinition() {
|
33
|
+
return this.info.definition;
|
34
|
+
}
|
35
|
+
getBlockReference() {
|
36
|
+
return (0, nodejs_utils_1.normalizeKapetaUri)(this.info.definition.metadata.name + ':' + this.info.version);
|
37
|
+
}
|
38
|
+
getSystemId() {
|
39
|
+
return this.systemId;
|
40
|
+
}
|
41
|
+
getInstanceId() {
|
42
|
+
return this.instanceId;
|
43
|
+
}
|
44
|
+
getServerPort(portType) {
|
45
|
+
return serviceManager_1.serviceManager.ensureServicePort(this.systemId, this.instanceId, portType);
|
46
|
+
}
|
47
|
+
async getServiceAddress(serviceName, portType) {
|
48
|
+
return serviceManager_1.serviceManager.getConsumerAddress(this.systemId, this.instanceId, serviceName, portType, this.environment);
|
49
|
+
}
|
50
|
+
getResourceInfo(resourceType, portType, resourceName) {
|
51
|
+
return operatorManager_1.operatorManager.getConsumerResourceInfo(this.systemId, this.instanceId, resourceType, portType, resourceName, this.environment, false);
|
52
|
+
}
|
53
|
+
async getInstanceHost(instanceId) {
|
54
|
+
const instance = instanceManager_1.instanceManager.getInstance(this.systemId, instanceId);
|
55
|
+
return instance?.address ?? null;
|
56
|
+
}
|
57
|
+
async getServerHost() {
|
58
|
+
return (0, utils_1.getBindAddressForEnvironment)(this.environment);
|
59
|
+
}
|
60
|
+
getProviderId() {
|
61
|
+
return 'internal';
|
62
|
+
}
|
63
|
+
getOrDefault(path, defaultValue) {
|
64
|
+
return this.get(path) ?? defaultValue;
|
65
|
+
}
|
66
|
+
get(path) {
|
67
|
+
return lodash_1.default.get(this.config, path);
|
68
|
+
}
|
69
|
+
getInstanceOperator(instanceId) {
|
70
|
+
return instanceManager_1.instanceManager.getInstanceOperator(this.systemId, instanceId, this.environment, false);
|
71
|
+
}
|
72
|
+
async getInstanceForConsumer(resourceName) {
|
73
|
+
const plan = await this.getPlan();
|
74
|
+
if (!plan) {
|
75
|
+
throw new Error('Could not find plan');
|
76
|
+
}
|
77
|
+
const instanceId = this.getInstanceId();
|
78
|
+
const connection = plan.spec.connections.find((connection) => connection.consumer.blockId === instanceId && connection.consumer.resourceName === resourceName);
|
79
|
+
if (!connection) {
|
80
|
+
throw new Error(`Could not find connection for consumer ${resourceName}`);
|
81
|
+
}
|
82
|
+
const instance = plan.spec.blocks.find((b) => b.id === connection.provider.blockId);
|
83
|
+
if (!instance) {
|
84
|
+
throw new Error(`Could not find instance ${connection.provider.blockId} in plan`);
|
85
|
+
}
|
86
|
+
const block = await this.getBlock(instance.block.ref);
|
87
|
+
if (!block) {
|
88
|
+
throw new Error(`Could not find block ${instance.block.ref} in plan`);
|
89
|
+
}
|
90
|
+
return {
|
91
|
+
instanceId: connection.provider.blockId,
|
92
|
+
connections: [connection],
|
93
|
+
block: block,
|
94
|
+
};
|
95
|
+
}
|
96
|
+
async getInstancesForProvider(resourceName) {
|
97
|
+
const plan = await this.getPlan();
|
98
|
+
if (!plan) {
|
99
|
+
throw new Error('Could not find plan');
|
100
|
+
}
|
101
|
+
const instanceId = this.getInstanceId();
|
102
|
+
const blockDetails = {};
|
103
|
+
const connections = plan.spec.connections.filter((connection) => connection.provider.blockId === instanceId && connection.provider.resourceName === resourceName);
|
104
|
+
for (const connection of connections) {
|
105
|
+
const blockInstanceId = connection.consumer.blockId;
|
106
|
+
if (blockDetails[blockInstanceId]) {
|
107
|
+
blockDetails[blockInstanceId].connections.push(connection);
|
108
|
+
continue;
|
109
|
+
}
|
110
|
+
const instance = plan.spec.blocks.find((b) => b.id === blockInstanceId);
|
111
|
+
if (!instance) {
|
112
|
+
throw new Error(`Could not find instance ${blockInstanceId} in plan`);
|
113
|
+
}
|
114
|
+
const block = await this.getBlock(instance.block.ref);
|
115
|
+
if (!block) {
|
116
|
+
throw new Error(`Could not find block ${instance.block.ref} in plan`);
|
117
|
+
}
|
118
|
+
blockDetails[blockInstanceId] = {
|
119
|
+
instanceId: blockInstanceId,
|
120
|
+
connections: [connection],
|
121
|
+
block: block,
|
122
|
+
};
|
123
|
+
}
|
124
|
+
return Object.values(blockDetails);
|
125
|
+
}
|
126
|
+
async getBlock(ref) {
|
127
|
+
const definition = await definitionsManager_1.definitionsManager.getDefinition(ref);
|
128
|
+
if (!definition) {
|
129
|
+
throw new Error(`Could not find definition for ${ref}`);
|
130
|
+
}
|
131
|
+
return definition.definition;
|
132
|
+
}
|
133
|
+
async getPlan() {
|
134
|
+
const definition = await definitionsManager_1.definitionsManager.getDefinition(this.systemId);
|
135
|
+
if (!definition) {
|
136
|
+
throw new Error(`Could not find plan ${this.systemId}`);
|
137
|
+
}
|
138
|
+
return definition.definition;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
exports.InternalConfigProvider = InternalConfigProvider;
|
142
|
+
async function createInternalConfigProvider(systemId, instanceId, info) {
|
143
|
+
const config = await configManager_1.configManager.getConfigForBlockInstance(systemId, instanceId);
|
144
|
+
return new InternalConfigProvider(systemId, instanceId, info, config);
|
145
|
+
}
|
146
|
+
exports.createInternalConfigProvider = createInternalConfigProvider;
|
@@ -2,6 +2,7 @@
|
|
2
2
|
* Copyright 2023 Kapeta Inc.
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
|
+
import { Task } from '../taskManager';
|
5
6
|
export declare function hasCLI(): Promise<boolean>;
|
6
|
-
export declare function ensureCLI(): Promise<
|
7
|
+
export declare function ensureCLI(): Promise<Task<void> | null>;
|
7
8
|
export declare function ensureCLICommands(): Promise<void>;
|
@@ -15,10 +15,16 @@ async function ensureCLI() {
|
|
15
15
|
if (await hasCLI()) {
|
16
16
|
return null;
|
17
17
|
}
|
18
|
-
return taskManager_1.taskManager.add(`cli:install`, () => {
|
18
|
+
return taskManager_1.taskManager.add(`cli:install`, (task) => {
|
19
19
|
const process = (0, nodejs_process_1.spawn)('npm', ['install', '-g', '@kapeta/kap'], {
|
20
20
|
shell: true,
|
21
21
|
});
|
22
|
+
process.process.stdout?.on('data', (data) => {
|
23
|
+
task.addLog(data.toString(), 'INFO');
|
24
|
+
});
|
25
|
+
process.process.stderr?.on('data', (data) => {
|
26
|
+
task.addLog(data.toString(), 'ERROR');
|
27
|
+
});
|
22
28
|
return process.wait();
|
23
29
|
}, {
|
24
30
|
name: `Installing Kapeta CLI`,
|
@@ -2,17 +2,39 @@
|
|
2
2
|
* Copyright 2023 Kapeta Inc.
|
3
3
|
* SPDX-License-Identifier: BUSL-1.1
|
4
4
|
*/
|
5
|
-
import { EntityList } from '@kapeta/schemas';
|
6
|
-
import { AnyMap,
|
5
|
+
import { EntityList, LocalInstance, LocalInstancePort } from '@kapeta/schemas';
|
6
|
+
import { AnyMap, EnvironmentType } from '../types';
|
7
7
|
export declare function getBlockInstanceContainerName(systemId: string, instanceId: string, blockType?: string): Promise<string>;
|
8
|
-
export declare function toPortInfo(port:
|
8
|
+
export declare function toPortInfo(port: LocalInstancePort): LocalInstancePort | {
|
9
9
|
port: number;
|
10
10
|
type: string;
|
11
11
|
};
|
12
|
+
export declare function getOperatorInstancePorts(systemId: string, operatorId: string, local: LocalInstance): Promise<{
|
13
|
+
portType: string;
|
14
|
+
port: number | undefined;
|
15
|
+
hostPort: any;
|
16
|
+
protocol: string | undefined;
|
17
|
+
}[]>;
|
18
|
+
/**
|
19
|
+
* Gets the hostname where all services are available - including the cluster service.
|
20
|
+
*
|
21
|
+
* For docker this is the internal docker host - otherwise it's the local machine
|
22
|
+
* Assumed to be the same address as the cluster service outside docker.
|
23
|
+
*/
|
24
|
+
export declare function getRemoteHostForEnvironment(environment: EnvironmentType | undefined): string;
|
25
|
+
/**
|
26
|
+
* Get the bind address for the given environment.
|
27
|
+
*
|
28
|
+
* Outside of docker we bind to 127.0.0.1 - inside we bind to everything (0.0.0.0)
|
29
|
+
*/
|
30
|
+
export declare function getBindAddressForEnvironment(environment: EnvironmentType | undefined, preferredHost?: string): string;
|
31
|
+
/**
|
32
|
+
* Get the docker host IP address for port binding.
|
33
|
+
*/
|
34
|
+
export declare function getDockerHostIp(preferredHost?: string): string;
|
12
35
|
export declare function getRemoteUrl(id: string, defautValue: string): any;
|
13
36
|
export declare function readYML(path: string): any;
|
14
37
|
export declare function isWindows(): boolean;
|
15
38
|
export declare function isMac(): boolean;
|
16
39
|
export declare function isLinux(): boolean;
|
17
|
-
export declare function getBindHost(preferredHost?: string): string;
|
18
40
|
export declare function getResolvedConfiguration(entities?: EntityList, config?: AnyMap, globalConfiguration?: AnyMap): AnyMap;
|