Skip to content

Commit 0cb5e83

Browse files
authored
Merge pull request #135 from devsapp/fix-nasConfig
Fix nas config and logConfig
2 parents 68e5937 + 35e097b commit 0cb5e83

File tree

5 files changed

+163
-16
lines changed

5 files changed

+163
-16
lines changed

__tests__/e2e/nodejs/s_oss_config_auto.yaml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,39 @@ resources:
3838
handler: index.handler
3939
memorySize: 128
4040
timeout: 60
41-
ossMountConfig: auto|mountDir=/mnt/test-oss-bucket|bucketPath=/|rules=[{"allowedOrigin":"*","allowedMethod":["GET","POST","PUT","DELETE","HEAD"],"allowedHeader":"*","exposeHeader":"Content-Length","maxAgeSeconds":30}]
41+
ossMountConfig: auto|mountDir=/mnt/test-oss-bucket|bucketPath=/|rules=[{"allowedOrigin":"*","allowedMethod":["GET","POST","PUT","DELETE","HEAD"],"allowedHeader":"*","exposeHeader":"Content-Length","maxAgeSeconds":30}]
42+
43+
fcDemo3: # 业务名称/模块名称
44+
component: ${env('fc_component_version', path('../../../'))}
45+
actions:
46+
pre-deploy:
47+
- run: npm install
48+
path: ./test-auto-code
49+
props: # 组件的属性值
50+
region: ${vars.region}
51+
functionName: fc3-event-${env('fc_component_function_name', 'nodejs18')}-nasConfig
52+
role: acs:ram::${config('AccountID')}:role/aliyunaliyunfcdefaultrole
53+
runtime: ${env('fc_component_runtime', 'nodejs18')}
54+
code: ./test-auto-code
55+
handler: index.handler
56+
memorySize: 128
57+
timeout: 60
58+
nasConfig: auto|mountDir=/mnt/fcDir|nasDir=/nasDir
59+
vpcConfig: auto
60+
61+
fcDemo4: # 业务名称/模块名称
62+
component: ${env('fc_component_version', path('../../../'))}
63+
actions:
64+
pre-deploy:
65+
- run: npm install
66+
path: ./test-auto-code
67+
props: # 组件的属性值
68+
region: ${vars.region}
69+
functionName: fc3-event-${env('fc_component_function_name', 'nodejs18')}-logConfig
70+
role: acs:ram::${config('AccountID')}:role/aliyunaliyunfcdefaultrole
71+
runtime: ${env('fc_component_runtime', 'nodejs18')}
72+
code: ./test-auto-code
73+
handler: index.handler
74+
memorySize: 128
75+
timeout: 60
76+
logConfig: auto|enableRequestMetrics=false|enableInstanceMetrics=false

publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Type: Component
33
Name: fc3
44
Provider:
55
- 阿里云
6-
Version: 0.1.13
6+
Version: 0.1.14
77
Description: 阿里云函数计算全生命周期管理
88
HomePage: https://github.com/devsapp/fc3
99
Organization: 阿里云函数计算(FC)

src/subCommands/deploy/impl/function.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import FC, { GetApiType } from '../../../resources/fc';
1818
import VPC_NAS from '../../../resources/vpc-nas';
1919
import Base from './base';
2020
import { ICredentials } from '@serverless-devs/component-interface';
21-
import { calculateCRC64, getFileSize } from '../../../utils';
21+
import { calculateCRC64, getFileSize, parseAutoConfig, checkFcDir } from '../../../utils';
2222
import OSS from '../../../resources/oss';
2323
import { setNodeModulesBinPermissions } from '../../../resources/fc/impl/utils';
2424

