@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.
Files changed (69) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/index.js +4 -1
  3. package/dist/cjs/src/assetManager.d.ts +2 -1
  4. package/dist/cjs/src/assetManager.js +3 -2
  5. package/dist/cjs/src/config/routes.js +2 -2
  6. package/dist/cjs/src/containerManager.d.ts +6 -3
  7. package/dist/cjs/src/containerManager.js +101 -21
  8. package/dist/cjs/src/instanceManager.d.ts +4 -2
  9. package/dist/cjs/src/instanceManager.js +71 -32
  10. package/dist/cjs/src/operatorManager.d.ts +6 -3
  11. package/dist/cjs/src/operatorManager.js +32 -23
  12. package/dist/cjs/src/progressListener.d.ts +8 -1
  13. package/dist/cjs/src/progressListener.js +12 -1
  14. package/dist/cjs/src/repositoryManager.js +3 -2
  15. package/dist/cjs/src/serviceManager.d.ts +0 -1
  16. package/dist/cjs/src/serviceManager.js +2 -8
  17. package/dist/cjs/src/taskManager.d.ts +2 -0
  18. package/dist/cjs/src/taskManager.js +9 -0
  19. package/dist/cjs/src/types.d.ts +1 -48
  20. package/dist/cjs/src/types.js +2 -1
  21. package/dist/cjs/src/utils/BlockInstanceRunner.js +45 -33
  22. package/dist/cjs/src/utils/InternalConfigProvider.d.ts +38 -0
  23. package/dist/cjs/src/utils/InternalConfigProvider.js +146 -0
  24. package/dist/cjs/src/utils/commandLineUtils.d.ts +2 -1
  25. package/dist/cjs/src/utils/commandLineUtils.js +7 -1
  26. package/dist/cjs/src/utils/utils.d.ts +26 -4
  27. package/dist/cjs/src/utils/utils.js +48 -8
  28. package/dist/esm/index.js +4 -1
  29. package/dist/esm/src/assetManager.d.ts +2 -1
  30. package/dist/esm/src/assetManager.js +3 -2
  31. package/dist/esm/src/config/routes.js +2 -2
  32. package/dist/esm/src/containerManager.d.ts +6 -3
  33. package/dist/esm/src/containerManager.js +101 -21
  34. package/dist/esm/src/instanceManager.d.ts +4 -2
  35. package/dist/esm/src/instanceManager.js +71 -32
  36. package/dist/esm/src/operatorManager.d.ts +6 -3
  37. package/dist/esm/src/operatorManager.js +32 -23
  38. package/dist/esm/src/progressListener.d.ts +8 -1
  39. package/dist/esm/src/progressListener.js +12 -1
  40. package/dist/esm/src/repositoryManager.js +3 -2
  41. package/dist/esm/src/serviceManager.d.ts +0 -1
  42. package/dist/esm/src/serviceManager.js +2 -8
  43. package/dist/esm/src/taskManager.d.ts +2 -0
  44. package/dist/esm/src/taskManager.js +9 -0
  45. package/dist/esm/src/types.d.ts +1 -48
  46. package/dist/esm/src/types.js +2 -1
  47. package/dist/esm/src/utils/BlockInstanceRunner.js +45 -33
  48. package/dist/esm/src/utils/InternalConfigProvider.d.ts +38 -0
  49. package/dist/esm/src/utils/InternalConfigProvider.js +146 -0
  50. package/dist/esm/src/utils/commandLineUtils.d.ts +2 -1
  51. package/dist/esm/src/utils/commandLineUtils.js +7 -1
  52. package/dist/esm/src/utils/utils.d.ts +26 -4
  53. package/dist/esm/src/utils/utils.js +48 -8
  54. package/index.ts +5 -2
  55. package/package.json +16 -14
  56. package/src/assetManager.ts +5 -4
  57. package/src/config/routes.ts +4 -2
  58. package/src/containerManager.ts +115 -26
  59. package/src/instanceManager.ts +86 -44
  60. package/src/operatorManager.ts +48 -40
  61. package/src/progressListener.ts +15 -1
  62. package/src/repositoryManager.ts +5 -3
  63. package/src/serviceManager.ts +3 -11
  64. package/src/taskManager.ts +11 -0
  65. package/src/types.ts +2 -50
  66. package/src/utils/BlockInstanceRunner.ts +60 -44
  67. package/src/utils/InternalConfigProvider.ts +214 -0
  68. package/src/utils/commandLineUtils.ts +10 -2
  69. package/src/utils/utils.ts +53 -10
