@pagerduty/backstage-plugin-backend 0.8.2-next.0 → 0.9.0-next.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/dist/index.cjs.js +521 -25
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/migrations/20240722_add_settings_table.js +27 -0
- package/package.json +2 -2
package/dist/index.cjs.js
CHANGED
|
@@ -12,10 +12,10 @@ var backendPluginApi = require('@backstage/backend-plugin-api');
|
|
|
12
12
|
var uuid = require('uuid');
|
|
13
13
|
var catalogClient = require('@backstage/catalog-client');
|
|
14
14
|
|
|
15
|
-
function
|
|
15
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
16
16
|
|
|
17
|
-
function
|
|
18
|
-
if (e && e
|
|
17
|
+
function _interopNamespaceCompat(e) {
|
|
18
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
19
19
|
var n = Object.create(null);
|
|
20
20
|
if (e) {
|
|
21
21
|
Object.keys(e).forEach(function (k) {
|
|
@@ -28,13 +28,13 @@ function _interopNamespace(e) {
|
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
-
n
|
|
31
|
+
n.default = e;
|
|
32
32
|
return Object.freeze(n);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
var fetch__default = /*#__PURE__*/
|
|
36
|
-
var express__namespace = /*#__PURE__*/
|
|
37
|
-
var Router__default = /*#__PURE__*/
|
|
35
|
+
var fetch__default = /*#__PURE__*/_interopDefaultCompat(fetch$1);
|
|
36
|
+
var express__namespace = /*#__PURE__*/_interopNamespaceCompat(express);
|
|
37
|
+
var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
|
|
38
38
|
|
|
39
39
|
let authPersistence;
|
|
40
40
|
let isLegacyConfig$1 = false;
|
|
@@ -255,6 +255,128 @@ function getApiBaseUrl(account) {
|
|
|
255
255
|
}
|
|
256
256
|
return fallbackEndpointConfig.apiBaseUrl;
|
|
257
257
|
}
|
|
258
|
+
async function addServiceRelationsToService(serviceRelations, account) {
|
|
259
|
+
let response;
|
|
260
|
+
const options = {
|
|
261
|
+
method: "POST",
|
|
262
|
+
headers: {
|
|
263
|
+
Authorization: await getAuthToken(account),
|
|
264
|
+
"Accept": "application/vnd.pagerduty+json;version=2",
|
|
265
|
+
"Content-Type": "application/json"
|
|
266
|
+
},
|
|
267
|
+
body: JSON.stringify({
|
|
268
|
+
relationships: serviceRelations
|
|
269
|
+
})
|
|
270
|
+
};
|
|
271
|
+
const apiBaseUrl = getApiBaseUrl(account);
|
|
272
|
+
const baseUrl = `${apiBaseUrl}/service_dependencies/associate`;
|
|
273
|
+
console.log(`Adding service relations: ${JSON.stringify({ relationships: serviceRelations })}`);
|
|
274
|
+
try {
|
|
275
|
+
response = await fetchWithRetries(`${baseUrl}`, options);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
throw new Error(`Failed to retrieve service dependencies: ${error}`);
|
|
278
|
+
}
|
|
279
|
+
if (response.status >= 500) {
|
|
280
|
+
throw new backstagePluginCommon.HttpError(`Failed to add service dependencies. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
281
|
+
}
|
|
282
|
+
switch (response.status) {
|
|
283
|
+
case 400:
|
|
284
|
+
throw new backstagePluginCommon.HttpError("Failed to add service dependencies. Caller provided invalid arguments. Please review the response for error details. Retrying with the same arguments will not work.", 400);
|
|
285
|
+
case 401:
|
|
286
|
+
throw new backstagePluginCommon.HttpError("Failed to add service dependencies. Caller did not supply credentials or did not provide the correct credentials. If you are using an API key, it may be invalid or your Authorization header may be malformed.", 401);
|
|
287
|
+
case 403:
|
|
288
|
+
throw new backstagePluginCommon.HttpError("Failed to add service dependencies. Caller is not authorized to view the requested resource. While your authentication is valid, the authenticated user or token does not have permission to perform this action.", 403);
|
|
289
|
+
case 404:
|
|
290
|
+
throw new backstagePluginCommon.HttpError("Failed to add service dependencies. The requested resource was not found.", 404);
|
|
291
|
+
}
|
|
292
|
+
let result;
|
|
293
|
+
try {
|
|
294
|
+
result = await response.json();
|
|
295
|
+
return result.relationships;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
throw new backstagePluginCommon.HttpError(`Failed to parse service dependency information: ${error}`, 500);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async function removeServiceRelationsFromService(serviceRelations, account) {
|
|
301
|
+
let response;
|
|
302
|
+
const options = {
|
|
303
|
+
method: "POST",
|
|
304
|
+
headers: {
|
|
305
|
+
Authorization: await getAuthToken(account),
|
|
306
|
+
"Accept": "application/vnd.pagerduty+json;version=2",
|
|
307
|
+
"Content-Type": "application/json"
|
|
308
|
+
},
|
|
309
|
+
body: JSON.stringify({
|
|
310
|
+
relationships: serviceRelations
|
|
311
|
+
})
|
|
312
|
+
};
|
|
313
|
+
const apiBaseUrl = getApiBaseUrl(account);
|
|
314
|
+
const baseUrl = `${apiBaseUrl}/service_dependencies/disassociate`;
|
|
315
|
+
console.log(`Removing service relations: ${JSON.stringify({ relationships: serviceRelations })}`);
|
|
316
|
+
try {
|
|
317
|
+
response = await fetchWithRetries(`${baseUrl}`, options);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
throw new Error(`Failed to retrieve service dependencies: ${error}`);
|
|
320
|
+
}
|
|
321
|
+
if (response.status >= 500) {
|
|
322
|
+
throw new backstagePluginCommon.HttpError(`Failed to remove service dependencies. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
323
|
+
}
|
|
324
|
+
switch (response.status) {
|
|
325
|
+
case 400:
|
|
326
|
+
throw new backstagePluginCommon.HttpError("Failed to remove service dependencies. Caller provided invalid arguments. Please review the response for error details. Retrying with the same arguments will not work.", 400);
|
|
327
|
+
case 401:
|
|
328
|
+
throw new backstagePluginCommon.HttpError("Failed to remove service dependencies. Caller did not supply credentials or did not provide the correct credentials. If you are using an API key, it may be invalid or your Authorization header may be malformed.", 401);
|
|
329
|
+
case 403:
|
|
330
|
+
throw new backstagePluginCommon.HttpError("Failed to remove service dependencies. Caller is not authorized to view the requested resource. While your authentication is valid, the authenticated user or token does not have permission to perform this action.", 403);
|
|
331
|
+
case 404:
|
|
332
|
+
throw new backstagePluginCommon.HttpError("Failed to remove service dependencies. The requested resource was not found.", 404);
|
|
333
|
+
}
|
|
334
|
+
let result;
|
|
335
|
+
try {
|
|
336
|
+
result = await response.json();
|
|
337
|
+
return result.relationships;
|
|
338
|
+
} catch (error) {
|
|
339
|
+
throw new backstagePluginCommon.HttpError(`Failed to parse service dependency information: ${error}`, 500);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
async function getServiceRelationshipsById(serviceId, account) {
|
|
343
|
+
let response;
|
|
344
|
+
const options = {
|
|
345
|
+
method: "GET",
|
|
346
|
+
headers: {
|
|
347
|
+
Authorization: await getAuthToken(account),
|
|
348
|
+
"Accept": "application/vnd.pagerduty+json;version=2",
|
|
349
|
+
"Content-Type": "application/json"
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const apiBaseUrl = getApiBaseUrl(account);
|
|
353
|
+
const baseUrl = `${apiBaseUrl}/service_dependencies/technical_services/${serviceId}`;
|
|
354
|
+
try {
|
|
355
|
+
response = await fetchWithRetries(`${baseUrl}`, options);
|
|
356
|
+
} catch (error) {
|
|
357
|
+
throw new Error(`Failed to retrieve service dependencies: ${error}`);
|
|
358
|
+
}
|
|
359
|
+
if (response.status >= 500) {
|
|
360
|
+
throw new backstagePluginCommon.HttpError(`Failed to list service dependencies. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
361
|
+
}
|
|
362
|
+
switch (response.status) {
|
|
363
|
+
case 400:
|
|
364
|
+
throw new backstagePluginCommon.HttpError("Failed to list service dependencies. Caller provided invalid arguments. Please review the response for error details. Retrying with the same arguments will not work.", 400);
|
|
365
|
+
case 401:
|
|
366
|
+
throw new backstagePluginCommon.HttpError("Failed to list service dependencies. Caller did not supply credentials or did not provide the correct credentials. If you are using an API key, it may be invalid or your Authorization header may be malformed.", 401);
|
|
367
|
+
case 403:
|
|
368
|
+
throw new backstagePluginCommon.HttpError("Failed to list service dependencies. Caller is not authorized to view the requested resource. While your authentication is valid, the authenticated user or token does not have permission to perform this action.", 403);
|
|
369
|
+
case 404:
|
|
370
|
+
throw new backstagePluginCommon.HttpError("Failed to list service dependencies. The requested resource was not found.", 404);
|
|
371
|
+
}
|
|
372
|
+
let result;
|
|
373
|
+
try {
|
|
374
|
+
result = await response.json();
|
|
375
|
+
return result.relationships;
|
|
376
|
+
} catch (error) {
|
|
377
|
+
throw new backstagePluginCommon.HttpError(`Failed to parse service dependency information: ${error}`, 500);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
258
380
|
async function getEscalationPolicies(offset, limit, account) {
|
|
259
381
|
var _a;
|
|
260
382
|
let response;
|
|
@@ -270,10 +392,13 @@ async function getEscalationPolicies(offset, limit, account) {
|
|
|
270
392
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
271
393
|
const baseUrl = `${apiBaseUrl}/escalation_policies`;
|
|
272
394
|
try {
|
|
273
|
-
response = await
|
|
395
|
+
response = await fetchWithRetries(`${baseUrl}?${params}`, options);
|
|
274
396
|
} catch (error) {
|
|
275
397
|
throw new Error(`Failed to retrieve escalation policies: ${error}`);
|
|
276
398
|
}
|
|
399
|
+
if (response.status >= 500) {
|
|
400
|
+
throw new backstagePluginCommon.HttpError(`Failed to list escalation policies. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
401
|
+
}
|
|
277
402
|
switch (response.status) {
|
|
278
403
|
case 400:
|
|
279
404
|
throw new backstagePluginCommon.HttpError("Failed to list escalation policies. Caller provided invalid arguments.", 400);
|
|
@@ -339,10 +464,13 @@ async function getOncallUsers(escalationPolicy, account) {
|
|
|
339
464
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
340
465
|
const baseUrl = `${apiBaseUrl}/oncalls`;
|
|
341
466
|
try {
|
|
342
|
-
response = await
|
|
467
|
+
response = await fetchWithRetries(`${baseUrl}?${params}`, options);
|
|
343
468
|
} catch (error) {
|
|
344
469
|
throw new Error(`Failed to retrieve oncalls: ${error}`);
|
|
345
470
|
}
|
|
471
|
+
if (response.status >= 500) {
|
|
472
|
+
throw new backstagePluginCommon.HttpError(`Failed to list oncalls. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
473
|
+
}
|
|
346
474
|
switch (response.status) {
|
|
347
475
|
case 400:
|
|
348
476
|
throw new backstagePluginCommon.HttpError("Failed to list oncalls. Caller provided invalid arguments.", 400);
|
|
@@ -395,10 +523,13 @@ async function getServiceById(serviceId, account) {
|
|
|
395
523
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
396
524
|
const baseUrl = `${apiBaseUrl}/services`;
|
|
397
525
|
try {
|
|
398
|
-
response = await
|
|
526
|
+
response = await fetchWithRetries(`${baseUrl}/${serviceId}?${params}`, options);
|
|
399
527
|
} catch (error) {
|
|
400
528
|
throw new Error(`Failed to retrieve service: ${error}`);
|
|
401
529
|
}
|
|
530
|
+
if (response.status >= 500) {
|
|
531
|
+
throw new backstagePluginCommon.HttpError(`Failed to get service. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
532
|
+
}
|
|
402
533
|
switch (response.status) {
|
|
403
534
|
case 400:
|
|
404
535
|
throw new backstagePluginCommon.HttpError("Failed to get service. Caller provided invalid arguments.", 400);
|
|
@@ -432,10 +563,13 @@ async function getServiceByIntegrationKey(integrationKey, account) {
|
|
|
432
563
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
433
564
|
const baseUrl = `${apiBaseUrl}/services`;
|
|
434
565
|
try {
|
|
435
|
-
response = await
|
|
566
|
+
response = await fetchWithRetries(`${baseUrl}?${params}`, options);
|
|
436
567
|
} catch (error) {
|
|
437
568
|
throw new Error(`Failed to retrieve service: ${error}`);
|
|
438
569
|
}
|
|
570
|
+
if (response.status >= 500) {
|
|
571
|
+
throw new backstagePluginCommon.HttpError(`Failed to get service. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
572
|
+
}
|
|
439
573
|
switch (response.status) {
|
|
440
574
|
case 400:
|
|
441
575
|
throw new backstagePluginCommon.HttpError("Failed to get service. Caller provided invalid arguments.", 400);
|
|
@@ -480,7 +614,10 @@ async function getAllServices() {
|
|
|
480
614
|
try {
|
|
481
615
|
do {
|
|
482
616
|
const paginatedUrl = `${baseUrl}?${params}&offset=${offset}&limit=${limit}`;
|
|
483
|
-
response = await
|
|
617
|
+
response = await fetchWithRetries(paginatedUrl, options);
|
|
618
|
+
if (response.status >= 500) {
|
|
619
|
+
throw new backstagePluginCommon.HttpError(`Failed to get services. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
620
|
+
}
|
|
484
621
|
switch (response.status) {
|
|
485
622
|
case 400:
|
|
486
623
|
throw new backstagePluginCommon.HttpError("Failed to get services. Caller provided invalid arguments.", 400);
|
|
@@ -519,10 +656,13 @@ async function getChangeEvents(serviceId, account) {
|
|
|
519
656
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
520
657
|
const baseUrl = `${apiBaseUrl}/services`;
|
|
521
658
|
try {
|
|
522
|
-
response = await
|
|
659
|
+
response = await fetchWithRetries(`${baseUrl}/${serviceId}/change_events?${params}`, options);
|
|
523
660
|
} catch (error) {
|
|
524
661
|
throw new Error(`Failed to retrieve change events for service: ${error}`);
|
|
525
662
|
}
|
|
663
|
+
if (response.status >= 500) {
|
|
664
|
+
throw new backstagePluginCommon.HttpError(`Failed to get change events for service. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
665
|
+
}
|
|
526
666
|
switch (response.status) {
|
|
527
667
|
case 400:
|
|
528
668
|
throw new backstagePluginCommon.HttpError("Failed to get change events for service. Caller provided invalid arguments.", 400);
|
|
@@ -555,10 +695,13 @@ async function getIncidents(serviceId, account) {
|
|
|
555
695
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
556
696
|
const baseUrl = `${apiBaseUrl}/incidents`;
|
|
557
697
|
try {
|
|
558
|
-
response = await
|
|
698
|
+
response = await fetchWithRetries(`${baseUrl}?${params}`, options);
|
|
559
699
|
} catch (error) {
|
|
560
700
|
throw new Error(`Failed to retrieve incidents for service: ${error}`);
|
|
561
701
|
}
|
|
702
|
+
if (response.status >= 500) {
|
|
703
|
+
throw new backstagePluginCommon.HttpError(`Failed to get incidents for service. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
704
|
+
}
|
|
562
705
|
switch (response.status) {
|
|
563
706
|
case 400:
|
|
564
707
|
throw new backstagePluginCommon.HttpError("Failed to get incidents for service. Caller provided invalid arguments.", 400);
|
|
@@ -592,10 +735,13 @@ async function getServiceStandards(serviceId, account) {
|
|
|
592
735
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
593
736
|
const baseUrl = `${apiBaseUrl}/standards/scores/technical_services/${serviceId}`;
|
|
594
737
|
try {
|
|
595
|
-
response = await
|
|
738
|
+
response = await fetchWithRetries(baseUrl, options);
|
|
596
739
|
} catch (error) {
|
|
597
740
|
throw new Error(`Failed to retrieve service standards for service: ${error}`);
|
|
598
741
|
}
|
|
742
|
+
if (response.status >= 500) {
|
|
743
|
+
throw new backstagePluginCommon.HttpError(`Failed to get service standards for service. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
744
|
+
}
|
|
599
745
|
switch (response.status) {
|
|
600
746
|
case 401:
|
|
601
747
|
throw new backstagePluginCommon.HttpError("Failed to get service standards for service. Caller did not supply credentials or did not provide the correct credentials.", 401);
|
|
@@ -636,10 +782,13 @@ async function getServiceMetrics(serviceId, account) {
|
|
|
636
782
|
const apiBaseUrl = getApiBaseUrl(account);
|
|
637
783
|
const baseUrl = `${apiBaseUrl}/analytics/metrics/incidents/services`;
|
|
638
784
|
try {
|
|
639
|
-
response = await
|
|
785
|
+
response = await fetchWithRetries(baseUrl, options);
|
|
640
786
|
} catch (error) {
|
|
641
787
|
throw new Error(`Failed to retrieve service metrics for service: ${error}`);
|
|
642
788
|
}
|
|
789
|
+
if (response.status >= 500) {
|
|
790
|
+
throw new backstagePluginCommon.HttpError(`Failed to get service metrics for service. PagerDuty API returned a server error. Retrying with the same arguments will not work.`, response.status);
|
|
791
|
+
}
|
|
643
792
|
switch (response.status) {
|
|
644
793
|
case 400:
|
|
645
794
|
throw new backstagePluginCommon.HttpError("Failed to get service metrics for service. Caller provided invalid arguments. Please review the response for error details. Retrying with the same arguments will not work.", 400);
|
|
@@ -653,14 +802,84 @@ async function getServiceMetrics(serviceId, account) {
|
|
|
653
802
|
throw new backstagePluginCommon.HttpError(`Failed to parse service metrics information: ${error}`, 500);
|
|
654
803
|
}
|
|
655
804
|
}
|
|
805
|
+
async function createServiceIntegration({ serviceId, vendorId, account }) {
|
|
806
|
+
var _a;
|
|
807
|
+
let response;
|
|
808
|
+
const apiBaseUrl = getApiBaseUrl(account);
|
|
809
|
+
const baseUrl = `${apiBaseUrl}/services`;
|
|
810
|
+
const token = await getAuthToken(account);
|
|
811
|
+
const options = {
|
|
812
|
+
method: "POST",
|
|
813
|
+
body: JSON.stringify({
|
|
814
|
+
integration: {
|
|
815
|
+
name: "Backstage",
|
|
816
|
+
service: {
|
|
817
|
+
id: serviceId,
|
|
818
|
+
type: "service_reference"
|
|
819
|
+
},
|
|
820
|
+
vendor: {
|
|
821
|
+
id: vendorId,
|
|
822
|
+
type: "vendor_reference"
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}),
|
|
826
|
+
headers: {
|
|
827
|
+
Authorization: token,
|
|
828
|
+
"Accept": "application/vnd.pagerduty+json;version=2",
|
|
829
|
+
"Content-Type": "application/json"
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
try {
|
|
833
|
+
response = await fetchWithRetries(`${baseUrl}/${serviceId}/integrations`, options);
|
|
834
|
+
} catch (error) {
|
|
835
|
+
throw new Error(`Failed to create service integration: ${error}`);
|
|
836
|
+
}
|
|
837
|
+
if (response.status >= 500) {
|
|
838
|
+
throw new Error(`Failed to create service integration. PagerDuty API returned a server error. Retrying with the same arguments will not work.`);
|
|
839
|
+
}
|
|
840
|
+
switch (response.status) {
|
|
841
|
+
case 400:
|
|
842
|
+
throw new Error(`Failed to create service integration. Caller provided invalid arguments.`);
|
|
843
|
+
case 401:
|
|
844
|
+
throw new Error(`Failed to create service integration. Caller did not supply credentials or did not provide the correct credentials.`);
|
|
845
|
+
case 403:
|
|
846
|
+
throw new Error(`Failed to create service integration. Caller is not authorized to view the requested resource.`);
|
|
847
|
+
case 429:
|
|
848
|
+
throw new Error(`Failed to create service integration. Rate limit exceeded.`);
|
|
849
|
+
}
|
|
850
|
+
let result;
|
|
851
|
+
try {
|
|
852
|
+
result = await response.json();
|
|
853
|
+
return (_a = result.integration.integration_key) != null ? _a : "";
|
|
854
|
+
} catch (error) {
|
|
855
|
+
throw new Error(`Failed to parse service information: ${error}`);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
async function fetchWithRetries(url, options) {
|
|
859
|
+
let response;
|
|
860
|
+
let error = new Error();
|
|
861
|
+
const maxRetries = 5;
|
|
862
|
+
const delay = 1e3;
|
|
863
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
864
|
+
try {
|
|
865
|
+
response = await fetch__default.default(url, options);
|
|
866
|
+
return response;
|
|
867
|
+
} catch (e) {
|
|
868
|
+
error = e;
|
|
869
|
+
}
|
|
870
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
871
|
+
}
|
|
872
|
+
throw new Error(`Failed to fetch data after ${maxRetries} retries. Last error: ${error}`);
|
|
873
|
+
}
|
|
656
874
|
|
|
657
875
|
async function createComponentEntitiesReferenceDict({ items: componentEntities }) {
|
|
658
876
|
const componentEntitiesDict = {};
|
|
659
877
|
await Promise.all(componentEntities.map(async (entity) => {
|
|
660
|
-
var _a
|
|
661
|
-
const
|
|
662
|
-
const
|
|
663
|
-
const
|
|
878
|
+
var _a;
|
|
879
|
+
const annotations = JSON.parse(JSON.stringify(entity.metadata.annotations));
|
|
880
|
+
const serviceId = annotations["pagerduty.com/service-id"];
|
|
881
|
+
const integrationKey = annotations["pagerduty.com/integration-key"];
|
|
882
|
+
const account = (_a = annotations["pagerduty.com/account"]) != null ? _a : "";
|
|
664
883
|
if (serviceId !== void 0 && serviceId !== "") {
|
|
665
884
|
componentEntitiesDict[serviceId] = {
|
|
666
885
|
ref: `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase(),
|
|
@@ -799,9 +1018,198 @@ async function createRouter(options) {
|
|
|
799
1018
|
}
|
|
800
1019
|
await loadAuthConfig(config, logger);
|
|
801
1020
|
loadPagerDutyEndpointsFromConfig(config, logger);
|
|
802
|
-
const router = Router__default
|
|
1021
|
+
const router = Router__default.default();
|
|
803
1022
|
router.use(express__namespace.json());
|
|
1023
|
+
router.delete("/dependencies/service/:serviceId", async (request, response) => {
|
|
1024
|
+
try {
|
|
1025
|
+
const serviceId = request.params.serviceId || "";
|
|
1026
|
+
const account = request.query.account || "";
|
|
1027
|
+
if (serviceId === "") {
|
|
1028
|
+
logger.info(`Bad Request: ':serviceId' must be provided as part of the path`);
|
|
1029
|
+
response.status(400).json("Bad Request: ':serviceId' must be provided as part of the path");
|
|
1030
|
+
}
|
|
1031
|
+
const dependencies = request.body;
|
|
1032
|
+
if (!dependencies || dependencies.length === 0) {
|
|
1033
|
+
logger.info(`Bad Request: 'dependencies' must be provided as part of the request body`);
|
|
1034
|
+
response.status(400).json("Bad Request: 'dependencies' must be provided as part of the request body");
|
|
1035
|
+
}
|
|
1036
|
+
logger.info(`Received dependencies to remove from PagerDuty: ${JSON.stringify(dependencies)}`);
|
|
1037
|
+
const serviceRelations = [];
|
|
1038
|
+
dependencies.forEach(async (dependency) => {
|
|
1039
|
+
serviceRelations.push({
|
|
1040
|
+
supporting_service: {
|
|
1041
|
+
id: dependency,
|
|
1042
|
+
type: "service"
|
|
1043
|
+
},
|
|
1044
|
+
dependent_service: {
|
|
1045
|
+
id: serviceId,
|
|
1046
|
+
type: "service"
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
});
|
|
1050
|
+
await removeServiceRelationsFromService(serviceRelations, account);
|
|
1051
|
+
response.sendStatus(200);
|
|
1052
|
+
} catch (error) {
|
|
1053
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1054
|
+
logger.error(`Error occurred while processing request: ${error.message}`);
|
|
1055
|
+
response.status(error.status).json({
|
|
1056
|
+
errors: [
|
|
1057
|
+
`${error.message}`
|
|
1058
|
+
]
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
router.post("/dependencies/service/:serviceId", async (request, response) => {
|
|
1064
|
+
try {
|
|
1065
|
+
logger.info(`Received params : ${JSON.stringify(request.params)}`);
|
|
1066
|
+
const serviceId = request.params.serviceId || "";
|
|
1067
|
+
const account = request.query.account || "";
|
|
1068
|
+
if (serviceId === "") {
|
|
1069
|
+
logger.info(`Bad Request: ':serviceId' must be provided as part of the path`);
|
|
1070
|
+
response.status(400).json("Bad Request: ':serviceId' must be provided as part of the path");
|
|
1071
|
+
}
|
|
1072
|
+
const dependencies = request.body;
|
|
1073
|
+
if (!dependencies || dependencies.length === 0) {
|
|
1074
|
+
logger.info(`Bad Request: 'dependencies' must be provided as part of the request body`);
|
|
1075
|
+
response.status(400).json("Bad Request: 'dependencies' must be provided as part of the request body");
|
|
1076
|
+
}
|
|
1077
|
+
logger.info(`Received dependencies to add to PagerDuty: ${JSON.stringify(dependencies)}`);
|
|
1078
|
+
const serviceRelations = [];
|
|
1079
|
+
dependencies.forEach(async (dependency) => {
|
|
1080
|
+
serviceRelations.push({
|
|
1081
|
+
supporting_service: {
|
|
1082
|
+
id: dependency,
|
|
1083
|
+
type: "service"
|
|
1084
|
+
},
|
|
1085
|
+
dependent_service: {
|
|
1086
|
+
id: serviceId,
|
|
1087
|
+
type: "service"
|
|
1088
|
+
}
|
|
1089
|
+
});
|
|
1090
|
+
});
|
|
1091
|
+
await addServiceRelationsToService(serviceRelations, account);
|
|
1092
|
+
response.sendStatus(200);
|
|
1093
|
+
} catch (error) {
|
|
1094
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1095
|
+
logger.error(`Error occurred while processing request: ${error.message}`);
|
|
1096
|
+
response.status(error.status).json({
|
|
1097
|
+
errors: [
|
|
1098
|
+
`${error.message}`
|
|
1099
|
+
]
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
router.get("/dependencies/service/:serviceId", async (request, response) => {
|
|
1105
|
+
try {
|
|
1106
|
+
const serviceId = request.params.serviceId;
|
|
1107
|
+
const account = request.query.account || "";
|
|
1108
|
+
if (serviceId) {
|
|
1109
|
+
const serviceRelationships = await getServiceRelationshipsById(serviceId, account);
|
|
1110
|
+
if (serviceRelationships && serviceRelationships.length > 0) {
|
|
1111
|
+
response.json({
|
|
1112
|
+
relationships: serviceRelationships
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
} else {
|
|
1116
|
+
response.status(400).json("Bad Request: ':serviceId' must be provided as part of the path");
|
|
1117
|
+
}
|
|
1118
|
+
response.status(404);
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1121
|
+
response.status(error.status).json({
|
|
1122
|
+
errors: [
|
|
1123
|
+
`${error.message}`
|
|
1124
|
+
]
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
router.get("/catalog/entity/:type/:namespace/:name", async (request, response) => {
|
|
1130
|
+
var _a;
|
|
1131
|
+
const type = request.params.type;
|
|
1132
|
+
const namespace = request.params.namespace;
|
|
1133
|
+
const name = request.params.name;
|
|
1134
|
+
try {
|
|
1135
|
+
if (type && namespace && name) {
|
|
1136
|
+
const entityRef = `${type}:${namespace}/${name}`.toLowerCase();
|
|
1137
|
+
const foundEntity = await (catalogApi == null ? void 0 : catalogApi.getEntityByRef(entityRef));
|
|
1138
|
+
if (foundEntity) {
|
|
1139
|
+
response.json((_a = foundEntity.metadata.annotations) == null ? void 0 : _a["pagerduty.com/service-id"]);
|
|
1140
|
+
} else {
|
|
1141
|
+
response.status(404);
|
|
1142
|
+
}
|
|
1143
|
+
} else {
|
|
1144
|
+
response.status(400).json("Bad Request: ':entityRef' must be provided as part of the path");
|
|
1145
|
+
}
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1148
|
+
response.status(error.status).json({
|
|
1149
|
+
errors: [
|
|
1150
|
+
`${error.message}`
|
|
1151
|
+
]
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
router.post("/settings", async (request, response) => {
|
|
1157
|
+
try {
|
|
1158
|
+
const settings = request.body;
|
|
1159
|
+
logger.info(`Received settings: ${JSON.stringify(settings)}`);
|
|
1160
|
+
await Promise.all(settings.map(async (setting) => {
|
|
1161
|
+
logger.info(`Processing setting: ${JSON.stringify(setting)}`);
|
|
1162
|
+
if (setting.id === void 0 || setting.value === void 0) {
|
|
1163
|
+
logger.info(`Bad Request: 'id' and 'value' are required`);
|
|
1164
|
+
response.status(400).json("Bad Request: 'id' and 'value' are required");
|
|
1165
|
+
}
|
|
1166
|
+
if (!isValidSetting(setting.value)) {
|
|
1167
|
+
logger.info(`Bad Request: 'value' is invalid`);
|
|
1168
|
+
response.status(400).json("Bad Request: 'value' is invalid. Valid options are 'backstage', 'pagerduty', 'both' or 'disabled'");
|
|
1169
|
+
}
|
|
1170
|
+
logger.info(`Setting value is valid: ${setting.value}`);
|
|
1171
|
+
await store.updateSetting(setting);
|
|
1172
|
+
logger.info(`Setting updated: ${JSON.stringify(setting)}`);
|
|
1173
|
+
}));
|
|
1174
|
+
response.sendStatus(200);
|
|
1175
|
+
} catch (error) {
|
|
1176
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1177
|
+
logger.error(`Error occurred while processing request: ${error.message}`);
|
|
1178
|
+
response.status(error.status).json({
|
|
1179
|
+
errors: [
|
|
1180
|
+
`${error.message}`
|
|
1181
|
+
]
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
router.get("/settings/:settingId", async (request, response) => {
|
|
1187
|
+
try {
|
|
1188
|
+
const settingId = request.params.settingId;
|
|
1189
|
+
const setting = await store.findSetting(settingId);
|
|
1190
|
+
if (!setting) {
|
|
1191
|
+
response.status(404).json(`Setting with id ${settingId} not found.`);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
response.json(setting);
|
|
1195
|
+
} catch (error) {
|
|
1196
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1197
|
+
response.status(error.status).json({
|
|
1198
|
+
errors: [
|
|
1199
|
+
`${error.message}`
|
|
1200
|
+
]
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
});
|
|
1205
|
+
function isValidSetting(value) {
|
|
1206
|
+
if (value === "backstage" || value === "pagerduty" || value === "both" || value === "disabled") {
|
|
1207
|
+
return true;
|
|
1208
|
+
}
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
804
1211
|
router.post("/mapping/entity", async (request, response) => {
|
|
1212
|
+
var _a;
|
|
805
1213
|
try {
|
|
806
1214
|
const entity = request.body;
|
|
807
1215
|
if (!entity.serviceId) {
|
|
@@ -809,6 +1217,24 @@ async function createRouter(options) {
|
|
|
809
1217
|
}
|
|
810
1218
|
const entityMappings = await store.getAllEntityMappings();
|
|
811
1219
|
const oldMapping = entityMappings.find((mapping) => mapping.serviceId === entity.serviceId);
|
|
1220
|
+
if (entity.entityRef !== "" && (entity.integrationKey === "" || entity.integrationKey === void 0)) {
|
|
1221
|
+
const backstageVendorId = "PRO19CT";
|
|
1222
|
+
const service = await getServiceById(entity.serviceId, entity.account);
|
|
1223
|
+
const backstageIntegration = (_a = service.integrations) == null ? void 0 : _a.find((integration) => {
|
|
1224
|
+
var _a2;
|
|
1225
|
+
return ((_a2 = integration.vendor) == null ? void 0 : _a2.id) === backstageVendorId;
|
|
1226
|
+
});
|
|
1227
|
+
if (!backstageIntegration) {
|
|
1228
|
+
const integrationKey = await createServiceIntegration({
|
|
1229
|
+
serviceId: entity.serviceId,
|
|
1230
|
+
vendorId: backstageVendorId,
|
|
1231
|
+
account: entity.account
|
|
1232
|
+
});
|
|
1233
|
+
entity.integrationKey = integrationKey;
|
|
1234
|
+
} else {
|
|
1235
|
+
entity.integrationKey = backstageIntegration.integration_key;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
812
1238
|
const entityMappingId = await store.insertEntityMapping(entity);
|
|
813
1239
|
if (entity.entityRef !== "") {
|
|
814
1240
|
await (catalogApi == null ? void 0 : catalogApi.refreshEntity(entity.entityRef));
|
|
@@ -838,16 +1264,13 @@ async function createRouter(options) {
|
|
|
838
1264
|
router.get("/mapping/entity", async (_, response) => {
|
|
839
1265
|
try {
|
|
840
1266
|
const entityMappings = await store.getAllEntityMappings();
|
|
841
|
-
logger.info(`Retrieved ${entityMappings.length} entity mappings from the database.`);
|
|
842
1267
|
const componentEntities = await catalogApi.getEntities({
|
|
843
1268
|
filter: {
|
|
844
1269
|
kind: "Component"
|
|
845
1270
|
}
|
|
846
1271
|
});
|
|
847
|
-
logger.info(`Retrieved ${componentEntities.items.length} entities from the catalog.`);
|
|
848
1272
|
const componentEntitiesDict = await createComponentEntitiesReferenceDict(componentEntities);
|
|
849
1273
|
const pagerDutyServices = await getAllServices();
|
|
850
|
-
logger.info(`Retrieved ${pagerDutyServices.length} services from PagerDuty.`);
|
|
851
1274
|
const result = await buildEntityMappingsResponse(entityMappings, componentEntitiesDict, componentEntities, pagerDutyServices);
|
|
852
1275
|
response.json(result);
|
|
853
1276
|
} catch (error) {
|
|
@@ -888,6 +1311,32 @@ async function createRouter(options) {
|
|
|
888
1311
|
}
|
|
889
1312
|
}
|
|
890
1313
|
});
|
|
1314
|
+
router.get("/mapping/entity/service/:serviceId", async (request, response) => {
|
|
1315
|
+
var _a;
|
|
1316
|
+
try {
|
|
1317
|
+
const serviceId = (_a = request.params.serviceId) != null ? _a : "";
|
|
1318
|
+
if (serviceId === "") {
|
|
1319
|
+
response.status(400).json("Required params not specified.");
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
const entityMapping = await store.findEntityMappingByServiceId(serviceId);
|
|
1323
|
+
if (!entityMapping) {
|
|
1324
|
+
response.status(404).json(`Mapping for serviceId ${serviceId} not found.`);
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
response.json({
|
|
1328
|
+
mapping: entityMapping
|
|
1329
|
+
});
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1332
|
+
response.status(error.status).json({
|
|
1333
|
+
errors: [
|
|
1334
|
+
`${error.message}`
|
|
1335
|
+
]
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
891
1340
|
router.get("/escalation_policies", async (_, response) => {
|
|
892
1341
|
try {
|
|
893
1342
|
let escalationPolicyList = await getAllEscalationPolicies();
|
|
@@ -989,6 +1438,31 @@ async function createRouter(options) {
|
|
|
989
1438
|
}
|
|
990
1439
|
}
|
|
991
1440
|
});
|
|
1441
|
+
router.post("/services/:serviceId/integration/:vendorId", async (request, response) => {
|
|
1442
|
+
try {
|
|
1443
|
+
const serviceId = request.params.serviceId || "";
|
|
1444
|
+
const vendorId = request.params.vendorId || "";
|
|
1445
|
+
const account = request.query.account || "";
|
|
1446
|
+
if (serviceId === "" || vendorId === "") {
|
|
1447
|
+
response.status(400).json("Bad Request: ':serviceId' and ':vendorId' must be provided as part of the path");
|
|
1448
|
+
}
|
|
1449
|
+
const integrationKey = await createServiceIntegration({
|
|
1450
|
+
serviceId,
|
|
1451
|
+
vendorId,
|
|
1452
|
+
account
|
|
1453
|
+
});
|
|
1454
|
+
response.json(integrationKey);
|
|
1455
|
+
} catch (error) {
|
|
1456
|
+
if (error instanceof backstagePluginCommon.HttpError) {
|
|
1457
|
+
logger.error(`Error occurred while processing request: ${error.message}`);
|
|
1458
|
+
response.status(error.status).json({
|
|
1459
|
+
errors: [
|
|
1460
|
+
`${error.message}`
|
|
1461
|
+
]
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
});
|
|
992
1466
|
router.get("/services/:serviceId/change-events", async (request, response) => {
|
|
993
1467
|
try {
|
|
994
1468
|
const serviceId = request.params.serviceId || "";
|
|
@@ -1108,6 +1582,28 @@ class PagerDutyBackendDatabase {
|
|
|
1108
1582
|
const rawEntity = await this.db("pagerduty_entity_mapping").where("entityRef", entityRef).first();
|
|
1109
1583
|
return rawEntity;
|
|
1110
1584
|
}
|
|
1585
|
+
async findEntityMappingByServiceId(serviceId) {
|
|
1586
|
+
const rawEntity = await this.db("pagerduty_entity_mapping").where("serviceId", serviceId).first();
|
|
1587
|
+
return rawEntity;
|
|
1588
|
+
}
|
|
1589
|
+
async updateSetting(setting) {
|
|
1590
|
+
const [result] = await this.db("pagerduty_settings").insert({
|
|
1591
|
+
id: setting.id,
|
|
1592
|
+
value: setting.value
|
|
1593
|
+
}).onConflict(["id"]).merge(["value"]).returning("id");
|
|
1594
|
+
return result.id;
|
|
1595
|
+
}
|
|
1596
|
+
async findSetting(settingId) {
|
|
1597
|
+
const rawEntity = await this.db("pagerduty_settings").where("id", settingId).first();
|
|
1598
|
+
return rawEntity;
|
|
1599
|
+
}
|
|
1600
|
+
async getAllSettings() {
|
|
1601
|
+
const rawEntities = await this.db("pagerduty_settings");
|
|
1602
|
+
if (!rawEntities) {
|
|
1603
|
+
return [];
|
|
1604
|
+
}
|
|
1605
|
+
return rawEntities;
|
|
1606
|
+
}
|
|
1111
1607
|
}
|
|
1112
1608
|
|
|
1113
1609
|
class CatalogFetchApi {
|
|
@@ -1168,5 +1664,5 @@ const pagerDutyPlugin = backendPluginApi.createBackendPlugin({
|
|
|
1168
1664
|
exports.buildEntityMappingsResponse = buildEntityMappingsResponse;
|
|
1169
1665
|
exports.createComponentEntitiesReferenceDict = createComponentEntitiesReferenceDict;
|
|
1170
1666
|
exports.createRouter = createRouter;
|
|
1171
|
-
exports
|
|
1667
|
+
exports.default = pagerDutyPlugin;
|
|
1172
1668
|
//# sourceMappingURL=index.cjs.js.map
|