@kapeta/local-cluster-service 0.8.2 → 0.9.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 (80) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/definitions.d.ts +1 -1
  3. package/dist/cjs/index.js +3 -3
  4. package/dist/cjs/src/assetManager.js +7 -4
  5. package/dist/cjs/src/attachments/routes.js +4 -4
  6. package/dist/cjs/src/clusterService.js +2 -0
  7. package/dist/cjs/src/codeGeneratorManager.js +3 -3
  8. package/dist/cjs/src/config/routes.js +1 -1
  9. package/dist/cjs/src/configManager.js +13 -1
  10. package/dist/cjs/src/containerManager.d.ts +22 -2
  11. package/dist/cjs/src/containerManager.js +42 -15
  12. package/dist/cjs/src/definitionsManager.d.ts +11 -0
  13. package/dist/cjs/src/definitionsManager.js +44 -0
  14. package/dist/cjs/src/filesystemManager.js +0 -2
  15. package/dist/cjs/src/instanceManager.d.ts +23 -47
  16. package/dist/cjs/src/instanceManager.js +416 -235
  17. package/dist/cjs/src/instances/routes.js +23 -14
  18. package/dist/cjs/src/middleware/kapeta.js +7 -0
  19. package/dist/cjs/src/networkManager.js +6 -0
  20. package/dist/cjs/src/operatorManager.js +8 -4
  21. package/dist/cjs/src/providerManager.js +3 -3
  22. package/dist/cjs/src/repositoryManager.js +7 -3
  23. package/dist/cjs/src/serviceManager.js +5 -0
  24. package/dist/cjs/src/types.d.ts +39 -13
  25. package/dist/cjs/src/types.js +28 -0
  26. package/dist/cjs/src/utils/BlockInstanceRunner.d.ts +3 -3
  27. package/dist/cjs/src/utils/BlockInstanceRunner.js +28 -29
  28. package/dist/cjs/src/utils/utils.d.ts +2 -0
  29. package/dist/cjs/src/utils/utils.js +18 -2
  30. package/dist/esm/index.js +4 -4
  31. package/dist/esm/src/assetManager.js +7 -4
  32. package/dist/esm/src/attachments/routes.js +5 -5
  33. package/dist/esm/src/clusterService.js +2 -0
  34. package/dist/esm/src/codeGeneratorManager.js +3 -3
  35. package/dist/esm/src/config/routes.js +1 -1
  36. package/dist/esm/src/configManager.js +13 -1
  37. package/dist/esm/src/containerManager.d.ts +22 -2
  38. package/dist/esm/src/containerManager.js +41 -14
  39. package/dist/esm/src/definitionsManager.d.ts +11 -0
  40. package/dist/esm/src/definitionsManager.js +38 -0
  41. package/dist/esm/src/filesystemManager.js +0 -2
  42. package/dist/esm/src/instanceManager.d.ts +23 -47
  43. package/dist/esm/src/instanceManager.js +416 -236
  44. package/dist/esm/src/instances/routes.js +23 -14
  45. package/dist/esm/src/middleware/kapeta.js +7 -0
  46. package/dist/esm/src/networkManager.js +6 -0
  47. package/dist/esm/src/operatorManager.js +8 -4
  48. package/dist/esm/src/providerManager.js +3 -3
  49. package/dist/esm/src/repositoryManager.js +7 -3
  50. package/dist/esm/src/serviceManager.js +5 -0
  51. package/dist/esm/src/types.d.ts +39 -13
  52. package/dist/esm/src/types.js +27 -1
  53. package/dist/esm/src/utils/BlockInstanceRunner.d.ts +3 -3
  54. package/dist/esm/src/utils/BlockInstanceRunner.js +29 -30
  55. package/dist/esm/src/utils/utils.d.ts +2 -0
  56. package/dist/esm/src/utils/utils.js +15 -1
  57. package/index.ts +10 -8
  58. package/package.json +2 -1
  59. package/src/assetManager.ts +7 -4
  60. package/src/attachments/routes.ts +8 -8
  61. package/src/clusterService.ts +3 -0
  62. package/src/codeGeneratorManager.ts +3 -2
  63. package/src/config/routes.ts +1 -1
  64. package/src/configManager.ts +13 -1
  65. package/src/containerManager.ts +63 -16
  66. package/src/definitionsManager.ts +54 -0
  67. package/src/filesystemManager.ts +0 -2
  68. package/src/identities/routes.ts +2 -3
  69. package/src/instanceManager.ts +495 -266
  70. package/src/instances/routes.ts +23 -17
  71. package/src/middleware/kapeta.ts +10 -0
  72. package/src/networkManager.ts +6 -0
  73. package/src/operatorManager.ts +11 -6
  74. package/src/providerManager.ts +3 -2
  75. package/src/repositoryManager.ts +14 -10
  76. package/src/serviceManager.ts +6 -0
  77. package/src/storageService.ts +1 -1
  78. package/src/types.ts +44 -14
  79. package/src/utils/BlockInstanceRunner.ts +34 -34
  80. package/src/utils/utils.ts +20 -2
