server-control-s3 0.0.15 → 1.0.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.
@@ -1,27 +1,29 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+
1
3
  declare const _default: {
2
4
  init: typeof init;
3
5
  getGitCommitHash: typeof getGitCommitHash;
4
6
  };
5
7
 
6
8
  interface Config {
7
- route_prefix: string;
8
9
  secret: string;
9
- sc_update_url_key_name: string;
10
- restart_function: () => void;
11
- service_port: number;
12
- http_proto: string;
13
- auth_middleware: boolean | ((req: any, res: any, next: any) => void);
14
- repo_dir: string;
15
- console_log: (...args: any[]) => void;
16
- error_log: (...args: any[]) => void;
17
- update_launch_default: boolean;
18
- remove_old_target: boolean;
19
- remote_repo_prefix?: string;
20
- metadata_opts?: any;
21
- asg_name?: string;
10
+ routePrefix: string;
11
+ updateUrlKeyName: string;
12
+ restartFunction: () => void;
13
+ port: number;
14
+ httpProto: string;
15
+ authMiddleware?: (req: Request, res: Response, next: NextFunction) => void;
16
+ repoDir: string;
17
+ consoleLog: (...args: any[]) => void;
18
+ errorLog: (...args: any[]) => void;
19
+ updateLaunchDefault: boolean;
20
+ removeOldTarget: boolean;
21
+ remoteRepoPrefix?: string;
22
+ metadataOpts?: any;
23
+ asgName?: string;
22
24
  region?: string;
23
25
  }
24
- declare function init(app: any, config: Partial<Config>): void;
26
+ declare function init(router: any, config: Partial<Config>): void;
25
27
  declare function getGitCommitHash(done: (err: any, result?: string) => void): void;
26
28
 
27
29
  export { _default as default, getGitCommitHash, init };
@@ -81,17 +81,20 @@ function webRequest(opts, done) {
81
81
  // ignore
82
82
  }
83
83
  }
84
- done(err, response_body);
84
+ done?.(err, response_body);
85
+ done = undefined;
85
86
  });
86
87
  });
87
88
  client_req.on('error', (err) => {
88
- done(err);
89
+ done?.(err);
90
+ done = undefined;
89
91
  });
90
92
  client_req.on('timeout', () => {
91
93
  client_req.destroy();
92
94
  const err = new Error('Request timed out');
93
95
  err.code = 'ETIMEDOUT';
94
- done(err);
96
+ done?.(err);
97
+ done = undefined;
95
98
  });
