diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 7629c86a1e..ddc8ed4b13 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -135,11 +135,11 @@ const OverviewContent = ({ entity }: { entity: Entity }) => ( - {/* {isPagerDutyAvailable(entity) && ( */} - - - - {/* )} */} + {isPagerDutyAvailable(entity) && ( + + + + )} {isGitHubAvailable(entity) && ( <> diff --git a/plugins/pagerduty/src/api/pagerDutyClient.ts b/plugins/pagerduty/src/api/pagerDutyClient.ts index dc2176680d..dbdc6622f4 100644 --- a/plugins/pagerduty/src/api/pagerDutyClient.ts +++ b/plugins/pagerduty/src/api/pagerDutyClient.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +const API_URL = 'https://api.pagerduty.com'; const EVENTS_API_URL = 'https://events.pagerduty.com/v2'; type Options = { @@ -43,6 +44,49 @@ const request = async ( return await response.json(); }; +const getByUrl = async (url: string, token: string) => { + const options = { + method: 'GET', + headers: { + Authorization: `Token token=${token}`, + Accept: 'application/vnd.pagerduty+json;version=2', + 'Content-Type': 'application/json', + }, + }; + return await request(url, options); +}; + +export const getServiceByIntegrationKey = async ( + integrationKey: string, + token: string, +) => { + const response = await getByUrl( + `${API_URL}/services?include[]=integrations&include[]=escalation_policies&query=${integrationKey}`, + token, + ); + if (response.services.length > 1) { + throw new Error('More than one service in response'); + } + return response.services[0]; +}; + +export const getIncidentsByServiceId = async ( + serviceId: string, + token: string, +) => { + return await getByUrl( + `${API_URL}/incidents?service_ids[]=${serviceId}`, + token, + ); +}; + +export const getOncallByPolicyId = async (policyId: string, token: string) => { + return await getByUrl( + `${API_URL}/oncalls?include[]=users&escalation_policy_ids[]=${policyId}`, + token, + ); +}; + export function triggerPagerDutyAlarm( integrationKey: string, source: string, diff --git a/plugins/pagerduty/src/components/Escalation.tsx b/plugins/pagerduty/src/components/Escalation.tsx index 74e253d516..69a4543c4b 100644 --- a/plugins/pagerduty/src/components/Escalation.tsx +++ b/plugins/pagerduty/src/components/Escalation.tsx @@ -102,8 +102,8 @@ type EscalationPolicyProps = { export const EscalationPolicy = ({ escalation }: EscalationPolicyProps) => ( Escalation Policy}> {escalation.length ? ( - escalation.map((user, index) => ( - + escalation.map((item, index) => ( + )) ) : ( diff --git a/plugins/pagerduty/src/components/Incidents.tsx b/plugins/pagerduty/src/components/Incidents.tsx index 98a26c66db..d2f6fc7128 100644 --- a/plugins/pagerduty/src/components/Incidents.tsx +++ b/plugins/pagerduty/src/components/Incidents.tsx @@ -80,8 +80,9 @@ const IncidentList = ({ incidents }: IncidentListProps) => { primary={incident.title} secondary={ - Created {moment(incident.createdAt).fromNow()}, assigned to{' '} - {(incident.assignees.length && incident.assignees[0].name) || + Created {moment(incident.created_at).fromNow()}, assigned to{' '} + {(incident?.assignments[0]?.assignee?.summary && + incident.assignments[0].assignee.summary) || 'nobody'} } diff --git a/plugins/pagerduty/src/components/PagerDutyServiceCard.tsx b/plugins/pagerduty/src/components/PagerDutyServiceCard.tsx index b7fde8eae3..e17e35a996 100644 --- a/plugins/pagerduty/src/components/PagerDutyServiceCard.tsx +++ b/plugins/pagerduty/src/components/PagerDutyServiceCard.tsx @@ -14,19 +14,18 @@ * limitations under the License. */ import React from 'react'; -import { - InfoCard, - MissingAnnotationEmptyState, - useApi, - configApiRef, -} from '@backstage/core'; +import { InfoCard, useApi, configApiRef } from '@backstage/core'; import { Entity } from '@backstage/catalog-model'; -import { Grid } from '@material-ui/core'; +import { Grid, LinearProgress } from '@material-ui/core'; import { Incidents } from './Incidents'; import { EscalationPolicy } from './Escalation'; -import { PagerDutyData } from './types'; import { TriggerButton } from './TriggerButton'; import { useAsync } from 'react-use'; +import { + getServiceByIntegrationKey, + getIncidentsByServiceId, + getOncallByPolicyId, +} from '../api/pagerDutyClient'; export const PAGERDUTY_INTEGRATION_KEY = 'pagerduty.com/integration-key'; @@ -40,65 +39,63 @@ type Props = { export const PagerDutyServiceCard = ({ entity }: Props) => { const configApi = useApi(configApiRef); - const { value, loading, error } = useAsync(async () => { - const response = await fetch( - `${configApi.getString('backend.baseUrl')}/api/pagerduty/services`, - ); - return await response.json(); - }); - if (value) console.log(value); - if (error) throw new Error(`Error in getting services, ${error}`); + // TODO: handle missing token + const token = configApi.getOptionalString('pagerduty.api.token') ?? undefined; + console.log({ token }); - // TODO: fetch this data - const mockData: PagerDutyData = { - pagerDutyServices: [ - { - activeIncidents: [ - { - id: 'id', - title: 'something happened', - status: 'triggered', - createdAt: '2020:01:01', - homepageUrl: 'url', - assignees: [ - { - name: 'name', - }, - ], - }, - ], - escalationPolicy: [ - { - email: 'user@example.com', - name: 'Name', - homepageUrl: 'https://spotify.pagerduty.com/users/FOO', - id: 'user id', - }, - ], - id: 'id', - name: 'name', - homepageUrl: 'https://spotify.pagety.com/service-directory/BAR', - }, - ], - }; + const { value, loading, error } = useAsync(async () => { + const integrationKey = entity.metadata.annotations![ + PAGERDUTY_INTEGRATION_KEY + ]; + + const service = await getServiceByIntegrationKey(integrationKey, token); + const incidents = await getIncidentsByServiceId( + (service as any).id /*// TODO: fix type */, + token, + ); + const oncalls = await getOncallByPolicyId( + (service as any).escalation_policy.id, // TODO: fix type + token, + ); + + return { + pagerDutyServices: [ + { + activeIncidents: incidents, + escalationPolicy: oncalls, + id: service.id, + name: service.name, + homepageUrl: service.html_url, + }, + ], + }; + }); + + if (error) { + // TODO: use the errorApi + console.log(error); + throw new Error(`Error in getting data: ${error.message}`); + } + + if (loading) { + return ; + } const { activeIncidents, escalationPolicy, homepageUrl, - } = mockData.pagerDutyServices[0]; + } = value!.pagerDutyServices[0]!; const link = { title: 'View in PagerDuty', link: homepageUrl, }; - return !isPluginApplicableToEntity(entity) ? ( - - ) : ( + return ( - - + +