Support external config schemas in the backend.

Signed-off-by: David Festal <dfestal@redhat.com>
This commit is contained in:
David Festal
2023-11-29 16:37:36 +01:00
parent 39812987d1
commit d7adbbf455
27 changed files with 566 additions and 8 deletions
+2
View File
@@ -4,6 +4,7 @@
```ts
import { Config } from '@backstage/config';
import { ConfigSchemaPackageEntry } from '@backstage/config-loader';
import express from 'express';
import { Logger } from 'winston';
import { PluginDatabaseManager } from '@backstage/backend-common';
@@ -13,6 +14,7 @@ export function createRouter(options: RouterOptions): Promise<express.Router>;
// @public (undocumented)
export interface RouterOptions {
additionalSchemas?: ConfigSchemaPackageEntry[];
appPackageName: string;
// (undocumented)
config: Config;
+6 -1
View File
@@ -20,6 +20,7 @@ import { Logger } from 'winston';
import { AppConfig, Config } from '@backstage/config';
import { JsonObject } from '@backstage/types';
import { loadConfigSchema, readEnvConfig } from '@backstage/config-loader';
import { ConfigSchemaPackageEntry } from '@backstage/config-loader';
type InjectOptions = {
appConfigs: AppConfig[];
@@ -74,6 +75,7 @@ type ReadOptions = {
env: { [name: string]: string | undefined };
appDistDir: string;
config: Config;
additionalSchemas?: ConfigSchemaPackageEntry[];
};
/**
@@ -90,7 +92,10 @@ export async function readConfigs(options: ReadOptions): Promise<AppConfig[]> {
const serializedSchema = await fs.readJson(schemaPath);
try {
const schema = await loadConfigSchema({ serialized: serializedSchema });
const schema = await loadConfigSchema({
serialized: serializedSchema,
additionalSchemas: options.additionalSchemas,
});
const frontendConfigs = await schema.process(
[{ data: config.get() as JsonObject, context: 'app' }],
+6 -1
View File
@@ -19,6 +19,7 @@ import {
coreServices,
createBackendPlugin,
} from '@backstage/backend-plugin-api';
import { schemaDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha';
import { createRouter } from './router';
import { loggerToWinstonLogger } from '@backstage/backend-common';
import { staticFallbackHandlerExtensionPoint } from '@backstage/plugin-app-node';
@@ -49,8 +50,9 @@ export const appPlugin = createBackendPlugin({
config: coreServices.rootConfig,
database: coreServices.database,
httpRouter: coreServices.httpRouter,
schemaDiscovery: schemaDiscoveryServiceRef,
},
async init({ logger, config, database, httpRouter }) {
async init({ logger, config, database, httpRouter, schemaDiscovery }) {
const appPackageName =
config.getOptionalString('app.packageName') ?? 'app';
const winstonLogger = loggerToWinstonLogger(logger);
@@ -61,6 +63,9 @@ export const appPlugin = createBackendPlugin({
database,
appPackageName,
staticFallbackHandler,
additionalSchemas: (
await schemaDiscovery?.getAdditionalSchemas()
)?.schemas,
});
httpRouter.use(router);
},
+13
View File
@@ -37,6 +37,7 @@ import {
CACHE_CONTROL_NO_CACHE,
CACHE_CONTROL_REVALIDATE_CACHE,
} from '../lib/headers';
import { ConfigSchemaPackageEntry } from '@backstage/config-loader';
// express uses mime v1 while we only have types for mime v2
type Mime = { lookup(arg0: string): string };
@@ -85,6 +86,17 @@ export interface RouterOptions {
* This also disables configuration injection though `APP_CONFIG_` environment variables.
*/
disableConfigInjection?: boolean;
/**
*
* Provides a list of additional config schemas, in addition to the serialized schemas
* generated during the application build.
* This is useful when additional plugins are dynamically loaded in the application at start,
* which were not part of the application build. This option allows feeding the corresponding
* JSON schemas.
*
*/
additionalSchemas?: ConfigSchemaPackageEntry[];
}
/** @public */
@@ -121,6 +133,7 @@ export async function createRouter(
config,
appDistDir,
env: process.env,
additionalSchemas: options.additionalSchemas,
});
injectedConfigPath = await injectConfig({ appConfigs, logger, staticDir });