@stacksjs/ts-cloud 0.9.2 → 0.9.4

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 (191) hide show
  1. package/dist/aws/index.js +1 -269
  2. package/dist/bin/chunk-00kg80qg.js +1 -0
  3. package/dist/bin/chunk-09nwf2gy.js +34 -0
  4. package/dist/bin/chunk-1k5kszjp.js +111 -0
  5. package/dist/bin/chunk-21e0mavm.js +1 -0
  6. package/dist/bin/chunk-271gk1n2.js +6 -0
  7. package/dist/bin/chunk-2empps47.js +2 -0
  8. package/dist/bin/chunk-38pq971s.js +2 -0
  9. package/dist/bin/chunk-3gykfyq4.js +37 -0
  10. package/dist/bin/chunk-3vqfexc4.js +70 -0
  11. package/dist/bin/chunk-4vrqm9h0.js +2 -0
  12. package/dist/bin/chunk-598yf4bs.js +1 -0
  13. package/dist/bin/chunk-5ectjq0b.js +1 -0
  14. package/dist/bin/chunk-5erkxpt7.js +512 -0
  15. package/dist/bin/chunk-5mrtzemj.js +1 -0
  16. package/dist/bin/chunk-5n9fmabb.js +1 -0
  17. package/dist/bin/chunk-9knpg30y.js +1 -0
  18. package/dist/bin/chunk-9pvsff8g.js +1 -0
  19. package/dist/bin/chunk-ax9mr6wm.js +44 -0
  20. package/dist/bin/chunk-axhnkn5g.js +2 -0
  21. package/dist/bin/chunk-c1vcdgvr.js +1 -0
  22. package/dist/bin/chunk-ctd2vg9w.js +2 -0
  23. package/dist/bin/chunk-dbgffky8.js +1 -0
  24. package/dist/bin/chunk-ddk4rt4j.js +6 -0
  25. package/dist/bin/chunk-dwr30vbv.js +1 -0
  26. package/dist/bin/chunk-e0rkrq70.js +1 -0
  27. package/dist/bin/chunk-e3xrwh9z.js +1 -0
  28. package/dist/bin/chunk-etrb03mt.js +1507 -0
  29. package/dist/bin/chunk-fhc6ntvd.js +2 -0
  30. package/dist/bin/chunk-fpm59y25.js +6 -0
  31. package/dist/bin/chunk-fvbxvq6b.js +1 -0
  32. package/dist/bin/chunk-fy8j3y8p.js +92 -0
  33. package/dist/bin/chunk-fz21b57w.js +1 -0
  34. package/dist/bin/chunk-gavvf0pg.js +141 -0
  35. package/dist/bin/chunk-ggn7ax8p.js +4 -0
  36. package/dist/bin/chunk-gpe2prkm.js +1 -0
  37. package/dist/bin/chunk-h5pa5men.js +2 -0
  38. package/dist/bin/chunk-hm08xdxf.js +2 -0
  39. package/dist/bin/chunk-hzgz13nf.js +1 -0
  40. package/dist/bin/chunk-j703btc5.js +50 -0
  41. package/dist/bin/chunk-k9t9wvms.js +1 -0
  42. package/dist/bin/chunk-m669wtgr.js +1 -0
  43. package/dist/bin/chunk-m7dgskt1.js +1 -0
  44. package/dist/bin/chunk-mh0kdzqp.js +2 -0
  45. package/dist/bin/chunk-mr0atd2s.js +2 -0
  46. package/dist/bin/chunk-mz0wbbsj.js +3 -0
  47. package/dist/bin/chunk-ngcyftm2.js +1 -0
  48. package/dist/bin/chunk-p66ptpmr.js +2 -0
  49. package/dist/bin/chunk-qk9qgepa.js +1 -0
  50. package/dist/bin/chunk-rxcvf10f.js +7364 -0
  51. package/dist/bin/chunk-rytk89az.js +60 -0
  52. package/dist/bin/chunk-tga3hhwk.js +6 -0
  53. package/dist/bin/chunk-tx0tqq2k.js +8 -0
  54. package/dist/bin/chunk-vek8a0w6.js +1 -0
  55. package/dist/bin/chunk-vm3q5gf2.js +3 -0
  56. package/dist/bin/chunk-y7s5r8y6.js +3 -0
  57. package/dist/bin/chunk-yv9sth30.js +1 -0
  58. package/dist/bin/chunk-zmegvjp8.js +581 -0
  59. package/dist/bin/cli.js +417 -10597
  60. package/dist/bin/dashboard-server.js +1 -6998
  61. package/dist/chunk-0ccta6z6.js +6 -0
  62. package/dist/chunk-0k1cs6pp.js +1 -0
  63. package/dist/chunk-1egjn203.js +704 -0
  64. package/dist/chunk-2wx29qga.js +5 -0
  65. package/dist/chunk-5m5rqmv7.js +1 -0
  66. package/dist/chunk-8ea5022g.js +114 -0
  67. package/dist/chunk-8xqn3c0w.js +2 -0
  68. package/dist/chunk-b4esxhmw.js +2 -0
  69. package/dist/chunk-b8e5wzwn.js +44 -0
  70. package/dist/chunk-bggt4n6e.js +2 -0
  71. package/dist/chunk-cwkg37rs.js +37 -0
  72. package/dist/chunk-dskvqt67.js +7355 -0
  73. package/dist/chunk-gahsdmxf.js +1617 -0
  74. package/dist/chunk-gnv3r2jg.js +1 -0
  75. package/dist/chunk-hg3c48cp.js +34 -0
  76. package/dist/chunk-m5azeva3.js +2 -0
  77. package/dist/chunk-r3qf56b3.js +92 -0
  78. package/dist/chunk-sdqa9ghv.js +141 -0
  79. package/dist/chunk-svrvvcm7.js +1 -0
  80. package/dist/chunk-v0p3hpc3.js +60 -0
  81. package/dist/chunk-wdzjbecg.js +50 -0
  82. package/dist/chunk-ww8k3g7j.js +1 -0
  83. package/dist/chunk-xmqfc62w.js +1 -0
  84. package/dist/chunk-xrebj679.js +435 -0
  85. package/dist/chunk-xt3s24vr.js +2 -0
  86. package/dist/chunk-y21zk0pn.js +4 -0
  87. package/dist/deploy/attach-credentials.d.ts +57 -0
  88. package/dist/deploy/index.js +1 -168
  89. package/dist/deploy/site-ports.d.ts +151 -0
  90. package/dist/deploy/site-target.d.ts +24 -1
  91. package/dist/dns/index.js +1 -41
  92. package/dist/drivers/index.js +1 -154
  93. package/dist/index.js +100 -6129
  94. package/dist/protection/index.js +1 -89
  95. package/dist/push/index.js +1 -509
  96. package/dist/spend/index.js +1 -173
  97. package/dist/ui/404.html +16 -548
  98. package/dist/ui/_stx/chunk.5ddb5087.js +90 -0
  99. package/dist/ui/_stx/chunk.9fd39d5b.js +86 -0
  100. package/dist/ui/_stx/chunk.d5301f79.js +119 -0
  101. package/dist/ui/_stx/crosswind.222ed683.css +1 -0
  102. package/dist/ui/_stx/crosswind.616c25f3.css +1 -0
  103. package/dist/ui/_stx/crosswind.80baa894.css +320 -0
  104. package/dist/ui/_stx/crosswind.906ee17c.css +1 -0
  105. package/dist/ui/_stx/crosswind.996ed49e.css +1 -0
  106. package/dist/ui/_stx/crosswind.b7a99a5c.css +1 -0
  107. package/dist/ui/_stx/router.fa5bc4dc.js +4 -0
  108. package/dist/ui/_stx/runtime.c696d17a.js +1 -0
  109. package/dist/ui/_stx/style.448ab192.css +1 -0
  110. package/dist/ui/accept-invitation.html +2 -1133
  111. package/dist/ui/access-denied.html +7 -1130
  112. package/dist/ui/account/automation.html +12 -1134
  113. package/dist/ui/account/security.html +13 -1136
  114. package/dist/ui/applications/compose.html +12 -1134
  115. package/dist/ui/applications/new.html +13 -1137
  116. package/dist/ui/data/backups.html +91 -1136
  117. package/dist/ui/data/services.html +89 -1136
  118. package/dist/ui/data/volumes.html +61 -1136
  119. package/dist/ui/index.html +60 -1136
  120. package/dist/ui/infrastructure/topology.html +128 -1135
  121. package/dist/ui/integrations.html +13 -1138
  122. package/dist/ui/operations/alerts.html +59 -1136
  123. package/dist/ui/operations/configuration.html +13 -1135
  124. package/dist/ui/operations/jobs.html +87 -1136
  125. package/dist/ui/operations/maintenance.html +12 -1134
  126. package/dist/ui/operations/observability.html +93 -1136
  127. package/dist/ui/operations/previews.html +12 -1134
  128. package/dist/ui/operations/queue.html +12 -1134
  129. package/dist/ui/operations/regions.html +12 -1134
  130. package/dist/ui/operations/releases.html +12 -1134
  131. package/dist/ui/operations/spend.html +65 -1136
  132. package/dist/ui/operations/workloads.html +115 -1136
  133. package/dist/ui/robots.txt +2 -0
  134. package/dist/ui/security.html +24 -1136
  135. package/dist/ui/server/actions.html +67 -1138
  136. package/dist/ui/server/activity.html +7 -1130
  137. package/dist/ui/server/capacity.html +12 -1134
  138. package/dist/ui/server/database.html +166 -1135
  139. package/dist/ui/server/deployments.html +60 -1136
  140. package/dist/ui/server/diagnostics.html +7 -1130
  141. package/dist/ui/server/firewall.html +286 -1212
  142. package/dist/ui/server/fleet.html +45 -1136
  143. package/dist/ui/server/logs.html +34 -1135
  144. package/dist/ui/server/metrics.html +124 -1140
  145. package/dist/ui/server/security.html +7 -1130
  146. package/dist/ui/server/services.html +46 -1133
  147. package/dist/ui/server/sites.html +287 -1137
  148. package/dist/ui/server/ssh-keys.html +62 -1135
  149. package/dist/ui/server/team.html +155 -1136
  150. package/dist/ui/server/terminal.html +97 -1183
  151. package/dist/ui/serverless/alarms.html +62 -1135
  152. package/dist/ui/serverless/assets.html +47 -1132
  153. package/dist/ui/serverless/cost.html +7 -1130
  154. package/dist/ui/serverless/data.html +46 -1135
  155. package/dist/ui/serverless/deployments.html +47 -1132
  156. package/dist/ui/serverless/firewall.html +7 -1130
  157. package/dist/ui/serverless/functions.html +50 -1136
  158. package/dist/ui/serverless/logs.html +34 -1135
  159. package/dist/ui/serverless/metrics.html +7 -1130
  160. package/dist/ui/serverless/queues.html +58 -1135
  161. package/dist/ui/serverless/secrets.html +62 -1136
  162. package/dist/ui/serverless/traces.html +12 -1134
  163. package/dist/ui/serverless.html +64 -1137
  164. package/dist/ui-src/pages/server/firewall.stx +14 -14
  165. package/package.json +3 -3
  166. package/dist/chunk-01d86gt1.js +0 -1324
  167. package/dist/chunk-050r7ycy.js +0 -46516
  168. package/dist/chunk-29rse4p1.js +0 -12203
  169. package/dist/chunk-32e7ya18.js +0 -642
  170. package/dist/chunk-4cjrg98a.js +0 -597
  171. package/dist/chunk-50jpda9q.js +0 -371
  172. package/dist/chunk-6a1t7fnq.js +0 -12121
  173. package/dist/chunk-728jvrr0.js +0 -1701
  174. package/dist/chunk-7m60qnc8.js +0 -1762
  175. package/dist/chunk-aa2dkn7b.js +0 -205
  176. package/dist/chunk-d48vtdj4.js +0 -433
  177. package/dist/chunk-f55nkpvb.js +0 -8
  178. package/dist/chunk-fgk8cqew.js +0 -152
  179. package/dist/chunk-he9a874b.js +0 -769
  180. package/dist/chunk-hg7rhrgd.js +0 -7274
  181. package/dist/chunk-k2yyatfw.js +0 -10
  182. package/dist/chunk-k4px0bnv.js +0 -23
  183. package/dist/chunk-nsgqsmrh.js +0 -1779
  184. package/dist/chunk-qr803fye.js +0 -2122
  185. package/dist/chunk-rds0sy87.js +0 -1771
  186. package/dist/chunk-rxgchb08.js +0 -42033
  187. package/dist/chunk-ttz2ra5j.js +0 -12
  188. package/dist/chunk-v0bahtg2.js +0 -4
  189. package/dist/chunk-va2yd85b.js +0 -200
  190. package/dist/chunk-x9s0cqfx.js +0 -13
  191. package/dist/chunk-zqtpg06c.js +0 -1752
