@kapeta/local-cluster-service 0.2.1 → 0.3.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [0.3.0](https://github.com/kapetacom/local-cluster-service/compare/v0.2.1...v0.3.0) (2023-05-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * load docker config from clusterConfig if available [KAP-609] ([1ced2c1](https://github.com/kapetacom/local-cluster-service/commit/1ced2c1ed2f72bf3331e558ee2c685385c89ab1f))
7
+
1
8
  ## [0.2.1](https://github.com/kapetacom/local-cluster-service/compare/v0.2.0...v0.2.1) (2023-05-07)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -22,7 +22,7 @@
22
22
  "homepage": "https://github.com/kapetacom/local-cluster-service#readme",
23
23
  "dependencies": {
24
24
  "@kapeta/codegen": "<2",
25
- "@kapeta/local-cluster-config": "<2",
25
+ "@kapeta/local-cluster-config": ">= 0.1.0 <2",
26
26
  "@kapeta/nodejs-api-client": "<2",
27
27
  "@kapeta/nodejs-registry-utils": "<2",
28
28
  "@kapeta/nodejs-utils": "<2",
@@ -44,6 +44,10 @@
44
44
  "devDependencies": {
45
45
  "nodemon": "^2.0.2"
46
46
  },
47
+ "prettier": {
48
+ "tabWidth": 4,
49
+ "singleQuote": true
50
+ },
47
51
  "release": {
48
52
  "plugins": [
49
53
  "@semantic-release/commit-analyzer",
@@ -1,13 +1,15 @@
1
- const {Docker} = require("node-docker-api");
2
- const path = require("path");
1
+ const { Docker } = require('node-docker-api');
2
+ const path = require('path');
3
3
  const _ = require('lodash');
4
- const FS = require("node:fs");
5
- const os = require("os");
6
- const Path = require("path");
7
- const storageService = require("./storageService");
8
- const mkdirp = require("mkdirp");
9
- const {parseKapetaUri} = require("@kapeta/nodejs-utils");
10
- const LABEL_PORT_PREFIX = "kapeta_port-";
4
+ const os = require('os');
5
+ const Path = require('path');
6
+ const storageService = require('./storageService');
7
+ const mkdirp = require('mkdirp');
8
+ const { parseKapetaUri } = require('@kapeta/nodejs-utils');
9
+
10
+ const ClusterConfiguration = require('@kapeta/local-cluster-config');
11
+
12
+ const LABEL_PORT_PREFIX = 'kapeta_port-';
11
13
 
12
14
  const NANO_SECOND = 1000000;
13
15
  const HEALTH_CHECK_INTERVAL = 2000;
@@ -15,9 +17,9 @@ const HEALTH_CHECK_MAX = 20;
15
17
 
16
18
  const promisifyStream = (stream) =>
17
19
  new Promise((resolve, reject) => {
18
- stream.on("data", (d) => console.log(d.toString()));
19
- stream.on("end", resolve);
20
- stream.on("error", reject);
20
+ stream.on('data', (d) => console.log(d.toString()));
21
+ stream.on('end', resolve);
22
+ stream.on('error', reject);
21
23
  });
22
24
 
23
25
  class ContainerManager {
@@ -27,8 +29,41 @@ class ContainerManager {
27
29
  this._mountDir = Path.join(storageService.getKapetaBasedir(), 'mounts');
28
30
  mkdirp.sync(this._mountDir);
29
31
  }
30
-
31
-
32
+
33
+ async initialize() {
34
+ // Use the value from cluster-service.yml if configured
35
+ const dockerConfig = ClusterConfiguration.getDockerConfig();
36
+ const connectOptions =
37
+ Object.keys(dockerConfig).length > 0
38
+ ? [dockerConfig]
39
+ : [
40
+ // use defaults: DOCKER_HOST etc from env, if available
41
+ undefined,
42
+ // default linux
43
+ { socketPath: '/var/run/docker.sock' },
44
+ // default macOS
45
+ {
46
+ socketPath: path.join(
47
+ os.homedir(),
48
+ '.docker/run/docker.sock'
49
+ ),
50
+ },
51
+ // Default http
52
+ { protocol: 'http', host: 'localhost', port: 2375 },
53
+ { protocol: 'https', host: 'localhost', port: 2376 },
54
+ ];
55
+ for (const opts of connectOptions) {
56
+ try {
57
+ const client = new Docker(opts);
58
+ await client.ping();
59
+ this._docker = client;
60
+ this._alive = true;
61
+ return;
62
+ } catch (err) {
63
+ // silently ignore bad configs
64
+ }
65
+ }
66
+ }
32
67
 
33
68
  isAlive() {
34
69
  return this._alive;
@@ -36,9 +71,14 @@ class ContainerManager {
36
71
 
37
72
  getMountPoint(kind, mountName) {
38
73
  const kindUri = parseKapetaUri(kind);
39
- return Path.join(this._mountDir, kindUri.handle, kindUri.name, mountName);
74
+ return Path.join(
75
+ this._mountDir,
76
+ kindUri.handle,
77
+ kindUri.name,
78
+ mountName
79
+ );
40
80
  }
41
-
81
+
42
82
  createMounts(kind, mountOpts) {
43
83
  const mounts = {};
44
84
 
@@ -50,42 +90,16 @@ class ContainerManager {
50
90
  return mounts;
51
91
  }
52
92
 
53
- async initialize() {
54
- // try
55
- const connectOptions = [
56
- // use defaults: DOCKER_HOST etc from env, if available
57
- undefined,
58
- // default linux
59
- {socketPath: "/var/run/docker.sock"},
60
- // default macOS
61
- {socketPath: path.join(os.homedir(), ".docker/run/docker.sock")},
62
- // Default http
63
- {protocol: "http", host: "localhost", port: 2375},
64
- {protocol: "https", host: "localhost", port: 2376},
65
- ];
66
- for (const opts of connectOptions) {
67
- try {
68
- const client = new Docker(opts);
69
- await client.ping();
70
- this._docker = client;
71
- this._alive = true;
72
- return;
73
- } catch (err) {
74
- // silently ignore bad configs
75
- }
76
- }
77
- throw new Error("Unable to connect to docker");
78
- }
79
-
80
93
  async ping() {
81
-
82
94
  try {
83
95
  const pingResult = await this.docker().ping();
84
96
  if (pingResult !== 'OK') {
85
97
  throw new Error(`Ping failed: ${pingResult}`);
86
98
  }
87
99
  } catch (e) {
88
- throw new Error(`Docker not running. Please start the docker daemon before running this command. Error: ${e.message}`);
100
+ throw new Error(
101
+ `Docker not running. Please start the docker daemon before running this command. Error: ${e.message}`
102
+ );
89
103
  }
90
104
  }
91
105
  docker() {
@@ -96,8 +110,8 @@ class ContainerManager {
96
110
  }
97
111
 
98
112
  async getContainerByName(containerName) {
99
- const containers = await this.docker().container.list({all: true});
100
- return containers.find(container => {
113
+ const containers = await this.docker().container.list({ all: true });
114
+ return containers.find((container) => {
101
115
  return container.data.Names.indexOf(`/${containerName}`) > -1;
102
116
  });
103
117
  }
@@ -108,8 +122,8 @@ class ContainerManager {
108
122
  tag = 'latest';
109
123
  }
110
124
 
111
- await this.docker().image
112
- .create(
125
+ await this.docker()
126
+ .image.create(
113
127
  {},
114
128
  {
115
129
  fromImage: imageName,
@@ -118,25 +132,25 @@ class ContainerManager {
118
132
  )
119
133
  .then((stream) => promisifyStream(stream));
120
134
  }
121
-
135
+
122
136
  toDockerMounts(mounts) {
123
- const Mounts = [];
137
+ const Mounts = [];
124
138
  _.forEach(mounts, (Source, Target) => {
125
139
  Mounts.push({
126
140
  Target,
127
141
  Source,
128
- Type: "bind",
142
+ Type: 'bind',
129
143
  ReadOnly: false,
130
- Consistency: "consistent",
144
+ Consistency: 'consistent',
131
145
  });
132
146
  });
133
-
147
+
134
148
  return Mounts;
135
149
  }
136
-
150
+
137
151
  toDockerHealth(health) {
138
152
  return {
139
- Test: ["CMD-SHELL", health.cmd],
153
+ Test: ['CMD-SHELL', health.cmd],
140
154
  Interval: health.interval
141
155
  ? health.interval * NANO_SECOND
142
156
  : 5000 * NANO_SECOND,
@@ -155,25 +169,24 @@ class ContainerManager {
155
169
  * @return {Promise<ContainerInfo>}
156
170
  */
157
171
  async run(image, name, opts) {
158
-
159
172
  const PortBindings = {};
160
173
  const Env = [];
161
174
  const Labels = {
162
- kapeta: "true",
175
+ kapeta: 'true',
163
176
  };
164
177
 
165
- console.log("Pulling image: %s", image);
178
+ console.log('Pulling image: %s', image);
166
179
 
167
180
  await this.pull(image);
168
181
 
169
- console.log("Image pulled: %s", image);
182
+ console.log('Image pulled: %s', image);
170
183
 
171
184
  _.forEach(opts.ports, (portInfo, containerPort) => {
172
185
  PortBindings['' + containerPort] = [
173
186
  {
174
187
  HostPort: '' + portInfo.hostPort,
175
- HostIp: '127.0.0.1'
176
- }
188
+ HostIp: '127.0.0.1',
189
+ },
177
190
  ];
178
191
 
179
192
  Labels[LABEL_PORT_PREFIX + portInfo.hostPort] = portInfo.type;
@@ -182,7 +195,7 @@ class ContainerManager {
182
195
  const Mounts = this.toDockerMounts(opts.mounts);
183
196
 
184
197
  _.forEach(opts.env, (value, name) => {
185
- Env.push(name + "=" + value);
198
+ Env.push(name + '=' + value);
186
199
  });
187
200
 
188
201
  let HealthCheck = undefined;
@@ -190,10 +203,9 @@ class ContainerManager {
190
203
  if (opts.health) {
191
204
  HealthCheck = this.toDockerHealth(opts.health);
192
205
 
193
- console.log("Adding health check", HealthCheck);
206
+ console.log('Adding health check', HealthCheck);
194
207
  }
195
208
 
196
-
197
209
  const dockerContainer = await this.startContainer({
198
210
  name: name,
199
211
  Image: image,
@@ -202,8 +214,8 @@ class ContainerManager {
202
214
  HealthCheck,
203
215
  HostConfig: {
204
216
  PortBindings,
205
- Mounts
206
- }
217
+ Mounts,
218
+ },
207
219
  });
208
220
 
209
221
  if (opts.health) {
@@ -221,14 +233,15 @@ class ContainerManager {
221
233
  return dockerContainer;
222
234
  }
223
235
 
224
-
225
236
  async waitForHealthy(container, attempt) {
226
237
  if (!attempt) {
227
238
  attempt = 0;
228
239
  }
229
240
 
230
241
  if (attempt >= HEALTH_CHECK_MAX) {
231
- throw new Error("Container did not become healthy within the timeout");
242
+ throw new Error(
243
+ 'Container did not become healthy within the timeout'
244
+ );
232
245
  }
233
246
 
234
247
  if (await this._isHealthy(container)) {
@@ -249,7 +262,7 @@ class ContainerManager {
249
262
 
250
263
  async _isHealthy(container) {
251
264
  const info = await container.status();
252
- return info?.data?.State?.Health?.Status === "healthy";
265
+ return info?.data?.State?.Health?.Status === 'healthy';
253
266
  }
254
267
 
255
268
  /**
@@ -265,7 +278,7 @@ class ContainerManager {
265
278
  await dockerContainer.status();
266
279
  } catch (err) {
267
280
  //Ignore
268
- console.log("Container not available - creating it: %s", name);
281
+ console.log('Container not available - creating it: %s', name);
269
282
  dockerContainer = null;
270
283
  }
271
284
 
@@ -314,7 +327,7 @@ class ContainerInfo {
314
327
  }
315
328
 
316
329
  async remove(opts) {
317
- await this._container.delete({force: !!opts.force});
330
+ await this._container.delete({ force: !!opts.force });
318
331
  }
319
332
 
320
333
  async getPort(type) {