Merge pull request #18238 from Bonial-International-GmbH/pjungermann/explore/tools-as-config

feat(explore): allow to provide explore tools through config
This commit is contained in:
Patrik Oldsberg
2023-06-20 15:09:54 +02:00
committed by GitHub
8 changed files with 179 additions and 5 deletions
+52
View File
@@ -0,0 +1,52 @@
---
'@backstage/plugin-explore-backend': patch
---
Allow to provide explore tools through config instead of data in code.
```yaml title="app-config.yaml"
explore:
tools:
- title: New Relic
description: Observability platform built to help engineers create and monitor their software
url: /newrelic
image: https://i.imgur.com/L37ikrX.jpg
tags:
- newrelic
- performance
- monitoring
- errors
- alerting
- title: CircleCI
description: Provides builds overview, detailed build info and retriggering functionality for CircleCI.
url: /circleci
image: https://miro.medium.com/max/1200/1*hkTBp22vLAqlIHkrkZHPnw.png
tags:
- circleci
- ci
- dev
# [...]
```
```diff title="packages/backend/src/plugins/explore.ts"
- import { ExploreTool } from '@backstage/plugin-explore-common';
- const exploreTools: ExploreTool[] = [
- {
- title: 'New Relic',
- description: 'Observability platform built to help engineers create and monitor their software',
- url: '/newrelic',
- image: 'https://i.imgur.com/L37ikrX.jpg',
- tags: ['newrelic', 'performance', 'monitoring', 'errors', 'alerting'],
- },
- {
- title: 'CircleCI',
- description: 'Provides builds overview, detailed build info and retriggering functionality for CircleCI.',
- url: '/circleci',
- image: 'https://miro.medium.com/max/1200/1*hkTBp22vLAqlIHkrkZHPnw.png',
- tags: ['circleci', 'ci', 'dev'],
- },
- ];
-
- StaticExploreToolProvider.fromData(tools)
+ StaticExploreToolProvider.fromData(env.config)
```
+51 -2
View File
@@ -7,14 +7,61 @@ for these tools.
## Getting started
### Install the Package
### Adding the plugin to your `packages/backend`
#### Tools as Config
Install dependencies
```bash
# From your Backstage root directory
yarn add --cwd packages/backend @backstage/plugin-explore-backend
```
You'll need to add the plugin to the router in your `backend` package. You can
do this by creating a file called `packages/backend/src/plugins/explore.ts` with the following content:
```ts title="packages/backend/src/plugins/explore.ts"
import {
createRouter,
StaticExploreToolProvider,
} from '@backstage/plugin-explore-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
return await createRouter({
logger: env.logger,
toolProvider: StaticExploreToolProvider.fromConfig(env.config),
});
}
```
#### Tools as Code
Install dependencies
```bash
# From your Backstage root directory
yarn add --cwd packages/backend @backstage/plugin-explore-backend @backstage/plugin-explore-common
```
### Adding the plugin to your `packages/backend`
Config:
```yaml
explore:
tools:
- title: New Relic
description: new relic plugin
url: /newrelic
image: https://i.imgur.com/L37ikrX.jpg
tags:
- newrelic
- proxy
- nerdGraph
```
You'll need to add the plugin to the router in your `backend` package. You can
do this by creating a file called `packages/backend/src/plugins/explore.ts` with the following content:
@@ -49,6 +96,8 @@ export default async function createPlugin(
}
```
#### Register the plugin router
With the `explore.ts` router setup in place, add the router to
`packages/backend/src/index.ts`:
+3
View File
@@ -3,6 +3,7 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { Config } from '@backstage/config';
import { ExploreTool } from '@backstage/plugin-explore-common';
import express from 'express';
import { GetExploreToolsRequest } from '@backstage/plugin-explore-common';
@@ -30,6 +31,8 @@ export interface RouterOptions {
// @public
export class StaticExploreToolProvider implements ExploreToolProvider {
// (undocumented)
static fromConfig(config: Config): StaticExploreToolProvider;
// (undocumented)
static fromData(tools: ExploreTool[]): StaticExploreToolProvider;
// (undocumented)
+31
View File
@@ -0,0 +1,31 @@
/*
* 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.
*/
export interface Config {
explore?: {
/**
* Tools to be used for the explore tool provider.
*/
tools?: Array<{
title: string;
description?: string;
url: string;
image: string;
tags?: string[];
lifecycle?: string;
}>;
};
}
+4 -1
View File
@@ -27,6 +27,7 @@
"@backstage/plugin-explore-common": "workspace:^",
"@backstage/plugin-search-backend-module-explore": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"@backstage/types": "workspace:^",
"@types/express": "*",
"express": "^4.18.1",
"express-promise-router": "^4.1.0",
@@ -42,6 +43,8 @@
"supertest": "^6.2.4"
},
"files": [
"config.d.ts",
"dist"
]
],
"configSchema": "config.d.ts"
}
@@ -14,7 +14,9 @@
* limitations under the License.
*/
import { ConfigReader } from '@backstage/config';
import { ExploreTool } from '@backstage/plugin-explore-common';
import { JsonObject } from '@backstage/types';
import { StaticExploreToolProvider } from './StaticExploreToolProvider';
describe('StaticExploreToolProvider', () => {
@@ -40,7 +42,24 @@ describe('StaticExploreToolProvider', () => {
const allTools: ExploreTool[] = [tool1, tool2, tool3];
describe('getTools', () => {
it('returns a list of all tools', async () => {
it('fromConfig returns a list of all tools', async () => {
const config = new ConfigReader({
explore: {
tools: [
tool1 as JsonObject,
tool2 as JsonObject,
tool3 as JsonObject,
],
},
});
const provider = StaticExploreToolProvider.fromConfig(config);
await expect(provider.getTools({})).resolves.toEqual({
tools: allTools,
});
});
it('fromData returns a list of all tools', async () => {
const provider = StaticExploreToolProvider.fromData(allTools);
await expect(provider.getTools({})).resolves.toEqual({
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { Config } from '@backstage/config';
import {
ExploreTool,
GetExploreToolsRequest,
@@ -35,7 +36,22 @@ const anyOf = <T>(prop: T | T[], matches: T[]) =>
export class StaticExploreToolProvider implements ExploreToolProvider {
private readonly tools: ExploreTool[];
static fromData(tools: ExploreTool[]) {
static fromConfig(config: Config): StaticExploreToolProvider {
const tools: ExploreTool[] =
config.getOptionalConfigArray('explore.tools')?.map(toolConfig => {
return {
description: toolConfig.getOptionalString('description'),
image: toolConfig.getString('image'),
lifecycle: toolConfig.getOptionalString('lifecycle'),
tags: toolConfig.getOptionalStringArray('tags'),
title: toolConfig.getString('title'),
url: toolConfig.getString('url'),
} as ExploreTool;
}) ?? [];
return this.fromData(tools);
}
static fromData(tools: ExploreTool[]): StaticExploreToolProvider {
return new StaticExploreToolProvider(tools);
}
+1
View File
@@ -6725,6 +6725,7 @@ __metadata:
"@backstage/plugin-explore-common": "workspace:^"
"@backstage/plugin-search-backend-module-explore": "workspace:^"
"@backstage/plugin-search-common": "workspace:^"
"@backstage/types": "workspace:^"
"@types/express": "*"
"@types/supertest": ^2.0.8
express: ^4.18.1