package/index.ts CHANGED
@@ -17,7 +17,7 @@ import AssetsRoutes from './src/assets/routes';
17
17
  import ProviderRoutes from './src/providers/routes';
18
18
  import AttachmentRoutes from './src/attachments/routes';
19
19
  import { getBindHost } from './src/utils/utils';
20
- import request from "request";
20
+ import request from 'request';
21
21
 
22
22
  export type LocalClusterService = HTTP.Server & { host?: string; port?: number };
23
23
 
@@ -40,13 +40,13 @@ function createServer() {
40
40
  res.send({
41
41
  ok: true,
42
42
  dockerStatus: await containerManager.checkAlive(),
43
- socketStatus: socketManager.isAlive()
43
+ socketStatus: socketManager.isAlive(),
44
44
  });
45
45
  });
46
46
 
47
47
  app.get('/ping', async (req, res) => {
48
48
  res.send({
49
- ok: true
49
+ ok: true,
50
50
  });
51
51
  });
52
52
 
@@ -54,7 +54,7 @@ function createServer() {
54
54
  console.error('Invalid request: %s %s', req.method, req.originalUrl);
55
55
  res.status(400).send({
56
56
  ok: false,
57
- error: 'Unknown'
57
+ error: 'Unknown',
58
58
  });
59
59
  });
60
60
 
@@ -84,7 +84,7 @@ export default {
84
84
  return currentServer.port;
85
85
  },
86
86
 
87
- ping: async function(host:string, port:number): Promise<{ ok:boolean }> {
87
+ ping: async function (host: string, port: number): Promise<{ ok: boolean }> {
88
88
  return new Promise((resolve, reject) => {
89
89
  request.get(`http://${host}:${port}/ping`, (err, res, body) => {
90
90
  if (err) {
@@ -93,8 +93,8 @@ export default {
93
93
  }
94
94
 
95
95
  resolve(JSON.parse(body));
96
- })
97
- })
96
+ });
97
+ });
98
98
  },
99
99
 
100
100
  /**
@@ -166,7 +166,9 @@ export default {
166
166
 
167
167
  const bindHost = getBindHost(host);
168
168
 
169
- currentServer.listen(port, bindHost, () => resolve({ host, port, dockerStatus: containerManager.isAlive() }));
169
+ currentServer.listen(port, bindHost, () =>
170
+ resolve({ host, port, dockerStatus: containerManager.isAlive() })
171
+ );
170
172
  currentServer.host = host;
171
173
  currentServer.port = port;
172
174
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -67,6 +67,7 @@
67
67
  "yaml": "^1.6.0"
68
68
  },
69
69
  "devDependencies": {
70
+ "@kapeta/eslint-config": "^0.6.1",
70
71
  "@kapeta/prettier-config": "^0.6.0",
71
72
  "@tsconfig/node18": "^18.2.0",
72
73
  "@types/express": "^4.17.17",
@@ -10,6 +10,8 @@ import { parseKapetaUri } from '@kapeta/nodejs-utils';
10
10
  import { repositoryManager } from './repositoryManager';
11
11
  import { BlockDefinition } from '@kapeta/schemas';
12
12
  import { Actions } from '@kapeta/nodejs-registry-utils';
13
+ import { definitionsManager } from './definitionsManager';
14
+ import { normalizeKapetaUri } from './utils/utils';
13
15
 
14
16
  export interface EnrichedAsset {
15
17
  ref: string;
@@ -67,7 +69,7 @@ class AssetManager {
67
69
  */
