diff --git a/package-lock.json b/package-lock.json index a9d9d558..992b4bf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@geek-fun/serverlessinsight", - "version": "0.0.4", + "version": "0.0.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@geek-fun/serverlessinsight", - "version": "0.0.4", + "version": "0.0.6", "license": "Apache-2.0", "dependencies": { "@alicloud/openapi-client": "^0.4.12", @@ -5722,6 +5722,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -10584,7 +10585,8 @@ "semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "shebang-command": { "version": "2.0.0", diff --git a/package.json b/package.json index b879b9f2..4fdf1d4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geek-fun/serverlessinsight", - "version": "0.0.5", + "version": "0.0.6", "description": "Full life cycle cross providers serverless application management for your fast-growing business.", "homepage": "https://serverlessinsight.geekfun.club", "main": "dist/src/index.js", diff --git a/src/common/iacHelper.ts b/src/common/iacHelper.ts index 6b63bbf7..e17e8c00 100644 --- a/src/common/iacHelper.ts +++ b/src/common/iacHelper.ts @@ -9,18 +9,24 @@ export const resolveCode = (location: string): string => { return fileContent.toString('base64'); }; -export const replaceVars = (value: T, stage: string): T => { +export const replaceReference = (value: T, stage: string): T => { if (typeof value === 'string') { const matchVar = value.match(/^\$\{vars\.(\w+)}$/); const containsVar = value.match(/\$\{vars\.(\w+)}/); const matchMap = value.match(/^\$\{stages\.(\w+)}$/); const containsMap = value.match(/\$\{stages\.(\w+)}/); + const matchFn = value.match(/^\$\{functions\.(\w+(\.\w+)?)}$/); + if (matchVar?.length) { return ros.Fn.ref(matchVar[1]) as T; } if (matchMap?.length) { return ros.Fn.findInMap('stages', '', matchMap[1]) as T; } + + if (matchFn?.length) { + return ros.Fn.getAtt(matchFn[1], 'FunctionName') as T; + } if (containsMap?.length && containsVar?.length) { return ros.Fn.sub( value.replace(/\$\{stages\.(\w+)}/g, '${$1}').replace(/\$\{vars\.(\w+)}/g, '${$1}'), @@ -36,12 +42,12 @@ export const replaceVars = (value: T, stage: string): T => { } if (Array.isArray(value)) { - return value.map((item) => replaceVars(item, stage)) as T; + return value.map((item) => replaceReference(item, stage)) as T; } if (typeof value === 'object' && value !== null) { return Object.fromEntries( - Object.entries(value).map(([key, val]) => [key, replaceVars(val, stage)]), + Object.entries(value).map(([key, val]) => [key, replaceReference(val, stage)]), ) as T; } diff --git a/src/stack/iacStack.ts b/src/stack/iacStack.ts index 257c1f65..76995316 100644 --- a/src/stack/iacStack.ts +++ b/src/stack/iacStack.ts @@ -4,14 +4,14 @@ import { ActionContext, EventTypes, ServerlessIac } from '../types'; import * as fc from '@alicloud/ros-cdk-fc3'; import * as ram from '@alicloud/ros-cdk-ram'; import * as agw from '@alicloud/ros-cdk-apigateway'; -import { replaceVars, resolveCode } from '../common'; +import { replaceReference, resolveCode } from '../common'; export class IacStack extends ros.Stack { constructor(scope: ros.Construct, iac: ServerlessIac, context: ActionContext) { super(scope, iac.service, { stackName: context.stackName, tags: iac.tags.reduce((acc: { [key: string]: string }, tag) => { - acc[tag.key] = replaceVars(tag.value, context.stage); + acc[tag.key] = replaceReference(tag.value, context.stage); return acc; }, {}), }); @@ -26,12 +26,12 @@ export class IacStack extends ros.Stack { ); // Define Mappings - new ros.RosMapping(this, 'stages', { mapping: replaceVars(iac.stages, context.stage) }); + new ros.RosMapping(this, 'stages', { mapping: replaceReference(iac.stages, context.stage) }); new ros.RosInfo( this, ros.RosInfo.description, - replaceVars(`${iac.service} stack`, context.stage), + replaceReference(`${iac.service} stack`, context.stage), ); iac.functions.forEach((fnc) => { @@ -39,12 +39,12 @@ export class IacStack extends ros.Stack { this, fnc.key, { - functionName: replaceVars(fnc.name, context.stage), - handler: replaceVars(fnc.handler, context.stage), - runtime: replaceVars(fnc.runtime, context.stage), - memorySize: replaceVars(fnc.memory, context.stage), - timeout: replaceVars(fnc.timeout, context.stage), - environmentVariables: replaceVars(fnc.environment, context.stage), + functionName: replaceReference(fnc.name, context.stage), + handler: replaceReference(fnc.handler, context.stage), + runtime: replaceReference(fnc.runtime, context.stage), + memorySize: replaceReference(fnc.memory, context.stage), + timeout: replaceReference(fnc.timeout, context.stage), + environmentVariables: replaceReference(fnc.environment, context.stage), code: { zipFile: resolveCode(fnc.code), }, @@ -57,10 +57,10 @@ export class IacStack extends ros.Stack { if (apiGateway?.length) { const gatewayAccessRole = new ram.RosRole( this, - replaceVars(`${iac.service}_role`, context.stage), + replaceReference(`${iac.service}_role`, context.stage), { - roleName: replaceVars(`${iac.service}-gateway-access-role`, context.stage), - description: replaceVars(`${iac.service} role`, context.stage), + roleName: replaceReference(`${iac.service}-gateway-access-role`, context.stage), + description: replaceReference(`${iac.service} role`, context.stage), assumeRolePolicyDocument: { version: '1', statement: [ @@ -75,7 +75,7 @@ export class IacStack extends ros.Stack { }, policies: [ { - policyName: replaceVars(`${iac.service}-policy`, context.stage), + policyName: replaceReference(`${iac.service}-policy`, context.stage), policyDocument: { version: '1', statement: [ @@ -95,10 +95,10 @@ export class IacStack extends ros.Stack { const apiGatewayGroup = new agw.RosGroup( this, - replaceVars(`${iac.service}_apigroup`, context.stage), + replaceReference(`${iac.service}_apigroup`, context.stage), { - groupName: replaceVars(`${iac.service}_apigroup`, context.stage), - tags: replaceVars(iac.tags, context.stage), + groupName: replaceReference(`${iac.service}_apigroup`, context.stage), + tags: replaceReference(iac.tags, context.stage), }, true, ); @@ -122,29 +122,29 @@ export class IacStack extends ros.Stack { const api = new agw.RosApi( this, - replaceVars(`${event.key}_api_${key}`, context.stage), + replaceReference(`${event.key}_api_${key}`, context.stage), { - apiName: replaceVars(`${event.name}_api_${key}`, context.stage), + apiName: replaceReference(`${event.name}_api_${key}`, context.stage), groupId: apiGatewayGroup.attrGroupId, visibility: 'PRIVATE', requestConfig: { requestProtocol: 'HTTP', - requestHttpMethod: replaceVars(trigger.method, context.stage), - requestPath: replaceVars(trigger.path, context.stage), + requestHttpMethod: replaceReference(trigger.method, context.stage), + requestPath: replaceReference(trigger.path, context.stage), requestMode: 'PASSTHROUGH', }, serviceConfig: { serviceProtocol: 'FunctionCompute', functionComputeConfig: { fcRegionId: context.region, - functionName: trigger.backend, + functionName: replaceReference(trigger.backend, trigger.backend), roleArn: gatewayAccessRole.attrArn, fcVersion: '3.0', }, }, resultSample: 'ServerlessInsight resultSample', resultType: 'JSON', - tags: replaceVars(iac.tags, context.stage), + tags: replaceReference(iac.tags, context.stage), }, true, ); diff --git a/tests/fixtures/deployFixture.ts b/tests/fixtures/deployFixture.ts index d9180099..af0ff73a 100644 --- a/tests/fixtures/deployFixture.ts +++ b/tests/fixtures/deployFixture.ts @@ -10,8 +10,8 @@ export const oneFcOneGatewayIac = { }, stages: { dev: { - region: '${vars:region}', - account_id: '${vars:account_id}', + region: '${vars.region}', + account_id: '${vars.account_id}', }, }, functions: [ @@ -37,7 +37,7 @@ export const oneFcOneGatewayIac = { { method: 'GET', path: '/api/hello', - backend: 'demo_fn_gateway', + backend: '${functions.hello_fn}', }, ], }, @@ -53,7 +53,12 @@ export const oneFcOneGatewayIac = { export const oneFcOneGatewayRos = { Description: 'my-demo-service stack', Mappings: { - stages: { dev: { account_id: '${vars:account_id}', region: '${vars:region}' } }, + stages: { + dev: { + account_id: { Ref: 'account_id' }, + region: { Ref: 'region' }, + }, + }, }, Metadata: { 'ALIYUN::ROS::Interface': { TemplateTags: ['Create by ROS CDK'] } }, Parameters: { @@ -76,7 +81,7 @@ export const oneFcOneGatewayRos = { ResultType: 'JSON', ServiceConfig: { FunctionComputeConfig: { - FunctionName: 'demo_fn_gateway', + FunctionName: { 'Fn::GetAtt': ['hello_fn', 'FunctionName'] }, RoleArn: { 'Fn::GetAtt': ['my-demo-service_role', 'Arn'] }, FcVersion: '3.0', }, @@ -145,8 +150,8 @@ export const oneFcIac = { }, stages: { dev: { - region: '${vars:region}', - account_id: '${vars:account_id}', + region: '${vars.region}', + account_id: '${vars.account_id}', }, }, functions: [ @@ -174,7 +179,12 @@ export const oneFcIac = { export const oneFcRos = { Description: 'my-demo-service stack', Mappings: { - stages: { dev: { account_id: '${vars:account_id}', region: '${vars:region}' } }, + stages: { + dev: { + account_id: { Ref: 'account_id' }, + region: { Ref: 'region' }, + }, + }, }, Metadata: { 'ALIYUN::ROS::Interface': { TemplateTags: ['Create by ROS CDK'] } }, Parameters: { diff --git a/tests/fixtures/serverless-insight.yml b/tests/fixtures/serverless-insight.yml index 9d161281..32c848db 100644 --- a/tests/fixtures/serverless-insight.yml +++ b/tests/fixtures/serverless-insight.yml @@ -48,7 +48,7 @@ events: triggers: - method: GET path: /api/hello - backend: insight-poc-fn + backend: ${functions.insight_poc_fn} # custom_domain: # domain_name: test.com # certificate_name: test