diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 02c5450021..b0bbb8cc8b 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -36,6 +36,8 @@ "dependencies": { "@backstage/backend-plugin-api": "^0.0.0", "@backstage/backend-common": "^0.14.0", + "@backstage/backend-tasks": "^0.3.2", + "@backstage/plugin-permission-node": "^0.6.2", "winston": "^3.2.1" }, "devDependencies": { diff --git a/packages/backend-app-api/src/services/implementations/cacheService.ts b/packages/backend-app-api/src/services/implementations/cacheService.ts new file mode 100644 index 0000000000..034f85f917 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/cacheService.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 { CacheManager } from '@backstage/backend-common'; +import { + configServiceRef, + createServiceFactory, + cacheServiceRef, +} from '@backstage/backend-plugin-api'; + +// TODO: Work out some naming and implementation patterns for these +export const cacheFactory = createServiceFactory({ + service: cacheServiceRef, + deps: { + configFactory: configServiceRef, + }, + factory: async ({ configFactory }) => { + const config = await configFactory('root'); + const cacheManager = CacheManager.fromConfig(config); + return async (pluginId: string) => { + return cacheManager.forPlugin(pluginId); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/configService.ts b/packages/backend-app-api/src/services/implementations/configService.ts index b066989069..e9a81ae100 100644 --- a/packages/backend-app-api/src/services/implementations/configService.ts +++ b/packages/backend-app-api/src/services/implementations/configService.ts @@ -22,16 +22,19 @@ import { } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from './loggerService'; -export const configService = createServiceFactory({ +export const configFactory = createServiceFactory({ service: configServiceRef, - deps: { loggerFactory: loggerServiceRef }, + deps: { + loggerFactory: loggerServiceRef, + }, factory: async ({ loggerFactory }) => { const logger = await loggerFactory('root'); const config = await loadBackendConfig({ argv: process.argv, logger: loggerToWinstonLogger(logger), }); - - return async () => config; + return async () => { + return config; + }; }, }); diff --git a/packages/backend-app-api/src/services/implementations/databaseService.ts b/packages/backend-app-api/src/services/implementations/databaseService.ts new file mode 100644 index 0000000000..a52da1e444 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/databaseService.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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 { DatabaseManager } from '@backstage/backend-common'; +import { + configServiceRef, + createServiceFactory, + databaseServiceRef, +} from '@backstage/backend-plugin-api'; + +export const databaseFactory = createServiceFactory({ + service: databaseServiceRef, + deps: { + configFactory: configServiceRef, + }, + factory: async ({ configFactory }) => { + const config = await configFactory('root'); + const databaseManager = DatabaseManager.fromConfig(config); + return async (pluginId: string) => { + return databaseManager.forPlugin(pluginId); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/discoveryService.ts b/packages/backend-app-api/src/services/implementations/discoveryService.ts new file mode 100644 index 0000000000..23af1924a0 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/discoveryService.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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 { SingleHostDiscovery } from '@backstage/backend-common'; +import { + configServiceRef, + createServiceFactory, + discoveryServiceRef, +} from '@backstage/backend-plugin-api'; + +export const discoveryFactory = createServiceFactory({ + service: discoveryServiceRef, + deps: { + configFactory: configServiceRef, + }, + factory: async ({ configFactory }) => { + const config = await configFactory('root'); + const discovery = SingleHostDiscovery.fromConfig(config); + return async () => { + return discovery; + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts new file mode 100644 index 0000000000..f520b43cd4 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/index.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 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 { cacheFactory } from './cacheService'; +import { configFactory } from './configService'; +import { databaseFactory } from './databaseService'; +import { discoveryFactory } from './discoveryService'; +import { loggerFactory } from './loggerService'; +import { permissionsFactory } from './permissionsService'; +import { schedulerFactory } from './schedulerService'; +import { tokenManagerFactory } from './tokenManagerService'; +import { urlReaderFactory } from './urlReaderService'; + +export const defaultServiceFactories = [ + cacheFactory, + configFactory, + databaseFactory, + discoveryFactory, + loggerFactory, + permissionsFactory, + schedulerFactory, + tokenManagerFactory, + urlReaderFactory, +]; diff --git a/packages/backend-app-api/src/services/implementations/loggerService.ts b/packages/backend-app-api/src/services/implementations/loggerService.ts index 4b6eadfa1f..ff6af4b643 100644 --- a/packages/backend-app-api/src/services/implementations/loggerService.ts +++ b/packages/backend-app-api/src/services/implementations/loggerService.ts @@ -55,7 +55,6 @@ export const loggerFactory = createServiceFactory({ const root = new BackstageLogger({ winston: createRootLogger(), }); - return async (pluginId: string) => { return root.child({ pluginId }); }; diff --git a/packages/backend-app-api/src/services/implementations/permissionsService.ts b/packages/backend-app-api/src/services/implementations/permissionsService.ts new file mode 100644 index 0000000000..97f0330917 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/permissionsService.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2022 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 { + configServiceRef, + createServiceFactory, + discoveryServiceRef, + permissionsServiceRef, + tokenManagerServiceRef, +} from '@backstage/backend-plugin-api'; +import { ServerPermissionClient } from '@backstage/plugin-permission-node'; + +export const permissionsFactory = createServiceFactory({ + service: permissionsServiceRef, + deps: { + configFactory: configServiceRef, + discoveryFactory: discoveryServiceRef, + tokenManagerFactory: tokenManagerServiceRef, + }, + factory: async ({ configFactory, discoveryFactory, tokenManagerFactory }) => { + const config = await configFactory('root'); + const discovery = await discoveryFactory('root'); + const tokenManager = await tokenManagerFactory('root'); + const permissions = ServerPermissionClient.fromConfig(config, { + discovery, + tokenManager, + }); + return async (_pluginId: string) => { + return permissions; + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/schedulerService.ts b/packages/backend-app-api/src/services/implementations/schedulerService.ts new file mode 100644 index 0000000000..130ccb3f5f --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/schedulerService.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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 { + configServiceRef, + createServiceFactory, + schedulerServiceRef, +} from '@backstage/backend-plugin-api'; +import { TaskScheduler } from '@backstage/backend-tasks'; + +export const schedulerFactory = createServiceFactory({ + service: schedulerServiceRef, + deps: { + configFactory: configServiceRef, + }, + factory: async ({ configFactory }) => { + const config = await configFactory('root'); + const taskScheduler = TaskScheduler.fromConfig(config); + return async (pluginId: string) => { + return taskScheduler.forPlugin(pluginId); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/tokenManagerService.ts b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts new file mode 100644 index 0000000000..7f0423e845 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts @@ -0,0 +1,60 @@ +/* + * Copyright 2022 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 { + configServiceRef, + loggerServiceRef, + createServiceFactory, + tokenManagerServiceRef, +} from '@backstage/backend-plugin-api'; +import { ServerTokenManager } from '@backstage/backend-common'; +import { loggerToWinstonLogger } from './loggerService'; + +export const tokenManagerFactory = createServiceFactory({ + service: tokenManagerServiceRef, + deps: { + configFactory: configServiceRef, + loggerFactory: loggerServiceRef, + }, + factory: async ({ configFactory, loggerFactory }) => { + const logger = await loggerFactory('root'); + const config = await configFactory('root'); + return async (_pluginId: string) => { + // doesn't the logger want to be inferred from the plugin tho here? + // maybe ... also why do we recreate it every time otherwise + // we should memoize on a per plugin right? so I think it's should be fine to re-use the plugin one + // we shouldn't recreate on a per plugin basis. + // hm - on the other hand, is this really ever called more than once? + // not this function right. should only be called when the plugin requests this serviceRef + // yeah so no need to worry about memo probably + // but we still want to scope the logger to the ServrTokenmanagfer>? + // mm sure maybe + // maybe in this case it doesn't provide so much value b + // oh hang on - isn't it up to THE MANAGER to make a child internally if it wants to do that + // so that it becomes a property intrinsic to that class, no matter how it's constructed + // or is that too much responsibility for it - making the constructor complex so to speak, making it harder to tweak that behavior + // this is not ultra efficient :) + + // I think the naming here is wrong to be gonest + // this isn't like the cache manager or the database manager + // the manager name is confusuion i think + // aye perhaps + return ServerTokenManager.fromConfig(config, { + logger: loggerToWinstonLogger(logger), + }); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/urlReaderService.ts b/packages/backend-app-api/src/services/implementations/urlReaderService.ts index afbc80d9ac..7df6ca33a9 100644 --- a/packages/backend-app-api/src/services/implementations/urlReaderService.ts +++ b/packages/backend-app-api/src/services/implementations/urlReaderService.ts @@ -26,10 +26,10 @@ import { loggerToWinstonLogger } from './loggerService'; export const urlReaderFactory = createServiceFactory({ service: urlReaderServiceRef, deps: { - loggerFactory: loggerServiceRef, configFactory: configServiceRef, + loggerFactory: loggerServiceRef, }, - factory: async ({ loggerFactory, configFactory }) => { + factory: async ({ configFactory, loggerFactory }) => { return async (pluginId: string) => { const logger = await loggerFactory(pluginId); return UrlReaders.default({ diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index a613e88bb1..6338b60bfb 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -15,7 +15,7 @@ */ import { BackendRegistrable, ServiceRef } from '@backstage/backend-plugin-api'; -import { ApiHolder, BackendRegisterInit } from './types'; +import { BackendRegisterInit, ApiHolder } from './types'; export class BackendInitializer { #started = false; @@ -131,15 +131,20 @@ export class BackendInitializer { const toRemove = new Set(); for (const registerInit of registerInitsToOrder) { - const unInitializedDependents = Array.from( - registerInit.provides, - ).filter(r => - registerInitsToOrder.some( - init => init !== registerInit && init.consumes.has(r), - ), - ); + const unInitializedDependents = []; + + for (const api of registerInit.provides) { + if ( + registerInitsToOrder.some( + init => init !== registerInit && init.consumes.has(api), + ) + ) { + unInitializedDependents.push(api); + } + } if (unInitializedDependents.length === 0) { + console.log(`DEBUG: pushed ${registerInit.id} to results`); orderedRegisterInits.push(registerInit); toRemove.add(registerInit); } diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index 5c2e7a9e96..c1c43a8ba8 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -20,7 +20,7 @@ import { FactoryFunc, ServiceRef, } from '@backstage/backend-plugin-api'; -import { loggerFactory } from '../services/implementations/loggerService'; +import { defaultServiceFactories } from '../services/implementations'; import { BackstageBackend } from './BackstageBackend'; export interface Backend { @@ -46,6 +46,8 @@ export type ApiHolder = { export function createBackend(options?: CreateBackendOptions): Backend { // TODO: merge with provided APIs - const defaultApis = [loggerFactory]; - return new BackstageBackend([...defaultApis, ...(options?.apis ?? [])]); + return new BackstageBackend([ + ...defaultServiceFactories, + ...(options?.apis ?? []), + ]); } diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 6d75af03a7..b5c724f764 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -35,7 +35,9 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/backend-common": "^0.14.0" + "@backstage/backend-common": "^0.14.0", + "@backstage/plugin-permission-common": "^0.6.2", + "@backstage/backend-tasks": "^0.3.2" }, "devDependencies": { "@backstage/cli": "^0.17.2-next.0" diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 8b78d2d0ee..30f2e009c5 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -36,3 +36,5 @@ export { cacheServiceRef } from './cacheServiceRef'; export { databaseServiceRef } from './databaseServiceRef'; export { discoveryServiceRef } from './discoveryServiceRef'; export { tokenManagerServiceRef } from './tokenManagerServiceRef'; +export { permissionsServiceRef } from './permissionsServiceRef'; +export { schedulerServiceRef } from './schedulerServiceRef'; diff --git a/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts new file mode 100644 index 0000000000..4355286611 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 { createServiceRef } from '../system/types'; +import { + PermissionAuthorizer, + PermissionEvaluator, +} from '@backstage/plugin-permission-common'; + +export const permissionsServiceRef = createServiceRef< + PermissionEvaluator | PermissionAuthorizer +>({ + id: 'core.permissions', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts similarity index 80% rename from packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts rename to packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts index 9dab256704..3a3abfcc10 100644 --- a/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts @@ -15,8 +15,8 @@ */ import { createServiceRef } from '../system/types'; -import { CacheManager } from '@backstage/backend-common'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; -export const cacheManagerServiceRef = createServiceRef({ - id: 'core.cacheManager', +export const schedulerServiceRef = createServiceRef({ + id: 'core.scheduler', }); diff --git a/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts new file mode 100644 index 0000000000..4355286611 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 { createServiceRef } from '../system/types'; +import { + PermissionAuthorizer, + PermissionEvaluator, +} from '@backstage/plugin-permission-common'; + +export const permissionsServiceRef = createServiceRef< + PermissionEvaluator | PermissionAuthorizer +>({ + id: 'core.permissions', +}); diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 45cf414e01..83ec4b044a 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -65,7 +65,7 @@ export const catalogPlugin = createBackendPlugin({ }, async init({ logger }) { // const builder = await CatalogBuilder.create(env); - logger.log('boppp'); + logger.info('boppp'); console.log('I HAZ', processingExtensions.processors[0].process()); }, });