Skip to content

Commit 7b17270

Browse files
authored
feat(core): support resolve env var syntax in input (#153)
1 parent 9361c3e commit 7b17270

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

apps/cli/src/command/diff.command.ts

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
filterResourceType,
1616
loadBackend,
1717
mergeKVConfigurations,
18+
recursiveReplaceEnvVars,
1819
toConfiguration,
1920
toKVConfiguration,
2021
} from './utils';
@@ -87,6 +88,12 @@ export const LoadLocalConfigurationTask = (
8788
ctx.local = toConfiguration(localKVConfiguration);
8889
},
8990
},
91+
{
92+
title: 'Resolve value variables',
93+
task: async () => {
94+
ctx.local = recursiveReplaceEnvVars(ctx.local);
95+
},
96+
},
9097
{
9198
title: 'Filter configuration resource type',
9299
enabled: () =>

apps/cli/src/command/utils.spec.ts

+84-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as ADCSDK from '@api7/adc-sdk';
22

3-
import { fillLabels, recursiveRemoveMetadataField } from './utils';
3+
import {
4+
fillLabels,
5+
recursiveRemoveMetadataField,
6+
recursiveReplaceEnvVars,
7+
} from './utils';
48

59
describe('CLI utils', () => {
610
it('should fill label selector for local resources', () => {
@@ -249,4 +253,83 @@ describe('CLI utils', () => {
249253
ssls: [{ certificates: [], snis: ['test'] }],
250254
});
251255
});
256+
257+
describe('Environment Variables', () => {
258+
it('mock config', () => {
259+
const config: ADCSDK.Configuration = {
260+
services: [
261+
{
262+
name: 'Test ${NAME}',
263+
routes: [
264+
{
265+
name: 'Test ${NAME}',
266+
uris: ['/test/${NAME}'],
267+
},
268+
],
269+
},
270+
],
271+
consumers: [
272+
{
273+
username: 'TEST_${NAME}',
274+
plugins: {
275+
'key-auth': {
276+
key: '${SECRET}',
277+
},
278+
},
279+
},
280+
],
281+
ssls: [
282+
{
283+
snis: ['test.com'],
284+
certificates: [
285+
{
286+
certificate: '${CERT}',
287+
key: '${KEY}',
288+
},
289+
],
290+
},
291+
],
292+
global_rules: {
293+
// object key contains variables will not be parsed
294+
'${GLOBAL_PLUGIN}': {
295+
key: '${SECRET}',
296+
},
297+
},
298+
plugin_metadata: {
299+
'file-logger': {
300+
log_format: {
301+
note: '${NOTE}',
302+
},
303+
},
304+
},
305+
};
306+
expect(
307+
recursiveReplaceEnvVars(config, {
308+
NAME: 'name',
309+
SECRET: 'secret',
310+
CERT: '-----',
311+
KEY: '-----',
312+
NOTE: 'note',
313+
}),
314+
).toEqual({
315+
consumers: [
316+
{ plugins: { 'key-auth': { key: 'secret' } }, username: 'TEST_name' },
317+
],
318+
global_rules: { '${GLOBAL_PLUGIN}': { key: 'secret' } },
319+
plugin_metadata: { 'file-logger': { log_format: { note: 'note' } } },
320+
services: [
321+
{
322+
name: 'Test name',
323+
routes: [{ name: 'Test name', uris: ['/test/name'] }],
324+
},
325+
],
326+
ssls: [
327+
{
328+
certificates: [{ certificate: '-----', key: '-----' }],
329+
snis: ['test.com'],
330+
},
331+
],
332+
});
333+
});
334+
});
252335
});

apps/cli/src/command/utils.ts

+26
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { BackendAPI7 } from '@api7/adc-backend-api7';
22
import { BackendAPISIX } from '@api7/adc-backend-apisix';
33
import * as ADCSDK from '@api7/adc-sdk';
44
import chalk from 'chalk';
5+
import { isObject, mapValues } from 'lodash';
56
import path from 'node:path';
67
import pluralize from 'pluralize';
78

@@ -269,6 +270,31 @@ export const recursiveRemoveMetadataField = (c: ADCSDK.Configuration) => {
269270
});
270271
};
271272

273+
export const recursiveReplaceEnvVars = (
274+
c: ADCSDK.Configuration,
275+
dataSource = process.env,
276+
): ADCSDK.Configuration => {
277+
const envVarRegex = /\$\{(\w+)\}/g;
278+
const replaceValue = (value: unknown): unknown => {
279+
if (typeof value === 'string')
280+
return value.replace(
281+
envVarRegex,
282+
(_, envVar) => dataSource?.[envVar] || '',
283+
);
284+
285+
return value;
286+
};
287+
288+
const recurseReplace = (value: unknown): unknown =>
289+
isObject(value) && !Array.isArray(value)
290+
? mapValues(value, recurseReplace)
291+
: Array.isArray(value)
292+
? value.map(recurseReplace)
293+
: replaceValue(value);
294+
295+
return mapValues(c, recurseReplace) as ADCSDK.Configuration;
296+
};
297+
272298
export const configurePluralize = () => {
273299
pluralize.addIrregularRule('route', 'routes');
274300
pluralize.addIrregularRule('service', 'services');

0 commit comments

Comments
 (0)