Run substitute prior to include processing
Signed-off-by: JP Dhabolt john.p.dhabolt@gmail.com Signed-off-by: JP Dhabolt <jdhabolt@agero.com>
This commit is contained in:
@@ -14,11 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { JsonValue } from '@backstage/config';
|
||||
import * as os from 'os';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import { createIncludeTransform } from './include';
|
||||
|
||||
const root = os.platform() === 'win32' ? 'C:\\' : '/';
|
||||
const substituteMe = '${MY_SUBSTITUTION}';
|
||||
const mySubstitution = 'fooSubstitution';
|
||||
|
||||
const env = jest.fn(async (name: string) => {
|
||||
return ({
|
||||
@@ -26,6 +29,24 @@ const env = jest.fn(async (name: string) => {
|
||||
} as { [name: string]: string })[name];
|
||||
});
|
||||
|
||||
const substitute = jest.fn(
|
||||
async (
|
||||
value: JsonValue,
|
||||
): Promise<{ applied: boolean; value?: JsonValue }> => {
|
||||
if (typeof value !== 'string') {
|
||||
return { applied: false };
|
||||
}
|
||||
if (value.includes(substituteMe)) {
|
||||
return {
|
||||
applied: true,
|
||||
value: value.replace(substituteMe, mySubstitution),
|
||||
};
|
||||
}
|
||||
|
||||
return { applied: false };
|
||||
},
|
||||
);
|
||||
|
||||
const readFile = jest.fn(async (path: string) => {
|
||||
const content = ({
|
||||
[resolvePath(root, 'my-secret')]: 'secret',
|
||||
@@ -33,6 +54,7 @@ const readFile = jest.fn(async (path: string) => {
|
||||
[resolvePath(root, 'my-data.yaml')]: 'some:\n yaml:\n key: 7',
|
||||
[resolvePath(root, 'my-data.yml')]: 'different: { key: hello }',
|
||||
[resolvePath(root, 'invalid.yaml')]: 'foo: [}',
|
||||
[resolvePath(root, `${mySubstitution}/my-data.json`)]: '{"foo":"bar"}',
|
||||
} as { [key: string]: string })[path];
|
||||
|
||||
if (!content) {
|
||||
@@ -41,7 +63,7 @@ const readFile = jest.fn(async (path: string) => {
|
||||
return content;
|
||||
});
|
||||
|
||||
const includeTransform = createIncludeTransform(env, readFile);
|
||||
const includeTransform = createIncludeTransform(env, readFile, substitute);
|
||||
|
||||
describe('includeTransform', () => {
|
||||
it('should not transform unknown values', async () => {
|
||||
@@ -136,4 +158,14 @@ describe('includeTransform', () => {
|
||||
'failed to parse included file invalid.yaml, YAMLSyntaxError: Flow sequence contains an unexpected }',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call substitute prior to handling includes directive', async () => {
|
||||
await expect(
|
||||
includeTransform({ $include: `${substituteMe}/my-data.json` }, root),
|
||||
).resolves.toEqual({
|
||||
applied: true,
|
||||
value: { foo: 'bar' },
|
||||
newBaseDir: `/${mySubstitution}`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,6 +35,7 @@ const includeFileParser: {
|
||||
export function createIncludeTransform(
|
||||
env: EnvFunc,
|
||||
readFile: ReadFileFunc,
|
||||
substitute: TransformFunc,
|
||||
): TransformFunc {
|
||||
return async (input: JsonValue, baseDir: string) => {
|
||||
if (!isObject(input)) {
|
||||
@@ -53,7 +54,11 @@ export function createIncludeTransform(
|
||||
return { applied: false };
|
||||
}
|
||||
|
||||
const includeValue = input[includeKey];
|
||||
const rawIncludedValue = input[includeKey];
|
||||
const substituteResults = await substitute(rawIncludedValue!, baseDir);
|
||||
const includeValue = substituteResults.applied
|
||||
? substituteResults.value
|
||||
: rawIncludedValue;
|
||||
if (typeof includeValue !== 'string') {
|
||||
throw new Error(`${includeKey} include value is not a string`);
|
||||
}
|
||||
|
||||
@@ -23,13 +23,8 @@ export type ReadFileFunc = (path: string) => Promise<string>;
|
||||
export type TransformFunc = (
|
||||
value: JsonValue,
|
||||
baseDir: string,
|
||||
) => Promise<
|
||||
| {
|
||||
applied: false;
|
||||
}
|
||||
| {
|
||||
applied: true;
|
||||
value: JsonValue | undefined;
|
||||
newBaseDir?: string | undefined;
|
||||
}
|
||||
>;
|
||||
) => Promise<{
|
||||
applied: boolean;
|
||||
value?: JsonValue;
|
||||
newBaseDir?: string;
|
||||
}>;
|
||||
|
||||
@@ -75,9 +75,10 @@ export async function loadConfig(
|
||||
fs.readFile(resolvePath(dir, path), 'utf8');
|
||||
|
||||
const input = yaml.parse(await readFile(configPath));
|
||||
const substitutionTransform = createSubstitutionTransform(env);
|
||||
const data = await applyConfigTransforms(dir, input, [
|
||||
createIncludeTransform(env, readFile),
|
||||
createSubstitutionTransform(env),
|
||||
createIncludeTransform(env, readFile, substitutionTransform),
|
||||
substitutionTransform,
|
||||
]);
|
||||
|
||||
configs.push({ data, context: basename(configPath) });
|
||||
|
||||
Reference in New Issue
Block a user