Refactor component to use pagerduty restApi directly
This commit is contained in:
@@ -135,11 +135,11 @@ const OverviewContent = ({ entity }: { entity: Entity }) => (
|
||||
<Grid item md={6}>
|
||||
<AboutCard entity={entity} />
|
||||
</Grid>
|
||||
{/* {isPagerDutyAvailable(entity) && ( */}
|
||||
<Grid item md={6}>
|
||||
<PagerDutyServiceCard entity={entity} />
|
||||
</Grid>
|
||||
{/* )} */}
|
||||
{isPagerDutyAvailable(entity) && (
|
||||
<Grid item md={6}>
|
||||
<PagerDutyServiceCard entity={entity} />
|
||||
</Grid>
|
||||
)}
|
||||
<RecentCICDRunsSwitcher entity={entity} />
|
||||
{isGitHubAvailable(entity) && (
|
||||
<>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -102,8 +102,8 @@ type EscalationPolicyProps = {
|
||||
export const EscalationPolicy = ({ escalation }: EscalationPolicyProps) => (
|
||||
<List dense subheader={<ListSubheader>Escalation Policy</ListSubheader>}>
|
||||
{escalation.length ? (
|
||||
escalation.map((user, index) => (
|
||||
<EscalationUser key={user.id + index} user={user} />
|
||||
escalation.map((item, index) => (
|
||||
<EscalationUser key={item.user.id + index} user={item.user} />
|
||||
))
|
||||
) : (
|
||||
<EscalationUsersEmptyState />
|
||||
|
||||
@@ -80,8 +80,9 @@ const IncidentList = ({ incidents }: IncidentListProps) => {
|
||||
primary={incident.title}
|
||||
secondary={
|
||||
<span style={{ wordBreak: 'break-all', whiteSpace: 'normal' }}>
|
||||
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'}
|
||||
</span>
|
||||
}
|
||||
|
||||
@@ -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 <LinearProgress />;
|
||||
}
|
||||
|
||||
const {
|
||||
activeIncidents,
|
||||
escalationPolicy,
|
||||
homepageUrl,
|
||||
} = mockData.pagerDutyServices[0];
|
||||
} = value!.pagerDutyServices[0]!;
|
||||
|
||||
const link = {
|
||||
title: 'View in PagerDuty',
|
||||
link: homepageUrl,
|
||||
};
|
||||
|
||||
return !isPluginApplicableToEntity(entity) ? (
|
||||
<MissingAnnotationEmptyState annotation={PAGERDUTY_INTEGRATION_KEY} />
|
||||
) : (
|
||||
return (
|
||||
<InfoCard title="PagerDuty" deepLink={link}>
|
||||
<Incidents incidents={activeIncidents} />
|
||||
<EscalationPolicy escalation={escalationPolicy} />
|
||||
<Incidents incidents={activeIncidents.incidents} />
|
||||
<EscalationPolicy escalation={escalationPolicy.oncalls} />
|
||||
<Grid container item xs={12} justify="flex-end">
|
||||
<TriggerButton entity={entity} />
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user