Expose types to handle Database management
This implements several types to own and manage databases on a database server. The current SimpleDatabase* classes preserve the present behaviour; future implementations can segregate databases to be owned by different roles.
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 Knex from 'knex';
|
||||
import { Config } from '@backstage/config';
|
||||
import { createDatabaseClient, ensureDatabaseExists } from './connection';
|
||||
import {
|
||||
DatabaseConfiguration,
|
||||
PluginDatabaseFactory,
|
||||
PluginDatabaseManager,
|
||||
} from './types';
|
||||
|
||||
export class SingleDatabaseConfiguration implements DatabaseConfiguration {
|
||||
private readonly config: Config;
|
||||
|
||||
constructor(config: Config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
getDatabaseConfig(_pluginId: string): Config {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
getAdminConfig(): Config {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
|
||||
export class SingleDatabaseManager implements PluginDatabaseManager {
|
||||
private readonly config: DatabaseConfiguration;
|
||||
|
||||
constructor(config: DatabaseConfiguration) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
getDatabaseFactory(pluginId: string): PluginDatabaseFactory {
|
||||
// eslint-disable-next-line no-use-before-define
|
||||
return new SinglePluginDatabaseFactory(this, pluginId);
|
||||
}
|
||||
|
||||
async getDatabase(pluginId: string, suffix?: string): Promise<Knex> {
|
||||
const config = this.config.getDatabaseConfig(pluginId);
|
||||
const overrides = SingleDatabaseManager.getDatabaseOverrides(
|
||||
pluginId,
|
||||
suffix,
|
||||
);
|
||||
const overrideConfig = overrides.connection as Knex.ConnectionConfig;
|
||||
await this.ensureDatabase(overrideConfig.database);
|
||||
|
||||
return createDatabaseClient(config, overrides);
|
||||
}
|
||||
|
||||
private static getDatabaseOverrides(
|
||||
pluginId: string,
|
||||
suffix?: string,
|
||||
): Knex.Config {
|
||||
const dbSuffix = suffix ? `_${suffix}` : '';
|
||||
return {
|
||||
connection: {
|
||||
database: `backstage_plugin_${pluginId}${dbSuffix}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private async ensureDatabase(database: string) {
|
||||
const config = this.config.getAdminConfig();
|
||||
await ensureDatabaseExists(config, database);
|
||||
}
|
||||
}
|
||||
|
||||
export class SinglePluginDatabaseFactory implements PluginDatabaseFactory {
|
||||
private manager: SingleDatabaseManager;
|
||||
private readonly pluginId: string;
|
||||
|
||||
constructor(manager: SingleDatabaseManager, pluginId: string) {
|
||||
this.manager = manager;
|
||||
this.pluginId = pluginId;
|
||||
}
|
||||
|
||||
getDatabase(database?: string): Promise<Knex> {
|
||||
return this.manager.getDatabase(this.pluginId, database);
|
||||
}
|
||||
}
|
||||
@@ -15,3 +15,5 @@
|
||||
*/
|
||||
|
||||
export * from './connection';
|
||||
export * from './types';
|
||||
export * from './SingleDatabase';
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import knex, { PgConnectionConfig } from 'knex';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { Config } from '@backstage/config';
|
||||
import { mergeDatabaseConfig } from './config';
|
||||
|
||||
@@ -44,7 +45,7 @@ export function buildPgDatabaseConfig(
|
||||
overrides?: knex.Config,
|
||||
) {
|
||||
return mergeDatabaseConfig(
|
||||
dbConfig.get(),
|
||||
cloneDeep(dbConfig.get()),
|
||||
{
|
||||
connection: getPgConnectionConfig(dbConfig, !!overrides),
|
||||
useNullAsDefault: true,
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 knex from 'knex';
|
||||
import { Config } from '@backstage/config';
|
||||
|
||||
/**
|
||||
* DatabaseConfiguration exposes the Application configuration to PluginDatabaseManager instances.
|
||||
*/
|
||||
export interface DatabaseConfiguration {
|
||||
/**
|
||||
* Returns the database configuration for the given Plugin.
|
||||
*/
|
||||
getDatabaseConfig(pluginId: string): Config;
|
||||
|
||||
/**
|
||||
* Returns the database configuration for administrating the database server.
|
||||
*/
|
||||
getAdminConfig(): Config;
|
||||
}
|
||||
|
||||
/**
|
||||
* The PluginDatabaseManager produces PluginDatabaseFactory objects for plugins to consume and store their data.
|
||||
*/
|
||||
export type PluginDatabaseManager = {
|
||||
/**
|
||||
* getDatabaseFactory returns the database factory object for plugins to obtain database connections.
|
||||
*/
|
||||
getDatabaseFactory(pluginId: string): PluginDatabaseFactory;
|
||||
};
|
||||
|
||||
/**
|
||||
* The PluginDatabaseFactory is used to provide a mechanism for backend plugins to obtain database connections for
|
||||
* itself.
|
||||
*
|
||||
* The purpose of this factory is to allow plugins to get isolated data stores so that plugins are discouraged from database integration.
|
||||
*/
|
||||
export type PluginDatabaseFactory = {
|
||||
/**
|
||||
* Returns a database connection. Plugins can omit the `database` parameter to get the default plugin database, or
|
||||
* provide an identifier that will be used to identify a separate database from the default.
|
||||
*
|
||||
* Plugins completely own and manage the state of the database (including schema/migrations/data.)
|
||||
*/
|
||||
getDatabase(database?: String): Promise<knex>;
|
||||
};
|
||||
Reference in New Issue
Block a user