@@ -68,7 +68,7 @@ class OperatorManager {
68
68
  /**
69
69
  * Get information about a specific consumed resource
70
70
  */
71
- async getConsumerResourceInfo(systemId, fromServiceId, resourceType, portType, name, environment) {
71
+ async getConsumerResourceInfo(systemId, fromServiceId, resourceType, portType, name, environment, ensureContainer = true) {
72
72
  systemId = (0, nodejs_utils_1.normalizeKapetaUri)(systemId);
73
73
  const plans = await definitionsManager_1.definitionsManager.getDefinitions(KIND_PLAN);
74
74
  const planUri = (0, nodejs_utils_1.parseKapetaUri)(systemId);
@@ -96,18 +96,20 @@ class OperatorManager {
96
96
  const kindUri = (0, nodejs_utils_1.parseKapetaUri)(blockResource.kind);
97
97
  const operator = await this.getOperator(resourceType, kindUri.version);
98
98
  const credentials = operator.getCredentials();
99
- const container = await this.ensureOperator(systemId, resourceType, kindUri.version);
100
- const portInfo = await container.getPort(portType);
101
- if (!portInfo) {
99
+ if (ensureContainer) {
100
+ await this.ensureOperator(systemId, resourceType, kindUri.version);
101
+ }
102
+ const hostPort = await serviceManager_1.serviceManager.ensureServicePort(systemId, resourceType, portType);
103
+ if (!hostPort) {
102
104
  throw new Error('Unknown resource port type : ' + resourceType + '#' + portType);
103
105
  }
104
106
  const dbName = name + '_' + fromServiceId.replace(/[^a-z0-9]/gi, '');
105
107
  const safeName = dbName.replace('_', '-');
106
108
  return {
107
- host: environment === 'docker' ? 'host.docker.internal' : '127.0.0.1',
108
- port: portInfo.hostPort,
109
+ host: (0, utils_1.getRemoteHostForEnvironment)(environment),
110
+ port: hostPort,
109
111
  type: portType,
110
- protocol: portInfo.protocol,
112
+ protocol: 'tcp',
111
113
  options: {
112
114
  // expose as fullName since that is not operator specific, but unique
113
115
  fullName: safeName,
@@ -116,6 +118,26 @@ class OperatorManager {
116
118
  credentials,
117
119
  };
118
120
  }
121
+ async getOperatorPorts(systemId, kind, version) {
122
+ const operator = await this.getOperator(kind, version);
123
+ const operatorData = operator.getLocalData();
124
+ const portTypes = Object.keys(operatorData.ports);
125
+ portTypes.sort();
126
+ const ports = {};
127
+ for (let i = 0; i < portTypes.length; i++) {
128
+ const portType = portTypes[i];
129
+ let containerPortInfo = operatorData.ports[portType];
130
+ const hostPort = await serviceManager_1.serviceManager.ensureServicePort(systemId, kind, portType);
131
+ const portInfo = (0, utils_1.toPortInfo)(containerPortInfo);
132
+ const portId = portInfo.port + '/' + portInfo.type;
133
+ ports[portId] = {
134
+ type: portType,
135
+ hostPort,
136
+ protocol: portInfo.type,
137
+ };
138
+ }
139
+ return ports;
140
+ }
119
141
  /**
120
142
  * Ensure we have a running operator of given type
121
143
  *
@@ -129,20 +151,7 @@ class OperatorManager {
129
151
  return await this.operatorLock.acquire(key, async () => {
130
152
  const operator = await this.getOperator(kind, version);
131
153
  const operatorData = operator.getLocalData();
132
- const portTypes = Object.keys(operatorData.ports);
133
- portTypes.sort();
134
- const ports = {};
135
- for (let i = 0; i < portTypes.length; i++) {
136
- const portType = portTypes[i];
137
- let containerPortInfo = operatorData.ports[portType];
138
- const hostPort = await serviceManager_1.serviceManager.ensureServicePort(systemId, kind, portType);
139
- const portInfo = (0, utils_1.toPortInfo)(containerPortInfo);
140
- const portId = portInfo.port + '/' + portInfo.type;
141
- ports[portId] = {
142
- type: portType,
143
- hostPort,
144
- };
145
- }
154
+ const ports = await this.getOperatorPorts(systemId, kind, version);
146
155
  const nameParts = [systemId, kind.toLowerCase(), version];
147
156
  const containerName = `kapeta-resource-${(0, md5_1.default)(nameParts.join('_'))}`;
148
157
  const PortBindings = {};
@@ -154,14 +163,14 @@ class OperatorManager {
154
163
  [containerManager_1.COMPOSE_LABEL_SERVICE]: [kind, version].join('_').replace(/[^a-z0-9]/gi, '_'),
155
164
  };
156
165
  const operatorMetadata = operator.getDefinitionInfo().definition.metadata;
157
- const bindHost = (0, utils_1.getBindHost)();
166
+ const hostIp = (0, utils_1.getDockerHostIp)();
158
167
  const ExposedPorts = {};
159
168
  lodash_1.default.forEach(ports, (portInfo, containerPort) => {
160
169
  ExposedPorts['' + containerPort] = {};
161
170
  PortBindings['' + containerPort] = [
162
171
  {
163
172
  HostPort: '' + portInfo.hostPort,
164
- HostIp: bindHost,
173
+ HostIp: hostIp,
165
174
  },
166
175
  ];
167
176
  Labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
@@ -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
- private emitLog;
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(new progressListener_1.ProgressListener(), [ref], {});
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 = this.getLocalHost(environmentType);
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
  }
@@ -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;
@@ -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=host.docker.internal`,
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, env);
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, env, assetVersion);
124
+ processInfo = await this._startLocalProcess(blockInstance, blockUri, envVars, assetVersion);
125
125
  }
126
126
  else {
127
- processInfo = await this._startDockerProcess(blockInstance, blockUri, env, assetVersion);
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
- const dockerImage = localContainer.image;
162
- if (!dockerImage) {
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 realLocalPath = await fs_extra_1.default.realpath(baseDir);
184
- const Mounts = containerManager_1.containerManager.toDockerMounts({
185
- [workingDir]: (0, containerManager_1.toLocalBindVolume)(realLocalPath),
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 bindHost = (0, utils_1.getBindHost)();
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 localPorts = local.ports ?? {};
322
+ const instancePorts = await (0, utils_1.getOperatorInstancePorts)(this._systemId, operatorId, local);
308
323
  const labels = {};
309
- const promises = Object.entries(localPorts).map(async ([portType, value]) => {
310
- const portInfo = (0, utils_1.toPortInfo)(value);
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: bindHost,
318
- HostPort: `${publicPort}`,
330
+ HostIp: hostIp,
331
+ HostPort: `${portInfo.hostPort}`,
319
332
  },
320
333
  ];
321
- labels[containerManager_1.CONTAINER_LABEL_PORT_PREFIX + publicPort] = portType;
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 bindHost = (0, utils_1.getBindHost)();
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: bindHost,
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>;