@geek-fun/serverlessinsight 0.2.0 → 0.3.0

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.
Files changed (38) hide show
  1. package/dist/package.json +18 -12
  2. package/dist/src/commands/deploy.js +2 -2
  3. package/dist/src/commands/destroy.js +5 -3
  4. package/dist/src/commands/index.js +32 -5
  5. package/dist/src/commands/validate.js +2 -2
  6. package/dist/src/common/actionContext.js +14 -9
  7. package/dist/src/common/base64.js +3 -1
  8. package/dist/src/common/domainHelper.js +10 -0
  9. package/dist/src/common/iacHelper.js +1 -1
  10. package/dist/src/common/index.d.ts +2 -0
  11. package/dist/src/common/index.js +2 -0
  12. package/dist/src/common/rosAssets.js +152 -0
  13. package/dist/src/common/rosClient.js +1 -53
  14. package/dist/src/parser/bucketParser.js +35 -0
  15. package/dist/src/parser/eventParser.js +1 -0
  16. package/dist/src/parser/functionParser.js +12 -3
  17. package/dist/src/parser/index.js +2 -0
  18. package/dist/src/stack/rfsStack/function.js +3 -3
  19. package/dist/src/stack/rosStack/bucket.js +126 -0
  20. package/dist/src/stack/rosStack/event.js +58 -51
  21. package/dist/src/stack/rosStack/function.js +152 -21
  22. package/dist/src/stack/rosStack/index.js +3 -0
  23. package/dist/src/types/domains/bucket.js +9 -0
  24. package/dist/src/types/domains/function.js +19 -0
  25. package/dist/src/types/index.d.ts +6 -0
  26. package/dist/src/types/index.js +1 -0
  27. package/dist/src/validator/bucketSchema.js +76 -0
  28. package/dist/src/validator/eventSchema.js +3 -7
  29. package/dist/src/validator/functionSchema.js +94 -18
  30. package/dist/src/validator/iacSchema.js +2 -0
  31. package/dist/src/validator/rootSchema.js +3 -0
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +18 -12
  34. package/samples/{aliyun-poc-fc.yml → aliyun-poc-api.yml} +9 -20
  35. package/samples/aliyun-poc-bucket.yml +20 -0
  36. package/samples/aliyun-poc-domain.yml +23 -0
  37. package/samples/aliyun-poc-fc-gpu.yml +54 -0
  38. package/samples/huawei-poc-fc.yml +4 -3
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.resolveBuckets = void 0;
40
+ const types_1 = require("../../types");
41
+ const oss = __importStar(require("@alicloud/ros-cdk-oss"));
42
+ const ros = __importStar(require("@alicloud/ros-cdk-core"));
43
+ const common_1 = require("../../common");
44
+ const ossDeployment = __importStar(require("@alicloud/ros-cdk-ossdeployment"));
45
+ const dns = __importStar(require("@alicloud/ros-cdk-dns"));
46
+ const node_path_1 = __importDefault(require("node:path"));
47
+ const ros_cdk_ram_1 = require("@alicloud/ros-cdk-ram");
48
+ const aclMap = new Map([
49
+ [types_1.BucketAccessEnum.PRIVATE, 'private'],
50
+ [types_1.BucketAccessEnum.PUBLIC_READ, 'public-read'],
51
+ [types_1.BucketAccessEnum.PUBLIC_READ_WRITE, 'public-read-write'],
52
+ ]);
53
+ const resolveBuckets = (scope, buckets, context) => {
54
+ if (!buckets) {
55
+ return undefined;
56
+ }
57
+ const bucketSources = buckets.some((bucket) => bucket?.website?.code);
58
+ let siAutoOssDeploymentBucketRole;
59
+ if (bucketSources) {
60
+ siAutoOssDeploymentBucketRole = new ros_cdk_ram_1.RosRole(scope, 'si_auto_od_bucket_role', {
61
+ roleName: ros.Fn.sub('si-auto-od-bucket-role-${ALIYUN::StackId}'),
62
+ description: 'roles created by ServerlessInsight for oss deployment to put files to oss bucket during deployment',
63
+ deletionForce: false,
64
+ ignoreExisting: false,
65
+ assumeRolePolicyDocument: {
66
+ version: '1',
67
+ statement: [
68
+ {
69
+ action: 'sts:AssumeRole',
70
+ effect: 'Allow',
71
+ principal: { service: ['fc.aliyuncs.com'] },
72
+ },
73
+ ],
74
+ },
75
+ policyAttachments: {
76
+ system: ['AliyunOSSFullAccess', 'AliyunLogFullAccess'],
77
+ },
78
+ }, true);
79
+ }
80
+ buckets.forEach((bucket) => {
81
+ const ossBucket = new oss.Bucket(scope, (0, common_1.replaceReference)(bucket.key, context), {
82
+ bucketName: (0, common_1.replaceReference)(bucket.name, context),
83
+ accessControl: aclMap.get((0, common_1.replaceReference)(bucket.security?.acl, context) ?? ''),
84
+ websiteConfigurationV2: bucket.website
85
+ ? {
86
+ indexDocument: {
87
+ type: '0',
88
+ suffix: (0, common_1.replaceReference)(bucket.website.index, context),
89
+ supportSubDir: 'true',
90
+ },
91
+ errorDocument: {
92
+ httpStatus: `${(0, common_1.replaceReference)(bucket.website.error_code, context)}`,
93
+ key: (0, common_1.replaceReference)(bucket.website.error_page, context),
94
+ },
95
+ }
96
+ : undefined,
97
+ });
98
+ if (bucket.website?.code) {
99
+ const filePath = node_path_1.default.resolve(process.cwd(), (0, common_1.replaceReference)(bucket.website.code, context));
100
+ new ossDeployment.BucketDeployment(scope, `si_auto_${bucket.key}_bucket_code_deployment`, {
101
+ sources: (0, common_1.getAssets)(filePath),
102
+ destinationBucket: ossBucket.attrName,
103
+ roleArn: siAutoOssDeploymentBucketRole.attrArn,
104
+ timeout: 3000,
105
+ logMonitoring: false,
106
+ retainOnCreate: false,
107
+ }, true);
108
+ }
109
+ if (bucket.website?.domain) {
110
+ const { rr, domainName } = (0, common_1.splitDomain)(bucket.website.domain);
111
+ new oss.Domain(scope, `${bucket.key}_custom_domain_${(0, common_1.encodeBase64ForRosId)(bucket.website.domain)}`, {
112
+ bucketName: ossBucket.attrName,
113
+ domainName: (0, common_1.replaceReference)(bucket.website.domain, context),
114
+ });
115
+ new dns.DomainRecord(scope, `${bucket.key}_custom_domain_record_${(0, common_1.encodeBase64ForRosId)(bucket.website.domain)}`, {
116
+ domainName: domainName,
117
+ rr,
118
+ type: 'CNAME',
119
+ value: [types_1.BucketAccessEnum.PUBLIC_READ, types_1.BucketAccessEnum.PUBLIC_READ_WRITE].includes(bucket.security?.acl ?? '')
120
+ ? ossBucket.attrDomainName
121
+ : ossBucket.attrInternalDomainName,
122
+ });
123
+ }
124
+ });
125
+ };
126
+ exports.resolveBuckets = resolveBuckets;
@@ -39,14 +39,17 @@ const ram = __importStar(require("@alicloud/ros-cdk-ram"));
39
39
  const common_1 = require("../../common");
