@geek-fun/serverlessinsight 0.6.7 → 0.6.9
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/domainUtils.js +19 -1
- package/dist/src/common/imsClient.js +6 -2
- package/dist/src/lang/en.js +6 -0
- package/dist/src/lang/zh-CN.js +8 -2
- package/dist/src/parser/bucketParser.js +5 -2
- package/dist/src/parser/eventParser.js +7 -1
- package/dist/src/stack/aliyunStack/apigwPlanner.js +1 -7
- package/dist/src/stack/aliyunStack/apigwResource.js +100 -28
- package/dist/src/stack/aliyunStack/apigwTypes.js +15 -1
- 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/ossResource.js +86 -27
- package/dist/src/stack/aliyunStack/ossTypes.js +32 -0
- package/dist/src/stack/aliyunStack/tablestoreTypes.js +14 -0
- package/dist/src/stack/scfStack/cosResource.js +91 -29
- package/dist/src/stack/scfStack/cosTypes.js +36 -0
- package/dist/src/stack/scfStack/scfTypes.js +30 -0
- package/dist/src/validator/bucketSchema.js +2 -0
- package/dist/src/validator/eventSchema.js +1 -0
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ const common_1 = require("../../common");
|
|
|
8
8
|
const certUtils_1 = require("../../common/certUtils");
|
|
9
9
|
const logger_1 = require("../../common/logger");
|
|
10
10
|
const lang_1 = require("../../lang");
|
|
11
|
+
const domainUtils_1 = require("../../common/domainUtils");
|
|
11
12
|
const buildApigwGroupInstanceFromProvider = (info, stage) => {
|
|
12
13
|
return {
|
|
13
14
|
type: 'ALIYUN_APIGW_GROUP',
|
|
@@ -130,13 +131,7 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
130
131
|
path: t.path,
|
|
131
132
|
backend: t.backend,
|
|
132
133
|
})),
|
|
133
|
-
domain: event.domain
|
|
134
|
-
? {
|
|
135
|
-
domainName: event.domain.domain_name,
|
|
136
|
-
hasCertificate: !!(event.domain.certificate_body || event.domain.certificate_id),
|
|
137
|
-
protocol: event.domain.protocol ?? null,
|
|
138
|
-
}
|
|
139
|
-
: null,
|
|
134
|
+
domain: (0, apigwTypes_1.extractEventDomainDefinition)(event.domain),
|
|
140
135
|
},
|
|
141
136
|
instances,
|
|
142
137
|
lastUpdated: new Date().toISOString(),
|
|
@@ -170,13 +165,7 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
170
165
|
path: t.path,
|
|
171
166
|
backend: t.backend,
|
|
172
167
|
})),
|
|
173
|
-
domain: event.domain
|
|
174
|
-
? {
|
|
175
|
-
domainName: event.domain.domain_name,
|
|
176
|
-
hasCertificate: !!(event.domain.certificate_body || event.domain.certificate_id),
|
|
177
|
-
protocol: event.domain.protocol ?? null,
|
|
178
|
-
}
|
|
179
|
-
: null,
|
|
168
|
+
domain: (0, apigwTypes_1.extractEventDomainDefinition)(event.domain),
|
|
180
169
|
},
|
|
181
170
|
instances,
|
|
182
171
|
lastUpdated: new Date().toISOString(),
|
|
@@ -185,8 +174,22 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
185
174
|
}
|
|
186
175
|
if (event.domain) {
|
|
187
176
|
try {
|
|
177
|
+
const primaryDomain = event.domain.domain_name;
|
|
178
|
+
const wwwBindApex = event.domain.www_bind_apex === true;
|
|
188
179
|
const domainConfig = await buildDomainBindingConfig(event.domain, groupId, serviceName, event.key, context.stage, client);
|
|
189
180
|
state = await client.apigw.bindCustomDomain(domainConfig, state, logicalId);
|
|
181
|
+
const wwwDomain = wwwBindApex ? (0, domainUtils_1.deriveWwwDomain)(primaryDomain) : null;
|
|
182
|
+
if (wwwDomain) {
|
|
183
|
+
logger_1.logger.info(lang_1.lang.__('APIGW_BINDING_DOMAIN', { domain: wwwDomain }));
|
|
184
|
+
const wwwDomainConfig = {
|
|
185
|
+
...domainConfig,
|
|
186
|
+
domainName: wwwDomain,
|
|
187
|
+
certificateName: domainConfig.certificateName
|
|
188
|
+
? `${domainConfig.certificateName}-www`
|
|
189
|
+
: undefined,
|
|
190
|
+
};
|
|
191
|
+
state = await client.apigw.bindCustomDomain(wwwDomainConfig, state, logicalId);
|
|
192
|
+
}
|
|
190
193
|
}
|
|
191
194
|
catch (error) {
|
|
192
195
|
logger_1.logger.error(lang_1.lang.__('APIGW_DOMAIN_BINDING_FAILED', { error: String(error) }));
|
|
@@ -206,13 +209,7 @@ const createApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
206
209
|
path: t.path,
|
|
207
210
|
backend: t.backend,
|
|
208
211
|
})),
|
|
209
|
-
domain: event.domain
|
|
210
|
-
? {
|
|
211
|
-
domainName: event.domain.domain_name,
|
|
212
|
-
hasCertificate: !!(event.domain.certificate_body || event.domain.certificate_id),
|
|
213
|
-
protocol: event.domain.protocol ?? null,
|
|
214
|
-
}
|
|
215
|
-
: null,
|
|
212
|
+
domain: (0, apigwTypes_1.extractEventDomainDefinition)(event.domain),
|
|
216
213
|
},
|
|
217
214
|
instances,
|
|
218
215
|
lastUpdated: new Date().toISOString(),
|
|
@@ -301,8 +298,65 @@ const updateApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
301
298
|
}
|
|
302
299
|
}
|
|
303
300
|
if (event.domain) {
|
|
301
|
+
const primaryDomain = event.domain.domain_name;
|
|
302
|
+
const wwwBindApex = event.domain.www_bind_apex === true;
|
|
303
|
+
const existingDomain = existingState.definition?.domain;
|
|
304
|
+
const previousWwwBindApex = existingDomain?.wwwBindApex === true;
|
|
305
|
+
const previousDomainName = existingDomain?.domainName;
|
|
304
306
|
const domainConfig = await buildDomainBindingConfig(event.domain, groupId, serviceName, event.key, context.stage, client);
|
|
305
307
|
state = await client.apigw.bindCustomDomain(domainConfig, state, logicalId);
|
|
308
|
+
const wwwDomain = wwwBindApex ? (0, domainUtils_1.deriveWwwDomain)(primaryDomain) : null;
|
|
309
|
+
if (wwwDomain) {
|
|
310
|
+
logger_1.logger.info(lang_1.lang.__('APIGW_BINDING_DOMAIN', { domain: wwwDomain }));
|
|
311
|
+
const wwwDomainConfig = {
|
|
312
|
+
...domainConfig,
|
|
313
|
+
domainName: wwwDomain,
|
|
314
|
+
certificateName: domainConfig.certificateName
|
|
315
|
+
? `${domainConfig.certificateName}-www`
|
|
316
|
+
: undefined,
|
|
317
|
+
};
|
|
318
|
+
state = await client.apigw.bindCustomDomain(wwwDomainConfig, state, logicalId);
|
|
319
|
+
}
|
|
320
|
+
if (previousWwwBindApex && previousDomainName) {
|
|
321
|
+
const previousWwwDomain = (0, domainUtils_1.deriveWwwDomain)(previousDomainName);
|
|
322
|
+
if (previousWwwDomain && previousWwwDomain !== wwwDomain) {
|
|
323
|
+
try {
|
|
324
|
+
await client.apigw.unbindCustomDomain(groupId, previousWwwDomain);
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
logger_1.logger.warn(lang_1.lang.__('APIGW_WWW_DOMAIN_UNBIND_FAILED', {
|
|
328
|
+
domain: previousWwwDomain,
|
|
329
|
+
error: String(error),
|
|
330
|
+
}));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
const existingDomain = existingState.definition?.domain;
|
|
337
|
+
if (existingDomain?.domainName) {
|
|
338
|
+
const previousDomain = existingDomain.domainName;
|
|
339
|
+
try {
|
|
340
|
+
await client.apigw.unbindCustomDomain(groupId, previousDomain);
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
logger_1.logger.warn(lang_1.lang.__('APIGW_DOMAIN_UNBIND_FAILED', { domain: previousDomain, error: String(error) }));
|
|
344
|
+
}
|
|
345
|
+
if (existingDomain.wwwBindApex === true) {
|
|
346
|
+
const previousWwwDomain = (0, domainUtils_1.deriveWwwDomain)(previousDomain);
|
|
347
|
+
if (previousWwwDomain) {
|
|
348
|
+
try {
|
|
349
|
+
await client.apigw.unbindCustomDomain(groupId, previousWwwDomain);
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
logger_1.logger.warn(lang_1.lang.__('APIGW_WWW_DOMAIN_UNBIND_FAILED', {
|
|
353
|
+
domain: previousWwwDomain,
|
|
354
|
+
error: String(error),
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
306
360
|
}
|
|
307
361
|
const groupDefinition = (0, apigwTypes_1.extractApigwGroupDefinition)(groupConfig);
|
|
308
362
|
const resourceState = {
|
|
@@ -315,13 +369,7 @@ const updateApigwResource = async (context, event, serviceName, roleArn, state)
|
|
|
315
369
|
path: t.path,
|
|
316
370
|
backend: t.backend,
|
|
317
371
|
})),
|
|
318
|
-
domain: event.domain
|
|
319
|
-
? {
|
|
320
|
-
domainName: event.domain.domain_name,
|
|
321
|
-
hasCertificate: !!(event.domain.certificate_body || event.domain.certificate_id),
|
|
322
|
-
protocol: event.domain.protocol ?? null,
|
|
323
|
-
}
|
|
324
|
-
: null,
|
|
372
|
+
domain: (0, apigwTypes_1.extractEventDomainDefinition)(event.domain),
|
|
325
373
|
},
|
|
326
374
|
instances,
|
|
327
375
|
lastUpdated: new Date().toISOString(),
|
|
@@ -344,6 +392,30 @@ const deleteApigwResource = async (context, logicalId, state) => {
|
|
|
344
392
|
}
|
|
345
393
|
const groupId = groupInstance.id;
|
|
346
394
|
state = await cleanupDnsRecords(context, logicalId, state);
|
|
395
|
+
const existingDomain = existingState.definition?.domain;
|
|
396
|
+
if (existingDomain?.domainName) {
|
|
397
|
+
const primaryDomain = existingDomain.domainName;
|
|
398
|
+
try {
|
|
399
|
+
await client.apigw.unbindCustomDomain(groupId, primaryDomain);
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
logger_1.logger.warn(lang_1.lang.__('APIGW_DOMAIN_UNBIND_FAILED', { domain: primaryDomain, error: String(error) }));
|
|
403
|
+
}
|
|
404
|
+
if (existingDomain.wwwBindApex === true) {
|
|
405
|
+
const wwwDomain = (0, domainUtils_1.deriveWwwDomain)(primaryDomain);
|
|
406
|
+
if (wwwDomain) {
|
|
407
|
+
try {
|
|
408
|
+
await client.apigw.unbindCustomDomain(groupId, wwwDomain);
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
logger_1.logger.warn(lang_1.lang.__('APIGW_WWW_DOMAIN_UNBIND_FAILED', {
|
|
412
|
+
domain: wwwDomain,
|
|
413
|
+
error: String(error),
|
|
414
|
+
}));
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
347
419
|
const deployments = existingInstances.filter((i) => i.type === 'ALIYUN_APIGW_DEPLOYMENT');
|
|
348
420
|
for (const deployment of deployments) {
|
|
349
421
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.inferProtocolConfig = exports.extractApigwDeploymentDefinition = exports.extractApigwApiDefinition = exports.extractApigwGroupDefinition = exports.triggerToApigwApiConfig = exports.generateApiKey = exports.eventToApigwGroupConfig = void 0;
|
|
3
|
+
exports.extractEventDomainDefinition = exports.inferProtocolConfig = exports.extractApigwDeploymentDefinition = exports.extractApigwApiDefinition = exports.extractApigwGroupDefinition = exports.triggerToApigwApiConfig = exports.generateApiKey = exports.eventToApigwGroupConfig = void 0;
|
|
4
4
|
const common_1 = require("../../common");
|
|
5
5
|
const lang_1 = require("../../lang");
|
|
6
6
|
/**
|
|
@@ -155,3 +155,17 @@ const inferProtocolConfig = (protocol) => {
|
|
|
155
155
|
return { requestProtocol: protocol };
|
|
156
156
|
};
|
|
157
157
|
exports.inferProtocolConfig = inferProtocolConfig;
|
|
158
|
+
const extractEventDomainDefinition = (domain) => {
|
|
159
|
+
if (!domain) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
domainName: domain.domain_name,
|
|
164
|
+
wwwBindApex: domain.www_bind_apex === true,
|
|
165
|
+
certificateId: domain.certificate_id ?? null,
|
|
166
|
+
certificateBody: domain.certificate_body ?? null,
|
|
167
|
+
certificatePrivateKey: domain.certificate_private_key ? '(managed)' : null,
|
|
168
|
+
protocol: domain.protocol ?? null,
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
exports.extractEventDomainDefinition = extractEventDomainDefinition;
|
|
@@ -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
|
};
|
|
@@ -12,6 +12,7 @@ const ossTypes_1 = require("./ossTypes");
|
|
|
12
12
|
const logger_1 = require("../../common/logger");
|
|
13
13
|
const lang_1 = require("../../lang");
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
const domainUtils_1 = require("../../common/domainUtils");
|
|
15
16
|
const buildOssInstanceFromProvider = (info, sid) => {
|
|
16
17
|
return {
|
|
17
18
|
type: types_1.ResourceTypeEnum.ALIYUN_OSS_BUCKET,
|
|
@@ -149,35 +150,59 @@ const createBucketResource = async (context, bucket, state) => {
|
|
|
149
150
|
let cnameInfo;
|
|
150
151
|
if (bucket.website?.domain) {
|
|
151
152
|
const certificate = await resolveBucketDomainCertificate(bucket, client);
|
|
153
|
+
const primaryDomain = bucket.website.domain;
|
|
154
|
+
const wwwBindApex = bucket.website.www_bind_apex ?? false;
|
|
152
155
|
logger_1.logger.info(lang_1.lang.__('BINDING_CUSTOM_DOMAIN_TO_BUCKET', {
|
|
153
|
-
domain:
|
|
156
|
+
domain: primaryDomain,
|
|
154
157
|
bucketName: config.bucketName,
|
|
155
158
|
}));
|
|
156
159
|
if (certificate) {
|
|
157
160
|
logger_1.logger.info(lang_1.lang.__('OSS_BUCKET_CERT_BINDING', {
|
|
158
|
-
domain:
|
|
161
|
+
domain: primaryDomain,
|
|
159
162
|
bucketName: config.bucketName,
|
|
160
163
|
}));
|
|
161
164
|
}
|
|
162
|
-
cnameInfo = await client.oss.bindCustomDomain(config.bucketName,
|
|
165
|
+
cnameInfo = await client.oss.bindCustomDomain(config.bucketName, primaryDomain, certificate);
|
|
163
166
|
if (cnameInfo) {
|
|
164
|
-
const instanceId = cnameInfo.dnsRecordId ??
|
|
167
|
+
const instanceId = cnameInfo.dnsRecordId ?? primaryDomain;
|
|
165
168
|
const dnsInstance = {
|
|
166
169
|
sid: (0, common_1.buildSid)('aliyun', 'alidns', context.stage, instanceId),
|
|
167
170
|
id: instanceId,
|
|
168
171
|
type: types_1.ResourceTypeEnum.ALIYUN_OSS_DNS_CNAME,
|
|
169
|
-
domain:
|
|
172
|
+
domain: primaryDomain,
|
|
170
173
|
cname: cnameInfo.cname,
|
|
171
174
|
...(cnameInfo.dnsRecordId ? { dnsRecordId: cnameInfo.dnsRecordId } : {}),
|
|
172
175
|
...(cnameInfo.txtRecordId ? { txtRecordId: cnameInfo.txtRecordId } : {}),
|
|
173
176
|
};
|
|
174
177
|
instances.push(dnsInstance);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
}
|
|
179
|
+
const wwwDomain = wwwBindApex ? (0, domainUtils_1.deriveWwwDomain)(primaryDomain) : null;
|
|
180
|
+
if (wwwDomain) {
|
|
181
|
+
logger_1.logger.info(lang_1.lang.__('BINDING_CUSTOM_DOMAIN_TO_BUCKET', {
|
|
182
|
+
domain: wwwDomain,
|
|
183
|
+
bucketName: config.bucketName,
|
|
184
|
+
}));
|
|
185
|
+
const wwwCnameInfo = await client.oss.bindCustomDomain(config.bucketName, wwwDomain, certificate);
|
|
186
|
+
if (wwwCnameInfo) {
|
|
187
|
+
const wwwInstanceId = wwwCnameInfo.dnsRecordId ?? wwwDomain;
|
|
188
|
+
const wwwDnsInstance = {
|
|
189
|
+
sid: (0, common_1.buildSid)('aliyun', 'alidns', context.stage, wwwInstanceId),
|
|
190
|
+
id: wwwInstanceId,
|
|
191
|
+
type: types_1.ResourceTypeEnum.ALIYUN_OSS_DNS_CNAME,
|
|
192
|
+
domain: wwwDomain,
|
|
193
|
+
cname: wwwCnameInfo.cname,
|
|
194
|
+
isWwwVariant: true,
|
|
195
|
+
...(wwwCnameInfo.dnsRecordId ? { dnsRecordId: wwwCnameInfo.dnsRecordId } : {}),
|
|
196
|
+
...(wwwCnameInfo.txtRecordId ? { txtRecordId: wwwCnameInfo.txtRecordId } : {}),
|
|
197
|
+
};
|
|
198
|
+
instances.push(wwwDnsInstance);
|
|
179
199
|
}
|
|
180
200
|
}
|
|
201
|
+
// Refresh bucket info to capture auto-added CORS rule
|
|
202
|
+
bucketInfo = await client.oss.getBucket(config.bucketName);
|
|
203
|
+
if (bucketInfo) {
|
|
204
|
+
instances[0] = buildOssInstanceFromProvider(bucketInfo, sid);
|
|
205
|
+
}
|
|
181
206
|
}
|
|
182
207
|
// Upload static files if code path is specified
|
|
183
208
|
if (bucket.website?.code) {
|
|
@@ -236,46 +261,78 @@ const updateBucketResource = async (context, bucket, state) => {
|
|
|
236
261
|
const logicalId = `buckets.${bucket.key}`;
|
|
237
262
|
const instances = [buildOssInstanceFromProvider(bucketInfo, sid)];
|
|
238
263
|
const existingState = state.resources[logicalId];
|
|
239
|
-
const
|
|
264
|
+
const existingDnsInstances = existingState?.instances?.filter((i) => i.type === types_1.ResourceTypeEnum.ALIYUN_OSS_DNS_CNAME);
|
|
265
|
+
const existingPrimaryDnsInstance = existingDnsInstances?.find((i) => !i.isWwwVariant);
|
|
266
|
+
const existingWwwDnsInstance = existingDnsInstances?.find((i) => i.isWwwVariant);
|
|
240
267
|
let cnameInfo;
|
|
241
268
|
if (bucket.website?.domain) {
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
269
|
+
const primaryDomain = bucket.website.domain;
|
|
270
|
+
const wwwBindApex = bucket.website.www_bind_apex ?? false;
|
|
271
|
+
const domainChanged = existingPrimaryDnsInstance?.domain !== primaryDomain;
|
|
272
|
+
if (domainChanged && existingDnsInstances) {
|
|
273
|
+
for (const instance of existingDnsInstances) {
|
|
274
|
+
await client.oss.unbindCustomDomain(config.bucketName, instance.domain, instance.dnsRecordId, instance.txtRecordId);
|
|
275
|
+
}
|
|
245
276
|
}
|
|
246
277
|
const certificate = await resolveBucketDomainCertificate(bucket, client);
|
|
247
278
|
logger_1.logger.info(lang_1.lang.__('BINDING_CUSTOM_DOMAIN_TO_BUCKET', {
|
|
248
|
-
domain:
|
|
279
|
+
domain: primaryDomain,
|
|
249
280
|
bucketName: config.bucketName,
|
|
250
281
|
}));
|
|
251
282
|
if (certificate) {
|
|
252
283
|
logger_1.logger.info(lang_1.lang.__('OSS_BUCKET_CERT_BINDING', {
|
|
253
|
-
domain:
|
|
284
|
+
domain: primaryDomain,
|
|
254
285
|
bucketName: config.bucketName,
|
|
255
286
|
}));
|
|
256
287
|
}
|
|
257
|
-
cnameInfo = await client.oss.bindCustomDomain(config.bucketName,
|
|
288
|
+
cnameInfo = await client.oss.bindCustomDomain(config.bucketName, primaryDomain, certificate);
|
|
258
289
|
if (cnameInfo) {
|
|
259
|
-
const instanceId = cnameInfo.dnsRecordId ??
|
|
290
|
+
const instanceId = cnameInfo.dnsRecordId ?? primaryDomain;
|
|
260
291
|
const dnsInstance = {
|
|
261
292
|
sid: (0, common_1.buildSid)('aliyun', 'alidns', context.stage, instanceId),
|
|
262
293
|
id: instanceId,
|
|
263
294
|
type: types_1.ResourceTypeEnum.ALIYUN_OSS_DNS_CNAME,
|
|
264
|
-
domain:
|
|
295
|
+
domain: primaryDomain,
|
|
265
296
|
cname: cnameInfo.cname,
|
|
266
297
|
...(cnameInfo.dnsRecordId ? { dnsRecordId: cnameInfo.dnsRecordId } : {}),
|
|
267
298
|
...(cnameInfo.txtRecordId ? { txtRecordId: cnameInfo.txtRecordId } : {}),
|
|
268
299
|
};
|
|
269
300
|
instances.push(dnsInstance);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
301
|
+
}
|
|
302
|
+
const wwwDomain = wwwBindApex ? (0, domainUtils_1.deriveWwwDomain)(primaryDomain) : null;
|
|
303
|
+
if (wwwDomain) {
|
|
304
|
+
logger_1.logger.info(lang_1.lang.__('BINDING_CUSTOM_DOMAIN_TO_BUCKET', {
|
|
305
|
+
domain: wwwDomain,
|
|
306
|
+
bucketName: config.bucketName,
|
|
307
|
+
}));
|
|
308
|
+
const wwwCnameInfo = await client.oss.bindCustomDomain(config.bucketName, wwwDomain, certificate);
|
|
309
|
+
if (wwwCnameInfo) {
|
|
310
|
+
const wwwInstanceId = wwwCnameInfo.dnsRecordId ?? wwwDomain;
|
|
311
|
+
const wwwDnsInstance = {
|
|
312
|
+
sid: (0, common_1.buildSid)('aliyun', 'alidns', context.stage, wwwInstanceId),
|
|
313
|
+
id: wwwInstanceId,
|
|
314
|
+
type: types_1.ResourceTypeEnum.ALIYUN_OSS_DNS_CNAME,
|
|
315
|
+
domain: wwwDomain,
|
|
316
|
+
cname: wwwCnameInfo.cname,
|
|
317
|
+
isWwwVariant: true,
|
|
318
|
+
...(wwwCnameInfo.dnsRecordId ? { dnsRecordId: wwwCnameInfo.dnsRecordId } : {}),
|
|
319
|
+
...(wwwCnameInfo.txtRecordId ? { txtRecordId: wwwCnameInfo.txtRecordId } : {}),
|
|
320
|
+
};
|
|
321
|
+
instances.push(wwwDnsInstance);
|
|
274
322
|
}
|
|
275
323
|
}
|
|
324
|
+
else if (existingWwwDnsInstance && !wwwBindApex) {
|
|
325
|
+
await client.oss.unbindCustomDomain(config.bucketName, existingWwwDnsInstance.domain, existingWwwDnsInstance.dnsRecordId, existingWwwDnsInstance.txtRecordId);
|
|
326
|
+
}
|
|
327
|
+
const refreshedInfo = await client.oss.getBucket(config.bucketName);
|
|
328
|
+
if (refreshedInfo) {
|
|
329
|
+
instances[0] = buildOssInstanceFromProvider(refreshedInfo, sid);
|
|
330
|
+
}
|
|
276
331
|
}
|
|
277
|
-
else if (
|
|
278
|
-
|
|
332
|
+
else if (existingDnsInstances) {
|
|
333
|
+
for (const instance of existingDnsInstances) {
|
|
334
|
+
await client.oss.unbindCustomDomain(config.bucketName, instance.domain, instance.dnsRecordId, instance.txtRecordId);
|
|
335
|
+
}
|
|
279
336
|
}
|
|
280
337
|
const resourceState = {
|
|
281
338
|
mode: 'managed',
|
|
@@ -295,9 +352,11 @@ exports.updateBucketResource = updateBucketResource;
|
|
|
295
352
|
const deleteBucketResource = async (context, bucketName, logicalId, state) => {
|
|
296
353
|
const client = (0, aliyunClient_1.createAliyunClient)(context);
|
|
297
354
|
const existingState = state.resources[logicalId];
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
300
|
-
|
|
355
|
+
const dnsInstances = existingState?.instances?.filter((i) => i.type === types_1.ResourceTypeEnum.ALIYUN_OSS_DNS_CNAME);
|
|
356
|
+
if (dnsInstances) {
|
|
357
|
+
for (const dnsInstance of dnsInstances) {
|
|
358
|
+
await client.oss.unbindCustomDomain(bucketName, dnsInstance.domain, dnsInstance.dnsRecordId, dnsInstance.txtRecordId);
|
|
359
|
+
}
|
|
301
360
|
}
|
|
302
361
|
try {
|
|
303
362
|
await client.oss.deleteBucket(bucketName);
|
|
@@ -30,6 +30,30 @@ const bucketToOssBucketConfig = (bucket) => {
|
|
|
30
30
|
if (bucket.website?.domain) {
|
|
31
31
|
config.domain = bucket.website.domain;
|
|
32
32
|
}
|
|
33
|
+
if (bucket.website?.www_bind_apex !== undefined) {
|
|
34
|
+
config.wwwBindApex = bucket.website.www_bind_apex;
|
|
35
|
+
}
|
|
36
|
+
if (bucket.website?.domain_certificate_id) {
|
|
37
|
+
config.domainCertificateId = bucket.website.domain_certificate_id;
|
|
38
|
+
}
|
|
39
|
+
if (bucket.website?.domain_certificate_body) {
|
|
40
|
+
config.domainCertificateBody = bucket.website.domain_certificate_body;
|
|
41
|
+
}
|
|
42
|
+
if (bucket.website?.domain_certificate_private_key) {
|
|
43
|
+
config.domainCertificatePrivateKey = bucket.website.domain_certificate_private_key;
|
|
44
|
+
}
|
|
45
|
+
if (bucket.website?.domain_protocol) {
|
|
46
|
+
config.domainProtocol = bucket.website.domain_protocol;
|
|
47
|
+
}
|
|
48
|
+
if (bucket.versioning?.status) {
|
|
49
|
+
config.versioningStatus = bucket.versioning.status;
|
|
50
|
+
}
|
|
51
|
+
if (bucket.security?.sse_algorithm) {
|
|
52
|
+
config.sseAlgorithm = bucket.security.sse_algorithm;
|
|
53
|
+
}
|
|
54
|
+
if (bucket.security?.sse_kms_master_key_id) {
|
|
55
|
+
config.sseKmsMasterKeyId = bucket.security.sse_kms_master_key_id;
|
|
56
|
+
}
|
|
33
57
|
return config;
|
|
34
58
|
};
|
|
35
59
|
exports.bucketToOssBucketConfig = bucketToOssBucketConfig;
|
|
@@ -45,6 +69,14 @@ const extractOssBucketDefinition = (config) => {
|
|
|
45
69
|
: {},
|
|
46
70
|
storageClass: config.storageClass ?? null,
|
|
47
71
|
domain: config.domain ?? null,
|
|
72
|
+
wwwBindApex: config.wwwBindApex ?? false,
|
|
73
|
+
domainCertificateId: config.domainCertificateId ?? null,
|
|
74
|
+
domainCertificateBody: config.domainCertificateBody ?? null,
|
|
75
|
+
domainCertificatePrivateKey: config.domainCertificatePrivateKey ? '(managed)' : null,
|
|
76
|
+
domainProtocol: config.domainProtocol ?? null,
|
|
77
|
+
versioningStatus: config.versioningStatus ?? null,
|
|
78
|
+
sseAlgorithm: config.sseAlgorithm ?? null,
|
|
79
|
+
sseKmsMasterKeyId: config.sseKmsMasterKeyId ?? null,
|
|
48
80
|
};
|
|
49
81
|
};
|
|
50
82
|
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
|
};
|