@geek-fun/serverlessinsight 0.6.7 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +1 -1
- package/dist/src/commands/plan.js +4 -1
- package/dist/src/common/aliyunClient/ecsOperations.js +189 -93
- package/dist/src/common/aliyunClient/nasOperations.js +12 -0
- package/dist/src/common/aliyunClient/ramOperations.js +19 -3
- package/dist/src/common/imsClient.js +6 -2
- package/dist/src/lang/en.js +4 -0
- package/dist/src/lang/zh-CN.js +4 -0
- package/dist/src/stack/aliyunStack/apigwPlanner.js +3 -1
- package/dist/src/stack/aliyunStack/apigwResource.js +12 -4
- package/dist/src/stack/aliyunStack/fc3Planner.js +28 -1
- package/dist/src/stack/aliyunStack/fc3Resource.js +3 -3
- package/dist/src/stack/aliyunStack/fc3Types.js +19 -0
- package/dist/src/stack/aliyunStack/ossTypes.js +28 -0
- package/dist/src/stack/aliyunStack/tablestoreTypes.js +14 -0
- package/dist/src/stack/scfStack/cosTypes.js +32 -0
- package/dist/src/stack/scfStack/scfTypes.js +30 -0
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geek-fun/serverlessinsight",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.8",
|
|
4
4
|
"description": "Full life cycle cross providers serverless application management for your fast-growing business.",
|
|
5
5
|
"homepage": "https://serverlessinsight.geekfun.club",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -23,7 +23,10 @@ const plan = async (options) => {
|
|
|
23
23
|
const iac = (0, parser_1.revalYaml)(iacLocation, context);
|
|
24
24
|
// Store IAC in context for access by all functions
|
|
25
25
|
(0, common_1.setIac)(iac);
|
|
26
|
-
|
|
26
|
+
const providerDisplayName = iac.provider.name === common_1.ProviderEnum.ALIYUN
|
|
27
|
+
? lang_1.lang.__('PROVIDER_ALIYUN')
|
|
28
|
+
: lang_1.lang.__('PROVIDER_TENCENT');
|
|
29
|
+
common_1.logger.info(lang_1.lang.__('GENERATING_PLAN_FOR_PROVIDER', { provider: providerDisplayName }));
|
|
27
30
|
const backend = (0, stateBackend_1.createStateBackend)(iac.backend, context);
|
|
28
31
|
let planResult;
|
|
29
32
|
if (iac.provider.name === common_1.ProviderEnum.TENCENT) {
|
|
@@ -78,115 +78,211 @@ const isDuplicateSecurityGroupRuleError = (error) => {
|
|
|
78
78
|
]);
|
|
79
79
|
return duplicateCodes.has(error.code);
|
|
80
80
|
};
|
|
81
|
-
const createEcsOperations = (ecsClient, context) =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
securityGroupName,
|
|
86
|
-
vpcId,
|
|
87
|
-
description: description ?? `ServerlessInsight security group for ${securityGroupName}`,
|
|
88
|
-
});
|
|
89
|
-
const response = await ecsClient.createSecurityGroup(createRequest);
|
|
90
|
-
const securityGroupId = response.body?.securityGroupId;
|
|
91
|
-
if (!securityGroupId) {
|
|
92
|
-
throw new Error('Failed to create security group');
|
|
93
|
-
}
|
|
94
|
-
// Add ingress rules
|
|
95
|
-
for (const rule of ingressRules) {
|
|
96
|
-
let parsedRule;
|
|
97
|
-
try {
|
|
98
|
-
parsedRule = (0, exports.parseSecurityGroupRule)(rule);
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
logger_1.logger.warn(`Skipping invalid ingress rule: ${rule}. ${String(error)}`);
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
const ingressRequest = new ecs.AuthorizeSecurityGroupRequest({
|
|
81
|
+
const createEcsOperations = (ecsClient, context) => {
|
|
82
|
+
const operations = {
|
|
83
|
+
createSecurityGroup: async (securityGroupName, vpcId, ingressRules, egressRules, description) => {
|
|
84
|
+
const createRequest = new ecs.CreateSecurityGroupRequest({
|
|
105
85
|
regionId: context.region,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
portRange: transformPortRange(parsedRule.protocol, parsedRule.portRange),
|
|
86
|
+
securityGroupName,
|
|
87
|
+
vpcId,
|
|
88
|
+
description: description ?? `ServerlessInsight security group for ${securityGroupName}`,
|
|
110
89
|
});
|
|
111
|
-
|
|
112
|
-
|
|
90
|
+
const response = await ecsClient.createSecurityGroup(createRequest);
|
|
91
|
+
const securityGroupId = response.body?.securityGroupId;
|
|
92
|
+
if (!securityGroupId) {
|
|
93
|
+
throw new Error('Failed to create security group');
|
|
113
94
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
95
|
+
// Add ingress rules
|
|
96
|
+
for (const rule of ingressRules) {
|
|
97
|
+
let parsedRule;
|
|
98
|
+
try {
|
|
99
|
+
parsedRule = (0, exports.parseSecurityGroupRule)(rule);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
logger_1.logger.warn(`Skipping invalid ingress rule: ${rule}. ${String(error)}`);
|
|
117
103
|
continue;
|
|
118
104
|
}
|
|
119
|
-
|
|
105
|
+
const ingressRequest = new ecs.AuthorizeSecurityGroupRequest({
|
|
106
|
+
regionId: context.region,
|
|
107
|
+
securityGroupId,
|
|
108
|
+
ipProtocol: parsedRule.protocol.toLowerCase(),
|
|
109
|
+
sourceCidrIp: parsedRule.cidr,
|
|
110
|
+
portRange: transformPortRange(parsedRule.protocol, parsedRule.portRange),
|
|
111
|
+
});
|
|
112
|
+
try {
|
|
113
|
+
await ecsClient.authorizeSecurityGroup(ingressRequest);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (isDuplicateSecurityGroupRuleError(error)) {
|
|
117
|
+
logger_1.logger.debug(`Ingress rule already exists, skipping: ${rule}`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
logger_1.logger.warn(`Failed to add ingress rule: ${rule}. ${String(error)}`);
|
|
121
|
+
}
|
|
120
122
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
// Add egress rules
|
|
124
|
+
for (const rule of egressRules) {
|
|
125
|
+
let parsedRule;
|
|
126
|
+
try {
|
|
127
|
+
parsedRule = (0, exports.parseSecurityGroupRule)(rule);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
logger_1.logger.warn(`Skipping invalid egress rule: ${rule}. ${String(error)}`);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const egressRequest = new ecs.AuthorizeSecurityGroupEgressRequest({
|
|
134
|
+
regionId: context.region,
|
|
135
|
+
securityGroupId,
|
|
136
|
+
ipProtocol: parsedRule.protocol.toLowerCase(),
|
|
137
|
+
destCidrIp: parsedRule.cidr,
|
|
138
|
+
portRange: transformPortRange(parsedRule.protocol, parsedRule.portRange),
|
|
139
|
+
});
|
|
140
|
+
try {
|
|
141
|
+
await ecsClient.authorizeSecurityGroupEgress(egressRequest);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (isDuplicateSecurityGroupRuleError(error)) {
|
|
145
|
+
logger_1.logger.debug(`Egress rule already exists, skipping: ${rule}`);
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
logger_1.logger.warn(`Failed to add egress rule: ${rule}. ${String(error)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const sg = await operations.getSecurityGroup(securityGroupId);
|
|
152
|
+
if (!sg) {
|
|
153
|
+
return {
|
|
154
|
+
securityGroupId,
|
|
155
|
+
securityGroupName,
|
|
156
|
+
vpcId,
|
|
157
|
+
description,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return sg;
|
|
161
|
+
},
|
|
162
|
+
getSecurityGroupRules: async (securityGroupId) => {
|
|
163
|
+
const ingressRules = [];
|
|
164
|
+
const egressRules = [];
|
|
125
165
|
try {
|
|
126
|
-
|
|
166
|
+
const request = new ecs.DescribeSecurityGroupAttributeRequest({
|
|
167
|
+
regionId: context.region,
|
|
168
|
+
securityGroupId,
|
|
169
|
+
direction: 'ingress',
|
|
170
|
+
});
|
|
171
|
+
const response = await ecsClient.describeSecurityGroupAttribute(request);
|
|
172
|
+
if (response?.body?.permissions?.permission) {
|
|
173
|
+
for (const perm of response.body.permissions.permission) {
|
|
174
|
+
ingressRules.push({
|
|
175
|
+
direction: 'ingress',
|
|
176
|
+
ipProtocol: perm.ipProtocol ?? '',
|
|
177
|
+
portRange: perm.portRange ?? '',
|
|
178
|
+
sourceCidrIp: perm.sourceCidrIp,
|
|
179
|
+
priority: perm.priority,
|
|
180
|
+
policy: perm.policy,
|
|
181
|
+
description: perm.description,
|
|
182
|
+
ruleId: perm.ruleId,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
127
186
|
}
|
|
128
187
|
catch (error) {
|
|
129
|
-
logger_1.logger.
|
|
130
|
-
continue;
|
|
188
|
+
logger_1.logger.debug(`Failed to get ingress rules: ${String(error)}`);
|
|
131
189
|
}
|
|
132
|
-
const egressRequest = new ecs.AuthorizeSecurityGroupEgressRequest({
|
|
133
|
-
regionId: context.region,
|
|
134
|
-
securityGroupId,
|
|
135
|
-
ipProtocol: parsedRule.protocol.toLowerCase(),
|
|
136
|
-
destCidrIp: parsedRule.cidr,
|
|
137
|
-
portRange: transformPortRange(parsedRule.protocol, parsedRule.portRange),
|
|
138
|
-
});
|
|
139
190
|
try {
|
|
140
|
-
|
|
191
|
+
const request = new ecs.DescribeSecurityGroupAttributeRequest({
|
|
192
|
+
regionId: context.region,
|
|
193
|
+
securityGroupId,
|
|
194
|
+
direction: 'egress',
|
|
195
|
+
});
|
|
196
|
+
const response = await ecsClient.describeSecurityGroupAttribute(request);
|
|
197
|
+
if (response?.body?.permissions?.permission) {
|
|
198
|
+
for (const perm of response.body.permissions.permission) {
|
|
199
|
+
egressRules.push({
|
|
200
|
+
direction: 'egress',
|
|
201
|
+
ipProtocol: perm.ipProtocol ?? '',
|
|
202
|
+
portRange: perm.portRange ?? '',
|
|
203
|
+
destCidrIp: perm.destCidrIp,
|
|
204
|
+
priority: perm.priority,
|
|
205
|
+
policy: perm.policy,
|
|
206
|
+
description: perm.description,
|
|
207
|
+
ruleId: perm.ruleId,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
141
211
|
}
|
|
142
212
|
catch (error) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
213
|
+
logger_1.logger.debug(`Failed to get egress rules: ${String(error)}`);
|
|
214
|
+
}
|
|
215
|
+
return { ingressRules, egressRules };
|
|
216
|
+
},
|
|
217
|
+
getSecurityGroup: async (securityGroupId) => {
|
|
218
|
+
try {
|
|
219
|
+
const request = new ecs.DescribeSecurityGroupsRequest({
|
|
220
|
+
regionId: context.region,
|
|
221
|
+
securityGroupId,
|
|
222
|
+
});
|
|
223
|
+
const response = await ecsClient.describeSecurityGroups(request);
|
|
224
|
+
if (!response ||
|
|
225
|
+
!response.body ||
|
|
226
|
+
!response.body.securityGroups ||
|
|
227
|
+
!response.body.securityGroups.securityGroup ||
|
|
228
|
+
response.body.securityGroups.securityGroup.length === 0) {
|
|
229
|
+
return null;
|
|
146
230
|
}
|
|
147
|
-
|
|
231
|
+
const sg = response.body.securityGroups.securityGroup[0];
|
|
232
|
+
const rules = await operations.getSecurityGroupRules(securityGroupId);
|
|
233
|
+
return {
|
|
234
|
+
securityGroupId: sg.securityGroupId ?? securityGroupId,
|
|
235
|
+
securityGroupName: sg.securityGroupName,
|
|
236
|
+
vpcId: sg.vpcId,
|
|
237
|
+
description: sg.description,
|
|
238
|
+
createTime: sg.creationTime,
|
|
239
|
+
ingressRules: rules.ingressRules,
|
|
240
|
+
egressRules: rules.egressRules,
|
|
241
|
+
};
|
|
148
242
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
243
|
+
catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
getSecurityGroupByName: async (securityGroupName, vpcId) => {
|
|
248
|
+
try {
|
|
249
|
+
const request = new ecs.DescribeSecurityGroupsRequest({
|
|
250
|
+
regionId: context.region,
|
|
251
|
+
securityGroupName,
|
|
252
|
+
vpcId,
|
|
253
|
+
});
|
|
254
|
+
const response = await ecsClient.describeSecurityGroups(request);
|
|
255
|
+
if (!response ||
|
|
256
|
+
!response.body ||
|
|
257
|
+
!response.body.securityGroups ||
|
|
258
|
+
!response.body.securityGroups.securityGroup ||
|
|
259
|
+
response.body.securityGroups.securityGroup.length === 0) {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
const sg = response.body.securityGroups.securityGroup[0];
|
|
263
|
+
const rules = await operations.getSecurityGroupRules(sg.securityGroupId);
|
|
264
|
+
return {
|
|
265
|
+
securityGroupId: sg.securityGroupId,
|
|
266
|
+
securityGroupName: sg.securityGroupName,
|
|
267
|
+
vpcId: sg.vpcId,
|
|
268
|
+
description: sg.description,
|
|
269
|
+
createTime: sg.creationTime,
|
|
270
|
+
ingressRules: rules.ingressRules,
|
|
271
|
+
egressRules: rules.egressRules,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
deleteSecurityGroup: async (securityGroupId) => {
|
|
279
|
+
const request = new ecs.DeleteSecurityGroupRequest({
|
|
160
280
|
regionId: context.region,
|
|
161
281
|
securityGroupId,
|
|
162
282
|
});
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
response.body.securityGroups.securityGroup.length === 0) {
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
const sg = response.body.securityGroups.securityGroup[0];
|
|
172
|
-
return {
|
|
173
|
-
securityGroupId: sg.securityGroupId ?? securityGroupId,
|
|
174
|
-
securityGroupName: sg.securityGroupName,
|
|
175
|
-
vpcId: sg.vpcId,
|
|
176
|
-
description: sg.description,
|
|
177
|
-
createTime: sg.creationTime,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
catch {
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
},
|
|
184
|
-
deleteSecurityGroup: async (securityGroupId) => {
|
|
185
|
-
const request = new ecs.DeleteSecurityGroupRequest({
|
|
186
|
-
regionId: context.region,
|
|
187
|
-
securityGroupId,
|
|
188
|
-
});
|
|
189
|
-
await ecsClient.deleteSecurityGroup(request);
|
|
190
|
-
},
|
|
191
|
-
});
|
|
283
|
+
await ecsClient.deleteSecurityGroup(request);
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
return operations;
|
|
287
|
+
};
|
|
192
288
|
exports.createEcsOperations = createEcsOperations;
|
|
@@ -97,6 +97,13 @@ const createNasOperations = (nasClient) => {
|
|
|
97
97
|
priority: 1,
|
|
98
98
|
});
|
|
99
99
|
await nasClient.createAccessRule(request);
|
|
100
|
+
return {
|
|
101
|
+
accessGroupName,
|
|
102
|
+
sourceCidrIp,
|
|
103
|
+
rwAccessType: 'RDWR',
|
|
104
|
+
userAccessType: 'no_squash',
|
|
105
|
+
priority: 1,
|
|
106
|
+
};
|
|
100
107
|
},
|
|
101
108
|
createFileSystem: async (storageClass, functionName) => {
|
|
102
109
|
const { fileSystemType, storageType } = storageClassMap[storageClass];
|
|
@@ -149,6 +156,11 @@ const createNasOperations = (nasClient) => {
|
|
|
149
156
|
protocolType: fs.protocolType,
|
|
150
157
|
status: fs.status,
|
|
151
158
|
createTime: fs.createTime,
|
|
159
|
+
description: fs.description,
|
|
160
|
+
zoneId: fs.zoneId,
|
|
161
|
+
capacity: fs.capacity,
|
|
162
|
+
encrypted: fs.encrypted,
|
|
163
|
+
mountTargetCount: fs.mountTargetCount,
|
|
152
164
|
};
|
|
153
165
|
}
|
|
154
166
|
catch {
|
|
@@ -131,6 +131,7 @@ const createRamOperations = (ramClient) => {
|
|
|
131
131
|
throw error;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
return policyName;
|
|
134
135
|
};
|
|
135
136
|
return {
|
|
136
137
|
createRole: async (roleName, trustedServices, description) => {
|
|
@@ -148,9 +149,12 @@ const createRamOperations = (ramClient) => {
|
|
|
148
149
|
arn: response.body?.role?.arn,
|
|
149
150
|
description: response.body?.role?.description,
|
|
150
151
|
createDate: response.body?.role?.createDate,
|
|
152
|
+
updateDate: response.body?.role?.updateDate,
|
|
153
|
+
maxSessionDuration: response.body?.role?.maxSessionDuration,
|
|
154
|
+
assumeRolePolicyDocument: assumeRolePolicy,
|
|
151
155
|
};
|
|
152
|
-
await attachRolePolicyForFc(roleName);
|
|
153
|
-
return roleInfo;
|
|
156
|
+
const policyName = await attachRolePolicyForFc(roleName);
|
|
157
|
+
return { ...roleInfo, policyName };
|
|
154
158
|
}
|
|
155
159
|
catch (error) {
|
|
156
160
|
if (error &&
|
|
@@ -166,13 +170,17 @@ const createRamOperations = (ramClient) => {
|
|
|
166
170
|
newAssumeRolePolicyDocument: assumeRolePolicy,
|
|
167
171
|
});
|
|
168
172
|
await ramClient.updateRole(updateRequest);
|
|
169
|
-
await attachRolePolicyForFc(roleName);
|
|
173
|
+
const policyName = await attachRolePolicyForFc(roleName);
|
|
170
174
|
return {
|
|
171
175
|
roleName,
|
|
172
176
|
roleId: getResponse.body?.role?.roleId,
|
|
173
177
|
arn: getResponse.body?.role?.arn,
|
|
174
178
|
description: getResponse.body?.role?.description,
|
|
175
179
|
createDate: getResponse.body?.role?.createDate,
|
|
180
|
+
updateDate: getResponse.body?.role?.updateDate,
|
|
181
|
+
maxSessionDuration: getResponse.body?.role?.maxSessionDuration,
|
|
182
|
+
assumeRolePolicyDocument: assumeRolePolicy,
|
|
183
|
+
policyName,
|
|
176
184
|
};
|
|
177
185
|
}
|
|
178
186
|
catch (recoveryError) {
|
|
@@ -197,6 +205,10 @@ const createRamOperations = (ramClient) => {
|
|
|
197
205
|
arn: getResponse.body?.role?.arn,
|
|
198
206
|
description: getResponse.body?.role?.description,
|
|
199
207
|
createDate: getResponse.body?.role?.createDate,
|
|
208
|
+
updateDate: getResponse.body?.role?.updateDate,
|
|
209
|
+
maxSessionDuration: getResponse.body?.role?.maxSessionDuration,
|
|
210
|
+
assumeRolePolicyDocument: assumeRolePolicy,
|
|
211
|
+
policyName: `${roleName}-policy`,
|
|
200
212
|
};
|
|
201
213
|
const updateRequest = new ram.UpdateRoleRequest({
|
|
202
214
|
roleName,
|
|
@@ -231,6 +243,10 @@ const createRamOperations = (ramClient) => {
|
|
|
231
243
|
arn: response.body.role.arn,
|
|
232
244
|
description: response.body.role.description,
|
|
233
245
|
createDate: response.body.role.createDate,
|
|
246
|
+
updateDate: response.body.role.updateDate,
|
|
247
|
+
maxSessionDuration: response.body.role.maxSessionDuration,
|
|
248
|
+
assumeRolePolicyDocument: response.body.role.assumeRolePolicyDocument,
|
|
249
|
+
policyName: `${roleName}-policy`,
|
|
234
250
|
};
|
|
235
251
|
}
|
|
236
252
|
catch (error) {
|
|
@@ -37,14 +37,18 @@ exports.getIamInfo = void 0;
|
|
|
37
37
|
const ims20190815_1 = __importStar(require("@alicloud/ims20190815")), ims20190815 = ims20190815_1;
|
|
38
38
|
const openApi = __importStar(require("@alicloud/openapi-client"));
|
|
39
39
|
const providerEnum_1 = require("./providerEnum");
|
|
40
|
+
const constants_1 = require("./constants");
|
|
40
41
|
const getIamInfo = async (context) => {
|
|
41
42
|
if (context.provider !== providerEnum_1.ProviderEnum.ALIYUN) {
|
|
42
43
|
return undefined;
|
|
43
44
|
}
|
|
44
|
-
const
|
|
45
|
+
const imsConfig = new openApi.Config({
|
|
45
46
|
accessKeyId: context.accessKeyId,
|
|
46
47
|
accessKeySecret: context.accessKeySecret,
|
|
47
|
-
})
|
|
48
|
+
});
|
|
49
|
+
imsConfig.connectTimeout = constants_1.ALIYUN_FC3_CONNECT_TIMEOUT_MS;
|
|
50
|
+
imsConfig.readTimeout = constants_1.ALIYUN_FC3_READ_TIMEOUT_MS;
|
|
51
|
+
const imsClient = new ims20190815_1.default(imsConfig);
|
|
48
52
|
const { body } = await imsClient.getUser(new ims20190815.GetUserRequest({ userAccessKeyId: context.accessKeyId }));
|
|
49
53
|
return body?.user
|
|
50
54
|
? {
|
package/dist/src/lang/en.js
CHANGED
|
@@ -79,6 +79,9 @@ exports.en = {
|
|
|
79
79
|
// Plan command messages
|
|
80
80
|
PLAN_COMMAND_TENCENT_ONLY: 'Plan command is currently only supported for Tencent provider',
|
|
81
81
|
GENERATING_PLAN_FOR_SCF: 'Generating plan for Tencent SCF resources...',
|
|
82
|
+
GENERATING_PLAN_FOR_PROVIDER: 'Generating plan for {{provider}} resources...',
|
|
83
|
+
PROVIDER_ALIYUN: 'Alibaba Cloud',
|
|
84
|
+
PROVIDER_TENCENT: 'Tencent Cloud',
|
|
82
85
|
DEPLOYMENT_PLAN: 'DEPLOYMENT PLAN',
|
|
83
86
|
NO_CHANGES_INFRASTRUCTURE_UP_TO_DATE: 'No changes. Infrastructure is up to date.',
|
|
84
87
|
CREATE: 'CREATE',
|
|
@@ -365,6 +368,7 @@ exports.en = {
|
|
|
365
368
|
CREATING_SLS_INDEX: 'Creating SLS index for: {{logstoreName}}',
|
|
366
369
|
CREATING_RAM_ROLE: 'Creating RAM role: {{roleName}}',
|
|
367
370
|
CREATING_SECURITY_GROUP: 'Creating security group: {{sgName}}',
|
|
371
|
+
SECURITY_GROUP_NOT_FOUND: 'Security group "{{sgName}}" not found in VPC "{{vpcId}}"',
|
|
368
372
|
CREATING_NAS_ACCESS_GROUP: 'Creating NAS access group: {{accessGroupName}}',
|
|
369
373
|
CREATING_NAS_ACCESS_RULE: 'Creating NAS access rule for: {{accessGroupName}}',
|
|
370
374
|
CREATING_NAS_FILE_SYSTEM: 'Creating NAS file system for: {{name}}',
|
package/dist/src/lang/zh-CN.js
CHANGED
|
@@ -79,6 +79,9 @@ exports.zhCN = {
|
|
|
79
79
|
// Plan command messages
|
|
80
80
|
PLAN_COMMAND_TENCENT_ONLY: 'Plan 命令目前仅支持腾讯云提供商',
|
|
81
81
|
GENERATING_PLAN_FOR_SCF: '正在为腾讯云 SCF 资源生成计划...',
|
|
82
|
+
GENERATING_PLAN_FOR_PROVIDER: '正在为{{provider}}资源生成计划...',
|
|
83
|
+
PROVIDER_ALIYUN: '阿里云',
|
|
84
|
+
PROVIDER_TENCENT: '腾讯云',
|
|
82
85
|
DEPLOYMENT_PLAN: '部署计划',
|
|
83
86
|
NO_CHANGES_INFRASTRUCTURE_UP_TO_DATE: '无变更。基础设施已是最新状态。',
|
|
84
87
|
CREATE: '创建',
|
|
@@ -362,6 +365,7 @@ exports.zhCN = {
|
|
|
362
365
|
CREATING_SLS_INDEX: '正在为 SLS 日志库创建索引: {{logstoreName}}',
|
|
363
366
|
CREATING_RAM_ROLE: '正在创建 RAM 角色: {{roleName}}',
|
|
364
367
|
CREATING_SECURITY_GROUP: '正在创建安全组: {{sgName}}',
|
|
368
|
+
SECURITY_GROUP_NOT_FOUND: '在 VPC "{{vpcId}}" 中未找到安全组 "{{sgName}}"',
|
|
365
369
|
CREATING_NAS_ACCESS_GROUP: '正在创建 NAS 权限组: {{accessGroupName}}',
|
|
366
370
|
CREATING_NAS_ACCESS_RULE: '正在为 NAS 权限组创建访问规则: {{accessGroupName}}',
|
|
367
371
|
CREATING_NAS_FILE_SYSTEM: '正在为 {{name}} 创建 NAS 文件系统',
|
|
@@ -43,7 +43,9 @@ const generateApigwPlan = async (context, state, events, serviceName) => {
|
|
|
43
43
|
domain: event.domain
|
|
44
44
|
? {
|
|
45
45
|
domainName: event.domain.domain_name,
|
|
46
|
-
|
|
46
|
+
certificateId: event.domain.certificate_id ?? null,
|
|
47
|
+
certificateBody: event.domain.certificate_body ?? null,
|
|
48
|
+
certificatePrivateKey: event.domain.certificate_private_key ? '(managed)' : null,
|
|
47
49
|
protocol: event.domain.protocol ?? null,
|
|
48
50
|
}
|
|
49
51
|
: null,
|
|
@@ -133,7 +133,9 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
133
133
|
domain: event.domain
|
|
134
134
|
? {
|
|
135
135
|
domainName: event.domain.domain_name,
|
|
136
|
-
|
|
136
|
+
certificateId: event.domain.certificate_id ?? null,
|
|
137
|
+
certificateBody: event.domain.certificate_body ?? null,
|
|
138
|
+
certificatePrivateKey: event.domain.certificate_private_key ? '(managed)' : null,
|
|
137
139
|
protocol: event.domain.protocol ?? null,
|
|
138
140
|
}
|
|
139
141
|
: null,
|
|
@@ -173,7 +175,9 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
173
175
|
domain: event.domain
|
|
174
176
|
? {
|
|
175
177
|
domainName: event.domain.domain_name,
|
|
176
|
-
|
|
178
|
+
certificateId: event.domain.certificate_id ?? null,
|
|
179
|
+
certificateBody: event.domain.certificate_body ?? null,
|
|
180
|
+
certificatePrivateKey: event.domain.certificate_private_key ? '(managed)' : null,
|
|
177
181
|
protocol: event.domain.protocol ?? null,
|
|
178
182
|
}
|
|
179
183
|
: null,
|
|
@@ -209,7 +213,9 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
209
213
|
domain: event.domain
|
|
210
214
|
? {
|
|
211
215
|
domainName: event.domain.domain_name,
|
|
212
|
-
|
|
216
|
+
certificateId: event.domain.certificate_id ?? null,
|
|
217
|
+
certificateBody: event.domain.certificate_body ?? null,
|
|
218
|
+
certificatePrivateKey: event.domain.certificate_private_key ? '(managed)' : null,
|
|
213
219
|
protocol: event.domain.protocol ?? null,
|
|
214
220
|
}
|
|
215
221
|
: null,
|
|
@@ -318,7 +324,9 @@ const updateApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
318
324
|
domain: event.domain
|
|
319
325
|
? {
|
|
320
326
|
domainName: event.domain.domain_name,
|
|
321
|
-
|
|
327
|
+
certificateId: event.domain.certificate_id ?? null,
|
|
328
|
+
certificateBody: event.domain.certificate_body ?? null,
|
|
329
|
+
certificatePrivateKey: event.domain.certificate_private_key ? '(managed)' : null,
|
|
322
330
|
protocol: event.domain.protocol ?? null,
|
|
323
331
|
}
|
|
324
332
|
: null,
|
|
@@ -4,6 +4,32 @@ exports.generateFunctionPlan = void 0;
|
|
|
4
4
|
const common_1 = require("../../common");
|
|
5
5
|
const aliyunClient_1 = require("../../common/aliyunClient");
|
|
6
6
|
const fc3Types_1 = require("./fc3Types");
|
|
7
|
+
const lang_1 = require("../../lang");
|
|
8
|
+
const isSecurityGroupId = (value) => value.startsWith('sg-');
|
|
9
|
+
const resolveSecurityGroupId = async (context, securityGroupName, vpcId) => {
|
|
10
|
+
if (isSecurityGroupId(securityGroupName)) {
|
|
11
|
+
return securityGroupName;
|
|
12
|
+
}
|
|
13
|
+
const client = (0, aliyunClient_1.createAliyunClient)(context);
|
|
14
|
+
const sg = await client.ecs.getSecurityGroupByName(securityGroupName, vpcId);
|
|
15
|
+
if (!sg) {
|
|
16
|
+
throw new Error(lang_1.lang.__('SECURITY_GROUP_NOT_FOUND', { sgName: securityGroupName, vpcId: vpcId ?? 'default' }));
|
|
17
|
+
}
|
|
18
|
+
return sg.securityGroupId;
|
|
19
|
+
};
|
|
20
|
+
const resolveVpcConfigSecurityGroup = async (context, config) => {
|
|
21
|
+
if (!config.vpcConfig?.securityGroupId) {
|
|
22
|
+
return config;
|
|
23
|
+
}
|
|
24
|
+
const securityGroupId = await resolveSecurityGroupId(context, config.vpcConfig.securityGroupId, config.vpcConfig.vpcId);
|
|
25
|
+
return {
|
|
26
|
+
...config,
|
|
27
|
+
vpcConfig: {
|
|
28
|
+
...config.vpcConfig,
|
|
29
|
+
securityGroupId,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
};
|
|
7
33
|
const planFunctionDeletion = (logicalId, definition) => ({
|
|
8
34
|
logicalId,
|
|
9
35
|
action: 'delete',
|
|
@@ -22,7 +48,8 @@ const generateFunctionPlan = async (context, state, functions) => {
|
|
|
22
48
|
const functionItems = await Promise.all(functions.map(async (fn) => {
|
|
23
49
|
const logicalId = `functions.${fn.key}`;
|
|
24
50
|
const currentState = (0, common_1.getResource)(state, logicalId);
|
|
25
|
-
const
|
|
51
|
+
const rawConfig = (0, fc3Types_1.functionToFc3Config)(fn);
|
|
52
|
+
const config = await resolveVpcConfigSecurityGroup(context, rawConfig);
|
|
26
53
|
const codePath = fn.code.path;
|
|
27
54
|
const desiredCodeHash = (0, common_1.computeFileHash)(codePath);
|
|
28
55
|
const desiredDefinition = (0, fc3Types_1.extractFc3Definition)(config, desiredCodeHash);
|
|
@@ -247,13 +247,13 @@ const createDependentResources = async (context, fn, serviceName, existingInstan
|
|
|
247
247
|
const accessGroupName = `${fn.name}-${context.stage}-nas-access-${mountPath}`;
|
|
248
248
|
logger_1.logger.info(lang_1.lang.__('CREATING_NAS_ACCESS_GROUP', { accessGroupName }));
|
|
249
249
|
const accessGroup = await client.nas.createAccessGroup(accessGroupName);
|
|
250
|
+
logger_1.logger.info(lang_1.lang.__('CREATING_NAS_ACCESS_RULE', { accessGroupName }));
|
|
251
|
+
const accessRule = await client.nas.createAccessRule(accessGroupName, '10.0.0.0/8');
|
|
250
252
|
instances.push({
|
|
251
253
|
type: 'ALIYUN_NAS_ACCESS_GROUP',
|
|
252
254
|
id: accessGroupName,
|
|
253
|
-
attributes: { ...accessGroup },
|
|
255
|
+
attributes: { ...accessGroup, accessRules: [accessRule] },
|
|
254
256
|
});
|
|
255
|
-
logger_1.logger.info(lang_1.lang.__('CREATING_NAS_ACCESS_RULE', { accessGroupName }));
|
|
256
|
-
await client.nas.createAccessRule(accessGroupName, '10.0.0.0/8');
|
|
257
257
|
logger_1.logger.info(lang_1.lang.__('CREATING_NAS_FILE_SYSTEM', { name: fn.name }));
|
|
258
258
|
const fileSystem = await client.nas.createFileSystem(nasItem.storage_class, fn.name);
|
|
259
259
|
instances.push({
|
|
@@ -50,6 +50,23 @@ const functionToFc3Config = (fn) => {
|
|
|
50
50
|
securityGroupId: fn.network.security_group.name,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
+
if (fn.storage?.nas && fn.storage.nas.length > 0) {
|
|
54
|
+
config.nasConfig = {
|
|
55
|
+
userId: 10003,
|
|
56
|
+
groupId: 10003,
|
|
57
|
+
mountPoints: fn.storage.nas.map((nas) => ({
|
|
58
|
+
serverAddr: nas.storage_class,
|
|
59
|
+
mountDir: nas.mount_path,
|
|
60
|
+
enableTls: false,
|
|
61
|
+
})),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (fn.log !== undefined) {
|
|
65
|
+
config.logConfig = {
|
|
66
|
+
enableRequestMetrics: fn.log,
|
|
67
|
+
enableInstanceMetrics: fn.log,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
53
70
|
return config;
|
|
54
71
|
};
|
|
55
72
|
exports.functionToFc3Config = functionToFc3Config;
|
|
@@ -65,6 +82,8 @@ const extractFc3Definition = (config, codeHash) => {
|
|
|
65
82
|
vpcConfig: config.vpcConfig ?? null,
|
|
66
83
|
gpuConfig: config.gpuConfig ?? null,
|
|
67
84
|
customContainerConfig: config.customContainerConfig ?? null,
|
|
85
|
+
nasConfig: config.nasConfig ?? null,
|
|
86
|
+
logConfig: config.logConfig ?? null,
|
|
68
87
|
codeHash,
|
|
69
88
|
};
|
|
70
89
|
};
|
|
@@ -30,6 +30,27 @@ const bucketToOssBucketConfig = (bucket) => {
|
|
|
30
30
|
if (bucket.website?.domain) {
|
|
31
31
|
config.domain = bucket.website.domain;
|
|
32
32
|
}
|
|
33
|
+
if (bucket.website?.domain_certificate_id) {
|
|
34
|
+
config.domainCertificateId = bucket.website.domain_certificate_id;
|
|
35
|
+
}
|
|
36
|
+
if (bucket.website?.domain_certificate_body) {
|
|
37
|
+
config.domainCertificateBody = bucket.website.domain_certificate_body;
|
|
38
|
+
}
|
|
39
|
+
if (bucket.website?.domain_certificate_private_key) {
|
|
40
|
+
config.domainCertificatePrivateKey = bucket.website.domain_certificate_private_key;
|
|
41
|
+
}
|
|
42
|
+
if (bucket.website?.domain_protocol) {
|
|
43
|
+
config.domainProtocol = bucket.website.domain_protocol;
|
|
44
|
+
}
|
|
45
|
+
if (bucket.versioning?.status) {
|
|
46
|
+
config.versioningStatus = bucket.versioning.status;
|
|
47
|
+
}
|
|
48
|
+
if (bucket.security?.sse_algorithm) {
|
|
49
|
+
config.sseAlgorithm = bucket.security.sse_algorithm;
|
|
50
|
+
}
|
|
51
|
+
if (bucket.security?.sse_kms_master_key_id) {
|
|
52
|
+
config.sseKmsMasterKeyId = bucket.security.sse_kms_master_key_id;
|
|
53
|
+
}
|
|
33
54
|
return config;
|
|
34
55
|
};
|
|
35
56
|
exports.bucketToOssBucketConfig = bucketToOssBucketConfig;
|
|
@@ -45,6 +66,13 @@ const extractOssBucketDefinition = (config) => {
|
|
|
45
66
|
: {},
|
|
46
67
|
storageClass: config.storageClass ?? null,
|
|
47
68
|
domain: config.domain ?? null,
|
|
69
|
+
domainCertificateId: config.domainCertificateId ?? null,
|
|
70
|
+
domainCertificateBody: config.domainCertificateBody ?? null,
|
|
71
|
+
domainCertificatePrivateKey: config.domainCertificatePrivateKey ? '(managed)' : null,
|
|
72
|
+
domainProtocol: config.domainProtocol ?? null,
|
|
73
|
+
versioningStatus: config.versioningStatus ?? null,
|
|
74
|
+
sseAlgorithm: config.sseAlgorithm ?? null,
|
|
75
|
+
sseKmsMasterKeyId: config.sseKmsMasterKeyId ?? null,
|
|
48
76
|
};
|
|
49
77
|
};
|
|
50
78
|
exports.extractOssBucketDefinition = extractOssBucketDefinition;
|
|
@@ -43,7 +43,12 @@ const tableToTableStoreConfig = (table) => {
|
|
|
43
43
|
instanceName: table.collection,
|
|
44
44
|
tableName: table.name,
|
|
45
45
|
clusterType,
|
|
46
|
+
description: table.desc,
|
|
46
47
|
primaryKey,
|
|
48
|
+
attributes: table.attributes.map((attr) => ({
|
|
49
|
+
name: attr.name,
|
|
50
|
+
type: attr.type,
|
|
51
|
+
})),
|
|
47
52
|
network: table.network,
|
|
48
53
|
};
|
|
49
54
|
// Add reserved throughput if specified
|
|
@@ -55,6 +60,12 @@ const tableToTableStoreConfig = (table) => {
|
|
|
55
60
|
},
|
|
56
61
|
};
|
|
57
62
|
}
|
|
63
|
+
if (table.throughput?.onDemand) {
|
|
64
|
+
config.onDemandThroughput = {
|
|
65
|
+
read: table.throughput.onDemand.read,
|
|
66
|
+
write: table.throughput.onDemand.write,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
58
69
|
// Default table options
|
|
59
70
|
config.tableOptions = {
|
|
60
71
|
timeToLive: -1, // -1 means never expire
|
|
@@ -68,8 +79,11 @@ const extractTableStoreDefinition = (config) => {
|
|
|
68
79
|
instanceName: config.instanceName,
|
|
69
80
|
tableName: config.tableName,
|
|
70
81
|
clusterType: config.clusterType,
|
|
82
|
+
description: config.description ?? null,
|
|
71
83
|
primaryKey: config.primaryKey,
|
|
84
|
+
attributes: config.attributes,
|
|
72
85
|
reservedThroughput: config.reservedThroughput ?? null,
|
|
86
|
+
onDemandThroughput: config.onDemandThroughput ?? null,
|
|
73
87
|
tableOptions: config.tableOptions ?? null,
|
|
74
88
|
network: config.network ?? null,
|
|
75
89
|
};
|
|
@@ -26,6 +26,30 @@ const bucketToCosBucketConfig = (bucket, region) => {
|
|
|
26
26
|
Key: bucket.website.error_page,
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
+
if (bucket.website.domain) {
|
|
30
|
+
config.Domain = bucket.website.domain;
|
|
31
|
+
}
|
|
32
|
+
if (bucket.website.domain_certificate_id) {
|
|
33
|
+
config.DomainCertificateId = bucket.website.domain_certificate_id;
|
|
34
|
+
}
|
|
35
|
+
if (bucket.website.domain_certificate_body) {
|
|
36
|
+
config.DomainCertificateBody = bucket.website.domain_certificate_body;
|
|
37
|
+
}
|
|
38
|
+
if (bucket.website.domain_certificate_private_key) {
|
|
39
|
+
config.DomainCertificatePrivateKey = bucket.website.domain_certificate_private_key;
|
|
40
|
+
}
|
|
41
|
+
if (bucket.website.domain_protocol) {
|
|
42
|
+
config.DomainProtocol = bucket.website.domain_protocol;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (bucket.versioning?.status) {
|
|
46
|
+
config.VersioningStatus = bucket.versioning.status;
|
|
47
|
+
}
|
|
48
|
+
if (bucket.security?.sse_algorithm) {
|
|
49
|
+
config.SseAlgorithm = bucket.security.sse_algorithm;
|
|
50
|
+
}
|
|
51
|
+
if (bucket.security?.sse_kms_master_key_id) {
|
|
52
|
+
config.SseKmsMasterKeyId = bucket.security.sse_kms_master_key_id;
|
|
29
53
|
}
|
|
30
54
|
return config;
|
|
31
55
|
};
|
|
@@ -41,6 +65,14 @@ const extractCosBucketDefinition = (config) => {
|
|
|
41
65
|
errorDocument: config.WebsiteConfiguration.ErrorDocument?.Key ?? null,
|
|
42
66
|
}
|
|
43
67
|
: {},
|
|
68
|
+
domain: config.Domain ?? null,
|
|
69
|
+
domainCertificateId: config.DomainCertificateId ?? null,
|
|
70
|
+
domainCertificateBody: config.DomainCertificateBody ?? null,
|
|
71
|
+
domainCertificatePrivateKey: config.DomainCertificatePrivateKey ? '(managed)' : null,
|
|
72
|
+
domainProtocol: config.DomainProtocol ?? null,
|
|
73
|
+
versioningStatus: config.VersioningStatus ?? null,
|
|
74
|
+
sseAlgorithm: config.SseAlgorithm ?? null,
|
|
75
|
+
sseKmsMasterKeyId: config.SseKmsMasterKeyId ?? null,
|
|
44
76
|
};
|
|
45
77
|
};
|
|
46
78
|
exports.extractCosBucketDefinition = extractCosBucketDefinition;
|
|
@@ -18,6 +18,31 @@ const functionToScfConfig = (fn) => {
|
|
|
18
18
|
})),
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
+
if (fn.network) {
|
|
22
|
+
config.VpcConfig = {
|
|
23
|
+
VpcId: fn.network.vpc_id,
|
|
24
|
+
SubnetId: fn.network.subnet_ids[0],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (fn.storage?.disk) {
|
|
28
|
+
config.DiskSize = fn.storage.disk;
|
|
29
|
+
}
|
|
30
|
+
if (fn.storage?.nas && fn.storage.nas.length > 0) {
|
|
31
|
+
config.CfsConfig = {
|
|
32
|
+
CfsInsList: fn.storage.nas.map((nas) => ({
|
|
33
|
+
LocalMountDir: nas.mount_path,
|
|
34
|
+
RemoteMountDir: '/',
|
|
35
|
+
})),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (fn.gpu) {
|
|
39
|
+
config.UseGpu = 'TRUE';
|
|
40
|
+
}
|
|
41
|
+
if (fn.container) {
|
|
42
|
+
config.ImageConfig = {
|
|
43
|
+
ImageUri: fn.container.image,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
21
46
|
return config;
|
|
22
47
|
};
|
|
23
48
|
exports.functionToScfConfig = functionToScfConfig;
|
|
@@ -31,6 +56,11 @@ const extractScfDefinition = (config, codeHash) => {
|
|
|
31
56
|
timeout: config.Timeout,
|
|
32
57
|
environment: envMap,
|
|
33
58
|
codeHash,
|
|
59
|
+
vpcConfig: config.VpcConfig ?? null,
|
|
60
|
+
diskSize: config.DiskSize ?? null,
|
|
61
|
+
cfsConfig: config.CfsConfig ?? null,
|
|
62
|
+
useGpu: config.UseGpu ?? null,
|
|
63
|
+
imageConfig: config.ImageConfig ?? null,
|
|
34
64
|
};
|
|
35
65
|
};
|
|
36
66
|
exports.extractScfDefinition = extractScfDefinition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geek-fun/serverlessinsight",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.8",
|
|
4
4
|
"description": "Full life cycle cross providers serverless application management for your fast-growing business.",
|
|
5
5
|
"homepage": "https://serverlessinsight.geekfun.club",
|
|
6
6
|
"main": "dist/src/index.js",
|