40
40
  const agw = __importStar(require("@alicloud/ros-cdk-apigateway"));
41
41
  const lodash_1 = require("lodash");
42
+ const dns = __importStar(require("@alicloud/ros-cdk-dns"));
42
43
  const resolveEvents = (scope, events, tags, context, service) => {
43
44
  if ((0, lodash_1.isEmpty)(events)) {
44
45
  return undefined;
45
46
  }
46
47
  const apiGateway = events.filter((event) => event.type === types_1.EventTypes.API_GATEWAY);
47
- if (apiGateway?.length) {
48
- const gatewayAccessRole = new ram.RosRole(scope, (0, common_1.replaceReference)(`${service}_role`, context), {
49
- roleName: (0, common_1.replaceReference)(`${service}-gateway-access-role`, context),
48
+ if (!apiGateway?.length)
49
+ return;
50
+ apiGateway.forEach((event) => {
51
+ const gatewayAccessRole = new ram.RosRole(scope, (0, common_1.replaceReference)(`${event.key}_role`, context), {
52
+ roleName: (0, common_1.replaceReference)(`${service}-${event.name}-agw-access-role`, context),
50
53
  description: (0, common_1.replaceReference)(`${service} role`, context),
51
54
  assumeRolePolicyDocument: {
52
55
  version: '1',
@@ -62,7 +65,7 @@ const resolveEvents = (scope, events, tags, context, service) => {
62
65
  },
63
66
  policies: [
64
67
  {
65
- policyName: (0, common_1.replaceReference)(`${service}-policy`, context),
68
+ policyName: (0, common_1.replaceReference)(`${service}-${event.name}-policy`, context),
66
69
  policyDocument: {
67
70
  version: '1',
68
71
  statement: [
@@ -82,55 +85,59 @@ const resolveEvents = (scope, events, tags, context, service) => {
82
85
  tags: (0, common_1.replaceReference)(tags, context),
83
86
  passthroughHeaders: 'host',
84
87
  }, true);
85
- // new agw.RosCustomDomain(
86
- // this,
87
- // 'customDomain',
88
- // {
89
- // domainName: 'example.com',
90
- // certificateName: 'example.com',
91
- // certificateBody: 'example.com',
92
- // certificatePrivateKey: 'example.com',
93
- // groupId: apiGatewayGroup.attrGroupId,
94
- // },
95
- // true,
96
- // );
97
- apiGateway.forEach((event) => {
98
- event.triggers.forEach((trigger) => {
99
- const key = (0, common_1.encodeBase64)((0, common_1.replaceReference)(`${trigger.method}_${trigger.path}`, context)).replace(/=+$/, '');
100
- const api = new agw.RosApi(scope, `${event.key}_api_${key}`, {
101
- apiName: (0, common_1.replaceReference)(`${event.name}_api_${key}`, context),
102
- groupId: apiGatewayGroup.attrGroupId,
103
- visibility: 'PRIVATE',
104
- authType: 'ANONYMOUS',
105
- requestConfig: {
106
- requestProtocol: 'HTTP',
107
- requestHttpMethod: (0, common_1.replaceReference)(trigger.method, context),
108
- requestPath: (0, common_1.replaceReference)(trigger.path, context),
109
- requestMode: 'PASSTHROUGH',
110
- },
111
- serviceConfig: {
112
- serviceProtocol: 'FunctionCompute',
113
- functionComputeConfig: {
114
- fcRegionId: context.region,
115
- functionName: (0, common_1.replaceReference)(trigger.backend, context),
116
- roleArn: gatewayAccessRole.attrArn,
117
- fcVersion: '3.0',
118
- method: (0, common_1.replaceReference)(trigger.method, context),
119
- },
88
+ if (event.domain) {
89
+ const dnsRecordRosId = `${event.key}_custom_domain_record_${(0, common_1.encodeBase64ForRosId)(event.domain.domain_name)}`;
90
+ const { domainName, rr } = (0, common_1.splitDomain)(event.domain?.domain_name);
91
+ new dns.DomainRecord(scope, dnsRecordRosId, {
92
+ domainName,
93
+ rr,
94
+ type: 'CNAME',
95
+ value: apiGatewayGroup.attrSubDomain,
96
+ });
97
+ const agwCustomDomain = new agw.RosCustomDomain(scope, `${event.key}_custom_domain_${(0, common_1.encodeBase64ForRosId)(event.domain.domain_name)}`, {
98
+ groupId: apiGatewayGroup.attrGroupId,
99
+ domainName: event.domain.domain_name,
100
+ certificateName: event.domain.certificate_name,
101
+ certificateBody: event.domain.certificate_body,
102
+ certificatePrivateKey: event.domain.certificate_private_key,
103
+ }, true);
104
+ agwCustomDomain.addRosDependency(dnsRecordRosId);
105
+ }
106
+ event.triggers.forEach((trigger) => {
107
+ const key = (0, common_1.encodeBase64ForRosId)((0, common_1.replaceReference)(`${trigger.method}_${trigger.path}`, context));
108
+ const api = new agw.RosApi(scope, `${event.key}_api_${key}`, {
109
+ apiName: (0, common_1.replaceReference)(`${event.name}_api_${key}`, context),
110
+ groupId: apiGatewayGroup.attrGroupId,
111
+ visibility: 'PRIVATE',
112
+ authType: 'ANONYMOUS',
113
+ requestConfig: {
114
+ requestProtocol: 'HTTP',
115
+ requestHttpMethod: (0, common_1.replaceReference)(trigger.method, context),
116
+ requestPath: (0, common_1.replaceReference)(trigger.path, context),
117
+ requestMode: 'PASSTHROUGH',
118
+ },
119
+ serviceConfig: {
120
+ serviceProtocol: 'FunctionCompute',
121
+ functionComputeConfig: {
122
+ fcRegionId: context.region,
123
+ functionName: (0, common_1.replaceReference)(trigger.backend, context),
124
+ roleArn: gatewayAccessRole.attrArn,
125
+ fcVersion: '3.0',
126
+ method: (0, common_1.replaceReference)(trigger.method, context),
120
127
  },
121
- resultSample: 'ServerlessInsight resultSample',
122
- resultType: 'PASSTHROUGH',
123
- tags: (0, common_1.replaceReference)(tags, context),
124
- }, true);
125
- api.addDependsOn(apiGatewayGroup);
126
- new agw.Deployment(scope, `${service}_deployment`, {
127
- apiId: api.attrApiId,
128
- groupId: apiGatewayGroup.attrGroupId,
129
- stageName: 'RELEASE',
130
- description: `${service} Api Gateway deployment`,
131
- });
128
+ },
129
+ resultSample: 'ServerlessInsight resultSample',
130
+ resultType: 'PASSTHROUGH',
131
+ tags: (0, common_1.replaceReference)(tags, context),
132
+ }, true);
133
+ api.addDependsOn(apiGatewayGroup);
134
+ new agw.Deployment(scope, `${service}_deployment`, {
135
+ apiId: api.attrApiId,
136
+ groupId: apiGatewayGroup.attrGroupId,
137
+ stageName: 'RELEASE',
138
+ description: `${service} Api Gateway deployment`,
132
139
  });
133
140
  });
134
- }
141
+ });
135
142
  };
136
143
  exports.resolveEvents = resolveEvents;
@@ -34,16 +34,67 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.resolveFunctions = void 0;
37
+ const types_1 = require("../../types");
37
38
  const common_1 = require("../../common");
38
39
  const fc = __importStar(require("@alicloud/ros-cdk-fc3"));
39
40
  const lodash_1 = require("lodash");
40
41
  const ossDeployment = __importStar(require("@alicloud/ros-cdk-ossdeployment"));
41
42
  const ros = __importStar(require("@alicloud/ros-cdk-core"));
42
43
  const sls = __importStar(require("@alicloud/ros-cdk-sls"));
44
+ const nas = __importStar(require("@alicloud/ros-cdk-nas"));
45
+ const ecs = __importStar(require("@alicloud/ros-cdk-ecs"));
46
+ const storageClassMap = {
47
+ [types_1.NasStorageClassEnum.STANDARD_CAPACITY]: { fileSystemType: 'standard', storageType: 'Capacity' },
48
+ [types_1.NasStorageClassEnum.STANDARD_PERFORMANCE]: {
49
+ fileSystemType: 'standard',
50
+ storageType: 'Performance',
51
+ },
52
+ [types_1.NasStorageClassEnum.EXTREME_STANDARD]: { fileSystemType: 'extreme', storageType: 'standard' },
53
+ [types_1.NasStorageClassEnum.EXTREME_ADVANCE]: { fileSystemType: 'extreme', storageType: 'advance' },
54
+ };
55
+ const securityGroupRangeMap = {
56
+ TCP: '1/65535',
57
+ UDP: '1/65535',
58
+ ICMP: '-1/-1',
59
+ GRE: '-1/-1',
60
+ ALL: '-1/-1',
61
+ };
62
+ const gpuConfigMap = {
63
+ [types_1.FunctionGpuEnum.TESLA_8]: { gpuMemorySize: 8192, gpuType: 'fc.gpu.tesla.1' },
64
+ [types_1.FunctionGpuEnum.TESLA_12]: { gpuMemorySize: 12288, gpuType: 'fc.gpu.tesla.1' },
65
+ [types_1.FunctionGpuEnum.TESLA_16]: { gpuMemorySize: 16384, gpuType: 'fc.gpu.tesla.1' },
66
+ [types_1.FunctionGpuEnum.AMPERE_8]: { gpuMemorySize: 8192, gpuType: 'fc.gpu.ampere.1' },
67
+ [types_1.FunctionGpuEnum.AMPERE_12]: { gpuMemorySize: 12288, gpuType: 'fc.gpu.ampere.1' },
68
+ [types_1.FunctionGpuEnum.AMPERE_16]: { gpuMemorySize: 16384, gpuType: 'fc.gpu.ampere.1' },
69
+ [types_1.FunctionGpuEnum.AMPERE_24]: { gpuMemorySize: 24576, gpuType: 'fc.gpu.ampere.1' },
70
+ [types_1.FunctionGpuEnum.ADA_48]: { gpuMemorySize: 49152, gpuType: 'fc.gpu.ada.1' },
71
+ };
72
+ const transformSecurityRules = (rules, ruleType) => {
73
+ return rules.map((rule) => {
74
+ const [protocol, cidrIp, portRange] = rule.split(':');
75
+ return {
76
+ ipProtocol: protocol.toLowerCase(),
77
+ portRange: portRange.toUpperCase() === 'ALL'
78
+ ? securityGroupRangeMap[protocol.toUpperCase()]
79
+ : portRange.includes('/')
80
+ ? portRange
81
+ : `${portRange}/${portRange}`,
82
+ [ruleType === 'INGRESS' ? 'sourceCidrIp' : 'destCidrIp']: cidrIp,
83
+ };
84
+ });
85
+ };
86
+ const transformGpuConfig = (gpu) => {
87
+ if (!gpu) {
88
+ return undefined;
89
+ }
90
+ return gpuConfigMap[gpu];
91
+ };
43
92
  const resolveFunctions = (scope, functions, tags, context, service) => {
44
93
  if ((0, lodash_1.isEmpty)(functions)) {
45
94
  return undefined;
46
95
  }
96
+ let logConfig = undefined;
97
+ const enableLog = functions?.some(({ log }) => log);
47
98
  const slsService = new sls.Project(scope, `${service}_sls`, { name: `${service}-sls`, tags: (0, common_1.replaceReference)(tags, context) }, true);
48
99
  const slsLogstore = new sls.Logstore(scope, `${service}_sls_logstore`, {
49
100
  logstoreName: `${service}-sls-logstore`,
@@ -55,11 +106,18 @@ const resolveFunctions = (scope, functions, tags, context, service) => {
55
106
  logstoreName: slsLogstore.attrLogstoreName,
56
107
  fullTextIndex: { enable: true },
57
108
  }, true);
109
+ if (enableLog) {
110
+ logConfig = {
111
+ project: slsLogstore.attrProjectName,
112
+ logstore: slsLogstore.attrLogstoreName,
113
+ enableRequestMetrics: true,
114
+ };
115
+ }
58
116
  const fileSources = functions
59
- ?.filter(({ code }) => (0, common_1.readCodeSize)(code) > common_1.CODE_ZIP_SIZE_LIMIT)
117
+ ?.filter(({ code }) => code?.path && (0, common_1.readCodeSize)(code.path) > common_1.CODE_ZIP_SIZE_LIMIT)
60
118
  .map(({ code, name }) => {
61
119
  const fcName = (0, common_1.replaceReference)(name, context);
62
- return { fcName, ...(0, common_1.getFileSource)(fcName, code) };
120
+ return { fcName, ...(0, common_1.getFileSource)(fcName, code.path) };
63
121
  });
64
122
  const destinationBucketName = ros.Fn.sub('si-bootstrap-artifacts-${ALIYUN::AccountId}-${ALIYUN::Region}');
65
123
  const ossDeploymentId = `${service}_artifacts_code_deployment`;
@@ -73,36 +131,109 @@ const resolveFunctions = (scope, functions, tags, context, service) => {
73
131
  }, true);
74
132
  }
75
133
  functions?.forEach((fnc) => {
76
- const storeInBucket = (0, common_1.readCodeSize)(fnc.code) > common_1.CODE_ZIP_SIZE_LIMIT;
77
- let code = {
78
- zipFile: (0, common_1.resolveCode)(fnc.code),
79
- };
80
- if (storeInBucket) {
81
- code = {
82
- ossBucketName: destinationBucketName,
83
- ossObjectName: fileSources?.find(({ fcName }) => fcName === (0, common_1.replaceReference)(fnc.name, context))?.objectKey,
134
+ let runtimeConfig;
135
+ const storeInBucket = !!fnc.code?.path && (0, common_1.readCodeSize)(fnc.code.path) > common_1.CODE_ZIP_SIZE_LIMIT;
136
+ if (fnc.container) {
137
+ runtimeConfig = {
138
+ runtime: 'custom-container',
139
+ handler: 'index.handler',
140
+ customContainerConfig: {
141
+ image: fnc.container.image,
142
+ command: fnc.container.cmd?.split(' '),
143
+ port: fnc.container.port,
144
+ },
145
+ };
146
+ }
147
+ else {
148
+ let code = {
149
+ zipFile: (0, common_1.resolveCode)(fnc.code.path),
150
+ };
151
+ if (storeInBucket) {
152
+ code = {
153
+ ossBucketName: destinationBucketName,
154
+ ossObjectName: fileSources?.find(({ fcName }) => fcName === (0, common_1.replaceReference)(fnc.name, context))?.objectKey,
155
+ };
156
+ }
157
+ runtimeConfig = {
158
+ code,
159
+ handler: (0, common_1.replaceReference)(fnc.code.handler, context),
160
+ runtime: (0, common_1.replaceReference)(fnc.code.runtime, context),
84
161
  };
85
162
  }
163
+ let vpcConfig = undefined;
164
+ if (fnc.network) {
165
+ const securityGroup = new ecs.SecurityGroup(scope, `${fnc.key}_security_group`, {
166
+ securityGroupName: fnc.network.security_group.name,
167
+ vpcId: (0, common_1.replaceReference)(fnc.network.vpc_id, context),
168
+ tags: (0, common_1.replaceReference)(tags, context),
169
+ securityGroupIngress: transformSecurityRules(fnc.network.security_group.ingress, 'INGRESS'),
170
+ securityGroupEgress: transformSecurityRules(fnc.network.security_group.egress, 'EGRESS'),
171
+ }, true);
172
+ vpcConfig = {
173
+ vpcId: (0, common_1.replaceReference)(fnc.network.vpc_id, context),
174
+ vSwitchIds: (0, common_1.replaceReference)(fnc.network.subnet_ids, context),
175
+ securityGroupId: securityGroup.attrSecurityGroupId,
176
+ };
177
+ }
178
+ let fcNas;
179
+ if (fnc.storage?.nas) {
180
+ fcNas = fnc.storage.nas.map((nasItem) => {
181
+ const { fileSystemType, storageType } = storageClassMap[nasItem.storage_class];
182
+ const accessGroup = new nas.AccessGroup(scope, `${fnc.key}_nas_access_${(0, common_1.encodeBase64ForRosId)(nasItem.mount_path)}`, {
183
+ accessGroupName: `${fnc.name}-nas-access-${(0, common_1.encodeBase64ForRosId)(nasItem.mount_path)}`,
184
+ accessGroupType: 'Vpc',
185
+ }, true);
186
+ const nasResource = new nas.FileSystem(scope, `${fnc.key}_nas_${(0, common_1.encodeBase64ForRosId)(nasItem.mount_path)}`, {
187
+ fileSystemType,
188
+ storageType,
189
+ protocolType: 'NFS',
190
+ tags: [
191
+ ...((0, common_1.replaceReference)(tags, context) ?? []),
192
+ { key: 'function-name', value: fnc.name },
193
+ ],
194
+ }, true);
195
+ const nasMountTarget = new nas.MountTarget(scope, `${fnc.key}_nas_mount_${(0, common_1.encodeBase64ForRosId)(nasItem.mount_path)}`, {
196
+ fileSystemId: nasResource.attrFileSystemId,
197
+ networkType: 'Vpc',
198
+ accessGroupName: accessGroup.attrAccessGroupName,
199
+ vpcId: fnc.network.vpc_id,
200
+ vSwitchId: fnc.network.subnet_ids[0],
201
+ }, true);
202
+ return { nas: nasResource, nasMount: nasMountTarget, mountDir: nasItem.mount_path };
203
+ });
204
+ }
86
205
  const fcn = new fc.RosFunction(scope, fnc.key, {
87
206
  functionName: (0, common_1.replaceReference)(fnc.name, context),
88
- handler: (0, common_1.replaceReference)(fnc.handler, context),
89
- runtime: (0, common_1.replaceReference)(fnc.runtime, context),
90
207
  memorySize: (0, common_1.replaceReference)(fnc.memory, context),
208
+ diskSize: fnc.storage?.disk,
209
+ gpuConfig: transformGpuConfig(fnc.gpu),
91
210
  timeout: (0, common_1.replaceReference)(fnc.timeout, context),
92
211
  environmentVariables: (0, common_1.replaceReference)(fnc.environment, context),
93
- code,
94
- logConfig: {
95
- project: slsLogstore.attrProjectName,
96
- logstore: slsLogstore.attrLogstoreName,
97
- enableRequestMetrics: true,
98
- },
212
+ logConfig,
213
+ vpcConfig,
214
+ ...runtimeConfig,
215
+ nasConfig: fcNas?.length
216
+ ? {
217
+ mountPoints: fcNas?.map(({ nasMount, mountDir }) => ({
218
+ mountDir,
219
+ serverAddr: `${nasMount.attrMountTargetDomain}:/`,
220
+ })),
221
+ }
222
+ : undefined,
99
223
  }, true);
100
- fcn.addRosDependency(`${service}_sls`);
101
- fcn.addRosDependency(`${service}_sls_logstore`);
102
- fcn.addRosDependency(`${service}_sls_index`);
224
+ if (enableLog) {
225
+ fcn.addRosDependency(`${service}_sls`);
226
+ fcn.addRosDependency(`${service}_sls_logstore`);
227
+ fcn.addRosDependency(`${service}_sls_index`);
228
+ }
103
229
  if (storeInBucket) {
104
230
  fcn.addRosDependency(`${service}_artifacts_code_deployment`);
105
231
  }
232
+ if (fcNas?.length) {
233
+ fcNas.forEach((nasItem) => {
234
+ fcn.addRosDependency(`${fnc.key}_nas_mount_${(0, common_1.encodeBase64ForRosId)(nasItem.mountDir)}`);
235
+ });
236
+ }
106
237
  });
107
238
  };
108
239
  exports.resolveFunctions = resolveFunctions;
@@ -45,6 +45,7 @@ const stage_1 = require("./stage");
45
45
  const vars_1 = require("./vars");
46
46
  const database_1 = require("./database");
47
47
  const event_1 = require("./event");
48
+ const bucket_1 = require("./bucket");
48
49
  __exportStar(require("./bootstrap"), exports);
49
50
  class RosStack extends ros.Stack {
50
51
  constructor(scope, iac, context) {
@@ -64,6 +65,8 @@ class RosStack extends ros.Stack {
64
65
  (0, event_1.resolveEvents)(this, iac.events, iac.tags, context, this.service);
65
66
  // Define Databases
66
67
  (0, database_1.resolveDatabases)(this, iac.databases, context);
68
+ // Define Buckets
69
+ (0, bucket_1.resolveBuckets)(this, iac.buckets, context);
67
70
  }
68
71
  }
69
72
  exports.RosStack = RosStack;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BucketAccessEnum = void 0;
4
+ var BucketAccessEnum;
5
+ (function (BucketAccessEnum) {
6
+ BucketAccessEnum["PRIVATE"] = "PRIVATE";
7
+ BucketAccessEnum["PUBLIC_READ"] = "PUBLIC_READ";
8
+ BucketAccessEnum["PUBLIC_READ_WRITE"] = "PUBLIC_READ_WRITE";
9
+ })(BucketAccessEnum || (exports.BucketAccessEnum = BucketAccessEnum = {}));
@@ -1,2 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FunctionGpuEnum = exports.NasStorageClassEnum = void 0;
4
+ var NasStorageClassEnum;
5
+ (function (NasStorageClassEnum) {
6
+ NasStorageClassEnum["STANDARD_PERFORMANCE"] = "STANDARD_PERFORMANCE";
7
+ NasStorageClassEnum["STANDARD_CAPACITY"] = "STANDARD_CAPACITY";
8
+ NasStorageClassEnum["EXTREME_STANDARD"] = "EXTREME_STANDARD";
9
+ NasStorageClassEnum["EXTREME_ADVANCE"] = "EXTREME_ADVANCE";
10
+ })(NasStorageClassEnum || (exports.NasStorageClassEnum = NasStorageClassEnum = {}));
11
+ var FunctionGpuEnum;
12
+ (function (FunctionGpuEnum) {
13
+ FunctionGpuEnum["TESLA_8"] = "TESLA_8";
14
+ FunctionGpuEnum["TESLA_12"] = "TESLA_12";
15
+ FunctionGpuEnum["TESLA_16"] = "TESLA_16";
16
+ FunctionGpuEnum["AMPERE_8"] = "AMPERE_8";
17
+ FunctionGpuEnum["AMPERE_12"] = "AMPERE_12";
18
+ FunctionGpuEnum["AMPERE_16"] = "AMPERE_16";
19
+ FunctionGpuEnum["AMPERE_24"] = "AMPERE_24";
20
+ FunctionGpuEnum["ADA_48"] = "ADA_48";
21
+ })(FunctionGpuEnum || (exports.FunctionGpuEnum = FunctionGpuEnum = {}));
@@ -4,12 +4,14 @@ import { EventDomain, EventRaw } from './domains/event';
4
4
  import { DatabaseDomain, DatabaseRaw } from './domains/database';
5
5
  import { FunctionDomain, FunctionRaw } from './domains/function';
6
6
  import { Provider } from './domains/provider';
7
+ import { BucketDomain, BucketRaw } from './domains/bucket';
7
8
  export * from './domains/database';
8
9
  export * from './domains/event';
9
10
  export * from './domains/function';
10
11
  export * from './domains/tag';
11
12
  export * from './domains/vars';
12
13
  export * from './domains/context';
14
+ export * from './domains/bucket';
13
15
  export * from './assets';
14
16
  export type ServerlessIacRaw = {
15
17
  version: string;
@@ -27,6 +29,9 @@ export type ServerlessIacRaw = {
27
29
  databases: {
28
30
  [key: string]: DatabaseRaw;
29
31
  };
32
+ buckets: {
33
+ [key: string]: BucketRaw;
34
+ };
30
35
  };
31
36
  export type ServerlessIac = {
32
37
  version: string;
@@ -41,4 +46,5 @@ export type ServerlessIac = {
41
46
  functions?: Array<FunctionDomain>;
42
47
  events?: Array<EventDomain>;
43
48
  databases?: Array<DatabaseDomain>;
49
+ buckets?: Array<BucketDomain>;
44
50
  };
@@ -20,4 +20,5 @@ __exportStar(require("./domains/function"), exports);
20
20
  __exportStar(require("./domains/tag"), exports);
21
21
  __exportStar(require("./domains/vars"), exports);
22
22
  __exportStar(require("./domains/context"), exports);
23
+ __exportStar(require("./domains/bucket"), exports);
23
24
  __exportStar(require("./assets"), exports);
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bucketSchema = void 0;
4
+ exports.bucketSchema = {
5
+ $id: 'https://serverlessinsight.geekfun.club/schemas/bucketschema.json',
6
+ type: 'object',
7
+ patternProperties: {
8
+ '.*': {
9
+ type: 'object',
10
+ properties: {
11
+ name: {
12
+ type: 'string',
13
+ },
14
+ storage: {
15
+ type: 'object',
16
+ properties: {
17
+ class: {
18
+ type: 'string',
19
+ },
20
+ },
21
+ required: ['class'],
22
+ },
23
+ versioning: {
24
+ type: 'object',
25
+ properties: {
26
+ status: {
27
+ type: 'string',
28
+ },
29
+ },
30
+ required: ['status'],
31
+ },
32
+ security: {
33
+ type: 'object',
34
+ properties: {
35
+ access: {
36
+ type: 'string',
37
+ enum: ['PRIVATE', 'PUBLIC_READ', 'PUBLIC_READ_WRITE'],
38
+ },
39
+ force_delete: {
40
+ type: 'boolean',
41
+ },
42
+ sse_algorithm: {
43
+ type: 'string',
44
+ },
45
+ sse_kms_master_key_id: {
46
+ type: 'string',
47
+ },
48
+ },
49
+ },
50
+ website: {
51
+ type: 'object',
52
+ properties: {
53
+ code: {
54
+ type: 'string',
55
+ },
56
+ domain: {
57
+ type: 'string',
58
+ },
59
+ index: {
60
+ type: 'string',
61
+ },
62
+ error_page: {
63
+ type: 'string',
64
+ },
65
+ error_code: {
66
+ type: 'number',
67
+ },
68
+ },
69
+ required: ['code'],
70
+ },
71
+ },
72
+ required: ['name'],
73
+ additionalProperties: false,
74
+ },
75
+ },
76
+ };