From ce17a1693141436b3c4ca9cc32b95dab5a0c22e6 Mon Sep 17 00:00:00 2001 From: Roy Jacobs Date: Wed, 25 Aug 2021 14:43:06 +0200 Subject: [PATCH 1/5] Allow the entities indexed by DefaultCatalogCollator to be filtered by kind Signed-off-by: Roy Jacobs --- .changeset/happy-cups-tap.md | 6 ++ packages/backend/src/plugins/search.ts | 2 +- plugins/catalog-backend/api-report.md | 11 ++++ plugins/catalog-backend/config.d.ts | 12 ++++ .../src/search/DefaultCatalogCollator.test.ts | 60 +++++++++++++++---- .../src/search/DefaultCatalogCollator.ts | 21 ++++++- 6 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 .changeset/happy-cups-tap.md diff --git a/.changeset/happy-cups-tap.md b/.changeset/happy-cups-tap.md new file mode 100644 index 0000000000..307b6fb4fc --- /dev/null +++ b/.changeset/happy-cups-tap.md @@ -0,0 +1,6 @@ +--- +'example-backend': patch +'@backstage/plugin-catalog-backend': patch +--- + +Allow the catalog search collator to filter the entities that it indexes diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts index 3470110408..2da108608e 100644 --- a/packages/backend/src/plugins/search.ts +++ b/packages/backend/src/plugins/search.ts @@ -68,7 +68,7 @@ export default async function createPlugin({ // particular collator gathers entities from the software catalog. indexBuilder.addCollator({ defaultRefreshIntervalSeconds: 600, - collator: new DefaultCatalogCollator({ discovery }), + collator: DefaultCatalogCollator.fromConfig(config, { discovery }), }); indexBuilder.addCollator({ diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index a7a100db65..b46f860207 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -581,9 +581,11 @@ export class DefaultCatalogCollator implements DocumentCollator { constructor({ discovery, locationTemplate, + allow, }: { discovery: PluginEndpointDiscovery; locationTemplate?: string; + allow?: string[]; }); // (undocumented) protected applyArgsToFormat( @@ -595,6 +597,15 @@ export class DefaultCatalogCollator implements DocumentCollator { // (undocumented) execute(): Promise; // (undocumented) + protected filterUrl: string; + // (undocumented) + static fromConfig( + config: Config, + options: { + discovery: PluginEndpointDiscovery; + }, + ): DefaultCatalogCollator; + // (undocumented) protected locationTemplate: string; // (undocumented) readonly type: string; diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 7da9cad139..5a9291541c 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -179,5 +179,17 @@ export interface Config { }; }; }; + + /** + * Configuration for search collation + */ + search?: { + /** + * Request search to only index these particular kinds. + * + * E.g. ["Component", "API", "Template", "Location"] + */ + allow: Array; + }; }; } diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts index 2b9745298c..c19d2d21a6 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts @@ -17,6 +17,11 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; import { DefaultCatalogCollator } from './DefaultCatalogCollator'; +import { setupServer } from 'msw/node'; +import { rest } from 'msw'; +import { ConfigReader } from '@backstage/config'; + +const server = setupServer(); const expectedEntities: Entity[] = [ { @@ -34,27 +39,37 @@ const expectedEntities: Entity[] = [ }, ]; -jest.mock('cross-fetch', () => ({ - __esModule: true, - default: async () => { - return { - json: async () => { - return expectedEntities; - }, - }; - }, -})); - describe('DefaultCatalogCollator', () => { let mockDiscoveryApi: jest.Mocked; let collator: DefaultCatalogCollator; - beforeEach(() => { + beforeAll(() => { mockDiscoveryApi = { - getBaseUrl: jest.fn().mockResolvedValueOnce('http://localhost:7000'), + getBaseUrl: jest.fn().mockResolvedValue('http://localhost:7000'), getExternalBaseUrl: jest.fn(), }; collator = new DefaultCatalogCollator({ discovery: mockDiscoveryApi }); + server.listen(); + }); + beforeEach(() => { + server.use( + rest.get('http://localhost:7000/entities', (req, res, ctx) => { + if (req.url.searchParams.has('filter')) { + const filter = req.url.searchParams.get('filter'); + if (filter === 'kind=Foo,Bar') { + // When filtering on the 'Foo,Bar' kinds we simply return no items, to simulate a filter + return res(ctx.json([])); + } + throw new Error('Unexpected filter parameter'); + } + return res(ctx.json(expectedEntities)); + }), + ); + }); + afterEach(() => server.resetHandlers()); + afterAll(() => { + server.close(); + jest.useRealTimers(); }); it('fetches from the configured catalog service', async () => { @@ -88,4 +103,23 @@ describe('DefaultCatalogCollator', () => { location: '/software/test-entity', }); }); + + it('allows filtering of the retrieved catalog entities', async () => { + const config = new ConfigReader({ + catalog: { + search: { + allow: ['Foo', 'Bar'], + }, + }, + }); + + // Provide an alternate location template. + collator = DefaultCatalogCollator.fromConfig(config, { + discovery: mockDiscoveryApi, + }); + + const documents = await collator.execute(); + // The simulated 'Foo,Bar' filter should return in an empty list + expect(documents).toHaveLength(0); + }); }); diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 1f9c68e549..4043cf1c1d 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -18,6 +18,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; import { IndexableDocument, DocumentCollator } from '@backstage/search-common'; import fetch from 'cross-fetch'; +import { Config } from '@backstage/config'; export interface CatalogEntityDocument extends IndexableDocument { componentType: string; @@ -30,18 +31,36 @@ export interface CatalogEntityDocument extends IndexableDocument { export class DefaultCatalogCollator implements DocumentCollator { protected discovery: PluginEndpointDiscovery; protected locationTemplate: string; + protected filterUrl: string; public readonly type: string = 'software-catalog'; + static fromConfig( + config: Config, + options: { discovery: PluginEndpointDiscovery }, + ) { + return new DefaultCatalogCollator({ + ...options, + allow: config.getOptionalStringArray('catalog.search.allow'), + }); + } + constructor({ discovery, locationTemplate, + allow, }: { discovery: PluginEndpointDiscovery; locationTemplate?: string; + allow?: string[]; }) { this.discovery = discovery; this.locationTemplate = locationTemplate || '/catalog/:namespace/:kind/:name'; + if (allow && allow.length) { + this.filterUrl = `?filter=kind=${allow.join(',')}`; + } else { + this.filterUrl = ''; + } } protected applyArgsToFormat( @@ -57,7 +76,7 @@ export class DefaultCatalogCollator implements DocumentCollator { async execute() { const baseUrl = await this.discovery.getBaseUrl('catalog'); - const res = await fetch(`${baseUrl}/entities`); + const res = await fetch(`${baseUrl}/entities${this.filterUrl}`); const entities: Entity[] = await res.json(); return entities.map((entity: Entity): CatalogEntityDocument => { return { From 2e4b7684455b7a918ded5e35e7903a22be568efe Mon Sep 17 00:00:00 2001 From: Roy Jacobs Date: Tue, 31 Aug 2021 13:12:59 +0200 Subject: [PATCH 2/5] Configure DefaultCatalogCollator programmatically Signed-off-by: Roy Jacobs --- .changeset/happy-cups-tap.md | 1 - plugins/catalog-backend/config.d.ts | 12 ------ .../src/search/DefaultCatalogCollator.test.ts | 37 +++++++++++++----- .../src/search/DefaultCatalogCollator.ts | 38 +++++++++++++------ plugins/catalog-backend/src/search/index.ts | 2 +- 5 files changed, 54 insertions(+), 36 deletions(-) diff --git a/.changeset/happy-cups-tap.md b/.changeset/happy-cups-tap.md index 307b6fb4fc..051f9def1c 100644 --- a/.changeset/happy-cups-tap.md +++ b/.changeset/happy-cups-tap.md @@ -1,5 +1,4 @@ --- -'example-backend': patch '@backstage/plugin-catalog-backend': patch --- diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 5a9291541c..7da9cad139 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -179,17 +179,5 @@ export interface Config { }; }; }; - - /** - * Configuration for search collation - */ - search?: { - /** - * Request search to only index these particular kinds. - * - * E.g. ["Component", "API", "Template", "Location"] - */ - allow: Array; - }; }; } diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts index c19d2d21a6..f1b7cfe862 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts @@ -16,7 +16,10 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; -import { DefaultCatalogCollator } from './DefaultCatalogCollator'; +import { + DefaultCatalogCollator, + mapFilterToQueryString, +} from './DefaultCatalogCollator'; import { setupServer } from 'msw/node'; import { rest } from 'msw'; import { ConfigReader } from '@backstage/config'; @@ -105,21 +108,35 @@ describe('DefaultCatalogCollator', () => { }); it('allows filtering of the retrieved catalog entities', async () => { - const config = new ConfigReader({ - catalog: { - search: { - allow: ['Foo', 'Bar'], - }, - }, - }); - // Provide an alternate location template. - collator = DefaultCatalogCollator.fromConfig(config, { + collator = DefaultCatalogCollator.fromConfig(new ConfigReader({}), { discovery: mockDiscoveryApi, + filter: { + kind: ['Foo', 'Bar'], + }, }); const documents = await collator.execute(); // The simulated 'Foo,Bar' filter should return in an empty list expect(documents).toHaveLength(0); }); + + it('can map filters to query strings', () => { + expect( + mapFilterToQueryString({ + a: 'Foo', + }), + ).toEqual('?filter=a=Foo'); + expect( + mapFilterToQueryString({ + a: ['Foo', 'Bar'], + }), + ).toEqual('?filter=a=Foo,Bar'); + expect( + mapFilterToQueryString({ + a: ['Foo', 'Bar'], + b: ['Quu', 'Qux'], + }), + ).toEqual('?filter=a=Foo,Bar,b=Quu,Qux'); + }); }); diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 4043cf1c1d..b372350a08 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -19,6 +19,7 @@ import { Entity } from '@backstage/catalog-model'; import { IndexableDocument, DocumentCollator } from '@backstage/search-common'; import fetch from 'cross-fetch'; import { Config } from '@backstage/config'; +import { CatalogEntitiesRequest } from '@backstage/catalog-client'; export interface CatalogEntityDocument extends IndexableDocument { componentType: string; @@ -31,36 +32,34 @@ export interface CatalogEntityDocument extends IndexableDocument { export class DefaultCatalogCollator implements DocumentCollator { protected discovery: PluginEndpointDiscovery; protected locationTemplate: string; - protected filterUrl: string; + protected filterUrl?: string; public readonly type: string = 'software-catalog'; static fromConfig( - config: Config, - options: { discovery: PluginEndpointDiscovery }, + _config: Config, + options: { + discovery: PluginEndpointDiscovery; + filter?: CatalogEntitiesRequest['filter']; + }, ) { return new DefaultCatalogCollator({ ...options, - allow: config.getOptionalStringArray('catalog.search.allow'), }); } constructor({ discovery, locationTemplate, - allow, + filter, }: { discovery: PluginEndpointDiscovery; locationTemplate?: string; - allow?: string[]; + filter?: CatalogEntitiesRequest['filter']; }) { this.discovery = discovery; this.locationTemplate = locationTemplate || '/catalog/:namespace/:kind/:name'; - if (allow && allow.length) { - this.filterUrl = `?filter=kind=${allow.join(',')}`; - } else { - this.filterUrl = ''; - } + this.filterUrl = mapFilterToQueryString(filter); } protected applyArgsToFormat( @@ -76,7 +75,7 @@ export class DefaultCatalogCollator implements DocumentCollator { async execute() { const baseUrl = await this.discovery.getBaseUrl('catalog'); - const res = await fetch(`${baseUrl}/entities${this.filterUrl}`); + const res = await fetch(`${baseUrl}/entities${this.filterUrl || ''}`); const entities: Entity[] = await res.json(); return entities.map((entity: Entity): CatalogEntityDocument => { return { @@ -96,3 +95,18 @@ export class DefaultCatalogCollator implements DocumentCollator { }); } } + +export function mapFilterToQueryString( + filter: CatalogEntitiesRequest['filter'], +): string | undefined { + if (!filter) { + return undefined; + } + + const mappedFilters = Object.entries(filter).map(kvp => { + const type = kvp[0]; + const values = [].concat(kvp[1]); + return `${type}=${values.join(',')}`; + }); + return `?filter=${mappedFilters.join(',')}`; +} diff --git a/plugins/catalog-backend/src/search/index.ts b/plugins/catalog-backend/src/search/index.ts index 7e13999864..dfe1cf541e 100644 --- a/plugins/catalog-backend/src/search/index.ts +++ b/plugins/catalog-backend/src/search/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export * from './DefaultCatalogCollator'; +export { DefaultCatalogCollator } from './DefaultCatalogCollator'; From 21f87ec5bc7e1fbdefc219596f6da9152982f1ac Mon Sep 17 00:00:00 2001 From: Roy Jacobs Date: Tue, 31 Aug 2021 13:56:05 +0200 Subject: [PATCH 3/5] Update api-report.md Signed-off-by: Roy Jacobs --- plugins/catalog-backend/api-report.md | 28 ++++++++------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index b46f860207..f6e864221c 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -7,6 +7,7 @@ import { Account } from 'aws-sdk/clients/organizations'; import { BitbucketIntegration } from '@backstage/integration'; +import { CatalogEntitiesRequest } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { DocumentCollator } from '@backstage/search-common'; import { Entity } from '@backstage/catalog-model'; @@ -204,22 +205,6 @@ export class CatalogBuilder { ): CatalogBuilder; } -// Warning: (ae-missing-release-tag) "CatalogEntityDocument" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface CatalogEntityDocument extends IndexableDocument { - // (undocumented) - componentType: string; - // (undocumented) - kind: string; - // (undocumented) - lifecycle: string; - // (undocumented) - namespace: string; - // (undocumented) - owner: string; -} - // Warning: (ae-missing-release-tag) "CatalogProcessingOrchestrator" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -581,11 +566,11 @@ export class DefaultCatalogCollator implements DocumentCollator { constructor({ discovery, locationTemplate, - allow, + filter, }: { discovery: PluginEndpointDiscovery; locationTemplate?: string; - allow?: string[]; + filter?: CatalogEntitiesRequest['filter']; }); // (undocumented) protected applyArgsToFormat( @@ -594,15 +579,18 @@ export class DefaultCatalogCollator implements DocumentCollator { ): string; // (undocumented) protected discovery: PluginEndpointDiscovery; + // Warning: (ae-forgotten-export) The symbol "CatalogEntityDocument" needs to be exported by the entry point index.d.ts + // // (undocumented) execute(): Promise; // (undocumented) - protected filterUrl: string; + protected filterUrl?: string; // (undocumented) static fromConfig( - config: Config, + _config: Config, options: { discovery: PluginEndpointDiscovery; + filter?: CatalogEntitiesRequest['filter']; }, ): DefaultCatalogCollator; // (undocumented) From 800a95bace135d7612aa84eb0ef6e3e556b49c25 Mon Sep 17 00:00:00 2001 From: Roy Jacobs Date: Thu, 2 Sep 2021 15:02:24 +0200 Subject: [PATCH 4/5] Use the CatalogClient to perform the request to the catalog backend Signed-off-by: Roy Jacobs --- plugins/catalog-backend/api-report.md | 7 +++- .../src/search/DefaultCatalogCollator.test.ts | 26 +------------ .../src/search/DefaultCatalogCollator.ts | 39 ++++++++----------- 3 files changed, 24 insertions(+), 48 deletions(-) diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index f6e864221c..01a824d049 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -7,6 +7,7 @@ import { Account } from 'aws-sdk/clients/organizations'; import { BitbucketIntegration } from '@backstage/integration'; +import { CatalogApi } from '@backstage/catalog-client'; import { CatalogEntitiesRequest } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { DocumentCollator } from '@backstage/search-common'; @@ -567,10 +568,12 @@ export class DefaultCatalogCollator implements DocumentCollator { discovery, locationTemplate, filter, + catalogClient, }: { discovery: PluginEndpointDiscovery; locationTemplate?: string; filter?: CatalogEntitiesRequest['filter']; + catalogClient?: CatalogApi; }); // (undocumented) protected applyArgsToFormat( @@ -578,13 +581,15 @@ export class DefaultCatalogCollator implements DocumentCollator { args: Record, ): string; // (undocumented) + protected readonly catalogClient: CatalogApi; + // (undocumented) protected discovery: PluginEndpointDiscovery; // Warning: (ae-forgotten-export) The symbol "CatalogEntityDocument" needs to be exported by the entry point index.d.ts // // (undocumented) execute(): Promise; // (undocumented) - protected filterUrl?: string; + protected filter?: CatalogEntitiesRequest['filter']; // (undocumented) static fromConfig( _config: Config, diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts index f1b7cfe862..bb556fc49f 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts @@ -16,10 +16,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; -import { - DefaultCatalogCollator, - mapFilterToQueryString, -} from './DefaultCatalogCollator'; +import { DefaultCatalogCollator } from './DefaultCatalogCollator'; import { setupServer } from 'msw/node'; import { rest } from 'msw'; import { ConfigReader } from '@backstage/config'; @@ -59,7 +56,7 @@ describe('DefaultCatalogCollator', () => { rest.get('http://localhost:7000/entities', (req, res, ctx) => { if (req.url.searchParams.has('filter')) { const filter = req.url.searchParams.get('filter'); - if (filter === 'kind=Foo,Bar') { + if (filter === 'kind=Foo,kind=Bar') { // When filtering on the 'Foo,Bar' kinds we simply return no items, to simulate a filter return res(ctx.json([])); } @@ -120,23 +117,4 @@ describe('DefaultCatalogCollator', () => { // The simulated 'Foo,Bar' filter should return in an empty list expect(documents).toHaveLength(0); }); - - it('can map filters to query strings', () => { - expect( - mapFilterToQueryString({ - a: 'Foo', - }), - ).toEqual('?filter=a=Foo'); - expect( - mapFilterToQueryString({ - a: ['Foo', 'Bar'], - }), - ).toEqual('?filter=a=Foo,Bar'); - expect( - mapFilterToQueryString({ - a: ['Foo', 'Bar'], - b: ['Quu', 'Qux'], - }), - ).toEqual('?filter=a=Foo,Bar,b=Quu,Qux'); - }); }); diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index b372350a08..6292b2a833 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -17,9 +17,12 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; import { IndexableDocument, DocumentCollator } from '@backstage/search-common'; -import fetch from 'cross-fetch'; import { Config } from '@backstage/config'; -import { CatalogEntitiesRequest } from '@backstage/catalog-client'; +import { + CatalogApi, + CatalogClient, + CatalogEntitiesRequest, +} from '@backstage/catalog-client'; export interface CatalogEntityDocument extends IndexableDocument { componentType: string; @@ -32,7 +35,8 @@ export interface CatalogEntityDocument extends IndexableDocument { export class DefaultCatalogCollator implements DocumentCollator { protected discovery: PluginEndpointDiscovery; protected locationTemplate: string; - protected filterUrl?: string; + protected filter?: CatalogEntitiesRequest['filter']; + protected readonly catalogClient: CatalogApi; public readonly type: string = 'software-catalog'; static fromConfig( @@ -51,15 +55,19 @@ export class DefaultCatalogCollator implements DocumentCollator { discovery, locationTemplate, filter, + catalogClient, }: { discovery: PluginEndpointDiscovery; locationTemplate?: string; filter?: CatalogEntitiesRequest['filter']; + catalogClient?: CatalogApi; }) { this.discovery = discovery; this.locationTemplate = locationTemplate || '/catalog/:namespace/:kind/:name'; - this.filterUrl = mapFilterToQueryString(filter); + this.filter = filter; + this.catalogClient = + catalogClient || new CatalogClient({ discoveryApi: discovery }); } protected applyArgsToFormat( @@ -74,10 +82,10 @@ export class DefaultCatalogCollator implements DocumentCollator { } async execute() { - const baseUrl = await this.discovery.getBaseUrl('catalog'); - const res = await fetch(`${baseUrl}/entities${this.filterUrl || ''}`); - const entities: Entity[] = await res.json(); - return entities.map((entity: Entity): CatalogEntityDocument => { + const response = await this.catalogClient.getEntities({ + filter: this.filter, + }); + return response.items.map((entity: Entity): CatalogEntityDocument => { return { title: entity.metadata.name, location: this.applyArgsToFormat(this.locationTemplate, { @@ -95,18 +103,3 @@ export class DefaultCatalogCollator implements DocumentCollator { }); } } - -export function mapFilterToQueryString( - filter: CatalogEntitiesRequest['filter'], -): string | undefined { - if (!filter) { - return undefined; - } - - const mappedFilters = Object.entries(filter).map(kvp => { - const type = kvp[0]; - const values = [].concat(kvp[1]); - return `${type}=${values.join(',')}`; - }); - return `?filter=${mappedFilters.join(',')}`; -} From a5013957e40d042638e25f762e86f67b06edab5b Mon Sep 17 00:00:00 2001 From: Roy Jacobs Date: Thu, 2 Sep 2021 15:10:15 +0200 Subject: [PATCH 5/5] Update the 'create-app' template to use the new constructor for DefaultCatalogCollator Signed-off-by: Roy Jacobs --- .changeset/fast-wasps-matter.md | 23 +++++++++++++++++++ .../packages/backend/src/plugins/search.ts | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 .changeset/fast-wasps-matter.md diff --git a/.changeset/fast-wasps-matter.md b/.changeset/fast-wasps-matter.md new file mode 100644 index 0000000000..6b6a682a37 --- /dev/null +++ b/.changeset/fast-wasps-matter.md @@ -0,0 +1,23 @@ +--- +'@backstage/create-app': patch +--- + +Updated the search configuration class to use the static `fromConfig`-based constructor for the `DefaultCatalogCollator`. + +To apply this change to an existing app, replace the following line in `search.ts`: + +```diff +-collator: new DefaultCatalogCollator({ discovery }) ++collator: DefaultCatalogCollator.fromConfig(config, { discovery }) +``` + +The `config` parameter was not needed before, so make sure you also add that in the signature of `createPlugin` +in `search.ts`: + +```diff +export default async function createPlugin({ + logger, + discovery, ++ config, +}: PluginEnvironment) { +``` diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts index 248ed37ea8..7fc317d23d 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/search.ts @@ -10,6 +10,7 @@ import { DefaultCatalogCollator } from '@backstage/plugin-catalog-backend'; export default async function createPlugin({ logger, discovery, + config, }: PluginEnvironment) { // Initialize a connection to a search engine. const searchEngine = new LunrSearchEngine({ logger }); @@ -19,7 +20,7 @@ export default async function createPlugin({ // particular collator gathers entities from the software catalog. indexBuilder.addCollator({ defaultRefreshIntervalSeconds: 600, - collator: new DefaultCatalogCollator({ discovery }), + collator: DefaultCatalogCollator.fromConfig(config, { discovery }), }); // The scheduler controls when documents are gathered from collators and sent