Skip to content

Commit 8ddcf77

Browse files
committed
test: add more test and fix stackname not pass issue #5
Signed-off-by: seven <[email protected]>
1 parent bb533b0 commit 8ddcf77

File tree

9 files changed

+351
-94
lines changed

9 files changed

+351
-94
lines changed

src/commands/deploy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const deploy = async (
55
stackName: string,
66
options: { location: string; parameters: { [key: string]: string } },
77
) => {
8-
const context = constructActionContext(options);
8+
const context = constructActionContext({ ...options, stackName });
99
logger.info('Validating yaml...');
1010
const iac = parseYaml(context.iacLocation);
1111
logger.info('Yaml is valid! 🎉');

src/common/actionContext.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ export const constructActionContext = (config?: {
1010
location?: string;
1111
parameters?: { [key: string]: string };
1212
stage?: string;
13+
stackName?: string;
1314
}): ActionContext => {
1415
return {
1516
stage: config?.stage ?? 'default',
17+
stackName: config?.stackName ?? '',
1618
region:
1719
config?.region ?? process.env.ROS_REGION_ID ?? process.env.ALIYUN_REGION ?? 'cn-hangzhou',
1820
accessKeyId: config?.accessKeyId ?? (process.env.ALIYUN_ACCESS_KEY_ID as string),

src/common/iacHelper.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import path from 'node:path';
2+
import fs from 'node:fs';
3+
import * as ros from '@alicloud/ros-cdk-core';
4+
5+
export const resolveCode = (location: string): string => {
6+
const filePath = path.resolve(process.cwd(), location);
7+
const fileContent = fs.readFileSync(filePath);
8+
9+
return fileContent.toString('base64');
10+
};
11+
12+
export const replaceVars = <T>(value: T, stage: string): T => {
13+
if (typeof value === 'string') {
14+
const matchVar = value.match(/^\$\{vars\.(\w+)}$/);
15+
const containsVar = value.match(/\$\{vars\.(\w+)}/);
16+
const matchMap = value.match(/^\$\{stages\.(\w+)}$/);
17+
const containsMap = value.match(/\$\{stages\.(\w+)}/);
18+
if (matchVar?.length) {
19+
return ros.Fn.ref(matchVar[1]) as T;
20+
}
21+
if (matchMap?.length) {
22+
return ros.Fn.findInMap('stages', '', matchMap[1]) as T;
23+
}
24+
if (containsMap?.length && containsVar?.length) {
25+
return ros.Fn.sub(
26+
value.replace(/\$\{stages\.(\w+)}/g, '${$1}').replace(/\$\{vars\.(\w+)}/g, '${$1}'),
27+
) as T;
28+
}
29+
if (containsVar?.length) {
30+
return ros.Fn.sub(value.replace(/\$\{vars\.(\w+)}/g, '${$1}')) as T;
31+
}
32+
if (containsMap?.length) {
33+
return ros.Fn.sub(value.replace(/\$\{stages\.(\w+)}/g, '${$1}')) as T;
34+
}
35+
return value;
36+
}
37+
38+
if (Array.isArray(value)) {
39+
return value.map((item) => replaceVars(item, stage)) as T;
40+
}
41+
42+
if (typeof value === 'object' && value !== null) {
43+
return Object.fromEntries(
44+
Object.entries(value).map(([key, val]) => [key, replaceVars(val, stage)]),
45+
) as T;
46+
}
47+
48+
return value;
49+
};

src/common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export * from './logger';
33
export * from './getVersion';
44
export * from './rosClient';
55
export * from './actionContext';
6+
export * from './iacHelper';

src/common/rosClient.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,7 @@ const updateStack = async (stackId: string, templateBody: unknown, context: Acti
5252
parameterValue: Util.assertAsString(parameter.key),
5353
}),
5454
);
55-
console.log(
56-
'parameters:',
57-
JSON.stringify({
58-
parameters,
59-
contextParam: context.parameters,
60-
}),
61-
);
55+
6256
const createStackRequest = new UpdateStackRequest({
6357
regionId: context.region,
6458
stackId,

src/stack/iacStack.ts

Lines changed: 37 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,15 @@
11
import * as ros from '@alicloud/ros-cdk-core';
2-
import { ActionContext, EventTypes, ServerlessIac } from '../types';
32
import { RosParameterType } from '@alicloud/ros-cdk-core';
3+
import { ActionContext, EventTypes, ServerlessIac } from '../types';
44
import * as fc from '@alicloud/ros-cdk-fc';
55
import * as ram from '@alicloud/ros-cdk-ram';
66
import * as agw from '@alicloud/ros-cdk-apigateway';
7-
import path from 'node:path';
8-
import fs from 'node:fs';
9-
10-
const resolveCode = (location: string): string => {
11-
const filePath = path.resolve(process.cwd(), location);
12-
const fileContent = fs.readFileSync(filePath);
13-
14-
return fileContent.toString('base64');
15-
};
16-
17-
const replaceVars = <T>(value: T, stage: string): T => {
18-
if (typeof value === 'string') {
19-
const matchVar = value.match(/^\$\{vars\.(\w+)}$/);
20-
const containsVar = value.match(/\$\{vars\.(\w+)}/);
21-
const matchMap = value.match(/^\$\{stages\.(\w+)}$/);
22-
const containsMap = value.match(/\$\{stages\.(\w+)}/);
23-
if (matchVar?.length) {
24-
return ros.Fn.ref(matchVar[1]) as T;
25-
}
26-
if (matchMap?.length) {
27-
return ros.Fn.findInMap('stages', '', matchMap[1]) as T;
28-
}
29-
if (containsMap?.length && containsVar?.length) {
30-
return ros.Fn.sub(
31-
value.replace(/\$\{stages\.(\w+)}/g, '${$1}').replace(/\$\{vars\.(\w+)}/g, '${$1}'),
32-
) as T;
33-
}
34-
if (containsVar?.length) {
35-
return ros.Fn.sub(value.replace(/\$\{vars\.(\w+)}/g, '${$1}')) as T;
36-
}
37-
if (containsMap?.length) {
38-
return ros.Fn.sub(value.replace(/\$\{stages\.(\w+)}/g, '${$1}')) as T;
39-
}
40-
return value;
41-
}
42-
43-
if (Array.isArray(value)) {
44-
return value.map((item) => replaceVars(item, stage)) as T;
45-
}
46-
47-
if (typeof value === 'object' && value !== null) {
48-
return Object.fromEntries(
49-
Object.entries(value).map(([key, val]) => [key, replaceVars(val, stage)]),
50-
) as T;
51-
}
52-
53-
return value;
54-
};
7+
import { replaceVars, resolveCode } from '../common';
558

569
export class IacStack extends ros.Stack {
5710
constructor(scope: ros.Construct, iac: ServerlessIac, context: ActionContext) {
5811
super(scope, iac.service, {
12+
stackName: context.stackName,
5913
tags: iac.tags.reduce((acc: { [key: string]: string }, tag) => {
6014
acc[tag.key] = replaceVars(tag.value, context.stage);
6115
return acc;
@@ -70,7 +24,7 @@ export class IacStack extends ros.Stack {
7024
defaultValue: value,
7125
}),
7226
);
73-
console.log('stages:', iac.stages);
27+
7428
// Define Mappings
7529
new ros.RosMapping(this, 'stages', { mapping: replaceVars(iac.stages, context.stage) });
7630

@@ -111,8 +65,8 @@ export class IacStack extends ros.Stack {
11165
func.addDependsOn(service);
11266
});
11367

114-
const apiGateway = iac.events.find((event) => event.type === EventTypes.API_GATEWAY);
115-
if (apiGateway) {
68+
const apiGateway = iac.events?.filter((event) => event.type === EventTypes.API_GATEWAY);
69+
if (apiGateway?.length) {
11670
const gatewayAccessRole = new ram.RosRole(
11771
this,
11872
replaceVars(`${iac.service}_role`, context.stage),
@@ -161,43 +115,41 @@ export class IacStack extends ros.Stack {
161115
true,
162116
);
163117

164-
iac.events
165-
.filter((event) => event.type === EventTypes.API_GATEWAY)
166-
.forEach((event) => {
167-
event.triggers.forEach((trigger) => {
168-
const key = `${trigger.method}_${trigger.path}`.toLowerCase().replace(/\//g, '_');
118+
apiGateway.forEach((event) => {
119+
event.triggers.forEach((trigger) => {
120+
const key = `${trigger.method}_${trigger.path}`.toLowerCase().replace(/\//g, '_');
169121

170-
const api = new agw.RosApi(
171-
this,
172-
replaceVars(`${event.key}_api_${key}`, context.stage),
173-
{
174-
apiName: replaceVars(`${event.name}_api_${key}`, context.stage),
175-
groupId: apiGatewayGroup.attrGroupId,
176-
visibility: 'PRIVATE',
177-
requestConfig: {
178-
requestProtocol: 'HTTP',
179-
requestHttpMethod: replaceVars(trigger.method, context.stage),
180-
requestPath: replaceVars(trigger.path, context.stage),
181-
requestMode: 'PASSTHROUGH',
182-
},
183-
serviceConfig: {
184-
serviceProtocol: 'FunctionCompute',
185-
functionComputeConfig: {
186-
fcRegionId: context.region,
187-
serviceName: service.serviceName,
188-
functionName: trigger.backend,
189-
roleArn: gatewayAccessRole.attrArn,
190-
},
122+
const api = new agw.RosApi(
123+
this,
124+
replaceVars(`${event.key}_api_${key}`, context.stage),
125+
{
126+
apiName: replaceVars(`${event.name}_api_${key}`, context.stage),
127+
groupId: apiGatewayGroup.attrGroupId,
128+
visibility: 'PRIVATE',
129+
requestConfig: {
130+
requestProtocol: 'HTTP',
131+
requestHttpMethod: replaceVars(trigger.method, context.stage),
132+
requestPath: replaceVars(trigger.path, context.stage),
133+
requestMode: 'PASSTHROUGH',
134+
},
135+
serviceConfig: {
136+
serviceProtocol: 'FunctionCompute',
137+
functionComputeConfig: {
138+
fcRegionId: context.region,
139+
serviceName: service.serviceName,
140+
functionName: trigger.backend,
141+
roleArn: gatewayAccessRole.attrArn,
191142
},
192-
resultSample: 'ServerlessInsight resultSample',
193-
resultType: 'JSON',
194-
tags: replaceVars(iac.tags, context.stage),
195143
},
196-
true,
197-
);
198-
api.addDependsOn(apiGatewayGroup);
199-
});
144+
resultSample: 'ServerlessInsight resultSample',
145+
resultType: 'JSON',
146+
tags: replaceVars(iac.tags, context.stage),
147+
},
148+
true,
149+
);
150+
api.addDependsOn(apiGatewayGroup);
200151
});
152+
});
201153
}
202154
}
203155
}

src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ export type ServerlessIac = {
6565
service: string;
6666
tags: Array<{ key: string; value: string }>;
6767
functions: Array<IacFunction>;
68-
events: Array<Event>;
68+
events?: Array<Event>;
6969
};
7070

7171
export type ActionContext = {
7272
stage: string;
73+
stackName: string;
7374
region: string;
7475
accessKeyId: string;
7576
accessKeySecret: string;

0 commit comments

Comments
 (0)