@@ -349,22 +349,30 @@ export default class Service extends Base {
349349
if (slsAuto) {
350350
const sls = new Sls(region, credential as ICredentials);
351351
const { project, logstore } = await sls.deploy();
352+
const logAutoConfig = parseAutoConfig(this.local.logConfig as string);
353+
const logParams = logAutoConfig?.params || {};
354+
const customFields: Record<string, any> = { ...logParams };
355+
const getConfigValue = (field: string, defaultValue: any) => {
356+
return field in customFields ? customFields[field] : defaultValue;
357+
};
352358
logger.write(
353359
yellow(`Created log resource succeeded, please replace logConfig: auto in yaml with:
354360
logConfig:
355-
enableInstanceMetrics: true
356-
enableRequestMetrics: true
357-
logBeginRule: DefaultRegex
361+
enableInstanceMetrics: ${getConfigValue('enableInstanceMetrics', true)}
362+
enableRequestMetrics: ${getConfigValue('enableRequestMetrics', true)}
363+
logBeginRule: ${getConfigValue('logBeginRule', 'DefaultRegex')}
358364
logstore: ${logstore}
359365
project: ${project}\n`),
360366
);
367+
361368
this.createResource.sls = { project, logstore };
362369
_.set(this.local, 'logConfig', {
363-
enableInstanceMetrics: true,
364-
enableRequestMetrics: true,
365-
logBeginRule: 'DefaultRegex',
370+
enableInstanceMetrics: getConfigValue('enableInstanceMetrics', true),
371+
enableRequestMetrics: getConfigValue('enableRequestMetrics', true),
372+
logBeginRule: getConfigValue('logBeginRule', 'DefaultRegex'),
366373
logstore,
367374
project,
375+
...customFields,
368376
});
369377
}
370378

@@ -443,7 +451,15 @@ vpcConfig:
443451
_.set(this.local, 'vpcConfig', vpcConfig);
444452
}
445453
if (nasAuto) {
446-
let serverAddr = `${mountTargetDomain}:/${functionName}`;
454+
const { params } = parseAutoConfig(this.local.nasConfig as string);
455+
const fcDir = params.mountDir
456+
? checkFcDir(params.mountDir, 'mountDir')
457+
: `/mnt/${functionName}`;
458+
if (params.nasDir && !params.nasDir.startsWith('/')) {
459+
throw new Error('nasDir must start with /');
460+
}
461+
const nasDir = params.nasDir ? params.nasDir : `/${functionName}`;
462+
let serverAddr = `${mountTargetDomain}:${nasDir}`;
447463
if (serverAddr.length > 128) {
448464
serverAddr = serverAddr.substring(0, 128);
449465
}
@@ -454,8 +470,9 @@ nasConfig:
454470
userId: 0
455471
mountPoints:
456472
- serverAddr: ${serverAddr}
457-
mountDir: /mnt/${functionName}
458-
enableTLS: false\n`),
473+
mountDir: ${fcDir}
474+
enableTLS: false
475+
`),
459476
);
460477
this.createResource.nas = { mountTargetDomain, fileSystemId };
461478
_.set(this.local, 'nasConfig', {
@@ -464,7 +481,7 @@ nasConfig:
464481
mountPoints: [
465482
{
466483
serverAddr,
467-
mountDir: `/mnt/${functionName}`,
484+
mountDir: fcDir,
468485
enableTLS: false,
469486
},
470487
],

src/subCommands/model/index.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { OSSMountPoint, VPCConfig } from '@alicloud/fc20230330';
1414
import { MODEL_DOWNLOAD_TIMEOUT } from './constants';
1515
import { initClient } from './utils';
1616
import * as $Dev20230714 from '@alicloud/devs20230714';
17+
import { parseAutoConfig, checkFcDir } from '../../utils';
1718

1819
const commandsList = Object.keys(commandsHelp.subCommands);
1920

@@ -239,7 +240,16 @@ vpcConfig:
239240
}
240241

241242
if (nasAuto) {
242-
let serverAddr = `${mountTargetDomain}:/${functionName}`;
243+
const nasAutoConfig = parseAutoConfig(this.local.nasConfig as string);
244+
const params = nasAutoConfig?.params || {};
245+
const fcDir = params.mountDir
246+
? checkFcDir(params.mountDir, 'mountDir')
247+
: `/mnt/${functionName}`;
248+
if (params.nasDir && !params.nasDir.startsWith('/')) {
249+
throw new Error('nasDir must start with /');
250+
}
251+
const nasDir = params.nasDir ? params.nasDir : `/${functionName}`;
252+
let serverAddr = `${mountTargetDomain}:${nasDir}`;
243253
if (serverAddr.length > 128) {
244254
serverAddr = serverAddr.substring(0, 128);
245255
}
@@ -250,7 +260,7 @@ groupId: 0
250260
userId: 0
251261
mountPoints:
252262
- serverAddr: ${serverAddr}
253-
mountDir: /mnt/${functionName}
263+
mountDir: ${fcDir}
254264
enableTLS: false\n`),
255265
);
256266
this.createResource.nas = { mountTargetDomain, fileSystemId };
@@ -260,7 +270,7 @@ mountPoints:
260270
mountPoints: [
261271
{
262272
serverAddr,
263-
mountDir: `/mnt/${functionName}`,
273+
mountDir: fcDir,
264274
enableTLS: false,
265275
},
266276
],

src/utils/index.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,40 @@ export const isAuto = (config: unknown): boolean => {
4949
return _.toUpper(autoConfig) === 'AUTO';
5050
};
5151

52+
export const parseAutoConfig = (
53+
config: string,
54+
): { isAuto: boolean; params: Record<string, any> } => {
55+
if (!_.isString(config)) {
56+
return { isAuto: false, params: {} };
57+
}
58+
59+
const parts = config.split('|');
60+
const baseConfig = parts[0];
61+
logger.debug(`parseAutoConfig, baseConfig = ${baseConfig}`);
62+
63+
if (_.toUpper(baseConfig) === 'AUTO') {
64+
const params: Record<string, any> = {};
65+
for (let i = 1; i < parts.length; i++) {
66+
const [key, value] = parts[i].split('=');
67+
if (key && value) {
68+
const trimmedValue = value.trim();
69+
if (typeof trimmedValue === 'string') {
70+
try {
71+
params[key.trim()] = JSON.parse(trimmedValue);
72+
} catch (error) {
73+
params[key.trim()] = trimmedValue;
74+
}
75+
} else {
76+
params[key.trim()] = trimmedValue;
77+
}
78+
}
79+
}
80+
return { isAuto: true, params };
81+
}
82+
83+
return { isAuto: false, params: {} };
84+
};
85+
5286
export const isAutoVpcConfig = (config: unknown): boolean => {
5387
logger.debug(`isAutoVpcConfig, vpcConfig = ${JSON.stringify(config)}`);
5488
if (_.isString(config)) {
@@ -223,3 +257,54 @@ export function getUserAgent(userAgent: string, command: string) {
223257
}
224258
return `${function_ai}Component:fc3;Nodejs:${process.version};OS:${process.platform}-${process.arch}command:${command}`;
225259
}
260+
261+
/**
262+
* 验证并规范化路径
263+
*/
264+
export function checkFcDir(path: string, paramName = 'path'): string {
265+
const normalizedPath = path.trim();
266+
267+
if (!normalizedPath.startsWith('/')) {
268+
throw new Error(`${paramName} does not start with '/'`);
269+
}
270+
271+
// 检查路径长度
272+
if (normalizedPath.length > 128) {
273+
throw new Error(
274+
`${paramName} is too long (${normalizedPath.length}), maximum length is 128 characters`,
275+
);
276+
}
277+
278+
// 检查不允许的系统目录前缀
279+
const forbiddenPrefixes = [
280+
'/bin',
281+
'/boot',
282+
'/dev',
283+
'/etc',
284+
'/lib',
285+
'/lib64',
286+
'/media',
287+
'/opt',
288+
'/proc',
289+
'/root',
290+
'/run',
291+
'/sbin',
292+
'/srv',
293+
'/sys',
294+
'/usr',
295+
'/var',
296+
];
297+
298+
for (const prefix of forbiddenPrefixes) {
299+
if (normalizedPath.startsWith(prefix)) {
300+
throw new Error(`Invalid ${paramName}, ${prefix} and its subdirectories are not allowed`);
301+
}
302+
}
303+
304+
const isValidTwoLevelPath = /^\/[^/]+\/.+/.test(normalizedPath);
305+
if (!isValidTwoLevelPath) {
306+
throw new Error(`Invalid ${paramName}, path must be in /**/** format with at least two levels`);
307+
}
308+
309+
return normalizedPath;
310+
}

0 commit comments

Comments
 (0)