more cleanup
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
@@ -40,6 +40,7 @@ import {
|
||||
actionsServiceFactory,
|
||||
} from '@backstage/backend-defaults/alpha';
|
||||
import { instanceMetadataServiceFactory } from './alpha/entrypoints/instanceMetadata/instanceMetadataServiceFactory';
|
||||
import { rootSystemMetadataServiceFactory } from './entrypoints/rootSystemMetadata';
|
||||
|
||||
export const defaultServiceFactories = [
|
||||
auditorServiceFactory,
|
||||
@@ -62,6 +63,7 @@ export const defaultServiceFactories = [
|
||||
userInfoServiceFactory,
|
||||
urlReaderServiceFactory,
|
||||
eventsServiceFactory,
|
||||
rootSystemMetadataServiceFactory,
|
||||
|
||||
// alpha services
|
||||
actionsRegistryServiceFactory,
|
||||
|
||||
+85
-217
@@ -13,199 +13,66 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Backend, createSpecializedBackend } from '@backstage/backend-app-api';
|
||||
import { rootSystemMetadataServiceFactory } from './rootSystemMetadataServiceFactory';
|
||||
|
||||
import { mockServices } from '@backstage/backend-test-utils';
|
||||
import getPort from 'get-port';
|
||||
import { default as getPort } from 'get-port';
|
||||
import {
|
||||
coreServices,
|
||||
createBackendPlugin,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
const baseFactories = [
|
||||
mockServices.rootHealth.factory(),
|
||||
mockServices.rootLogger.factory(),
|
||||
mockServices.rootLifecycle.factory(),
|
||||
mockServices.rootHttpRouter.factory(),
|
||||
mockServices.lifecycle.factory(),
|
||||
mockServices.logger.factory(),
|
||||
];
|
||||
import { createBackend } from '../../CreateBackend';
|
||||
|
||||
describe('SystemMetadataService', () => {
|
||||
describe('multiple backends testing', () => {
|
||||
let instance1: Backend;
|
||||
let instance2: Backend;
|
||||
let instance1HttpPort: number;
|
||||
let instance2HttpPort: number;
|
||||
|
||||
const configFactory = (port: number) =>
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
listen: {
|
||||
port,
|
||||
},
|
||||
},
|
||||
discovery: {
|
||||
instances: [
|
||||
{
|
||||
baseUrl: `http://localhost:${instance1HttpPort}`,
|
||||
},
|
||||
{
|
||||
baseUrl: `http://localhost:${instance2HttpPort}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
beforeEach(async () => {
|
||||
instance1HttpPort = await getPort();
|
||||
instance2HttpPort = await getPort();
|
||||
// Setup code for multiple backend instances
|
||||
instance1 = createSpecializedBackend({
|
||||
defaultServiceFactories: [
|
||||
...baseFactories,
|
||||
rootSystemMetadataServiceFactory,
|
||||
configFactory(instance1HttpPort),
|
||||
],
|
||||
});
|
||||
|
||||
instance2 = createSpecializedBackend({
|
||||
defaultServiceFactories: [
|
||||
...baseFactories,
|
||||
rootSystemMetadataServiceFactory,
|
||||
configFactory(instance2HttpPort),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should list plugins across instances', async () => {
|
||||
instance1.add(
|
||||
createBackendPlugin({
|
||||
pluginId: 'test',
|
||||
register(reg) {
|
||||
reg.registerInit({
|
||||
deps: {},
|
||||
async init() {
|
||||
// do nothing
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
instance2.add(
|
||||
createBackendPlugin({
|
||||
pluginId: 'test-other',
|
||||
register(reg) {
|
||||
reg.registerInit({
|
||||
deps: {},
|
||||
async init() {
|
||||
// do nothing
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await instance1.start();
|
||||
await instance2.start();
|
||||
|
||||
const instance1Response = await fetch(
|
||||
`http://localhost:${instance1HttpPort}/.backstage/systemMetadata/v1/features/installed`,
|
||||
);
|
||||
|
||||
expect(instance1Response.status).toBe(200);
|
||||
await expect(instance1Response.json()).resolves.toMatchObject({
|
||||
test: [
|
||||
{
|
||||
externalUrl: `http://localhost:${instance1HttpPort}`,
|
||||
internalUrl: `http://localhost:${instance1HttpPort}`,
|
||||
},
|
||||
],
|
||||
'test-other': [
|
||||
{
|
||||
externalUrl: `http://localhost:${instance2HttpPort}`,
|
||||
internalUrl: `http://localhost:${instance2HttpPort}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const instance2Response = await fetch(
|
||||
`http://localhost:${instance2HttpPort}/.backstage/systemMetadata/v1/features/installed`,
|
||||
);
|
||||
|
||||
expect(instance2Response.status).toBe(200);
|
||||
|
||||
await expect(instance2Response.json()).resolves.toMatchObject({
|
||||
test: [
|
||||
{
|
||||
externalUrl: `http://localhost:${instance1HttpPort}`,
|
||||
internalUrl: `http://localhost:${instance1HttpPort}`,
|
||||
},
|
||||
],
|
||||
'test-other': [
|
||||
{
|
||||
externalUrl: `http://localhost:${instance2HttpPort}`,
|
||||
internalUrl: `http://localhost:${instance2HttpPort}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await instance1.stop();
|
||||
await instance2.stop();
|
||||
});
|
||||
});
|
||||
|
||||
describe('single backend test', () => {
|
||||
describe('returns plugins from config', () => {
|
||||
let port: number;
|
||||
let instance: Backend;
|
||||
let testPlugin: ReturnType<typeof createBackendPlugin>;
|
||||
beforeEach(async () => {
|
||||
port = await getPort();
|
||||
|
||||
instance = createSpecializedBackend({
|
||||
defaultServiceFactories: [
|
||||
...baseFactories,
|
||||
rootSystemMetadataServiceFactory,
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
listen: {
|
||||
port,
|
||||
},
|
||||
},
|
||||
discovery: {
|
||||
instances: [
|
||||
{
|
||||
baseUrl: `http://localhost:${port}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
testPlugin = createBackendPlugin({
|
||||
pluginId: 'test-plugin',
|
||||
register(reg) {
|
||||
reg.registerInit({
|
||||
deps: {},
|
||||
init: async () => {},
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should list all known instances', async () => {
|
||||
const instance = createBackend();
|
||||
instance.add(
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: {
|
||||
listen: {
|
||||
port,
|
||||
},
|
||||
baseUrl: `http://localhost:${port}`,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
instance.add(testPlugin);
|
||||
await instance.start();
|
||||
|
||||
const instanceResponse = await fetch(
|
||||
`http://localhost:${port}/.backstage/systemMetadata/v1/instances`,
|
||||
`http://localhost:${port}/.backstage/systemMetadata/v1/plugins/installed`,
|
||||
);
|
||||
|
||||
expect(instanceResponse.status).toBe(200);
|
||||
await expect(instanceResponse.json()).resolves.toMatchObject({
|
||||
items: [
|
||||
{
|
||||
externalUrl: `http://localhost:${port}`,
|
||||
internalUrl: `http://localhost:${port}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
await expect(instanceResponse.json()).resolves.toMatchObject([
|
||||
{
|
||||
hosts: [
|
||||
{
|
||||
external: `http://localhost:${port}`,
|
||||
internal: `http://localhost:${port}`,
|
||||
},
|
||||
],
|
||||
pluginId: 'test-plugin',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should react to config updates', async () => {
|
||||
@@ -215,16 +82,7 @@ describe('SystemMetadataService', () => {
|
||||
listen: {
|
||||
port,
|
||||
},
|
||||
},
|
||||
discovery: {
|
||||
instances: [
|
||||
{
|
||||
baseUrl: `http://localhost:${port}`,
|
||||
},
|
||||
{
|
||||
baseUrl: `not-a-real-host`,
|
||||
},
|
||||
],
|
||||
baseUrl: `http://localhost:${port}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -233,39 +91,41 @@ describe('SystemMetadataService', () => {
|
||||
deps: {},
|
||||
factory: () => config,
|
||||
});
|
||||
instance = createSpecializedBackend({
|
||||
defaultServiceFactories: [
|
||||
...baseFactories,
|
||||
rootSystemMetadataServiceFactory,
|
||||
configFactory,
|
||||
],
|
||||
});
|
||||
const instance = createBackend();
|
||||
instance.add(configFactory);
|
||||
instance.add(testPlugin);
|
||||
await instance.start();
|
||||
|
||||
const instance1Response = await fetch(
|
||||
`http://localhost:${port}/.backstage/systemMetadata/v1/instances`,
|
||||
`http://localhost:${port}/.backstage/systemMetadata/v1/plugins/installed`,
|
||||
);
|
||||
|
||||
expect(instance1Response.status).toBe(200);
|
||||
await expect(instance1Response.json()).resolves.toMatchObject({
|
||||
items: [
|
||||
{
|
||||
externalUrl: `http://localhost:${port}`,
|
||||
internalUrl: `http://localhost:${port}`,
|
||||
},
|
||||
{
|
||||
externalUrl: `not-a-real-host`,
|
||||
internalUrl: `not-a-real-host`,
|
||||
},
|
||||
],
|
||||
});
|
||||
await expect(instance1Response.json()).resolves.toMatchObject([
|
||||
{
|
||||
hosts: [
|
||||
{
|
||||
external: `http://localhost:${port}`,
|
||||
internal: `http://localhost:${port}`,
|
||||
},
|
||||
],
|
||||
pluginId: 'test-plugin',
|
||||
},
|
||||
]);
|
||||
|
||||
config.update({
|
||||
data: {
|
||||
backend: {
|
||||
listen: {
|
||||
port,
|
||||
},
|
||||
baseUrl: `http://localhost:${port}`,
|
||||
},
|
||||
discovery: {
|
||||
instances: [
|
||||
endpoints: [
|
||||
{
|
||||
baseUrl: `http://localhost:${port}`,
|
||||
target: `http://test.internal`,
|
||||
plugins: ['your-new-plugin'],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -273,22 +133,30 @@ describe('SystemMetadataService', () => {
|
||||
});
|
||||
|
||||
const responseAfterUpdate = await fetch(
|
||||
`http://localhost:${port}/.backstage/systemMetadata/v1/instances`,
|
||||
`http://localhost:${port}/.backstage/systemMetadata/v1/plugins/installed`,
|
||||
);
|
||||
|
||||
expect(responseAfterUpdate.status).toBe(200);
|
||||
await expect(responseAfterUpdate.json()).resolves.toMatchObject({
|
||||
items: [
|
||||
{
|
||||
externalUrl: `http://localhost:${port}`,
|
||||
internalUrl: `http://localhost:${port}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await instance.stop();
|
||||
await expect(responseAfterUpdate.json()).resolves.toMatchObject([
|
||||
{
|
||||
hosts: [
|
||||
{
|
||||
external: 'http://test.internal',
|
||||
internal: 'http://test.internal',
|
||||
},
|
||||
],
|
||||
pluginId: 'your-new-plugin',
|
||||
},
|
||||
{
|
||||
hosts: [
|
||||
{
|
||||
external: `http://localhost:${port}`,
|
||||
internal: `http://localhost:${port}`,
|
||||
},
|
||||
],
|
||||
pluginId: 'test-plugin',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
-14
@@ -22,7 +22,6 @@ import {
|
||||
RootSystemMetadataServicePluginInfo,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { HostDiscovery } from '../../discovery';
|
||||
import {} from '@backstage/backend-plugin-api';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
@@ -80,17 +79,4 @@ export class DefaultRootSystemMetadataService
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
public async getHosts(): Promise<
|
||||
ReadonlyArray<string | { external: string; internal: string }>
|
||||
> {
|
||||
const resolutions = await this.#hostDiscovery.listResolutions();
|
||||
const hosts = new Set<string | { external: string; internal: string }>();
|
||||
for (const [_, targets] of resolutions.entries()) {
|
||||
for (const target of targets) {
|
||||
hosts.add(target as string | { external: string; internal: string });
|
||||
}
|
||||
}
|
||||
return Array.from(hosts);
|
||||
}
|
||||
}
|
||||
|
||||
-5
@@ -26,11 +26,6 @@ export async function createSystemMetadataRouter(options: {
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/hosts', async (_, res) => {
|
||||
const hosts = await systemMetadata.getHosts();
|
||||
res.json({ items: hosts });
|
||||
});
|
||||
|
||||
router.get('/plugins/installed', async (_, res) => {
|
||||
res.json(await systemMetadata.getInstalledPlugins());
|
||||
});
|
||||
|
||||
@@ -39,10 +39,7 @@ import { ConfigSources } from '@backstage/config-loader';
|
||||
import { Logs, MockedLogger, LogContent } from '../__testUtils__/testUtils';
|
||||
import { PluginScanner } from '../scanner/plugin-scanner';
|
||||
import { findPaths } from '@backstage/cli-common';
|
||||
import {
|
||||
createMockDirectory,
|
||||
mockServices,
|
||||
} from '@backstage/backend-test-utils';
|
||||
import { createMockDirectory } from '@backstage/backend-test-utils';
|
||||
import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';
|
||||
import { BackstagePackageJson, PackageRole } from '@backstage/cli-node';
|
||||
|
||||
@@ -1000,8 +997,6 @@ describe('backend-dynamic-feature-service', () => {
|
||||
|
||||
const backend = createSpecializedBackend({
|
||||
defaultServiceFactories: [
|
||||
mockServices.rootHealth.factory(),
|
||||
mockServices.rootHttpRouter.mock().factory,
|
||||
rootLifecycleServiceFactory,
|
||||
createServiceFactory({
|
||||
service: coreServices.rootConfig,
|
||||
|
||||
@@ -25,8 +25,4 @@ export interface RootSystemMetadataService {
|
||||
getInstalledPlugins: () => Promise<
|
||||
ReadonlyArray<RootSystemMetadataServicePluginInfo>
|
||||
>;
|
||||
|
||||
getHosts: () => Promise<
|
||||
ReadonlyArray<string | { external: string; internal: string }>
|
||||
>;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
"text-extensions": "^2.4.0",
|
||||
"uuid": "^11.0.0",
|
||||
"yn": "^4.0.0",
|
||||
"zen-observable": "^0.10.0",
|
||||
"zod": "^3.22.4",
|
||||
"zod-to-json-schema": "^3.20.4"
|
||||
},
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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 { Observable } from '@backstage/types';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
|
||||
export function createMockObservable<T>(value: T): Observable<T> {
|
||||
return new ObservableImpl(observer => {
|
||||
observer.next(value);
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
@@ -39,7 +39,6 @@ export function simpleMock<TService>(
|
||||
const mock = mockFactory();
|
||||
if (partialImpl) {
|
||||
for (const [key, impl] of Object.entries(partialImpl)) {
|
||||
console.log(key, impl, mock);
|
||||
if (typeof impl === 'function') {
|
||||
(mock as any)[key].mockImplementation(impl);
|
||||
} else {
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
coreServices,
|
||||
createBackendFeatureLoader,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { rootSystemMetadataServiceFactory } from '@backstage/backend-defaults/rootSystemMetadata';
|
||||
|
||||
const backend = createBackend();
|
||||
|
||||
@@ -70,7 +69,6 @@ backend.add(searchLoader);
|
||||
backend.add(import('@backstage/plugin-techdocs-backend'));
|
||||
backend.add(import('@backstage/plugin-signals-backend'));
|
||||
backend.add(import('@backstage/plugin-notifications-backend'));
|
||||
backend.add(rootSystemMetadataServiceFactory);
|
||||
|
||||
backend.add(import('@backstage/plugin-events-backend-module-google-pubsub'));
|
||||
backend.add(import('@backstage/plugin-mcp-actions-backend'));
|
||||
|
||||
@@ -2854,7 +2854,6 @@ __metadata:
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/errors": "workspace:^"
|
||||
express-promise-router: "npm:^4.1.0"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -2951,7 +2950,6 @@ __metadata:
|
||||
winston-transport: "npm:^4.5.0"
|
||||
yauzl: "npm:^3.0.0"
|
||||
yn: "npm:^4.0.0"
|
||||
zen-observable: "npm:^0.10.0"
|
||||
zod: "npm:^3.22.4"
|
||||
zod-to-json-schema: "npm:^3.20.4"
|
||||
peerDependencies:
|
||||
@@ -3104,7 +3102,6 @@ __metadata:
|
||||
text-extensions: "npm:^2.4.0"
|
||||
uuid: "npm:^11.0.0"
|
||||
yn: "npm:^4.0.0"
|
||||
zen-observable: "npm:^0.10.0"
|
||||
zod: "npm:^3.22.4"
|
||||
zod-to-json-schema: "npm:^3.20.4"
|
||||
languageName: unknown
|
||||
|
||||
Reference in New Issue
Block a user