@geek-fun/serverlessinsight 0.4.0 → 0.5.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 (160) hide show
  1. package/.gitattributes +1 -0
  2. package/README.md +108 -8
  3. package/README.zh-CN.md +52 -8
  4. package/dist/package.json +37 -35
  5. package/dist/src/commands/deploy.js +17 -7
  6. package/dist/src/commands/destroy.js +27 -4
  7. package/dist/src/commands/forceUnlock.js +61 -0
  8. package/dist/src/commands/index.js +86 -14
  9. package/dist/src/commands/local.js +10 -1
  10. package/dist/src/commands/plan.js +33 -0
  11. package/dist/src/commands/template.js +3 -1
  12. package/dist/src/commands/validate.js +2 -1
  13. package/dist/src/common/aliyunClient/apigwOperations.js +652 -0
  14. package/dist/src/common/aliyunClient/dnsOperations.js +90 -0
  15. package/dist/src/common/aliyunClient/ecsOperations.js +141 -0
  16. package/dist/src/common/aliyunClient/esOperations.js +219 -0
  17. package/dist/src/common/aliyunClient/fc3Operations.js +270 -0
  18. package/dist/src/common/aliyunClient/index.js +141 -0
  19. package/dist/src/common/aliyunClient/nasOperations.js +233 -0
  20. package/dist/src/common/aliyunClient/ossOperations.js +237 -0
  21. package/dist/src/common/aliyunClient/ramOperations.js +205 -0
  22. package/dist/src/common/aliyunClient/rdsOperations.js +206 -0
  23. package/dist/src/common/aliyunClient/slsOperations.js +218 -0
  24. package/dist/src/common/aliyunClient/tablestoreOperations.js +199 -0
  25. package/dist/src/common/aliyunClient/types.js +2 -0
  26. package/dist/src/common/constants.js +7 -1
  27. package/dist/src/common/context.js +32 -14
  28. package/dist/src/common/credentials.js +39 -0
  29. package/dist/src/common/dependencyGraph/graph.js +280 -0
  30. package/dist/src/common/dependencyGraph/index.js +18 -0
  31. package/dist/src/common/dependencyGraph/types.js +2 -0
  32. package/dist/src/common/fileUtils.js +16 -0
  33. package/dist/src/common/hashUtils.js +121 -0
  34. package/dist/src/common/iacHelper.js +25 -97
  35. package/dist/src/common/imsClient.js +4 -0
  36. package/dist/src/common/index.js +7 -2
  37. package/dist/src/common/lockManager.js +212 -0
  38. package/dist/src/common/logger.js +89 -6
  39. package/dist/src/common/providerEnum.js +2 -3
  40. package/dist/src/common/runtimeMapper.js +160 -0
  41. package/dist/src/common/scfClient.js +84 -0
  42. package/dist/src/common/stateManager.js +107 -0
  43. package/dist/src/common/tencentClient/cosOperations.js +287 -0
  44. package/dist/src/common/tencentClient/esOperations.js +156 -0
  45. package/dist/src/common/tencentClient/index.js +116 -0
  46. package/dist/src/common/tencentClient/scfOperations.js +141 -0
  47. package/dist/src/common/tencentClient/tdsqlcOperations.js +211 -0
  48. package/dist/src/common/tencentClient/types.js +17 -0
  49. package/dist/src/lang/en.js +254 -0
  50. package/dist/src/lang/index.js +28 -8
  51. package/dist/src/lang/zh-CN.js +229 -0
  52. package/dist/src/parser/bucketParser.js +25 -12
  53. package/dist/src/parser/databaseParser.js +14 -10
  54. package/dist/src/parser/functionParser.js +19 -6
  55. package/dist/src/parser/parseUtils.js +74 -0
  56. package/dist/src/parser/tableParser.js +19 -17
  57. package/dist/src/stack/aliyunStack/apigwExecutor.js +84 -0
  58. package/dist/src/stack/aliyunStack/apigwPlanner.js +118 -0
  59. package/dist/src/stack/aliyunStack/apigwResource.js +339 -0
  60. package/dist/src/stack/aliyunStack/apigwTypes.js +125 -0
  61. package/dist/src/stack/aliyunStack/databaseExecutor.js +112 -0
  62. package/dist/src/stack/aliyunStack/databasePlanner.js +128 -0
  63. package/dist/src/stack/aliyunStack/databaseResource.js +228 -0
  64. package/dist/src/stack/aliyunStack/deployer.js +133 -0
  65. package/dist/src/stack/aliyunStack/destroyer.js +114 -0
  66. package/dist/src/stack/aliyunStack/esServerlessTypes.js +141 -0
  67. package/dist/src/stack/aliyunStack/fc3Executor.js +91 -0
  68. package/dist/src/stack/aliyunStack/fc3Planner.js +77 -0
  69. package/dist/src/stack/aliyunStack/fc3Resource.js +511 -0
  70. package/dist/src/stack/aliyunStack/fc3Types.js +76 -0
  71. package/dist/src/stack/aliyunStack/index.js +40 -0
  72. package/dist/src/stack/aliyunStack/ossExecutor.js +91 -0
  73. package/dist/src/stack/aliyunStack/ossPlanner.js +76 -0
  74. package/dist/src/stack/aliyunStack/ossResource.js +196 -0
  75. package/dist/src/stack/aliyunStack/ossTypes.js +50 -0
  76. package/dist/src/stack/aliyunStack/planner.js +37 -0
  77. package/dist/src/stack/aliyunStack/rdsTypes.js +217 -0
  78. package/dist/src/stack/aliyunStack/tablestoreExecutor.js +92 -0
  79. package/dist/src/stack/aliyunStack/tablestorePlanner.js +94 -0
  80. package/dist/src/stack/aliyunStack/tablestoreResource.js +120 -0
  81. package/dist/src/stack/aliyunStack/tablestoreTypes.js +77 -0
  82. package/dist/src/stack/bucketTypes.js +17 -0
  83. package/dist/src/stack/deploy.js +24 -77
  84. package/dist/src/stack/localStack/bucket.js +11 -6
  85. package/dist/src/stack/localStack/event.js +10 -5
  86. package/dist/src/stack/localStack/function.js +13 -7
  87. package/dist/src/stack/localStack/functionRunner.js +1 -1
  88. package/dist/src/stack/localStack/localServer.js +7 -6
  89. package/dist/src/stack/scfStack/cosExecutor.js +91 -0
  90. package/dist/src/stack/scfStack/cosPlanner.js +76 -0
  91. package/dist/src/stack/scfStack/cosResource.js +126 -0
  92. package/dist/src/stack/scfStack/cosTypes.js +46 -0
  93. package/dist/src/stack/scfStack/deployer.js +91 -0
  94. package/dist/src/stack/scfStack/destroyer.js +88 -0
  95. package/dist/src/stack/scfStack/esServerlessExecutor.js +105 -0
  96. package/dist/src/stack/scfStack/esServerlessPlanner.js +86 -0
  97. package/dist/src/stack/scfStack/esServerlessResource.js +94 -0
  98. package/dist/src/stack/scfStack/esServerlessTypes.js +48 -0
  99. package/dist/src/stack/scfStack/index.js +35 -0
  100. package/dist/src/stack/scfStack/planner.js +91 -0
  101. package/dist/src/stack/scfStack/scfExecutor.js +91 -0
  102. package/dist/src/stack/scfStack/scfPlanner.js +78 -0
  103. package/dist/src/stack/scfStack/scfResource.js +216 -0
  104. package/dist/src/stack/scfStack/scfTypes.js +41 -0
  105. package/dist/src/stack/scfStack/tdsqlcExecutor.js +105 -0
  106. package/dist/src/stack/scfStack/tdsqlcPlanner.js +90 -0
  107. package/dist/src/stack/scfStack/tdsqlcResource.js +146 -0
  108. package/dist/src/stack/scfStack/tdsqlcTypes.js +59 -0
  109. package/dist/src/types/domains/lock.js +2 -0
  110. package/dist/src/types/domains/resolvable.js +2 -0
  111. package/dist/src/types/domains/state.js +19 -0
  112. package/dist/src/types/index.js +4 -0
  113. package/dist/src/validator/bucketSchema.js +4 -10
  114. package/dist/src/validator/databaseSchema.js +36 -36
  115. package/dist/src/validator/eventSchema.js +3 -2
  116. package/dist/src/validator/functionSchema.js +51 -46
  117. package/dist/src/validator/iacSchema.js +52 -3
  118. package/dist/src/validator/rootSchema.js +47 -1
  119. package/dist/src/validator/tableschema.js +9 -8
  120. package/dist/src/validator/templateRefSchema.js +23 -0
  121. package/dist/tsconfig.tsbuildinfo +1 -1
  122. package/package.json +37 -35
  123. package/samples/README_TENCENT_COS.md +486 -0
  124. package/samples/README_TENCENT_SCF.md +272 -0
  125. package/samples/aliyun-poc-api.yml +1 -1
  126. package/samples/aliyun-poc-bucket.yml +0 -1
  127. package/samples/aliyun-poc-domain.yml +0 -1
  128. package/samples/aliyun-poc-es.yml +14 -13
  129. package/samples/aliyun-poc-rds.yml +0 -2
  130. package/samples/aliyun-poc-table.yml +1 -3
  131. package/samples/tencent-poc-cos.yml +20 -0
  132. package/samples/tencent-poc-scf.yml +36 -0
  133. package/dist/src/commands/index.d.ts +0 -2
  134. package/dist/src/common/index.d.ts +0 -11
  135. package/dist/src/common/rosAssets.js +0 -178
  136. package/dist/src/common/rosClient.js +0 -198
  137. package/dist/src/index.d.ts +0 -1
  138. package/dist/src/lang/index.d.ts +0 -3
  139. package/dist/src/parser/index.d.ts +0 -3
  140. package/dist/src/stack/index.d.ts +0 -1
  141. package/dist/src/stack/localStack/index.d.ts +0 -5
  142. package/dist/src/stack/rfsStack/index.d.ts +0 -9
  143. package/dist/src/stack/rosStack/bootstrap.js +0 -187
  144. package/dist/src/stack/rosStack/bucket.js +0 -127
  145. package/dist/src/stack/rosStack/database.js +0 -313
  146. package/dist/src/stack/rosStack/event.js +0 -143
  147. package/dist/src/stack/rosStack/function.js +0 -259
  148. package/dist/src/stack/rosStack/index.d.ts +0 -7
  149. package/dist/src/stack/rosStack/index.js +0 -75
  150. package/dist/src/stack/rosStack/stage.js +0 -46
  151. package/dist/src/stack/rosStack/table.js +0 -95
  152. package/dist/src/stack/rosStack/tag.js +0 -11
  153. package/dist/src/stack/rosStack/vars.js +0 -49
  154. package/dist/src/types/index.d.ts +0 -55
  155. package/dist/src/types/localStack/index.d.ts +0 -81
  156. package/dist/src/validator/index.d.ts +0 -1
  157. package/layers/si-bootstrap-sdk/Dockerfile-aliyuncli +0 -12
  158. package/layers/si-bootstrap-sdk/README.md +0 -1
  159. package/layers/si-bootstrap-sdk/package-lock.json +0 -875
  160. package/layers/si-bootstrap-sdk/package.json +0 -33
