config-loader,backend-common: refactor config loading to pass in path and use common util for backend
This commit is contained in:
@@ -29,7 +29,9 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/cli-common": "^0.1.1-alpha.16",
|
||||
"@backstage/config": "^0.1.1-alpha.16",
|
||||
"@backstage/config-loader": "^0.1.1-alpha.16",
|
||||
"@types/cors": "^2.8.6",
|
||||
"@types/express": "^4.17.6",
|
||||
"compression": "^1.7.4",
|
||||
|
||||
+12
-6
@@ -14,11 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { findRootPath } from './paths';
|
||||
import { findPaths } from '@backstage/cli-common';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
|
||||
describe('findRootPath', () => {
|
||||
it('should find root path', () => {
|
||||
const rootPath = findRootPath(process.cwd());
|
||||
expect(typeof rootPath).toBe('string');
|
||||
/**
|
||||
* Load configuration for a Backend
|
||||
*/
|
||||
export async function loadBackendConfig() {
|
||||
const paths = findPaths(__dirname);
|
||||
const configs = await loadConfig({
|
||||
rootPath: paths.targetRoot,
|
||||
shouldReadSecrets: true,
|
||||
});
|
||||
});
|
||||
return configs;
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './config';
|
||||
export * from './errors';
|
||||
export * from './logging';
|
||||
export * from './middleware';
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
"@backstage/backend-common": "^0.1.1-alpha.16",
|
||||
"@backstage/catalog-model": "^0.1.1-alpha.16",
|
||||
"@backstage/config": "^0.1.1-alpha.16",
|
||||
"@backstage/config-loader": "^0.1.1-alpha.16",
|
||||
"@backstage/plugin-auth-backend": "^0.1.1-alpha.16",
|
||||
"@backstage/plugin-catalog-backend": "^0.1.1-alpha.16",
|
||||
"@backstage/plugin-identity-backend": "^0.1.1-alpha.16",
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
import {
|
||||
createServiceBuilder,
|
||||
loadBackendConfig,
|
||||
getRootLogger,
|
||||
useHotMemoize,
|
||||
} from '@backstage/backend-common';
|
||||
import { ConfigReader, AppConfig } from '@backstage/config';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import knex, { PgConnectionConfig } from 'knex';
|
||||
import healthcheck from './plugins/healthcheck';
|
||||
import auth from './plugins/auth';
|
||||
@@ -85,7 +85,7 @@ function makeCreateEnv(loadedConfigs: AppConfig[]) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const configs = await loadConfig({ shouldReadSecrets: true });
|
||||
const configs = await loadBackendConfig();
|
||||
const configReader = ConfigReader.fromConfigs(configs);
|
||||
const createEnv = makeCreateEnv(configs);
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import { Command } from 'commander';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { buildBundle } from '../../lib/bundler';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const appConfigs = await loadConfig();
|
||||
const appConfigs = await loadConfig({ rootPath: paths.targetRoot });
|
||||
await buildBundle({
|
||||
entry: 'src/index',
|
||||
statsJsonEnabled: cmd.stats,
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import { Command } from 'commander';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { serveBundle } from '../../lib/bundler';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const appConfigs = await loadConfig();
|
||||
const appConfigs = await loadConfig({ rootPath: paths.targetRoot });
|
||||
const waitForExit = await serveBundle({
|
||||
entry: 'src/index',
|
||||
checksEnabled: cmd.check,
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { Command } from 'commander';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { serveBackend } from '../../lib/bundler/backend';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const appConfigs = await loadConfig();
|
||||
const appConfigs = await loadConfig({ rootPath: paths.targetRoot });
|
||||
const waitForExit = await serveBackend({
|
||||
entry: 'src/index',
|
||||
checksEnabled: cmd.check,
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import { Command } from 'commander';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { buildBundle } from '../../lib/bundler';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const appConfigs = await loadConfig();
|
||||
const appConfigs = await loadConfig({ rootPath: paths.targetRoot });
|
||||
await buildBundle({
|
||||
entry: 'dev/index',
|
||||
statsJsonEnabled: cmd.stats,
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
import { Command } from 'commander';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { paths } from '../../lib/paths';
|
||||
import { serveBundle } from '../../lib/bundler';
|
||||
|
||||
export default async (cmd: Command) => {
|
||||
const appConfigs = await loadConfig();
|
||||
const appConfigs = await loadConfig({ rootPath: paths.targetRoot });
|
||||
const waitForExit = await serveBundle({
|
||||
entry: 'dev/index',
|
||||
checksEnabled: cmd.check,
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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 fs from 'fs-extra';
|
||||
import { dirname, resolve as resolvePath } from 'path';
|
||||
|
||||
/**
|
||||
* Looks for a package.json that has name: "root" to identify the root of the monorepo
|
||||
*
|
||||
* This is a copy of the same function in the CLI
|
||||
*/
|
||||
export function findRootPath(topPath: string): string {
|
||||
let path = topPath;
|
||||
|
||||
// Some sanity check to avoid infinite loop
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
const packagePath = resolvePath(path, 'package.json');
|
||||
const exists = fs.pathExistsSync(packagePath);
|
||||
if (exists) {
|
||||
try {
|
||||
const data = fs.readJsonSync(packagePath);
|
||||
if (data.name === 'root' || data.name.includes('backstage-e2e')) {
|
||||
return path;
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to parse package.json file while searching for root, ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const newPath = dirname(path);
|
||||
if (newPath === path) {
|
||||
throw new Error(
|
||||
`No package.json with name "root" found as a parent of ${topPath}`,
|
||||
);
|
||||
}
|
||||
path = newPath;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Iteration limit reached when searching for root package.json at ${topPath}`,
|
||||
);
|
||||
}
|
||||
@@ -14,13 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import { findRootPath } from './paths';
|
||||
|
||||
type ResolveOptions = {
|
||||
// Same as configPath in LoadConfigOptions
|
||||
configPath?: string;
|
||||
// Root path for search for app-config.yaml
|
||||
rootPath: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -31,13 +29,7 @@ export async function resolveStaticConfig(
|
||||
): Promise<string[]> {
|
||||
// TODO: We'll want this to be a bit more elaborate, probably adding configs for
|
||||
// specific env, and maybe local config for plugins.
|
||||
let { configPath } = options;
|
||||
if (!configPath) {
|
||||
configPath = resolvePath(
|
||||
findRootPath(fs.realpathSync(process.cwd())),
|
||||
'app-config.yaml',
|
||||
);
|
||||
}
|
||||
const configPath = resolvePath(options.rootPath, 'app-config.yaml');
|
||||
|
||||
return [configPath];
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ import {
|
||||
} from './lib';
|
||||
|
||||
export type LoadConfigOptions = {
|
||||
// Config path, defaults to app-config.yaml in project root
|
||||
configPath?: string;
|
||||
// Root path for search for app-config.yaml
|
||||
rootPath: string;
|
||||
|
||||
// Whether to read secrets or omit them, defaults to false.
|
||||
shouldReadSecrets?: boolean;
|
||||
@@ -59,7 +59,7 @@ class Context {
|
||||
}
|
||||
|
||||
export async function loadConfig(
|
||||
options: LoadConfigOptions = {},
|
||||
options: LoadConfigOptions,
|
||||
): Promise<AppConfig[]> {
|
||||
const configs = [];
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^{{version}}",
|
||||
"@backstage/catalog-model": "^{{version}}",
|
||||
"@backstage/config": "^0.1.1-alpha.13",
|
||||
"@backstage/config-loader": "^0.1.1-alpha.13",
|
||||
"@backstage/config": "^{{version}}",
|
||||
"@backstage/plugin-auth-backend": "^{{version}}",
|
||||
"@backstage/plugin-catalog-backend": "^{{version}}",
|
||||
"@backstage/plugin-identity-backend": "^{{version}}",
|
||||
@@ -42,7 +41,7 @@
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.15",
|
||||
"@backstage/cli": "^{{version}}",
|
||||
"@types/dockerode": "^2.5.32",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-serve-static-core": "^4.17.5",
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
import {
|
||||
createServiceBuilder,
|
||||
loadBackendConfig,
|
||||
getRootLogger,
|
||||
useHotMemoize,
|
||||
} from '@backstage/backend-common';
|
||||
import { ConfigReader, AppConfig } from '@backstage/config';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
{{#if dbTypePG}}
|
||||
import knex, { PgConnectionConfig } from 'knex';
|
||||
{{/if}}
|
||||
@@ -78,7 +78,7 @@ function makeCreateEnv(loadedConfigs: AppConfig[]) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const configs = await loadConfig();
|
||||
const configs = await loadBackendConfig();
|
||||
const configReader = ConfigReader.fromConfigs(configs);
|
||||
const createEnv = makeCreateEnv(configs);
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.1.1-alpha.16",
|
||||
"@backstage/config": "^0.1.1-alpha.16",
|
||||
"@backstage/config-loader": "^0.1.1-alpha.16",
|
||||
"@types/express": "^4.17.6",
|
||||
"body-parser": "^1.19.0",
|
||||
"compression": "^1.7.4",
|
||||
|
||||
@@ -18,9 +18,12 @@ import Knex from 'knex';
|
||||
import { Server } from 'http';
|
||||
import { Logger } from 'winston';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { createRouter } from './router';
|
||||
import { createServiceBuilder, useHotMemoize } from '@backstage/backend-common';
|
||||
import {
|
||||
createServiceBuilder,
|
||||
useHotMemoize,
|
||||
loadBackendConfig,
|
||||
} from '@backstage/backend-common';
|
||||
|
||||
export interface ServerOptions {
|
||||
logger: Logger;
|
||||
@@ -30,7 +33,7 @@ export async function startStandaloneServer(
|
||||
options: ServerOptions,
|
||||
): Promise<Server> {
|
||||
const logger = options.logger.child({ service: 'auth-backend' });
|
||||
const config = ConfigReader.fromConfigs(await loadConfig());
|
||||
const config = ConfigReader.fromConfigs(await loadBackendConfig());
|
||||
|
||||
const database = useHotMemoize(module, () => {
|
||||
const knex = Knex({
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.1.1-alpha.16",
|
||||
"@backstage/config": "^0.1.1-alpha.16",
|
||||
"@backstage/config-loader": "^0.1.1-alpha.16",
|
||||
"@types/express": "^4.17.6",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^3.0.3",
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
import { createRouter } from './router';
|
||||
import winston from 'winston';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
import { loadBackendConfig } from '@backstage/backend-common';
|
||||
|
||||
describe('createRouter', () => {
|
||||
it('works', async () => {
|
||||
const logger = winston.createLogger();
|
||||
const config = ConfigReader.fromConfigs(await loadConfig());
|
||||
const config = ConfigReader.fromConfigs(await loadBackendConfig());
|
||||
const router = await createRouter({
|
||||
config,
|
||||
logger,
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createServiceBuilder } from '@backstage/backend-common';
|
||||
import {
|
||||
createServiceBuilder,
|
||||
loadBackendConfig,
|
||||
} from '@backstage/backend-common';
|
||||
import { Server } from 'http';
|
||||
import { Logger } from 'winston';
|
||||
import { createRouter } from './router';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { loadConfig } from '@backstage/config-loader';
|
||||
|
||||
export interface ServerOptions {
|
||||
port: number;
|
||||
@@ -34,7 +36,7 @@ export async function startStandaloneServer(
|
||||
|
||||
logger.debug('Creating application...');
|
||||
|
||||
const config = ConfigReader.fromConfigs(await loadConfig());
|
||||
const config = ConfigReader.fromConfigs(await loadBackendConfig());
|
||||
const router = await createRouter({
|
||||
config,
|
||||
logger,
|
||||
|
||||
Reference in New Issue
Block a user