alchemy 0.54.0 → 0.55.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.
- package/lib/aws/ec2/index.d.ts +10 -0
- package/lib/aws/ec2/index.d.ts.map +1 -0
- package/lib/aws/ec2/index.js +10 -0
- package/lib/aws/ec2/index.js.map +1 -0
- package/lib/aws/ec2/internet-gateway-attachment.d.ts +150 -0
- package/lib/aws/ec2/internet-gateway-attachment.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway-attachment.js +248 -0
- package/lib/aws/ec2/internet-gateway-attachment.js.map +1 -0
- package/lib/aws/ec2/internet-gateway.d.ts +132 -0
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.js +311 -0
- package/lib/aws/ec2/internet-gateway.js.map +1 -0
- package/lib/aws/ec2/nat-gateway.d.ts +145 -0
- package/lib/aws/ec2/nat-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/nat-gateway.js +618 -0
- package/lib/aws/ec2/nat-gateway.js.map +1 -0
- package/lib/aws/ec2/route-table-association.d.ts +134 -0
- package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.js +364 -0
- package/lib/aws/ec2/route-table-association.js.map +1 -0
- package/lib/aws/ec2/route-table.d.ts +94 -0
- package/lib/aws/ec2/route-table.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.js +253 -0
- package/lib/aws/ec2/route-table.js.map +1 -0
- package/lib/aws/ec2/route.d.ts +130 -0
- package/lib/aws/ec2/route.d.ts.map +1 -0
- package/lib/aws/ec2/route.js +253 -0
- package/lib/aws/ec2/route.js.map +1 -0
- package/lib/aws/ec2/security-group-rule.d.ts +84 -0
- package/lib/aws/ec2/security-group-rule.d.ts.map +1 -0
- package/lib/aws/ec2/security-group-rule.js +123 -0
- package/lib/aws/ec2/security-group-rule.js.map +1 -0
- package/lib/aws/ec2/security-group.d.ts +84 -0
- package/lib/aws/ec2/security-group.d.ts.map +1 -0
- package/lib/aws/ec2/security-group.js +207 -0
- package/lib/aws/ec2/security-group.js.map +1 -0
- package/lib/aws/ec2/subnet.d.ts +110 -0
- package/lib/aws/ec2/subnet.d.ts.map +1 -0
- package/lib/aws/ec2/subnet.js +336 -0
- package/lib/aws/ec2/subnet.js.map +1 -0
- package/lib/aws/ec2/utils.d.ts +15 -0
- package/lib/aws/ec2/utils.d.ts.map +1 -0
- package/lib/aws/ec2/utils.js +79 -0
- package/lib/aws/ec2/utils.js.map +1 -0
- package/lib/aws/ec2/vpc.d.ts +160 -0
- package/lib/aws/ec2/vpc.d.ts.map +1 -0
- package/lib/aws/ec2/vpc.js +453 -0
- package/lib/aws/ec2/vpc.js.map +1 -0
- package/lib/aws/index.d.ts +7 -0
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +8 -0
- package/lib/aws/index.js.map +1 -1
- package/lib/aws/utils.d.ts +25 -0
- package/lib/aws/utils.d.ts.map +1 -0
- package/lib/aws/utils.js +89 -0
- package/lib/aws/utils.js.map +1 -0
- package/lib/build-date.d.ts +6 -0
- package/lib/build-date.d.ts.map +1 -0
- package/lib/build-date.js +8 -0
- package/lib/build-date.js.map +1 -0
- package/lib/util/params.d.ts +5 -0
- package/lib/util/params.d.ts.map +1 -0
- package/lib/util/params.js +30 -0
- package/lib/util/params.js.map +1 -0
- package/lib/util/timeout.d.ts +31 -0
- package/lib/util/timeout.d.ts.map +1 -0
- package/lib/util/timeout.js +109 -0
- package/lib/util/timeout.js.map +1 -0
- package/lib/util/xml.d.ts +5 -0
- package/lib/util/xml.d.ts.map +1 -0
- package/lib/util/xml.js +8 -0
- package/lib/util/xml.js.map +1 -0
- package/package.json +3 -1
- package/src/aws/ec2/index.ts +9 -0
- package/src/aws/ec2/internet-gateway-attachment.ts +468 -0
- package/src/aws/ec2/internet-gateway.ts +557 -0
- package/src/aws/ec2/nat-gateway.ts +1123 -0
- package/src/aws/ec2/route-table-association.ts +747 -0
- package/src/aws/ec2/route-table.ts +452 -0
- package/src/aws/ec2/route.ts +447 -0
- package/src/aws/ec2/security-group-rule.ts +229 -0
- package/src/aws/ec2/security-group.ts +418 -0
- package/src/aws/ec2/subnet.ts +625 -0
- package/src/aws/ec2/utils.ts +102 -0
- package/src/aws/ec2/vpc.ts +969 -0
- package/src/aws/index.ts +9 -0
- package/src/aws/utils.ts +137 -0
- package/src/build-date.ts +8 -0
- package/src/util/params.ts +33 -0
- package/src/util/timeout.ts +178 -0
- package/src/util/xml.ts +7 -0
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
import type { AwsClient } from "aws4fetch";
|
|
2
|
+
import { XMLParser } from "fast-xml-parser";
|
|
3
|
+
import type { Context } from "../../context.ts";
|
|
4
|
+
import { Resource } from "../../resource.ts";
|
|
5
|
+
import { ignore } from "../../util/ignore.ts";
|
|
6
|
+
import { logger } from "../../util/logger.ts";
|
|
7
|
+
import {
|
|
8
|
+
mergeTimeoutConfig,
|
|
9
|
+
type TimeoutConfig,
|
|
10
|
+
waitForResourceState,
|
|
11
|
+
} from "../../util/timeout.ts";
|
|
12
|
+
import { callEC2Api, createEC2Client } from "./utils.ts";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Properties for creating or updating a VPC
|
|
16
|
+
*/
|
|
17
|
+
export interface VpcProps {
|
|
18
|
+
/**
|
|
19
|
+
* The IPv4 network range for the VPC, in CIDR notation
|
|
20
|
+
* @example "10.0.0.0/16"
|
|
21
|
+
*/
|
|
22
|
+
cidrBlock: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Whether to enable DNS resolution for the VPC
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
enableDnsSupport?: boolean;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Whether to enable DNS hostnames for the VPC
|
|
32
|
+
* @default true
|
|
33
|
+
*/
|
|
34
|
+
enableDnsHostnames?: boolean;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The tenancy option for instances launched into the VPC
|
|
38
|
+
* @default "default"
|
|
39
|
+
*/
|
|
40
|
+
instanceTenancy?: "default" | "dedicated" | "host";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Additional IPv4 CIDR blocks to associate with the VPC
|
|
44
|
+
* These will be associated after VPC creation
|
|
45
|
+
*/
|
|
46
|
+
additionalCidrBlocks?: string[];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* IPv6 CIDR block configuration
|
|
50
|
+
*/
|
|
51
|
+
ipv6Config?: {
|
|
52
|
+
/**
|
|
53
|
+
* Whether to assign an Amazon-provided IPv6 CIDR block
|
|
54
|
+
*/
|
|
55
|
+
amazonProvidedIpv6CidrBlock?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The ID of an IPv6 address pool from which to allocate the IPv6 CIDR block
|
|
58
|
+
*/
|
|
59
|
+
ipv6Pool?: string;
|
|
60
|
+
/**
|
|
61
|
+
* The netmask length of the IPv6 CIDR block
|
|
62
|
+
* @default 56
|
|
63
|
+
*/
|
|
64
|
+
ipv6CidrBlockNetworkBorderGroup?: string;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Tags to apply to the VPC
|
|
69
|
+
*/
|
|
70
|
+
tags?: Record<string, string>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Timeout configuration for VPC operations
|
|
74
|
+
* @default VPC-specific sensible defaults (60 attempts, 2000ms delay)
|
|
75
|
+
*/
|
|
76
|
+
timeout?: Partial<TimeoutConfig>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Output returned after VPC creation/update
|
|
81
|
+
*/
|
|
82
|
+
export interface Vpc extends Resource<"aws::Vpc">, VpcProps {
|
|
83
|
+
/**
|
|
84
|
+
* The ID of the VPC
|
|
85
|
+
*/
|
|
86
|
+
vpcId: string;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The current state of the VPC
|
|
90
|
+
*/
|
|
91
|
+
state: "pending" | "available";
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Whether the VPC is the default VPC
|
|
95
|
+
*/
|
|
96
|
+
isDefault: boolean;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The ID of the set of DHCP options associated with the VPC
|
|
100
|
+
*/
|
|
101
|
+
dhcpOptionsId: string;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Information about the IPv4 CIDR blocks associated with the VPC
|
|
105
|
+
*/
|
|
106
|
+
cidrBlockAssociationSet?: Array<{
|
|
107
|
+
associationId: string;
|
|
108
|
+
cidrBlock: string;
|
|
109
|
+
cidrBlockState: {
|
|
110
|
+
state:
|
|
111
|
+
| "associating"
|
|
112
|
+
| "associated"
|
|
113
|
+
| "disassociating"
|
|
114
|
+
| "disassociated"
|
|
115
|
+
| "failing"
|
|
116
|
+
| "failed";
|
|
117
|
+
statusMessage?: string;
|
|
118
|
+
};
|
|
119
|
+
}>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Information about the IPv6 CIDR blocks associated with the VPC
|
|
123
|
+
*/
|
|
124
|
+
ipv6CidrBlockAssociationSet?: Array<{
|
|
125
|
+
associationId: string;
|
|
126
|
+
ipv6CidrBlock: string;
|
|
127
|
+
ipv6CidrBlockState: {
|
|
128
|
+
state:
|
|
129
|
+
| "associating"
|
|
130
|
+
| "associated"
|
|
131
|
+
| "disassociating"
|
|
132
|
+
| "disassociated"
|
|
133
|
+
| "failing"
|
|
134
|
+
| "failed";
|
|
135
|
+
statusMessage?: string;
|
|
136
|
+
};
|
|
137
|
+
networkBorderGroup?: string;
|
|
138
|
+
ipv6Pool?: string;
|
|
139
|
+
}>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The ID of the AWS account that owns the VPC
|
|
143
|
+
*/
|
|
144
|
+
ownerId?: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* AWS VPC (Virtual Private Cloud) Resource
|
|
149
|
+
*
|
|
150
|
+
* Creates and manages Amazon VPC instances with configurable CIDR blocks,
|
|
151
|
+
* DNS settings, and instance tenancy options.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Create a basic VPC with default settings
|
|
155
|
+
* const vpc = await Vpc("main-vpc", {
|
|
156
|
+
* cidrBlock: "10.0.0.0/16",
|
|
157
|
+
* tags: {
|
|
158
|
+
* Name: "main-vpc",
|
|
159
|
+
* Environment: "production"
|
|
160
|
+
* }
|
|
161
|
+
* });
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* // Create a VPC with custom DNS settings
|
|
165
|
+
* const vpc = await Vpc("custom-vpc", {
|
|
166
|
+
* cidrBlock: "172.16.0.0/16",
|
|
167
|
+
* enableDnsSupport: true,
|
|
168
|
+
* enableDnsHostnames: true,
|
|
169
|
+
* instanceTenancy: "default",
|
|
170
|
+
* tags: {
|
|
171
|
+
* Name: "custom-vpc"
|
|
172
|
+
* }
|
|
173
|
+
* });
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* // Create a VPC with dedicated tenancy and custom timeout
|
|
177
|
+
* const dedicatedVpc = await Vpc("dedicated-vpc", {
|
|
178
|
+
* cidrBlock: "192.168.0.0/16",
|
|
179
|
+
* instanceTenancy: "dedicated",
|
|
180
|
+
* enableDnsSupport: false,
|
|
181
|
+
* enableDnsHostnames: false,
|
|
182
|
+
* timeout: {
|
|
183
|
+
* maxAttempts: 90,
|
|
184
|
+
* delayMs: 3000
|
|
185
|
+
* },
|
|
186
|
+
* tags: {
|
|
187
|
+
* Name: "dedicated-vpc",
|
|
188
|
+
* Type: "isolated"
|
|
189
|
+
* }
|
|
190
|
+
* });
|
|
191
|
+
*/
|
|
192
|
+
export const Vpc = Resource(
|
|
193
|
+
"aws::Vpc",
|
|
194
|
+
async function (
|
|
195
|
+
this: Context<Vpc>,
|
|
196
|
+
_id: string,
|
|
197
|
+
props: VpcProps,
|
|
198
|
+
): Promise<Vpc> {
|
|
199
|
+
const client = await createEC2Client();
|
|
200
|
+
const timeoutConfig = mergeTimeoutConfig(VPC_TIMEOUT, props.timeout);
|
|
201
|
+
|
|
202
|
+
if (this.phase === "delete") {
|
|
203
|
+
if (this.output?.vpcId) {
|
|
204
|
+
logger.log(`🗑️ Deleting VPC: ${this.output.vpcId}`);
|
|
205
|
+
|
|
206
|
+
// Simply delete the VPC - other resources should handle themselves
|
|
207
|
+
await ignore("InvalidVpcID.NotFound", async () => {
|
|
208
|
+
await callEC2Api(client, "DeleteVpc", parseVpcXmlResponse, {
|
|
209
|
+
VpcId: this.output.vpcId,
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Wait for VPC to be fully deleted
|
|
214
|
+
await waitForVpcDeleted(client, this.output.vpcId, timeoutConfig);
|
|
215
|
+
|
|
216
|
+
logger.log(` ✅ VPC ${this.output.vpcId} deletion completed`);
|
|
217
|
+
}
|
|
218
|
+
return this.destroy();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let vpc: AwsVpc;
|
|
222
|
+
|
|
223
|
+
if (this.phase === "update" && this.output?.vpcId) {
|
|
224
|
+
// Get existing VPC
|
|
225
|
+
const response = await callEC2Api<DescribeVpcsResponse>(
|
|
226
|
+
client,
|
|
227
|
+
"DescribeVpcs",
|
|
228
|
+
parseVpcXmlResponse,
|
|
229
|
+
{
|
|
230
|
+
"VpcId.1": this.output.vpcId,
|
|
231
|
+
},
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (!response.Vpcs?.[0]) {
|
|
235
|
+
throw new Error(`VPC ${this.output.vpcId} not found`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
vpc = response.Vpcs[0];
|
|
239
|
+
|
|
240
|
+
// Update DNS attributes if they've changed
|
|
241
|
+
if (props.enableDnsSupport !== undefined) {
|
|
242
|
+
const modifyParams: ModifyVpcAttributeParams = {
|
|
243
|
+
VpcId: vpc.VpcId,
|
|
244
|
+
EnableDnsSupport: {
|
|
245
|
+
Value: props.enableDnsSupport,
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
await callEC2Api(
|
|
249
|
+
client,
|
|
250
|
+
"ModifyVpcAttribute",
|
|
251
|
+
parseVpcXmlResponse,
|
|
252
|
+
convertModifyVpcAttributeParamsToAwsFormat(modifyParams),
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (props.enableDnsHostnames !== undefined) {
|
|
257
|
+
const modifyParams: ModifyVpcAttributeParams = {
|
|
258
|
+
VpcId: vpc.VpcId,
|
|
259
|
+
EnableDnsHostnames: {
|
|
260
|
+
Value: props.enableDnsHostnames,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
await callEC2Api(
|
|
264
|
+
client,
|
|
265
|
+
"ModifyVpcAttribute",
|
|
266
|
+
parseVpcXmlResponse,
|
|
267
|
+
convertModifyVpcAttributeParamsToAwsFormat(modifyParams),
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
// Create new VPC
|
|
272
|
+
const createVpcParams: CreateVpcParams = {
|
|
273
|
+
CidrBlock: props.cidrBlock,
|
|
274
|
+
InstanceTenancy: props.instanceTenancy || "default",
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// Add tags if specified
|
|
278
|
+
if (props.tags) {
|
|
279
|
+
createVpcParams.TagSpecifications = [
|
|
280
|
+
{
|
|
281
|
+
ResourceType: "vpc",
|
|
282
|
+
Tags: Object.entries(props.tags).map(([key, value]) => ({
|
|
283
|
+
Key: key,
|
|
284
|
+
Value: value,
|
|
285
|
+
})),
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const createParams = convertVpcParamsToAwsFormat(createVpcParams);
|
|
291
|
+
|
|
292
|
+
const response = await callEC2Api<CreateVpcResponse>(
|
|
293
|
+
client,
|
|
294
|
+
"CreateVpc",
|
|
295
|
+
parseVpcXmlResponse,
|
|
296
|
+
createParams,
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
if (!response.Vpc) {
|
|
300
|
+
throw new Error(
|
|
301
|
+
`Failed to create VPC - Response: ${JSON.stringify(response)}`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
vpc = response.Vpc;
|
|
306
|
+
|
|
307
|
+
// Wait for VPC to be available
|
|
308
|
+
await waitForVpcAvailable(client, vpc.VpcId!, timeoutConfig);
|
|
309
|
+
|
|
310
|
+
// Set DNS attributes if specified
|
|
311
|
+
if (props.enableDnsSupport !== undefined) {
|
|
312
|
+
const modifyParams: ModifyVpcAttributeParams = {
|
|
313
|
+
VpcId: vpc.VpcId,
|
|
314
|
+
EnableDnsSupport: {
|
|
315
|
+
Value: props.enableDnsSupport,
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
await callEC2Api(
|
|
319
|
+
client,
|
|
320
|
+
"ModifyVpcAttribute",
|
|
321
|
+
parseVpcXmlResponse,
|
|
322
|
+
convertModifyVpcAttributeParamsToAwsFormat(modifyParams),
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (props.enableDnsHostnames !== undefined) {
|
|
327
|
+
const modifyParams: ModifyVpcAttributeParams = {
|
|
328
|
+
VpcId: vpc.VpcId,
|
|
329
|
+
EnableDnsHostnames: {
|
|
330
|
+
Value: props.enableDnsHostnames,
|
|
331
|
+
},
|
|
332
|
+
};
|
|
333
|
+
await callEC2Api(
|
|
334
|
+
client,
|
|
335
|
+
"ModifyVpcAttribute",
|
|
336
|
+
parseVpcXmlResponse,
|
|
337
|
+
convertModifyVpcAttributeParamsToAwsFormat(modifyParams),
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return this({
|
|
343
|
+
vpcId: vpc.VpcId!,
|
|
344
|
+
state: vpc.State as "pending" | "available",
|
|
345
|
+
isDefault: vpc.IsDefault || false,
|
|
346
|
+
dhcpOptionsId: vpc.DhcpOptionsId!,
|
|
347
|
+
...props,
|
|
348
|
+
});
|
|
349
|
+
},
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* VPC timeout constants
|
|
354
|
+
*/
|
|
355
|
+
export const VPC_TIMEOUT: TimeoutConfig = {
|
|
356
|
+
maxAttempts: 60,
|
|
357
|
+
delayMs: 2000, // 2 seconds - VPCs are medium speed resources
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Comprehensive AWS VPC API Parameter Types
|
|
362
|
+
*/
|
|
363
|
+
|
|
364
|
+
// Common structures
|
|
365
|
+
interface TagSpecification {
|
|
366
|
+
ResourceType: string;
|
|
367
|
+
Tags: Array<{
|
|
368
|
+
Key: string;
|
|
369
|
+
Value: string;
|
|
370
|
+
}>;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// VPC API Request Parameters
|
|
374
|
+
interface CreateVpcParams {
|
|
375
|
+
CidrBlock: string;
|
|
376
|
+
InstanceTenancy?: "default" | "dedicated" | "host";
|
|
377
|
+
TagSpecifications?: TagSpecification[];
|
|
378
|
+
AmazonProvidedIpv6CidrBlock?: boolean;
|
|
379
|
+
Ipv6Pool?: string;
|
|
380
|
+
Ipv6CidrBlock?: string;
|
|
381
|
+
Ipv4IpamPoolId?: string;
|
|
382
|
+
Ipv4NetmaskLength?: number;
|
|
383
|
+
Ipv6IpamPoolId?: string;
|
|
384
|
+
Ipv6NetmaskLength?: number;
|
|
385
|
+
DryRun?: boolean;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
interface ModifyVpcAttributeParams {
|
|
389
|
+
VpcId: string;
|
|
390
|
+
EnableDnsHostnames?: {
|
|
391
|
+
Value: boolean;
|
|
392
|
+
};
|
|
393
|
+
EnableDnsSupport?: {
|
|
394
|
+
Value: boolean;
|
|
395
|
+
};
|
|
396
|
+
EnableNetworkAddressUsageMetrics?: {
|
|
397
|
+
Value: boolean;
|
|
398
|
+
};
|
|
399
|
+
DryRun?: boolean;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Helper function to convert typed VPC parameters to AWS API format
|
|
404
|
+
*/
|
|
405
|
+
function convertVpcParamsToAwsFormat(
|
|
406
|
+
params: CreateVpcParams,
|
|
407
|
+
): Record<string, string> {
|
|
408
|
+
const awsParams: Record<string, string> = {
|
|
409
|
+
CidrBlock: params.CidrBlock,
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
if (params.InstanceTenancy) {
|
|
413
|
+
awsParams.InstanceTenancy = params.InstanceTenancy;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (params.AmazonProvidedIpv6CidrBlock !== undefined) {
|
|
417
|
+
awsParams.AmazonProvidedIpv6CidrBlock =
|
|
418
|
+
params.AmazonProvidedIpv6CidrBlock.toString();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (params.Ipv6Pool) {
|
|
422
|
+
awsParams.Ipv6Pool = params.Ipv6Pool;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (params.Ipv6CidrBlock) {
|
|
426
|
+
awsParams.Ipv6CidrBlock = params.Ipv6CidrBlock;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (params.Ipv4IpamPoolId) {
|
|
430
|
+
awsParams.Ipv4IpamPoolId = params.Ipv4IpamPoolId;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (params.Ipv4NetmaskLength !== undefined) {
|
|
434
|
+
awsParams.Ipv4NetmaskLength = params.Ipv4NetmaskLength.toString();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (params.Ipv6IpamPoolId) {
|
|
438
|
+
awsParams.Ipv6IpamPoolId = params.Ipv6IpamPoolId;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (params.Ipv6NetmaskLength !== undefined) {
|
|
442
|
+
awsParams.Ipv6NetmaskLength = params.Ipv6NetmaskLength.toString();
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (params.DryRun !== undefined) {
|
|
446
|
+
awsParams.DryRun = params.DryRun.toString();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Handle TagSpecifications
|
|
450
|
+
if (params.TagSpecifications) {
|
|
451
|
+
params.TagSpecifications.forEach((tagSpec, specIndex) => {
|
|
452
|
+
const specNum = specIndex + 1;
|
|
453
|
+
awsParams[`TagSpecification.${specNum}.ResourceType`] =
|
|
454
|
+
tagSpec.ResourceType;
|
|
455
|
+
|
|
456
|
+
tagSpec.Tags.forEach((tag, tagIndex) => {
|
|
457
|
+
const tagNum = tagIndex + 1;
|
|
458
|
+
awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Key`] = tag.Key;
|
|
459
|
+
awsParams[`TagSpecification.${specNum}.Tag.${tagNum}.Value`] =
|
|
460
|
+
tag.Value;
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return awsParams;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function convertModifyVpcAttributeParamsToAwsFormat(
|
|
469
|
+
params: ModifyVpcAttributeParams,
|
|
470
|
+
): Record<string, string> {
|
|
471
|
+
const awsParams: Record<string, string> = {
|
|
472
|
+
VpcId: params.VpcId,
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
if (params.EnableDnsHostnames) {
|
|
476
|
+
awsParams["EnableDnsHostnames.Value"] =
|
|
477
|
+
params.EnableDnsHostnames.Value.toString();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (params.EnableDnsSupport) {
|
|
481
|
+
awsParams["EnableDnsSupport.Value"] =
|
|
482
|
+
params.EnableDnsSupport.Value.toString();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (params.EnableNetworkAddressUsageMetrics) {
|
|
486
|
+
awsParams["EnableNetworkAddressUsageMetrics.Value"] =
|
|
487
|
+
params.EnableNetworkAddressUsageMetrics.Value.toString();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
if (params.DryRun !== undefined) {
|
|
491
|
+
awsParams.DryRun = params.DryRun.toString();
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return awsParams;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* AWS VPC API response types
|
|
499
|
+
*/
|
|
500
|
+
interface AwsVpc {
|
|
501
|
+
VpcId: string;
|
|
502
|
+
State: "pending" | "available";
|
|
503
|
+
CidrBlock: string;
|
|
504
|
+
DhcpOptionsId: string;
|
|
505
|
+
InstanceTenancy: "default" | "dedicated" | "host";
|
|
506
|
+
IsDefault: boolean;
|
|
507
|
+
Tags?: Array<{
|
|
508
|
+
Key: string;
|
|
509
|
+
Value: string;
|
|
510
|
+
}>;
|
|
511
|
+
CidrBlockAssociationSet?: Array<{
|
|
512
|
+
AssociationId: string;
|
|
513
|
+
CidrBlock: string;
|
|
514
|
+
CidrBlockState: {
|
|
515
|
+
State:
|
|
516
|
+
| "associating"
|
|
517
|
+
| "associated"
|
|
518
|
+
| "disassociating"
|
|
519
|
+
| "disassociated"
|
|
520
|
+
| "failing"
|
|
521
|
+
| "failed";
|
|
522
|
+
StatusMessage?: string;
|
|
523
|
+
};
|
|
524
|
+
}>;
|
|
525
|
+
Ipv6CidrBlockAssociationSet?: Array<{
|
|
526
|
+
AssociationId: string;
|
|
527
|
+
Ipv6CidrBlock: string;
|
|
528
|
+
Ipv6CidrBlockState: {
|
|
529
|
+
State:
|
|
530
|
+
| "associating"
|
|
531
|
+
| "associated"
|
|
532
|
+
| "disassociating"
|
|
533
|
+
| "disassociated"
|
|
534
|
+
| "failing"
|
|
535
|
+
| "failed";
|
|
536
|
+
StatusMessage?: string;
|
|
537
|
+
};
|
|
538
|
+
NetworkBorderGroup?: string;
|
|
539
|
+
Ipv6Pool?: string;
|
|
540
|
+
}>;
|
|
541
|
+
OwnerId?: string;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
interface CreateVpcResponse {
|
|
545
|
+
Vpc: AwsVpc;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
interface DescribeVpcsResponse {
|
|
549
|
+
Vpcs: AwsVpc[];
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
interface AwsSecurityGroup {
|
|
553
|
+
GroupId: string;
|
|
554
|
+
GroupName: string;
|
|
555
|
+
VpcId: string;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
interface DescribeSecurityGroupsResponse {
|
|
559
|
+
SecurityGroups: AwsSecurityGroup[];
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Raw XML parsing interfaces for type safety
|
|
564
|
+
*/
|
|
565
|
+
interface RawVpcXmlItem {
|
|
566
|
+
vpcId: string;
|
|
567
|
+
state: string;
|
|
568
|
+
cidrBlock: string;
|
|
569
|
+
dhcpOptionsId: string;
|
|
570
|
+
instanceTenancy: string;
|
|
571
|
+
isDefault: string | boolean;
|
|
572
|
+
tagSet?: {
|
|
573
|
+
item?:
|
|
574
|
+
| Array<{
|
|
575
|
+
key: string;
|
|
576
|
+
value: string;
|
|
577
|
+
}>
|
|
578
|
+
| {
|
|
579
|
+
key: string;
|
|
580
|
+
value: string;
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
cidrBlockAssociationSet?: {
|
|
584
|
+
item?:
|
|
585
|
+
| Array<{
|
|
586
|
+
associationId: string;
|
|
587
|
+
cidrBlock: string;
|
|
588
|
+
cidrBlockState: {
|
|
589
|
+
state: string;
|
|
590
|
+
statusMessage?: string;
|
|
591
|
+
};
|
|
592
|
+
}>
|
|
593
|
+
| {
|
|
594
|
+
associationId: string;
|
|
595
|
+
cidrBlock: string;
|
|
596
|
+
cidrBlockState: {
|
|
597
|
+
state: string;
|
|
598
|
+
statusMessage?: string;
|
|
599
|
+
};
|
|
600
|
+
};
|
|
601
|
+
};
|
|
602
|
+
ipv6CidrBlockAssociationSet?: {
|
|
603
|
+
item?:
|
|
604
|
+
| Array<{
|
|
605
|
+
associationId: string;
|
|
606
|
+
ipv6CidrBlock: string;
|
|
607
|
+
ipv6CidrBlockState: {
|
|
608
|
+
state: string;
|
|
609
|
+
statusMessage?: string;
|
|
610
|
+
};
|
|
611
|
+
networkBorderGroup?: string;
|
|
612
|
+
ipv6Pool?: string;
|
|
613
|
+
}>
|
|
614
|
+
| {
|
|
615
|
+
associationId: string;
|
|
616
|
+
ipv6CidrBlock: string;
|
|
617
|
+
ipv6CidrBlockState: {
|
|
618
|
+
state: string;
|
|
619
|
+
statusMessage?: string;
|
|
620
|
+
};
|
|
621
|
+
networkBorderGroup?: string;
|
|
622
|
+
ipv6Pool?: string;
|
|
623
|
+
};
|
|
624
|
+
};
|
|
625
|
+
ownerId?: string;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
interface RawSecurityGroupXmlItem {
|
|
629
|
+
groupId: string;
|
|
630
|
+
groupName: string;
|
|
631
|
+
vpcId: string;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Parse XML responses specifically for VPC operations
|
|
636
|
+
*/
|
|
637
|
+
function parseVpcXmlResponse<
|
|
638
|
+
T extends
|
|
639
|
+
| CreateVpcResponse
|
|
640
|
+
| DescribeVpcsResponse
|
|
641
|
+
| DescribeSecurityGroupsResponse
|
|
642
|
+
| { success: boolean },
|
|
643
|
+
>(xmlText: string): T {
|
|
644
|
+
const parser = new XMLParser({
|
|
645
|
+
ignoreAttributes: true,
|
|
646
|
+
parseAttributeValue: true,
|
|
647
|
+
parseTagValue: true,
|
|
648
|
+
trimValues: true,
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
const parsed = parser.parse(xmlText);
|
|
652
|
+
const result: Record<string, unknown> = {};
|
|
653
|
+
|
|
654
|
+
// Parse CreateVpcResponse
|
|
655
|
+
if (parsed.CreateVpcResponse) {
|
|
656
|
+
const vpc = parsed.CreateVpcResponse.vpc as RawVpcXmlItem;
|
|
657
|
+
if (vpc) {
|
|
658
|
+
result.Vpc = {
|
|
659
|
+
VpcId: vpc.vpcId,
|
|
660
|
+
State: vpc.state as "pending" | "available",
|
|
661
|
+
CidrBlock: vpc.cidrBlock,
|
|
662
|
+
DhcpOptionsId: vpc.dhcpOptionsId,
|
|
663
|
+
InstanceTenancy: vpc.instanceTenancy as
|
|
664
|
+
| "default"
|
|
665
|
+
| "dedicated"
|
|
666
|
+
| "host",
|
|
667
|
+
IsDefault: vpc.isDefault === "true" || vpc.isDefault === true,
|
|
668
|
+
Tags: vpc.tagSet?.item
|
|
669
|
+
? Array.isArray(vpc.tagSet.item)
|
|
670
|
+
? vpc.tagSet.item.map((tag) => ({ Key: tag.key, Value: tag.value }))
|
|
671
|
+
: [{ Key: vpc.tagSet.item.key, Value: vpc.tagSet.item.value }]
|
|
672
|
+
: undefined,
|
|
673
|
+
CidrBlockAssociationSet: vpc.cidrBlockAssociationSet?.item
|
|
674
|
+
? Array.isArray(vpc.cidrBlockAssociationSet.item)
|
|
675
|
+
? vpc.cidrBlockAssociationSet.item.map((assoc) => ({
|
|
676
|
+
AssociationId: assoc.associationId,
|
|
677
|
+
CidrBlock: assoc.cidrBlock,
|
|
678
|
+
CidrBlockState: {
|
|
679
|
+
State: assoc.cidrBlockState.state as
|
|
680
|
+
| "associating"
|
|
681
|
+
| "associated"
|
|
682
|
+
| "disassociating"
|
|
683
|
+
| "disassociated"
|
|
684
|
+
| "failing"
|
|
685
|
+
| "failed",
|
|
686
|
+
StatusMessage: assoc.cidrBlockState.statusMessage,
|
|
687
|
+
},
|
|
688
|
+
}))
|
|
689
|
+
: [
|
|
690
|
+
{
|
|
691
|
+
AssociationId: vpc.cidrBlockAssociationSet.item.associationId,
|
|
692
|
+
CidrBlock: vpc.cidrBlockAssociationSet.item.cidrBlock,
|
|
693
|
+
CidrBlockState: {
|
|
694
|
+
State: vpc.cidrBlockAssociationSet.item.cidrBlockState
|
|
695
|
+
.state as
|
|
696
|
+
| "associating"
|
|
697
|
+
| "associated"
|
|
698
|
+
| "disassociating"
|
|
699
|
+
| "disassociated"
|
|
700
|
+
| "failing"
|
|
701
|
+
| "failed",
|
|
702
|
+
StatusMessage:
|
|
703
|
+
vpc.cidrBlockAssociationSet.item.cidrBlockState
|
|
704
|
+
.statusMessage,
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
]
|
|
708
|
+
: undefined,
|
|
709
|
+
Ipv6CidrBlockAssociationSet: vpc.ipv6CidrBlockAssociationSet?.item
|
|
710
|
+
? Array.isArray(vpc.ipv6CidrBlockAssociationSet.item)
|
|
711
|
+
? vpc.ipv6CidrBlockAssociationSet.item.map((assoc) => ({
|
|
712
|
+
AssociationId: assoc.associationId,
|
|
713
|
+
Ipv6CidrBlock: assoc.ipv6CidrBlock,
|
|
714
|
+
Ipv6CidrBlockState: {
|
|
715
|
+
State: assoc.ipv6CidrBlockState.state as
|
|
716
|
+
| "associating"
|
|
717
|
+
| "associated"
|
|
718
|
+
| "disassociating"
|
|
719
|
+
| "disassociated"
|
|
720
|
+
| "failing"
|
|
721
|
+
| "failed",
|
|
722
|
+
StatusMessage: assoc.ipv6CidrBlockState.statusMessage,
|
|
723
|
+
},
|
|
724
|
+
NetworkBorderGroup: assoc.networkBorderGroup,
|
|
725
|
+
Ipv6Pool: assoc.ipv6Pool,
|
|
726
|
+
}))
|
|
727
|
+
: [
|
|
728
|
+
{
|
|
729
|
+
AssociationId:
|
|
730
|
+
vpc.ipv6CidrBlockAssociationSet.item.associationId,
|
|
731
|
+
Ipv6CidrBlock:
|
|
732
|
+
vpc.ipv6CidrBlockAssociationSet.item.ipv6CidrBlock,
|
|
733
|
+
Ipv6CidrBlockState: {
|
|
734
|
+
State: vpc.ipv6CidrBlockAssociationSet.item
|
|
735
|
+
.ipv6CidrBlockState.state as
|
|
736
|
+
| "associating"
|
|
737
|
+
| "associated"
|
|
738
|
+
| "disassociating"
|
|
739
|
+
| "disassociated"
|
|
740
|
+
| "failing"
|
|
741
|
+
| "failed",
|
|
742
|
+
StatusMessage:
|
|
743
|
+
vpc.ipv6CidrBlockAssociationSet.item.ipv6CidrBlockState
|
|
744
|
+
.statusMessage,
|
|
745
|
+
},
|
|
746
|
+
NetworkBorderGroup:
|
|
747
|
+
vpc.ipv6CidrBlockAssociationSet.item.networkBorderGroup,
|
|
748
|
+
Ipv6Pool: vpc.ipv6CidrBlockAssociationSet.item.ipv6Pool,
|
|
749
|
+
},
|
|
750
|
+
]
|
|
751
|
+
: undefined,
|
|
752
|
+
OwnerId: vpc.ownerId,
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// Parse DescribeVpcsResponse
|
|
758
|
+
if (parsed.DescribeVpcsResponse) {
|
|
759
|
+
const vpcSet = parsed.DescribeVpcsResponse.vpcSet;
|
|
760
|
+
if (vpcSet?.item) {
|
|
761
|
+
const vpcs = Array.isArray(vpcSet.item) ? vpcSet.item : [vpcSet.item];
|
|
762
|
+
result.Vpcs = vpcs.map((vpc: RawVpcXmlItem) => ({
|
|
763
|
+
VpcId: vpc.vpcId,
|
|
764
|
+
State: vpc.state as "pending" | "available",
|
|
765
|
+
CidrBlock: vpc.cidrBlock,
|
|
766
|
+
DhcpOptionsId: vpc.dhcpOptionsId,
|
|
767
|
+
InstanceTenancy: vpc.instanceTenancy as
|
|
768
|
+
| "default"
|
|
769
|
+
| "dedicated"
|
|
770
|
+
| "host",
|
|
771
|
+
IsDefault: vpc.isDefault === "true" || vpc.isDefault === true,
|
|
772
|
+
Tags: vpc.tagSet?.item
|
|
773
|
+
? Array.isArray(vpc.tagSet.item)
|
|
774
|
+
? vpc.tagSet.item.map((tag) => ({ Key: tag.key, Value: tag.value }))
|
|
775
|
+
: [{ Key: vpc.tagSet.item.key, Value: vpc.tagSet.item.value }]
|
|
776
|
+
: undefined,
|
|
777
|
+
CidrBlockAssociationSet: vpc.cidrBlockAssociationSet?.item
|
|
778
|
+
? Array.isArray(vpc.cidrBlockAssociationSet.item)
|
|
779
|
+
? vpc.cidrBlockAssociationSet.item.map((assoc) => ({
|
|
780
|
+
AssociationId: assoc.associationId,
|
|
781
|
+
CidrBlock: assoc.cidrBlock,
|
|
782
|
+
CidrBlockState: {
|
|
783
|
+
State: assoc.cidrBlockState.state as
|
|
784
|
+
| "associating"
|
|
785
|
+
| "associated"
|
|
786
|
+
| "disassociating"
|
|
787
|
+
| "disassociated"
|
|
788
|
+
| "failing"
|
|
789
|
+
| "failed",
|
|
790
|
+
StatusMessage: assoc.cidrBlockState.statusMessage,
|
|
791
|
+
},
|
|
792
|
+
}))
|
|
793
|
+
: [
|
|
794
|
+
{
|
|
795
|
+
AssociationId: vpc.cidrBlockAssociationSet.item.associationId,
|
|
796
|
+
CidrBlock: vpc.cidrBlockAssociationSet.item.cidrBlock,
|
|
797
|
+
CidrBlockState: {
|
|
798
|
+
State: vpc.cidrBlockAssociationSet.item.cidrBlockState
|
|
799
|
+
.state as
|
|
800
|
+
| "associating"
|
|
801
|
+
| "associated"
|
|
802
|
+
| "disassociating"
|
|
803
|
+
| "disassociated"
|
|
804
|
+
| "failing"
|
|
805
|
+
| "failed",
|
|
806
|
+
StatusMessage:
|
|
807
|
+
vpc.cidrBlockAssociationSet.item.cidrBlockState
|
|
808
|
+
.statusMessage,
|
|
809
|
+
},
|
|
810
|
+
},
|
|
811
|
+
]
|
|
812
|
+
: undefined,
|
|
813
|
+
Ipv6CidrBlockAssociationSet: vpc.ipv6CidrBlockAssociationSet?.item
|
|
814
|
+
? Array.isArray(vpc.ipv6CidrBlockAssociationSet.item)
|
|
815
|
+
? vpc.ipv6CidrBlockAssociationSet.item.map((assoc) => ({
|
|
816
|
+
AssociationId: assoc.associationId,
|
|
817
|
+
Ipv6CidrBlock: assoc.ipv6CidrBlock,
|
|
818
|
+
Ipv6CidrBlockState: {
|
|
819
|
+
State: assoc.ipv6CidrBlockState.state as
|
|
820
|
+
| "associating"
|
|
821
|
+
| "associated"
|
|
822
|
+
| "disassociating"
|
|
823
|
+
| "disassociated"
|
|
824
|
+
| "failing"
|
|
825
|
+
| "failed",
|
|
826
|
+
StatusMessage: assoc.ipv6CidrBlockState.statusMessage,
|
|
827
|
+
},
|
|
828
|
+
NetworkBorderGroup: assoc.networkBorderGroup,
|
|
829
|
+
Ipv6Pool: assoc.ipv6Pool,
|
|
830
|
+
}))
|
|
831
|
+
: [
|
|
832
|
+
{
|
|
833
|
+
AssociationId:
|
|
834
|
+
vpc.ipv6CidrBlockAssociationSet.item.associationId,
|
|
835
|
+
Ipv6CidrBlock:
|
|
836
|
+
vpc.ipv6CidrBlockAssociationSet.item.ipv6CidrBlock,
|
|
837
|
+
Ipv6CidrBlockState: {
|
|
838
|
+
State: vpc.ipv6CidrBlockAssociationSet.item
|
|
839
|
+
.ipv6CidrBlockState.state as
|
|
840
|
+
| "associating"
|
|
841
|
+
| "associated"
|
|
842
|
+
| "disassociating"
|
|
843
|
+
| "disassociated"
|
|
844
|
+
| "failing"
|
|
845
|
+
| "failed",
|
|
846
|
+
StatusMessage:
|
|
847
|
+
vpc.ipv6CidrBlockAssociationSet.item.ipv6CidrBlockState
|
|
848
|
+
.statusMessage,
|
|
849
|
+
},
|
|
850
|
+
NetworkBorderGroup:
|
|
851
|
+
vpc.ipv6CidrBlockAssociationSet.item.networkBorderGroup,
|
|
852
|
+
Ipv6Pool: vpc.ipv6CidrBlockAssociationSet.item.ipv6Pool,
|
|
853
|
+
},
|
|
854
|
+
]
|
|
855
|
+
: undefined,
|
|
856
|
+
OwnerId: vpc.ownerId,
|
|
857
|
+
}));
|
|
858
|
+
} else {
|
|
859
|
+
result.Vpcs = [];
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// Parse DescribeSecurityGroupsResponse
|
|
864
|
+
if (parsed.DescribeSecurityGroupsResponse) {
|
|
865
|
+
const securityGroupSet =
|
|
866
|
+
parsed.DescribeSecurityGroupsResponse.securityGroupInfo;
|
|
867
|
+
if (securityGroupSet?.item) {
|
|
868
|
+
const securityGroups = Array.isArray(securityGroupSet.item)
|
|
869
|
+
? securityGroupSet.item
|
|
870
|
+
: [securityGroupSet.item];
|
|
871
|
+
result.SecurityGroups = securityGroups.map(
|
|
872
|
+
(sg: RawSecurityGroupXmlItem) => ({
|
|
873
|
+
GroupId: sg.groupId,
|
|
874
|
+
GroupName: sg.groupName,
|
|
875
|
+
VpcId: sg.vpcId,
|
|
876
|
+
}),
|
|
877
|
+
);
|
|
878
|
+
} else {
|
|
879
|
+
result.SecurityGroups = [];
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// Handle success responses
|
|
884
|
+
if (parsed.ModifyVpcAttributeResponse || parsed.DeleteVpcResponse) {
|
|
885
|
+
result.success = true;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
return result as T;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Wait for VPC to be in available state
|
|
893
|
+
*/
|
|
894
|
+
async function waitForVpcAvailable(
|
|
895
|
+
client: AwsClient,
|
|
896
|
+
vpcId: string,
|
|
897
|
+
timeoutConfig: TimeoutConfig,
|
|
898
|
+
): Promise<void> {
|
|
899
|
+
const checkFunction = async () => {
|
|
900
|
+
const response = await callEC2Api<DescribeVpcsResponse>(
|
|
901
|
+
client,
|
|
902
|
+
"DescribeVpcs",
|
|
903
|
+
parseVpcXmlResponse,
|
|
904
|
+
{
|
|
905
|
+
"VpcId.1": vpcId,
|
|
906
|
+
},
|
|
907
|
+
);
|
|
908
|
+
return response.Vpcs?.[0];
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
const isReady = (vpc: AwsVpc | undefined) => {
|
|
912
|
+
return vpc?.State === "available";
|
|
913
|
+
};
|
|
914
|
+
|
|
915
|
+
await waitForResourceState(
|
|
916
|
+
checkFunction,
|
|
917
|
+
isReady,
|
|
918
|
+
timeoutConfig,
|
|
919
|
+
vpcId,
|
|
920
|
+
"VPC",
|
|
921
|
+
"is now available",
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Wait for VPC to be deleted
|
|
927
|
+
*/
|
|
928
|
+
async function waitForVpcDeleted(
|
|
929
|
+
client: AwsClient,
|
|
930
|
+
vpcId: string,
|
|
931
|
+
timeoutConfig: TimeoutConfig,
|
|
932
|
+
): Promise<void> {
|
|
933
|
+
const checkFunction = async () => {
|
|
934
|
+
try {
|
|
935
|
+
const response = await callEC2Api<DescribeVpcsResponse>(
|
|
936
|
+
client,
|
|
937
|
+
"DescribeVpcs",
|
|
938
|
+
parseVpcXmlResponse,
|
|
939
|
+
{
|
|
940
|
+
"VpcId.1": vpcId,
|
|
941
|
+
},
|
|
942
|
+
);
|
|
943
|
+
return response.Vpcs?.[0];
|
|
944
|
+
} catch (error: any) {
|
|
945
|
+
// If VPC is not found, it's been deleted - return undefined
|
|
946
|
+
if (
|
|
947
|
+
error.code === "InvalidVpcID.NotFound" ||
|
|
948
|
+
error.code === "InvalidVpc.NotFound"
|
|
949
|
+
) {
|
|
950
|
+
return undefined;
|
|
951
|
+
}
|
|
952
|
+
throw error;
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
|
|
956
|
+
const isReady = (vpc: AwsVpc | undefined) => {
|
|
957
|
+
// VPC is deleted if it doesn't exist
|
|
958
|
+
return !vpc;
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
await waitForResourceState(
|
|
962
|
+
checkFunction,
|
|
963
|
+
isReady,
|
|
964
|
+
timeoutConfig,
|
|
965
|
+
vpcId,
|
|
966
|
+
"VPC",
|
|
967
|
+
"be deleted",
|
|
968
|
+
);
|
|
969
|
+
}
|