@@ -0,0 +1,237 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createOssOperations = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const createOssOperations = (ossClient, region) => {
10
+ const useBucket = (bucketName) => {
11
+ ossClient.useBucket(bucketName);
12
+ };
13
+ return {
14
+ createBucket: async (config) => {
15
+ if (config.storageClass) {
16
+ await ossClient.putBucket(config.bucketName, {
17
+ storageClass: config.storageClass,
18
+ });
19
+ }
20
+ else {
21
+ await ossClient.putBucket(config.bucketName);
22
+ }
23
+ // Set ACL if specified
24
+ if (config.acl) {
25
+ useBucket(config.bucketName);
26
+ await ossClient.putBucketACL(config.bucketName, config.acl);
27
+ }
28
+ // Set website configuration if specified
29
+ if (config.websiteConfig) {
30
+ useBucket(config.bucketName);
31
+ await ossClient.putBucketWebsite(config.bucketName, {
32
+ index: config.websiteConfig.indexDocument,
33
+ error: config.websiteConfig.errorDocument,
34
+ });
35
+ }
36
+ return {
37
+ name: config.bucketName,
38
+ location: `oss-${region}`,
39
+ acl: config.acl,
40
+ websiteConfig: config.websiteConfig,
41
+ storageClass: config.storageClass,
42
+ };
43
+ },
44
+ getBucket: async (bucketName) => {
45
+ try {
46
+ useBucket(bucketName);
47
+ // Get bucket info
48
+ const infoResult = await ossClient.getBucketInfo(bucketName);
49
+ const bucket = infoResult.bucket;
50
+ // Get ACL
51
+ let acl;
52
+ try {
53
+ const aclResult = await ossClient.getBucketACL(bucketName);
54
+ acl = aclResult.acl;
55
+ }
56
+ catch {
57
+ // ACL might not be accessible
58
+ }
59
+ // Get website config
60
+ let websiteConfig;
61
+ try {
62
+ const websiteResult = await ossClient.getBucketWebsite(bucketName);
63
+ if (websiteResult.index) {
64
+ websiteConfig = {
65
+ indexDocument: websiteResult.index,
66
+ errorDocument: websiteResult.error,
67
+ };
68
+ }
69
+ }
70
+ catch {
71
+ // Website config might not exist
72
+ }
73
+ // Get logging config
74
+ let loggingConfig;
75
+ try {
76
+ const loggingResult = await ossClient.getBucketLogging(bucketName);
77
+ if (loggingResult.enable && loggingResult.prefix) {
78
+ loggingConfig = {
79
+ targetPrefix: loggingResult.prefix,
80
+ };
81
+ }
82
+ }
83
+ catch {
84
+ // Logging config might not exist
85
+ }
86
+ // Get CORS rules
87
+ let corsRules;
88
+ try {
89
+ const corsResult = await ossClient.getBucketCORS(bucketName);
90
+ if (corsResult.rules && corsResult.rules.length > 0) {
91
+ corsRules = corsResult.rules.map((rule) => ({
92
+ allowedOrigins: Array.isArray(rule.allowedOrigin)
93
+ ? rule.allowedOrigin
94
+ : [rule.allowedOrigin],
95
+ allowedMethods: Array.isArray(rule.allowedMethod)
96
+ ? rule.allowedMethod
97
+ : [rule.allowedMethod],
98
+ allowedHeaders: rule.allowedHeader
99
+ ? Array.isArray(rule.allowedHeader)
100
+ ? rule.allowedHeader
101
+ : [rule.allowedHeader]
102
+ : undefined,
103
+ exposeHeaders: rule.exposeHeader
104
+ ? Array.isArray(rule.exposeHeader)
105
+ ? rule.exposeHeader
106
+ : [rule.exposeHeader]
107
+ : undefined,
108
+ maxAgeSeconds: typeof rule.maxAgeSeconds === 'number' ? rule.maxAgeSeconds : undefined,
109
+ }));
110
+ }
111
+ }
112
+ catch {
113
+ // CORS config might not exist
114
+ }
115
+ // Get lifecycle rules
116
+ let lifecycleRules;
117
+ try {
118
+ const lifecycleResult = await ossClient.getBucketLifecycle(bucketName);
119
+ if (lifecycleResult.rules && lifecycleResult.rules.length > 0) {
120
+ lifecycleRules = lifecycleResult.rules.map((rule) => ({
121
+ id: rule.id,
122
+ status: rule.status,
123
+ prefix: rule.prefix,
124
+ expiration: rule.days
125
+ ? {
126
+ days: typeof rule.days === 'number' ? rule.days : parseInt(rule.days, 10),
127
+ }
128
+ : rule.date
129
+ ? {
130
+ date: rule.date,
131
+ }
132
+ : undefined,
133
+ }));
134
+ }
135
+ }
136
+ catch {
137
+ // Lifecycle config might not exist
138
+ }
139
+ // Build owner info
140
+ const owner = bucket?.Owner
141
+ ? {
142
+ id: bucket.Owner.ID,
143
+ displayName: bucket.Owner.DisplayName,
144
+ }
145
+ : undefined;
146
+ return {
147
+ name: bucketName,
148
+ location: bucket?.Location,
149
+ creationDate: bucket?.CreationDate,
150
+ storageClass: bucket?.StorageClass,
151
+ dataRedundancyType: bucket?.DataRedundancyType,
152
+ resourceGroupId: bucket?.ResourceGroupId,
153
+ comment: bucket?.Comment,
154
+ owner,
155
+ blockPublicAccess: bucket?.BlockPublicAccess,
156
+ accessMonitorStatus: bucket?.AccessMonitor,
157
+ acl,
158
+ websiteConfig,
159
+ loggingConfig,
160
+ corsRules,
161
+ lifecycleRules,
162
+ };
163
+ }
164
+ catch (error) {
165
+ if (error &&
166
+ typeof error === 'object' &&
167
+ 'code' in error &&
168
+ (error.code === 'NoSuchBucket' || error.code === 'AccessDenied')) {
169
+ return null;
170
+ }
171
+ throw error;
172
+ }
173
+ },
174
+ updateBucketAcl: async (bucketName, acl) => {
175
+ useBucket(bucketName);
176
+ await ossClient.putBucketACL(bucketName, acl);
177
+ },
178
+ updateBucketWebsite: async (bucketName, websiteConfig) => {
179
+ useBucket(bucketName);
180
+ await ossClient.putBucketWebsite(bucketName, {
181
+ index: websiteConfig.indexDocument,
182
+ error: websiteConfig.errorDocument,
183
+ });
184
+ },
185
+ deleteBucketWebsite: async (bucketName) => {
186
+ useBucket(bucketName);
187
+ await ossClient.deleteBucketWebsite(bucketName);
188
+ },
189
+ deleteBucket: async (bucketName) => {
190
+ useBucket(bucketName);
191
+ // List and delete all objects first
192
+ try {
193
+ let marker;
194
+ do {
195
+ const listResult = await ossClient.list({
196
+ 'max-keys': 1000,
197
+ marker,
198
+ }, {});
199
+ if (listResult.objects && listResult.objects.length > 0) {
200
+ const keys = listResult.objects.map((obj) => obj.name);
201
+ await ossClient.deleteMulti(keys, { quiet: true });
202
+ }
203
+ marker = listResult.isTruncated ? listResult.nextMarker : undefined;
204
+ } while (marker);
205
+ }
206
+ catch {
207
+ // Ignore errors when listing/deleting objects
208
+ }
209
+ await ossClient.deleteBucket(bucketName);
210
+ },
211
+ uploadFiles: async (bucketName, sourcePath) => {
212
+ useBucket(bucketName);
213
+ const uploadDirectory = async (dirPath, prefix = '') => {
214
+ const entries = node_fs_1.default.readdirSync(dirPath, { withFileTypes: true });
215
+ for (const entry of entries) {
216
+ const fullPath = node_path_1.default.join(dirPath, entry.name);
217
+ const ossKey = prefix ? `${prefix}/${entry.name}` : entry.name;
218
+ if (entry.isDirectory()) {
219
+ await uploadDirectory(fullPath, ossKey);
220
+ }
221
+ else if (entry.isFile()) {
222
+ await ossClient.put(ossKey, fullPath);
223
+ }
224
+ }
225
+ };
226
+ const stats = node_fs_1.default.statSync(sourcePath);
227
+ if (stats.isDirectory()) {
228
+ await uploadDirectory(sourcePath);
229
+ }
230
+ else {
231
+ const fileName = node_path_1.default.basename(sourcePath);
232
+ await ossClient.put(fileName, sourcePath);
233
+ }
234
+ },
235
+ };
236
+ };
237
+ exports.createOssOperations = createOssOperations;
@@ -0,0 +1,205 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createRamOperations = void 0;
37
+ const ram = __importStar(require("@alicloud/ram20150501"));
38
+ const FC_ASSUME_ROLE_POLICY = JSON.stringify({
39
+ Version: '1',
40
+ Statement: [
41
+ {
42
+ Action: 'sts:AssumeRole',
43
+ Effect: 'Allow',
44
+ Principal: {
45
+ Service: ['fc.aliyuncs.com'],
46
+ },
47
+ },
48
+ ],
49
+ });
50
+ const FC_EXECUTION_POLICY = JSON.stringify({
51
+ Version: '1',
52
+ Statement: [
53
+ {
54
+ Effect: 'Allow',
55
+ Action: [
56
+ 'log:PostLogStoreLogs',
57
+ 'log:CreateLogStore',
58
+ 'log:GetLogStore',
59
+ 'log:ListShards',
60
+ 'log:GetCursorOrData',
61
+ ],
62
+ Resource: '*',
63
+ },
64
+ {
65
+ Effect: 'Allow',
66
+ Action: ['nas:*'],
67
+ Resource: '*',
68
+ },
69
+ {
70
+ Effect: 'Allow',
71
+ Action: [
72
+ 'ecs:CreateNetworkInterface',
73
+ 'ecs:DeleteNetworkInterface',
74
+ 'ecs:DescribeNetworkInterfaces',
75
+ 'ecs:CreateNetworkInterfacePermission',
76
+ 'ecs:DescribeNetworkInterfacePermissions',
77
+ 'ecs:DeleteNetworkInterfacePermission',
78
+ ],
79
+ Resource: '*',
80
+ },
81
+ {
82
+ Effect: 'Allow',
83
+ Action: ['vpc:DescribeVSwitchAttributes'],
84
+ Resource: '*',
85
+ },
86
+ ],
87
+ });
88
+ const createRamOperations = (ramClient) => {
89
+ const attachRolePolicyForFc = async (roleName) => {
90
+ const policyName = `${roleName}-policy`;
91
+ // Create policy
92
+ try {
93
+ const createPolicyRequest = new ram.CreatePolicyRequest({
94
+ policyName,
95
+ policyDocument: FC_EXECUTION_POLICY,
96
+ description: `FC execution policy for ${roleName}`,
97
+ });
98
+ await ramClient.createPolicy(createPolicyRequest);
99
+ }
100
+ catch (error) {
101
+ // Policy may already exist
102
+ if (!(error &&
103
+ typeof error === 'object' &&
104
+ 'code' in error &&
105
+ error.code === 'EntityAlreadyExists.Policy')) {
106
+ throw error;
107
+ }
108
+ }
109
+ // Attach policy to role
110
+ try {
111
+ const attachRequest = new ram.AttachPolicyToRoleRequest({
112
+ policyType: 'Custom',
113
+ policyName,
114
+ roleName,
115
+ });
116
+ await ramClient.attachPolicyToRole(attachRequest);
117
+ }
118
+ catch (error) {
119
+ // Policy may already be attached
120
+ if (!(error &&
121
+ typeof error === 'object' &&
122
+ 'code' in error &&
123
+ error.code === 'EntityAlreadyExists.Role.Policy')) {
124
+ throw error;
125
+ }
126
+ }
127
+ };
128
+ return {
129
+ createRole: async (roleName, description) => {
130
+ const request = new ram.CreateRoleRequest({
131
+ roleName,
132
+ assumeRolePolicyDocument: FC_ASSUME_ROLE_POLICY,
133
+ description: description ?? `ServerlessInsight FC execution role for ${roleName}`,
134
+ });
135
+ const response = await ramClient.createRole(request);
136
+ // Attach policy to role
137
+ await attachRolePolicyForFc(roleName);
138
+ return {
139
+ roleName,
140
+ roleId: response.body?.role?.roleId,
141
+ arn: response.body?.role?.arn,
142
+ description: response.body?.role?.description,
143
+ createDate: response.body?.role?.createDate,
144
+ };
145
+ },
146
+ getRole: async (roleName) => {
147
+ try {
148
+ const request = new ram.GetRoleRequest({
149
+ roleName,
150
+ });
151
+ const response = await ramClient.getRole(request);
152
+ if (!response || !response.body || !response.body.role) {
153
+ return null;
154
+ }
155
+ return {
156
+ roleName: response.body.role.roleName ?? roleName,
157
+ roleId: response.body.role.roleId,
158
+ arn: response.body.role.arn,
159
+ description: response.body.role.description,
160
+ createDate: response.body.role.createDate,
161
+ };
162
+ }
163
+ catch (error) {
164
+ if (error &&
165
+ typeof error === 'object' &&
166
+ 'code' in error &&
167
+ error.code === 'EntityNotExist.Role') {
168
+ return null;
169
+ }
170
+ throw error;
171
+ }
172
+ },
173
+ deleteRole: async (roleName) => {
174
+ const policyName = `${roleName}-policy`;
175
+ // Detach policy from role
176
+ try {
177
+ const detachRequest = new ram.DetachPolicyFromRoleRequest({
178
+ policyType: 'Custom',
179
+ policyName,
180
+ roleName,
181
+ });
182
+ await ramClient.detachPolicyFromRole(detachRequest);
183
+ }
184
+ catch {
185
+ // Ignore if policy is not attached
186
+ }
187
+ // Delete policy
188
+ try {
189
+ const deletePolicyRequest = new ram.DeletePolicyRequest({
190
+ policyName,
191
+ });
192
+ await ramClient.deletePolicy(deletePolicyRequest);
193
+ }
194
+ catch {
195
+ // Ignore if policy doesn't exist
196
+ }
197
+ // Delete role
198
+ const request = new ram.DeleteRoleRequest({
199
+ roleName,
200
+ });
201
+ await ramClient.deleteRole(request);
202
+ },
203
+ };
204
+ };
205
+ exports.createRamOperations = createRamOperations;
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRdsOperations = exports.RdsInstanceStatus = void 0;
4
+ const logger_1 = require("../logger");
5
+ const lang_1 = require("../../lang");
6
+ var RdsInstanceStatus;
7
+ (function (RdsInstanceStatus) {
8
+ RdsInstanceStatus["RUNNING"] = "Running";
9
+ RdsInstanceStatus["CREATING"] = "Creating";
10
+ RdsInstanceStatus["DELETED"] = "Deleted";
11
+ RdsInstanceStatus["DELETE_FAILED"] = "DeleteFailed";
12
+ RdsInstanceStatus["RESTARTING"] = "Restarting";
13
+ })(RdsInstanceStatus || (exports.RdsInstanceStatus = RdsInstanceStatus = {}));
14
+ const waitForRdsInstanceReady = async (getInstance, instanceId) => {
15
+ const maxAttempts = 60;
16
+ let attempts = 0;
17
+ while (attempts < maxAttempts) {
18
+ const instance = await getInstance(instanceId);
19
+ if (!instance) {
20
+ throw new Error(lang_1.lang.__('RDS_INSTANCE_NOT_FOUND', { instanceId }));
21
+ }
22
+ if (instance.dbInstanceStatus === RdsInstanceStatus.RUNNING) {
23
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_READY', { instanceId }));
24
+ return;
25
+ }
26
+ if (instance.dbInstanceStatus === RdsInstanceStatus.DELETED ||
27
+ instance.dbInstanceStatus === RdsInstanceStatus.DELETE_FAILED) {
28
+ throw new Error(lang_1.lang.__('RDS_INSTANCE_ERROR_STATE', { status: instance.dbInstanceStatus }));
29
+ }
30
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_WAITING', {
31
+ instanceId,
32
+ status: instance.dbInstanceStatus ?? 'unknown',
33
+ }));
34
+ await new Promise((resolve) => setTimeout(resolve, 10000));
35
+ attempts++;
36
+ }
37
+ throw new Error(lang_1.lang.__('RDS_INSTANCE_TIMEOUT_READY', { instanceId }));
38
+ };
39
+ const createRdsOperations = (rdsClient, context) => {
40
+ const operations = {
41
+ createInstance: async (config) => {
42
+ const params = {
43
+ RegionId: context.region,
44
+ Engine: config.engine,
45
+ EngineVersion: config.engineVersion,
46
+ DBInstanceClass: config.dbInstanceClass,
47
+ DBInstanceStorage: config.dbInstanceStorage,
48
+ Category: config.category,
49
+ DBInstanceStorageType: config.dbInstanceStorageType,
50
+ DBInstanceDescription: config.dbInstanceDescription,
51
+ PayType: 'Serverless',
52
+ SecurityIPList: config.securityIPList || '0.0.0.0/0',
53
+ VpcId: config.vpcId,
54
+ VSwitchId: config.vSwitchId,
55
+ ZoneId: config.zoneId,
56
+ MasterUsername: config.masterUsername,
57
+ MasterUserPassword: config.masterUserPassword,
58
+ MasterUserType: config.masterUserType || 'Super',
59
+ ServerlessConfig: config.serverlessConfig
60
+ ? {
61
+ MinCapacity: config.serverlessConfig.minCapacity,
62
+ MaxCapacity: config.serverlessConfig.maxCapacity,
63
+ AutoPause: config.serverlessConfig.autoPause,
64
+ SwitchForce: config.serverlessConfig.switchForce,
65
+ }
66
+ : undefined,
67
+ BurstingEnabled: config.burstingEnabled,
68
+ };
69
+ try {
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ const response = await rdsClient.createDBInstance(params);
72
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_CREATION_INITIATED'));
73
+ if (!response.body?.DBInstanceId) {
74
+ throw new Error(lang_1.lang.__('RDS_INSTANCE_NO_ID_RETURNED'));
75
+ }
76
+ const instanceId = response.body.DBInstanceId;
77
+ // Wait for instance to be ready
78
+ await waitForRdsInstanceReady(operations.getInstance, instanceId);
79
+ return instanceId;
80
+ }
81
+ catch (error) {
82
+ logger_1.logger.error(lang_1.lang.__('RDS_INSTANCE_CREATION_FAILED', { error: String(error) }));
83
+ throw error;
84
+ }
85
+ },
86
+ getInstance: async (instanceId) => {
87
+ const params = {
88
+ DBInstanceId: instanceId,
89
+ };
90
+ try {
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ const response = await rdsClient.describeDBInstanceAttribute(params);
93
+ if (!response.body?.Items?.DBInstanceAttribute ||
94
+ response.body.Items.DBInstanceAttribute.length === 0) {
95
+ return null;
96
+ }
97
+ const instance = response.body.Items.DBInstanceAttribute[0];
98
+ return {
99
+ dbInstanceId: instance.DBInstanceId,
100
+ dbInstanceDescription: instance.DBInstanceDescription,
101
+ engine: instance.Engine,
102
+ engineVersion: instance.EngineVersion,
103
+ dbInstanceClass: instance.DBInstanceClass,
104
+ dbInstanceStorage: instance.DBInstanceStorage,
105
+ category: instance.Category,
106
+ dbInstanceStorageType: instance.DBInstanceStorageType,
107
+ serverlessConfig: instance.ServerlessConfig
108
+ ? {
109
+ minCapacity: instance.ServerlessConfig.MinCapacity,
110
+ maxCapacity: instance.ServerlessConfig.MaxCapacity,
111
+ autoPause: instance.ServerlessConfig.AutoPause,
112
+ switchForce: instance.ServerlessConfig.SwitchForce,
113
+ }
114
+ : undefined,
115
+ masterUsername: instance.MasterUsername,
116
+ vpcId: instance.VpcId,
117
+ vSwitchId: instance.VSwitchId,
118
+ zoneId: instance.ZoneId,
119
+ connectionString: instance.ConnectionString,
120
+ port: instance.Port,
121
+ dbInstanceStatus: instance.DBInstanceStatus,
122
+ createTime: instance.CreateTime,
123
+ regionId: instance.RegionId,
124
+ securityIPList: instance.SecurityIPList,
125
+ multiAZ: instance.MultiAZ === 'true',
126
+ };
127
+ }
128
+ catch (error) {
129
+ logger_1.logger.error(lang_1.lang.__('RDS_INSTANCE_GET_FAILED', { error: String(error) }));
130
+ return null;
131
+ }
132
+ },
133
+ updateInstance: async (instanceId, config) => {
134
+ try {
135
+ // Update serverless configuration
136
+ if (config.serverlessConfig) {
137
+ const serverlessParams = {
138
+ DBInstanceId: instanceId,
139
+ ServerlessConfig: {
140
+ MinCapacity: config.serverlessConfig.minCapacity,
141
+ MaxCapacity: config.serverlessConfig.maxCapacity,
142
+ AutoPause: config.serverlessConfig.autoPause,
143
+ SwitchForce: config.serverlessConfig.switchForce,
144
+ },
145
+ };
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ await rdsClient.modifyDBInstanceSpec(serverlessParams);
148
+ }
149
+ // Update security IP list if provided
150
+ if (config.securityIPList) {
151
+ const securityParams = {
152
+ DBInstanceId: instanceId,
153
+ SecurityIPList: config.securityIPList,
154
+ };
155
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
+ await rdsClient.modifySecurityIps(securityParams);
157
+ }
158
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_UPDATED', { instanceId }));
159
+ // Wait for instance to be ready
160
+ await waitForRdsInstanceReady(operations.getInstance, instanceId);
161
+ }
162
+ catch (error) {
163
+ logger_1.logger.error(lang_1.lang.__('RDS_INSTANCE_UPDATE_FAILED', { error: String(error) }));
164
+ throw error;
165
+ }
166
+ },
167
+ deleteInstance: async (instanceId) => {
168
+ const params = {
169
+ DBInstanceId: instanceId,
170
+ };
171
+ try {
172
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
173
+ await rdsClient.deleteDBInstance(params);
174
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_DELETION_INITIATED', { instanceId }));
175
+ // Wait for instance to be deleted
176
+ const maxAttempts = 60;
177
+ let attempts = 0;
178
+ while (attempts < maxAttempts) {
179
+ const instance = await operations.getInstance(instanceId);
180
+ if (!instance) {
181
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_DELETED', { instanceId }));
182
+ return;
183
+ }
184
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_WAITING_DELETE', { instanceId }));
185
+ await new Promise((resolve) => setTimeout(resolve, 10000));
186
+ attempts++;
187
+ }
188
+ throw new Error(lang_1.lang.__('RDS_INSTANCE_TIMEOUT_DELETE', { instanceId }));
189
+ }
190
+ catch (error) {
191
+ // If instance is not found, consider it deleted
192
+ if (error &&
193
+ typeof error === 'object' &&
194
+ 'code' in error &&
195
+ error.code === 'InvalidDBInstanceId.NotFound') {
196
+ logger_1.logger.info(lang_1.lang.__('RDS_INSTANCE_DELETED', { instanceId }));
197
+ return;
198
+ }
199
+ logger_1.logger.error(lang_1.lang.__('RDS_INSTANCE_DELETE_FAILED', { error: String(error) }));
200
+ throw error;
201
+ }
202
+ },
203
+ };
204
+ return operations;
205
+ };
206
+ exports.createRdsOperations = createRdsOperations;