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.
- package/dist/server_control.d.ts +17 -15
- package/dist/server_control.js +65 -98
- package/package.json +5 -3
package/dist/server_control.d.ts
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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(
|
|
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 };
|
package/dist/server_control.js
CHANGED
|
@@ -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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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(
|
|
180
|
+
function init(router, config) {
|
|
178
181
|
Object.assign(g_config, DEFAULT_CONFIG, config);
|
|
179
|
-
if (
|
|
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
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
(
|
|
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
|
-
|
|
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 (
|
|
231
|
-
g_config.
|
|
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
|
-
|
|
233
|
+
InstanceList: result.instance_list,
|
|
258
234
|
};
|
|
259
235
|
if (result.auto_scale_group) {
|
|
260
|
-
body.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
376
|
+
const proto = g_config.httpProto;
|
|
401
377
|
const ip = instance.PrivateIpAddress;
|
|
402
|
-
const port = g_config.
|
|
403
|
-
const prefix = g_config.
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
442
|
-
const url = `${g_config.
|
|
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.
|
|
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
|
|
438
|
+
const hash = req.body?.hash ?? req.query.hash;
|
|
467
439
|
if (hash) {
|
|
468
|
-
const url = `${g_config.
|
|
469
|
-
const key_name = g_config.
|
|
470
|
-
const ami_id = req.body
|
|
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.
|
|
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.
|
|
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.
|
|
559
|
+
const proto = g_config.httpProto;
|
|
588
560
|
const ip = instance.PrivateIpAddress;
|
|
589
|
-
const port = g_config.
|
|
590
|
-
const prefix = g_config.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
657
|
+
g_config.errorLog(...args);
|
|
691
658
|
}
|
|
692
659
|
function _defaultRestartFunction() {
|
|
693
|
-
g_config.
|
|
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": "
|
|
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
|
|
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
|
|
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",
|