96
99
  if (request_body) {
97
100
  client_req.write(request_body);
@@ -157,78 +160,51 @@ var index = {
157
160
  };
158
161
  const MAX_WAIT_COUNT = 12;
159
162
  const SERVER_WAIT_MS = 10 * 1000;
163
+ const SERVER_UPDATE_TIMEOUT = 2 * 60 * 1000;
160
164
  const DEFAULT_CONFIG = {
161
- route_prefix: '',
162
165
  secret: 'secret',
163
- sc_update_url_key_name: 'SC_UPDATE_URL',
164
- restart_function: _defaultRestartFunction,
165
- service_port: 80,
166
- http_proto: 'http',
167
- auth_middleware: false,
168
- repo_dir: process.env.PWD || '.',
169
- console_log: console.log,
170
- error_log: console.error,
171
- update_launch_default: true,
172
- remove_old_target: true,
166
+ routePrefix: '',
167
+ updateUrlKeyName: 'SC_UPDATE_URL',
168
+ restartFunction: _defaultRestartFunction,
169
+ port: 80,
170
+ httpProto: 'http',
171
+ repoDir: process.env.PWD || '.',
172
+ consoleLog: console.log,
173
+ errorLog: console.error,
174
+ updateLaunchDefault: true,
175
+ removeOldTarget: true,
173
176
  };
174
177
  const g_config = {};
175
178
  let g_gitCommitHash = false;
176
179
  let g_updateHash = '';
177
- function init(app, config) {
180
+ function init(router, config) {
178
181
  Object.assign(g_config, DEFAULT_CONFIG, config);
179
- if (typeof g_config.route_prefix !== 'string') {
180
- throw 'server-control route_prefix required';
181
- }
182
- if (!g_config.remote_repo_prefix) {
182
+ if (!g_config.remoteRepoPrefix) {
183
183
  throw 'server-control remote_repo_prefix required';
184
184
  }
185
- g_config.route_prefix.replace(/\/$/, '');
186
- g_config.remote_repo_prefix.replace(/\/$/, '');
187
- asyncSeries([
188
- (done) => {
189
- _getAwsRegion(done);
190
- },
191
- (done) => {
192
- getGitCommitHash(() => { });
193
- const { route_prefix } = g_config;
194
- if (g_config.remove_old_target) {
195
- _removeOldTarget();
196
- }
197
- app.all(route_prefix + '/server_data', _parseQuery, _secretOrAuth, _serverData);
198
- app.all(route_prefix + '/group_data', _parseQuery, _secretOrAuth, _groupData);
199
- app.all(route_prefix + '/update_group', _parseQuery, _secretOrAuth, _updateGroup);
200
- app.all(route_prefix + '/update_server', _parseQuery, _secretOrAuth, _updateServer);
201
- done();
202
- },
203
- ]);
204
- }
205
- function _parseQuery(req, res, next) {
206
- if (typeof req.query === 'string') {
207
- const query = {};
208
- req.query.split('&').forEach((key_val) => {
209
- const split = key_val.split('=');
210
- query[split[0]] = split[1] || '';
211
- });
212
- req.query = query;
185
+ _getAwsRegion(() => { });
186
+ getGitCommitHash(() => { });
187
+ if (g_config.removeOldTarget) {
188
+ _removeOldTarget();
213
189
  }
214
- next();
190
+ router.use(_secretOrAuth);
191
+ router.all('/server_data', _serverData);
192
+ router.all('/group_data', _groupData);
193
+ router.all('/update_group', _updateGroup);
194
+ router.all('/update_server', _updateServer);
215
195
  }
216
196
  function _secretOrAuth(req, res, next) {
217
197
  if (req.headers && req.headers['x-sc-secret'] === g_config.secret) {
218
198
  next();
219
199
  }
220
- else if (req.body &&
221
- req.body.secret &&
222
- req.body.secret === g_config.secret) {
200
+ else if (req.body?.secret === g_config.secret) {
223
201
  next();
224
202
  }
225
- else if (req.cookies &&
226
- req.cookies.secret &&
227
- req.cookies.secret === g_config.secret) {
203
+ else if (req.cookies?.secret === g_config.secret) {
228
204
  next();
229
205
  }
230
- else if (typeof g_config.auth_middleware === 'function') {
231
- g_config.auth_middleware(req, res, next);
206
+ else if (g_config.authMiddleware) {
207
+ g_config.authMiddleware(req, res, next);
232
208
  }
233
209
  else {
234
210
  res.sendStatus(403);
@@ -254,15 +230,15 @@ function _groupData(req, res) {
254
230
  const body = {
255
231
  LATEST: result.latest || 'unknown',
256
232
  InstanceId: result.InstanceId || 'unknown',
257
- instance_list: result.instance_list,
233
+ InstanceList: result.instance_list,
258
234
  };
259
235
  if (result.auto_scale_group) {
260
- body.auto_scale_group = {
236
+ body.AutoScaleGroup = {
261
237
  AutoScalingGroupName: result.auto_scale_group.AutoScalingGroupName,
262
238
  LaunchTemplate: result.auto_scale_group.LaunchTemplate,
263
239
  };
264
240
  if (result.launch_template) {
265
- body.launch_template = result.launch_template;
241
+ body.LaunchTemplate = result.launch_template;
266
242
  }
267
243
  }
268
244
  if (err) {
@@ -294,7 +270,7 @@ function _getGroupData(done) {
294
270
  (done) => {
295
271
  const opts = {
296
272
  url: 'http://169.254.169.254/latest/meta-data/instance-id',
297
- ...(g_config.metadata_opts || {}),
273
+ ...(g_config.metadataOpts || {}),
298
274
  };
299
275
  webRequest(opts, (err, results) => {
300
276
  if (err) {
@@ -308,11 +284,11 @@ function _getGroupData(done) {
308
284
  const command = new clientAutoScaling.DescribeAutoScalingGroupsCommand({});
309
285
  autoscaling.send(command).then((data) => {
310
286
  asg = data.AutoScalingGroups.find((group) => {
311
- return (group.AutoScalingGroupName === g_config.asg_name ||
287
+ return (group.AutoScalingGroupName === g_config.asgName ||
312
288
  group.Instances.find((i) => i.InstanceId === InstanceId));
313
289
  });
314
290
  if (!asg) {
315
- _errorLog('_getGroupData: asg not found:', g_config.asg_name);
291
+ _errorLog('_getGroupData: asg not found:', g_config.asgName);
316
292
  done('asg_not_found');
317
293
  }
318
294
  else {
@@ -397,20 +373,16 @@ function _getGroupData(done) {
397
373
  });
398
374
  }
399
375
  function _getServerData(instance, done) {
400
- const proto = g_config.http_proto;
376
+ const proto = g_config.httpProto;
401
377
  const ip = instance.PrivateIpAddress;
402
- const port = g_config.service_port;
403
- const prefix = g_config.route_prefix;
378
+ const port = g_config.port;
379
+ const prefix = g_config.routePrefix;
404
380
  const url = `${proto}://${ip}:${port}${prefix}/server_data`;
405
381
  const opts = {
406
382
  url,
407
383
  method: 'GET',
408
- headers: {
409
- 'x-sc-secret': g_config.secret,
410
- },
411
- json: {
412
- secret: g_config.secret,
413
- },
384
+ headers: { 'x-sc-secret': g_config.secret },
385
+ json: { secret: g_config.secret },
414
386
  };
415
387
  webRequest(opts, (err, body) => {
416
388
  if (err) {
@@ -421,7 +393,7 @@ function _getServerData(instance, done) {
421
393
  }
422
394
  function _updateServer(req, res) {
423
395
  res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
424
- const hash = req.body.hash || req.query.hash;
396
+ const hash = req.body?.hash ?? req.query.hash;
425
397
  if (hash) {
426
398
  _updateSelf(hash, (err) => {
427
399
  if (err) {
@@ -429,7 +401,7 @@ function _updateServer(req, res) {
429
401
  }
430
402
  else {
431
403
  res.send('Restarting server');
432
- g_config.restart_function();
404
+ g_config.restartFunction();
433
405
  }
434
406
  });
435
407
  }
@@ -438,8 +410,8 @@ function _updateServer(req, res) {
438
410
  }
439
411
  }
440
412
  function _updateSelf(hash, done) {
441
- const dir = g_config.repo_dir;
442
- const url = `${g_config.remote_repo_prefix}/${hash}.tar.gz`;
413
+ const dir = g_config.repoDir;
414
+ const url = `${g_config.remoteRepoPrefix}/${hash}.tar.gz`;
443
415
  const cmd = `cd ${dir} && ${__dirname}/../scripts/update_to_hash.sh ${url}`;
444
416
  child_process__namespace.exec(cmd, (err, stdout, stderr) => {
445
417
  if (err) {
@@ -453,7 +425,7 @@ function _updateSelf(hash, done) {
453
425
  });
454
426
  }
455
427
  function _removeOldTarget() {
456
- const dir = g_config.repo_dir;
428
+ const dir = g_config.repoDir;
457
429
  const cmd = `${__dirname}/../scripts/remove_old_target.sh ${dir}`;
458
430
  child_process__namespace.exec(cmd, (err, stdout, stderr) => {
459
431
  if (err) {
@@ -463,11 +435,11 @@ function _removeOldTarget() {
463
435
  }
464
436
  function _updateGroup(req, res) {
465
437
  res.header('Cache-Control', 'no-cache, no-store, must-revalidate');
466
- const hash = req.body.hash || req.query.hash;
438
+ const hash = req.body?.hash ?? req.query.hash;
467
439
  if (hash) {
468
- const url = `${g_config.remote_repo_prefix}/${hash}.tar.gz`;
469
- const key_name = g_config.sc_update_url_key_name;
470
- const ami_id = req.body.ami_id || req.query.ami_id || false;
440
+ const url = `${g_config.remoteRepoPrefix}/${hash}.tar.gz`;
441
+ const key_name = g_config.updateUrlKeyName;
442
+ const ami_id = req.body?.ami_id ?? req.query.ami_id ?? false;
471
443
  const ec2 = _getEC2();
472
444
  let group_data = false;
473
445
  let old_data = '';
@@ -519,7 +491,7 @@ function _updateGroup(req, res) {
519
491
  });
520
492
  },
521
493
  (done) => {
522
- if (g_config.update_launch_default) {
494
+ if (g_config.updateLaunchDefault) {
523
495
  const opts = {
524
496
  DefaultVersion: String(new_version),
525
497
  LaunchTemplateId: group_data.launch_template.LaunchTemplateId,
@@ -573,7 +545,7 @@ function _updateGroup(req, res) {
573
545
  body._msg =
574
546
  'Successful updating all servers, restarting this server.';
575
547
  res.send(body);
576
- g_config.restart_function();
548
+ g_config.restartFunction();
577
549
  }
578
550
  });
579
551
  }
@@ -584,21 +556,17 @@ function _updateGroup(req, res) {
584
556
  function _updateInstance(hash, instance, done) {
585
557
  asyncSeries([
586
558
  (done) => {
587
- const proto = g_config.http_proto;
559
+ const proto = g_config.httpProto;
588
560
  const ip = instance.PrivateIpAddress;
589
- const port = g_config.service_port;
590
- const prefix = g_config.route_prefix;
561
+ const port = g_config.port;
562
+ const prefix = g_config.routePrefix;
591
563
  const url = `${proto}://${ip}:${port}${prefix}/update_server`;
592
564
  const opts = {
593
565
  url,
594
566
  method: 'GET',
595
- headers: {
596
- 'x-sc-secret': g_config.secret,
597
- },
598
- json: {
599
- hash,
600
- secret: g_config.secret,
601
- },
567
+ headers: { 'x-sc-secret': g_config.secret },
568
+ timeout: SERVER_UPDATE_TIMEOUT,
569
+ json: { hash, secret: g_config.secret },
602
570
  };
603
571
  webRequest(opts, done);
604
572
  },
@@ -629,7 +597,7 @@ function _waitForServer(params, done) {
629
597
  });
630
598
  }
631
599
  function _getLatest(done) {
632
- const url = g_config.remote_repo_prefix + '/LATEST';
600
+ const url = g_config.remoteRepoPrefix + '/LATEST';
633
601
  fetchFileContents(url, { region: g_config.region }, (err, body) => {
634
602
  done(err, body && body.trim());
635
603
  });
@@ -639,7 +607,7 @@ function getGitCommitHash(done) {
639
607
  done && done(null, g_gitCommitHash);
640
608
  }
641
609
  else {
642
- const file = node_path.join(g_config.repo_dir, '.git_commit_hash');
610
+ const file = node_path.join(g_config.repoDir, '.git_commit_hash');
643
611
  fs__namespace.readFile(file, 'utf8', (err, result) => {
644
612
  if (!err && !result) {
645
613
  err = 'no_result';
@@ -660,7 +628,7 @@ function _getAwsRegion(done) {
660
628
  }
661
629
  const opts = {
662
630
  url: 'http://169.254.169.254/latest/dynamic/instance-identity/document',
663
- ...(g_config.metadata_opts || {}),
631
+ ...(g_config.metadataOpts || {}),
664
632
  };
665
633
  webRequest(opts, (err, results) => {
666
634
  if (err) {
@@ -677,7 +645,6 @@ function _getAwsRegion(done) {
677
645
  _errorLog('_getAwsRegion: threw:', e);
678
646
  }
679
647
  }
680
- done();
681
648
  });
682
649
  }
683
650
  function _getAutoscaling() {
@@ -687,10 +654,10 @@ function _getEC2() {
687
654
  return new clientEc2.EC2Client({ region: g_config.region });
688
655
  }
689
656
  function _errorLog(...args) {
690
- g_config.error_log(...args);
657
+ g_config.errorLog(...args);
691
658
  }
692
659
  function _defaultRestartFunction() {
693
- g_config.console_log('server-control: updated to: ', g_updateHash, 'restarting...');
660
+ g_config.consoleLog('server-control: updated to: ', g_updateHash, 'restarting...');
694
661
  setTimeout(function () {
695
662
  process.exit(0);
696
663
  }, 100);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "server-control-s3",
3
- "version": "0.0.15",
3
+ "version": "1.0.2",
4
4
  "author": {
5
5
  "name": "Jim Lake"
6
6
  },
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "repository": {
16
16
  "type": "git",
17
- "url": "git@github.com:jim-lake/server-control-s3.git"
17
+ "url": "git+ssh://git@github.com/jim-lake/server-control-s3.git"
18
18
  },
19
19
  "files": [
20
20
  "dist/*",
@@ -24,7 +24,8 @@
24
24
  "types": "dist/server_control.d.ts",
25
25
  "scripts": {
26
26
  "build": "rm -rf dist && rollup -c",
27
- "lint": "eslint src --ext ts && eslint test --ext ts && eslint example --ext js",
27
+ "lint": "eslint src && eslint test",
28
+ "ts-check": "tsc --noEmit",
28
29
  "pretty": "prettier --write \"src/*.ts\" \"example/*.js\" \"test/*.ts\"",
29
30
  "test": "npm run build && npm run test-only",
30
31
  "test-only": "NODE_OPTIONS='--import=tsx' mocha --require test/local_setup.ts \"test/*.test.ts\""
@@ -41,6 +42,7 @@
41
42
  "@rollup/plugin-typescript": "^12.1.4",
42
43
  "@types/async": "^3.2.24",
43
44
  "@types/chai": "^5.2.2",
45
+ "@types/express": "^5.0.3",
44
46
  "@types/mocha": "^10.0.10",
45
47
  "@types/supertest": "^6.0.3",
46
48
  "@typescript-eslint/eslint-plugin": "^8.36.0",