@friggframework/admin-scripts 2.0.0--canary.517.a353e20.0 → 2.0.0--canary.517.5b0b222.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/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/admin-scripts",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.517.
|
|
4
|
+
"version": "2.0.0--canary.517.5b0b222.0",
|
|
5
5
|
"description": "Admin Script Runner for Frigg - Execute maintenance and operational scripts in hosted environments",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@aws-sdk/client-scheduler": "^3.588.0",
|
|
8
|
-
"@friggframework/core": "2.0.0--canary.517.
|
|
8
|
+
"@friggframework/core": "2.0.0--canary.517.5b0b222.0",
|
|
9
9
|
"@hapi/boom": "^10.0.1",
|
|
10
10
|
"express": "^4.18.2",
|
|
11
11
|
"serverless-http": "^3.2.0"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@friggframework/eslint-config": "2.0.0--canary.517.
|
|
15
|
-
"@friggframework/prettier-config": "2.0.0--canary.517.
|
|
16
|
-
"@friggframework/test": "2.0.0--canary.517.
|
|
14
|
+
"@friggframework/eslint-config": "2.0.0--canary.517.5b0b222.0",
|
|
15
|
+
"@friggframework/prettier-config": "2.0.0--canary.517.5b0b222.0",
|
|
16
|
+
"@friggframework/test": "2.0.0--canary.517.5b0b222.0",
|
|
17
17
|
"eslint": "^8.22.0",
|
|
18
18
|
"jest": "^29.7.0",
|
|
19
19
|
"prettier": "^2.7.1",
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"maintenance",
|
|
45
45
|
"operations"
|
|
46
46
|
],
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "5b0b222431533db4fe13b46369d88026a6fd4a19"
|
|
48
48
|
}
|
|
@@ -27,11 +27,23 @@ const {
|
|
|
27
27
|
} = require('../../adapters/scheduler-adapter-factory');
|
|
28
28
|
|
|
29
29
|
describe('Admin Script Router', () => {
|
|
30
|
+
let server;
|
|
30
31
|
let mockFactory;
|
|
31
32
|
let mockRunner;
|
|
32
33
|
let mockCommands;
|
|
33
34
|
let mockSchedulerAdapter;
|
|
34
35
|
|
|
36
|
+
// One persistent HTTP server for the whole file. Using request(server) spins up
|
|
37
|
+
// a fresh ephemeral server per call (35+ here); under load that occasionally
|
|
38
|
+
// mis-serves (empty-body 404s), which is the source of the flake.
|
|
39
|
+
beforeAll((done) => {
|
|
40
|
+
server = app.listen(0, done);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterAll((done) => {
|
|
44
|
+
server.close(done);
|
|
45
|
+
});
|
|
46
|
+
|
|
35
47
|
class TestScript extends AdminScriptBase {
|
|
36
48
|
static Definition = {
|
|
37
49
|
name: 'test-script',
|
|
@@ -98,7 +110,7 @@ describe('Admin Script Router', () => {
|
|
|
98
110
|
|
|
99
111
|
describe('GET /admin/scripts', () => {
|
|
100
112
|
it('should list all registered scripts', async () => {
|
|
101
|
-
const response = await request(
|
|
113
|
+
const response = await request(server).get('/admin/scripts');
|
|
102
114
|
|
|
103
115
|
expect(response.status).toBe(200);
|
|
104
116
|
expect(response.body.scripts).toHaveLength(1);
|
|
@@ -116,7 +128,7 @@ describe('Admin Script Router', () => {
|
|
|
116
128
|
throw new Error('Factory error');
|
|
117
129
|
});
|
|
118
130
|
|
|
119
|
-
const response = await request(
|
|
131
|
+
const response = await request(server).get('/admin/scripts');
|
|
120
132
|
|
|
121
133
|
expect(response.status).toBe(500);
|
|
122
134
|
expect(response.body.error).toBe('Failed to list scripts');
|
|
@@ -125,7 +137,7 @@ describe('Admin Script Router', () => {
|
|
|
125
137
|
|
|
126
138
|
describe('GET /admin/scripts/:scriptName', () => {
|
|
127
139
|
it('should return script details', async () => {
|
|
128
|
-
const response = await request(
|
|
140
|
+
const response = await request(server).get(
|
|
129
141
|
'/admin/scripts/test-script'
|
|
130
142
|
);
|
|
131
143
|
|
|
@@ -138,7 +150,7 @@ describe('Admin Script Router', () => {
|
|
|
138
150
|
it('should return 404 for non-existent script', async () => {
|
|
139
151
|
mockFactory.has.mockReturnValue(false);
|
|
140
152
|
|
|
141
|
-
const response = await request(
|
|
153
|
+
const response = await request(server).get(
|
|
142
154
|
'/admin/scripts/non-existent-script'
|
|
143
155
|
);
|
|
144
156
|
|
|
@@ -157,7 +169,7 @@ describe('Admin Script Router', () => {
|
|
|
157
169
|
metrics: { durationMs: 100 },
|
|
158
170
|
});
|
|
159
171
|
|
|
160
|
-
const response = await request(
|
|
172
|
+
const response = await request(server)
|
|
161
173
|
.post('/admin/scripts/test-script')
|
|
162
174
|
.send({
|
|
163
175
|
params: { foo: 'bar' },
|
|
@@ -189,7 +201,7 @@ describe('Admin Script Router', () => {
|
|
|
189
201
|
id: 'exec-456',
|
|
190
202
|
});
|
|
191
203
|
|
|
192
|
-
const response = await request(
|
|
204
|
+
const response = await request(server)
|
|
193
205
|
.post('/admin/scripts/test-script')
|
|
194
206
|
.send({
|
|
195
207
|
params: { foo: 'bar' },
|
|
@@ -216,7 +228,7 @@ describe('Admin Script Router', () => {
|
|
|
216
228
|
id: 'exec-789',
|
|
217
229
|
});
|
|
218
230
|
|
|
219
|
-
const response = await request(
|
|
231
|
+
const response = await request(server)
|
|
220
232
|
.post('/admin/scripts/test-script')
|
|
221
233
|
.send({
|
|
222
234
|
params: { foo: 'bar' },
|
|
@@ -230,7 +242,7 @@ describe('Admin Script Router', () => {
|
|
|
230
242
|
it('should return 503 when ADMIN_SCRIPT_QUEUE_URL is not set', async () => {
|
|
231
243
|
delete process.env.ADMIN_SCRIPT_QUEUE_URL;
|
|
232
244
|
|
|
233
|
-
const response = await request(
|
|
245
|
+
const response = await request(server)
|
|
234
246
|
.post('/admin/scripts/test-script')
|
|
235
247
|
.send({
|
|
236
248
|
params: { foo: 'bar' },
|
|
@@ -244,7 +256,7 @@ describe('Admin Script Router', () => {
|
|
|
244
256
|
it('should return 404 for non-existent script', async () => {
|
|
245
257
|
mockFactory.has.mockReturnValue(false);
|
|
246
258
|
|
|
247
|
-
const response = await request(
|
|
259
|
+
const response = await request(server)
|
|
248
260
|
.post('/admin/scripts/non-existent')
|
|
249
261
|
.send({
|
|
250
262
|
params: {},
|
|
@@ -258,7 +270,7 @@ describe('Admin Script Router', () => {
|
|
|
258
270
|
// TestScript.Definition.config.timeout is 300000 (> 25000)
|
|
259
271
|
process.env.AWS_LAMBDA_FUNCTION_NAME = 'admin-script-router';
|
|
260
272
|
|
|
261
|
-
const response = await request(
|
|
273
|
+
const response = await request(server)
|
|
262
274
|
.post('/admin/scripts/test-script')
|
|
263
275
|
.send({ params: {}, mode: 'sync' });
|
|
264
276
|
|
|
@@ -290,7 +302,7 @@ describe('Admin Script Router', () => {
|
|
|
290
302
|
metrics: { durationMs: 1 },
|
|
291
303
|
});
|
|
292
304
|
|
|
293
|
-
const response = await request(
|
|
305
|
+
const response = await request(server)
|
|
294
306
|
.post('/admin/scripts/short-script')
|
|
295
307
|
.send({ params: {}, mode: 'sync' });
|
|
296
308
|
|
|
@@ -308,7 +320,7 @@ describe('Admin Script Router', () => {
|
|
|
308
320
|
code: 'DB_ERROR',
|
|
309
321
|
});
|
|
310
322
|
|
|
311
|
-
const response = await request(
|
|
323
|
+
const response = await request(server)
|
|
312
324
|
.post('/admin/scripts/test-script')
|
|
313
325
|
.send({ params: { foo: 'bar' }, mode: 'async' });
|
|
314
326
|
|
|
@@ -327,7 +339,7 @@ describe('Admin Script Router', () => {
|
|
|
327
339
|
status: 'COMPLETED',
|
|
328
340
|
});
|
|
329
341
|
|
|
330
|
-
const response = await request(
|
|
342
|
+
const response = await request(server).get(
|
|
331
343
|
'/admin/scripts/test-script/executions/exec-123'
|
|
332
344
|
);
|
|
333
345
|
|
|
@@ -343,7 +355,7 @@ describe('Admin Script Router', () => {
|
|
|
343
355
|
code: 'EXECUTION_NOT_FOUND',
|
|
344
356
|
});
|
|
345
357
|
|
|
346
|
-
const response = await request(
|
|
358
|
+
const response = await request(server).get(
|
|
347
359
|
'/admin/scripts/test-script/executions/non-existent'
|
|
348
360
|
);
|
|
349
361
|
|
|
@@ -359,7 +371,7 @@ describe('Admin Script Router', () => {
|
|
|
359
371
|
{ id: 'exec-2', name: 'test-script', state: 'RUNNING' },
|
|
360
372
|
]);
|
|
361
373
|
|
|
362
|
-
const response = await request(
|
|
374
|
+
const response = await request(server).get(
|
|
363
375
|
'/admin/scripts/test-script/executions'
|
|
364
376
|
);
|
|
365
377
|
|
|
@@ -376,7 +388,7 @@ describe('Admin Script Router', () => {
|
|
|
376
388
|
it('should accept query parameters (status maps to state, limit is bounded)', async () => {
|
|
377
389
|
mockCommands.findExecutionsByName.mockResolvedValue([]);
|
|
378
390
|
|
|
379
|
-
await request(
|
|
391
|
+
await request(server).get(
|
|
380
392
|
'/admin/scripts/test-script/executions?status=COMPLETED&limit=10'
|
|
381
393
|
);
|
|
382
394
|
|
|
@@ -410,7 +422,7 @@ describe('Admin Script Router', () => {
|
|
|
410
422
|
.fn()
|
|
411
423
|
.mockResolvedValue(dbSchedule);
|
|
412
424
|
|
|
413
|
-
const response = await request(
|
|
425
|
+
const response = await request(server).get(
|
|
414
426
|
'/admin/scripts/test-script/schedule'
|
|
415
427
|
);
|
|
416
428
|
|
|
@@ -441,7 +453,7 @@ describe('Admin Script Router', () => {
|
|
|
441
453
|
|
|
442
454
|
mockFactory.get.mockReturnValue(ScheduledTestScript);
|
|
443
455
|
|
|
444
|
-
const response = await request(
|
|
456
|
+
const response = await request(server).get(
|
|
445
457
|
'/admin/scripts/test-script/schedule'
|
|
446
458
|
);
|
|
447
459
|
|
|
@@ -455,7 +467,7 @@ describe('Admin Script Router', () => {
|
|
|
455
467
|
.fn()
|
|
456
468
|
.mockResolvedValue(null);
|
|
457
469
|
|
|
458
|
-
const response = await request(
|
|
470
|
+
const response = await request(server).get(
|
|
459
471
|
'/admin/scripts/test-script/schedule'
|
|
460
472
|
);
|
|
461
473
|
|
|
@@ -467,7 +479,7 @@ describe('Admin Script Router', () => {
|
|
|
467
479
|
it('should return 404 for non-existent script', async () => {
|
|
468
480
|
mockFactory.has.mockReturnValue(false);
|
|
469
481
|
|
|
470
|
-
const response = await request(
|
|
482
|
+
const response = await request(server).get(
|
|
471
483
|
'/admin/scripts/non-existent/schedule'
|
|
472
484
|
);
|
|
473
485
|
|
|
@@ -493,7 +505,7 @@ describe('Admin Script Router', () => {
|
|
|
493
505
|
.fn()
|
|
494
506
|
.mockResolvedValue(newSchedule);
|
|
495
507
|
|
|
496
|
-
const response = await request(
|
|
508
|
+
const response = await request(server)
|
|
497
509
|
.put('/admin/scripts/test-script/schedule')
|
|
498
510
|
.send({
|
|
499
511
|
enabled: true,
|
|
@@ -530,7 +542,7 @@ describe('Admin Script Router', () => {
|
|
|
530
542
|
.fn()
|
|
531
543
|
.mockResolvedValue(updatedSchedule);
|
|
532
544
|
|
|
533
|
-
const response = await request(
|
|
545
|
+
const response = await request(server)
|
|
534
546
|
.put('/admin/scripts/test-script/schedule')
|
|
535
547
|
.send({
|
|
536
548
|
enabled: false,
|
|
@@ -542,7 +554,7 @@ describe('Admin Script Router', () => {
|
|
|
542
554
|
});
|
|
543
555
|
|
|
544
556
|
it('should require enabled field', async () => {
|
|
545
|
-
const response = await request(
|
|
557
|
+
const response = await request(server)
|
|
546
558
|
.put('/admin/scripts/test-script/schedule')
|
|
547
559
|
.send({
|
|
548
560
|
cronExpression: '0 12 * * *',
|
|
@@ -553,7 +565,7 @@ describe('Admin Script Router', () => {
|
|
|
553
565
|
});
|
|
554
566
|
|
|
555
567
|
it('should require cronExpression when enabled is true', async () => {
|
|
556
|
-
const response = await request(
|
|
568
|
+
const response = await request(server)
|
|
557
569
|
.put('/admin/scripts/test-script/schedule')
|
|
558
570
|
.send({
|
|
559
571
|
enabled: true,
|
|
@@ -566,7 +578,7 @@ describe('Admin Script Router', () => {
|
|
|
566
578
|
it('should return 404 for non-existent script', async () => {
|
|
567
579
|
mockFactory.has.mockReturnValue(false);
|
|
568
580
|
|
|
569
|
-
const response = await request(
|
|
581
|
+
const response = await request(server)
|
|
570
582
|
.put('/admin/scripts/non-existent/schedule')
|
|
571
583
|
.send({
|
|
572
584
|
enabled: true,
|
|
@@ -601,7 +613,7 @@ describe('Admin Script Router', () => {
|
|
|
601
613
|
scheduleName: 'frigg-script-test-script',
|
|
602
614
|
});
|
|
603
615
|
|
|
604
|
-
const response = await request(
|
|
616
|
+
const response = await request(server)
|
|
605
617
|
.put('/admin/scripts/test-script/schedule')
|
|
606
618
|
.send({
|
|
607
619
|
enabled: true,
|
|
@@ -648,7 +660,7 @@ describe('Admin Script Router', () => {
|
|
|
648
660
|
.mockResolvedValue(existingSchedule);
|
|
649
661
|
mockSchedulerAdapter.deleteSchedule.mockResolvedValue();
|
|
650
662
|
|
|
651
|
-
const response = await request(
|
|
663
|
+
const response = await request(server)
|
|
652
664
|
.put('/admin/scripts/test-script/schedule')
|
|
653
665
|
.send({
|
|
654
666
|
enabled: false,
|
|
@@ -683,7 +695,7 @@ describe('Admin Script Router', () => {
|
|
|
683
695
|
new Error('AWS Scheduler API error')
|
|
684
696
|
);
|
|
685
697
|
|
|
686
|
-
const response = await request(
|
|
698
|
+
const response = await request(server)
|
|
687
699
|
.put('/admin/scripts/test-script/schedule')
|
|
688
700
|
.send({
|
|
689
701
|
enabled: true,
|
|
@@ -711,7 +723,7 @@ describe('Admin Script Router', () => {
|
|
|
711
723
|
},
|
|
712
724
|
});
|
|
713
725
|
|
|
714
|
-
const response = await request(
|
|
726
|
+
const response = await request(server).delete(
|
|
715
727
|
'/admin/scripts/test-script/schedule'
|
|
716
728
|
);
|
|
717
729
|
|
|
@@ -745,7 +757,7 @@ describe('Admin Script Router', () => {
|
|
|
745
757
|
|
|
746
758
|
mockFactory.get.mockReturnValue(ScheduledTestScript);
|
|
747
759
|
|
|
748
|
-
const response = await request(
|
|
760
|
+
const response = await request(server).delete(
|
|
749
761
|
'/admin/scripts/test-script/schedule'
|
|
750
762
|
);
|
|
751
763
|
|
|
@@ -760,7 +772,7 @@ describe('Admin Script Router', () => {
|
|
|
760
772
|
deletedCount: 0,
|
|
761
773
|
});
|
|
762
774
|
|
|
763
|
-
const response = await request(
|
|
775
|
+
const response = await request(server).delete(
|
|
764
776
|
'/admin/scripts/test-script/schedule'
|
|
765
777
|
);
|
|
766
778
|
|
|
@@ -774,7 +786,7 @@ describe('Admin Script Router', () => {
|
|
|
774
786
|
it('should return 404 for non-existent script', async () => {
|
|
775
787
|
mockFactory.has.mockReturnValue(false);
|
|
776
788
|
|
|
777
|
-
const response = await request(
|
|
789
|
+
const response = await request(server).delete(
|
|
778
790
|
'/admin/scripts/non-existent/schedule'
|
|
779
791
|
);
|
|
780
792
|
|
|
@@ -797,7 +809,7 @@ describe('Admin Script Router', () => {
|
|
|
797
809
|
});
|
|
798
810
|
mockSchedulerAdapter.deleteSchedule.mockResolvedValue();
|
|
799
811
|
|
|
800
|
-
const response = await request(
|
|
812
|
+
const response = await request(server).delete(
|
|
801
813
|
'/admin/scripts/test-script/schedule'
|
|
802
814
|
);
|
|
803
815
|
|
|
@@ -819,7 +831,7 @@ describe('Admin Script Router', () => {
|
|
|
819
831
|
},
|
|
820
832
|
});
|
|
821
833
|
|
|
822
|
-
const response = await request(
|
|
834
|
+
const response = await request(server).delete(
|
|
823
835
|
'/admin/scripts/test-script/schedule'
|
|
824
836
|
);
|
|
825
837
|
|
|
@@ -843,7 +855,7 @@ describe('Admin Script Router', () => {
|
|
|
843
855
|
new Error('Scheduler delete failed')
|
|
844
856
|
);
|
|
845
857
|
|
|
846
|
-
const response = await request(
|
|
858
|
+
const response = await request(server).delete(
|
|
847
859
|
'/admin/scripts/test-script/schedule'
|
|
848
860
|
);
|
|
849
861
|
|