From cb672b0502fab6740b0f0004c777d4b2336deb2a Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Fri, 11 Feb 2022 14:44:05 +0000 Subject: [PATCH] Add a discovery API Signed-off-by: Karan Shah --- .../airbrake/dev/components/ApiBar/ApiBar.tsx | 6 ------ .../ContextProvider/ContextProvider.tsx | 5 ----- plugins/airbrake/dev/index.tsx | 8 +++++-- plugins/airbrake/package.json | 2 +- .../airbrake/src/api/ProductionApi.test.ts | 14 ++++++------- plugins/airbrake/src/api/ProductionApi.ts | 6 ++++-- .../src/api/mock/LocalDiscoveryApi.ts | 21 +++++++++++++++++++ plugins/airbrake/src/api/mock/index.ts | 4 +++- .../EntityAirbrakeWidget.test.tsx | 7 ++++--- plugins/airbrake/src/extensions.test.tsx | 2 +- plugins/airbrake/src/plugin.ts | 10 ++++++--- 11 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 plugins/airbrake/src/api/mock/LocalDiscoveryApi.ts diff --git a/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx b/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx index eae00c2d32..7a4ee42f14 100644 --- a/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx +++ b/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx @@ -71,12 +71,6 @@ export const ApiBar = () => { value.setProjectId?.(parseInt(e.target.value, 10) || undefined) } /> - value.setApiKey?.(e.target.value)} - /> )} diff --git a/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx b/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx index 6d7fe0f7f2..d46366d8f6 100644 --- a/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx +++ b/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx @@ -23,23 +23,18 @@ import React, { interface ContextInterface { projectId?: number; setProjectId?: Dispatch>; - apiKey?: string; - setApiKey?: Dispatch>; } export const Context = React.createContext({}); export const ContextProvider = ({ children }: PropsWithChildren<{}>) => { const [projectId, setProjectId] = useState(); - const [apiKey, setApiKey] = useState(''); return ( {children} diff --git a/plugins/airbrake/dev/index.tsx b/plugins/airbrake/dev/index.tsx index cd0d29301f..d2b2d33e40 100644 --- a/plugins/airbrake/dev/index.tsx +++ b/plugins/airbrake/dev/index.tsx @@ -19,13 +19,14 @@ import { TestApiProvider } from '@backstage/test-utils'; import { airbrakePlugin, EntityAirbrakeContent } from '../src'; import { airbrakeApiRef, + localDiscoveryApi, MockAirbrakeApi, ProductionAirbrakeApi, } from '../src/api'; import { ApiBar } from './components/ApiBar'; import { Content, Header, Page } from '@backstage/core-components'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { createEntity } from '../src/api/mock/MockEntity'; +import { createEntity } from '../src/api'; import CloudOffIcon from '@material-ui/icons/CloudOff'; import CloudIcon from '@material-ui/icons/Cloud'; import { Context, ContextProvider } from './components/ContextProvider'; @@ -61,7 +62,10 @@ createDevApp() {value => ( diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index a914013d77..45671a94cd 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -22,6 +22,7 @@ "dependencies": { "@backstage/catalog-model": "^0.9.10", "@backstage/core-components": "^0.8.8", + "@backstage/core-app-api": "^0.5.2", "@backstage/core-plugin-api": "^0.6.0", "@backstage/dev-utils": "^0.2.21", "@backstage/plugin-catalog-react": "^0.6.14", @@ -39,7 +40,6 @@ "devDependencies": { "@backstage/app-defaults": "^0.1.7", "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", "@backstage/dev-utils": "^0.2.21", "@backstage/test-utils": "^0.2.4", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/airbrake/src/api/ProductionApi.test.ts b/plugins/airbrake/src/api/ProductionApi.test.ts index 04bb73caf7..f09127b4c2 100644 --- a/plugins/airbrake/src/api/ProductionApi.test.ts +++ b/plugins/airbrake/src/api/ProductionApi.test.ts @@ -19,21 +19,19 @@ import { rest } from 'msw'; import mockGroupsData from './mock/airbrakeGroupsApiMock.json'; import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { localDiscoveryApi } from './mock'; describe('The production Airbrake API', () => { - const productionApi = new ProductionAirbrakeApi('fakeApiKey'); + const productionApi = new ProductionAirbrakeApi(localDiscoveryApi); const worker = setupServer(); setupRequestMockHandlers(worker); it('fetches groups using the provided project ID', async () => { worker.use( rest.get( - 'https://api.airbrake.io/api/v4/projects/123456/groups', - (req, res, ctx) => { - if (req.url.searchParams.get('key') === 'fakeApiKey') { - return res(ctx.status(200), ctx.json(mockGroupsData)); - } - return res(ctx.status(401)); + 'http://localhost:7007/api/airbrake/api/v4/projects/123456/groups', + (_, res, ctx) => { + return res(ctx.status(200), ctx.json(mockGroupsData)); }, ), ); @@ -46,7 +44,7 @@ describe('The production Airbrake API', () => { it('throws if fetching groups was unsuccessful', async () => { worker.use( rest.get( - 'https://api.airbrake.io/api/v4/projects/123456/groups', + 'http://localhost:7007/api/airbrake/api/v4/projects/123456/groups', (_, res, ctx) => { return res(ctx.status(500)); }, diff --git a/plugins/airbrake/src/api/ProductionApi.ts b/plugins/airbrake/src/api/ProductionApi.ts index 76416bc173..21ca19ee7d 100644 --- a/plugins/airbrake/src/api/ProductionApi.ts +++ b/plugins/airbrake/src/api/ProductionApi.ts @@ -16,12 +16,14 @@ import { Groups } from './airbrakeGroups'; import { AirbrakeApi } from './AirbrakeApi'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; export class ProductionAirbrakeApi implements AirbrakeApi { - constructor(private readonly apiKey?: string) {} + constructor(private readonly discoveryApi: DiscoveryApi) {} async fetchGroups(projectId: string): Promise { - const apiUrl = `https://api.airbrake.io/api/v4/projects/${projectId}/groups?key=${this.apiKey}`; + const baseUrl = await this.discoveryApi.getBaseUrl('airbrake'); + const apiUrl = `${baseUrl}/api/v4/projects/${projectId}/groups`; const response = await fetch(apiUrl); diff --git a/plugins/airbrake/src/api/mock/LocalDiscoveryApi.ts b/plugins/airbrake/src/api/mock/LocalDiscoveryApi.ts new file mode 100644 index 0000000000..6990ce9c93 --- /dev/null +++ b/plugins/airbrake/src/api/mock/LocalDiscoveryApi.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { UrlPatternDiscovery } from '@backstage/core-app-api'; + +export const localDiscoveryApi = UrlPatternDiscovery.compile( + 'http://localhost:7007/api/{{ pluginId }}', +); diff --git a/plugins/airbrake/src/api/mock/index.ts b/plugins/airbrake/src/api/mock/index.ts index 0588d45fa6..4e0ab5fabf 100644 --- a/plugins/airbrake/src/api/mock/index.ts +++ b/plugins/airbrake/src/api/mock/index.ts @@ -14,4 +14,6 @@ * limitations under the License. */ -export { MockAirbrakeApi } from './MockApi'; +export * from './MockApi'; +export * from './MockEntity'; +export * from './LocalDiscoveryApi'; diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx index ef1ac229c9..ee14a17f9a 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx @@ -23,9 +23,10 @@ import { setupRequestMockHandlers, TestApiProvider, } from '@backstage/test-utils'; -import { createEntity } from '../../api/mock/MockEntity'; +import { createEntity } from '../../api'; import { airbrakeApiRef, + localDiscoveryApi, MockAirbrakeApi, ProductionAirbrakeApi, } from '../../api'; @@ -65,7 +66,7 @@ describe('EntityAirbrakeContent', () => { it('states that an error occurred if the API call fails', async () => { worker.use( rest.get( - 'https://api.airbrake.io/api/v4/projects/123/groups', + 'http://localhost:7007/api/airbrake/api/v4/projects/123/groups', (_, res, ctx) => { return res(ctx.status(500)); }, @@ -76,7 +77,7 @@ describe('EntityAirbrakeContent', () => { const widget = await renderInTestApp( diff --git a/plugins/airbrake/src/extensions.test.tsx b/plugins/airbrake/src/extensions.test.tsx index d677d939a4..05afe8f1e3 100644 --- a/plugins/airbrake/src/extensions.test.tsx +++ b/plugins/airbrake/src/extensions.test.tsx @@ -18,7 +18,7 @@ import { EntityAirbrakeContent } from './extensions'; import { Route } from 'react-router'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { airbrakeApiRef, MockAirbrakeApi } from './api'; -import { createEntity } from './api/mock/MockEntity'; +import { createEntity } from './api'; import { EntityProvider } from '@backstage/plugin-catalog-react'; describe('The Airbrake entity', () => { diff --git a/plugins/airbrake/src/plugin.ts b/plugins/airbrake/src/plugin.ts index f008b48ad4..e7e3dae1cb 100644 --- a/plugins/airbrake/src/plugin.ts +++ b/plugins/airbrake/src/plugin.ts @@ -13,7 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createApiFactory, createPlugin } from '@backstage/core-plugin-api'; +import { + createApiFactory, + createPlugin, + discoveryApiRef, +} from '@backstage/core-plugin-api'; import { rootRouteRef } from './routes'; import { airbrakeApiRef, ProductionAirbrakeApi } from './api'; @@ -23,8 +27,8 @@ export const airbrakePlugin = createPlugin({ apis: [ createApiFactory({ api: airbrakeApiRef, - deps: {}, - factory: () => new ProductionAirbrakeApi(), + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new ProductionAirbrakeApi(discoveryApi), }), ], routes: {