68
70
  getAssets(assetKinds?: string[]): EnrichedAsset[] {
69
71
  if (!assetKinds) {
70
- const blockTypeProviders = ClusterConfiguration.getDefinitions([
72
+ const blockTypeProviders = definitionsManager.getDefinitions([
71
73
  'core/block-type',
72
74
  'core/block-type-operator',
73
75
  ]);
@@ -77,7 +79,7 @@ class AssetManager {
77
79
  assetKinds.push('core/plan');
78
80
  }
79
81
 
80
- const assets = ClusterConfiguration.getDefinitions(assetKinds);
82
+ const assets = definitionsManager.getDefinitions(assetKinds);
81
83
 
82
84
  return assets.map(enrichAsset);
83
85
  }
@@ -97,6 +99,7 @@ class AssetManager {
97
99
  }
98
100
 
99
101
  async getAsset(ref: string, noCache: boolean = false): Promise<EnrichedAsset | undefined> {
102
+ ref = normalizeKapetaUri(ref);
100
103
  const cacheKey = `getAsset:${ref}`;
101
104
  if (!noCache && this.cache.has(cacheKey)) {
102
105
  return this.cache.get(cacheKey);
@@ -104,10 +107,10 @@ class AssetManager {
104
107
  const uri = parseKapetaUri(ref);
105
108
  await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version);
106
109
 
107
- let asset = ClusterConfiguration.getDefinitions()
110
+ let asset = definitionsManager
111
+ .getDefinitions()
108
112
  .map(enrichAsset)
109
113
  .find((a) => parseKapetaUri(a.ref).equals(uri));
110
-
111
114
  if (!asset) {
112
115
  throw new Error('Asset not found: ' + ref);
113
116
  }
@@ -3,7 +3,7 @@ import { KapetaAPI } from '@kapeta/nodejs-api-client';
3
3
 
4
4
  import { corsHandler } from '../middleware/cors';
5
5
  import { Request, Response } from 'express';
6
- import {storageService} from "../storageService";
6
+ import { storageService } from '../storageService';
7
7
 
8
8
  const router = Router();
9
9
  const api = new KapetaAPI();
@@ -22,7 +22,7 @@ router.put('/:handle/:name', async (req: Request, res: Response) => {
22
22
  if (!req.headers['content-type']) {
23
23
  res.status(400).send({
24
24
  status: 400,
25
- error: 'Missing content-type header'
25
+ error: 'Missing content-type header',
26
26
  });
27
27
  return;
28
28
  }
@@ -30,7 +30,7 @@ router.put('/:handle/:name', async (req: Request, res: Response) => {
30
30
  if (!req.headers['content-length']) {
31
31
  res.status(400).send({
32
32
  status: 400,
33
- error: 'Missing content-length header'
33
+ error: 'Missing content-length header',
34
34
  });
35
35
  return;
36
36
  }
@@ -38,15 +38,15 @@ router.put('/:handle/:name', async (req: Request, res: Response) => {
38
38
  if (!req.headers['content-disposition']) {
39
39
  res.status(400).send({
40
40
  status: 400,
41
- error: 'Missing content-disposition header'
41
+ error: 'Missing content-disposition header',
42
42
  });
43
43
  return;
44
44
  }
45
45
 
46
46
  try {
47
- const {handle, name} = req.params;
47
+ const { handle, name } = req.params;
48
48
  const url = `${endpoint}/${handle}/${name}/attachments`;
49
- const result = await api.send<{url:string}>({
49
+ const result = await api.send<{ url: string }>({
50
50
  method: 'PUT',
51
51
  url,
52
52
  auth: true,
@@ -55,10 +55,10 @@ router.put('/:handle/:name', async (req: Request, res: Response) => {
55
55
  'content-length': req.headers['content-length'],
56
56
  'content-disposition': req.headers['content-disposition'],
57
57
  },
58
- body: req
58
+ body: req,
59
59
  });
60
60
  res.send(result);
61
- } catch (e:any) {
61
+ } catch (e: any) {
62
62
  res.status(e.status ?? 500).send(e);
63
63
  }
64
64
  });
@@ -1,3 +1,5 @@
1
+ import { normalizeKapetaUri } from './utils/utils';
2
+
1
3
  const net = require('net');
2
4
  const DEFAULT_SERVER_PORT = 35100;
3
5
  const DEFAULT_START_PORT = 40000;
@@ -125,6 +127,7 @@ class ClusterService {
125
127
  * @return {string}
126
128
  */
127
129
  getProxyPath(systemId: string, consumerInstanceId: string, consumerResourceName: string, portType: string) {
130
+ systemId = normalizeKapetaUri(systemId);
128
131
  return `/proxy/${encodeURIComponent(systemId)}/${encodeURIComponent(consumerInstanceId)}/${encodeURIComponent(
129
132
  consumerResourceName
130
133
  )}/${encodeURIComponent(portType)}/`;
@@ -2,6 +2,7 @@ import Path from 'path';
2
2
  import { registry as Targets, BlockCodeGenerator, CodeWriter } from '@kapeta/codegen';
3
3
  import ClusterConfiguration from '@kapeta/local-cluster-config';
4
4
  import { BlockDefinition } from '@kapeta/schemas';
5
+ import { definitionsManager } from './definitionsManager';
5
6
 
6
7
  const TARGET_KIND = 'core/language-target';
7
8
  const BLOCK_TYPE_KIND = 'core/block-type';
@@ -9,7 +10,7 @@ const BLOCK_TYPE_KIND = 'core/block-type';
9
10
  class CodeGeneratorManager {
10
11
  async reload() {
11
12
  Targets.reset();
12
- const languageTargets = ClusterConfiguration.getDefinitions(TARGET_KIND);
13
+ const languageTargets = definitionsManager.getDefinitions(TARGET_KIND);
13
14
  for (const languageTarget of languageTargets) {
14
15
  const key = `${languageTarget.definition.metadata.name}:${languageTarget.version}`;
15
16
  try {
@@ -31,7 +32,7 @@ class CodeGeneratorManager {
31
32
  return false;
32
33
  }
33
34
 
34
- const blockTypes = ClusterConfiguration.getDefinitions(BLOCK_TYPE_KIND);
35
+ const blockTypes = definitionsManager.getDefinitions(BLOCK_TYPE_KIND);
35
36
  const blockTypeKinds = blockTypes.map(
36
37
  (blockType) => blockType.definition.metadata.name.toLowerCase() + ':' + blockType.version
37
38
  );
@@ -41,7 +41,7 @@ router.put('/instance', async (req: KapetaBodyRequest, res) => {
41
41
  if (req.kapeta!.instanceId) {
42
42
  configManager.setConfigForSection(req.kapeta!.systemId, req.kapeta!.instanceId, config);
43
43
  //Restart the instance if it is running after config change
44
- await instanceManager.restartIfRunning(req.kapeta!.systemId, req.kapeta!.instanceId);
44
+ await instanceManager.restart(req.kapeta!.systemId, req.kapeta!.instanceId);
45
45
  } else {
46
46
  configManager.setConfigForSystem(req.kapeta!.systemId, config);
47
47
  }
@@ -3,6 +3,7 @@ import { BlockInstance } from '@kapeta/schemas';
3
3
  import { storageService } from './storageService';
4
4
  import { assetManager } from './assetManager';
5
5
  import { parseKapetaUri } from '@kapeta/nodejs-utils';
6
+ import { normalizeKapetaUri } from './utils/utils';
6
7
 
7
8
  type AnyMap = { [key: string]: any };
8
9
 
@@ -19,6 +20,7 @@ class ConfigManager {
19
20
  }
20
21
 
21
22
  _forSystem(systemId: string) {
23
+ systemId = normalizeKapetaUri(systemId);
22
24
  if (!this._config[systemId]) {
23
25
  this._config[systemId] = {};
24
26
  }
@@ -27,16 +29,19 @@ class ConfigManager {
27
29
  }
28
30
 
29
31
  setConfigForSystem(systemId: string, config: AnyMap) {
32
+ systemId = normalizeKapetaUri(systemId);
30
33
  const systemConfig = config || {};
31
34
 
32
35
  storageService.put('config', systemId, systemConfig);
33
36
  }
34
37
 
35
38
  getConfigForSystem(systemId: string): AnyMap {
39
+ systemId = normalizeKapetaUri(systemId);
36
40
  return this._forSystem(systemId);
37
41
  }
38
42
 
39
43
  setConfigForSection(systemId: string, sectionId: string, config: AnyMap) {
44
+ systemId = normalizeKapetaUri(systemId);
40
45
  let systemConfig = this._forSystem(systemId);
41
46
  systemConfig[sectionId] = config || {};
42
47
 
@@ -44,6 +49,7 @@ class ConfigManager {
44
49
  }
45
50
 
46
51
  getConfigForSection(systemId: string, sectionId: string) {
52
+ systemId = normalizeKapetaUri(systemId);
47
53
  const systemConfig = this._forSystem(systemId);
48
54
 
49
55
  if (!systemConfig[sectionId]) {
@@ -70,6 +76,10 @@ class ConfigManager {
70
76
  * @returns {Promise<{systemId:string,instanceId:string}>}
71
77
  */
72
78
  async resolveIdentity(blockRef: string, systemId?: string) {
79
+ blockRef = normalizeKapetaUri(blockRef);
80
+ if (systemId) {
81
+ systemId = normalizeKapetaUri(systemId);
82
+ }
73
83
  const planAssets = assetManager.getPlans();
74
84
 
75
85
  const blockUri = parseKapetaUri(blockRef);
@@ -89,7 +99,7 @@ class ConfigManager {
89
99
  const refUri = parseKapetaUri(blockInstance.block.ref);
90
100
  if (refUri.equals(blockUri)) {
91
101
  matchingIdentities.push({
92
- systemId: planAsset.ref,
102
+ systemId: normalizeKapetaUri(planAsset.ref),
93
103
  instanceId: blockInstance.id,
94
104
  });
95
105
  }
@@ -120,6 +130,8 @@ class ConfigManager {
120
130
  }
121
131
 
122
132
  async verifyIdentity(blockRef: string, systemId: string, instanceId: string) {
133
+ blockRef = normalizeKapetaUri(blockRef);
134
+ systemId = normalizeKapetaUri(systemId);
123
135
  const planAssets = assetManager.getPlans();
124
136
  const systemUri = systemId ? parseKapetaUri(systemId) : null;
125
137
  const blockUri = parseKapetaUri(blockRef);
@@ -27,6 +27,25 @@ export interface DockerMounts {
27
27
  Consistency: string;
28
28
  }
29
29
 
30
+ interface DockerState {
31
+ Status: 'created' | 'running' | 'paused' | 'restarting' | 'removing' | 'exited' | 'dead';
32
+ Running: boolean;
33
+ Paused: boolean;
34
+ Restarting: boolean;
35
+ OOMKilled: boolean;
36
+ Dead: boolean;
37
+ Pid: number;
38
+ ExitCode: number;
39
+ Error: string;
40
+ StartedAt: string;
41
+ FinishedAt: string;
42
+ Health?: {
43
+ Status: 'starting' | 'healthy' | 'unhealthy' | 'none';
44
+ FailingStreak: number;
45
+ Log: any[] | null;
46
+ };
47
+ }
48
+
30
49
  interface Health {
31
50
  cmd: string;
32
51
  interval?: number;
@@ -36,11 +55,13 @@ interface Health {
36
55
 
37
56
  const LABEL_PORT_PREFIX = 'kapeta_port-';
38
57
  const NANO_SECOND = 1000000;
39
- const HEALTH_CHECK_INTERVAL = 2000;
40
- const HEALTH_CHECK_MAX = 30;
58
+ const HEALTH_CHECK_INTERVAL = 3000;
59
+ const HEALTH_CHECK_MAX = 20;
41
60
  const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
42
61
  const IMAGE_PULL_CACHE: { [key: string]: number } = {};
43
62
 
63
+ export const HEALTH_CHECK_TIMEOUT = HEALTH_CHECK_INTERVAL * HEALTH_CHECK_MAX * 2;
64
+
44
65
  const promisifyStream = (stream: ReadStream) =>
45
66
  new Promise((resolve, reject) => {
46
67
  stream.on('data', (d) => console.log(d.toString()));
@@ -116,7 +137,7 @@ class ContainerManager {
116
137
  }
117
138
 
118
139
  try {
119
- await this._docker.ping()
140
+ await this._docker.ping();
120
141
  this._alive = true;
121
142
  } catch (e) {
122
143
  this._alive = false;
@@ -165,11 +186,17 @@ class ContainerManager {
165
186
  return this._docker;
166
187
  }
167
188
 
168
- async getContainerByName(containerName: string): Promise<Container | undefined> {
189
+ async getContainerByName(containerName: string): Promise<ContainerInfo | undefined> {
169
190
  const containers = await this.docker().container.list({ all: true });
170
- return containers.find((container) => {
171
- return (container.data as any).Names.indexOf(`/${containerName}`) > -1;
191
+ const out = containers.find((container) => {
192
+ const containerData = container.data as any;
193
+ return containerData.Names.indexOf(`/${containerName}`) > -1;
172
194
  });
195
+
196
+ if (out) {
197
+ return new ContainerInfo(out);
198
+ }
199
+ return undefined;
173
200
  }
174
201
 
175
202
  async pull(image: string, cacheForMS: number = IMAGE_PULL_CACHE_TTL) {
@@ -371,18 +398,28 @@ class ContainerManager {
371
398
  }
372
399
 
373
400
  async _isReady(container: Container) {
374
- const info: Container = await container.status();
401
+ let info: Container;
402
+ try {
403
+ info = await container.status();
404
+ } catch (err) {
405
+ return false;
406
+ }
375
407
  const infoData: any = info?.data;
376
- if (infoData?.State?.Status === 'exited') {
408
+ const state = infoData?.State as DockerState;
409
+ if (state?.Status === 'exited' || state?.Status === 'removing' || state?.Status === 'dead') {
377
410
  throw new Error('Container exited unexpectedly');
378
411
  }
379
412
  return infoData?.State?.Running ?? false;
380
413
  }
381
414
 
382
415
  async _isHealthy(container: Container) {
383
- const info = await container.status();
384
- const infoData: any = info?.data;
385
- return infoData?.State?.Health?.Status === 'healthy';
416
+ try {
417
+ const info = await container.status();
418
+ const infoData: any = info?.data;
419
+ return infoData?.State?.Health?.Status === 'healthy';
420
+ } catch (err) {
421
+ return false;
422
+ }
386
423
  }
387
424
 
388
425
  /**
@@ -429,7 +466,7 @@ export class ContainerInfo {
429
466
  }
430
467
 
431
468
  async isRunning() {
432
- const inspectResult = await this.getStatus();
469
+ const inspectResult = await this.inspect();
433
470
 
434
471
  if (!inspectResult || !inspectResult.State) {
435
472
  return false;
@@ -464,14 +501,24 @@ export class ContainerInfo {
464
501
  return null;
465
502
  }
466
503
 
467
- async getStatus() {
468
- const result = await this._container.status();
504
+ async inspect() {
505
+ try {
506
+ const result = await this._container.status();
507
+
508
+ return result ? (result.data as any) : null;
509
+ } catch (err) {
510
+ return null;
511
+ }
512
+ }
513
+
514
+ async status() {
515
+ const result = await this.inspect();
469
516
 
470
- return result ? (result.data as any) : null;
517
+ return result.State as DockerState;
471
518
  }
472
519
 
473
520
  async getPorts(): Promise<PortMap | false> {
474
- const inspectResult = await this.getStatus();
521
+ const inspectResult = await this.inspect();
475
522
 
476
523
  if (!inspectResult || !inspectResult.Config || !inspectResult.Config.Labels) {
477
524
  return false;
@@ -0,0 +1,54 @@
1
+ import ClusterConfiguration, { DefinitionInfo } from '@kapeta/local-cluster-config';
2
+
3
+ const CACHE_TTL = 60 * 1000; // 1 min
4
+
5
+ interface DefinitionCacheEntry {
6
+ expires: number;
7
+ definitions: DefinitionInfo[];
8
+ }
9
+
10
+ class DefinitionsManager {
11
+ private cache: { [key: string]: DefinitionCacheEntry } = {};
12
+
13
+ private getKey(kindFilter?: string | string[]) {
14
+ if (kindFilter) {
15
+ if (Array.isArray(kindFilter)) {
16
+ return kindFilter.join(',');
17
+ }
18
+ return kindFilter;
19
+ }
20
+ return 'none';
21
+ }
22
+
23
+ public clearCache() {
24
+ this.cache = {};
25
+ }
26
+
27
+ private doCached(key: string, getter: () => DefinitionInfo[]) {
28
+ if (this.cache[key]) {
29
+ if (this.cache[key].expires > Date.now()) {
30
+ return this.cache[key].definitions;
31
+ }
32
+ delete this.cache[key];
33
+ }
34
+
35
+ this.cache[key] = {
36
+ expires: Date.now() + CACHE_TTL,
37
+ definitions: getter(),
38
+ };
39
+
40
+ return this.cache[key].definitions;
41
+ }
42
+
43
+ public getDefinitions(kindFilter?: string | string[]) {
44
+ const key = this.getKey(kindFilter);
45
+
46
+ return this.doCached(key, () => ClusterConfiguration.getDefinitions(kindFilter));
47
+ }
48
+
49
+ public getProviderDefinitions() {
50
+ return this.doCached('providers', () => ClusterConfiguration.getProviderDefinitions());
51
+ }
52
+ }
53
+
54
+ export const definitionsManager = new DefinitionsManager();
@@ -17,9 +17,7 @@ function isFile(path: string) {
17
17
  class FilesystemManager {
18
18
  async writeFile(path: string, data: string | Buffer) {
19
19
  const dirName = Path.dirname(path);
20
- console.log('Dir name', dirName, path);
21
20
  if (!FS.existsSync(dirName)) {
22
- console.log('Making folder', dirName);
23
21
  FSExtra.mkdirpSync(dirName, {});
24
22
  }
25
23
  FS.writeFileSync(path, data);
@@ -12,16 +12,15 @@ router.use('/', corsHandler);
12
12
  router.get('/current', async (req: Request, res: Response) => {
13
13
  try {
14
14
  res.send(await api.getCurrentIdentity());
15
- } catch (e:any) {
15
+ } catch (e: any) {
16
16
  res.status(e.status ?? 500).send(e);
17
17
  }
18
-
19
18
  });
20
19
 
21
20
  router.get('/:identityId/memberships', async (req: Request, res: Response) => {
22
21
  try {
23
22
  res.send(await api.getMemberships(req.params.identityId));
24
- } catch (e:any) {
23
+ } catch (e: any) {
25
24
  res.status(e.status ?? 500).send(e);
26
25
  }
27
26
  });