Use the CatalogClient to perform the request to the catalog backend

Signed-off-by: Roy Jacobs <roy.jacobs@gmail.com>
This commit is contained in:
Roy Jacobs
2021-09-02 15:02:24 +02:00
parent 21f87ec5bc
commit 800a95bace
3 changed files with 24 additions and 48 deletions
+6 -1
View File
@@ -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, string>,
): 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<CatalogEntityDocument[]>;
// (undocumented)
protected filterUrl?: string;
protected filter?: CatalogEntitiesRequest['filter'];
// (undocumented)
static fromConfig(
_config: Config,
@@ -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');
});
});
@@ -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(',')}`;
}