diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index ddc8ed4b13..4fc894ef90 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -68,7 +68,7 @@ import { } from '@roadiehq/backstage-plugin-github-pull-requests'; import { isPluginApplicableToEntity as isPagerDutyAvailable, - PagerDutyServiceCard, + PagerDutyCard, } from '@backstage/plugin-pagerduty'; const CICDSwitcher = ({ entity }: { entity: Entity }) => { @@ -137,7 +137,7 @@ const OverviewContent = ({ entity }: { entity: Entity }) => ( {isPagerDutyAvailable(entity) && ( - + )} diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 43aad8579a..29518bd858 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -24,6 +24,7 @@ "@backstage/theme": "^0.1.1-alpha.25", "@backstage/catalog-model": "^0.1.1-alpha.25", "@backstage/test-utils": "^0.1.1-alpha.25", + "@backstage/plugin-catalog": "^0.1.1-alpha.25", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", diff --git a/plugins/pagerduty/src/api/pagerDutyClient.ts b/plugins/pagerduty/src/api/client.ts similarity index 68% rename from plugins/pagerduty/src/api/pagerDutyClient.ts rename to plugins/pagerduty/src/api/client.ts index 7b1aa442c3..985bb25e5a 100644 --- a/plugins/pagerduty/src/api/pagerDutyClient.ts +++ b/plugins/pagerduty/src/api/client.ts @@ -25,55 +25,41 @@ import { OnCallsResponse, OnCall, } from '../components/types'; +import { PagerDutyClient } from './types'; + +export class UnauthorizedError extends Error { + constructor() { + super(); + } +} export const pagerDutyApiRef = createApiRef({ id: 'plugin.pagerduty.api', description: 'Used to fetch data from PagerDuty API', }); -interface PagerDutyClient { - getServiceByIntegrationKey(integrationKey: string): Promise; - getIncidentsByServiceId(serviceId: string): Promise; - getOnCallByPolicyId(policyId: string): Promise; -} - export class PagerDutyClientApi implements PagerDutyClient { - private API_URL = 'https://api.pagerduty.com'; - private EVENTS_API_URL = 'https://events.pagerduty.com/v2'; - - constructor(private readonly config?: ClientApiConfig) {} + constructor(private readonly config: ClientApiConfig) {} async getServiceByIntegrationKey(integrationKey: string): Promise { - if (!this.config?.token) { - throw new Error('Missing token'); - } - const params = `include[]=integrations&include[]=escalation_policies&query=${integrationKey}`; - const url = `${this.API_URL}/services?${params}`; + const url = `${this.config.api_url}/services?${params}`; const { services } = await this.getByUrl(url); return services; } async getIncidentsByServiceId(serviceId: string): Promise { - if (!this.config?.token) { - throw new Error('Missing token'); - } - const params = `service_ids[]=${serviceId}`; - const url = `${this.API_URL}/incidents?${params}`; + const url = `${this.config.api_url}/incidents?${params}`; const { incidents } = await this.getByUrl(url); return incidents; } async getOnCallByPolicyId(policyId: string): Promise { - if (!this.config?.token) { - throw new Error('Missing token'); - } - const params = `include[]=users&escalation_policy_ids[]=${policyId}`; - const url = `${this.API_URL}/oncalls?${params}`; + const url = `${this.config.api_url}/oncalls?${params}`; const { oncalls } = await this.getByUrl(url); return oncalls; @@ -110,14 +96,13 @@ export class PagerDutyClientApi implements PagerDutyClient { body, }; - return this.request(`${this.EVENTS_API_URL}/enqueue`, options); + return this.request(`${this.config.events_url}/enqueue`, options); } private async getByUrl(url: string): Promise { const options = { method: 'GET', headers: { - Authorization: `Token token=${this.config!.token}`, Accept: 'application/vnd.pagerduty+json;version=2', 'Content-Type': 'application/json', }, @@ -131,17 +116,16 @@ export class PagerDutyClientApi implements PagerDutyClient { url: string, options: RequestOptions, ): Promise { - try { - const response = await fetch(url, options); - if (!response.ok) { - const payload = await response.json(); - const errors = payload.errors.map((error: string) => error).join(' '); - const message = `Request failed with ${response.status}, ${errors}`; - throw new Error(message); - } - return response; - } catch (error) { - throw new Error(error); + const response = await fetch(url, options); + if (response.status === 401) { + throw new UnauthorizedError(); } + if (!response.ok) { + const payload = await response.json(); + const errors = payload.errors.map((error: string) => error).join(' '); + const message = `Request failed with ${response.status}, ${errors}`; + throw new Error(message); + } + return response; } } diff --git a/plugins/pagerduty/src/api/index.ts b/plugins/pagerduty/src/api/index.ts new file mode 100644 index 0000000000..5ac7470475 --- /dev/null +++ b/plugins/pagerduty/src/api/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + PagerDutyClientApi, + pagerDutyApiRef, + UnauthorizedError, +} from './client'; +export type { PagerDutyClient } from './types'; diff --git a/plugins/pagerduty/src/api/types.ts b/plugins/pagerduty/src/api/types.ts new file mode 100644 index 0000000000..cb9d7fc5bc --- /dev/null +++ b/plugins/pagerduty/src/api/types.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Incident, OnCall, Service } from '../components/types'; + +export interface PagerDutyClient { + /** + * Fetches a list of services, filtered by the provided integration key. + * + */ + getServiceByIntegrationKey(integrationKey: string): Promise; + + /** + * Fetches a list of incidents a provided service has. + * + */ + getIncidentsByServiceId(serviceId: string): Promise; + + /** + * Fetches the list of users in an escalation policy. + * + */ + getOnCallByPolicyId(policyId: string): Promise; +} diff --git a/plugins/pagerduty/src/index.ts b/plugins/pagerduty/src/index.ts index b24018887a..58dc39932d 100644 --- a/plugins/pagerduty/src/index.ts +++ b/plugins/pagerduty/src/index.ts @@ -16,5 +16,5 @@ export { plugin } from './plugin'; export { isPluginApplicableToEntity, - PagerDutyServiceCard, -} from './components/PagerDutyServiceCard'; + PagerDutyCard, +} from './components/PagerDutyCard'; diff --git a/plugins/pagerduty/src/plugin.ts b/plugins/pagerduty/src/plugin.ts index 4073551dc8..2e07b5c430 100644 --- a/plugins/pagerduty/src/plugin.ts +++ b/plugins/pagerduty/src/plugin.ts @@ -19,7 +19,7 @@ import { createRouteRef, configApiRef, } from '@backstage/core'; -import { pagerDutyApiRef, PagerDutyClientApi } from './api/pagerDutyClient'; +import { pagerDutyApiRef, PagerDutyClientApi } from './api'; export const rootRouteRef = createRouteRef({ path: '/pagerduty', @@ -34,7 +34,10 @@ export const plugin = createPlugin({ deps: { configApi: configApiRef }, factory: ({ configApi }) => new PagerDutyClientApi({ - token: configApi.getOptionalString('pagerduty.api.token'), + api_url: `${configApi.getString( + 'backend.baseUrl', + )}/api/proxy/pagerduty`, + events_url: 'https://events.pagerduty.com/v2', }), }), ],