@kapeta/local-cluster-service 0.19.4 → 0.19.6
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/proxy/types/rest.d.ts +2 -0
- package/dist/cjs/src/proxy/types/rest.js +2 -1
- package/dist/cjs/src/utils/BlockInstanceRunner.js +10 -1
- package/dist/cjs/src/utils/pathTemplateParser.js +13 -3
- package/dist/cjs/test/proxy/types/rest.test.d.ts +1 -0
- package/dist/cjs/test/proxy/types/rest.test.js +45 -0
- package/dist/cjs/test/utils/pathTemplateParser.test.d.ts +1 -0
- package/dist/cjs/test/utils/pathTemplateParser.test.js +23 -0
- package/dist/esm/src/proxy/types/rest.d.ts +2 -0
- package/dist/esm/src/proxy/types/rest.js +2 -1
- package/dist/esm/src/utils/BlockInstanceRunner.js +10 -1
- package/dist/esm/src/utils/pathTemplateParser.js +13 -3
- package/dist/esm/test/proxy/types/rest.test.d.ts +1 -0
- package/dist/esm/test/proxy/types/rest.test.js +45 -0
- package/dist/esm/test/utils/pathTemplateParser.test.d.ts +1 -0
- package/dist/esm/test/utils/pathTemplateParser.test.js +23 -0
- package/jest.config.js +8 -0
- package/package.json +5 -2
- package/src/proxy/types/rest.ts +1 -1
- package/src/utils/BlockInstanceRunner.ts +11 -1
- package/src/utils/pathTemplateParser.ts +17 -3
- package/test/proxy/types/rest.test.ts +49 -0
- package/test/utils/pathTemplateParser.test.ts +24 -0
- package/tsconfig.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [0.19.6](https://github.com/kapetacom/local-cluster-service/compare/v0.19.5...v0.19.6) (2023-09-08)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Allow more docker opts from language targets ([#71](https://github.com/kapetacom/local-cluster-service/issues/71)) ([dd9e9bb](https://github.com/kapetacom/local-cluster-service/commit/dd9e9bb91fb6aa6d082b1864b268234ece9b8920))
|
7
|
+
|
8
|
+
## [0.19.5](https://github.com/kapetacom/local-cluster-service/compare/v0.19.4...v0.19.5) (2023-09-07)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* Handle query and hash in path matching ([#70](https://github.com/kapetacom/local-cluster-service/issues/70)) ([e743cf8](https://github.com/kapetacom/local-cluster-service/commit/e743cf80c6754f43c948fd25967f04808429a784))
|
14
|
+
|
1
15
|
## [0.19.4](https://github.com/kapetacom/local-cluster-service/compare/v0.19.3...v0.19.4) (2023-09-05)
|
2
16
|
|
3
17
|
|
@@ -1,4 +1,6 @@
|
|
1
1
|
import { Response } from 'express';
|
2
2
|
import { ProxyRequestInfo } from '../../types';
|
3
3
|
import { StringBodyRequest } from '../../middleware/stringBody';
|
4
|
+
import { Resource } from '@kapeta/schemas';
|
5
|
+
export declare function getRestMethodId(restResource: Resource, httpMethod: string, httpPath: string): string | undefined;
|
4
6
|
export declare function proxyRestRequest(req: StringBodyRequest, res: Response, opts: ProxyRequestInfo): void;
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.proxyRestRequest = void 0;
|
6
|
+
exports.proxyRestRequest = exports.getRestMethodId = void 0;
|
7
7
|
const lodash_1 = __importDefault(require("lodash"));
|
8
8
|
const request_1 = __importDefault(require("request"));
|
9
9
|
const path_1 = __importDefault(require("path"));
|
@@ -24,6 +24,7 @@ function getRestMethodId(restResource, httpMethod, httpPath) {
|
|
24
24
|
return pathTemplate.matches(httpPath);
|
25
25
|
});
|
26
26
|
}
|
27
|
+
exports.getRestMethodId = getRestMethodId;
|
27
28
|
/**
|
28
29
|
*
|
29
30
|
* @param req {Request}
|
@@ -135,22 +135,31 @@ class BlockInstanceRunner {
|
|
135
135
|
const dockerOpts = localContainer.options ?? {};
|
136
136
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
137
137
|
const workingDir = localContainer.workingDir ? localContainer.workingDir : '/workspace';
|
138
|
+
const customHostConfigs = localContainer.HostConfig ?? {};
|
139
|
+
const customLabels = localContainer.Labels ?? {};
|
140
|
+
const customEnvs = localContainer.Env ?? [];
|
141
|
+
delete localContainer.HostConfig;
|
142
|
+
delete localContainer.Labels;
|
143
|
+
delete localContainer.Env;
|
138
144
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
139
145
|
let HealthCheck = undefined;
|
140
146
|
if (localContainer.healthcheck) {
|
141
147
|
HealthCheck = containerManager_1.containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
142
148
|
}
|
143
149
|
return this.ensureContainer({
|
150
|
+
...dockerOpts,
|
144
151
|
Image: dockerImage,
|
145
152
|
name: containerName,
|
146
153
|
WorkingDir: workingDir,
|
147
154
|
Labels: {
|
155
|
+
...customLabels,
|
148
156
|
instance: blockInstance.id,
|
149
157
|
},
|
150
158
|
HealthCheck,
|
151
159
|
ExposedPorts,
|
152
160
|
Cmd: startCmd ? startCmd.split(/\s+/g) : [],
|
153
161
|
Env: [
|
162
|
+
...customEnvs,
|
154
163
|
...DOCKER_ENV_VARS,
|
155
164
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
156
165
|
...Object.entries({
|
@@ -159,13 +168,13 @@ class BlockInstanceRunner {
|
|
159
168
|
}).map(([key, value]) => `${key}=${value}`),
|
160
169
|
],
|
161
170
|
HostConfig: {
|
171
|
+
...customHostConfigs,
|
162
172
|
Binds: [
|
163
173
|
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${homeDir}/.kapeta`,
|
164
174
|
`${(0, containerManager_1.toLocalBindVolume)(baseDir)}:${workingDir}`,
|
165
175
|
],
|
166
176
|
PortBindings,
|
167
177
|
},
|
168
|
-
...dockerOpts,
|
169
178
|
});
|
170
179
|
}
|
171
180
|
async _startDockerProcess(blockInstance, blockInfo, env, assetVersion) {
|
@@ -3,6 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pathTemplateParser = exports.PathTemplate = void 0;
|
4
4
|
const TYPE_VARIABLE = 'variable';
|
5
5
|
const TYPE_PATH = 'path';
|
6
|
+
function normalizePath(path) {
|
7
|
+
if (!path.startsWith('/')) {
|
8
|
+
path = '/' + path;
|
9
|
+
}
|
10
|
+
if (path.includes('#')) {
|
11
|
+
path = path.split('#')[0];
|
12
|
+
}
|
13
|
+
if (path.includes('?')) {
|
14
|
+
path = path.split('?')[0];
|
15
|
+
}
|
16
|
+
return path;
|
17
|
+
}
|
6
18
|
/**
|
7
19
|
* A path template is a string that can be used to match a path and extract variables from it.
|
8
20
|
*
|
@@ -62,9 +74,7 @@ class PathTemplate {
|
|
62
74
|
return this.parse(path) !== null;
|
63
75
|
}
|
64
76
|
parse(path) {
|
65
|
-
|
66
|
-
path = '/' + path;
|
67
|
-
}
|
77
|
+
path = normalizePath(path);
|
68
78
|
const values = {};
|
69
79
|
for (let i = 0; i < this._parts.length; i++) {
|
70
80
|
const part = this._parts[i];
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const rest_1 = require("../../../src/proxy/types/rest");
|
4
|
+
describe('getRestMethodId', () => {
|
5
|
+
it('should match @Query in url', () => {
|
6
|
+
const restResource = new TestResource();
|
7
|
+
const restMethodId = (0, rest_1.getRestMethodId)(restResource, "POST", "/names?name=Ib");
|
8
|
+
expect(restMethodId).toBeDefined();
|
9
|
+
});
|
10
|
+
});
|
11
|
+
class TestResource {
|
12
|
+
kind = "";
|
13
|
+
metadata = new TestResourceMetaData();
|
14
|
+
get spec() {
|
15
|
+
return {
|
16
|
+
methods: [
|
17
|
+
{
|
18
|
+
responseType: {
|
19
|
+
ref: "Name[]"
|
20
|
+
},
|
21
|
+
method: "GET",
|
22
|
+
path: "/names",
|
23
|
+
arguments: {}
|
24
|
+
},
|
25
|
+
{
|
26
|
+
responseType: {
|
27
|
+
ref: "Name"
|
28
|
+
},
|
29
|
+
method: "POST",
|
30
|
+
path: "/names",
|
31
|
+
arguments: {
|
32
|
+
name: {
|
33
|
+
type: "string",
|
34
|
+
transport: "QUERY"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
]
|
39
|
+
};
|
40
|
+
}
|
41
|
+
;
|
42
|
+
}
|
43
|
+
class TestResourceMetaData {
|
44
|
+
name = "";
|
45
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const pathTemplateParser_1 = require("../../src/utils/pathTemplateParser");
|
4
|
+
describe('pathTemplateParser', () => {
|
5
|
+
it('must return parameters for query parameters from parse', () => {
|
6
|
+
const template = new pathTemplateParser_1.PathTemplate('/names');
|
7
|
+
const parse = template.parse('/names?name=Ib#test');
|
8
|
+
console.log(parse);
|
9
|
+
expect(parse).toBeTruthy();
|
10
|
+
});
|
11
|
+
it('must return parameters defined in url', () => {
|
12
|
+
const template = new pathTemplateParser_1.PathTemplate('/names/{identityId}');
|
13
|
+
const parse = template.parse('/names/idn_xxyyzz');
|
14
|
+
expect(parse).toBeTruthy();
|
15
|
+
expect(parse).toMatchObject({ identityId: 'idn_xxyyzz' });
|
16
|
+
});
|
17
|
+
it('must return parameters defined in url regardless of query parameters', () => {
|
18
|
+
const template = new pathTemplateParser_1.PathTemplate('/names/{identityId}');
|
19
|
+
const parse = template.parse('/names/idn_xxyyzz?name=Ib#test');
|
20
|
+
expect(parse).toBeTruthy();
|
21
|
+
expect(parse).toMatchObject({ identityId: 'idn_xxyyzz' });
|
22
|
+
});
|
23
|
+
});
|
@@ -1,4 +1,6 @@
|
|
1
1
|
import { Response } from 'express';
|
2
2
|
import { ProxyRequestInfo } from '../../types';
|
3
3
|
import { StringBodyRequest } from '../../middleware/stringBody';
|
4
|
+
import { Resource } from '@kapeta/schemas';
|
5
|
+
export declare function getRestMethodId(restResource: Resource, httpMethod: string, httpPath: string): string | undefined;
|
4
6
|
export declare function proxyRestRequest(req: StringBodyRequest, res: Response, opts: ProxyRequestInfo): void;
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.proxyRestRequest = void 0;
|
6
|
+
exports.proxyRestRequest = exports.getRestMethodId = void 0;
|
7
7
|
const lodash_1 = __importDefault(require("lodash"));
|
8
8
|
const request_1 = __importDefault(require("request"));
|
9
9
|
const path_1 = __importDefault(require("path"));
|
@@ -24,6 +24,7 @@ function getRestMethodId(restResource, httpMethod, httpPath) {
|
|
24
24
|
return pathTemplate.matches(httpPath);
|
25
25
|
});
|
26
26
|
}
|
27
|
+
exports.getRestMethodId = getRestMethodId;
|
27
28
|
/**
|
28
29
|
*
|
29
30
|
* @param req {Request}
|
@@ -135,22 +135,31 @@ class BlockInstanceRunner {
|
|
135
135
|
const dockerOpts = localContainer.options ?? {};
|
136
136
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
137
137
|
const workingDir = localContainer.workingDir ? localContainer.workingDir : '/workspace';
|
138
|
+
const customHostConfigs = localContainer.HostConfig ?? {};
|
139
|
+
const customLabels = localContainer.Labels ?? {};
|
140
|
+
const customEnvs = localContainer.Env ?? [];
|
141
|
+
delete localContainer.HostConfig;
|
142
|
+
delete localContainer.Labels;
|
143
|
+
delete localContainer.Env;
|
138
144
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
139
145
|
let HealthCheck = undefined;
|
140
146
|
if (localContainer.healthcheck) {
|
141
147
|
HealthCheck = containerManager_1.containerManager.toDockerHealth({ cmd: localContainer.healthcheck });
|
142
148
|
}
|
143
149
|
return this.ensureContainer({
|
150
|
+
...dockerOpts,
|
144
151
|
Image: dockerImage,
|
145
152
|
name: containerName,
|
146
153
|
WorkingDir: workingDir,
|
147
154
|
Labels: {
|
155
|
+
...customLabels,
|
148
156
|
instance: blockInstance.id,
|
149
157
|
},
|
150
158
|
HealthCheck,
|
151
159
|
ExposedPorts,
|
152
160
|
Cmd: startCmd ? startCmd.split(/\s+/g) : [],
|
153
161
|
Env: [
|
162
|
+
...customEnvs,
|
154
163
|
...DOCKER_ENV_VARS,
|
155
164
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService_1.clusterService.getClusterServicePort()}`,
|
156
165
|
...Object.entries({
|
@@ -159,13 +168,13 @@ class BlockInstanceRunner {
|
|
159
168
|
}).map(([key, value]) => `${key}=${value}`),
|
160
169
|
],
|
161
170
|
HostConfig: {
|
171
|
+
...customHostConfigs,
|
162
172
|
Binds: [
|
163
173
|
`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${homeDir}/.kapeta`,
|
164
174
|
`${(0, containerManager_1.toLocalBindVolume)(baseDir)}:${workingDir}`,
|
165
175
|
],
|
166
176
|
PortBindings,
|
167
177
|
},
|
168
|
-
...dockerOpts,
|
169
178
|
});
|
170
179
|
}
|
171
180
|
async _startDockerProcess(blockInstance, blockInfo, env, assetVersion) {
|
@@ -3,6 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pathTemplateParser = exports.PathTemplate = void 0;
|
4
4
|
const TYPE_VARIABLE = 'variable';
|
5
5
|
const TYPE_PATH = 'path';
|
6
|
+
function normalizePath(path) {
|
7
|
+
if (!path.startsWith('/')) {
|
8
|
+
path = '/' + path;
|
9
|
+
}
|
10
|
+
if (path.includes('#')) {
|
11
|
+
path = path.split('#')[0];
|
12
|
+
}
|
13
|
+
if (path.includes('?')) {
|
14
|
+
path = path.split('?')[0];
|
15
|
+
}
|
16
|
+
return path;
|
17
|
+
}
|
6
18
|
/**
|
7
19
|
* A path template is a string that can be used to match a path and extract variables from it.
|
8
20
|
*
|
@@ -62,9 +74,7 @@ class PathTemplate {
|
|
62
74
|
return this.parse(path) !== null;
|
63
75
|
}
|
64
76
|
parse(path) {
|
65
|
-
|
66
|
-
path = '/' + path;
|
67
|
-
}
|
77
|
+
path = normalizePath(path);
|
68
78
|
const values = {};
|
69
79
|
for (let i = 0; i < this._parts.length; i++) {
|
70
80
|
const part = this._parts[i];
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,45 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const rest_1 = require("../../../src/proxy/types/rest");
|
4
|
+
describe('getRestMethodId', () => {
|
5
|
+
it('should match @Query in url', () => {
|
6
|
+
const restResource = new TestResource();
|
7
|
+
const restMethodId = (0, rest_1.getRestMethodId)(restResource, "POST", "/names?name=Ib");
|
8
|
+
expect(restMethodId).toBeDefined();
|
9
|
+
});
|
10
|
+
});
|
11
|
+
class TestResource {
|
12
|
+
kind = "";
|
13
|
+
metadata = new TestResourceMetaData();
|
14
|
+
get spec() {
|
15
|
+
return {
|
16
|
+
methods: [
|
17
|
+
{
|
18
|
+
responseType: {
|
19
|
+
ref: "Name[]"
|
20
|
+
},
|
21
|
+
method: "GET",
|
22
|
+
path: "/names",
|
23
|
+
arguments: {}
|
24
|
+
},
|
25
|
+
{
|
26
|
+
responseType: {
|
27
|
+
ref: "Name"
|
28
|
+
},
|
29
|
+
method: "POST",
|
30
|
+
path: "/names",
|
31
|
+
arguments: {
|
32
|
+
name: {
|
33
|
+
type: "string",
|
34
|
+
transport: "QUERY"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
]
|
39
|
+
};
|
40
|
+
}
|
41
|
+
;
|
42
|
+
}
|
43
|
+
class TestResourceMetaData {
|
44
|
+
name = "";
|
45
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
const pathTemplateParser_1 = require("../../src/utils/pathTemplateParser");
|
4
|
+
describe('pathTemplateParser', () => {
|
5
|
+
it('must return parameters for query parameters from parse', () => {
|
6
|
+
const template = new pathTemplateParser_1.PathTemplate('/names');
|
7
|
+
const parse = template.parse('/names?name=Ib#test');
|
8
|
+
console.log(parse);
|
9
|
+
expect(parse).toBeTruthy();
|
10
|
+
});
|
11
|
+
it('must return parameters defined in url', () => {
|
12
|
+
const template = new pathTemplateParser_1.PathTemplate('/names/{identityId}');
|
13
|
+
const parse = template.parse('/names/idn_xxyyzz');
|
14
|
+
expect(parse).toBeTruthy();
|
15
|
+
expect(parse).toMatchObject({ identityId: 'idn_xxyyzz' });
|
16
|
+
});
|
17
|
+
it('must return parameters defined in url regardless of query parameters', () => {
|
18
|
+
const template = new pathTemplateParser_1.PathTemplate('/names/{identityId}');
|
19
|
+
const parse = template.parse('/names/idn_xxyyzz?name=Ib#test');
|
20
|
+
expect(parse).toBeTruthy();
|
21
|
+
expect(parse).toMatchObject({ identityId: 'idn_xxyyzz' });
|
22
|
+
});
|
23
|
+
});
|
package/jest.config.js
ADDED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@kapeta/local-cluster-service",
|
3
|
-
"version": "0.19.
|
3
|
+
"version": "0.19.6",
|
4
4
|
"description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
|
5
5
|
"type": "commonjs",
|
6
6
|
"exports": {
|
@@ -32,7 +32,7 @@
|
|
32
32
|
"scripts": {
|
33
33
|
"start": "node ./dist/cjs/start.js",
|
34
34
|
"dev": "nodemon -e js,ts,json ./start.ts",
|
35
|
-
"test": "
|
35
|
+
"test": "jest",
|
36
36
|
"clean": "rm -rf ./dist",
|
37
37
|
"build:esm": "tsc --module nodenext --moduleResolution nodenext --outDir ./dist/esm && echo '{\"type\":\"module\"}' > ./dist/esm/package.json",
|
38
38
|
"build:cjs": "tsc --outDir ./dist/cjs && echo '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json",
|
@@ -80,6 +80,7 @@
|
|
80
80
|
"@types/fs-extra": "^11.0.1",
|
81
81
|
"@types/glob": "^8.1.0",
|
82
82
|
"@types/gunzip-maybe": "^1.4.0",
|
83
|
+
"@types/jest": "^29.5.4",
|
83
84
|
"@types/lodash": "^4.14.195",
|
84
85
|
"@types/md5": "^2.3.2",
|
85
86
|
"@types/node": "^20.5.8",
|
@@ -88,8 +89,10 @@
|
|
88
89
|
"@types/tar-stream": "^2.2.2",
|
89
90
|
"eslint": "^8.42.0",
|
90
91
|
"eslint-config-prettier": "^8.8.0",
|
92
|
+
"jest": "^29.6.4",
|
91
93
|
"nodemon": "^2.0.2",
|
92
94
|
"prettier": "^2.8.8",
|
95
|
+
"ts-jest": "^29.1.1",
|
93
96
|
"ts-node": "^10.9.1"
|
94
97
|
},
|
95
98
|
"prettier": "@kapeta/prettier-config",
|
package/src/proxy/types/rest.ts
CHANGED
@@ -10,7 +10,7 @@ import { ProxyRequestInfo, SimpleRequest, StringMap } from '../../types';
|
|
10
10
|
import { StringBodyRequest } from '../../middleware/stringBody';
|
11
11
|
import { Resource } from '@kapeta/schemas';
|
12
12
|
|
13
|
-
function getRestMethodId(restResource: Resource, httpMethod: string, httpPath: string) {
|
13
|
+
export function getRestMethodId(restResource: Resource, httpMethod: string, httpPath: string) {
|
14
14
|
return _.findKey(restResource.spec.methods, (method) => {
|
15
15
|
let methodType = method.method ? method.method.toUpperCase() : 'GET';
|
16
16
|
|
@@ -171,6 +171,13 @@ export class BlockInstanceRunner {
|
|
171
171
|
const homeDir = localContainer.userHome ? localContainer.userHome : '/root';
|
172
172
|
const workingDir = localContainer.workingDir ? localContainer.workingDir : '/workspace';
|
173
173
|
|
174
|
+
const customHostConfigs = localContainer.HostConfig ?? {};
|
175
|
+
const customLabels = localContainer.Labels ?? {};
|
176
|
+
const customEnvs = localContainer.Env ?? [];
|
177
|
+
delete localContainer.HostConfig;
|
178
|
+
delete localContainer.Labels;
|
179
|
+
delete localContainer.Env;
|
180
|
+
|
174
181
|
const { PortBindings, ExposedPorts, addonEnv } = await this.getDockerPortBindings(blockInstance, assetVersion);
|
175
182
|
|
176
183
|
let HealthCheck = undefined;
|
@@ -179,16 +186,19 @@ export class BlockInstanceRunner {
|
|
179
186
|
}
|
180
187
|
|
181
188
|
return this.ensureContainer({
|
189
|
+
...dockerOpts,
|
182
190
|
Image: dockerImage,
|
183
191
|
name: containerName,
|
184
192
|
WorkingDir: workingDir,
|
185
193
|
Labels: {
|
194
|
+
...customLabels,
|
186
195
|
instance: blockInstance.id,
|
187
196
|
},
|
188
197
|
HealthCheck,
|
189
198
|
ExposedPorts,
|
190
199
|
Cmd: startCmd ? startCmd.split(/\s+/g) : [],
|
191
200
|
Env: [
|
201
|
+
...customEnvs,
|
192
202
|
...DOCKER_ENV_VARS,
|
193
203
|
`KAPETA_LOCAL_CLUSTER_PORT=${clusterService.getClusterServicePort()}`,
|
194
204
|
...Object.entries({
|
@@ -197,13 +207,13 @@ export class BlockInstanceRunner {
|
|
197
207
|
}).map(([key, value]) => `${key}=${value}`),
|
198
208
|
],
|
199
209
|
HostConfig: {
|
210
|
+
...customHostConfigs,
|
200
211
|
Binds: [
|
201
212
|
`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${homeDir}/.kapeta`,
|
202
213
|
`${toLocalBindVolume(baseDir)}:${workingDir}`,
|
203
214
|
],
|
204
215
|
PortBindings,
|
205
216
|
},
|
206
|
-
...dockerOpts,
|
207
217
|
});
|
208
218
|
}
|
209
219
|
|
@@ -3,6 +3,22 @@ import { StringMap } from '../types';
|
|
3
3
|
const TYPE_VARIABLE = 'variable';
|
4
4
|
const TYPE_PATH = 'path';
|
5
5
|
|
6
|
+
function normalizePath(path: string) {
|
7
|
+
if (!path.startsWith('/')) {
|
8
|
+
path = '/' + path;
|
9
|
+
}
|
10
|
+
|
11
|
+
if (path.includes('#')) {
|
12
|
+
path = path.split('#')[0];
|
13
|
+
}
|
14
|
+
|
15
|
+
if (path.includes('?')) {
|
16
|
+
path = path.split('?')[0];
|
17
|
+
}
|
18
|
+
|
19
|
+
return path;
|
20
|
+
}
|
21
|
+
|
6
22
|
/**
|
7
23
|
* A path template is a string that can be used to match a path and extract variables from it.
|
8
24
|
*
|
@@ -71,9 +87,7 @@ export class PathTemplate {
|
|
71
87
|
}
|
72
88
|
|
73
89
|
parse(path: string) {
|
74
|
-
|
75
|
-
path = '/' + path;
|
76
|
-
}
|
90
|
+
path = normalizePath(path);
|
77
91
|
|
78
92
|
const values: StringMap = {};
|
79
93
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import {getRestMethodId} from "../../../src/proxy/types/rest";
|
2
|
+
import {Resource, ResourceMetadata} from '@kapeta/schemas';
|
3
|
+
|
4
|
+
describe('getRestMethodId', () => {
|
5
|
+
it('should match @Query in url', () => {
|
6
|
+
const restResource = new TestResource();
|
7
|
+
|
8
|
+
const restMethodId = getRestMethodId(restResource, "POST", "/names?name=Ib");
|
9
|
+
expect(restMethodId).toBeDefined();
|
10
|
+
})
|
11
|
+
});
|
12
|
+
|
13
|
+
class TestResource implements Resource {
|
14
|
+
kind = "";
|
15
|
+
metadata = new TestResourceMetaData();
|
16
|
+
|
17
|
+
get spec(): { [p: string]: any } {
|
18
|
+
return {
|
19
|
+
methods: [
|
20
|
+
{
|
21
|
+
responseType: {
|
22
|
+
ref: "Name[]"
|
23
|
+
},
|
24
|
+
method: "GET",
|
25
|
+
path: "/names",
|
26
|
+
arguments: {}
|
27
|
+
},
|
28
|
+
{
|
29
|
+
responseType: {
|
30
|
+
ref: "Name"
|
31
|
+
},
|
32
|
+
method: "POST",
|
33
|
+
path: "/names",
|
34
|
+
arguments: {
|
35
|
+
name: {
|
36
|
+
type: "string",
|
37
|
+
transport: "QUERY"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
]
|
42
|
+
}
|
43
|
+
};
|
44
|
+
}
|
45
|
+
|
46
|
+
class TestResourceMetaData implements ResourceMetadata {
|
47
|
+
[property: string]: any;
|
48
|
+
name: string = "";
|
49
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { PathTemplate } from '../../src/utils/pathTemplateParser';
|
2
|
+
|
3
|
+
describe('pathTemplateParser', () => {
|
4
|
+
it('must return parameters for query parameters from parse', () => {
|
5
|
+
const template = new PathTemplate('/names');
|
6
|
+
const parse = template.parse('/names?name=Ib#test');
|
7
|
+
console.log(parse);
|
8
|
+
expect(parse).toBeTruthy();
|
9
|
+
});
|
10
|
+
|
11
|
+
it('must return parameters defined in url', () => {
|
12
|
+
const template = new PathTemplate('/names/{identityId}');
|
13
|
+
const parse = template.parse('/names/idn_xxyyzz');
|
14
|
+
expect(parse).toBeTruthy();
|
15
|
+
expect(parse).toMatchObject({ identityId: 'idn_xxyyzz' });
|
16
|
+
});
|
17
|
+
|
18
|
+
it('must return parameters defined in url regardless of query parameters', () => {
|
19
|
+
const template = new PathTemplate('/names/{identityId}');
|
20
|
+
const parse = template.parse('/names/idn_xxyyzz?name=Ib#test');
|
21
|
+
expect(parse).toBeTruthy();
|
22
|
+
expect(parse).toMatchObject({ identityId: 'idn_xxyyzz' });
|
23
|
+
});
|
24
|
+
});
|
package/tsconfig.json
CHANGED