simplify implementation
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
+13
-14
@@ -19,11 +19,17 @@ import {
|
||||
RootConfigService,
|
||||
RootInstanceMetadataService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { HostDiscovery } from '../../../../entrypoints/discovery';
|
||||
import {
|
||||
RootSystemMetadataService,
|
||||
RootSystemMetadataServicePluginInfo,
|
||||
} from '@backstage/backend-plugin-api/alpha';
|
||||
import { getEndpoints } from '../../../../entrypoints/discovery/parsing';
|
||||
import { Config } from '@backstage/config';
|
||||
|
||||
function getPlugins(config: Config): string[] {
|
||||
const endpoints = getEndpoints(config);
|
||||
return Array.from(new Set(endpoints.flatMap(endpoint => endpoint.plugins)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
@@ -31,20 +37,17 @@ import {
|
||||
export class DefaultRootSystemMetadataService
|
||||
implements RootSystemMetadataService
|
||||
{
|
||||
#hostDiscovery: HostDiscovery;
|
||||
#plugins: string[];
|
||||
#instanceMetadata: RootInstanceMetadataService;
|
||||
constructor(options: {
|
||||
logger: LoggerService;
|
||||
config: RootConfigService;
|
||||
instanceMetadata: RootInstanceMetadataService;
|
||||
}) {
|
||||
this.#hostDiscovery = HostDiscovery.fromConfig(options.config, {
|
||||
logger: options.logger,
|
||||
});
|
||||
options.config.subscribe?.(() => {
|
||||
this.#hostDiscovery = HostDiscovery.fromConfig(options.config, {
|
||||
logger: options.logger,
|
||||
});
|
||||
const { config } = options;
|
||||
this.#plugins = getPlugins(config);
|
||||
config.subscribe?.(() => {
|
||||
this.#plugins = getPlugins(config);
|
||||
});
|
||||
this.#instanceMetadata = options.instanceMetadata;
|
||||
}
|
||||
@@ -60,11 +63,7 @@ export class DefaultRootSystemMetadataService
|
||||
public async getInstalledPlugins(): Promise<
|
||||
RootSystemMetadataServicePluginInfo[]
|
||||
> {
|
||||
const resolutions = await this.#hostDiscovery.listResolutions();
|
||||
const plugins = [];
|
||||
for (const pluginId of resolutions.keys()) {
|
||||
plugins.push({ pluginId });
|
||||
}
|
||||
const plugins = this.#plugins.map(pluginId => ({ pluginId }));
|
||||
|
||||
for (const plugin of await this.#instanceMetadata.getInstalledPlugins()) {
|
||||
plugins.push({ pluginId: plugin.pluginId });
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
import { readHttpServerOptions } from '../rootHttpRouter/http/config';
|
||||
import { SrvResolvers } from './SrvResolvers';
|
||||
import { trimEnd } from 'lodash';
|
||||
import { getEndpoints } from './parsing';
|
||||
|
||||
type Resolver = (pluginId: string) => Promise<string>;
|
||||
|
||||
@@ -150,11 +151,6 @@ export class HostDiscovery implements DiscoveryService {
|
||||
throw new Error('Not initialized');
|
||||
};
|
||||
|
||||
#resolutions: Map<
|
||||
string,
|
||||
Set<{ hash: string; target: { internal?: string; external?: string } }>
|
||||
> = new Map();
|
||||
|
||||
static fromConfig(config: RootConfigService, options?: HostDiscoveryOptions) {
|
||||
const discovery = new HostDiscovery(new SrvResolvers());
|
||||
|
||||
@@ -198,23 +194,12 @@ export class HostDiscovery implements DiscoveryService {
|
||||
return await resolver(pluginId);
|
||||
}
|
||||
|
||||
async listResolutions() {
|
||||
const _targets: Map<string, { internal?: string; external?: string }[]> =
|
||||
new Map();
|
||||
for (const [pluginId, targets] of this.#resolutions.entries()) {
|
||||
const currentTargets = [...targets.values()].map(({ target }) => ({
|
||||
...target,
|
||||
}));
|
||||
if (_targets.has(pluginId)) {
|
||||
_targets.set(pluginId, [..._targets.get(pluginId)!, ...currentTargets]);
|
||||
} else {
|
||||
_targets.set(pluginId, currentTargets);
|
||||
}
|
||||
}
|
||||
return _targets;
|
||||
#updateResolvers(config: Config, defaultEndpoints?: HostDiscoveryEndpoint[]) {
|
||||
this.#updateFallbackResolvers(config);
|
||||
this.#updatePluginResolvers(config, defaultEndpoints);
|
||||
}
|
||||
|
||||
#getInstanceAddress(config: Config) {
|
||||
#updateFallbackResolvers(config: Config) {
|
||||
const backendBaseUrl = trimEnd(config.getString('backend.baseUrl'), '/');
|
||||
|
||||
const {
|
||||
@@ -236,26 +221,12 @@ export class HostDiscovery implements DiscoveryService {
|
||||
host = `[${host}]`;
|
||||
}
|
||||
|
||||
return {
|
||||
internal: `${protocol}://${host}:${listenPort}`,
|
||||
external: backendBaseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
#updateResolvers(config: Config, defaultEndpoints?: HostDiscoveryEndpoint[]) {
|
||||
this.#updateFallbackResolvers(config);
|
||||
this.#updatePluginResolvers(config, defaultEndpoints);
|
||||
}
|
||||
|
||||
#updateFallbackResolvers(config: Config) {
|
||||
const { internal, external } = this.#getInstanceAddress(config);
|
||||
|
||||
this.#internalFallbackResolver = this.#makeResolver(
|
||||
`${internal}/api/{{pluginId}}`,
|
||||
`${protocol}://${host}:${listenPort}/api/{{pluginId}}`,
|
||||
false,
|
||||
);
|
||||
this.#externalFallbackResolver = this.#makeResolver(
|
||||
`${external}/api/{{pluginId}}`,
|
||||
`${backendBaseUrl}/api/{{pluginId}}`,
|
||||
false,
|
||||
);
|
||||
}
|
||||
@@ -268,25 +239,7 @@ export class HostDiscovery implements DiscoveryService {
|
||||
const endpoints = defaultEndpoints?.slice() ?? [];
|
||||
|
||||
// Allow config to override the default endpoints
|
||||
const endpointConfigs = config.getOptionalConfigArray(
|
||||
'discovery.endpoints',
|
||||
);
|
||||
for (const endpointConfig of endpointConfigs ?? []) {
|
||||
if (typeof endpointConfig.get('target') === 'string') {
|
||||
endpoints.push({
|
||||
target: endpointConfig.getString('target'),
|
||||
plugins: endpointConfig.getStringArray('plugins'),
|
||||
});
|
||||
} else {
|
||||
endpoints.push({
|
||||
target: {
|
||||
internal: endpointConfig.getOptionalString('target.internal'),
|
||||
external: endpointConfig.getOptionalString('target.external'),
|
||||
},
|
||||
plugins: endpointConfig.getStringArray('plugins'),
|
||||
});
|
||||
}
|
||||
}
|
||||
endpoints.push(...getEndpoints(config));
|
||||
|
||||
// Build up a new set of resolvers
|
||||
const internalResolvers: Map<string, Resolver> = new Map();
|
||||
@@ -294,7 +247,6 @@ export class HostDiscovery implements DiscoveryService {
|
||||
for (const { target, plugins } of endpoints) {
|
||||
let internalResolver: Resolver | undefined;
|
||||
let externalResolver: Resolver | undefined;
|
||||
this.#addResolution(target, plugins);
|
||||
|
||||
if (typeof target === 'string') {
|
||||
internalResolver = externalResolver = this.#makeResolver(target, false);
|
||||
@@ -324,26 +276,6 @@ export class HostDiscovery implements DiscoveryService {
|
||||
this.#externalResolvers = externalResolvers;
|
||||
}
|
||||
|
||||
#addResolution(
|
||||
target: string | { internal?: string; external?: string },
|
||||
plugins: string[],
|
||||
) {
|
||||
for (const pluginId of plugins) {
|
||||
if (!this.#resolutions.has(pluginId)) {
|
||||
this.#resolutions.set(pluginId, new Set());
|
||||
}
|
||||
const standardizedTarget =
|
||||
typeof target === 'string'
|
||||
? { external: target, internal: target }
|
||||
: target;
|
||||
const matchingResolution = this.#resolutions.get(pluginId)!;
|
||||
const hash = JSON.stringify(standardizedTarget);
|
||||
if (![...matchingResolution.values()].some(e => e.hash === hash)) {
|
||||
matchingResolution.add({ target: standardizedTarget, hash });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#makeResolver(urlPattern: string, allowSrv: boolean): Resolver {
|
||||
const withPluginId = (pluginId: string, url: string) => {
|
||||
return url.replace(
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2025 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 { Config } from '@backstage/config';
|
||||
import type { HostDiscoveryEndpoint } from './HostDiscovery';
|
||||
|
||||
export function getEndpoints(config: Config): HostDiscoveryEndpoint[] {
|
||||
const endpoints: HostDiscoveryEndpoint[] = [];
|
||||
// Allow config to override the default endpoints
|
||||
const endpointConfigs = config.getOptionalConfigArray('discovery.endpoints');
|
||||
for (const endpointConfig of endpointConfigs ?? []) {
|
||||
if (typeof endpointConfig.get('target') === 'string') {
|
||||
endpoints.push({
|
||||
target: endpointConfig.getString('target'),
|
||||
plugins: endpointConfig.getStringArray('plugins'),
|
||||
});
|
||||
} else {
|
||||
endpoints.push({
|
||||
target: {
|
||||
internal: endpointConfig.getOptionalString('target.internal'),
|
||||
external: endpointConfig.getOptionalString('target.external'),
|
||||
},
|
||||
plugins: endpointConfig.getStringArray('plugins'),
|
||||
});
|
||||
}
|
||||
}
|
||||
return endpoints;
|
||||
}
|
||||
Reference in New Issue
Block a user