update config handling to support internal/external split and adjust types

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
aramissennyeydd
2025-01-17 18:11:02 -05:00
parent fcc38f1b01
commit ff2c41bff5
6 changed files with 50 additions and 22 deletions
@@ -38,7 +38,7 @@ export class DefaultSystemMetadataService implements SystemMetadataService {
// @alpha
export const systemMetadataServiceFactory: ServiceFactory<
SystemMetadataService,
'plugin',
'root',
'singleton'
>;
@@ -22,14 +22,49 @@ import {
BackstageInstance,
SystemMetadataService,
} from '@backstage/backend-plugin-api/alpha';
import z from 'zod';
const targetObjectSchema = z.object({
internal: z.string(),
external: z.string(),
});
/**
* @alpha
*/
export class DefaultSystemMetadataService implements SystemMetadataService {
private instances: BackstageInstance[];
constructor(
private options: { logger: LoggerService; config: RootConfigService },
) {}
) {
const getInstances = () => {
const endpoints =
options.config.getOptionalConfigArray('discovery.instances') ?? [];
const instances: BackstageInstance[] = [];
for (const endpoint of endpoints) {
const baseUrl = endpoint.getOptional('baseUrl');
if (baseUrl) {
if (typeof baseUrl === 'string') {
instances.push({ internalUrl: baseUrl, externalUrl: baseUrl });
} else {
const parseAttempt = targetObjectSchema.safeParse(baseUrl);
if (parseAttempt.success) {
const { internal, external } = parseAttempt.data;
instances.push({
internalUrl: internal,
externalUrl: external,
});
}
}
}
}
return instances;
};
this.instances = getInstances();
this.options.config.subscribe?.(() => {
this.instances = getInstances();
});
}
public static create(pluginEnv: {
logger: LoggerService;
@@ -39,15 +74,6 @@ export class DefaultSystemMetadataService implements SystemMetadataService {
}
async listInstances() {
const endpoints =
this.options.config.getOptionalConfigArray('discovery.instances') ?? [];
const instances: BackstageInstance[] = [];
for (const endpoint of endpoints) {
const baseUrl = endpoint.getOptionalString('baseUrl');
if (baseUrl) {
instances.push({ url: baseUrl });
}
}
return instances;
return this.instances;
}
}
@@ -43,17 +43,20 @@ export async function createSystemMetadataRouter(options: {
const featurePromises = await Promise.allSettled(
instances.map(async instance => {
const response = await fetch(
`${instance.url}/.backstage/instanceMetadata/v1/features/installed`,
`${instance.internalUrl}/.backstage/instanceMetadata/v1/features/installed`,
);
if (response.ok) {
return { instance, response: await response.json() };
}
throw new Error(
`Failed to fetch installed features from ${instance.url}`,
`Failed to fetch installed features from ${instance.internalUrl}`,
);
}),
);
const pluginByInstance: Record<string, string[]> = {};
const pluginByInstance: Record<
string,
{ internalUrl: string; externalUrl: string }[]
> = {};
for (const result of featurePromises) {
if (result.status !== 'fulfilled') {
logger.error(`Failed to fetch installed features: ${result.reason}`);
@@ -67,7 +70,7 @@ export async function createSystemMetadataRouter(options: {
if (!pluginByInstance[feature.pluginId]) {
pluginByInstance[feature.pluginId] = [];
}
pluginByInstance[feature.pluginId].push(instance.url);
pluginByInstance[feature.pluginId].push(instance);
}
}
}
@@ -40,5 +40,4 @@ export const systemMetadataServiceRef = createServiceRef<
export type {
BackstageInstance,
SystemMetadataService,
Target,
} from './services/definitions/SystemMetadataService';
@@ -14,14 +14,12 @@
* limitations under the License.
*/
/** @alpha */
export type Target = string | { internal: string; external: string };
/**
* @alpha
*/
export interface BackstageInstance {
url: Target;
internalUrl: string;
externalUrl: string;
}
/**
+3 -1
View File
@@ -6,4 +6,6 @@ discovery:
plugins: [catalog]
instances:
- baseUrl: http://localhost:7007
- baseUrl: http://localhost:7008
- baseUrl:
internal: http://localhost:7008
external: http://127.0.0.1:7008