@kapeta/local-cluster-service 0.40.0 → 0.40.2
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/.github/workflows/main.yml +2 -1
- package/CHANGELOG.md +14 -0
- package/dist/cjs/src/containerManager.js +15 -5
- package/dist/cjs/src/proxy/types/rest.js +5 -0
- package/dist/cjs/src/proxy/types/web.js +2 -2
- package/dist/cjs/src/utils/BlockInstanceRunner.js +11 -4
- package/dist/cjs/src/utils/InternalConfigProvider.js +2 -2
- package/dist/esm/src/containerManager.js +15 -5
- package/dist/esm/src/proxy/types/rest.js +5 -0
- package/dist/esm/src/proxy/types/web.js +2 -2
- package/dist/esm/src/utils/BlockInstanceRunner.js +11 -4
- package/dist/esm/src/utils/InternalConfigProvider.js +2 -2
- package/package.json +1 -1
- package/src/containerManager.ts +20 -12
- package/src/proxy/types/rest.ts +5 -0
- package/src/proxy/types/web.ts +2 -2
- package/src/utils/BlockInstanceRunner.ts +12 -4
- package/src/utils/InternalConfigProvider.ts +2 -2
@@ -8,9 +8,10 @@ jobs:
|
|
8
8
|
build:
|
9
9
|
runs-on: ubuntu-latest
|
10
10
|
steps:
|
11
|
-
- uses: actions/checkout@
|
11
|
+
- uses: actions/checkout@v4
|
12
12
|
with:
|
13
13
|
token: ${{ secrets.BOT_TOKEN }}
|
14
|
+
fetch-depth: 0
|
14
15
|
- uses: actions/setup-node@v3
|
15
16
|
- run: npm ci
|
16
17
|
- run: npm run build --if-present
|
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [0.40.2](https://github.com/kapetacom/local-cluster-service/compare/v0.40.1...v0.40.2) (2024-03-11)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Several issues when running external docker images ([#132](https://github.com/kapetacom/local-cluster-service/issues/132)) ([5218368](https://github.com/kapetacom/local-cluster-service/commit/521836819aa39084fe1c4f781fb560682e42fc8f))
|
7
|
+
|
8
|
+
## [0.40.1](https://github.com/kapetacom/local-cluster-service/compare/v0.40.0...v0.40.1) (2024-02-28)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* bump release ([1a6fbb2](https://github.com/kapetacom/local-cluster-service/commit/1a6fbb2d8095e1bc7878e35e52fe40a5a498f9e6))
|
14
|
+
|
1
15
|
# [0.40.0](https://github.com/kapetacom/local-cluster-service/compare/v0.39.2...v0.40.0) (2024-02-28)
|
2
16
|
|
3
17
|
|
@@ -216,6 +216,10 @@ class ContainerManager {
|
|
216
216
|
if (!tag) {
|
217
217
|
tag = 'latest';
|
218
218
|
}
|
219
|
+
if (tag === 'local') {
|
220
|
+
// Local image - no need to pull
|
221
|
+
return false;
|
222
|
+
}
|
219
223
|
const imageTagList = (await this.docker().listImages({}))
|
220
224
|
.filter((imageData) => !!imageData.RepoTags)
|
221
225
|
.map((imageData) => imageData.RepoTags);
|
@@ -619,16 +623,22 @@ class ContainerManager {
|
|
619
623
|
buildDockerImage(dockerFile, imageName) {
|
620
624
|
const taskName = `Building docker image: ${imageName}`;
|
621
625
|
const processor = async (task) => {
|
622
|
-
const
|
623
|
-
const
|
626
|
+
const baseDir = path_1.default.dirname(dockerFile);
|
627
|
+
const entries = await fs_extra_1.default.readdir(baseDir);
|
628
|
+
const contextInfo = {
|
624
629
|
context: path_1.default.dirname(dockerFile),
|
625
|
-
src:
|
626
|
-
}
|
630
|
+
src: entries,
|
631
|
+
};
|
632
|
+
const stream = await this.docker().buildImage(contextInfo, {
|
627
633
|
t: imageName,
|
628
634
|
dockerfile: path_1.default.basename(dockerFile),
|
629
635
|
});
|
630
636
|
await processJsonStream(`image:build:${imageName}`, stream, (data) => {
|
631
|
-
if (data.
|
637
|
+
if (data.error) {
|
638
|
+
task.future.reject(new Error(data.error));
|
639
|
+
task.addLog(data.error, 'ERROR');
|
640
|
+
}
|
641
|
+
else if (data.stream) {
|
632
642
|
// Emit raw output to the task log
|
633
643
|
task.addLog(data.stream);
|
634
644
|
}
|
@@ -15,6 +15,7 @@ const pathTemplateParser_1 = require("../../utils/pathTemplateParser");
|
|
15
15
|
const networkManager_1 = require("../../networkManager");
|
16
16
|
const socketManager_1 = require("../../socketManager");
|
17
17
|
const qs_1 = require("qs");
|
18
|
+
const web_1 = require("./web");
|
18
19
|
function getRestMethodId(restResource, httpMethod, httpPath) {
|
19
20
|
return lodash_1.default.findKey(restResource.spec.methods, (method) => {
|
20
21
|
let methodType = method.method ? method.method.toUpperCase() : 'GET';
|
@@ -63,6 +64,10 @@ function resolveMethods(req, opts) {
|
|
63
64
|
};
|
64
65
|
}
|
65
66
|
function proxyRestRequest(req, res, opts) {
|
67
|
+
if (lodash_1.default.isEmpty(opts.consumerResource.spec.methods) && lodash_1.default.isEmpty(opts.providerResource.spec.methods)) {
|
68
|
+
// If there are no methods defined, we assume the user controls the path and we just proxy the raw request
|
69
|
+
return (0, web_1.proxyHttpRequest)(req, res, opts);
|
70
|
+
}
|
66
71
|
let { consumerMethod, providerMethod } = resolveMethods(req, opts);
|
67
72
|
const consumerPathTemplate = (0, pathTemplateParser_1.pathTemplateParser)(consumerMethod.path);
|
68
73
|
const providerPathTemplate = (0, pathTemplateParser_1.pathTemplateParser)(providerMethod.path);
|
@@ -20,8 +20,8 @@ function proxyHttpRequest(req, res, opts) {
|
|
20
20
|
delete requestHeaders['connection'];
|
21
21
|
delete requestHeaders['host'];
|
22
22
|
delete requestHeaders['origin'];
|
23
|
-
const sourceBasePath = opts.consumerResource.spec.path;
|
24
|
-
const targetBasePath = opts.providerResource.spec.path;
|
23
|
+
const sourceBasePath = opts.consumerResource.spec.path ?? '/';
|
24
|
+
const targetBasePath = opts.providerResource.spec.path ?? '/';
|
25
25
|
let path = opts.consumerPath;
|
26
26
|
if (opts.consumerPath.startsWith(sourceBasePath)) {
|
27
27
|
path = path.replace(sourceBasePath, targetBasePath);
|
@@ -34,7 +34,7 @@ const DOCKER_ENV_VARS = [
|
|
34
34
|
`KAPETA_LOCAL_SERVER=0.0.0.0`,
|
35
35
|
`KAPETA_LOCAL_CLUSTER_HOST=${types_1.DOCKER_HOST_INTERNAL}`,
|
36
36
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
37
|
-
`KAPETA_ENVIRONMENT_PLATFORM=${node_os_1.default.platform()}
|
37
|
+
`KAPETA_ENVIRONMENT_PLATFORM=${node_os_1.default.platform()}`,
|
38
38
|
];
|
39
39
|
async function getProvider(uri) {
|
40
40
|
const providers = await definitionsManager_1.definitionsManager.getProviderDefinitions();
|
@@ -172,8 +172,15 @@ class BlockInstanceRunner {
|
|
172
172
|
if (!fs_extra_1.default.existsSync(dockerFile)) {
|
173
173
|
throw new Error(`Dockerfile not found at: ${dockerFile}`);
|
174
174
|
}
|
175
|
-
|
176
|
-
|
175
|
+
console.log('Building docker image from Dockerfile "%s": %s ', dockerFile, dockerImage);
|
176
|
+
try {
|
177
|
+
const task = containerManager_1.containerManager.buildDockerImage(dockerFile, dockerImage);
|
178
|
+
await task.wait();
|
179
|
+
}
|
180
|
+
catch (err) {
|
181
|
+
throw new Error(`Error building docker image: ${err}`);
|
182
|
+
}
|
183
|
+
console.log('Docker images was build from file "%s": %s', dockerFile, dockerImage);
|
177
184
|
}
|
178
185
|
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, targetKindUri.id);
|
179
186
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
@@ -205,7 +212,7 @@ class BlockInstanceRunner {
|
|
205
212
|
...dockerOpts,
|
206
213
|
Image: dockerImage,
|
207
214
|
name: containerName,
|
208
|
-
WorkingDir: workingDir,
|
215
|
+
WorkingDir: isDockerImage ? workingDir : undefined,
|
209
216
|
Labels: {
|
210
217
|
...customLabels,
|
211
218
|
instance: blockInstance.id,
|
@@ -41,8 +41,8 @@ class InternalConfigProvider {
|
|
41
41
|
getInstanceId() {
|
42
42
|
return this.instanceId;
|
43
43
|
}
|
44
|
-
getServerPort(portType) {
|
45
|
-
return
|
44
|
+
async getServerPort(portType) {
|
45
|
+
return '80';
|
46
46
|
}
|
47
47
|
async getServiceAddress(serviceName, portType) {
|
48
48
|
return serviceManager_1.serviceManager.getConsumerAddress(this.systemId, this.instanceId, serviceName, portType, this.environment);
|
@@ -216,6 +216,10 @@ class ContainerManager {
|
|
216
216
|
if (!tag) {
|
217
217
|
tag = 'latest';
|
218
218
|
}
|
219
|
+
if (tag === 'local') {
|
220
|
+
// Local image - no need to pull
|
221
|
+
return false;
|
222
|
+
}
|
219
223
|
const imageTagList = (await this.docker().listImages({}))
|
220
224
|
.filter((imageData) => !!imageData.RepoTags)
|
221
225
|
.map((imageData) => imageData.RepoTags);
|
@@ -619,16 +623,22 @@ class ContainerManager {
|
|
619
623
|
buildDockerImage(dockerFile, imageName) {
|
620
624
|
const taskName = `Building docker image: ${imageName}`;
|
621
625
|
const processor = async (task) => {
|
622
|
-
const
|
623
|
-
const
|
626
|
+
const baseDir = path_1.default.dirname(dockerFile);
|
627
|
+
const entries = await fs_extra_1.default.readdir(baseDir);
|
628
|
+
const contextInfo = {
|
624
629
|
context: path_1.default.dirname(dockerFile),
|
625
|
-
src:
|
626
|
-
}
|
630
|
+
src: entries,
|
631
|
+
};
|
632
|
+
const stream = await this.docker().buildImage(contextInfo, {
|
627
633
|
t: imageName,
|
628
634
|
dockerfile: path_1.default.basename(dockerFile),
|
629
635
|
});
|
630
636
|
await processJsonStream(`image:build:${imageName}`, stream, (data) => {
|
631
|
-
if (data.
|
637
|
+
if (data.error) {
|
638
|
+
task.future.reject(new Error(data.error));
|
639
|
+
task.addLog(data.error, 'ERROR');
|
640
|
+
}
|
641
|
+
else if (data.stream) {
|
632
642
|
// Emit raw output to the task log
|
633
643
|
task.addLog(data.stream);
|
634
644
|
}
|
@@ -15,6 +15,7 @@ const pathTemplateParser_1 = require("../../utils/pathTemplateParser");
|
|
15
15
|
const networkManager_1 = require("../../networkManager");
|
16
16
|
const socketManager_1 = require("../../socketManager");
|
17
17
|
const qs_1 = require("qs");
|
18
|
+
const web_1 = require("./web");
|
18
19
|
function getRestMethodId(restResource, httpMethod, httpPath) {
|
19
20
|
return lodash_1.default.findKey(restResource.spec.methods, (method) => {
|
20
21
|
let methodType = method.method ? method.method.toUpperCase() : 'GET';
|
@@ -63,6 +64,10 @@ function resolveMethods(req, opts) {
|
|
63
64
|
};
|
64
65
|
}
|
65
66
|
function proxyRestRequest(req, res, opts) {
|
67
|
+
if (lodash_1.default.isEmpty(opts.consumerResource.spec.methods) && lodash_1.default.isEmpty(opts.providerResource.spec.methods)) {
|
68
|
+
// If there are no methods defined, we assume the user controls the path and we just proxy the raw request
|
69
|
+
return (0, web_1.proxyHttpRequest)(req, res, opts);
|
70
|
+
}
|
66
71
|
let { consumerMethod, providerMethod } = resolveMethods(req, opts);
|
67
72
|
const consumerPathTemplate = (0, pathTemplateParser_1.pathTemplateParser)(consumerMethod.path);
|
68
73
|
const providerPathTemplate = (0, pathTemplateParser_1.pathTemplateParser)(providerMethod.path);
|
@@ -20,8 +20,8 @@ function proxyHttpRequest(req, res, opts) {
|
|
20
20
|
delete requestHeaders['connection'];
|
21
21
|
delete requestHeaders['host'];
|
22
22
|
delete requestHeaders['origin'];
|
23
|
-
const sourceBasePath = opts.consumerResource.spec.path;
|
24
|
-
const targetBasePath = opts.providerResource.spec.path;
|
23
|
+
const sourceBasePath = opts.consumerResource.spec.path ?? '/';
|
24
|
+
const targetBasePath = opts.providerResource.spec.path ?? '/';
|
25
25
|
let path = opts.consumerPath;
|
26
26
|
if (opts.consumerPath.startsWith(sourceBasePath)) {
|
27
27
|
path = path.replace(sourceBasePath, targetBasePath);
|
@@ -34,7 +34,7 @@ const DOCKER_ENV_VARS = [
|
|
34
34
|
`KAPETA_LOCAL_SERVER=0.0.0.0`,
|
35
35
|
`KAPETA_LOCAL_CLUSTER_HOST=${types_1.DOCKER_HOST_INTERNAL}`,
|
36
36
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
37
|
-
`KAPETA_ENVIRONMENT_PLATFORM=${node_os_1.default.platform()}
|
37
|
+
`KAPETA_ENVIRONMENT_PLATFORM=${node_os_1.default.platform()}`,
|
38
38
|
];
|
39
39
|
async function getProvider(uri) {
|
40
40
|
const providers = await definitionsManager_1.definitionsManager.getProviderDefinitions();
|
@@ -172,8 +172,15 @@ class BlockInstanceRunner {
|
|
172
172
|
if (!fs_extra_1.default.existsSync(dockerFile)) {
|
173
173
|
throw new Error(`Dockerfile not found at: ${dockerFile}`);
|
174
174
|
}
|
175
|
-
|
176
|
-
|
175
|
+
console.log('Building docker image from Dockerfile "%s": %s ', dockerFile, dockerImage);
|
176
|
+
try {
|
177
|
+
const task = containerManager_1.containerManager.buildDockerImage(dockerFile, dockerImage);
|
178
|
+
await task.wait();
|
179
|
+
}
|
180
|
+
catch (err) {
|
181
|
+
throw new Error(`Error building docker image: ${err}`);
|
182
|
+
}
|
183
|
+
console.log('Docker images was build from file "%s": %s', dockerFile, dockerImage);
|
177
184
|
}
|
178
185
|
const containerName = await (0, utils_1.getBlockInstanceContainerName)(this._systemId, blockInstance.id, targetKindUri.id);
|
179
186
|
const startCmd = localContainer.handlers?.onCreate ? localContainer.handlers.onCreate : '';
|
@@ -205,7 +212,7 @@ class BlockInstanceRunner {
|
|
205
212
|
...dockerOpts,
|
206
213
|
Image: dockerImage,
|
207
214
|
name: containerName,
|
208
|
-
WorkingDir: workingDir,
|
215
|
+
WorkingDir: isDockerImage ? workingDir : undefined,
|
209
216
|
Labels: {
|
210
217
|
...customLabels,
|
211
218
|
instance: blockInstance.id,
|
@@ -41,8 +41,8 @@ class InternalConfigProvider {
|
|
41
41
|
getInstanceId() {
|
42
42
|
return this.instanceId;
|
43
43
|
}
|
44
|
-
getServerPort(portType) {
|
45
|
-
return
|
44
|
+
async getServerPort(portType) {
|
45
|
+
return '80';
|
46
46
|
}
|
47
47
|
async getServiceAddress(serviceName, portType) {
|
48
48
|
return serviceManager_1.serviceManager.getConsumerAddress(this.systemId, this.instanceId, serviceName, portType, this.environment);
|
package/package.json
CHANGED
package/src/containerManager.ts
CHANGED
@@ -306,6 +306,11 @@ class ContainerManager {
|
|
306
306
|
tag = 'latest';
|
307
307
|
}
|
308
308
|
|
309
|
+
if (tag === 'local') {
|
310
|
+
// Local image - no need to pull
|
311
|
+
return false;
|
312
|
+
}
|
313
|
+
|
309
314
|
const imageTagList = (await this.docker().listImages({}))
|
310
315
|
.filter((imageData) => !!imageData.RepoTags)
|
311
316
|
.map((imageData) => imageData.RepoTags as string[]);
|
@@ -786,20 +791,23 @@ class ContainerManager {
|
|
786
791
|
buildDockerImage(dockerFile: string, imageName: string) {
|
787
792
|
const taskName = `Building docker image: ${imageName}`;
|
788
793
|
const processor = async (task: Task) => {
|
789
|
-
const
|
790
|
-
const
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
);
|
794
|
+
const baseDir = Path.dirname(dockerFile);
|
795
|
+
const entries = await FSExtra.readdir(baseDir);
|
796
|
+
const contextInfo = {
|
797
|
+
context: Path.dirname(dockerFile),
|
798
|
+
src: entries,
|
799
|
+
};
|
800
|
+
|
801
|
+
const stream = await this.docker().buildImage(contextInfo, {
|
802
|
+
t: imageName,
|
803
|
+
dockerfile: Path.basename(dockerFile),
|
804
|
+
});
|
800
805
|
|
801
806
|
await processJsonStream<string>(`image:build:${imageName}`, stream, (data) => {
|
802
|
-
if (data.
|
807
|
+
if (data.error) {
|
808
|
+
task.future.reject(new Error(data.error));
|
809
|
+
task.addLog(data.error, 'ERROR');
|
810
|
+
} else if (data.stream) {
|
803
811
|
// Emit raw output to the task log
|
804
812
|
task.addLog(data.stream);
|
805
813
|
}
|
package/src/proxy/types/rest.ts
CHANGED
@@ -15,6 +15,7 @@ import { ProxyRequestInfo, SimpleRequest, StringMap } from '../../types';
|
|
15
15
|
import { StringBodyRequest } from '../../middleware/stringBody';
|
16
16
|
import { Resource } from '@kapeta/schemas';
|
17
17
|
import { stringify } from 'qs';
|
18
|
+
import { proxyHttpRequest } from './web';
|
18
19
|
|
19
20
|
export function getRestMethodId(restResource: Resource, httpMethod: string, httpPath: string) {
|
20
21
|
return _.findKey(restResource.spec.methods, (method) => {
|
@@ -86,6 +87,10 @@ function resolveMethods(req: Request, opts: ProxyRequestInfo) {
|
|
86
87
|
}
|
87
88
|
|
88
89
|
export function proxyRestRequest(req: StringBodyRequest, res: Response, opts: ProxyRequestInfo) {
|
90
|
+
if (_.isEmpty(opts.consumerResource.spec.methods) && _.isEmpty(opts.providerResource.spec.methods)) {
|
91
|
+
// If there are no methods defined, we assume the user controls the path and we just proxy the raw request
|
92
|
+
return proxyHttpRequest(req, res, opts);
|
93
|
+
}
|
89
94
|
let { consumerMethod, providerMethod } = resolveMethods(req, opts);
|
90
95
|
|
91
96
|
const consumerPathTemplate = pathTemplateParser(consumerMethod.path);
|
package/src/proxy/types/web.ts
CHANGED
@@ -21,8 +21,8 @@ export function proxyHttpRequest(req: StringBodyRequest, res: Response, opts: Pr
|
|
21
21
|
delete requestHeaders['host'];
|
22
22
|
delete requestHeaders['origin'];
|
23
23
|
|
24
|
-
const sourceBasePath = opts.consumerResource.spec.path;
|
25
|
-
const targetBasePath = opts.providerResource.spec.path;
|
24
|
+
const sourceBasePath = opts.consumerResource.spec.path ?? '/';
|
25
|
+
const targetBasePath = opts.providerResource.spec.path ?? '/';
|
26
26
|
let path = opts.consumerPath;
|
27
27
|
if (opts.consumerPath.startsWith(sourceBasePath)) {
|
28
28
|
path = path.replace(sourceBasePath, targetBasePath);
|
@@ -48,7 +48,7 @@ const DOCKER_ENV_VARS = [
|
|
48
48
|
`KAPETA_LOCAL_SERVER=0.0.0.0`,
|
49
49
|
`KAPETA_LOCAL_CLUSTER_HOST=${DOCKER_HOST_INTERNAL}`,
|
50
50
|
`KAPETA_ENVIRONMENT_TYPE=docker`,
|
51
|
-
`KAPETA_ENVIRONMENT_PLATFORM=${OS.platform()}
|
51
|
+
`KAPETA_ENVIRONMENT_PLATFORM=${OS.platform()}`,
|
52
52
|
];
|
53
53
|
|
54
54
|
async function getProvider(uri: KapetaURI) {
|
@@ -231,8 +231,16 @@ export class BlockInstanceRunner {
|
|
231
231
|
if (!FSExtra.existsSync(dockerFile)) {
|
232
232
|
throw new Error(`Dockerfile not found at: ${dockerFile}`);
|
233
233
|
}
|
234
|
-
|
235
|
-
|
234
|
+
|
235
|
+
console.log('Building docker image from Dockerfile "%s": %s ', dockerFile, dockerImage);
|
236
|
+
try {
|
237
|
+
const task = containerManager.buildDockerImage(dockerFile, dockerImage);
|
238
|
+
await task.wait();
|
239
|
+
} catch (err: any) {
|
240
|
+
throw new Error(`Error building docker image: ${err}`);
|
241
|
+
}
|
242
|
+
|
243
|
+
console.log('Docker images was build from file "%s": %s', dockerFile, dockerImage);
|
236
244
|
}
|
237
245
|
|
238
246
|
const containerName = await getBlockInstanceContainerName(this._systemId, blockInstance.id, targetKindUri.id);
|
@@ -275,7 +283,7 @@ export class BlockInstanceRunner {
|
|
275
283
|
...dockerOpts,
|
276
284
|
Image: dockerImage,
|
277
285
|
name: containerName,
|
278
|
-
WorkingDir: workingDir,
|
286
|
+
WorkingDir: isDockerImage ? workingDir : undefined,
|
279
287
|
Labels: {
|
280
288
|
...customLabels,
|
281
289
|
instance: blockInstance.id,
|
@@ -59,8 +59,8 @@ export class InternalConfigProvider implements ConfigProvider {
|
|
59
59
|
getInstanceId(): string {
|
60
60
|
return this.instanceId;
|
61
61
|
}
|
62
|
-
getServerPort(portType?: string | undefined): Promise<string> {
|
63
|
-
return
|
62
|
+
async getServerPort(portType?: string | undefined): Promise<string> {
|
63
|
+
return '80';
|
64
64
|
}
|
65
65
|
async getServiceAddress(serviceName: string, portType: string): Promise<string | null> {
|
66
66
|
return serviceManager.getConsumerAddress(
|