refactor: rename and deprecate database manager
Changes: - Deprecates SingleConnectionManager and aliases to DatabaseManager. - Simplifies database config typing in `config.d.ts`. - Drops implementation specific assert in SingleConnectionManager test. - Move database prefix reference and drop static property for default value. Signed-off-by: Minn Soe <contributions@minn.io>
This commit is contained in:
@@ -104,6 +104,12 @@ export function createServiceBuilder(_module: NodeModule): ServiceBuilderImpl;
|
||||
// @public (undocumented)
|
||||
export function createStatusCheckRouter(options: StatusCheckRouterOptions): Promise<express.Router>;
|
||||
|
||||
// @public (undocumented)
|
||||
export class DatabaseManager {
|
||||
forPlugin(pluginId: string): PluginDatabaseManager;
|
||||
static fromConfig(config: Config): DatabaseManager;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export class DockerContainerRunner implements ContainerRunner {
|
||||
constructor({ dockerClient }: {
|
||||
@@ -267,14 +273,6 @@ export type PluginCacheManager = {
|
||||
getClient: (options?: ClientOptions) => CacheClient;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export class PluginConnectionDatabaseManager {
|
||||
// (undocumented)
|
||||
static readonly DEFAULT_PREFIX = "backstage_plugin_";
|
||||
forPlugin(pluginId: string): PluginDatabaseManager;
|
||||
static fromConfig(config: Config): PluginConnectionDatabaseManager;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface PluginDatabaseManager {
|
||||
getClient(): Promise<Knex>;
|
||||
@@ -344,11 +342,8 @@ export type ServiceBuilder = {
|
||||
// @public (undocumented)
|
||||
export function setRootLogger(newLogger: winston.Logger): void;
|
||||
|
||||
// @public
|
||||
export class SingleConnectionDatabaseManager {
|
||||
forPlugin(pluginId: string): PluginDatabaseManager;
|
||||
static fromConfig(config: Config): SingleConnectionDatabaseManager;
|
||||
}
|
||||
// @public @deprecated
|
||||
export const SingleConnectionDatabaseManager: typeof DatabaseManager;
|
||||
|
||||
// @public
|
||||
export class SingleHostDiscovery implements PluginEndpointDiscovery {
|
||||
|
||||
Vendored
+29
-38
@@ -14,22 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type PluginDatabaseConfig =
|
||||
| {
|
||||
/** Database client to use for plugin. */
|
||||
client?: 'sqlite3';
|
||||
/** Database connection to use with plugin. */
|
||||
connection?: ':memory:' | string | { filename: string };
|
||||
}
|
||||
| {
|
||||
/** Database client to use for plugin. */
|
||||
client?: 'pg';
|
||||
/**
|
||||
* PostgreSQL connection string or knex configuration object for plugin.
|
||||
* @secret
|
||||
*/
|
||||
connection?: string | object;
|
||||
};
|
||||
export type PluginDatabaseConfig = {
|
||||
/** Database client to use. */
|
||||
client?: 'sqlite3' | 'pg';
|
||||
/**
|
||||
* Database connection to use.
|
||||
* @secret
|
||||
*/
|
||||
connection?: string | object;
|
||||
};
|
||||
|
||||
export interface Config {
|
||||
app: {
|
||||
@@ -70,32 +63,30 @@ export interface Config {
|
||||
};
|
||||
};
|
||||
|
||||
/** Database connection configuration, select database type using the `client` field */
|
||||
database:
|
||||
| {
|
||||
client: 'sqlite3';
|
||||
connection: ':memory:' | string | { filename: string };
|
||||
/** Optional sqlite3 database filename prefix. */
|
||||
prefix?: string;
|
||||
/** Override database config per plugin. */
|
||||
plugin?: {
|
||||
[pluginId: string]: PluginDatabaseConfig;
|
||||
};
|
||||
}
|
||||
| {
|
||||
client: 'pg';
|
||||
/** Database connection configuration, select base database type using the `client` field */
|
||||
database: {
|
||||
/** Default database client to use */
|
||||
client: 'sqlite3' | 'pg';
|
||||
/**
|
||||
* Base database connection string or Knex object
|
||||
* @secret
|
||||
*/
|
||||
connection: string | object;
|
||||
/** Database name prefix override */
|
||||
prefix?: string;
|
||||
/** Plugin specific database configuration and client override */
|
||||
plugin?: {
|
||||
[pluginId: string]: {
|
||||
/** Database client override */
|
||||
client?: 'sqlite3' | 'pg';
|
||||
/**
|
||||
* PostgreSQL connection string or knex configuration object.
|
||||
* Database connection string or Knex object override
|
||||
* @secret
|
||||
*/
|
||||
connection: string | object;
|
||||
/** Optional PostgreSQL database prefix. */
|
||||
prefix?: string;
|
||||
/** Override database config per plugin. */
|
||||
plugin?: {
|
||||
[pluginId: string]: PluginDatabaseConfig;
|
||||
};
|
||||
connection?: string | object;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/** Cache connection configuration, select cache type using the `store` field */
|
||||
cache?:
|
||||
|
||||
+25
-32
@@ -16,7 +16,7 @@
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { omit } from 'lodash';
|
||||
import { createDatabaseClient, ensureDatabaseExists } from './connection';
|
||||
import { PluginConnectionDatabaseManager } from './PluginConnection';
|
||||
import { DatabaseManager } from './DatabaseManager';
|
||||
|
||||
jest.mock('./connection', () => ({
|
||||
...jest.requireActual('./connection'),
|
||||
@@ -24,40 +24,35 @@ jest.mock('./connection', () => ({
|
||||
ensureDatabaseExists: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('PluginConnectionDatabaseManager', () => {
|
||||
describe('DatabaseManager', () => {
|
||||
// This is similar to the ts-jest `mocked` helper.
|
||||
const mocked = (f: Function) => f as jest.Mock;
|
||||
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
|
||||
describe('PluginConnectionDatabaseManager.fromConfig', () => {
|
||||
const backendConfig = {
|
||||
backend: {
|
||||
database: {
|
||||
client: 'pg',
|
||||
connection: {
|
||||
host: 'localhost',
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
database: 'foodb',
|
||||
describe('DatabaseManager.fromConfig', () => {
|
||||
it('accesses the backend.database key', () => {
|
||||
const config = new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
client: 'pg',
|
||||
connection: {
|
||||
host: 'localhost',
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
database: 'foodb',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const defaultConfig = () => new ConfigReader(backendConfig);
|
||||
});
|
||||
const getConfigSpy = jest.spyOn(config, 'getConfig');
|
||||
DatabaseManager.fromConfig(config);
|
||||
|
||||
it('accesses the backend.database key', () => {
|
||||
const getConfig = jest.fn();
|
||||
const config = defaultConfig();
|
||||
config.getConfig = getConfig;
|
||||
|
||||
PluginConnectionDatabaseManager.fromConfig(config);
|
||||
|
||||
expect(getConfig.mock.calls[0][0]).toEqual('backend.database');
|
||||
expect(getConfigSpy).toHaveBeenCalledWith('backend.database');
|
||||
});
|
||||
});
|
||||
|
||||
describe('PluginConnectionDatabaseManager.forPlugin', () => {
|
||||
describe('DatabaseManager.forPlugin', () => {
|
||||
const config = {
|
||||
backend: {
|
||||
database: {
|
||||
@@ -92,9 +87,7 @@ describe('PluginConnectionDatabaseManager', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
const manager = PluginConnectionDatabaseManager.fromConfig(
|
||||
new ConfigReader(config),
|
||||
);
|
||||
const manager = DatabaseManager.fromConfig(new ConfigReader(config));
|
||||
|
||||
it('connects to a plugin database using default config', async () => {
|
||||
const pluginId = 'pluginwithoutconfig';
|
||||
@@ -120,7 +113,7 @@ describe('PluginConnectionDatabaseManager', () => {
|
||||
});
|
||||
|
||||
it('provides a plugin db which uses components from top level connection string', async () => {
|
||||
const testManager = PluginConnectionDatabaseManager.fromConfig(
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
@@ -153,7 +146,7 @@ describe('PluginConnectionDatabaseManager', () => {
|
||||
});
|
||||
|
||||
it('uses top level sqlite database filename if plugin config is not present', async () => {
|
||||
const testManager = PluginConnectionDatabaseManager.fromConfig(
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
@@ -175,7 +168,7 @@ describe('PluginConnectionDatabaseManager', () => {
|
||||
});
|
||||
|
||||
it('provides an inmemory sqlite database if top level is also inmemory and plugin config is not present', async () => {
|
||||
const testManager = PluginConnectionDatabaseManager.fromConfig(
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
@@ -280,7 +273,7 @@ describe('PluginConnectionDatabaseManager', () => {
|
||||
});
|
||||
|
||||
it('generates a database name override when prefix is not explicitly set', async () => {
|
||||
const testManager = PluginConnectionDatabaseManager.fromConfig(
|
||||
const testManager = DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: {
|
||||
@@ -302,7 +295,7 @@ describe('PluginConnectionDatabaseManager', () => {
|
||||
|
||||
expect(overrides).toHaveProperty(
|
||||
'connection.database',
|
||||
expect.stringContaining(PluginConnectionDatabaseManager.DEFAULT_PREFIX),
|
||||
expect.stringContaining('backstage_plugin_'),
|
||||
);
|
||||
});
|
||||
|
||||
+15
-15
@@ -28,11 +28,9 @@ function pluginPath(pluginId: string): string {
|
||||
return `plugin.${pluginId}`;
|
||||
}
|
||||
|
||||
export class PluginConnectionDatabaseManager {
|
||||
static readonly DEFAULT_PREFIX = 'backstage_plugin_';
|
||||
|
||||
export class DatabaseManager {
|
||||
/**
|
||||
* Creates a PluginConnectionDatabaseManager from `backend.database` config.
|
||||
* Creates a DatabaseManager from `backend.database` config.
|
||||
*
|
||||
* The database manager allows the user to set connection and client settings on a per pluginId
|
||||
* basis by defining a database config block under `plugin.<pluginId>` in addition to top level
|
||||
@@ -41,13 +39,19 @@ export class PluginConnectionDatabaseManager {
|
||||
*
|
||||
* @param config The loaded application configuration.
|
||||
*/
|
||||
static fromConfig(config: Config): PluginConnectionDatabaseManager {
|
||||
return new PluginConnectionDatabaseManager(
|
||||
config.getConfig('backend.database'),
|
||||
static fromConfig(config: Config): DatabaseManager {
|
||||
const databaseConfig = config.getConfig('backend.database');
|
||||
|
||||
return new DatabaseManager(
|
||||
databaseConfig,
|
||||
databaseConfig.getOptionalString('prefix'),
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(private readonly config: Config) {}
|
||||
private constructor(
|
||||
private readonly config: Config,
|
||||
private readonly prefix: string = 'backstage_plugin_',
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Generates a PluginDatabaseManager for consumption by plugins.
|
||||
@@ -70,8 +74,8 @@ export class PluginConnectionDatabaseManager {
|
||||
*
|
||||
* This method provides the effective database name which is determined using global
|
||||
* and plugin specific database config. If no explicit database name is configured,
|
||||
* this method will provide a generated name which is the pluginId prefixed using
|
||||
* the value from `PluginConnectionDatabaseManager.DEFAULT_PREFIX`.
|
||||
* this method will provide a generated name which is the pluginId prefixed with
|
||||
* 'backstage_plugin_'.
|
||||
*
|
||||
* @param pluginId Lookup the database name for given plugin
|
||||
*/
|
||||
@@ -85,10 +89,6 @@ export class PluginConnectionDatabaseManager {
|
||||
? rootConnection
|
||||
: this.config.getOptionalString('connection.filename') ?? ':memory:';
|
||||
|
||||
const prefix =
|
||||
this.config.getOptionalString('prefix') ??
|
||||
PluginConnectionDatabaseManager.DEFAULT_PREFIX;
|
||||
|
||||
const isSqlite = this.config.getString('client') === 'sqlite3';
|
||||
return (
|
||||
// attempt to lookup pg and mysql database name
|
||||
@@ -98,7 +98,7 @@ export class PluginConnectionDatabaseManager {
|
||||
// if root is sqlite - attempt to use top level connection, fallback to :memory:
|
||||
(isSqlite ? rootSqliteName : null) ??
|
||||
// generate a database name using prefix and pluginId
|
||||
`${prefix}${pluginId}`
|
||||
`${this.prefix}${pluginId}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@ import { ConfigReader } from '@backstage/config';
|
||||
import { createDatabaseClient, ensureDatabaseExists } from './connection';
|
||||
import { SingleConnectionDatabaseManager } from './SingleConnection';
|
||||
|
||||
jest.mock('./connection');
|
||||
jest.mock('./connection', () => ({
|
||||
...jest.requireActual('./connection'),
|
||||
createDatabaseClient: jest.fn(),
|
||||
ensureDatabaseExists: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('SingleConnectionDatabaseManager', () => {
|
||||
const defaultConfigOptions = {
|
||||
@@ -43,9 +47,8 @@ describe('SingleConnectionDatabaseManager', () => {
|
||||
|
||||
describe('SingleConnectionDatabaseManager.fromConfig', () => {
|
||||
it('accesses the backend.database key', () => {
|
||||
const getConfig = jest.fn();
|
||||
const config = defaultConfig();
|
||||
config.getConfig = getConfig;
|
||||
const getConfig = jest.spyOn(config, 'getConfig');
|
||||
|
||||
SingleConnectionDatabaseManager.fromConfig(config);
|
||||
|
||||
@@ -64,7 +67,6 @@ describe('SingleConnectionDatabaseManager', () => {
|
||||
|
||||
const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1);
|
||||
const callArgs = mockCalls[0];
|
||||
expect(callArgs[0].get()).toEqual(defaultConfigOptions.backend.database);
|
||||
expect(callArgs[1].connection.database).toEqual(
|
||||
`backstage_plugin_${pluginId}`,
|
||||
);
|
||||
|
||||
@@ -14,69 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Knex } from 'knex';
|
||||
import { Config } from '@backstage/config';
|
||||
import { createDatabaseClient, ensureDatabaseExists } from './connection';
|
||||
import { PluginDatabaseManager } from './types';
|
||||
import { DatabaseManager } from './DatabaseManager';
|
||||
|
||||
/**
|
||||
* Implements a Database Manager which will automatically create new databases
|
||||
* for plugins when requested. All requested databases are created with the
|
||||
* credentials provided; if the database already exists no attempt to create
|
||||
* the database will be made.
|
||||
*
|
||||
* @deprecated Use `DatabaseManager` from `@backend-common` instead.
|
||||
*/
|
||||
export class SingleConnectionDatabaseManager {
|
||||
/**
|
||||
* Creates a new SingleConnectionDatabaseManager instance by reading from the `backend`
|
||||
* config section, specifically the `.database` key for discovering the management
|
||||
* database configuration.
|
||||
*
|
||||
* @param config The loaded application configuration.
|
||||
*/
|
||||
static fromConfig(config: Config): SingleConnectionDatabaseManager {
|
||||
return new SingleConnectionDatabaseManager(
|
||||
config.getConfig('backend.database'),
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(private readonly config: Config) {}
|
||||
|
||||
/**
|
||||
* Generates a PluginDatabaseManager for consumption by plugins.
|
||||
*
|
||||
* @param pluginId The plugin that the database manager should be created for. Plugin names should be unique.
|
||||
*/
|
||||
forPlugin(pluginId: string): PluginDatabaseManager {
|
||||
const _this = this;
|
||||
|
||||
return {
|
||||
getClient(): Promise<Knex> {
|
||||
return _this.getDatabase(pluginId);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private async getDatabase(pluginId: string): Promise<Knex> {
|
||||
const config = this.config;
|
||||
const overrides = SingleConnectionDatabaseManager.getDatabaseOverrides(
|
||||
pluginId,
|
||||
);
|
||||
const overrideConfig = overrides.connection as Knex.ConnectionConfig;
|
||||
await this.ensureDatabase(overrideConfig.database);
|
||||
|
||||
return createDatabaseClient(config, overrides);
|
||||
}
|
||||
|
||||
private static getDatabaseOverrides(pluginId: string): Knex.Config {
|
||||
return {
|
||||
connection: {
|
||||
database: `backstage_plugin_${pluginId}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private async ensureDatabase(database: string) {
|
||||
const config = this.config;
|
||||
await ensureDatabaseExists(config, database);
|
||||
}
|
||||
}
|
||||
export const SingleConnectionDatabaseManager = DatabaseManager;
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
export * from './connection';
|
||||
export * from './types';
|
||||
export * from './SingleConnection';
|
||||
export * from './PluginConnection';
|
||||
export * from './DatabaseManager';
|
||||
|
||||
Reference in New Issue
Block a user