config-loader: Change loadConfig return type to object

Signed-off-by: Johan Haals <johan.haals@gmail.com>
This commit is contained in:
Johan Haals
2021-11-17 11:26:35 +01:00
parent 7439368ce5
commit 1e99c73c75
8 changed files with 172 additions and 113 deletions
+14
View File
@@ -0,0 +1,14 @@
---
'@backstage/config-loader': minor
---
Update `loadConfig` to return `LoadConfigResult` instead of an array of `AppConfig`.
This function is primarily used internally by other config loaders like `loadBackendConfig` which means no changes are required for most users.
If you use `loadConfig` directly you will need to update your usage from:
```diff
- const appConfigs = await loadConfig(options)
+ const { appConfigs } = await loadConfig(options)
```
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/backend-common': patch
'@backstage/cli': patch
---
Update internal usage of `configLoader.loadConfig` that now returns an object instead of an array of configs.
+7 -5
View File
@@ -200,7 +200,7 @@ export async function loadBackendConfig(options: {
});
const config = new ObservableConfigProxy(options.logger);
const configs = await loadConfig({
const { appConfigs } = await loadConfig({
configRoot: paths.targetRoot,
configPaths: [],
configTargets: configTargets,
@@ -227,14 +227,16 @@ export async function loadBackendConfig(options: {
});
options.logger.info(
`Loaded config from ${configs.map(c => c.context).join(', ')}`,
`Loaded config from ${appConfigs.map(c => c.context).join(', ')}`,
);
config.setConfig(ConfigReader.fromConfigs(configs));
config.setConfig(ConfigReader.fromConfigs(appConfigs));
// Subscribe to config changes and update the redaction list for logging
updateRedactionList(schema, configs, options.logger);
config.subscribe(() => updateRedactionList(schema, configs, options.logger));
updateRedactionList(schema, appConfigs, options.logger);
config.subscribe(() =>
updateRedactionList(schema, appConfigs, options.logger),
);
return config;
}
+1 -1
View File
@@ -54,7 +54,7 @@ export async function loadCliConfig(options: Options) {
packagePaths: [paths.resolveTargetRoot('package.json')],
});
const appConfigs = await loadConfig({
const { appConfigs } = await loadConfig({
experimentalEnvFunc: options.mockEnv
? async name => process.env[name] || 'x'
: undefined,
+8 -1
View File
@@ -38,7 +38,9 @@ export type ConfigTarget =
export type ConfigVisibility = 'frontend' | 'backend' | 'secret';
// @public
export function loadConfig(options: LoadConfigOptions): Promise<AppConfig[]>;
export function loadConfig(
options: LoadConfigOptions,
): Promise<LoadConfigResult>;
// @public
export type LoadConfigOptions = {
@@ -66,6 +68,11 @@ export type LoadConfigOptionsWatch = {
stopSignal?: Promise<void>;
};
// @public
export type LoadConfigResult = {
appConfigs: AppConfig[];
};
// @public
export function loadConfigSchema(
options: LoadConfigSchemaOptions,
+1
View File
@@ -34,4 +34,5 @@ export type {
LoadConfigOptions,
LoadConfigOptionsWatch,
LoadConfigOptionsRemote,
LoadConfigResult,
} from './loader';
+118 -102
View File
@@ -122,18 +122,20 @@ describe('loadConfig', () => {
configTargets: [],
env: 'production',
}),
).resolves.toEqual([
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
).resolves.toEqual({
appConfigs: [
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
]);
],
});
});
it('load config from remote path', async () => {
@@ -151,18 +153,20 @@ describe('loadConfig', () => {
reloadIntervalSeconds: 30,
},
}),
).resolves.toEqual([
{
context: configUrl,
data: {
app: {
title: 'Remote Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
).resolves.toEqual({
appConfigs: [
{
context: configUrl,
data: {
app: {
title: 'Remote Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
]);
],
});
});
it('loads config with secrets from two different files', async () => {
@@ -173,28 +177,30 @@ describe('loadConfig', () => {
configTargets: [{ path: '/root/app-config.yaml' }],
env: 'production',
}),
).resolves.toEqual([
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
).resolves.toEqual({
appConfigs: [
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
{
context: 'app-config2.yaml',
data: {
app: {
title: 'Example App 2',
sessionKey: 'abc123',
escaped: '${Escaped}',
{
context: 'app-config2.yaml',
data: {
app: {
title: 'Example App 2',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
]);
],
});
});
it('loads config with secrets from single file', async () => {
@@ -205,18 +211,20 @@ describe('loadConfig', () => {
configTargets: [{ path: '/root/app-config.yaml' }],
env: 'production',
}),
).resolves.toEqual([
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
).resolves.toEqual({
appConfigs: [
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
]);
],
});
});
it('loads development config with secrets', async () => {
@@ -230,34 +238,36 @@ describe('loadConfig', () => {
],
env: 'development',
}),
).resolves.toEqual([
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
{
context: 'app-config.development.yaml',
data: {
app: {
sessionKey: 'development-key',
},
backend: {
foo: {
bar: 'token is-secret',
).resolves.toEqual({
appConfigs: [
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
other: {
secret: 'abc123',
},
{
context: 'app-config.development.yaml',
data: {
app: {
sessionKey: 'development-key',
},
backend: {
foo: {
bar: 'token is-secret',
},
},
other: {
secret: 'abc123',
},
},
},
},
]);
],
});
});
it('loads deep substituted config', async () => {
@@ -268,19 +278,21 @@ describe('loadConfig', () => {
configTargets: [{ path: '/root/app-config.substitute.yaml' }],
env: 'development',
}),
).resolves.toEqual([
{
context: 'app-config.substitute.yaml',
data: {
app: {
someConfig: {
secret: '123abc',
).resolves.toEqual({
appConfigs: [
{
context: 'app-config.substitute.yaml',
data: {
app: {
someConfig: {
secret: '123abc',
},
noSubstitute: 'notSubstituted',
},
noSubstitute: 'notSubstituted',
},
},
},
]);
],
});
});
it('watches config files', async () => {
@@ -297,18 +309,20 @@ describe('loadConfig', () => {
stopSignal: stopSignal.promise,
},
}),
).resolves.toEqual([
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
).resolves.toEqual({
appConfigs: [
{
context: 'app-config.yaml',
data: {
app: {
title: 'Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
]);
],
});
await fs.writeJson('/root/app-config.yaml', {
app: {
@@ -349,18 +363,20 @@ describe('loadConfig', () => {
reloadIntervalSeconds: 1,
},
}),
).resolves.toEqual([
{
context: configUrl,
data: {
app: {
title: 'Remote Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
).resolves.toEqual({
appConfigs: [
{
context: configUrl,
data: {
app: {
title: 'Remote Example App',
sessionKey: 'abc123',
escaped: '${Escaped}',
},
},
},
},
]);
],
});
server.use(reloadHandler);
+17 -4
View File
@@ -88,6 +88,17 @@ export type LoadConfigOptions = {
watch?: LoadConfigOptionsWatch;
};
/**
* Results of loading configuration files.
* @public
*/
export type LoadConfigResult = {
/**
* Array of all loaded configs.
*/
appConfigs: AppConfig[];
};
/**
* Load configuration data.
*
@@ -95,7 +106,7 @@ export type LoadConfigOptions = {
*/
export async function loadConfig(
options: LoadConfigOptions,
): Promise<AppConfig[]> {
): Promise<LoadConfigResult> {
const { configRoot, experimentalEnvFunc: envFunc, watch, remote } = options;
const configPaths: string[] = options.configTargets
@@ -290,7 +301,9 @@ export async function loadConfig(
watchRemoteConfig(watch, remote);
}
return remote
? [...remoteConfigs, ...fileConfigs, ...envConfigs]
: [...fileConfigs, ...envConfigs];
return {
appConfigs: remote
? [...remoteConfigs, ...fileConfigs, ...envConfigs]
: [...fileConfigs, ...envConfigs],
};
}