Merge pull request #19334 from backstage/service-factories-become-backend-features
Service factories become backend features
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
---
|
||||
'@backstage/backend-plugin-api': patch
|
||||
'@backstage/backend-test-utils': minor
|
||||
'@backstage/backend-defaults': minor
|
||||
'@backstage/backend-app-api': minor
|
||||
---
|
||||
|
||||
**BREAKING**: Removed the `services` option from `createBackend`. Service factories are now `BackendFeature`s and should be installed with `backend.add(...)` instead. The following should be migrated:
|
||||
|
||||
```ts
|
||||
const backend = createBackend({ services: [myCustomServiceFactory] });
|
||||
```
|
||||
|
||||
To instead pass the service factory via `backend.add(...)`:
|
||||
|
||||
```ts
|
||||
const backend = createBackend();
|
||||
backend.add(customRootLoggerServiceFactory);
|
||||
```
|
||||
@@ -43,7 +43,7 @@ import { UrlReader } from '@backstage/backend-common';
|
||||
// @public (undocumented)
|
||||
export interface Backend {
|
||||
// (undocumented)
|
||||
add(feature: BackendFeature): void;
|
||||
add(feature: BackendFeature | (() => BackendFeature)): void;
|
||||
// (undocumented)
|
||||
start(): Promise<void>;
|
||||
// (undocumented)
|
||||
@@ -81,7 +81,7 @@ export function createSpecializedBackend(
|
||||
// @public (undocumented)
|
||||
export interface CreateSpecializedBackendOptions {
|
||||
// (undocumented)
|
||||
services: ServiceFactoryOrFunction[];
|
||||
defaultServiceFactories: ServiceFactoryOrFunction[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
|
||||
@@ -95,7 +95,7 @@ describe('featureDiscoveryServiceFactory', () => {
|
||||
const fn = jest.fn().mockResolvedValue({});
|
||||
|
||||
await startTestBackend({
|
||||
services: [
|
||||
features: [
|
||||
createServiceFactory({
|
||||
service: coreServices.identity,
|
||||
deps: {},
|
||||
|
||||
+1
-2
@@ -61,8 +61,7 @@ describe('schedulerFactory', () => {
|
||||
});
|
||||
|
||||
await startTestBackend({
|
||||
features: [plugin()],
|
||||
services: [subject],
|
||||
features: [plugin(), subject],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
createExtensionPoint,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { BackendInitializer } from './BackendInitializer';
|
||||
import { ServiceRegistry } from './ServiceRegistry';
|
||||
|
||||
import {
|
||||
lifecycleServiceFactory,
|
||||
loggerServiceFactory,
|
||||
@@ -65,7 +65,7 @@ describe('BackendInitializer', () => {
|
||||
const rootFactory = jest.fn();
|
||||
const pluginFactory = jest.fn();
|
||||
|
||||
const registry = new ServiceRegistry([
|
||||
const services = [
|
||||
createServiceFactory({
|
||||
service: rootRef,
|
||||
deps: {},
|
||||
@@ -82,9 +82,9 @@ describe('BackendInitializer', () => {
|
||||
deps: {},
|
||||
factory: () => new MockLogger(),
|
||||
})(),
|
||||
]);
|
||||
];
|
||||
|
||||
const init = new BackendInitializer(registry);
|
||||
const init = new BackendInitializer(services);
|
||||
await init.start();
|
||||
|
||||
expect(rootFactory).toHaveBeenCalled();
|
||||
@@ -97,7 +97,7 @@ describe('BackendInitializer', () => {
|
||||
const extensionPoint = createExtensionPoint<{ values: string[] }>({
|
||||
id: 'a',
|
||||
});
|
||||
const init = new BackendInitializer(new ServiceRegistry(baseFactories));
|
||||
const init = new BackendInitializer(baseFactories);
|
||||
|
||||
init.add(
|
||||
createBackendModule({
|
||||
@@ -151,7 +151,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should forward errors when plugins fail to start', async () => {
|
||||
const init = new BackendInitializer(new ServiceRegistry([]));
|
||||
const init = new BackendInitializer([]);
|
||||
init.add(
|
||||
createBackendPlugin({
|
||||
pluginId: 'test',
|
||||
@@ -171,7 +171,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should forward errors when modules fail to start', async () => {
|
||||
const init = new BackendInitializer(new ServiceRegistry([]));
|
||||
const init = new BackendInitializer([]);
|
||||
init.add(
|
||||
createBackendModule({
|
||||
pluginId: 'test',
|
||||
@@ -192,7 +192,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should reject duplicate plugins', async () => {
|
||||
const init = new BackendInitializer(new ServiceRegistry([]));
|
||||
const init = new BackendInitializer([]);
|
||||
init.add(
|
||||
createBackendPlugin({
|
||||
pluginId: 'test',
|
||||
@@ -221,7 +221,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should reject duplicate modules', async () => {
|
||||
const init = new BackendInitializer(new ServiceRegistry([]));
|
||||
const init = new BackendInitializer([]);
|
||||
init.add(
|
||||
createBackendModule({
|
||||
pluginId: 'test',
|
||||
@@ -254,16 +254,14 @@ describe('BackendInitializer', () => {
|
||||
it('should reject modules with circular dependencies', async () => {
|
||||
const extA = createExtensionPoint<string>({ id: 'a' });
|
||||
const extB = createExtensionPoint<string>({ id: 'b' });
|
||||
const init = new BackendInitializer(
|
||||
new ServiceRegistry([
|
||||
rootLifecycleServiceFactory(),
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLogger,
|
||||
deps: {},
|
||||
factory: () => new MockLogger(),
|
||||
})(),
|
||||
]),
|
||||
);
|
||||
const init = new BackendInitializer([
|
||||
rootLifecycleServiceFactory(),
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLogger,
|
||||
deps: {},
|
||||
factory: () => new MockLogger(),
|
||||
})(),
|
||||
]);
|
||||
init.add(
|
||||
createBackendModule({
|
||||
pluginId: 'test',
|
||||
@@ -296,7 +294,7 @@ describe('BackendInitializer', () => {
|
||||
});
|
||||
|
||||
it('should reject modules that depend on extension points other plugins', async () => {
|
||||
const init = new BackendInitializer(new ServiceRegistry(baseFactories));
|
||||
const init = new BackendInitializer(baseFactories);
|
||||
const extA = createExtensionPoint<string>({ id: 'a' });
|
||||
init.add(
|
||||
createBackendPlugin({
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
ExtensionPoint,
|
||||
coreServices,
|
||||
ServiceRef,
|
||||
ServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleServiceFactory';
|
||||
import { BackendPluginLifecycleImpl } from '../services/implementations/lifecycle/lifecycleServiceFactory';
|
||||
@@ -29,6 +30,7 @@ import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring
|
||||
import { ForwardedError, ConflictError } from '@backstage/errors';
|
||||
import { featureDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha';
|
||||
import { DependencyGraph } from '../lib/DependencyGraph';
|
||||
import { ServiceRegistry } from './ServiceRegistry';
|
||||
|
||||
export interface BackendRegisterInit {
|
||||
consumes: Set<ServiceOrExtensionPoint>;
|
||||
@@ -46,10 +48,12 @@ export class BackendInitializer {
|
||||
ExtensionPoint<unknown>,
|
||||
{ impl: unknown; pluginId: string }
|
||||
>();
|
||||
#serviceHolder: EnumerableServiceHolder;
|
||||
#serviceHolder: EnumerableServiceHolder | undefined;
|
||||
#providedServiceFactories = new Array<ServiceFactory>();
|
||||
#defaultApiFactories: ServiceFactory[];
|
||||
|
||||
constructor(serviceHolder: EnumerableServiceHolder) {
|
||||
this.#serviceHolder = serviceHolder;
|
||||
constructor(defaultApiFactories: ServiceFactory[]) {
|
||||
this.#defaultApiFactories = defaultApiFactories;
|
||||
}
|
||||
|
||||
async #getInitDeps(
|
||||
@@ -69,7 +73,7 @@ export class BackendInitializer {
|
||||
}
|
||||
result.set(name, ep.impl);
|
||||
} else {
|
||||
const impl = await this.#serviceHolder.get(
|
||||
const impl = await this.#serviceHolder!.get(
|
||||
ref as ServiceRef<unknown>,
|
||||
pluginId,
|
||||
);
|
||||
@@ -104,13 +108,35 @@ export class BackendInitializer {
|
||||
`Failed to add feature, invalid type '${feature.$$type}'`,
|
||||
);
|
||||
}
|
||||
const internalFeature = feature as InternalBackendFeature;
|
||||
if (internalFeature.version !== 'v1') {
|
||||
|
||||
if (isServiceFactory(feature)) {
|
||||
if (feature.service.id === coreServices.pluginMetadata.id) {
|
||||
throw new Error(
|
||||
`The ${coreServices.pluginMetadata.id} service cannot be overridden`,
|
||||
);
|
||||
}
|
||||
if (
|
||||
this.#providedServiceFactories.find(
|
||||
sf => sf.service.id === feature.service.id,
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
`Duplicate service implementations provided for ${feature.service.id}`,
|
||||
);
|
||||
}
|
||||
this.#providedServiceFactories.push(feature);
|
||||
} else if (isInternalBackendFeature(feature)) {
|
||||
if (feature.version !== 'v1') {
|
||||
throw new Error(
|
||||
`Failed to add feature, invalid version '${feature.version}'`,
|
||||
);
|
||||
}
|
||||
this.#features.push(feature);
|
||||
} else {
|
||||
throw new Error(
|
||||
`Failed to add feature, invalid version '${internalFeature.version}'`,
|
||||
`Failed to add feature, invalid feature ${JSON.stringify(feature)}`,
|
||||
);
|
||||
}
|
||||
this.#features.push(internalFeature);
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
@@ -141,6 +167,11 @@ export class BackendInitializer {
|
||||
}
|
||||
|
||||
async #doStart(): Promise<void> {
|
||||
this.#serviceHolder = new ServiceRegistry([
|
||||
...this.#defaultApiFactories,
|
||||
...this.#providedServiceFactories,
|
||||
]);
|
||||
|
||||
const featureDiscovery = await this.#serviceHolder.get(
|
||||
featureDiscoveryServiceRef,
|
||||
'root',
|
||||
@@ -319,7 +350,7 @@ export class BackendInitializer {
|
||||
|
||||
// Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this
|
||||
async #getRootLifecycleImpl(): Promise<BackendLifecycleImpl> {
|
||||
const lifecycleService = await this.#serviceHolder.get(
|
||||
const lifecycleService = await this.#serviceHolder!.get(
|
||||
coreServices.rootLifecycle,
|
||||
'root',
|
||||
);
|
||||
@@ -332,7 +363,7 @@ export class BackendInitializer {
|
||||
async #getPluginLifecycleImpl(
|
||||
pluginId: string,
|
||||
): Promise<BackendPluginLifecycleImpl> {
|
||||
const lifecycleService = await this.#serviceHolder.get(
|
||||
const lifecycleService = await this.#serviceHolder!.get(
|
||||
coreServices.lifecycle,
|
||||
pluginId,
|
||||
);
|
||||
@@ -342,3 +373,15 @@ export class BackendInitializer {
|
||||
throw new Error('Unexpected plugin lifecycle service implementation');
|
||||
}
|
||||
}
|
||||
|
||||
function isServiceFactory(feature: BackendFeature): feature is ServiceFactory {
|
||||
return !!(feature as ServiceFactory).service;
|
||||
}
|
||||
|
||||
function isInternalBackendFeature(
|
||||
feature: BackendFeature,
|
||||
): feature is InternalBackendFeature {
|
||||
return (
|
||||
typeof (feature as InternalBackendFeature).getRegistrations === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,22 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ServiceFactory, BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { BackendFeature, ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
import { BackendInitializer } from './BackendInitializer';
|
||||
import { ServiceRegistry } from './ServiceRegistry';
|
||||
import { Backend } from './types';
|
||||
|
||||
export class BackstageBackend implements Backend {
|
||||
#services: ServiceRegistry;
|
||||
#initializer: BackendInitializer;
|
||||
|
||||
constructor(apiFactories: ServiceFactory[]) {
|
||||
this.#services = new ServiceRegistry(apiFactories);
|
||||
this.#initializer = new BackendInitializer(this.#services);
|
||||
constructor(defaultServiceFactories: ServiceFactory[]) {
|
||||
this.#initializer = new BackendInitializer(defaultServiceFactories);
|
||||
}
|
||||
|
||||
add(feature: BackendFeature): void {
|
||||
this.#initializer.add(feature);
|
||||
add(feature: BackendFeature | (() => BackendFeature)): void {
|
||||
this.#initializer.add(typeof feature === 'function' ? feature() : feature);
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
|
||||
@@ -31,7 +31,7 @@ const sf1 = createServiceFactory({
|
||||
async factory() {
|
||||
return { x: 1 };
|
||||
},
|
||||
})();
|
||||
});
|
||||
|
||||
const ref2 = createServiceRef<{ x: number }>({
|
||||
scope: 'root',
|
||||
@@ -43,14 +43,14 @@ const sf2 = createServiceFactory({
|
||||
async factory() {
|
||||
return { x: 2 };
|
||||
},
|
||||
})();
|
||||
});
|
||||
const sf2b = createServiceFactory({
|
||||
service: ref2,
|
||||
deps: {},
|
||||
async factory() {
|
||||
return { x: 22 };
|
||||
},
|
||||
})();
|
||||
});
|
||||
|
||||
const refDefault1 = createServiceRef<{ x: number }>({
|
||||
id: '1',
|
||||
@@ -61,7 +61,7 @@ const refDefault1 = createServiceRef<{ x: number }>({
|
||||
async factory() {
|
||||
return { x: 10 };
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
});
|
||||
|
||||
const refDefault2a = createServiceRef<{ x: number }>({
|
||||
@@ -95,7 +95,7 @@ describe('ServiceRegistry', () => {
|
||||
});
|
||||
|
||||
it('should return an implementation for a registered ref', async () => {
|
||||
const registry = new ServiceRegistry([sf1]);
|
||||
const registry = new ServiceRegistry([sf1()]);
|
||||
await expect(registry.get(ref1, 'catalog')).resolves.toEqual({ x: 1 });
|
||||
await expect(registry.get(ref1, 'scaffolder')).resolves.toEqual({ x: 1 });
|
||||
expect(await registry.get(ref1, 'catalog')).toBe(
|
||||
@@ -110,7 +110,7 @@ describe('ServiceRegistry', () => {
|
||||
});
|
||||
|
||||
it('should handle multiple factories with different serviceRefs', async () => {
|
||||
const registry = new ServiceRegistry([sf1, sf2]);
|
||||
const registry = new ServiceRegistry([sf1(), sf2()]);
|
||||
|
||||
await expect(registry.get(ref1, 'catalog')).resolves.toEqual({
|
||||
x: 1,
|
||||
@@ -131,7 +131,7 @@ describe('ServiceRegistry', () => {
|
||||
return { x: 2 };
|
||||
},
|
||||
});
|
||||
const registry = new ServiceRegistry([factory(), sf1]);
|
||||
const registry = new ServiceRegistry([factory(), sf1()]);
|
||||
await expect(registry.get(ref2, 'catalog')).rejects.toThrow(
|
||||
"Failed to instantiate 'root' scoped service '2' because it depends on 'plugin' scoped service '1'.",
|
||||
);
|
||||
@@ -145,7 +145,7 @@ describe('ServiceRegistry', () => {
|
||||
return { x: rootDep.x };
|
||||
},
|
||||
});
|
||||
const registry = new ServiceRegistry([factory(), sf2]);
|
||||
const registry = new ServiceRegistry([factory(), sf2()]);
|
||||
await expect(registry.get(ref1, 'catalog')).resolves.toEqual({
|
||||
x: 2,
|
||||
});
|
||||
@@ -160,7 +160,7 @@ describe('ServiceRegistry', () => {
|
||||
return { x: rootDep.x };
|
||||
},
|
||||
});
|
||||
const registry = new ServiceRegistry([factory(), sf2]);
|
||||
const registry = new ServiceRegistry([factory(), sf2()]);
|
||||
await expect(registry.get(ref, 'catalog')).resolves.toEqual({
|
||||
x: 2,
|
||||
});
|
||||
@@ -182,7 +182,7 @@ describe('ServiceRegistry', () => {
|
||||
});
|
||||
|
||||
it('should use the last factory for each ref', async () => {
|
||||
const registry = new ServiceRegistry([sf2, sf2b]);
|
||||
const registry = new ServiceRegistry([sf2(), sf2b()]);
|
||||
await expect(registry.get(ref2, 'catalog')).resolves.toEqual({
|
||||
x: 22,
|
||||
});
|
||||
@@ -196,7 +196,7 @@ describe('ServiceRegistry', () => {
|
||||
});
|
||||
|
||||
it('should not use the defaultFactory from the ref if provided to the registry', async () => {
|
||||
const registry = new ServiceRegistry([sf1]);
|
||||
const registry = new ServiceRegistry([sf1()]);
|
||||
await expect(registry.get(refDefault1, 'catalog')).resolves.toEqual({
|
||||
x: 1,
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ function toInternalServiceFactory<TService, TScope extends 'plugin' | 'root'>(
|
||||
factory: ServiceFactory<TService, TScope>,
|
||||
): InternalServiceFactory<TService, TScope> {
|
||||
const f = factory as InternalServiceFactory<TService, TScope>;
|
||||
if (f.$$type !== '@backstage/ServiceFactory') {
|
||||
if (f.$$type !== '@backstage/BackendFeature') {
|
||||
throw new Error(`Invalid service factory, bad type '${f.$$type}'`);
|
||||
}
|
||||
if (f.version !== 'v1') {
|
||||
|
||||
@@ -22,13 +22,15 @@ import { createSpecializedBackend } from './createSpecializedBackend';
|
||||
|
||||
describe('createSpecializedBackend', () => {
|
||||
it('should create a backend without services', () => {
|
||||
expect(() => createSpecializedBackend({ services: [] })).not.toThrow();
|
||||
expect(() =>
|
||||
createSpecializedBackend({ defaultServiceFactories: [] }),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw on duplicate service implementations', () => {
|
||||
expect(() =>
|
||||
createSpecializedBackend({
|
||||
services: [
|
||||
defaultServiceFactories: [
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
@@ -55,7 +57,7 @@ describe('createSpecializedBackend', () => {
|
||||
it('should throw when providing a plugin metadata service implementation', () => {
|
||||
expect(() =>
|
||||
createSpecializedBackend({
|
||||
services: [
|
||||
defaultServiceFactories: [
|
||||
createServiceFactory({
|
||||
service: coreServices.pluginMetadata,
|
||||
deps: {},
|
||||
|
||||
@@ -24,7 +24,7 @@ import { Backend, CreateSpecializedBackendOptions } from './types';
|
||||
export function createSpecializedBackend(
|
||||
options: CreateSpecializedBackendOptions,
|
||||
): Backend {
|
||||
const services = options.services.map(sf =>
|
||||
const services = options.defaultServiceFactories.map(sf =>
|
||||
typeof sf === 'function' ? sf() : sf,
|
||||
);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
* @public
|
||||
*/
|
||||
export interface Backend {
|
||||
add(feature: BackendFeature): void;
|
||||
add(feature: BackendFeature | (() => BackendFeature)): void;
|
||||
start(): Promise<void>;
|
||||
stop(): Promise<void>;
|
||||
}
|
||||
@@ -34,7 +34,7 @@ export interface Backend {
|
||||
* @public
|
||||
*/
|
||||
export interface CreateSpecializedBackendOptions {
|
||||
services: ServiceFactoryOrFunction[];
|
||||
defaultServiceFactories: ServiceFactoryOrFunction[];
|
||||
}
|
||||
|
||||
export interface ServiceHolder {
|
||||
|
||||
@@ -4,14 +4,7 @@
|
||||
|
||||
```ts
|
||||
import { Backend } from '@backstage/backend-app-api';
|
||||
import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export function createBackend(options?: CreateBackendOptions): Backend;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CreateBackendOptions {
|
||||
// (undocumented)
|
||||
services?: ServiceFactoryOrFunction[];
|
||||
}
|
||||
export function createBackend(): Backend;
|
||||
```
|
||||
|
||||
@@ -22,60 +22,63 @@ import { createBackend } from './CreateBackend';
|
||||
|
||||
describe('createBackend', () => {
|
||||
it('should not throw when overriding a default service implementation', () => {
|
||||
expect(() =>
|
||||
createBackend({
|
||||
services: [
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
factory: async () => ({
|
||||
addStartupHook: () => {},
|
||||
addShutdownHook: () => {},
|
||||
}),
|
||||
const backend = createBackend();
|
||||
|
||||
expect(() => {
|
||||
backend.add(
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
factory: async () => ({
|
||||
addStartupHook: () => {},
|
||||
addShutdownHook: () => {},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
).not.toThrow();
|
||||
}),
|
||||
);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw on duplicate service implementations', () => {
|
||||
expect(() =>
|
||||
createBackend({
|
||||
services: [
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
factory: async () => ({
|
||||
addStartupHook: () => {},
|
||||
addShutdownHook: () => {},
|
||||
}),
|
||||
}),
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
factory: async () => ({
|
||||
addStartupHook: () => {},
|
||||
addShutdownHook: () => {},
|
||||
}),
|
||||
}),
|
||||
],
|
||||
const backend = createBackend();
|
||||
|
||||
backend.add(
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
factory: async () => ({
|
||||
addStartupHook: () => {},
|
||||
addShutdownHook: () => {},
|
||||
}),
|
||||
}),
|
||||
).toThrow(
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
backend.add(
|
||||
createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {},
|
||||
factory: async () => ({
|
||||
addStartupHook: () => {},
|
||||
addShutdownHook: () => {},
|
||||
}),
|
||||
}),
|
||||
);
|
||||
}).toThrow(
|
||||
'Duplicate service implementations provided for core.rootLifecycle',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw when providing a plugin metadata service implementation', () => {
|
||||
const backend = createBackend();
|
||||
|
||||
expect(() =>
|
||||
createBackend({
|
||||
services: [
|
||||
createServiceFactory({
|
||||
service: coreServices.pluginMetadata,
|
||||
deps: {},
|
||||
factory: async () => ({ getId: () => 'test' }),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
backend.add(
|
||||
createServiceFactory({
|
||||
service: coreServices.pluginMetadata,
|
||||
deps: {},
|
||||
factory: async () => ({ getId: () => 'test' }),
|
||||
}),
|
||||
),
|
||||
).toThrow('The core.pluginMetadata service cannot be overridden');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,10 +33,6 @@ import {
|
||||
urlReaderServiceFactory,
|
||||
identityServiceFactory,
|
||||
} from '@backstage/backend-app-api';
|
||||
import {
|
||||
ServiceFactory,
|
||||
ServiceFactoryOrFunction,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export const defaultServiceFactories = [
|
||||
cacheServiceFactory(),
|
||||
@@ -59,27 +55,6 @@ export const defaultServiceFactories = [
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface CreateBackendOptions {
|
||||
services?: ServiceFactoryOrFunction[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function createBackend(options?: CreateBackendOptions): Backend {
|
||||
const services = new Array<ServiceFactory>();
|
||||
|
||||
// Highest priority: Services passed directly to createBackend
|
||||
const providedServices = (options?.services ?? []).map(sf =>
|
||||
typeof sf === 'function' ? sf() : sf,
|
||||
);
|
||||
services.push(...providedServices);
|
||||
|
||||
// Lowest priority: Default services that are not already provided by environment or directly to createBackend
|
||||
const defaultServices = defaultServiceFactories.filter(
|
||||
sf => !services.some(({ service }) => service.id === sf.service.id),
|
||||
);
|
||||
services.push(...defaultServices);
|
||||
|
||||
return createSpecializedBackend({ services });
|
||||
export function createBackend(): Backend {
|
||||
return createSpecializedBackend({ defaultServiceFactories });
|
||||
}
|
||||
|
||||
@@ -25,5 +25,4 @@
|
||||
// TODO(Rugvip): Remove this once backend-common is no longer used by backend-app-api
|
||||
import '@backstage/backend-common';
|
||||
|
||||
export type { CreateBackendOptions } from './CreateBackend';
|
||||
export { createBackend } from './CreateBackend';
|
||||
|
||||
@@ -409,9 +409,7 @@ export type SearchResponseFile = {
|
||||
export interface ServiceFactory<
|
||||
TService = unknown,
|
||||
TScope extends 'plugin' | 'root' = 'plugin' | 'root',
|
||||
> {
|
||||
// (undocumented)
|
||||
$$type: '@backstage/ServiceFactory';
|
||||
> extends BackendFeature {
|
||||
// (undocumented)
|
||||
service: ServiceRef<TService, TScope>;
|
||||
}
|
||||
|
||||
@@ -21,4 +21,5 @@
|
||||
*/
|
||||
|
||||
export * from './services';
|
||||
export type { BackendFeature } from './types';
|
||||
export * from './wiring';
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BackendFeature } from '../../types';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
@@ -51,9 +53,7 @@ export type ServiceRef<
|
||||
export interface ServiceFactory<
|
||||
TService = unknown,
|
||||
TScope extends 'plugin' | 'root' = 'plugin' | 'root',
|
||||
> {
|
||||
$$type: '@backstage/ServiceFactory';
|
||||
|
||||
> extends BackendFeature {
|
||||
service: ServiceRef<TService, TScope>;
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ export function createServiceFactory<
|
||||
if (anyConf.service.scope === 'root') {
|
||||
const c = anyConf as RootServiceFactoryConfig<TService, TImpl, TDeps>;
|
||||
return {
|
||||
$$type: '@backstage/ServiceFactory',
|
||||
$$type: '@backstage/BackendFeature',
|
||||
version: 'v1',
|
||||
service: c.service,
|
||||
deps: c.deps,
|
||||
@@ -262,7 +262,7 @@ export function createServiceFactory<
|
||||
TDeps
|
||||
>;
|
||||
return {
|
||||
$$type: '@backstage/ServiceFactory',
|
||||
$$type: '@backstage/BackendFeature',
|
||||
version: 'v1',
|
||||
service: c.service,
|
||||
...('createRootContext' in c
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2023 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.
|
||||
*/
|
||||
|
||||
/** @internal */
|
||||
export interface BackendFeatureFactory<
|
||||
TOptions extends [options?: object] = [],
|
||||
> {
|
||||
(...options: TOptions): BackendFeature;
|
||||
$$type: '@backstage/BackendFeatureFactory';
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackendFeature {
|
||||
// NOTE: This type is opaque in order to simplify future API evolution.
|
||||
$$type: '@backstage/BackendFeature';
|
||||
}
|
||||
@@ -14,14 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BackendFeature, BackendFeatureFactory } from '../types';
|
||||
import {
|
||||
BackendModuleRegistrationPoints,
|
||||
BackendPluginRegistrationPoints,
|
||||
ExtensionPoint,
|
||||
InternalBackendModuleRegistration,
|
||||
InternalBackendPluginRegistration,
|
||||
BackendFeatureFactory,
|
||||
BackendFeature,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,5 @@ export {
|
||||
export type {
|
||||
BackendModuleRegistrationPoints,
|
||||
BackendPluginRegistrationPoints,
|
||||
BackendFeature,
|
||||
ExtensionPoint,
|
||||
} from './types';
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ServiceRef } from '../services/system/types';
|
||||
import { BackendFeature } from '../types';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@@ -71,18 +72,6 @@ export interface BackendModuleRegistrationPoints {
|
||||
}): void;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface BackendFeatureFactory {
|
||||
(): BackendFeature;
|
||||
$$type: '@backstage/BackendFeatureFactory';
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackendFeature {
|
||||
// NOTE: This type is opaque in order to simplify future API evolution.
|
||||
$$type: '@backstage/BackendFeature';
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface InternalBackendFeature extends BackendFeature {
|
||||
version: 'v1';
|
||||
|
||||
@@ -21,7 +21,6 @@ import { RootConfigService } from '@backstage/backend-plugin-api';
|
||||
import { RootLifecycleService } from '@backstage/backend-plugin-api';
|
||||
import { SchedulerService } from '@backstage/backend-plugin-api';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
import { ServiceRef } from '@backstage/backend-plugin-api';
|
||||
import { TokenManagerService } from '@backstage/backend-plugin-api';
|
||||
import { UrlReaderService } from '@backstage/backend-plugin-api';
|
||||
|
||||
@@ -127,11 +126,8 @@ export function setupRequestMockHandlers(worker: {
|
||||
}): void;
|
||||
|
||||
// @public (undocumented)
|
||||
export function startTestBackend<
|
||||
TServices extends any[],
|
||||
TExtensionPoints extends any[],
|
||||
>(
|
||||
options: TestBackendOptions<TServices, TExtensionPoints>,
|
||||
export function startTestBackend<TExtensionPoints extends any[]>(
|
||||
options: TestBackendOptions<TExtensionPoints>,
|
||||
): Promise<TestBackend>;
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -140,10 +136,7 @@ export interface TestBackend extends Backend {
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface TestBackendOptions<
|
||||
TServices extends any[],
|
||||
TExtensionPoints extends any[],
|
||||
> {
|
||||
export interface TestBackendOptions<TExtensionPoints extends any[]> {
|
||||
// (undocumented)
|
||||
extensionPoints?: readonly [
|
||||
...{
|
||||
@@ -154,16 +147,7 @@ export interface TestBackendOptions<
|
||||
},
|
||||
];
|
||||
// (undocumented)
|
||||
features?: BackendFeature[];
|
||||
// (undocumented)
|
||||
services?: readonly [
|
||||
...{
|
||||
[index in keyof TServices]:
|
||||
| ServiceFactory<TServices[index]>
|
||||
| (() => ServiceFactory<TServices[index]>)
|
||||
| [ServiceRef<TServices[index]>, Partial<TServices[index]>];
|
||||
},
|
||||
];
|
||||
features?: Array<BackendFeature | (() => BackendFeature)>;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
||||
@@ -31,7 +31,6 @@ import { startTestBackend } from './TestBackend';
|
||||
let globalTestBackendHasBeenStopped = false;
|
||||
beforeAll(async () => {
|
||||
await startTestBackend({
|
||||
services: [],
|
||||
features: [
|
||||
createBackendModule({
|
||||
moduleId: 'test.module',
|
||||
@@ -46,7 +45,7 @@ beforeAll(async () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
@@ -68,17 +67,37 @@ describe('TestBackend', () => {
|
||||
const extensionPoint5 = createExtensionPoint<Obj>({ id: 'b5' });
|
||||
await expect(
|
||||
startTestBackend({
|
||||
services: [
|
||||
features: [
|
||||
// @ts-expect-error
|
||||
[extensionPoint1, { a: 'a' }],
|
||||
[serviceRef, { a: 'a' }],
|
||||
[serviceRef, { a: 'a', b: 'b' }],
|
||||
// @ts-expect-error
|
||||
[serviceRef, { c: 'c' }],
|
||||
// @ts-expect-error
|
||||
[serviceRef, { a: 'a', c: 'c' }],
|
||||
// @ts-expect-error
|
||||
[serviceRef, { a: 'a', b: 'b', c: 'c' }],
|
||||
createServiceFactory(() => ({
|
||||
service: serviceRef,
|
||||
deps: {},
|
||||
// @ts-expect-error
|
||||
factory: async () => ({ a: 'a' }),
|
||||
})),
|
||||
createServiceFactory(() => ({
|
||||
service: serviceRef,
|
||||
deps: {},
|
||||
factory: async () => ({ a: 'a', b: 'b' }),
|
||||
})),
|
||||
createServiceFactory(() => ({
|
||||
service: serviceRef,
|
||||
deps: {},
|
||||
// @ts-expect-error
|
||||
factory: async () => ({ c: 'c' }),
|
||||
})),
|
||||
createServiceFactory(() => ({
|
||||
service: serviceRef,
|
||||
deps: {},
|
||||
// @ts-expect-error
|
||||
factory: async () => ({ a: 'a', c: 'c' }),
|
||||
})),
|
||||
createServiceFactory(() => ({
|
||||
service: serviceRef,
|
||||
deps: {},
|
||||
factory: async () => ({ a: 'a', b: 'b', c: 'c' }),
|
||||
})),
|
||||
],
|
||||
extensionPoints: [
|
||||
// @ts-expect-error
|
||||
@@ -124,8 +143,7 @@ describe('TestBackend', () => {
|
||||
});
|
||||
|
||||
await startTestBackend({
|
||||
services: [sf],
|
||||
features: [testModule()],
|
||||
features: [testModule(), sf()],
|
||||
});
|
||||
|
||||
expect(testFn).toHaveBeenCalledWith('winning');
|
||||
@@ -150,7 +168,6 @@ describe('TestBackend', () => {
|
||||
});
|
||||
|
||||
const backend = await startTestBackend({
|
||||
services: [],
|
||||
features: [testModule()],
|
||||
});
|
||||
|
||||
@@ -192,7 +209,6 @@ describe('TestBackend', () => {
|
||||
});
|
||||
|
||||
await startTestBackend({
|
||||
services: [],
|
||||
features: [testPlugin()],
|
||||
});
|
||||
});
|
||||
@@ -244,7 +260,7 @@ describe('TestBackend', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
createBackendModule({
|
||||
pluginId: 'testB',
|
||||
moduleId: 'test',
|
||||
@@ -256,7 +272,7 @@ describe('TestBackend', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
).resolves.not.toBeUndefined();
|
||||
@@ -277,7 +293,7 @@ describe('TestBackend', () => {
|
||||
async init() {},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
createBackendModule({
|
||||
pluginId: 'testB',
|
||||
moduleId: 'test',
|
||||
@@ -287,7 +303,7 @@ describe('TestBackend', () => {
|
||||
async init() {},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
|
||||
@@ -24,8 +24,6 @@ import {
|
||||
} from '@backstage/backend-app-api';
|
||||
import { HostDiscovery } from '@backstage/backend-common';
|
||||
import {
|
||||
ServiceFactory,
|
||||
ServiceRef,
|
||||
createServiceFactory,
|
||||
BackendFeature,
|
||||
ExtensionPoint,
|
||||
@@ -40,18 +38,7 @@ import express from 'express';
|
||||
import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types';
|
||||
|
||||
/** @public */
|
||||
export interface TestBackendOptions<
|
||||
TServices extends any[],
|
||||
TExtensionPoints extends any[],
|
||||
> {
|
||||
services?: readonly [
|
||||
...{
|
||||
[index in keyof TServices]:
|
||||
| ServiceFactory<TServices[index]>
|
||||
| (() => ServiceFactory<TServices[index]>)
|
||||
| [ServiceRef<TServices[index]>, Partial<TServices[index]>];
|
||||
},
|
||||
];
|
||||
export interface TestBackendOptions<TExtensionPoints extends any[]> {
|
||||
extensionPoints?: readonly [
|
||||
...{
|
||||
[index in keyof TExtensionPoints]: [
|
||||
@@ -60,7 +47,7 @@ export interface TestBackendOptions<
|
||||
];
|
||||
},
|
||||
];
|
||||
features?: BackendFeature[];
|
||||
features?: Array<BackendFeature | (() => BackendFeature)>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
@@ -95,29 +82,37 @@ const defaultServiceFactories = [
|
||||
* @returns
|
||||
*/
|
||||
function createExtensionPointTestModules(
|
||||
features: BackendFeature[],
|
||||
features: Array<BackendFeature | (() => BackendFeature)>,
|
||||
extensionPointTuples?: readonly [
|
||||
ref: ExtensionPoint<unknown>,
|
||||
impl: unknown,
|
||||
][],
|
||||
): BackendFeature[] {
|
||||
): Array<() => BackendFeature> {
|
||||
if (!extensionPointTuples) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const registrations = features.flatMap(feature => {
|
||||
const registrations = features.flatMap(featureOrFunction => {
|
||||
const feature =
|
||||
typeof featureOrFunction === 'function'
|
||||
? featureOrFunction()
|
||||
: featureOrFunction;
|
||||
|
||||
if (feature.$$type !== '@backstage/BackendFeature') {
|
||||
throw new Error(
|
||||
`Failed to add feature, invalid type '${feature.$$type}'`,
|
||||
);
|
||||
}
|
||||
const internalFeature = feature as InternalBackendFeature;
|
||||
if (internalFeature.version !== 'v1') {
|
||||
throw new Error(
|
||||
`Failed to add feature, invalid version '${internalFeature.version}'`,
|
||||
);
|
||||
|
||||
if (isInternalBackendFeature(feature)) {
|
||||
if (feature.version !== 'v1') {
|
||||
throw new Error(
|
||||
`Failed to add feature, invalid version '${feature.version}'`,
|
||||
);
|
||||
}
|
||||
return feature.getRegistrations();
|
||||
}
|
||||
return internalFeature.getRegistrations();
|
||||
return [];
|
||||
});
|
||||
|
||||
const extensionPointMap = new Map(
|
||||
@@ -170,7 +165,7 @@ function createExtensionPointTestModules(
|
||||
|
||||
reg.registerInit({ deps: {}, async init() {} });
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -180,18 +175,10 @@ function createExtensionPointTestModules(
|
||||
const backendInstancesToCleanUp = new Array<Backend>();
|
||||
|
||||
/** @public */
|
||||
export async function startTestBackend<
|
||||
TServices extends any[],
|
||||
TExtensionPoints extends any[],
|
||||
>(
|
||||
options: TestBackendOptions<TServices, TExtensionPoints>,
|
||||
export async function startTestBackend<TExtensionPoints extends any[]>(
|
||||
options: TestBackendOptions<TExtensionPoints>,
|
||||
): Promise<TestBackend> {
|
||||
const {
|
||||
services = [],
|
||||
extensionPoints,
|
||||
features = [],
|
||||
...otherOptions
|
||||
} = options;
|
||||
const { extensionPoints, features = [], ...otherOptions } = options;
|
||||
|
||||
let server: ExtendedHttpServer;
|
||||
|
||||
@@ -247,39 +234,13 @@ export async function startTestBackend<
|
||||
},
|
||||
});
|
||||
|
||||
const factories = services.map(serviceDef => {
|
||||
if (Array.isArray(serviceDef)) {
|
||||
// if type is ExtensionPoint?
|
||||
// do something differently?
|
||||
const [ref, impl] = serviceDef;
|
||||
if (ref.scope === 'plugin') {
|
||||
return createServiceFactory({
|
||||
service: ref as ServiceRef<unknown, 'plugin'>,
|
||||
deps: {},
|
||||
factory: async () => impl,
|
||||
})();
|
||||
}
|
||||
return createServiceFactory({
|
||||
service: ref as ServiceRef<unknown, 'root'>,
|
||||
deps: {},
|
||||
factory: async () => impl,
|
||||
})();
|
||||
}
|
||||
if (typeof serviceDef === 'function') {
|
||||
return serviceDef();
|
||||
}
|
||||
return serviceDef as ServiceFactory;
|
||||
});
|
||||
|
||||
for (const factory of defaultServiceFactories) {
|
||||
if (!factories.some(f => f.service.id === factory.service.id)) {
|
||||
factories.push(factory);
|
||||
}
|
||||
}
|
||||
|
||||
const backend = createSpecializedBackend({
|
||||
...otherOptions,
|
||||
services: [...factories, rootHttpRouterFactory, discoveryFactory],
|
||||
defaultServiceFactories: [
|
||||
...defaultServiceFactories,
|
||||
rootHttpRouterFactory,
|
||||
discoveryFactory,
|
||||
],
|
||||
});
|
||||
|
||||
backendInstancesToCleanUp.push(backend);
|
||||
@@ -329,3 +290,11 @@ function registerTestHooks() {
|
||||
}
|
||||
|
||||
registerTestHooks();
|
||||
|
||||
function isInternalBackendFeature(
|
||||
feature: BackendFeature,
|
||||
): feature is InternalBackendFeature {
|
||||
return (
|
||||
typeof (feature as InternalBackendFeature).getRegistrations === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ describe('appPlugin', () => {
|
||||
|
||||
it('boots', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [appPlugin()],
|
||||
services: [
|
||||
features: [
|
||||
appPlugin(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
app: {
|
||||
|
||||
+20
-10
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { Duration } from 'luxon';
|
||||
import { catalogModuleAwsS3EntityProvider } from './catalogModuleAwsS3EntityProvider';
|
||||
@@ -45,7 +47,7 @@ describe('catalogModuleAwsS3EntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
awsS3: {
|
||||
@@ -57,16 +59,24 @@ describe('catalogModuleAwsS3EntityProvider', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleAwsS3EntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
createServiceFactory(() => ({
|
||||
service: coreServices.logger,
|
||||
deps: {},
|
||||
factory: getVoidLogger,
|
||||
}))(),
|
||||
createServiceFactory(() => ({
|
||||
service: coreServices.scheduler,
|
||||
deps: {},
|
||||
factory: () => scheduler,
|
||||
}))(),
|
||||
],
|
||||
features: [catalogModuleAwsS3EntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+16
-11
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { Duration } from 'luxon';
|
||||
import { catalogModuleAzureDevOpsEntityProvider } from './catalogModuleAzureDevOpsEntityProvider';
|
||||
@@ -45,7 +46,7 @@ describe('catalogModuleAzureDevOpsEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
azureDevOps: {
|
||||
@@ -60,16 +61,20 @@ describe('catalogModuleAzureDevOpsEntityProvider', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleAzureDevOpsEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
mockServices.logger.factory(),
|
||||
createServiceFactory(() => ({
|
||||
deps: {},
|
||||
service: coreServices.scheduler,
|
||||
factory: async () => scheduler,
|
||||
})),
|
||||
],
|
||||
features: [catalogModuleAzureDevOpsEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+11
-4
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
@@ -55,7 +58,8 @@ describe('catalogModuleBitbucketCloudEntityProvider', () => {
|
||||
[catalogProcessingExtensionPoint, catalogExtensionPointImpl],
|
||||
[eventsExtensionPoint, eventsExtensionPointImpl],
|
||||
],
|
||||
services: [
|
||||
features: [
|
||||
catalogModuleBitbucketCloudEntityProvider(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
catalog: {
|
||||
@@ -71,9 +75,12 @@ describe('catalogModuleBitbucketCloudEntityProvider', () => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
[coreServices.scheduler, scheduler],
|
||||
createServiceFactory({
|
||||
service: coreServices.scheduler,
|
||||
deps: {},
|
||||
factory: async () => scheduler,
|
||||
}),
|
||||
],
|
||||
features: [catalogModuleBitbucketCloudEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+16
-11
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { catalogModuleBitbucketServerEntityProvider } from './catalogModuleBitbucketServerEntityProvider';
|
||||
import { Duration } from 'luxon';
|
||||
@@ -45,7 +46,7 @@ describe('catalogModuleBitbucketServerEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
bitbucketServer: {
|
||||
@@ -64,16 +65,20 @@ describe('catalogModuleBitbucketServerEntityProvider', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleBitbucketServerEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
mockServices.logger.factory(),
|
||||
createServiceFactory({
|
||||
service: coreServices.scheduler,
|
||||
deps: {},
|
||||
factory: async () => scheduler,
|
||||
}),
|
||||
],
|
||||
features: [catalogModuleBitbucketServerEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+16
-11
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { Duration } from 'luxon';
|
||||
import { catalogModuleGerritEntityProvider } from './catalogModuleGerritEntityProvider';
|
||||
@@ -45,7 +46,7 @@ describe('catalogModuleGerritEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
gerrit: {
|
||||
@@ -70,16 +71,20 @@ describe('catalogModuleGerritEntityProvider', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleGerritEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
mockServices.logger.factory(),
|
||||
createServiceFactory({
|
||||
service: coreServices.scheduler,
|
||||
deps: {},
|
||||
factory: async () => scheduler,
|
||||
}),
|
||||
],
|
||||
features: [catalogModuleGerritEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+15
-11
@@ -14,18 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { Duration } from 'luxon';
|
||||
import { catalogModuleGithubEntityProvider } from './catalogModuleGithubEntityProvider';
|
||||
import { GithubEntityProvider } from '../providers/GithubEntityProvider';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
describe('catalogModuleGithubEntityProvider', () => {
|
||||
it('should register provider at the catalog extension point', async () => {
|
||||
@@ -45,7 +46,7 @@ describe('catalogModuleGithubEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
github: {
|
||||
@@ -57,16 +58,19 @@ describe('catalogModuleGithubEntityProvider', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleGithubEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
createServiceFactory({
|
||||
service: coreServices.scheduler,
|
||||
deps: {},
|
||||
factory: async () => scheduler,
|
||||
}),
|
||||
],
|
||||
features: [catalogModuleGithubEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+16
-11
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { Duration } from 'luxon';
|
||||
import { catalogModuleGitlabDiscoveryEntityProvider } from './catalogModuleGitlabDiscoveryEntityProvider';
|
||||
@@ -45,7 +46,7 @@ describe('catalogModuleGitlabDiscoveryEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
integrations: {
|
||||
gitlab: [
|
||||
{
|
||||
@@ -69,16 +70,20 @@ describe('catalogModuleGitlabDiscoveryEntityProvider', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleGitlabDiscoveryEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
mockServices.logger.factory(),
|
||||
createServiceFactory({
|
||||
deps: {},
|
||||
service: coreServices.scheduler,
|
||||
factory: async () => scheduler,
|
||||
}),
|
||||
],
|
||||
features: [catalogModuleGitlabDiscoveryEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
|
||||
|
||||
+7
-18
@@ -14,13 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import {
|
||||
coreServices,
|
||||
createBackendModule,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { IncrementalEntityProvider } from '../types';
|
||||
import {
|
||||
@@ -43,26 +42,16 @@ describe('catalogModuleIncrementalIngestionEntityProvider', () => {
|
||||
const addEntityProvider = jest.fn();
|
||||
const httpRouterUse = jest.fn();
|
||||
|
||||
const scheduler = {};
|
||||
const database = {
|
||||
getClient: jest.fn(),
|
||||
};
|
||||
const httpRouter = {
|
||||
use: httpRouterUse,
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [
|
||||
[catalogProcessingExtensionPoint, { addEntityProvider }],
|
||||
],
|
||||
services: [
|
||||
[coreServices.rootConfig, new ConfigReader({})],
|
||||
[coreServices.database, database],
|
||||
[coreServices.httpRouter, httpRouter],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
],
|
||||
features: [
|
||||
createServiceFactory({
|
||||
service: coreServices.httpRouter,
|
||||
deps: {},
|
||||
factory: () => ({ use: httpRouterUse }),
|
||||
}),
|
||||
catalogModuleIncrementalIngestionEntityProvider(),
|
||||
createBackendModule({
|
||||
pluginId: 'catalog',
|
||||
@@ -82,7 +71,7 @@ describe('catalogModuleIncrementalIngestionEntityProvider', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -55,16 +55,15 @@ async function main() {
|
||||
},
|
||||
};
|
||||
|
||||
const backend = createBackend({
|
||||
services: [
|
||||
createServiceFactory({
|
||||
service: coreServices.rootConfig,
|
||||
deps: {},
|
||||
factory: () => new ConfigReader(config),
|
||||
}),
|
||||
],
|
||||
});
|
||||
const backend = createBackend();
|
||||
|
||||
backend.add(
|
||||
createServiceFactory({
|
||||
service: coreServices.rootConfig,
|
||||
deps: {},
|
||||
factory: () => new ConfigReader(config),
|
||||
}),
|
||||
);
|
||||
backend.add(catalogPlugin());
|
||||
backend.add(catalogModuleIncrementalIngestionEntityProvider());
|
||||
backend.add(
|
||||
@@ -86,7 +85,7 @@ async function main() {
|
||||
},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
);
|
||||
|
||||
await backend.start();
|
||||
|
||||
+15
-11
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { Duration } from 'luxon';
|
||||
import { catalogModuleMicrosoftGraphOrgEntityProvider } from './catalogModuleMicrosoftGraphOrgEntityProvider';
|
||||
@@ -45,7 +46,7 @@ describe('catalogModuleMicrosoftGraphOrgEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
microsoftGraphOrg: {
|
||||
@@ -62,16 +63,19 @@ describe('catalogModuleMicrosoftGraphOrgEntityProvider', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModuleMicrosoftGraphOrgEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
createServiceFactory(() => ({
|
||||
deps: {},
|
||||
service: coreServices.scheduler,
|
||||
factory: async () => scheduler,
|
||||
})),
|
||||
],
|
||||
features: [catalogModuleMicrosoftGraphOrgEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual(Duration.fromISO('PT30M'));
|
||||
|
||||
+15
-11
@@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
PluginTaskScheduler,
|
||||
TaskScheduleDefinition,
|
||||
} from '@backstage/backend-tasks';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
|
||||
import { catalogModulePuppetDbEntityProvider } from './catalogModulePuppetDbEntityProvider';
|
||||
import { PuppetDbEntityProvider } from '../providers/PuppetDbEntityProvider';
|
||||
@@ -44,7 +45,7 @@ describe('catalogModulePuppetDbEntityProvider', () => {
|
||||
},
|
||||
} as unknown as PluginTaskScheduler;
|
||||
|
||||
const config = new ConfigReader({
|
||||
const config = {
|
||||
catalog: {
|
||||
providers: {
|
||||
puppetdb: {
|
||||
@@ -56,16 +57,19 @@ describe('catalogModulePuppetDbEntityProvider', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[catalogProcessingExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
catalogModulePuppetDbEntityProvider(),
|
||||
mockServices.rootConfig.factory({ data: config }),
|
||||
createServiceFactory(() => ({
|
||||
deps: {},
|
||||
service: coreServices.scheduler,
|
||||
factory: async () => scheduler,
|
||||
})),
|
||||
],
|
||||
features: [catalogModulePuppetDbEntityProvider()],
|
||||
});
|
||||
|
||||
expect(usedSchedule?.frequency).toEqual({ minutes: 10 });
|
||||
|
||||
@@ -180,7 +180,6 @@ describePerformanceTest('stitchingPerformance', () => {
|
||||
const tracker = new Tracker(knex, load);
|
||||
|
||||
const backend = await startTestBackend({
|
||||
services: [staticDatabase(knex)],
|
||||
features: [
|
||||
catalogPlugin(),
|
||||
createBackendModule({
|
||||
@@ -201,7 +200,8 @@ describePerformanceTest('stitchingPerformance', () => {
|
||||
},
|
||||
});
|
||||
},
|
||||
})(),
|
||||
}),
|
||||
staticDatabase(knex),
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
+40
-35
@@ -14,10 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
SchedulerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha';
|
||||
import { TestEventBroker } from '@backstage/plugin-events-backend-test-utils';
|
||||
import { eventsModuleAwsSqsConsumingEventPublisher } from './eventsModuleAwsSqsConsumingEventPublisher';
|
||||
@@ -25,31 +27,6 @@ import { AwsSqsConsumingEventPublisher } from '../publisher/AwsSqsConsumingEvent
|
||||
|
||||
describe('eventsModuleAwsSqsConsumingEventPublisher', () => {
|
||||
it('should be correctly wired and set up', async () => {
|
||||
const config = new ConfigReader({
|
||||
events: {
|
||||
modules: {
|
||||
awsSqs: {
|
||||
awsSqsConsumingEventPublisher: {
|
||||
topics: {
|
||||
fake1: {
|
||||
queue: {
|
||||
region: 'eu-west-1',
|
||||
url: 'https://fake1.queue.url',
|
||||
},
|
||||
},
|
||||
fake2: {
|
||||
queue: {
|
||||
region: 'us-east-1',
|
||||
url: 'https://fake2.queue.url',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
let addedPublishers: AwsSqsConsumingEventPublisher[] | undefined;
|
||||
const extensionPoint = {
|
||||
addPublishers: (publishers: any) => {
|
||||
@@ -59,16 +36,44 @@ describe('eventsModuleAwsSqsConsumingEventPublisher', () => {
|
||||
|
||||
const scheduler = {
|
||||
scheduleTask: jest.fn(),
|
||||
};
|
||||
} as unknown as SchedulerService;
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
[coreServices.scheduler, scheduler],
|
||||
features: [
|
||||
eventsModuleAwsSqsConsumingEventPublisher(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
events: {
|
||||
modules: {
|
||||
awsSqs: {
|
||||
awsSqsConsumingEventPublisher: {
|
||||
topics: {
|
||||
fake1: {
|
||||
queue: {
|
||||
region: 'eu-west-1',
|
||||
url: 'https://fake1.queue.url',
|
||||
},
|
||||
},
|
||||
fake2: {
|
||||
queue: {
|
||||
region: 'us-east-1',
|
||||
url: 'https://fake2.queue.url',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
createServiceFactory({
|
||||
service: coreServices.scheduler,
|
||||
deps: {},
|
||||
factory: () => scheduler,
|
||||
}),
|
||||
],
|
||||
features: [eventsModuleAwsSqsConsumingEventPublisher()],
|
||||
});
|
||||
|
||||
expect(addedPublishers).not.toBeUndefined();
|
||||
|
||||
-1
@@ -34,7 +34,6 @@ describe('eventsModuleAzureDevOpsEventRouter', () => {
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [],
|
||||
features: [eventsModuleAzureDevOpsEventRouter()],
|
||||
});
|
||||
|
||||
|
||||
-1
@@ -34,7 +34,6 @@ describe('eventsModuleBitbucketCloudEventRouter', () => {
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [],
|
||||
features: [eventsModuleBitbucketCloudEventRouter()],
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ describe('eventsModuleGerritEventRouter', () => {
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [],
|
||||
features: [eventsModuleGerritEventRouter()],
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ describe('eventsModuleGithubEventRouter', () => {
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [],
|
||||
features: [eventsModuleGithubEventRouter()],
|
||||
});
|
||||
|
||||
|
||||
+15
-15
@@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha';
|
||||
import {
|
||||
HttpPostIngressOptions,
|
||||
@@ -47,20 +45,22 @@ describe('eventsModuleGithubWebhook', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const config = new ConfigReader({
|
||||
events: {
|
||||
modules: {
|
||||
github: {
|
||||
webhookSecret: secret,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [[coreServices.rootConfig, config]],
|
||||
features: [eventsModuleGithubWebhook()],
|
||||
features: [
|
||||
eventsModuleGithubWebhook(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
events: {
|
||||
modules: {
|
||||
github: {
|
||||
webhookSecret: secret,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(addedIngress).not.toBeUndefined();
|
||||
|
||||
@@ -34,7 +34,6 @@ describe('eventsModuleGitlabEventRouter', () => {
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [],
|
||||
features: [eventsModuleGitlabEventRouter()],
|
||||
});
|
||||
|
||||
|
||||
+15
-15
@@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { coreServices } from '@backstage/backend-plugin-api';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha';
|
||||
import {
|
||||
HttpPostIngressOptions,
|
||||
@@ -42,20 +40,22 @@ describe('gitlabWebhookEventsModule', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const config = new ConfigReader({
|
||||
events: {
|
||||
modules: {
|
||||
gitlab: {
|
||||
webhookSecret: 'test-secret',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [[eventsExtensionPoint, extensionPoint]],
|
||||
services: [[coreServices.rootConfig, config]],
|
||||
features: [eventsModuleGitlabWebhook()],
|
||||
features: [
|
||||
eventsModuleGitlabWebhook(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
events: {
|
||||
modules: {
|
||||
gitlab: {
|
||||
webhookSecret: 'test-secret',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
expect(addedIngress).not.toBeUndefined();
|
||||
|
||||
@@ -14,13 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { errorHandler, getVoidLogger } from '@backstage/backend-common';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { errorHandler } from '@backstage/backend-common';
|
||||
import {
|
||||
coreServices,
|
||||
createBackendModule,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
|
||||
import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha';
|
||||
import {
|
||||
TestEventBroker,
|
||||
@@ -38,14 +38,6 @@ describe('eventPlugin', () => {
|
||||
const publisher = new TestEventPublisher();
|
||||
const subscriber = new TestEventSubscriber('sub', ['fake']);
|
||||
|
||||
const config = new ConfigReader({
|
||||
events: {
|
||||
http: {
|
||||
topics: ['fake'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const httpRouter = Router();
|
||||
httpRouter.use(express.json());
|
||||
httpRouter.use(errorHandler());
|
||||
@@ -70,12 +62,25 @@ describe('eventPlugin', () => {
|
||||
|
||||
await startTestBackend({
|
||||
extensionPoints: [],
|
||||
services: [
|
||||
[coreServices.rootConfig, config],
|
||||
[coreServices.httpRouter, httpRouter],
|
||||
[coreServices.logger, getVoidLogger()],
|
||||
features: [
|
||||
eventsPlugin(),
|
||||
testModule(),
|
||||
mockServices.logger.factory(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
events: {
|
||||
http: {
|
||||
topics: ['fake'],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
createServiceFactory({
|
||||
service: coreServices.httpRouter,
|
||||
deps: {},
|
||||
factory: async () => httpRouter,
|
||||
}),
|
||||
],
|
||||
features: [eventsPlugin(), testModule()],
|
||||
});
|
||||
|
||||
expect(publisher.eventBroker).toBe(eventBroker);
|
||||
|
||||
@@ -49,8 +49,8 @@ describe('searchModuleCatalogCollator', () => {
|
||||
},
|
||||
],
|
||||
],
|
||||
features: [searchModuleCatalogCollator()],
|
||||
services: [
|
||||
features: [
|
||||
searchModuleCatalogCollator(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
search: {
|
||||
|
||||
@@ -34,8 +34,8 @@ describe('searchModuleExploreCollator', () => {
|
||||
extensionPoints: [
|
||||
[searchIndexRegistryExtensionPoint, extensionPointMock],
|
||||
],
|
||||
features: [searchModuleExploreCollator()],
|
||||
services: [
|
||||
features: [
|
||||
searchModuleExploreCollator(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
search: {
|
||||
|
||||
@@ -34,8 +34,8 @@ describe('searchModuleTechDocsCollator', () => {
|
||||
extensionPoints: [
|
||||
[searchIndexRegistryExtensionPoint, extensionPointMock],
|
||||
],
|
||||
features: [searchModuleTechDocsCollator()],
|
||||
services: [
|
||||
features: [
|
||||
searchModuleTechDocsCollator(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
search: {
|
||||
|
||||
Reference in New Issue
Block a user