search-backend-module-{catalog,explore,techdocs}: migrate to support new auth services

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Co-authored-by: Carl-Erik Bergström <cbergstrom@spotify.com>
Co-authored-by: blam <ben@blam.sh>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-02-16 13:57:03 +01:00
parent 58b5e450dd
commit bb368a598b
8 changed files with 76 additions and 21 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-search-backend-module-techdocs': patch
'@backstage/plugin-search-backend-module-catalog': patch
'@backstage/plugin-search-backend-module-explore': patch
---
Migrated to support new auth services.
@@ -5,6 +5,7 @@
```ts
/// <reference types="node" />
import { AuthService } from '@backstage/backend-plugin-api';
import { CatalogApi } from '@backstage/catalog-client';
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
import { Config } from '@backstage/config';
@@ -41,6 +42,7 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory {
// @public (undocumented)
export type DefaultCatalogCollatorFactoryOptions = {
auth?: AuthService;
discovery: PluginEndpointDiscovery;
tokenManager: TokenManager;
locationTemplate?: string;
@@ -17,6 +17,7 @@
import {
PluginEndpointDiscovery,
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
import {
CatalogApi,
@@ -33,9 +34,11 @@ import { Readable } from 'stream';
import { CatalogCollatorEntityTransformer } from './CatalogCollatorEntityTransformer';
import { readCollatorConfigOptions } from './config';
import { defaultCatalogCollatorEntityTransformer } from './defaultCatalogCollatorEntityTransformer';
import { AuthService } from '@backstage/backend-plugin-api';
/** @public */
export type DefaultCatalogCollatorFactoryOptions = {
auth?: AuthService;
discovery: PluginEndpointDiscovery;
tokenManager: TokenManager;
/**
@@ -71,20 +74,26 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory {
private filter?: GetEntitiesRequest['filter'];
private batchSize: number;
private readonly catalogClient: CatalogApi;
private tokenManager: TokenManager;
private entityTransformer: CatalogCollatorEntityTransformer;
private auth: AuthService;
static fromConfig(
configRoot: Config,
options: DefaultCatalogCollatorFactoryOptions,
) {
const configOptions = readCollatorConfigOptions(configRoot);
const { auth: adaptedAuth } = createLegacyAuthAdapters({
auth: options.auth,
discovery: options.discovery,
tokenManager: options.tokenManager,
});
return new DefaultCatalogCollatorFactory({
locationTemplate:
options.locationTemplate ?? configOptions.locationTemplate,
filter: options.filter ?? configOptions.filter,
batchSize: options.batchSize ?? configOptions.batchSize,
entityTransformer: options.entityTransformer,
auth: adaptedAuth,
discovery: options.discovery,
tokenManager: options.tokenManager,
catalogClient: options.catalogClient,
@@ -96,17 +105,18 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory {
filter: GetEntitiesRequest['filter'];
batchSize: number;
entityTransformer?: CatalogCollatorEntityTransformer;
auth: AuthService;
discovery: PluginEndpointDiscovery;
tokenManager: TokenManager;
catalogClient?: CatalogApi;
}) {
const {
auth,
batchSize,
discovery,
locationTemplate,
filter,
catalogClient,
tokenManager,
entityTransformer,
} = options;
@@ -115,9 +125,9 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory {
this.batchSize = batchSize;
this.catalogClient =
catalogClient || new CatalogClient({ discoveryApi: discovery });
this.tokenManager = tokenManager;
this.entityTransformer =
entityTransformer ?? defaultCatalogCollatorEntityTransformer;
this.auth = auth;
}
async getCollator(): Promise<Readable> {
@@ -125,7 +135,6 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory {
}
private async *execute(): AsyncGenerator<CatalogEntityDocument> {
const { token } = await this.tokenManager.getToken();
let entitiesRetrieved = 0;
let moreEntitiesToGet = true;
@@ -133,6 +142,10 @@ export class DefaultCatalogCollatorFactory implements DocumentCollatorFactory {
// limit (and allow some control over) memory used by the search backend
// at index-time.
while (moreEntitiesToGet) {
const { token } = await this.auth.getPluginRequestToken({
onBehalfOf: await this.auth.getOwnServiceCredentials(),
targetPluginId: 'catalog',
});
const entities = (
await this.catalogClient.getEntities(
{
@@ -5,6 +5,7 @@
```ts
/// <reference types="node" />
import { AuthService } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { ExploreTool } from '@backstage/plugin-explore-common';
@@ -37,5 +38,6 @@ export type ToolDocumentCollatorFactoryOptions = {
discovery: PluginEndpointDiscovery;
logger: Logger;
tokenManager?: TokenManager;
auth?: AuthService;
};
```
@@ -17,7 +17,9 @@
import {
PluginEndpointDiscovery,
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
import { AuthService } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { ExploreTool } from '@backstage/plugin-explore-common';
import {
@@ -44,6 +46,7 @@ export type ToolDocumentCollatorFactoryOptions = {
discovery: PluginEndpointDiscovery;
logger: Logger;
tokenManager?: TokenManager;
auth?: AuthService;
};
/**
@@ -56,12 +59,13 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory {
private readonly discovery: PluginEndpointDiscovery;
private readonly logger: Logger;
private readonly tokenManager?: TokenManager;
private readonly auth: AuthService;
private constructor(options: ToolDocumentCollatorFactoryOptions) {
this.discovery = options.discovery;
this.logger = options.logger;
this.tokenManager = options.tokenManager;
this.auth = createLegacyAuthAdapters(options).auth;
}
static fromConfig(
@@ -94,16 +98,13 @@ export class ToolDocumentCollatorFactory implements DocumentCollatorFactory {
private async fetchTools() {
const baseUrl = await this.discovery.getBaseUrl('explore');
let headers = {};
if (this.tokenManager) {
const { token } = await this.tokenManager.getToken();
headers = {
Authorization: `Bearer ${token}`,
};
}
const response = await fetch(`${baseUrl}/tools`, headers);
const { token } = await this.auth.getPluginRequestToken({
onBehalfOf: await this.auth.getOwnServiceCredentials(),
targetPluginId: 'explore',
});
const response = await fetch(`${baseUrl}/tools`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) {
throw new Error(
@@ -5,10 +5,12 @@
```ts
/// <reference types="node" />
import { AuthService } from '@backstage/backend-plugin-api';
import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { Entity } from '@backstage/catalog-model';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { Logger } from 'winston';
import { Permission } from '@backstage/plugin-permission-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
@@ -44,6 +46,8 @@ export type TechDocsCollatorFactoryOptions = {
discovery: PluginEndpointDiscovery;
logger: Logger;
tokenManager: TokenManager;
auth?: AuthService;
httpAuth?: HttpAuthService;
locationTemplate?: string;
catalogClient?: CatalogApi;
parallelismLimit?: number;
@@ -74,6 +74,8 @@ export default createBackendModule({
deps: {
config: coreServices.rootConfig,
logger: coreServices.logger,
auth: coreServices.auth,
httpAuth: coreServices.httpAuth,
discovery: coreServices.discovery,
tokenManager: coreServices.tokenManager,
scheduler: coreServices.scheduler,
@@ -83,6 +85,8 @@ export default createBackendModule({
async init({
config,
logger,
auth,
httpAuth,
discovery,
tokenManager,
scheduler,
@@ -106,6 +110,8 @@ export default createBackendModule({
factory: DefaultTechDocsCollatorFactory.fromConfig(config, {
discovery,
tokenManager,
auth,
httpAuth,
logger: loggerToWinstonLogger(logger),
catalogClient: catalog,
entityTransformer: transformer,
@@ -17,6 +17,7 @@
import {
PluginEndpointDiscovery,
TokenManager,
createLegacyAuthAdapters,
} from '@backstage/backend-common';
import {
CatalogApi,
@@ -41,6 +42,7 @@ import { Readable } from 'stream';
import { Logger } from 'winston';
import { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer';
import { defaultTechDocsCollatorEntityTransformer } from './defaultTechDocsCollatorEntityTransformer';
import { AuthService, HttpAuthService } from '@backstage/backend-plugin-api';
interface MkSearchIndexDoc {
title: string;
@@ -57,6 +59,8 @@ export type TechDocsCollatorFactoryOptions = {
discovery: PluginEndpointDiscovery;
logger: Logger;
tokenManager: TokenManager;
auth?: AuthService;
httpAuth?: HttpAuthService;
locationTemplate?: string;
catalogClient?: CatalogApi;
parallelismLimit?: number;
@@ -84,8 +88,8 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
private discovery: PluginEndpointDiscovery;
private locationTemplate: string;
private readonly logger: Logger;
private readonly auth: AuthService;
private readonly catalogClient: CatalogApi;
private readonly tokenManager: TokenManager;
private readonly parallelismLimit: number;
private readonly legacyPathCasing: boolean;
private entityTransformer: TechDocsCollatorEntityTransformer;
@@ -100,9 +104,14 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
new CatalogClient({ discoveryApi: options.discovery });
this.parallelismLimit = options.parallelismLimit ?? 10;
this.legacyPathCasing = options.legacyPathCasing ?? false;
this.tokenManager = options.tokenManager;
this.entityTransformer =
options.entityTransformer ?? defaultTechDocsCollatorEntityTransformer;
this.auth = createLegacyAuthAdapters({
auth: options.auth,
discovery: options.discovery,
tokenManager: options.tokenManager,
}).auth;
}
static fromConfig(config: Config, options: TechDocsCollatorFactoryOptions) {
@@ -131,7 +140,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
private async *execute(): AsyncGenerator<TechDocsDocument, void, undefined> {
const limit = pLimit(this.parallelismLimit);
const techDocsBaseUrl = await this.discovery.getBaseUrl('techdocs');
const { token } = await this.tokenManager.getToken();
let entitiesRetrieved = 0;
let moreEntitiesToGet = true;
@@ -141,6 +150,11 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
// parallelism limit to simplify configuration.
const batchSize = this.parallelismLimit * 50;
while (moreEntitiesToGet) {
const { token: catalogToken } = await this.auth.getPluginRequestToken({
onBehalfOf: await this.auth.getOwnServiceCredentials(),
targetPluginId: 'catalog',
});
const entities = (
await this.catalogClient.getEntities(
{
@@ -151,7 +165,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
limit: batchSize,
offset: entitiesRetrieved,
},
{ token },
{ token: catalogToken },
)
).items;
@@ -174,6 +188,12 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
);
try {
const { token: techdocsToken } =
await this.auth.getPluginRequestToken({
onBehalfOf: await this.auth.getOwnServiceCredentials(),
targetPluginId: 'techdocs',
});
const searchIndexResponse = await fetch(
DefaultTechDocsCollatorFactory.constructDocsIndexUrl(
techDocsBaseUrl,
@@ -181,7 +201,7 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory {
),
{
headers: {
Authorization: `Bearer ${token}`,
Authorization: `Bearer ${techdocsToken}`,
},
},
);