@@ -1,1762 +0,0 @@
1
- import {
2
- AWSClient
3
- } from "./chunk-zqtpg06c.js";
4
-
5
- // src/aws/ec2.ts
6
- class EC2Client {
7
- client;
8
- region;
9
- constructor(region = "us-east-1") {
10
- this.region = region;
11
- this.client = new AWSClient;
12
- }
13
- async describeInstances(options) {
14
- const params = {
15
- Action: "DescribeInstances",
16
- Version: "2016-11-15"
17
- };
18
- if (options?.InstanceIds) {
19
- options.InstanceIds.forEach((id, i) => {
20
- params[`InstanceId.${i + 1}`] = id;
21
- });
22
- }
23
- if (options?.Filters) {
24
- options.Filters.forEach((filter, i) => {
25
- params[`Filter.${i + 1}.Name`] = filter.Name;
26
- filter.Values.forEach((val, j) => {
27
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
28
- });
29
- });
30
- }
31
- if (options?.MaxResults) {
32
- params.MaxResults = String(options.MaxResults);
33
- }
34
- if (options?.NextToken) {
35
- params.NextToken = options.NextToken;
36
- }
37
- const result = await this.client.request({
38
- service: "ec2",
39
- region: this.region,
40
- method: "POST",
41
- path: "/",
42
- headers: {
43
- "Content-Type": "application/x-www-form-urlencoded"
44
- },
45
- body: new URLSearchParams(params).toString()
46
- });
47
- const response = result.DescribeInstancesResponse || result;
48
- return {
49
- Reservations: this.parseReservations(response.reservationSet?.item),
50
- NextToken: response.nextToken
51
- };
52
- }
53
- async getInstance(instanceId) {
54
- const result = await this.describeInstances({ InstanceIds: [instanceId] });
55
- return result.Reservations?.[0]?.Instances?.[0];
56
- }
57
- async getConsoleOutput(instanceId, latest) {
58
- const params = {
59
- Action: "GetConsoleOutput",
60
- Version: "2016-11-15",
61
- InstanceId: instanceId
62
- };
63
- if (latest) {
64
- params.Latest = "true";
65
- }
66
- const result = await this.client.request({
67
- service: "ec2",
68
- region: this.region,
69
- method: "POST",
70
- path: "/",
71
- headers: {
72
- "Content-Type": "application/x-www-form-urlencoded"
73
- },
74
- body: new URLSearchParams(params).toString()
75
- });
76
- const response = result.GetConsoleOutputResponse || result;
77
- return {
78
- InstanceId: response.instanceId,
79
- Output: response.output,
80
- Timestamp: response.timestamp
81
- };
82
- }
83
- async getConsoleOutputDecoded(instanceId, options) {
84
- const result = await this.getConsoleOutput(instanceId, options?.latest);
85
- if (!result.Output) {
86
- return "No console output available yet";
87
- }
88
- const decoded = Buffer.from(result.Output, "base64").toString("utf-8");
89
- if (options?.tailLines) {
90
- const lines = decoded.split(`
91
- `);
92
- return lines.slice(-options.tailLines).join(`
93
- `);
94
- }
95
- return decoded;
96
- }
97
- async describeInstanceStatus(options) {
98
- const params = {
99
- Action: "DescribeInstanceStatus",
100
- Version: "2016-11-15"
101
- };
102
- if (options?.InstanceIds) {
103
- options.InstanceIds.forEach((id, i) => {
104
- params[`InstanceId.${i + 1}`] = id;
105
- });
106
- }
107
- if (options?.IncludeAllInstances) {
108
- params.IncludeAllInstances = "true";
109
- }
110
- if (options?.Filters) {
111
- options.Filters.forEach((filter, i) => {
112
- params[`Filter.${i + 1}.Name`] = filter.Name;
113
- filter.Values.forEach((val, j) => {
114
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
115
- });
116
- });
117
- }
118
- const result = await this.client.request({
119
- service: "ec2",
120
- region: this.region,
121
- method: "POST",
122
- path: "/",
123
- headers: {
124
- "Content-Type": "application/x-www-form-urlencoded"
125
- },
126
- body: new URLSearchParams(params).toString()
127
- });
128
- return {
129
- InstanceStatuses: this.parseArray(result.instanceStatusSet?.item).map((item) => ({
130
- InstanceId: item.instanceId,
131
- InstanceState: item.instanceState ? {
132
- Code: Number.parseInt(item.instanceState.code),
133
- Name: item.instanceState.name
134
- } : undefined,
135
- InstanceStatus: item.instanceStatus ? {
136
- Status: item.instanceStatus.status,
137
- Details: this.parseArray(item.instanceStatus.details?.item).map((d) => ({
138
- Name: d.name,
139
- Status: d.status
140
- }))
141
- } : undefined,
142
- SystemStatus: item.systemStatus ? {
143
- Status: item.systemStatus.status,
144
- Details: this.parseArray(item.systemStatus.details?.item).map((d) => ({
145
- Name: d.name,
146
- Status: d.status
147
- }))
148
- } : undefined
149
- }))
150
- };
151
- }
152
- async startInstances(instanceIds) {
153
- const params = {
154
- Action: "StartInstances",
155
- Version: "2016-11-15"
156
- };
157
- instanceIds.forEach((id, i) => {
158
- params[`InstanceId.${i + 1}`] = id;
159
- });
160
- const result = await this.client.request({
161
- service: "ec2",
162
- region: this.region,
163
- method: "POST",
164
- path: "/",
165
- headers: {
166
- "Content-Type": "application/x-www-form-urlencoded"
167
- },
168
- body: new URLSearchParams(params).toString()
169
- });
170
- return {
171
- StartingInstances: this.parseArray(result.instancesSet?.item).map((item) => ({
172
- InstanceId: item.instanceId,
173
- CurrentState: item.currentState ? { Name: item.currentState.name } : undefined,
174
- PreviousState: item.previousState ? { Name: item.previousState.name } : undefined
175
- }))
176
- };
177
- }
178
- async stopInstances(instanceIds, force) {
179
- const params = {
180
- Action: "StopInstances",
181
- Version: "2016-11-15"
182
- };
183
- instanceIds.forEach((id, i) => {
184
- params[`InstanceId.${i + 1}`] = id;
185
- });
186
- if (force) {
187
- params.Force = "true";
188
- }
189
- const result = await this.client.request({
190
- service: "ec2",
191
- region: this.region,
192
- method: "POST",
193
- path: "/",
194
- headers: {
195
- "Content-Type": "application/x-www-form-urlencoded"
196
- },
197
- body: new URLSearchParams(params).toString()
198
- });
199
- return {
200
- StoppingInstances: this.parseArray(result.instancesSet?.item).map((item) => ({
201
- InstanceId: item.instanceId,
202
- CurrentState: item.currentState ? { Name: item.currentState.name } : undefined,
203
- PreviousState: item.previousState ? { Name: item.previousState.name } : undefined
204
- }))
205
- };
206
- }
207
- async rebootInstances(instanceIds) {
208
- const params = {
209
- Action: "RebootInstances",
210
- Version: "2016-11-15"
211
- };
212
- instanceIds.forEach((id, i) => {
213
- params[`InstanceId.${i + 1}`] = id;
214
- });
215
- await this.client.request({
216
- service: "ec2",
217
- region: this.region,
218
- method: "POST",
219
- path: "/",
220
- headers: {
221
- "Content-Type": "application/x-www-form-urlencoded"
222
- },
223
- body: new URLSearchParams(params).toString()
224
- });
225
- }
226
- async terminateInstances(instanceIds) {
227
- const params = {
228
- Action: "TerminateInstances",
229
- Version: "2016-11-15"
230
- };
231
- instanceIds.forEach((id, i) => {
232
- params[`InstanceId.${i + 1}`] = id;
233
- });
234
- const result = await this.client.request({
235
- service: "ec2",
236
- region: this.region,
237
- method: "POST",
238
- path: "/",
239
- headers: {
240
- "Content-Type": "application/x-www-form-urlencoded"
241
- },
242
- body: new URLSearchParams(params).toString()
243
- });
244
- return {
245
- TerminatingInstances: this.parseArray(result.instancesSet?.item).map((item) => ({
246
- InstanceId: item.instanceId,
247
- CurrentState: item.currentState ? { Name: item.currentState.name } : undefined,
248
- PreviousState: item.previousState ? { Name: item.previousState.name } : undefined
249
- }))
250
- };
251
- }
252
- async createImage(options) {
253
- const params = {
254
- Action: "CreateImage",
255
- Version: "2016-11-15",
256
- InstanceId: options.InstanceId,
257
- Name: options.Name
258
- };
259
- if (options.Description)
260
- params.Description = options.Description;
261
- if (options.NoReboot !== undefined)
262
- params.NoReboot = String(options.NoReboot);
263
- if (options.TagSpecifications) {
264
- options.TagSpecifications.forEach((spec, i) => {
265
- params[`TagSpecification.${i + 1}.ResourceType`] = spec.ResourceType;
266
- spec.Tags.forEach((tag, j) => {
267
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Key`] = tag.Key;
268
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Value`] = tag.Value;
269
- });
270
- });
271
- }
272
- const result = await this.client.request({
273
- service: "ec2",
274
- region: this.region,
275
- method: "POST",
276
- path: "/",
277
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
278
- body: new URLSearchParams(params).toString()
279
- });
280
- const response = result.CreateImageResponse || result;
281
- return { ImageId: response.imageId };
282
- }
283
- async deregisterImage(imageId) {
284
- await this.client.request({
285
- service: "ec2",
286
- region: this.region,
287
- method: "POST",
288
- path: "/",
289
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
290
- body: new URLSearchParams({ Action: "DeregisterImage", Version: "2016-11-15", ImageId: imageId }).toString()
291
- });
292
- }
293
- async describeVpcs(options) {
294
- const params = {
295
- Action: "DescribeVpcs",
296
- Version: "2016-11-15"
297
- };
298
- if (options?.VpcIds) {
299
- options.VpcIds.forEach((id, i) => {
300
- params[`VpcId.${i + 1}`] = id;
301
- });
302
- }
303
- if (options?.Filters) {
304
- options.Filters.forEach((filter, i) => {
305
- params[`Filter.${i + 1}.Name`] = filter.Name;
306
- filter.Values.forEach((val, j) => {
307
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
308
- });
309
- });
310
- }
311
- const result = await this.client.request({
312
- service: "ec2",
313
- region: this.region,
314
- method: "POST",
315
- path: "/",
316
- headers: {
317
- "Content-Type": "application/x-www-form-urlencoded"
318
- },
319
- body: new URLSearchParams(params).toString()
320
- });
321
- return {
322
- Vpcs: this.parseArray(result.vpcSet?.item).map((item) => ({
323
- VpcId: item.vpcId,
324
- CidrBlock: item.cidrBlock,
325
- State: item.state,
326
- DhcpOptionsId: item.dhcpOptionsId,
327
- InstanceTenancy: item.instanceTenancy,
328
- IsDefault: item.isDefault === "true",
329
- Tags: this.parseTags(item.tagSet?.item)
330
- }))
331
- };
332
- }
333
- async describeSubnets(options) {
334
- const params = {
335
- Action: "DescribeSubnets",
336
- Version: "2016-11-15"
337
- };
338
- if (options?.SubnetIds) {
339
- options.SubnetIds.forEach((id, i) => {
340
- params[`SubnetId.${i + 1}`] = id;
341
- });
342
- }
343
- if (options?.Filters) {
344
- options.Filters.forEach((filter, i) => {
345
- params[`Filter.${i + 1}.Name`] = filter.Name;
346
- filter.Values.forEach((val, j) => {
347
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
348
- });
349
- });
350
- }
351
- const result = await this.client.request({
352
- service: "ec2",
353
- region: this.region,
354
- method: "POST",
355
- path: "/",
356
- headers: {
357
- "Content-Type": "application/x-www-form-urlencoded"
358
- },
359
- body: new URLSearchParams(params).toString()
360
- });
361
- return {
362
- Subnets: this.parseArray(result.subnetSet?.item).map((item) => ({
363
- SubnetId: item.subnetId,
364
- VpcId: item.vpcId,
365
- CidrBlock: item.cidrBlock,
366
- AvailabilityZone: item.availabilityZone,
367
- AvailableIpAddressCount: Number.parseInt(item.availableIpAddressCount),
368
- State: item.state,
369
- MapPublicIpOnLaunch: item.mapPublicIpOnLaunch === "true",
370
- Tags: this.parseTags(item.tagSet?.item)
371
- }))
372
- };
373
- }
374
- async describeSecurityGroups(options) {
375
- const params = {
376
- Action: "DescribeSecurityGroups",
377
- Version: "2016-11-15"
378
- };
379
- if (options?.GroupIds) {
380
- options.GroupIds.forEach((id, i) => {
381
- params[`GroupId.${i + 1}`] = id;
382
- });
383
- }
384
- if (options?.GroupNames) {
385
- options.GroupNames.forEach((name, i) => {
386
- params[`GroupName.${i + 1}`] = name;
387
- });
388
- }
389
- if (options?.Filters) {
390
- options.Filters.forEach((filter, i) => {
391
- params[`Filter.${i + 1}.Name`] = filter.Name;
392
- filter.Values.forEach((val, j) => {
393
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
394
- });
395
- });
396
- }
397
- const result = await this.client.request({
398
- service: "ec2",
399
- region: this.region,
400
- method: "POST",
401
- path: "/",
402
- headers: {
403
- "Content-Type": "application/x-www-form-urlencoded"
404
- },
405
- body: new URLSearchParams(params).toString()
406
- });
407
- return {
408
- SecurityGroups: this.parseArray(result.securityGroupInfo?.item).map((item) => ({
409
- GroupId: item.groupId,
410
- GroupName: item.groupName,
411
- Description: item.groupDescription,
412
- VpcId: item.vpcId,
413
- IpPermissions: this.parseIpPermissions(item.ipPermissions?.item),
414
- IpPermissionsEgress: this.parseIpPermissions(item.ipPermissionsEgress?.item),
415
- Tags: this.parseTags(item.tagSet?.item)
416
- }))
417
- };
418
- }
419
- async describeInternetGateways(options) {
420
- const params = {
421
- Action: "DescribeInternetGateways",
422
- Version: "2016-11-15"
423
- };
424
- if (options?.InternetGatewayIds) {
425
- options.InternetGatewayIds.forEach((id, i) => {
426
- params[`InternetGatewayId.${i + 1}`] = id;
427
- });
428
- }
429
- if (options?.Filters) {
430
- options.Filters.forEach((filter, i) => {
431
- params[`Filter.${i + 1}.Name`] = filter.Name;
432
- filter.Values.forEach((val, j) => {
433
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
434
- });
435
- });
436
- }
437
- const result = await this.client.request({
438
- service: "ec2",
439
- region: this.region,
440
- method: "POST",
441
- path: "/",
442
- headers: {
443
- "Content-Type": "application/x-www-form-urlencoded"
444
- },
445
- body: new URLSearchParams(params).toString()
446
- });
447
- return {
448
- InternetGateways: this.parseArray(result.internetGatewaySet?.item).map((item) => ({
449
- InternetGatewayId: item.internetGatewayId,
450
- Attachments: this.parseArray(item.attachmentSet?.item).map((a) => ({
451
- VpcId: a.vpcId,
452
- State: a.state
453
- })),
454
- Tags: this.parseTags(item.tagSet?.item)
455
- }))
456
- };
457
- }
458
- async describeAddresses(options) {
459
- const params = {
460
- Action: "DescribeAddresses",
461
- Version: "2016-11-15"
462
- };
463
- if (options?.AllocationIds) {
464
- options.AllocationIds.forEach((id, i) => {
465
- params[`AllocationId.${i + 1}`] = id;
466
- });
467
- }
468
- if (options?.PublicIps) {
469
- options.PublicIps.forEach((ip, i) => {
470
- params[`PublicIp.${i + 1}`] = ip;
471
- });
472
- }
473
- if (options?.Filters) {
474
- options.Filters.forEach((filter, i) => {
475
- params[`Filter.${i + 1}.Name`] = filter.Name;
476
- filter.Values.forEach((val, j) => {
477
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
478
- });
479
- });
480
- }
481
- const result = await this.client.request({
482
- service: "ec2",
483
- region: this.region,
484
- method: "POST",
485
- path: "/",
486
- headers: {
487
- "Content-Type": "application/x-www-form-urlencoded"
488
- },
489
- body: new URLSearchParams(params).toString()
490
- });
491
- return {
492
- Addresses: this.parseArray(result.addressesSet?.item).map((item) => ({
493
- PublicIp: item.publicIp,
494
- AllocationId: item.allocationId,
495
- AssociationId: item.associationId,
496
- InstanceId: item.instanceId,
497
- NetworkInterfaceId: item.networkInterfaceId,
498
- PrivateIpAddress: item.privateIpAddress,
499
- Domain: item.domain,
500
- Tags: this.parseTags(item.tagSet?.item)
501
- }))
502
- };
503
- }
504
- async allocateAddress(options) {
505
- const params = {
506
- Action: "AllocateAddress",
507
- Version: "2016-11-15"
508
- };
509
- if (options?.Domain) {
510
- params.Domain = options.Domain;
511
- }
512
- if (options?.TagSpecifications) {
513
- options.TagSpecifications.forEach((spec, i) => {
514
- params[`TagSpecification.${i + 1}.ResourceType`] = spec.ResourceType;
515
- spec.Tags.forEach((tag, j) => {
516
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Key`] = tag.Key;
517
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Value`] = tag.Value;
518
- });
519
- });
520
- }
521
- const result = await this.client.request({
522
- service: "ec2",
523
- region: this.region,
524
- method: "POST",
525
- path: "/",
526
- headers: {
527
- "Content-Type": "application/x-www-form-urlencoded"
528
- },
529
- body: new URLSearchParams(params).toString()
530
- });
531
- return {
532
- AllocationId: result.allocationId,
533
- PublicIp: result.publicIp,
534
- Domain: result.domain
535
- };
536
- }
537
- async associateAddress(options) {
538
- const params = {
539
- Action: "AssociateAddress",
540
- Version: "2016-11-15"
541
- };
542
- if (options.AllocationId) {
543
- params.AllocationId = options.AllocationId;
544
- }
545
- if (options.PublicIp) {
546
- params.PublicIp = options.PublicIp;
547
- }
548
- if (options.InstanceId) {
549
- params.InstanceId = options.InstanceId;
550
- }
551
- if (options.NetworkInterfaceId) {
552
- params.NetworkInterfaceId = options.NetworkInterfaceId;
553
- }
554
- if (options.PrivateIpAddress) {
555
- params.PrivateIpAddress = options.PrivateIpAddress;
556
- }
557
- if (options.AllowReassociation) {
558
- params.AllowReassociation = "true";
559
- }
560
- const result = await this.client.request({
561
- service: "ec2",
562
- region: this.region,
563
- method: "POST",
564
- path: "/",
565
- headers: {
566
- "Content-Type": "application/x-www-form-urlencoded"
567
- },
568
- body: new URLSearchParams(params).toString()
569
- });
570
- return {
571
- AssociationId: result.associationId
572
- };
573
- }
574
- async createTags(options) {
575
- const params = {
576
- Action: "CreateTags",
577
- Version: "2016-11-15"
578
- };
579
- options.Resources.forEach((id, i) => {
580
- params[`ResourceId.${i + 1}`] = id;
581
- });
582
- options.Tags.forEach((tag, i) => {
583
- params[`Tag.${i + 1}.Key`] = tag.Key;
584
- params[`Tag.${i + 1}.Value`] = tag.Value;
585
- });
586
- await this.client.request({
587
- service: "ec2",
588
- region: this.region,
589
- method: "POST",
590
- path: "/",
591
- headers: {
592
- "Content-Type": "application/x-www-form-urlencoded"
593
- },
594
- body: new URLSearchParams(params).toString()
595
- });
596
- }
597
- async waitForInstanceState(instanceId, targetState, options) {
598
- const maxWait = options?.maxWaitMs || 300000;
599
- const pollInterval = options?.pollIntervalMs || 5000;
600
- const startTime = Date.now();
601
- while (Date.now() - startTime < maxWait) {
602
- let instance;
603
- try {
604
- instance = await this.getInstance(instanceId);
605
- } catch {
606
- instance = undefined;
607
- }
608
- if (instance?.State?.Name === targetState) {
609
- return instance;
610
- }
611
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
612
- }
613
- return;
614
- }
615
- async createVpc(options) {
616
- const params = {
617
- Action: "CreateVpc",
618
- Version: "2016-11-15",
619
- CidrBlock: options.CidrBlock
620
- };
621
- if (options.InstanceTenancy) {
622
- params.InstanceTenancy = options.InstanceTenancy;
623
- }
624
- if (options.TagSpecifications) {
625
- options.TagSpecifications.forEach((spec, i) => {
626
- params[`TagSpecification.${i + 1}.ResourceType`] = spec.ResourceType;
627
- spec.Tags.forEach((tag, j) => {
628
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Key`] = tag.Key;
629
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Value`] = tag.Value;
630
- });
631
- });
632
- }
633
- const result = await this.client.request({
634
- service: "ec2",
635
- region: this.region,
636
- method: "POST",
637
- path: "/",
638
- headers: {
639
- "Content-Type": "application/x-www-form-urlencoded"
640
- },
641
- body: new URLSearchParams(params).toString()
642
- });
643
- const response = result.CreateVpcResponse || result;
644
- const vpc = response.vpc;
645
- return {
646
- Vpc: vpc ? {
647
- VpcId: vpc.vpcId,
648
- CidrBlock: vpc.cidrBlock,
649
- State: vpc.state,
650
- DhcpOptionsId: vpc.dhcpOptionsId,
651
- InstanceTenancy: vpc.instanceTenancy,
652
- IsDefault: vpc.isDefault === "true",
653
- Tags: this.parseTags(vpc.tagSet?.item)
654
- } : undefined
655
- };
656
- }
657
- async createSubnet(options) {
658
- const params = {
659
- Action: "CreateSubnet",
660
- Version: "2016-11-15",
661
- VpcId: options.VpcId,
662
- CidrBlock: options.CidrBlock
663
- };
664
- if (options.AvailabilityZone) {
665
- params.AvailabilityZone = options.AvailabilityZone;
666
- }
667
- if (options.TagSpecifications) {
668
- options.TagSpecifications.forEach((spec, i) => {
669
- params[`TagSpecification.${i + 1}.ResourceType`] = spec.ResourceType;
670
- spec.Tags.forEach((tag, j) => {
671
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Key`] = tag.Key;
672
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Value`] = tag.Value;
673
- });
674
- });
675
- }
676
- const result = await this.client.request({
677
- service: "ec2",
678
- region: this.region,
679
- method: "POST",
680
- path: "/",
681
- headers: {
682
- "Content-Type": "application/x-www-form-urlencoded"
683
- },
684
- body: new URLSearchParams(params).toString()
685
- });
686
- const response = result.CreateSubnetResponse || result;
687
- const subnet = response.subnet;
688
- return {
689
- Subnet: subnet ? {
690
- SubnetId: subnet.subnetId,
691
- VpcId: subnet.vpcId,
692
- CidrBlock: subnet.cidrBlock,
693
- AvailabilityZone: subnet.availabilityZone,
694
- AvailableIpAddressCount: subnet.availableIpAddressCount ? Number.parseInt(subnet.availableIpAddressCount) : undefined,
695
- State: subnet.state,
696
- MapPublicIpOnLaunch: subnet.mapPublicIpOnLaunch === "true",
697
- Tags: this.parseTags(subnet.tagSet?.item)
698
- } : undefined
699
- };
700
- }
701
- async modifySubnetAttribute(options) {
702
- const params = {
703
- Action: "ModifySubnetAttribute",
704
- Version: "2016-11-15",
705
- SubnetId: options.SubnetId
706
- };
707
- if (options.MapPublicIpOnLaunch !== undefined) {
708
- params["MapPublicIpOnLaunch.Value"] = String(options.MapPublicIpOnLaunch.Value);
709
- }
710
- await this.client.request({
711
- service: "ec2",
712
- region: this.region,
713
- method: "POST",
714
- path: "/",
715
- headers: {
716
- "Content-Type": "application/x-www-form-urlencoded"
717
- },
718
- body: new URLSearchParams(params).toString()
719
- });
720
- }
721
- async createSecurityGroup(options) {
722
- const params = {
723
- Action: "CreateSecurityGroup",
724
- Version: "2016-11-15",
725
- GroupName: options.GroupName,
726
- GroupDescription: options.Description
727
- };
728
- if (options.VpcId) {
729
- params.VpcId = options.VpcId;
730
- }
731
- if (options.TagSpecifications) {
732
- options.TagSpecifications.forEach((spec, i) => {
733
- params[`TagSpecification.${i + 1}.ResourceType`] = spec.ResourceType;
734
- spec.Tags.forEach((tag, j) => {
735
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Key`] = tag.Key;
736
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Value`] = tag.Value;
737
- });
738
- });
739
- }
740
- const result = await this.client.request({
741
- service: "ec2",
742
- region: this.region,
743
- method: "POST",
744
- path: "/",
745
- headers: {
746
- "Content-Type": "application/x-www-form-urlencoded"
747
- },
748
- body: new URLSearchParams(params).toString()
749
- });
750
- const response = result.CreateSecurityGroupResponse || result;
751
- return {
752
- GroupId: response.groupId
753
- };
754
- }
755
- async authorizeSecurityGroupIngress(options) {
756
- const params = {
757
- Action: "AuthorizeSecurityGroupIngress",
758
- Version: "2016-11-15",
759
- GroupId: options.GroupId
760
- };
761
- this.encodeIpPermissions(params, options.IpPermissions);
762
- await this.client.request({
763
- service: "ec2",
764
- region: this.region,
765
- method: "POST",
766
- path: "/",
767
- headers: {
768
- "Content-Type": "application/x-www-form-urlencoded"
769
- },
770
- body: new URLSearchParams(params).toString()
771
- });
772
- }
773
- async authorizeSecurityGroupEgress(options) {
774
- const params = {
775
- Action: "AuthorizeSecurityGroupEgress",
776
- Version: "2016-11-15",
777
- GroupId: options.GroupId
778
- };
779
- this.encodeIpPermissions(params, options.IpPermissions);
780
- await this.client.request({
781
- service: "ec2",
782
- region: this.region,
783
- method: "POST",
784
- path: "/",
785
- headers: {
786
- "Content-Type": "application/x-www-form-urlencoded"
787
- },
788
- body: new URLSearchParams(params).toString()
789
- });
790
- }
791
- async describeRouteTables(options) {
792
- const params = {
793
- Action: "DescribeRouteTables",
794
- Version: "2016-11-15"
795
- };
796
- if (options?.RouteTableIds) {
797
- options.RouteTableIds.forEach((id, i) => {
798
- params[`RouteTableId.${i + 1}`] = id;
799
- });
800
- }
801
- if (options?.Filters) {
802
- options.Filters.forEach((filter, i) => {
803
- params[`Filter.${i + 1}.Name`] = filter.Name;
804
- filter.Values.forEach((val, j) => {
805
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
806
- });
807
- });
808
- }
809
- const result = await this.client.request({
810
- service: "ec2",
811
- region: this.region,
812
- method: "POST",
813
- path: "/",
814
- headers: {
815
- "Content-Type": "application/x-www-form-urlencoded"
816
- },
817
- body: new URLSearchParams(params).toString()
818
- });
819
- const response = result.DescribeRouteTablesResponse || result;
820
- return {
821
- RouteTables: this.parseArray(response.routeTableSet?.item).map((item) => ({
822
- RouteTableId: item.routeTableId,
823
- VpcId: item.vpcId,
824
- Routes: this.parseArray(item.routeSet?.item).map((r) => ({
825
- DestinationCidrBlock: r.destinationCidrBlock,
826
- GatewayId: r.gatewayId,
827
- NatGatewayId: r.natGatewayId,
828
- State: r.state
829
- })),
830
- Associations: this.parseArray(item.associationSet?.item).map((a) => ({
831
- RouteTableAssociationId: a.routeTableAssociationId,
832
- SubnetId: a.subnetId,
833
- Main: a.main === "true" || a.main === true
834
- })),
835
- Tags: this.parseTags(item.tagSet?.item)
836
- }))
837
- };
838
- }
839
- async deleteVpc(vpcId) {
840
- const params = {
841
- Action: "DeleteVpc",
842
- Version: "2016-11-15",
843
- VpcId: vpcId
844
- };
845
- await this.client.request({
846
- service: "ec2",
847
- region: this.region,
848
- method: "POST",
849
- path: "/",
850
- headers: {
851
- "Content-Type": "application/x-www-form-urlencoded"
852
- },
853
- body: new URLSearchParams(params).toString()
854
- });
855
- }
856
- async deleteSubnet(subnetId) {
857
- const params = {
858
- Action: "DeleteSubnet",
859
- Version: "2016-11-15",
860
- SubnetId: subnetId
861
- };
862
- await this.client.request({
863
- service: "ec2",
864
- region: this.region,
865
- method: "POST",
866
- path: "/",
867
- headers: {
868
- "Content-Type": "application/x-www-form-urlencoded"
869
- },
870
- body: new URLSearchParams(params).toString()
871
- });
872
- }
873
- async deleteSecurityGroup(groupId) {
874
- await this.client.request({
875
- service: "ec2",
876
- region: this.region,
877
- method: "POST",
878
- path: "/",
879
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
880
- body: new URLSearchParams({ Action: "DeleteSecurityGroup", Version: "2016-11-15", GroupId: groupId }).toString()
881
- });
882
- }
883
- async describeNetworkInterfaces(options) {
884
- const params = {
885
- Action: "DescribeNetworkInterfaces",
886
- Version: "2016-11-15"
887
- };
888
- if (options?.NetworkInterfaceIds) {
889
- options.NetworkInterfaceIds.forEach((id, i) => {
890
- params[`NetworkInterfaceId.${i + 1}`] = id;
891
- });
892
- }
893
- if (options?.Filters) {
894
- options.Filters.forEach((filter, i) => {
895
- params[`Filter.${i + 1}.Name`] = filter.Name;
896
- filter.Values.forEach((val, j) => {
897
- params[`Filter.${i + 1}.Value.${j + 1}`] = val;
898
- });
899
- });
900
- }
901
- const result = await this.client.request({
902
- service: "ec2",
903
- region: this.region,
904
- method: "POST",
905
- path: "/",
906
- headers: {
907
- "Content-Type": "application/x-www-form-urlencoded"
908
- },
909
- body: new URLSearchParams(params).toString()
910
- });
911
- const response = result.DescribeNetworkInterfacesResponse || result;
912
- return {
913
- NetworkInterfaces: this.parseArray(response.networkInterfaceSet?.item).map((ni) => ({
914
- NetworkInterfaceId: ni.networkInterfaceId,
915
- SubnetId: ni.subnetId,
916
- VpcId: ni.vpcId,
917
- Status: ni.status,
918
- Attachment: ni.attachment ? {
919
- AttachmentId: ni.attachment.attachmentId,
920
- InstanceId: ni.attachment.instanceId,
921
- Status: ni.attachment.status
922
- } : undefined
923
- }))
924
- };
925
- }
926
- async detachNetworkInterface(attachmentId, force) {
927
- const params = {
928
- Action: "DetachNetworkInterface",
929
- Version: "2016-11-15",
930
- AttachmentId: attachmentId
931
- };
932
- if (force) {
933
- params.Force = "true";
934
- }
935
- await this.client.request({
936
- service: "ec2",
937
- region: this.region,
938
- method: "POST",
939
- path: "/",
940
- headers: {
941
- "Content-Type": "application/x-www-form-urlencoded"
942
- },
943
- body: new URLSearchParams(params).toString()
944
- });
945
- }
946
- async deleteNetworkInterface(networkInterfaceId) {
947
- const params = {
948
- Action: "DeleteNetworkInterface",
949
- Version: "2016-11-15",
950
- NetworkInterfaceId: networkInterfaceId
951
- };
952
- await this.client.request({
953
- service: "ec2",
954
- region: this.region,
955
- method: "POST",
956
- path: "/",
957
- headers: {
958
- "Content-Type": "application/x-www-form-urlencoded"
959
- },
960
- body: new URLSearchParams(params).toString()
961
- });
962
- }
963
- async describeRegions() {
964
- const params = {
965
- Action: "DescribeRegions",
966
- Version: "2016-11-15"
967
- };
968
- const result = await this.client.request({
969
- service: "ec2",
970
- region: this.region,
971
- method: "POST",
972
- path: "/",
973
- headers: {
974
- "Content-Type": "application/x-www-form-urlencoded"
975
- },
976
- body: new URLSearchParams(params).toString()
977
- });
978
- const response = result.DescribeRegionsResponse || result;
979
- return {
980
- Regions: this.parseArray(response.regionInfo?.item).map((r) => ({
981
- RegionName: r.regionName,
982
- Endpoint: r.regionEndpoint
983
- }))
984
- };
985
- }
986
- async runInstances(options) {
987
- const params = {
988
- Action: "RunInstances",
989
- Version: "2016-11-15",
990
- ImageId: options.ImageId,
991
- InstanceType: options.InstanceType,
992
- MinCount: String(options.MinCount),
993
- MaxCount: String(options.MaxCount)
994
- };
995
- if (options.SecurityGroupIds) {
996
- options.SecurityGroupIds.forEach((id, i) => {
997
- params[`SecurityGroupId.${i + 1}`] = id;
998
- });
999
- }
1000
- if (options.SubnetId) {
1001
- params.SubnetId = options.SubnetId;
1002
- }
1003
- if (options.UserData) {
1004
- params.UserData = options.UserData;
1005
- }
1006
- if (options.IamInstanceProfile) {
1007
- if (options.IamInstanceProfile.Name) {
1008
- params["IamInstanceProfile.Name"] = options.IamInstanceProfile.Name;
1009
- }
1010
- if (options.IamInstanceProfile.Arn) {
1011
- params["IamInstanceProfile.Arn"] = options.IamInstanceProfile.Arn;
1012
- }
1013
- }
1014
- if (options.TagSpecifications) {
1015
- options.TagSpecifications.forEach((spec, i) => {
1016
- params[`TagSpecification.${i + 1}.ResourceType`] = spec.ResourceType;
1017
- spec.Tags.forEach((tag, j) => {
1018
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Key`] = tag.Key;
1019
- params[`TagSpecification.${i + 1}.Tag.${j + 1}.Value`] = tag.Value;
1020
- });
1021
- });
1022
- }
1023
- const result = await this.client.request({
1024
- service: "ec2",
1025
- region: this.region,
1026
- method: "POST",
1027
- path: "/",
1028
- headers: {
1029
- "Content-Type": "application/x-www-form-urlencoded"
1030
- },
1031
- body: new URLSearchParams(params).toString()
1032
- });
1033
- const response = result.RunInstancesResponse || result;
1034
- return {
1035
- Instances: this.parseInstances(response.instancesSet?.item || response.instancesSet)
1036
- };
1037
- }
1038
- encodeIpPermissions(params, permissions) {
1039
- permissions.forEach((perm, i) => {
1040
- const prefix = `IpPermissions.${i + 1}`;
1041
- if (perm.IpProtocol !== undefined) {
1042
- params[`${prefix}.IpProtocol`] = perm.IpProtocol;
1043
- }
1044
- if (perm.FromPort !== undefined) {
1045
- params[`${prefix}.FromPort`] = String(perm.FromPort);
1046
- }
1047
- if (perm.ToPort !== undefined) {
1048
- params[`${prefix}.ToPort`] = String(perm.ToPort);
1049
- }
1050
- if (perm.IpRanges) {
1051
- perm.IpRanges.forEach((range, j) => {
1052
- if (range.CidrIp) {
1053
- params[`${prefix}.IpRanges.${j + 1}.CidrIp`] = range.CidrIp;
1054
- }
1055
- if (range.Description) {
1056
- params[`${prefix}.IpRanges.${j + 1}.Description`] = range.Description;
1057
- }
1058
- });
1059
- }
1060
- if (perm.Ipv6Ranges) {
1061
- perm.Ipv6Ranges.forEach((range, j) => {
1062
- if (range.CidrIpv6) {
1063
- params[`${prefix}.Ipv6Ranges.${j + 1}.CidrIpv6`] = range.CidrIpv6;
1064
- }
1065
- if (range.Description) {
1066
- params[`${prefix}.Ipv6Ranges.${j + 1}.Description`] = range.Description;
1067
- }
1068
- });
1069
- }
1070
- if (perm.UserIdGroupPairs) {
1071
- perm.UserIdGroupPairs.forEach((pair, j) => {
1072
- if (pair.GroupId) {
1073
- params[`${prefix}.Groups.${j + 1}.GroupId`] = pair.GroupId;
1074
- }
1075
- if (pair.UserId) {
1076
- params[`${prefix}.Groups.${j + 1}.UserId`] = pair.UserId;
1077
- }
1078
- if (pair.Description) {
1079
- params[`${prefix}.Groups.${j + 1}.Description`] = pair.Description;
1080
- }
1081
- });
1082
- }
1083
- });
1084
- }
1085
- parseArray(item) {
1086
- if (!item)
1087
- return [];
1088
- return Array.isArray(item) ? item : [item];
1089
- }
1090
- parseFirstIpv6Address(item) {
1091
- for (const eni of this.parseArray(item)) {
1092
- for (const entry of this.parseArray(eni?.ipv6AddressesSet?.item)) {
1093
- if (entry?.ipv6Address)
1094
- return entry.ipv6Address;
1095
- }
1096
- }
1097
- return;
1098
- }
1099
- parseTags(item) {
1100
- return this.parseArray(item).map((t) => ({
1101
- Key: t.key,
1102
- Value: t.value
1103
- }));
1104
- }
1105
- parseReservations(item) {
1106
- return this.parseArray(item).map((r) => ({
1107
- ReservationId: r.reservationId,
1108
- Instances: this.parseInstances(r.instancesSet?.item || r.instancesSet)
1109
- }));
1110
- }
1111
- parseInstances(item) {
1112
- return this.parseArray(item).map((i) => ({
1113
- InstanceId: i.instanceId,
1114
- ImageId: i.imageId,
1115
- InstanceType: i.instanceType,
1116
- State: i.instanceState ? {
1117
- Code: Number.parseInt(i.instanceState.code),
1118
- Name: i.instanceState.name
1119
- } : undefined,
1120
- PrivateIpAddress: i.privateIpAddress,
1121
- PublicIpAddress: i.ipAddress,
1122
- Ipv6Address: this.parseFirstIpv6Address(i.networkInterfaceSet?.item),
1123
- SubnetId: i.subnetId,
1124
- VpcId: i.vpcId,
1125
- SecurityGroups: this.parseArray(i.groupSet?.item).map((g) => ({
1126
- GroupId: g.groupId,
1127
- GroupName: g.groupName
1128
- })),
1129
- Tags: this.parseTags(i.tagSet?.item),
1130
- LaunchTime: i.launchTime,
1131
- Placement: i.placement ? {
1132
- AvailabilityZone: i.placement.availabilityZone,
1133
- Tenancy: i.placement.tenancy
1134
- } : undefined,
1135
- Architecture: i.architecture,
1136
- RootDeviceType: i.rootDeviceType,
1137
- RootDeviceName: i.rootDeviceName,
1138
- BlockDeviceMappings: this.parseArray(i.blockDeviceMapping?.item).map((b) => ({
1139
- DeviceName: b.deviceName,
1140
- Ebs: b.ebs ? {
1141
- VolumeId: b.ebs.volumeId,
1142
- Status: b.ebs.status,
1143
- AttachTime: b.ebs.attachTime,
1144
- DeleteOnTermination: b.ebs.deleteOnTermination === "true"
1145
- } : undefined
1146
- })),
1147
- IamInstanceProfile: i.iamInstanceProfile ? {
1148
- Arn: i.iamInstanceProfile.arn,
1149
- Id: i.iamInstanceProfile.id
1150
- } : undefined
1151
- }));
1152
- }
1153
- parseIpPermissions(item) {
1154
- return this.parseArray(item).map((p) => ({
1155
- IpProtocol: p.ipProtocol,
1156
- FromPort: p.fromPort ? Number.parseInt(p.fromPort) : undefined,
1157
- ToPort: p.toPort ? Number.parseInt(p.toPort) : undefined,
1158
- IpRanges: this.parseArray(p.ipRanges?.item).map((r) => ({
1159
- CidrIp: r.cidrIp,
1160
- Description: r.description
1161
- })),
1162
- Ipv6Ranges: this.parseArray(p.ipv6Ranges?.item).map((r) => ({
1163
- CidrIpv6: r.cidrIpv6,
1164
- Description: r.description
1165
- })),
1166
- UserIdGroupPairs: this.parseArray(p.groups?.item).map((g) => ({
1167
- GroupId: g.groupId,
1168
- UserId: g.userId,
1169
- Description: g.description
1170
- }))
1171
- }));
1172
- }
1173
- }
1174
-
1175
- // src/aws/ssm.ts
1176
- class SSMClient {
1177
- client;
1178
- region;
1179
- constructor(region = "us-east-1", profile) {
1180
- this.region = region;
1181
- this.client = new AWSClient;
1182
- }
1183
- async putParameter(options) {
1184
- const params = {
1185
- Name: options.Name,
1186
- Value: options.Value
1187
- };
1188
- if (options.Type) {
1189
- params.Type = options.Type;
1190
- }
1191
- if (options.Description) {
1192
- params.Description = options.Description;
1193
- }
1194
- if (options.KeyId) {
1195
- params.KeyId = options.KeyId;
1196
- }
1197
- if (options.Overwrite !== undefined) {
1198
- params.Overwrite = options.Overwrite;
1199
- }
1200
- if (options.AllowedPattern) {
1201
- params.AllowedPattern = options.AllowedPattern;
1202
- }
1203
- if (options.Tags && options.Tags.length > 0) {
1204
- params.Tags = options.Tags;
1205
- }
1206
- if (options.Tier) {
1207
- params.Tier = options.Tier;
1208
- }
1209
- if (options.DataType) {
1210
- params.DataType = options.DataType;
1211
- }
1212
- const result = await this.client.request({
1213
- service: "ssm",
1214
- region: this.region,
1215
- method: "POST",
1216
- path: "/",
1217
- headers: {
1218
- "X-Amz-Target": "AmazonSSM.PutParameter",
1219
- "Content-Type": "application/x-amz-json-1.1"
1220
- },
1221
- body: JSON.stringify(params)
1222
- });
1223
- return {
1224
- Version: result.Version,
1225
- Tier: result.Tier
1226
- };
1227
- }
1228
- async getParameter(options) {
1229
- const params = {
1230
- Name: options.Name
1231
- };
1232
- if (options.WithDecryption !== undefined) {
1233
- params.WithDecryption = options.WithDecryption;
1234
- }
1235
- const result = await this.client.request({
1236
- service: "ssm",
1237
- region: this.region,
1238
- method: "POST",
1239
- path: "/",
1240
- headers: {
1241
- "X-Amz-Target": "AmazonSSM.GetParameter",
1242
- "Content-Type": "application/x-amz-json-1.1"
1243
- },
1244
- body: JSON.stringify(params)
1245
- });
1246
- return {
1247
- Parameter: result.Parameter ? this.parseParameter(result.Parameter) : undefined
1248
- };
1249
- }
1250
- async getParameters(options) {
1251
- const params = {
1252
- Names: options.Names
1253
- };
1254
- if (options.WithDecryption !== undefined) {
1255
- params.WithDecryption = options.WithDecryption;
1256
- }
1257
- const result = await this.client.request({
1258
- service: "ssm",
1259
- region: this.region,
1260
- method: "POST",
1261
- path: "/",
1262
- headers: {
1263
- "X-Amz-Target": "AmazonSSM.GetParameters",
1264
- "Content-Type": "application/x-amz-json-1.1"
1265
- },
1266
- body: JSON.stringify(params)
1267
- });
1268
- return {
1269
- Parameters: result.Parameters?.map((p) => this.parseParameter(p)),
1270
- InvalidParameters: result.InvalidParameters
1271
- };
1272
- }
1273
- async getParametersByPath(options) {
1274
- const params = {
1275
- Path: options.Path
1276
- };
1277
- if (options.Recursive !== undefined) {
1278
- params.Recursive = options.Recursive;
1279
- }
1280
- if (options.WithDecryption !== undefined) {
1281
- params.WithDecryption = options.WithDecryption;
1282
- }
1283
- if (options.MaxResults) {
1284
- params.MaxResults = options.MaxResults;
1285
- }
1286
- if (options.NextToken) {
1287
- params.NextToken = options.NextToken;
1288
- }
1289
- if (options.ParameterFilters && options.ParameterFilters.length > 0) {
1290
- params.ParameterFilters = options.ParameterFilters;
1291
- }
1292
- const result = await this.client.request({
1293
- service: "ssm",
1294
- region: this.region,
1295
- method: "POST",
1296
- path: "/",
1297
- headers: {
1298
- "X-Amz-Target": "AmazonSSM.GetParametersByPath",
1299
- "Content-Type": "application/x-amz-json-1.1"
1300
- },
1301
- body: JSON.stringify(params)
1302
- });
1303
- return {
1304
- Parameters: result.Parameters?.map((p) => this.parseParameter(p)),
1305
- NextToken: result.NextToken
1306
- };
1307
- }
1308
- async deleteParameter(options) {
1309
- const params = {
1310
- Name: options.Name
1311
- };
1312
- await this.client.request({
1313
- service: "ssm",
1314
- region: this.region,
1315
- method: "POST",
1316
- path: "/",
1317
- headers: {
1318
- "X-Amz-Target": "AmazonSSM.DeleteParameter",
1319
- "Content-Type": "application/x-amz-json-1.1"
1320
- },
1321
- body: JSON.stringify(params)
1322
- });
1323
- }
1324
- async deleteParameters(names) {
1325
- const params = {
1326
- Names: names
1327
- };
1328
- const result = await this.client.request({
1329
- service: "ssm",
1330
- region: this.region,
1331
- method: "POST",
1332
- path: "/",
1333
- headers: {
1334
- "X-Amz-Target": "AmazonSSM.DeleteParameters",
1335
- "Content-Type": "application/x-amz-json-1.1"
1336
- },
1337
- body: JSON.stringify(params)
1338
- });
1339
- return {
1340
- DeletedParameters: result.DeletedParameters,
1341
- InvalidParameters: result.InvalidParameters
1342
- };
1343
- }
1344
- async describeParameters(options) {
1345
- const params = {};
1346
- if (options?.Filters && options.Filters.length > 0) {
1347
- params.Filters = options.Filters;
1348
- }
1349
- if (options?.ParameterFilters && options.ParameterFilters.length > 0) {
1350
- params.ParameterFilters = options.ParameterFilters;
1351
- }
1352
- if (options?.MaxResults) {
1353
- params.MaxResults = options.MaxResults;
1354
- }
1355
- if (options?.NextToken) {
1356
- params.NextToken = options.NextToken;
1357
- }
1358
- const result = await this.client.request({
1359
- service: "ssm",
1360
- region: this.region,
1361
- method: "POST",
1362
- path: "/",
1363
- headers: {
1364
- "X-Amz-Target": "AmazonSSM.DescribeParameters",
1365
- "Content-Type": "application/x-amz-json-1.1"
1366
- },
1367
- body: JSON.stringify(params)
1368
- });
1369
- return {
1370
- Parameters: result.Parameters?.map((p) => this.parseParameter(p)),
1371
- NextToken: result.NextToken
1372
- };
1373
- }
1374
- async getParameterHistory(options) {
1375
- const params = {
1376
- Name: options.Name
1377
- };
1378
- if (options.WithDecryption !== undefined) {
1379
- params.WithDecryption = options.WithDecryption;
1380
- }
1381
- if (options.MaxResults) {
1382
- params.MaxResults = options.MaxResults;
1383
- }
1384
- if (options.NextToken) {
1385
- params.NextToken = options.NextToken;
1386
- }
1387
- const result = await this.client.request({
1388
- service: "ssm",
1389
- region: this.region,
1390
- method: "POST",
1391
- path: "/",
1392
- headers: {
1393
- "X-Amz-Target": "AmazonSSM.GetParameterHistory",
1394
- "Content-Type": "application/x-amz-json-1.1"
1395
- },
1396
- body: JSON.stringify(params)
1397
- });
1398
- return {
1399
- Parameters: result.Parameters?.map((p) => ({
1400
- Name: p.Name,
1401
- Type: p.Type,
1402
- KeyId: p.KeyId,
1403
- LastModifiedDate: p.LastModifiedDate,
1404
- LastModifiedUser: p.LastModifiedUser,
1405
- Description: p.Description,
1406
- Value: p.Value,
1407
- Version: p.Version,
1408
- Labels: p.Labels,
1409
- Tier: p.Tier
1410
- })),
1411
- NextToken: result.NextToken
1412
- };
1413
- }
1414
- async labelParameterVersion(options) {
1415
- const params = {
1416
- Name: options.Name,
1417
- Labels: options.Labels
1418
- };
1419
- if (options.ParameterVersion !== undefined) {
1420
- params.ParameterVersion = options.ParameterVersion;
1421
- }
1422
- const result = await this.client.request({
1423
- service: "ssm",
1424
- region: this.region,
1425
- method: "POST",
1426
- path: "/",
1427
- headers: {
1428
- "X-Amz-Target": "AmazonSSM.LabelParameterVersion",
1429
- "Content-Type": "application/x-amz-json-1.1"
1430
- },
1431
- body: JSON.stringify(params)
1432
- });
1433
- return {
1434
- InvalidLabels: result.InvalidLabels,
1435
- ParameterVersion: result.ParameterVersion
1436
- };
1437
- }
1438
- async addTagsToResource(options) {
1439
- const params = {
1440
- ResourceType: options.ResourceType,
1441
- ResourceId: options.ResourceId,
1442
- Tags: options.Tags
1443
- };
1444
- await this.client.request({
1445
- service: "ssm",
1446
- region: this.region,
1447
- method: "POST",
1448
- path: "/",
1449
- headers: {
1450
- "X-Amz-Target": "AmazonSSM.AddTagsToResource",
1451
- "Content-Type": "application/x-amz-json-1.1"
1452
- },
1453
- body: JSON.stringify(params)
1454
- });
1455
- }
1456
- async removeTagsFromResource(options) {
1457
- const params = {
1458
- ResourceType: options.ResourceType,
1459
- ResourceId: options.ResourceId,
1460
- TagKeys: options.TagKeys
1461
- };
1462
- await this.client.request({
1463
- service: "ssm",
1464
- region: this.region,
1465
- method: "POST",
1466
- path: "/",
1467
- headers: {
1468
- "X-Amz-Target": "AmazonSSM.RemoveTagsFromResource",
1469
- "Content-Type": "application/x-amz-json-1.1"
1470
- },
1471
- body: JSON.stringify(params)
1472
- });
1473
- }
1474
- async listTagsForResource(options) {
1475
- const params = {
1476
- ResourceType: options.ResourceType,
1477
- ResourceId: options.ResourceId
1478
- };
1479
- const result = await this.client.request({
1480
- service: "ssm",
1481
- region: this.region,
1482
- method: "POST",
1483
- path: "/",
1484
- headers: {
1485
- "X-Amz-Target": "AmazonSSM.ListTagsForResource",
1486
- "Content-Type": "application/x-amz-json-1.1"
1487
- },
1488
- body: JSON.stringify(params)
1489
- });
1490
- return {
1491
- TagList: result.TagList
1492
- };
1493
- }
1494
- async setString(name, value, options) {
1495
- return this.putParameter({
1496
- Name: name,
1497
- Value: value,
1498
- Type: "String",
1499
- Description: options?.description,
1500
- Overwrite: options?.overwrite ?? true,
1501
- Tags: options?.tags
1502
- });
1503
- }
1504
- async setSecureString(name, value, options) {
1505
- return this.putParameter({
1506
- Name: name,
1507
- Value: value,
1508
- Type: "SecureString",
1509
- Description: options?.description,
1510
- Overwrite: options?.overwrite ?? true,
1511
- KeyId: options?.kmsKeyId,
1512
- Tags: options?.tags
1513
- });
1514
- }
1515
- async getValue(name) {
1516
- const result = await this.getParameter({
1517
- Name: name,
1518
- WithDecryption: true
1519
- });
1520
- return result.Parameter?.Value;
1521
- }
1522
- async getAllByPath(path, recursive = true) {
1523
- const allParams = [];
1524
- let nextToken;
1525
- do {
1526
- const result = await this.getParametersByPath({
1527
- Path: path,
1528
- Recursive: recursive,
1529
- WithDecryption: true,
1530
- NextToken: nextToken
1531
- });
1532
- if (result.Parameters) {
1533
- allParams.push(...result.Parameters);
1534
- }
1535
- nextToken = result.NextToken;
1536
- } while (nextToken);
1537
- return allParams;
1538
- }
1539
- parseParameter(p) {
1540
- return {
1541
- Name: p.Name,
1542
- Type: p.Type,
1543
- Value: p.Value,
1544
- Version: p.Version,
1545
- LastModifiedDate: p.LastModifiedDate,
1546
- ARN: p.ARN,
1547
- DataType: p.DataType,
1548
- Description: p.Description,
1549
- AllowedPattern: p.AllowedPattern,
1550
- KeyId: p.KeyId,
1551
- Tier: p.Tier
1552
- };
1553
- }
1554
- async sendCommand(options) {
1555
- if (!options.InstanceIds && !options.Targets) {
1556
- throw new Error("SendCommand requires either InstanceIds or Targets");
1557
- }
1558
- const params = {
1559
- DocumentName: options.DocumentName
1560
- };
1561
- if (options.InstanceIds) {
1562
- params.InstanceIds = options.InstanceIds;
1563
- }
1564
- if (options.Targets) {
1565
- params.Targets = options.Targets;
1566
- }
1567
- if (options.Parameters) {
1568
- params.Parameters = options.Parameters;
1569
- }
1570
- if (options.TimeoutSeconds) {
1571
- params.TimeoutSeconds = options.TimeoutSeconds;
1572
- }
1573
- if (options.Comment) {
1574
- params.Comment = options.Comment;
1575
- }
1576
- if (options.OutputS3BucketName) {
1577
- params.OutputS3BucketName = options.OutputS3BucketName;
1578
- }
1579
- if (options.OutputS3KeyPrefix) {
1580
- params.OutputS3KeyPrefix = options.OutputS3KeyPrefix;
1581
- }
1582
- const result = await this.client.request({
1583
- service: "ssm",
1584
- region: this.region,
1585
- method: "POST",
1586
- path: "/",
1587
- headers: {
1588
- "X-Amz-Target": "AmazonSSM.SendCommand",
1589
- "Content-Type": "application/x-amz-json-1.1"
1590
- },
1591
- body: JSON.stringify(params)
1592
- });
1593
- return {
1594
- CommandId: result.Command?.CommandId,
1595
- Status: result.Command?.Status,
1596
- StatusDetails: result.Command?.StatusDetails
1597
- };
1598
- }
1599
- async getCommandInvocation(options) {
1600
- const params = {
1601
- CommandId: options.CommandId,
1602
- InstanceId: options.InstanceId
1603
- };
1604
- const result = await this.client.request({
1605
- service: "ssm",
1606
- region: this.region,
1607
- method: "POST",
1608
- path: "/",
1609
- headers: {
1610
- "X-Amz-Target": "AmazonSSM.GetCommandInvocation",
1611
- "Content-Type": "application/x-amz-json-1.1"
1612
- },
1613
- body: JSON.stringify(params)
1614
- });
1615
- return {
1616
- Status: result.Status,
1617
- StatusDetails: result.StatusDetails,
1618
- StandardOutputContent: result.StandardOutputContent,
1619
- StandardErrorContent: result.StandardErrorContent,
1620
- ResponseCode: result.ResponseCode
1621
- };
1622
- }
1623
- async runShellCommand(instanceId, commands, options) {
1624
- const sendResult = await this.sendCommand({
1625
- InstanceIds: [instanceId],
1626
- DocumentName: "AWS-RunShellScript",
1627
- Parameters: {
1628
- commands
1629
- },
1630
- TimeoutSeconds: options?.timeoutSeconds || 600
1631
- });
1632
- if (!sendResult.CommandId) {
1633
- return { success: false, error: "Failed to send command" };
1634
- }
1635
- if (options?.waitForCompletion === false) {
1636
- return { success: true, status: "Pending" };
1637
- }
1638
- const pollInterval = options?.pollIntervalMs || 2000;
1639
- const maxWait = options?.maxWaitMs || 300000;
1640
- const startTime = Date.now();
1641
- while (Date.now() - startTime < maxWait) {
1642
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
1643
- try {
1644
- const invocation = await this.getCommandInvocation({
1645
- CommandId: sendResult.CommandId,
1646
- InstanceId: instanceId
1647
- });
1648
- if (invocation.Status === "Success") {
1649
- return {
1650
- success: true,
1651
- output: invocation.StandardOutputContent,
1652
- error: invocation.StandardErrorContent,
1653
- status: invocation.Status
1654
- };
1655
- }
1656
- if (invocation.Status === "Failed" || invocation.Status === "Cancelled" || invocation.Status === "TimedOut") {
1657
- return {
1658
- success: false,
1659
- output: invocation.StandardOutputContent,
1660
- error: invocation.StandardErrorContent || invocation.StatusDetails,
1661
- status: invocation.Status
1662
- };
1663
- }
1664
- } catch (e) {
1665
- if (!e.message?.includes("InvocationDoesNotExist")) {
1666
- return { success: false, error: e.message };
1667
- }
1668
- }
1669
- }
1670
- return { success: false, error: "Command timed out waiting for completion" };
1671
- }
1672
- async listCommandInvocations(options) {
1673
- const params = {
1674
- CommandId: options.CommandId
1675
- };
1676
- if (options.Details) {
1677
- params.Details = true;
1678
- }
1679
- const result = await this.client.request({
1680
- service: "ssm",
1681
- region: this.region,
1682
- method: "POST",
1683
- path: "/",
1684
- headers: {
1685
- "X-Amz-Target": "AmazonSSM.ListCommandInvocations",
1686
- "Content-Type": "application/x-amz-json-1.1"
1687
- },
1688
- body: JSON.stringify(params)
1689
- });
1690
- const invocations = result.CommandInvocations || [];
1691
- return invocations.map((inv) => ({
1692
- InstanceId: inv.InstanceId,
1693
- Status: inv.Status,
1694
- StatusDetails: inv.StatusDetails,
1695
- StandardOutputContent: inv.CommandPlugins?.[0]?.Output,
1696
- StandardErrorContent: inv.CommandPlugins?.[0]?.StandardErrorUrl
1697
- }));
1698
- }
1699
- async sendCommandByTags(options) {
1700
- const targets = Object.entries(options.tags).map(([key, value]) => ({
1701
- Key: `tag:${key}`,
1702
- Values: [value]
1703
- }));
1704
- const sendResult = await this.sendCommand({
1705
- Targets: targets,
1706
- DocumentName: "AWS-RunShellScript",
1707
- Parameters: { commands: options.commands },
1708
- TimeoutSeconds: options.timeoutSeconds || 600,
1709
- Comment: options.comment
1710
- });
1711
- if (!sendResult.CommandId) {
1712
- return { success: false, instanceCount: 0, perInstance: [], error: "Failed to send command" };
1713
- }
1714
- const pollInterval = options.pollIntervalMs || 3000;
1715
- const maxWait = options.maxWaitMs || 600000;
1716
- const startTime = Date.now();
1717
- const terminalStatuses = new Set(["Success", "Failed", "Cancelled", "TimedOut"]);
1718
- let lastInvocations = [];
1719
- while (Date.now() - startTime < maxWait) {
1720
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
1721
- try {
1722
- lastInvocations = await this.listCommandInvocations({
1723
- CommandId: sendResult.CommandId,
1724
- Details: true
1725
- });
1726
- if (lastInvocations.length === 0)
1727
- continue;
1728
- const allDone = lastInvocations.every((inv) => terminalStatuses.has(inv.Status || ""));
1729
- if (allDone) {
1730
- const perInstance = lastInvocations.map((inv) => ({
1731
- instanceId: inv.InstanceId,
1732
- status: inv.Status || "Unknown",
1733
- output: inv.StandardOutputContent,
1734
- error: inv.StandardErrorContent || inv.StatusDetails
1735
- }));
1736
- const allSucceeded = lastInvocations.every((inv) => inv.Status === "Success");
1737
- return {
1738
- success: allSucceeded,
1739
- instanceCount: lastInvocations.length,
1740
- perInstance,
1741
- error: allSucceeded ? undefined : "One or more instances reported a non-success status"
1742
- };
1743
- }
1744
- } catch (e) {
1745
- if (!e.message?.includes("InvocationDoesNotExist")) {
1746
- return { success: false, instanceCount: 0, perInstance: [], error: e.message };
1747
- }
1748
- }
1749
- }
1750
- return {
1751
- success: false,
1752
- instanceCount: lastInvocations.length,
1753
- perInstance: lastInvocations.map((inv) => ({
1754
- instanceId: inv.InstanceId,
1755
- status: inv.Status || "Unknown"
1756
- })),
1757
- error: "Command timed out waiting for all instances to complete"
1758
- };
1759
- }
1760
- }
1761
-
1762
- export { EC2Client, SSMClient };