@kapeta/local-cluster-service 0.8.1 → 0.8.3

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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.8.3](https://github.com/kapetacom/local-cluster-service/compare/v0.8.2...v0.8.3) (2023-07-23)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Format ([736158b](https://github.com/kapetacom/local-cluster-service/commit/736158b8685aa2ac1193cdabbbb34d81f6d2e302))
7
+
8
+ ## [0.8.2](https://github.com/kapetacom/local-cluster-service/compare/v0.8.1...v0.8.2) (2023-07-23)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Check for existing cluster services on the same point and exit if it exists ([#47](https://github.com/kapetacom/local-cluster-service/issues/47)) ([3c76c3c](https://github.com/kapetacom/local-cluster-service/commit/3c76c3c24927212e4a06dc627e6c7262b2c60c4f))
14
+
1
15
  ## [0.8.1](https://github.com/kapetacom/local-cluster-service/compare/v0.8.0...v0.8.1) (2023-07-22)
2
16
 
3
17
 
package/definitions.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  declare module 'recursive-watch' {
2
- export default function watch(path:string, callback:(filename:string) => void):() => void;
2
+ export default function watch(path: string, callback: (filename: string) => void): () => void;
3
3
  }
4
4
 
5
5
  declare module '@kapeta/nodejs-registry-utils' {
@@ -12,6 +12,9 @@ export type StartResult = {
12
12
  declare const _default: {
13
13
  isRunning: () => boolean;
14
14
  getCurrentPort: () => number | undefined;
15
+ ping: (host: string, port: number) => Promise<{
16
+ ok: boolean;
17
+ }>;
15
18
  /**
16
19
  * Starts the local cluster service.
17
20
  * resolves when listening is done with port number. Rejects if listening failed.
package/dist/cjs/index.js CHANGED
@@ -21,6 +21,7 @@ const routes_7 = __importDefault(require("./src/assets/routes"));
21
21
  const routes_8 = __importDefault(require("./src/providers/routes"));
22
22
  const routes_9 = __importDefault(require("./src/attachments/routes"));
23
23
  const utils_1 = require("./src/utils/utils");
24
+ const request_1 = __importDefault(require("request"));
24
25
  let currentServer = null;
25
26
  function createServer() {
26
27
  const app = (0, express_1.default)();
@@ -33,11 +34,23 @@ function createServer() {
33
34
  app.use('/assets', routes_7.default);
34
35
  app.use('/providers', routes_8.default);
35
36
  app.use('/attachments', routes_9.default);
37
+ app.get('/status', async (req, res) => {
38
+ res.send({
39
+ ok: true,
40
+ dockerStatus: await containerManager_1.containerManager.checkAlive(),
41
+ socketStatus: socketManager_1.socketManager.isAlive(),
42
+ });
43
+ });
44
+ app.get('/ping', async (req, res) => {
45
+ res.send({
46
+ ok: true,
47
+ });
48
+ });
36
49
  app.use('/', (req, res) => {
37
50
  console.error('Invalid request: %s %s', req.method, req.originalUrl);
38
51
  res.status(400).send({
39
52
  ok: false,
40
- error: 'Unknown'
53
+ error: 'Unknown',
41
54
  });
42
55
  });
43
56
  const server = http_1.default.createServer(app);
@@ -61,6 +74,17 @@ exports.default = {
61
74
  }
62
75
  return currentServer.port;
63
76
  },
77
+ ping: async function (host, port) {
78
+ return new Promise((resolve, reject) => {
79
+ request_1.default.get(`http://${host}:${port}/ping`, (err, res, body) => {
80
+ if (err) {
81
+ reject(err);
82
+ return;
83
+ }
84
+ resolve(JSON.parse(body));
85
+ });
86
+ });
87
+ },
64
88
  /**
65
89
  * Starts the local cluster service.
66
90
  * resolves when listening is done with port number. Rejects if listening failed.
@@ -83,6 +107,16 @@ exports.default = {
83
107
  if (clusterHost) {
84
108
  clusterService_1.clusterService.setClusterServiceHost(clusterHost);
85
109
  }
110
+ let pingResult = undefined;
111
+ try {
112
+ pingResult = await this.ping(clusterHost, clusterPort);
113
+ }
114
+ catch (e) {
115
+ //Ignore - expected to not be running since we're starting it
116
+ }
117
+ if (pingResult?.ok) {
118
+ throw new Error(`Cluster service already running on: ${clusterHost}:${clusterPort}.`);
119
+ }
86
120
  await clusterService_1.clusterService.init();
87
121
  currentServer = createServer();
88
122
  const port = clusterService_1.clusterService.getClusterServicePort();
@@ -20,21 +20,21 @@ router.put('/:handle/:name', async (req, res) => {
20
20
  if (!req.headers['content-type']) {
21
21
  res.status(400).send({
22
22
  status: 400,
23
- error: 'Missing content-type header'
23
+ error: 'Missing content-type header',
24
24
  });
25
25
  return;
26
26
  }
27
27
  if (!req.headers['content-length']) {
28
28
  res.status(400).send({
29
29
  status: 400,
30
- error: 'Missing content-length header'
30
+ error: 'Missing content-length header',
31
31
  });
32
32
  return;
33
33
  }
34
34
  if (!req.headers['content-disposition']) {
35
35
  res.status(400).send({
36
36
  status: 400,
37
- error: 'Missing content-disposition header'
37
+ error: 'Missing content-disposition header',
38
38
  });
39
39
  return;
40
40
  }
@@ -50,7 +50,7 @@ router.put('/:handle/:name', async (req, res) => {
50
50
  'content-length': req.headers['content-length'],
51
51
  'content-disposition': req.headers['content-disposition'],
52
52
  },
53
- body: req
53
+ body: req,
54
54
  });
55
55
  res.send(result);
56
56
  }
@@ -30,6 +30,7 @@ declare class ContainerManager {
30
30
  private _version;
31
31
  constructor();
32
32
  initialize(): Promise<void>;
33
+ checkAlive(): Promise<boolean>;
33
34
  isAlive(): boolean;
34
35
  getMountPoint(kind: string, mountName: string): string;
35
36
  createMounts(kind: string, mountOpts: StringMap): StringMap;
@@ -77,6 +77,25 @@ class ContainerManager {
77
77
  }
78
78
  throw new Error('Could not connect to docker daemon. Please make sure docker is running and working.');
79
79
  }
80
+ async checkAlive() {
81
+ if (!this._docker) {
82
+ try {
83
+ await this.initialize();
84
+ }
85
+ catch (e) {
86
+ this._alive = false;
87
+ }
88
+ return this._alive;
89
+ }
90
+ try {
91
+ await this._docker.ping();
92
+ this._alive = true;
93
+ }
94
+ catch (e) {
95
+ this._alive = false;
96
+ }
97
+ return this._alive;
98
+ }
80
99
  isAlive() {
81
100
  return this._alive;
82
101
  }
@@ -4,6 +4,7 @@ export declare class SocketManager {
4
4
  private _sockets;
5
5
  constructor();
6
6
  setIo(io: Server): void;
7
+ isAlive(): boolean;
7
8
  private get io();
8
9
  emit(context: string, type: string, payload: any): void;
9
10
  _bindIO(): void;
@@ -14,10 +14,12 @@ class SocketManager {
14
14
  return this;
15
15
  }
16
16
  setIo(io) {
17
- console.log('Socket server ready');
18
17
  this._io = io;
19
18
  this._bindIO();
20
19
  }
20
+ isAlive() {
21
+ return !!this._io;
22
+ }
21
23
  get io() {
22
24
  if (!this._io) {
23
25
  throw new Error('Socket server not ready');
@@ -37,11 +39,9 @@ class SocketManager {
37
39
  _bindSocket(socket) {
38
40
  socket.on('disconnect', () => this._handleSocketDestroyed(socket));
39
41
  socket.on('join', (id) => {
40
- console.log('socket joined ', id);
41
42
  socket.join(id);
42
43
  });
43
44
  socket.on('leave', (id) => {
44
- console.log('socket left ', id);
45
45
  socket.leave(id);
46
46
  });
47
47
  }
@@ -317,9 +317,7 @@ class BlockInstanceRunner {
317
317
  ...Object.entries(env).map(([key, value]) => `${key}=${value}`),
318
318
  ],
319
319
  HostConfig: {
320
- Binds: [
321
- `${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`,
322
- ],
320
+ Binds: [`${(0, containerManager_1.toLocalBindVolume)(local_cluster_config_1.default.getKapetaBasedir())}:${innerHome}`],
323
321
  },
324
322
  });
325
323
  try {
@@ -29,7 +29,7 @@ function isLinux() {
29
29
  }
30
30
  exports.isLinux = isLinux;
31
31
  function getBindHost(preferredHost = '127.0.0.1') {
32
- // On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
32
+ // On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
33
33
  // TODO: This might pose a security risk - so we should authenticate all requests using a shared secret/nonce that we pass around.
34
34
  return isLinux() ? '0.0.0.0' : preferredHost;
35
35
  }
package/dist/cjs/start.js CHANGED
@@ -9,4 +9,5 @@ index_1.default
9
9
  .then(({ host, port }) => console.log('Listening on port %s:%s', host, port))
10
10
  .catch((e) => {
11
11
  console.error('Failed to start local cluster due to an error:\n\t - %s', e.toString());
12
+ process.exit(1);
12
13
  });
@@ -12,6 +12,9 @@ export type StartResult = {
12
12
  declare const _default: {
13
13
  isRunning: () => boolean;
14
14
  getCurrentPort: () => number | undefined;
15
+ ping: (host: string, port: number) => Promise<{
16
+ ok: boolean;
17
+ }>;
15
18
  /**
16
19
  * Starts the local cluster service.
17
20
  * resolves when listening is done with port number. Rejects if listening failed.
package/dist/esm/index.js CHANGED
@@ -16,6 +16,7 @@ import AssetsRoutes from './src/assets/routes';
16
16
  import ProviderRoutes from './src/providers/routes';
17
17
  import AttachmentRoutes from './src/attachments/routes';
18
18
  import { getBindHost } from './src/utils/utils';
19
+ import request from 'request';
19
20
  let currentServer = null;
20
21
  function createServer() {
21
22
  const app = express();
@@ -28,11 +29,23 @@ function createServer() {
28
29
  app.use('/assets', AssetsRoutes);
29
30
  app.use('/providers', ProviderRoutes);
30
31
  app.use('/attachments', AttachmentRoutes);
32
+ app.get('/status', async (req, res) => {
33
+ res.send({
34
+ ok: true,
35
+ dockerStatus: await containerManager.checkAlive(),
36
+ socketStatus: socketManager.isAlive(),
37
+ });
38
+ });
39
+ app.get('/ping', async (req, res) => {
40
+ res.send({
41
+ ok: true,
42
+ });
43
+ });
31
44
  app.use('/', (req, res) => {
32
45
  console.error('Invalid request: %s %s', req.method, req.originalUrl);
33
46
  res.status(400).send({
34
47
  ok: false,
35
- error: 'Unknown'
48
+ error: 'Unknown',
36
49
  });
37
50
  });
38
51
  const server = HTTP.createServer(app);
@@ -56,6 +69,17 @@ export default {
56
69
  }
57
70
  return currentServer.port;
58
71
  },
72
+ ping: async function (host, port) {
73
+ return new Promise((resolve, reject) => {
74
+ request.get(`http://${host}:${port}/ping`, (err, res, body) => {
75
+ if (err) {
76
+ reject(err);
77
+ return;
78
+ }
79
+ resolve(JSON.parse(body));
80
+ });
81
+ });
82
+ },
59
83
  /**
60
84
  * Starts the local cluster service.
61
85
  * resolves when listening is done with port number. Rejects if listening failed.
@@ -78,6 +102,16 @@ export default {
78
102
  if (clusterHost) {
79
103
  clusterService.setClusterServiceHost(clusterHost);
80
104
  }
105
+ let pingResult = undefined;
106
+ try {
107
+ pingResult = await this.ping(clusterHost, clusterPort);
108
+ }
109
+ catch (e) {
110
+ //Ignore - expected to not be running since we're starting it
111
+ }
112
+ if (pingResult?.ok) {
113
+ throw new Error(`Cluster service already running on: ${clusterHost}:${clusterPort}.`);
114
+ }
81
115
  await clusterService.init();
82
116
  currentServer = createServer();
83
117
  const port = clusterService.getClusterServicePort();
@@ -1,7 +1,7 @@
1
1
  import Router from 'express-promise-router';
2
2
  import { KapetaAPI } from '@kapeta/nodejs-api-client';
3
3
  import { corsHandler } from '../middleware/cors';
4
- import { storageService } from "../storageService";
4
+ import { storageService } from '../storageService';
5
5
  const router = Router();
6
6
  const api = new KapetaAPI();
7
7
  const DEFAULT_REGISTRY_BASE = 'https://registry.kapeta.com';
@@ -15,21 +15,21 @@ router.put('/:handle/:name', async (req, res) => {
15
15
  if (!req.headers['content-type']) {
16
16
  res.status(400).send({
17
17
  status: 400,
18
- error: 'Missing content-type header'
18
+ error: 'Missing content-type header',
19
19
  });
20
20
  return;
21
21
  }
22
22
  if (!req.headers['content-length']) {
23
23
  res.status(400).send({
24
24
  status: 400,
25
- error: 'Missing content-length header'
25
+ error: 'Missing content-length header',
26
26
  });
27
27
  return;
28
28
  }
29
29
  if (!req.headers['content-disposition']) {
30
30
  res.status(400).send({
31
31
  status: 400,
32
- error: 'Missing content-disposition header'
32
+ error: 'Missing content-disposition header',
33
33
  });
34
34
  return;
35
35
  }
@@ -45,7 +45,7 @@ router.put('/:handle/:name', async (req, res) => {
45
45
  'content-length': req.headers['content-length'],
46
46
  'content-disposition': req.headers['content-disposition'],
47
47
  },
48
- body: req
48
+ body: req,
49
49
  });
50
50
  res.send(result);
51
51
  }
@@ -30,6 +30,7 @@ declare class ContainerManager {
30
30
  private _version;
31
31
  constructor();
32
32
  initialize(): Promise<void>;
33
+ checkAlive(): Promise<boolean>;
33
34
  isAlive(): boolean;
34
35
  getMountPoint(kind: string, mountName: string): string;
35
36
  createMounts(kind: string, mountOpts: StringMap): StringMap;
@@ -71,6 +71,25 @@ class ContainerManager {
71
71
  }
72
72
  throw new Error('Could not connect to docker daemon. Please make sure docker is running and working.');
73
73
  }
74
+ async checkAlive() {
75
+ if (!this._docker) {
76
+ try {
77
+ await this.initialize();
78
+ }
79
+ catch (e) {
80
+ this._alive = false;
81
+ }
82
+ return this._alive;
83
+ }
84
+ try {
85
+ await this._docker.ping();
86
+ this._alive = true;
87
+ }
88
+ catch (e) {
89
+ this._alive = false;
90
+ }
91
+ return this._alive;
92
+ }
74
93
  isAlive() {
75
94
  return this._alive;
76
95
  }
@@ -4,6 +4,7 @@ export declare class SocketManager {
4
4
  private _sockets;
5
5
  constructor();
6
6
  setIo(io: Server): void;
7
+ isAlive(): boolean;
7
8
  private get io();
8
9
  emit(context: string, type: string, payload: any): void;
9
10
  _bindIO(): void;
@@ -8,10 +8,12 @@ export class SocketManager {
8
8
  return this;
9
9
  }
10
10
  setIo(io) {
11
- console.log('Socket server ready');
12
11
  this._io = io;
13
12
  this._bindIO();
14
13
  }
14
+ isAlive() {
15
+ return !!this._io;
16
+ }
15
17
  get io() {
16
18
  if (!this._io) {
17
19
  throw new Error('Socket server not ready');
@@ -31,11 +33,9 @@ export class SocketManager {
31
33
  _bindSocket(socket) {
32
34
  socket.on('disconnect', () => this._handleSocketDestroyed(socket));
33
35
  socket.on('join', (id) => {
34
- console.log('socket joined ', id);
35
36
  socket.join(id);
36
37
  });
37
38
  socket.on('leave', (id) => {
38
- console.log('socket left ', id);
39
39
  socket.leave(id);
40
40
  });
41
41
  }
@@ -311,9 +311,7 @@ export class BlockInstanceRunner {
311
311
  ...Object.entries(env).map(([key, value]) => `${key}=${value}`),
312
312
  ],
313
313
  HostConfig: {
314
- Binds: [
315
- `${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
316
- ],
314
+ Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
317
315
  },
318
316
  });
319
317
  try {
@@ -19,7 +19,7 @@ export function isLinux() {
19
19
  return !isWindows() && !isMac();
20
20
  }
21
21
  export function getBindHost(preferredHost = '127.0.0.1') {
22
- // On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
22
+ // On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
23
23
  // TODO: This might pose a security risk - so we should authenticate all requests using a shared secret/nonce that we pass around.
24
24
  return isLinux() ? '0.0.0.0' : preferredHost;
25
25
  }
package/dist/esm/start.js CHANGED
@@ -4,4 +4,5 @@ localClusterService
4
4
  .then(({ host, port }) => console.log('Listening on port %s:%s', host, port))
5
5
  .catch((e) => {
6
6
  console.error('Failed to start local cluster due to an error:\n\t - %s', e.toString());
7
+ process.exit(1);
7
8
  });
package/index.ts CHANGED
@@ -17,6 +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
21
 
21
22
  export type LocalClusterService = HTTP.Server & { host?: string; port?: number };
22
23
 
@@ -35,13 +36,28 @@ function createServer() {
35
36
  app.use('/assets', AssetsRoutes);
36
37
  app.use('/providers', ProviderRoutes);
37
38
  app.use('/attachments', AttachmentRoutes);
39
+ app.get('/status', async (req, res) => {
40
+ res.send({
41
+ ok: true,
42
+ dockerStatus: await containerManager.checkAlive(),
43
+ socketStatus: socketManager.isAlive(),
44
+ });
45
+ });
46
+
47
+ app.get('/ping', async (req, res) => {
48
+ res.send({
49
+ ok: true,
50
+ });
51
+ });
52
+
38
53
  app.use('/', (req: express.Request, res: express.Response) => {
39
54
  console.error('Invalid request: %s %s', req.method, req.originalUrl);
40
55
  res.status(400).send({
41
56
  ok: false,
42
- error: 'Unknown'
57
+ error: 'Unknown',
43
58
  });
44
59
  });
60
+
45
61
  const server = HTTP.createServer(app);
46
62
 
47
63
  //socket
@@ -68,6 +84,19 @@ export default {
68
84
  return currentServer.port;
69
85
  },
70
86
 
87
+ ping: async function (host: string, port: number): Promise<{ ok: boolean }> {
88
+ return new Promise((resolve, reject) => {
89
+ request.get(`http://${host}:${port}/ping`, (err, res, body) => {
90
+ if (err) {
91
+ reject(err);
92
+ return;
93
+ }
94
+
95
+ resolve(JSON.parse(body));
96
+ });
97
+ });
98
+ },
99
+
71
100
  /**
72
101
  * Starts the local cluster service.
73
102
  * resolves when listening is done with port number. Rejects if listening failed.
@@ -95,6 +124,17 @@ export default {
95
124
  clusterService.setClusterServiceHost(clusterHost);
96
125
  }
97
126
 
127
+ let pingResult = undefined;
128
+ try {
129
+ pingResult = await this.ping(clusterHost, clusterPort);
130
+ } catch (e: any) {
131
+ //Ignore - expected to not be running since we're starting it
132
+ }
133
+
134
+ if (pingResult?.ok) {
135
+ throw new Error(`Cluster service already running on: ${clusterHost}:${clusterPort}.`);
136
+ }
137
+
98
138
  await clusterService.init();
99
139
 
100
140
  currentServer = createServer();
@@ -126,7 +166,9 @@ export default {
126
166
 
127
167
  const bindHost = getBindHost(host);
128
168
 
129
- currentServer.listen(port, bindHost, () => resolve({ host, port, dockerStatus: containerManager.isAlive() }));
169
+ currentServer.listen(port, bindHost, () =>
170
+ resolve({ host, port, dockerStatus: containerManager.isAlive() })
171
+ );
130
172
  currentServer.host = host;
131
173
  currentServer.port = port;
132
174
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "scripts": {
33
33
  "start": "node ./dist/cjs/start.js",
34
- "dev": "nodemon -e js,ts,json ts-node --transpile-only ./start.ts",
34
+ "dev": "nodemon -e js,ts,json ./start.ts",
35
35
  "test": "echo its fine",
36
36
  "clean": "rm -rf ./dist",
37
37
  "build:esm": "tsc --module esnext --outDir ./dist/esm && echo '{\"type\":\"module\"}' > ./dist/esm/package.json",
@@ -63,7 +63,6 @@
63
63
  "request": "2.88.2",
64
64
  "request-promise": "4.2.6",
65
65
  "socket.io": "^4.5.2",
66
- "ts-node": "^10.9.1",
67
66
  "typescript": "^5.1.6",
68
67
  "yaml": "^1.6.0"
69
68
  },
@@ -79,7 +78,8 @@
79
78
  "eslint": "^8.42.0",
80
79
  "eslint-config-prettier": "^8.8.0",
81
80
  "nodemon": "^2.0.2",
82
- "prettier": "^2.8.8"
81
+ "prettier": "^2.8.8",
82
+ "ts-node": "^10.9.1"
83
83
  },
84
84
  "prettier": "@kapeta/prettier-config",
85
85
  "release": {
@@ -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
  });
@@ -105,6 +105,26 @@ class ContainerManager {
105
105
  throw new Error('Could not connect to docker daemon. Please make sure docker is running and working.');
106
106
  }
107
107
 
108
+ async checkAlive() {
109
+ if (!this._docker) {
110
+ try {
111
+ await this.initialize();
112
+ } catch (e) {
113
+ this._alive = false;
114
+ }
115
+ return this._alive;
116
+ }
117
+
118
+ try {
119
+ await this._docker.ping();
120
+ this._alive = true;
121
+ } catch (e) {
122
+ this._alive = false;
123
+ }
124
+
125
+ return this._alive;
126
+ }
127
+
108
128
  isAlive() {
109
129
  return this._alive;
110
130
  }
@@ -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
  });
@@ -41,23 +41,23 @@ class RepositoryManager {
41
41
 
42
42
  console.log('Watching local repository for provider changes: %s', baseDir);
43
43
  try {
44
- this.watcher = watch(baseDir, (filename:string) => {
44
+ this.watcher = watch(baseDir, (filename: string) => {
45
45
  if (!filename) {
46
46
  return;
47
47
  }
48
-
48
+
49
49
  const [handle, name, version] = filename.toString().split(/\//g);
50
50
  if (!name || !version) {
51
51
  return;
52
52
  }
53
-
53
+
54
54
  if (!this.changeEventsEnabled) {
55
55
  return;
56
56
  }
57
-
57
+
58
58
  const ymlPath = Path.join(baseDir, handle, name, version, 'kapeta.yml');
59
59
  const newDefinitions = ClusterConfiguration.getDefinitions();
60
-
60
+
61
61
  const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
62
62
  let currentDefinition = allDefinitions.find((d) => d.ymlPath === ymlPath);
63
63
  const ymlExists = FS.existsSync(ymlPath);
@@ -85,13 +85,13 @@ class RepositoryManager {
85
85
  return;
86
86
  }
87
87
  }
88
-
88
+
89
89
  const payload = {
90
90
  type,
91
91
  definition: currentDefinition?.definition,
92
92
  asset: { handle, name, version },
93
93
  };
94
-
94
+
95
95
  allDefinitions = newDefinitions;
96
96
  socketManager.emit(`assets`, 'changed', payload);
97
97
  });
@@ -12,12 +12,14 @@ export class SocketManager {
12
12
  }
13
13
 
14
14
  setIo(io: Server) {
15
- console.log('Socket server ready');
16
15
  this._io = io;
17
-
18
16
  this._bindIO();
19
17
  }
20
18
 
19
+ isAlive() {
20
+ return !!this._io;
21
+ }
22
+
21
23
  private get io() {
22
24
  if (!this._io) {
23
25
  throw new Error('Socket server not ready');
@@ -41,11 +43,9 @@ export class SocketManager {
41
43
  _bindSocket(socket: Socket) {
42
44
  socket.on('disconnect', () => this._handleSocketDestroyed(socket));
43
45
  socket.on('join', (id) => {
44
- console.log('socket joined ', id);
45
46
  socket.join(id);
46
47
  });
47
48
  socket.on('leave', (id) => {
48
- console.log('socket left ', id);
49
49
  socket.leave(id);
50
50
  });
51
51
  }
@@ -53,7 +53,7 @@ class StorageService {
53
53
  this._writeConfig();
54
54
  }
55
55
 
56
- get<T = any>(section: string, property?: string, defaultValue?:T): T|undefined {
56
+ get<T = any>(section: string, property?: string, defaultValue?: T): T | undefined {
57
57
  if (!property) {
58
58
  return this.section(section);
59
59
  }
@@ -216,7 +216,7 @@ export class BlockInstanceRunner {
216
216
 
217
217
  PortBindings[dockerPort] = [
218
218
  {
219
- HostIp: bindHost,
219
+ HostIp: bindHost,
220
220
  HostPort: `${publicPort}`,
221
221
  },
222
222
  ];
@@ -380,9 +380,7 @@ export class BlockInstanceRunner {
380
380
  ...Object.entries(env).map(([key, value]) => `${key}=${value}`),
381
381
  ],
382
382
  HostConfig: {
383
- Binds: [
384
- `${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`,
385
- ],
383
+ Binds: [`${toLocalBindVolume(ClusterConfig.getKapetaBasedir())}:${innerHome}`],
386
384
  },
387
385
  });
388
386
 
@@ -24,7 +24,7 @@ export function isLinux() {
24
24
  }
25
25
 
26
26
  export function getBindHost(preferredHost = '127.0.0.1') {
27
- // On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
27
+ // On Linux we need to bind to 0.0.0.0 to be able to connect to it from docker containers.
28
28
  // TODO: This might pose a security risk - so we should authenticate all requests using a shared secret/nonce that we pass around.
29
29
  return isLinux() ? '0.0.0.0' : preferredHost;
30
- }
30
+ }
package/start.ts CHANGED
@@ -5,4 +5,5 @@ localClusterService
5
5
  .then(({ host, port }) => console.log('Listening on port %s:%s', host, port))
6
6
  .catch((e) => {
7
7
  console.error('Failed to start local cluster due to an error:\n\t - %s', e.toString());
8
+ process.exit(1);
8
9
  });