From e2e3dd08a5444cf7a4aac96018274a02f2b86199 Mon Sep 17 00:00:00 2001 From: Dustin Brewer Date: Thu, 9 Mar 2023 22:47:17 +0000 Subject: [PATCH] Add FireHydrant annotation option Signed-off-by: Dustin Brewer --- .changeset/tidy-planes-unite.md | 5 ++++ plugins/firehydrant/README.md | 8 ++++++ plugins/firehydrant/package.json | 1 + plugins/firehydrant/src/api/index.ts | 5 +++- .../ServiceDetailsCard/ServiceDetailsCard.tsx | 7 ++--- plugins/firehydrant/src/components/hooks.ts | 27 +++++++++++++++++++ .../src/components/serviceDetails.ts | 13 +++++++-- plugins/firehydrant/src/index.ts | 6 ++++- plugins/firehydrant/src/plugin.ts | 3 +++ yarn.lock | 1 + 10 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 .changeset/tidy-planes-unite.md create mode 100644 plugins/firehydrant/src/components/hooks.ts diff --git a/.changeset/tidy-planes-unite.md b/.changeset/tidy-planes-unite.md new file mode 100644 index 0000000000..158498d381 --- /dev/null +++ b/.changeset/tidy-planes-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-firehydrant': minor +--- + +Allow firehydrant to use component annotation diff --git a/plugins/firehydrant/README.md b/plugins/firehydrant/README.md index d7169e08f0..4472536245 100644 --- a/plugins/firehydrant/README.md +++ b/plugins/firehydrant/README.md @@ -56,3 +56,11 @@ proxy: # Supply the token you generated from https://app.firehydrant.io/organizations/bots Authorization: Bearer fhb-e4911b22bcd788c4a4afeb0c111ffbfa ``` + +4. Optionally add an annotation to the yaml config file of a component + +```yaml +metadata: + annotations: + firehydrant.com/service-name: +``` diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 293679c2ea..8084876f69 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -23,6 +23,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { + "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", diff --git a/plugins/firehydrant/src/api/index.ts b/plugins/firehydrant/src/api/index.ts index 7101b5dc62..45834d90e9 100644 --- a/plugins/firehydrant/src/api/index.ts +++ b/plugins/firehydrant/src/api/index.ts @@ -30,6 +30,7 @@ export interface FireHydrantAPI { getServiceDetails(options: { serviceName: string; + lookupByName: boolean; }): Promise; getServiceIncidents(options: { @@ -77,10 +78,12 @@ export class FireHydrantAPIClient implements FireHydrantAPI { async getServiceDetails(options: { serviceName: string; + lookupByName: boolean; }): Promise { + const queryOpt = options.lookupByName ? 'name' : 'query'; const proxyUrl = await this.getApiUrl(); const response = await fetch( - `${proxyUrl}/services?query=${options.serviceName}`, + `${proxyUrl}/services?${queryOpt}=${options.serviceName}`, ); if (!response.ok) { diff --git a/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.tsx b/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.tsx index bc2dd46fef..b6bfbcc13b 100644 --- a/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.tsx +++ b/plugins/firehydrant/src/components/ServiceDetailsCard/ServiceDetailsCard.tsx @@ -39,6 +39,7 @@ import { ResponseErrorPanel, } from '@backstage/core-components'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { isFireHydrantAvailable, getFireHydrantServiceName } from '../hooks'; const useStyles = makeStyles(theme => ({ button: { @@ -149,14 +150,14 @@ export const ServiceDetailsCard = () => { const startDate = DateTime.now().minus({ days: 30 }).toUTC(); const endDate = DateTime.now().toUTC(); + // The service name is provided by an annotation or a Backstage generated service name. // The Backstage service name in FireHydrant is a unique formatted string // that requires the entity's kind, name, and namespace. - const fireHydrantServiceName = `${entity?.kind}:${ - entity?.metadata?.namespace ?? 'default' - }/${entity?.metadata?.name}`; + const fireHydrantServiceName = getFireHydrantServiceName(entity); const { loading, value, error } = useServiceDetails({ serviceName: fireHydrantServiceName, + lookupByName: isFireHydrantAvailable(entity), }); const activeIncidents: string[] = value?.service?.active_incidents ?? []; diff --git a/plugins/firehydrant/src/components/hooks.ts b/plugins/firehydrant/src/components/hooks.ts new file mode 100644 index 0000000000..e8129e1b28 --- /dev/null +++ b/plugins/firehydrant/src/components/hooks.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2023 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 { Entity } from '@backstage/catalog-model'; + +export const FIREHYDRANT_SERVICE_NAME_ANNOTATION = + 'firehydrant.com/service-name'; +export const isFireHydrantAvailable = (entity: Entity) => + Boolean(entity.metadata.annotations?.[FIREHYDRANT_SERVICE_NAME_ANNOTATION]); +export const getFireHydrantServiceName = (entity: Entity) => + isFireHydrantAvailable(entity) + ? entity?.metadata.annotations?.[FIREHYDRANT_SERVICE_NAME_ANNOTATION] ?? '' + : `${entity?.kind}:${entity?.metadata?.namespace ?? 'default'}/${ + entity?.metadata?.name + }`; diff --git a/plugins/firehydrant/src/components/serviceDetails.ts b/plugins/firehydrant/src/components/serviceDetails.ts index 9c12677577..f0ea325419 100644 --- a/plugins/firehydrant/src/components/serviceDetails.ts +++ b/plugins/firehydrant/src/components/serviceDetails.ts @@ -17,13 +17,22 @@ import useAsyncRetry from 'react-use/lib/useAsyncRetry'; import { fireHydrantApiRef } from '../api'; import { errorApiRef, useApi } from '@backstage/core-plugin-api'; -export const useServiceDetails = ({ serviceName }: { serviceName: string }) => { +export const useServiceDetails = ({ + serviceName, + lookupByName, +}: { + serviceName: string; + lookupByName: boolean; +}) => { const api = useApi(fireHydrantApiRef); const errorApi = useApi(errorApiRef); const { loading, value, error, retry } = useAsyncRetry(async () => { try { - return await api.getServiceDetails({ serviceName: serviceName }); + return await api.getServiceDetails({ + serviceName: serviceName, + lookupByName: lookupByName, + }); } catch (e) { errorApi.post(e); return Promise.reject(e); diff --git a/plugins/firehydrant/src/index.ts b/plugins/firehydrant/src/index.ts index f1ef66fd3e..218b944244 100644 --- a/plugins/firehydrant/src/index.ts +++ b/plugins/firehydrant/src/index.ts @@ -20,4 +20,8 @@ * @packageDocumentation */ -export { firehydrantPlugin, FirehydrantCard } from './plugin'; +export { + firehydrantPlugin, + FirehydrantCard, + isFireHydrantAvailable, +} from './plugin'; diff --git a/plugins/firehydrant/src/plugin.ts b/plugins/firehydrant/src/plugin.ts index 6deefe4fce..14a8c53c66 100644 --- a/plugins/firehydrant/src/plugin.ts +++ b/plugins/firehydrant/src/plugin.ts @@ -50,3 +50,6 @@ export const FirehydrantCard = firehydrantPlugin.provide( }, }), ); + +/** @public */ +export { isFireHydrantAvailable } from './components/hooks'; diff --git a/yarn.lock b/yarn.lock index 4ad5e727d0..5d3cd95dbb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6249,6 +6249,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-firehydrant@workspace:plugins/firehydrant" dependencies: + "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" "@backstage/core-components": "workspace:^"