@aws-cdk/aws-ec2-alpha 2.156.0-alpha.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/.jsii +8230 -0
- package/.jsii.tabl.json.gz +0 -0
- package/.warnings.jsii.js +259 -0
- package/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +207 -0
- package/awslint.json +7 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +26 -0
- package/lib/ipam.d.ts +250 -0
- package/lib/ipam.js +255 -0
- package/lib/route.d.ts +390 -0
- package/lib/route.js +270 -0
- package/lib/subnet-v2.d.ts +152 -0
- package/lib/subnet-v2.js +272 -0
- package/lib/util.d.ts +157 -0
- package/lib/util.js +310 -0
- package/lib/vpc-v2-base.d.ts +132 -0
- package/lib/vpc-v2-base.js +264 -0
- package/lib/vpc-v2.d.ts +222 -0
- package/lib/vpc-v2.js +303 -0
- package/package.json +110 -0
- package/rosetta/_generated.ts-fixture +6 -0
- package/rosetta/default.ts-fixture +15 -0
package/lib/subnet-v2.js
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.SubnetV2 = exports.IpCidr = void 0;
|
|
5
|
+
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
|
6
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
7
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
8
|
+
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
|
9
|
+
const constructs_1 = require("constructs");
|
|
10
|
+
const util_1 = require("./util");
|
|
11
|
+
/**
|
|
12
|
+
* IPv4 or IPv6 CIDR range for the subnet
|
|
13
|
+
*/
|
|
14
|
+
class IpCidr {
|
|
15
|
+
constructor(props) {
|
|
16
|
+
this.cidr = props;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.IpCidr = IpCidr;
|
|
20
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
21
|
+
IpCidr[_a] = { fqn: "@aws-cdk/aws-ec2-alpha.IpCidr", version: "2.156.0-alpha.0" };
|
|
22
|
+
/**
|
|
23
|
+
* The SubnetV2 class represents a subnet within a VPC (Virtual Private Cloud) in AWS.
|
|
24
|
+
* It extends the Resource class and implements the ISubnet interface.
|
|
25
|
+
*
|
|
26
|
+
* Instances of this class can be used to create and manage subnets within a VpcV2 instance.
|
|
27
|
+
* Subnets can be configured with specific IP address ranges (IPv4 and IPv6), availability zones,
|
|
28
|
+
* and subnet types (e.g., public, private, isolated).
|
|
29
|
+
*
|
|
30
|
+
* @resource AWS::EC2::Subnet
|
|
31
|
+
*
|
|
32
|
+
*/
|
|
33
|
+
class SubnetV2 extends aws_cdk_lib_1.Resource {
|
|
34
|
+
/**
|
|
35
|
+
* Constructs a new SubnetV2 instance.
|
|
36
|
+
* @param scope The parent Construct that this resource will be part of.
|
|
37
|
+
* @param id The unique identifier for this resource.
|
|
38
|
+
* @param props The configuration properties for the subnet.
|
|
39
|
+
*/
|
|
40
|
+
constructor(scope, id, props) {
|
|
41
|
+
super(scope, id, {
|
|
42
|
+
physicalName: props.subnetName ?? aws_cdk_lib_1.Lazy.string({
|
|
43
|
+
produce: () => aws_cdk_lib_1.Names.uniqueResourceName(this, { maxLength: 128, allowedSpecialCharacters: '_' }),
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* The variable name `internetConnectivityEstablished` does not reflect what it actually is.
|
|
48
|
+
* The naming is enforced by ISubnet. We need to keep it to maintain compatibility.
|
|
49
|
+
* It exposes the RouteTable-Subnet association so that other resources can depend on it.
|
|
50
|
+
* E.g. Resources in a subnet, when being deleted, may need the RouteTable to exist in order to delete properly
|
|
51
|
+
*/
|
|
52
|
+
this._internetConnectivityEstablished = new constructs_1.DependencyGroup();
|
|
53
|
+
try {
|
|
54
|
+
jsiiDeprecationWarnings._aws_cdk_aws_ec2_alpha_SubnetV2Props(props);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
58
|
+
Error.captureStackTrace(error, SubnetV2);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
const ipv4CidrBlock = props.ipv4CidrBlock.cidr;
|
|
63
|
+
const ipv6CidrBlock = props.ipv6CidrBlock?.cidr;
|
|
64
|
+
if (!checkCidrRanges(props.vpc, props.ipv4CidrBlock.cidr)) {
|
|
65
|
+
throw new Error('CIDR block should be within the range of VPC');
|
|
66
|
+
}
|
|
67
|
+
;
|
|
68
|
+
let overlap = false;
|
|
69
|
+
let overlapIpv6 = false;
|
|
70
|
+
overlap = validateOverlappingCidrRanges(props.vpc, props.ipv4CidrBlock.cidr);
|
|
71
|
+
//check whether VPC supports ipv6
|
|
72
|
+
if (props.ipv6CidrBlock?.cidr) {
|
|
73
|
+
validateSupportIpv6(props.vpc);
|
|
74
|
+
overlapIpv6 = validateOverlappingCidrRangesipv6(props.vpc, props.ipv6CidrBlock?.cidr);
|
|
75
|
+
}
|
|
76
|
+
if (overlap || overlapIpv6) {
|
|
77
|
+
throw new Error('CIDR block should not overlap with existing subnet blocks');
|
|
78
|
+
}
|
|
79
|
+
if (props.assignIpv6AddressOnCreation && !props.ipv6CidrBlock) {
|
|
80
|
+
throw new Error('IPv6 CIDR block is required when assigning IPv6 address on creation');
|
|
81
|
+
}
|
|
82
|
+
const subnet = new aws_ec2_1.CfnSubnet(this, 'Subnet', {
|
|
83
|
+
vpcId: props.vpc.vpcId,
|
|
84
|
+
cidrBlock: ipv4CidrBlock,
|
|
85
|
+
ipv6CidrBlock: ipv6CidrBlock,
|
|
86
|
+
availabilityZone: props.availabilityZone,
|
|
87
|
+
assignIpv6AddressOnCreation: props.assignIpv6AddressOnCreation ?? false,
|
|
88
|
+
});
|
|
89
|
+
this.node.defaultChild = subnet;
|
|
90
|
+
this.ipv4CidrBlock = props.ipv4CidrBlock.cidr;
|
|
91
|
+
this.ipv6CidrBlock = props.ipv6CidrBlock?.cidr;
|
|
92
|
+
this.subnetId = subnet.ref;
|
|
93
|
+
this.availabilityZone = props.availabilityZone;
|
|
94
|
+
this._networkAcl = aws_ec2_1.NetworkAcl.fromNetworkAclId(this, 'Acl', subnet.attrNetworkAclAssociationId);
|
|
95
|
+
if (props.routeTable) {
|
|
96
|
+
this.routeTable = props.routeTable;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const defaultTable = new aws_ec2_1.CfnRouteTable(this, 'RouteTable', {
|
|
100
|
+
vpcId: props.vpc.vpcId,
|
|
101
|
+
});
|
|
102
|
+
this.routeTable = { routeTableId: defaultTable.ref };
|
|
103
|
+
}
|
|
104
|
+
const routeAssoc = new aws_ec2_1.CfnSubnetRouteTableAssociation(this, 'RouteTableAssociation', {
|
|
105
|
+
subnetId: this.subnetId,
|
|
106
|
+
routeTableId: this.routeTable.routeTableId,
|
|
107
|
+
});
|
|
108
|
+
this._internetConnectivityEstablished.add(routeAssoc);
|
|
109
|
+
this.internetConnectivityEstablished = this._internetConnectivityEstablished;
|
|
110
|
+
this.subnetType = props.subnetType;
|
|
111
|
+
storeSubnetToVpcByType(props.vpc, this, props.subnetType);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Associate a Network ACL with this subnet
|
|
115
|
+
*
|
|
116
|
+
* @param id The unique identifier for this association.
|
|
117
|
+
* @param networkAcl The Network ACL to associate with this subnet.
|
|
118
|
+
* This allows controlling inbound and outbound traffic for instances in this subnet.
|
|
119
|
+
*/
|
|
120
|
+
associateNetworkAcl(id, networkAcl) {
|
|
121
|
+
this._networkAcl = networkAcl;
|
|
122
|
+
const scope = networkAcl instanceof constructs_1.Construct ? networkAcl : this;
|
|
123
|
+
const other = networkAcl instanceof constructs_1.Construct ? this : networkAcl;
|
|
124
|
+
new aws_ec2_1.SubnetNetworkAclAssociation(scope, id + aws_cdk_lib_1.Names.nodeUniqueId(other.node), {
|
|
125
|
+
networkAcl,
|
|
126
|
+
subnet: this,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Returns the Network ACL associated with this subnet.
|
|
131
|
+
*/
|
|
132
|
+
get networkAcl() {
|
|
133
|
+
return this._networkAcl;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.SubnetV2 = SubnetV2;
|
|
137
|
+
_b = JSII_RTTI_SYMBOL_1;
|
|
138
|
+
SubnetV2[_b] = { fqn: "@aws-cdk/aws-ec2-alpha.SubnetV2", version: "2.156.0-alpha.0" };
|
|
139
|
+
const subnetTypeMap = {
|
|
140
|
+
[aws_ec2_1.SubnetType.PRIVATE_ISOLATED]: (vpc, subnet) => vpc.isolatedSubnets.push(subnet),
|
|
141
|
+
[aws_ec2_1.SubnetType.PUBLIC]: (vpc, subnet) => vpc.publicSubnets.push(subnet),
|
|
142
|
+
[aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS]: (vpc, subnet) => vpc.privateSubnets.push(subnet),
|
|
143
|
+
[aws_ec2_1.SubnetType.ISOLATED]: (vpc, subnet) => vpc.isolatedSubnets.push(subnet),
|
|
144
|
+
[aws_ec2_1.SubnetType.PRIVATE]: (vpc, subnet) => vpc.privateSubnets.push(subnet),
|
|
145
|
+
[aws_ec2_1.SubnetType.PRIVATE_WITH_NAT]: (vpc, subnet) => vpc.privateSubnets.push(subnet),
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Stores the provided subnet in the VPC's collection of subnets based on the specified subnet type.
|
|
149
|
+
*
|
|
150
|
+
* @param vpc The VPC instance to which the subnet belongs.
|
|
151
|
+
* @param subnet The subnet instance to be stored.
|
|
152
|
+
* @param type The type of the subnet (e.g., public, private, isolated).
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
155
|
+
function storeSubnetToVpcByType(vpc, subnet, type) {
|
|
156
|
+
const findFunctionType = subnetTypeMap[type];
|
|
157
|
+
if (findFunctionType) {
|
|
158
|
+
findFunctionType(vpc, subnet);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
throw new Error(`Unsupported subnet type: ${type}`);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Need to set explicit dependency as during stack deletion,
|
|
165
|
+
* the cidr blocks may get deleted first and will fail as the subnets are still using the cidr blocks
|
|
166
|
+
*/
|
|
167
|
+
for (const cidr of vpc.secondaryCidrBlock) {
|
|
168
|
+
subnet.node.addDependency(cidr);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Validates whether the provided VPC supports IPv6 addresses.
|
|
173
|
+
*
|
|
174
|
+
* @param vpc The VPC instance to be validated.
|
|
175
|
+
* @throws Error if the VPC does not support IPv6 addresses.
|
|
176
|
+
* @returns True if the VPC supports IPv6 addresses, false otherwise.
|
|
177
|
+
* @internal
|
|
178
|
+
*/
|
|
179
|
+
function validateSupportIpv6(vpc) {
|
|
180
|
+
if (vpc.secondaryCidrBlock.some((secondaryAddress) => secondaryAddress.amazonProvidedIpv6CidrBlock === true ||
|
|
181
|
+
secondaryAddress.ipv6IpamPoolId != undefined)) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
throw new Error('To use IPv6, the VPC must enable IPv6 support.');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Checks if the provided CIDR range falls within the IP address ranges of the given VPC.
|
|
190
|
+
*
|
|
191
|
+
* @param vpc The VPC instance to check against.
|
|
192
|
+
* @param cidrRange The CIDR range to be checked.
|
|
193
|
+
* @returns True if the CIDR range falls within the VPC's IP address ranges, false otherwise.
|
|
194
|
+
* @internal
|
|
195
|
+
*/
|
|
196
|
+
function checkCidrRanges(vpc, cidrRange) {
|
|
197
|
+
const vpcCidrBlock = [vpc.ipv4CidrBlock];
|
|
198
|
+
for (const ipAddress of vpc.secondaryCidrBlock) {
|
|
199
|
+
if (ipAddress.cidrBlock) {
|
|
200
|
+
vpcCidrBlock.push(ipAddress.cidrBlock);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const cidrs = vpcCidrBlock.map(cidr => new util_1.CidrBlock(cidr));
|
|
204
|
+
const subnetCidrBlock = new util_1.CidrBlock(cidrRange);
|
|
205
|
+
return cidrs.some(c => c.containsCidr(subnetCidrBlock));
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Validates if the provided IPv4 CIDR block overlaps with existing subnet CIDR blocks within the given VPC.
|
|
209
|
+
*
|
|
210
|
+
* @param vpc The VPC instance to check against.
|
|
211
|
+
* @param ipv4CidrBlock The IPv4 CIDR block to be validated.
|
|
212
|
+
* @returns True if the IPv4 CIDR block overlaps with existing subnet CIDR blocks, false otherwise.
|
|
213
|
+
* @internal
|
|
214
|
+
*/
|
|
215
|
+
function validateOverlappingCidrRanges(vpc, ipv4CidrBlock) {
|
|
216
|
+
let allSubnets;
|
|
217
|
+
try {
|
|
218
|
+
allSubnets = vpc.selectSubnets().subnets;
|
|
219
|
+
}
|
|
220
|
+
catch (e) {
|
|
221
|
+
'No subnets in VPC';
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
const ipMap = new Array();
|
|
225
|
+
const inputRange = new util_1.CidrBlock(ipv4CidrBlock);
|
|
226
|
+
const inputIpMap = [inputRange.minIp(), inputRange.maxIp()];
|
|
227
|
+
for (const subnet of allSubnets) {
|
|
228
|
+
const cidrBlock = new util_1.CidrBlock(subnet.ipv4CidrBlock);
|
|
229
|
+
ipMap.push([cidrBlock.minIp(), cidrBlock.maxIp()]);
|
|
230
|
+
}
|
|
231
|
+
for (const range of ipMap) {
|
|
232
|
+
if (inputRange.rangesOverlap(range, inputIpMap)) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Validates if the provided IPv6 CIDR block overlaps with existing subnet CIDR blocks within the given VPC.
|
|
240
|
+
*
|
|
241
|
+
* @param vpc The VPC instance to check against.
|
|
242
|
+
* @param ipv6CidrBlock The IPv6 CIDR block to be validated.
|
|
243
|
+
* @returns True if the IPv6 CIDR block overlaps with existing subnet CIDR blocks, false otherwise.
|
|
244
|
+
* @throws Error if no subnets are found in the VPC.
|
|
245
|
+
* @internal
|
|
246
|
+
*/
|
|
247
|
+
function validateOverlappingCidrRangesipv6(vpc, ipv6CidrBlock) {
|
|
248
|
+
let allSubnets;
|
|
249
|
+
try {
|
|
250
|
+
allSubnets = vpc.selectSubnets().subnets;
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
'No subnets in VPC';
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
const ipv6Map = [];
|
|
257
|
+
const inputRange = new util_1.CidrBlockIpv6(ipv6CidrBlock);
|
|
258
|
+
let result = false;
|
|
259
|
+
for (const subnet of allSubnets) {
|
|
260
|
+
if (subnet.ipv6CidrBlock) {
|
|
261
|
+
const cidrBlock = new util_1.CidrBlockIpv6(subnet.ipv6CidrBlock);
|
|
262
|
+
ipv6Map.push(cidrBlock.cidr);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
for (const range of ipv6Map) {
|
|
266
|
+
if (inputRange.rangesOverlap(range, inputRange.cidr)) {
|
|
267
|
+
result = true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VibmV0LXYyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3VibmV0LXYyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDZDQUFvRDtBQUNwRCxpREFBdUw7QUFDdkwsMkNBQXFFO0FBRXJFLGlDQUFrRDtBQVNsRDs7R0FFRztBQUNILE1BQWEsTUFBTTtJQU9qQixZQUFZLEtBQWE7UUFDdkIsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUM7S0FDbkI7O0FBVEgsd0JBVUM7OztBQXlFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBYSxRQUFTLFNBQVEsc0JBQVE7SUFrRHBDOzs7OztPQUtHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFvQjtRQUM1RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFlBQVksRUFBRSxLQUFLLENBQUMsVUFBVSxJQUFJLGtCQUFJLENBQUMsTUFBTSxDQUFDO2dCQUM1QyxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsbUJBQUssQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLHdCQUF3QixFQUFFLEdBQUcsRUFBRSxDQUFDO2FBQ2pHLENBQUM7U0FDSCxDQUFDLENBQUM7UUExQ0w7Ozs7O1dBS0c7UUFDYyxxQ0FBZ0MsR0FBRyxJQUFJLDRCQUFlLEVBQUUsQ0FBQzs7Ozs7OytDQXpCL0QsUUFBUTs7OztRQStEakIsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUM7UUFDL0MsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUM7UUFFaEQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUMxRCxNQUFNLElBQUksS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFD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QUM7WUFDekIsTUFBTSxTQUFTLEdBQUcsSUFBSSxvQkFBYSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUMxRCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMvQixDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7UUFDNUIsSUFBSSxVQUFVLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNyRCxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlc291cmNlLCBOYW1lcywgTGF6eSB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IENmblJvdXRlVGFibGUsIENmblN1Ym5ldCwgQ2ZuU3VibmV0Um91dGVUYWJsZUFzc29jaWF0aW9uLCBJTmV0d29ya0FjbCwgSVJvdXRlVGFibGUsIElTdWJuZXQsIE5ldHdvcmtBY2wsIFN1Ym5ldE5ldHdvcmtBY2xBc3NvY2lhdGlvbiwgU3VibmV0VHlwZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBEZXBlbmRlbmN5R3JvdXAsIElEZXBlbmRhYmxlIH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBJVnBjVjIgfSBmcm9tICcuL3ZwYy12Mi1iYXNlJztcbmltcG9ydCB7IENpZHJCbG9jaywgQ2lkckJsb2NrSXB2NiB9IGZyb20gJy4vdXRpbCc7XG5cbi8qKlxuICogSW50ZXJmYWNlIHRvIGRlZmluZSBzdWJuZXQgQ0lEUlxuICovXG5pbnRlcmZhY2UgSUNpZHIge1xuICByZWFkb25seSBjaWRyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogSVB2NCBvciBJUHY2IENJRFIgcmFuZ2UgZm9yIHRoZSBzdWJuZXRcbiAqL1xuZXhwb3J0IGNsYXNzIElwQ2lkciBpbXBsZW1lbnRzIElDaWRyIHtcblxuICAvKipcbiAqIElQdjYgQ0lEUiByYW5nZSBmb3IgdGhlIHN1Ym5ldFxuICogQWxsb3dlZCBvbmx5IGlmIElQdjYgaXMgZW5hYmxlZCBvbiBWUGNcbiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY2lkcjogc3RyaW5nO1xuICBjb25zdHJ1Y3Rvcihwcm9wczogc3RyaW5nICkge1xuICAgIHRoaXMuY2lkciA9IHByb3BzO1xuICB9XG59XG5cbi8qKlxuICogUHJvcGVydGllcyB0byBkZWZpbmUgc3VibmV0IGZvciBWUEMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3VibmV0VjJQcm9wcyB7XG4vKipcbiAqIFZQQyBQcm9wXG4gKi9cbiAgcmVhZG9ubHkgdnBjOiBJVnBjVjI7XG5cbiAgLyoqXG4gICAqIGlwdjQgY2lkciB0byBhc3NpZ24gdG8gdGhpcyBzdWJuZXQuXG4gICAqIFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2UtZWMyLXN1Ym5ldC5odG1sI2Nmbi1lYzItc3VibmV0LWNpZHJibG9ja1xuICAgKi9cbiAgcmVhZG9ubHkgaXB2NENpZHJCbG9jazogSXBDaWRyO1xuXG4gIC8qKlxuICAgKiBJcHY2IENJRFIgUmFuZ2UgZm9yIHN1Ym5ldFxuICAgKiBAZGVmYXVsdCBObyBJcHY2IGFkZHJlc3NcbiAgICovXG4gIHJlYWRvbmx5IGlwdjZDaWRyQmxvY2s/OiBJcENpZHI7XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBBWiBmb3IgdGhlIHN1Ym5ldFxuICAgKi9cbiAgcmVhZG9ubHkgYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gUm91dGUgZm9yIHN1Ym5ldFxuICAgKiBAZGVmYXVsdCBEZWZhdWx0IHJvdXRlIHRhYmxlXG4gICAqL1xuICByZWFkb25seSByb3V0ZVRhYmxlPzogSVJvdXRlVGFibGU7XG5cbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIFN1Ym5ldCB0byBjb25maWd1cmUuXG4gICAqXG4gICAqIFRoZSBTdWJuZXQgdHlwZSB3aWxsIGNvbnRyb2wgdGhlIGFiaWxpdHkgdG8gcm91dGUgYW5kIGNvbm5lY3QgdG8gdGhlXG4gICAqIEludGVybmV0LlxuICAgKlxuICAgKiBUT0RPOiBBZGQgdmFsaWRhdGlvbiBjaGVjayBgc3VibmV0VHlwZWAgd2hlbiBhZGRpbmcgcmVzb3VyY2VzIChlLmcuIGNhbm5vdCBhZGQgTmF0R2F0ZXdheSB0byBwcml2YXRlKVxuICAgKi9cbiAgcmVhZG9ubHkgc3VibmV0VHlwZTogU3VibmV0VHlwZTtcblxuICAvKipcbiAgICogU3VibmV0IG5hbWVcbiAgICogQGRlZmF1bHQgbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgc3VibmV0TmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgYSBuZXR3b3JrIGludGVyZmFjZSBjcmVhdGVkIGluIHRoaXMgc3VibmV0IHJlY2VpdmVzIGFuIElQdjYgYWRkcmVzcy5cbiAgICpcbiAgICogSWYgeW91IHNwZWNpZnkgQXNzaWduSXB2NkFkZHJlc3NPbkNyZWF0aW9uLCB5b3UgbXVzdCBhbHNvIHNwZWNpZnkgSXB2NkNpZHJCbG9jay5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGFzc2lnbklwdjZBZGRyZXNzT25DcmVhdGlvbj86IGJvb2xlYW47XG5cbn1cblxuLyoqXG4gKiBJbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIHByb3BlcnRpZXMgZm9yIFN1Ym5ldFYyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSVN1Ym5ldFYyIGV4dGVuZHMgSVN1Ym5ldCB7XG5cbiAgLyoqXG4gICAqIFRoZSBJUHY2IENJRFIgYmxvY2sgZm9yIHRoaXMgc3VibmV0XG4gICAqL1xuICByZWFkb25seSBpcHY2Q2lkckJsb2NrPzogc3RyaW5nO1xuXG59XG5cbi8qKlxuICogVGhlIFN1Ym5ldFYyIGNsYXNzIHJlcHJlc2VudHMgYSBzdWJuZXQgd2l0aGluIGEgVlBDIChWaXJ0dWFsIFByaXZhdGUgQ2xvdWQpIGluIEFXUy5cbiAqIEl0IGV4dGVuZHMgdGhlIFJlc291cmNlIGNsYXNzIGFuZCBpbXBsZW1lbnRzIHRoZSBJU3VibmV0IGludGVyZmFjZS5cbiAqXG4gKiBJbnN0YW5jZXMgb2YgdGhpcyBjbGFzcyBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYW5kIG1hbmFnZSBzdWJuZXRzIHdpdGhpbiBhIFZwY1YyIGluc3RhbmNlLlxuICogU3VibmV0cyBjYW4gYmUgY29uZmlndXJlZCB3aXRoIHNwZWNpZmljIElQIGFkZHJlc3MgcmFuZ2VzIChJUHY0IGFuZCBJUHY2KSwgYXZhaWxhYmlsaXR5IHpvbmVzLFxuICogYW5kIHN1Ym5ldCB0eXBlcyAoZS5nLiwgcHVibGljLCBwcml2YXRlLCBpc29sYXRlZCkuXG4gKlxuICogQHJlc291cmNlIEFXUzo6RUMyOjpTdWJuZXRcbiAqXG4gKi9cbmV4cG9ydCBjbGFzcyBTdWJuZXRWMiBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSVN1Ym5ldFYyIHtcblxuICAvKipcbiAgICogVGhlIEF2YWlsYWJpbGl0eSBab25lIHRoZSBzdWJuZXQgaXMgbG9jYXRlZCBpblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGF2YWlsYWJpbGl0eVpvbmU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHN1Ym5ldElkIGZvciB0aGlzIHBhcnRpY3VsYXIgc3VibmV0XG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzdWJuZXRJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiAgRGVwZW5kZW5jaWVzIGZvciBpbnRlcm5ldCBjb25uZWN0aXZpdHlcbiAgICogVGhpcyBQcm9wZXJ0eSBleHBvc2VzIHRoZSBSb3V0ZVRhYmxlLVN1Ym5ldCBhc3NvY2lhdGlvbiBzbyB0aGF0IG90aGVyIHJlc291cmNlcyBjYW4gZGVwZW5kIG9uIGl0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGludGVybmV0Q29ubmVjdGl2aXR5RXN0YWJsaXNoZWQ6IElEZXBlbmRhYmxlO1xuXG4gIC8qKlxuICAgKiBUaGUgdmFyaWFibGUgbmFtZSBgaW50ZXJuZXRDb25uZWN0aXZpdHlFc3RhYmxpc2hlZGAgZG9lcyBub3QgcmVmbGVjdCB3aGF0IGl0IGFjdHVhbGx5IGlzLlxuICAgKiBUaGUgbmFtaW5nIGlzIGVuZm9yY2VkIGJ5IElTdWJuZXQuIFdlIG5lZWQgdG8ga2VlcCBpdCB0byBtYWludGFpbiBjb21wYXRpYmlsaXR5LlxuICAgKiBJdCBleHBvc2VzIHRoZSBSb3V0ZVRhYmxlLVN1Ym5ldCBhc3NvY2lhdGlvbiBzbyB0aGF0IG90aGVyIHJlc291cmNlcyBjYW4gZGVwZW5kIG9uIGl0LlxuICAgKiBFLmcuIFJlc291cmNlcyBpbiBhIHN1Ym5ldCwgd2hlbiBiZWluZyBkZWxldGVkLCBtYXkgbmVlZCB0aGUgUm91dGVUYWJsZSB0byBleGlzdCBpbiBvcmRlciB0byBkZWxldGUgcHJvcGVybHlcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2ludGVybmV0Q29ubmVjdGl2aXR5RXN0YWJsaXNoZWQgPSBuZXcgRGVwZW5kZW5jeUdyb3VwKCk7XG5cbiAgLyoqXG4gICAqIFRoZSBJUHY0IENJRFIgYmxvY2sgZm9yIHRoaXMgc3VibmV0XG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXB2NENpZHJCbG9jazogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgSVB2NiBDSURSIEJsb2NrIGZvciB0aGlzIHN1Ym5ldFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGlwdjZDaWRyQmxvY2s/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByb3V0ZSB0YWJsZSBmb3IgdGhpcyBzdWJuZXRcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSByb3V0ZVRhYmxlOiBJUm91dGVUYWJsZTtcblxuICAvKipcbiAgICogVGhlIHR5cGUgb2Ygc3VibmV0IChwdWJsaWMgb3IgcHJpdmF0ZSkgdGhhdCB0aGlzIHN1Ym5ldCByZXByZXNlbnRzLlxuICAgKiBAYXR0cmlidXRlIFN1Ym5ldFR5cGVcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzdWJuZXRUeXBlOiBTdWJuZXRUeXBlO1xuXG4gIHByaXZhdGUgX25ldHdvcmtBY2w6IElOZXR3b3JrQWNsO1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFN1Ym5ldFYyIGluc3RhbmNlLlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHBhcmVudCBDb25zdHJ1Y3QgdGhhdCB0aGlzIHJlc291cmNlIHdpbGwgYmUgcGFydCBvZi5cbiAgICogQHBhcmFtIGlkIFRoZSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhpcyByZXNvdXJjZS5cbiAgICogQHBhcmFtIHByb3BzIFRoZSBjb25maWd1cmF0aW9uIHByb3BlcnRpZXMgZm9yIHRoZSBzdWJuZXQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogU3VibmV0VjJQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgcGh5c2ljYWxOYW1lOiBwcm9wcy5zdWJuZXROYW1lID8/IExhenkuc3RyaW5nKHtcbiAgICAgICAgcHJvZHVjZTogKCkgPT4gTmFtZXMudW5pcXVlUmVzb3VyY2VOYW1lKHRoaXMsIHsgbWF4TGVuZ3RoOiAxMjgsIGFsbG93ZWRTcGVjaWFsQ2hhcmFjdGVyczogJ18nIH0pLFxuICAgICAgfSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBpcHY0Q2lkckJsb2NrID0gcHJvcHMuaXB2NENpZHJCbG9jay5jaWRyO1xuICAgIGNvbnN0IGlwdjZDaWRyQmxvY2sgPSBwcm9wcy5pcHY2Q2lkckJsb2NrPy5jaWRyO1xuXG4gICAgaWYgKCFjaGVja0NpZHJSYW5nZXMocHJvcHMudnBjLCBwcm9wcy5pcHY0Q2lkckJsb2NrLmNpZHIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NJRFIgYmxvY2sgc2hvdWxkIGJlIHdpdGhpbiB0aGUgcmFuZ2Ugb2YgVlBDJyk7XG4gICAgfTtcblxuICAgIGxldCBvdmVybGFwOiBib29sZWFuID0gZmFsc2U7XG4gICAgbGV0IG92ZXJsYXBJcHY2OiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBvdmVybGFwID0gdmFsaWRhdGVPdmVybGFwcGluZ0NpZHJSYW5nZXMocHJvcHMudnBjLCBwcm9wcy5pcHY0Q2lkckJsb2NrLmNpZHIpO1xuXG4gICAgLy9jaGVjayB3aGV0aGVyIFZQQyBzdXBwb3J0cyBpcHY2XG4gICAgaWYgKHByb3BzLmlwdjZDaWRyQmxvY2s/LmNpZHIpIHtcbiAgICAgIHZhbGlkYXRlU3VwcG9ydElwdjYocHJvcHMudnBjKTtcbiAgICAgIG92ZXJsYXBJcHY2ID0gdmFsaWRhdGVPdmVybGFwcGluZ0NpZHJSYW5nZXNpcHY2KHByb3BzLnZwYywgcHJvcHMuaXB2NkNpZHJCbG9jaz8uY2lkcik7XG4gICAgfVxuXG4gICAgaWYgKG92ZXJsYXAgfHwgb3ZlcmxhcElwdjYpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ0lEUiBibG9jayBzaG91bGQgbm90IG92ZXJsYXAgd2l0aCBleGlzdGluZyBzdWJuZXQgYmxvY2tzJyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmFzc2lnbklwdjZBZGRyZXNzT25DcmVhdGlvbiAmJiAhcHJvcHMuaXB2NkNpZHJCbG9jaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJUHY2IENJRFIgYmxvY2sgaXMgcmVxdWlyZWQgd2hlbiBhc3NpZ25pbmcgSVB2NiBhZGRyZXNzIG9uIGNyZWF0aW9uJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3VibmV0ID0gbmV3IENmblN1Ym5ldCh0aGlzLCAnU3VibmV0Jywge1xuICAgICAgdnBjSWQ6IHByb3BzLnZwYy52cGNJZCxcbiAgICAgIGNpZHJCbG9jazogaXB2NENpZHJCbG9jayxcbiAgICAgIGlwdjZDaWRyQmxvY2s6IGlwdjZDaWRyQmxvY2ssXG4gICAgICBhdmFpbGFiaWxpdHlab25lOiBwcm9wcy5hdmFpbGFiaWxpdHlab25lLFxuICAgICAgYXNzaWduSXB2NkFkZHJlc3NPbkNyZWF0aW9uOiBwcm9wcy5hc3NpZ25JcHY2QWRkcmVzc09uQ3JlYXRpb24gPz8gZmFsc2UsXG4gICAgfSk7XG5cbiAgICB0aGlzLm5vZGUuZGVmYXVsdENoaWxkID0gc3VibmV0O1xuICAgIHRoaXMuaXB2NENpZHJCbG9jayA9IHByb3BzLmlwdjRDaWRyQmxvY2suY2lkcjtcbiAgICB0aGlzLmlwdjZDaWRyQmxvY2sgPSBwcm9wcy5pcHY2Q2lkckJsb2NrPy5jaWRyO1xuICAgIHRoaXMuc3VibmV0SWQgPSBzdWJuZXQucmVmO1xuICAgIHRoaXMuYXZhaWxhYmlsaXR5Wm9uZSA9IHByb3BzLmF2YWlsYWJpbGl0eVpvbmU7XG5cbiAgICB0aGlzLl9uZXR3b3JrQWNsID0gTmV0d29ya0FjbC5mcm9tTmV0d29ya0FjbElkKHRoaXMsICdBY2wnLCBzdWJuZXQuYXR0ck5ldHdvcmtBY2xBc3NvY2lhdGlvbklkKTtcblxuICAgIGlmIChwcm9wcy5yb3V0ZVRhYmxlKSB7XG4gICAgICB0aGlzLnJvdXRlVGFibGUgPSBwcm9wcy5yb3V0ZVRhYmxlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBkZWZhdWx0VGFibGUgPSBuZXcgQ2ZuUm91dGVUYWJsZSh0aGlzLCAnUm91dGVUYWJsZScsIHtcbiAgICAgICAgdnBjSWQ6IHByb3BzLnZwYy52cGNJZCxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5yb3V0ZVRhYmxlID0geyByb3V0ZVRhYmxlSWQ6IGRlZmF1bHRUYWJsZS5yZWYgfTtcbiAgICB9XG5cbiAgICBjb25zdCByb3V0ZUFzc29jID0gbmV3IENmblN1Ym5ldFJvdXRlVGFibGVBc3NvY2lhdGlvbih0aGlzLCAnUm91dGVUYWJsZUFzc29jaWF0aW9uJywge1xuICAgICAgc3VibmV0SWQ6IHRoaXMuc3VibmV0SWQsXG4gICAgICByb3V0ZVRhYmxlSWQ6IHRoaXMucm91dGVUYWJsZS5yb3V0ZVRhYmxlSWQsXG4gICAgfSk7XG4gICAgdGhpcy5faW50ZXJuZXRDb25uZWN0aXZpdHlFc3RhYmxpc2hlZC5hZGQocm91dGVBc3NvYyk7XG4gICAgdGhpcy5pbnRlcm5ldENvbm5lY3Rpdml0eUVzdGFibGlzaGVkID0gdGhpcy5faW50ZXJuZXRDb25uZWN0aXZpdHlFc3RhYmxpc2hlZDtcblxuICAgIHRoaXMuc3VibmV0VHlwZSA9IHByb3BzLnN1Ym5ldFR5cGU7XG4gICAgc3RvcmVTdWJuZXRUb1ZwY0J5VHlwZShwcm9wcy52cGMsIHRoaXMsIHByb3BzLnN1Ym5ldFR5cGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc29jaWF0ZSBhIE5ldHdvcmsgQUNMIHdpdGggdGhpcyBzdWJuZXRcbiAgICpcbiAgICogQHBhcmFtIGlkIFRoZSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhpcyBhc3NvY2lhdGlvbi5cbiAgICogQHBhcmFtIG5ldHdvcmtBY2wgVGhlIE5ldHdvcmsgQUNMIHRvIGFzc29jaWF0ZSB3aXRoIHRoaXMgc3VibmV0LlxuICAgKiBUaGlzIGFsbG93cyBjb250cm9sbGluZyBpbmJvdW5kIGFuZCBvdXRib3VuZCB0cmFmZmljIGZvciBpbnN0YW5jZXMgaW4gdGhpcyBzdWJuZXQuXG4gICAqL1xuICBwdWJsaWMgYXNzb2NpYXRlTmV0d29ya0FjbChpZDogc3RyaW5nLCBuZXR3b3JrQWNsOiBJTmV0d29ya0FjbCkge1xuICAgIHRoaXMuX25ldHdvcmtBY2wgPSBuZXR3b3JrQWNsO1xuXG4gICAgY29uc3Qgc2NvcGUgPSBuZXR3b3JrQWNsIGluc3RhbmNlb2YgQ29uc3RydWN0ID8gbmV0d29ya0FjbCA6IHRoaXM7XG4gICAgY29uc3Qgb3RoZXIgPSBuZXR3b3JrQWNsIGluc3RhbmNlb2YgQ29uc3RydWN0ID8gdGhpcyA6IG5ldHdvcmtBY2w7XG4gICAgbmV3IFN1Ym5ldE5ldHdvcmtBY2xBc3NvY2lhdGlvbihzY29wZSwgaWQgKyBOYW1lcy5ub2RlVW5pcXVlSWQob3RoZXIubm9kZSksIHtcbiAgICAgIG5ldHdvcmtBY2wsXG4gICAgICBzdWJuZXQ6IHRoaXMsXG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIE5ldHdvcmsgQUNMIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHN1Ym5ldC5cbiAgICovXG5cbiAgcHVibGljIGdldCBuZXR3b3JrQWNsKCk6IElOZXR3b3JrQWNsIHtcbiAgICByZXR1cm4gdGhpcy5fbmV0d29ya0FjbDtcbiAgfVxufVxuXG5jb25zdCBzdWJuZXRUeXBlTWFwID0ge1xuICBbU3VibmV0VHlwZS5QUklWQVRFX0lTT0xBVEVEXTogKHZwYzogSVZwY1YyLCBzdWJuZXQ6IFN1Ym5ldFYyKSA9PiB2cGMuaXNvbGF0ZWRTdWJuZXRzLnB1c2goc3VibmV0KSxcbiAgW1N1Ym5ldFR5cGUuUFVCTElDXTogKHZwYzogSVZwY1YyLCBzdWJuZXQ6IFN1Ym5ldFYyKSA9PiB2cGMucHVibGljU3VibmV0cy5wdXNoKHN1Ym5ldCksXG4gIFtTdWJuZXRUeXBlLlBSSVZBVEVfV0lUSF9FR1JFU1NdOiAodnBjOiBJVnBjVjIsIHN1Ym5ldDogU3VibmV0VjIpID0+IHZwYy5wcml2YXRlU3VibmV0cy5wdXNoKHN1Ym5ldCksXG4gIFtTdWJuZXRUeXBlLklTT0xBVEVEXTogKHZwYzogSVZwY1YyLCBzdWJuZXQ6IFN1Ym5ldFYyKSA9PiB2cGMuaXNvbGF0ZWRTdWJuZXRzLnB1c2goc3VibmV0KSxcbiAgW1N1Ym5ldFR5cGUuUFJJVkFURV06ICh2cGM6IElWcGNWMiwgc3VibmV0OiBTdWJuZXRWMikgPT4gdnBjLnByaXZhdGVTdWJuZXRzLnB1c2goc3VibmV0KSxcbiAgW1N1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX05BVF06ICh2cGM6IElWcGNWMiwgc3VibmV0OiBTdWJuZXRWMikgPT4gdnBjLnByaXZhdGVTdWJuZXRzLnB1c2goc3VibmV0KSxcbn07XG5cbi8qKlxuICogU3RvcmVzIHRoZSBwcm92aWRlZCBzdWJuZXQgaW4gdGhlIFZQQydzIGNvbGxlY3Rpb24gb2Ygc3VibmV0cyBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIHN1Ym5ldCB0eXBlLlxuICpcbiAqIEBwYXJhbSB2cGMgVGhlIFZQQyBpbnN0YW5jZSB0byB3aGljaCB0aGUgc3VibmV0IGJlbG9uZ3MuXG4gKiBAcGFyYW0gc3VibmV0IFRoZSBzdWJuZXQgaW5zdGFuY2UgdG8gYmUgc3RvcmVkLlxuICogQHBhcmFtIHR5cGUgVGhlIHR5cGUgb2YgdGhlIHN1Ym5ldCAoZS5nLiwgcHVibGljLCBwcml2YXRlLCBpc29sYXRlZCkuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZnVuY3Rpb24gc3RvcmVTdWJuZXRUb1ZwY0J5VHlwZSh2cGM6IElWcGNWMiwgc3VibmV0OiBTdWJuZXRWMiwgdHlwZTogU3VibmV0VHlwZSkge1xuICBjb25zdCBmaW5kRnVuY3Rpb25UeXBlID0gc3VibmV0VHlwZU1hcFt0eXBlXTtcbiAgaWYgKGZpbmRGdW5jdGlvblR5cGUpIHtcbiAgICBmaW5kRnVuY3Rpb25UeXBlKHZwYywgc3VibmV0KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIHN1Ym5ldCB0eXBlOiAke3R5cGV9YCk7XG4gIH1cblxuICAvKipcbiAgICogTmVlZCB0byBzZXQgZXhwbGljaXQgZGVwZW5kZW5jeSBhcyBkdXJpbmcgc3RhY2sgZGVsZXRpb24sXG4gICAqIHRoZSBjaWRyIGJsb2NrcyBtYXkgZ2V0IGRlbGV0ZWQgZmlyc3QgYW5kIHdpbGwgZmFpbCBhcyB0aGUgc3VibmV0cyBhcmUgc3RpbGwgdXNpbmcgdGhlIGNpZHIgYmxvY2tzXG4gICAqL1xuICBmb3IgKGNvbnN0IGNpZHIgb2YgdnBjLnNlY29uZGFyeUNpZHJCbG9jaykge1xuICAgIHN1Ym5ldC5ub2RlLmFkZERlcGVuZGVuY3koY2lkcik7XG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgd2hldGhlciB0aGUgcHJvdmlkZWQgVlBDIHN1cHBvcnRzIElQdjYgYWRkcmVzc2VzLlxuICpcbiAqIEBwYXJhbSB2cGMgVGhlIFZQQyBpbnN0YW5jZSB0byBiZSB2YWxpZGF0ZWQuXG4gKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBWUEMgZG9lcyBub3Qgc3VwcG9ydCBJUHY2IGFkZHJlc3Nlcy5cbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIFZQQyBzdXBwb3J0cyBJUHY2IGFkZHJlc3NlcywgZmFsc2Ugb3RoZXJ3aXNlLlxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlU3VwcG9ydElwdjYodnBjOiBJVnBjVjIpIHtcbiAgaWYgKHZwYy5zZWNvbmRhcnlDaWRyQmxvY2suc29tZSgoc2Vjb25kYXJ5QWRkcmVzcykgPT4gc2Vjb25kYXJ5QWRkcmVzcy5hbWF6b25Qcm92aWRlZElwdjZDaWRyQmxvY2sgPT09IHRydWUgfHxcbiAgc2Vjb25kYXJ5QWRkcmVzcy5pcHY2SXBhbVBvb2xJZCAhPSB1bmRlZmluZWQpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUbyB1c2UgSVB2NiwgdGhlIFZQQyBtdXN0IGVuYWJsZSBJUHY2IHN1cHBvcnQuJyk7XG4gIH1cbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIHByb3ZpZGVkIENJRFIgcmFuZ2UgZmFsbHMgd2l0aGluIHRoZSBJUCBhZGRyZXNzIHJhbmdlcyBvZiB0aGUgZ2l2ZW4gVlBDLlxuICpcbiAqIEBwYXJhbSB2cGMgVGhlIFZQQyBpbnN0YW5jZSB0byBjaGVjayBhZ2FpbnN0LlxuICogQHBhcmFtIGNpZHJSYW5nZSBUaGUgQ0lEUiByYW5nZSB0byBiZSBjaGVja2VkLlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgQ0lEUiByYW5nZSBmYWxscyB3aXRoaW4gdGhlIFZQQydzIElQIGFkZHJlc3MgcmFuZ2VzLCBmYWxzZSBvdGhlcndpc2UuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZnVuY3Rpb24gY2hlY2tDaWRyUmFuZ2VzKHZwYzogSVZwY1YyLCBjaWRyUmFuZ2U6IHN0cmluZykge1xuXG4gIGNvbnN0IHZwY0NpZHJCbG9jayA9IFt2cGMuaXB2NENpZHJCbG9ja107XG5cbiAgZm9yIChjb25zdCBpcEFkZHJlc3Mgb2YgdnBjLnNlY29uZGFyeUNpZHJCbG9jaykge1xuICAgIGlmIChpcEFkZHJlc3MuY2lkckJsb2NrKSB7XG4gICAgICB2cGNDaWRyQmxvY2sucHVzaChpcEFkZHJlc3MuY2lkckJsb2NrKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgY2lkcnMgPSB2cGNDaWRyQmxvY2subWFwKGNpZHIgPT4gbmV3IENpZHJCbG9jayhjaWRyKSk7XG5cbiAgY29uc3Qgc3VibmV0Q2lkckJsb2NrID0gbmV3IENpZHJCbG9jayhjaWRyUmFuZ2UpO1xuXG4gIHJldHVybiBjaWRycy5zb21lKGMgPT4gYy5jb250YWluc0NpZHIoc3VibmV0Q2lkckJsb2NrKSk7XG5cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgaWYgdGhlIHByb3ZpZGVkIElQdjQgQ0lEUiBibG9jayBvdmVybGFwcyB3aXRoIGV4aXN0aW5nIHN1Ym5ldCBDSURSIGJsb2NrcyB3aXRoaW4gdGhlIGdpdmVuIFZQQy5cbiAqXG4gKiBAcGFyYW0gdnBjIFRoZSBWUEMgaW5zdGFuY2UgdG8gY2hlY2sgYWdhaW5zdC5cbiAqIEBwYXJhbSBpcHY0Q2lkckJsb2NrIFRoZSBJUHY0IENJRFIgYmxvY2sgdG8gYmUgdmFsaWRhdGVkLlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgSVB2NCBDSURSIGJsb2NrIG92ZXJsYXBzIHdpdGggZXhpc3Rpbmcgc3VibmV0IENJRFIgYmxvY2tzLCBmYWxzZSBvdGhlcndpc2UuXG4gKiBAaW50ZXJuYWxcbiAqL1xuXG5mdW5jdGlvbiB2YWxpZGF0ZU92ZXJsYXBwaW5nQ2lkclJhbmdlcyh2cGM6IElWcGNWMiwgaXB2NENpZHJCbG9jazogc3RyaW5nKTogYm9vbGVhbiB7XG5cbiAgbGV0IGFsbFN1Ym5ldHM6IElTdWJuZXRWMltdO1xuICB0cnkge1xuICAgIGFsbFN1Ym5ldHMgPSB2cGMuc2VsZWN0U3VibmV0cygpLnN1Ym5ldHM7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAnTm8gc3VibmV0cyBpbiBWUEMnO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IGlwTWFwOiBbc3RyaW5nLCBzdHJpbmddW10gPSBuZXcgQXJyYXkoKTtcblxuICBjb25zdCBpbnB1dFJhbmdlID0gbmV3IENpZHJCbG9jayhpcHY0Q2lkckJsb2NrKTtcblxuICBjb25zdCBpbnB1dElwTWFwOiBbc3RyaW5nLCBzdHJpbmddID0gW2lucHV0UmFuZ2UubWluSXAoKSwgaW5wdXRSYW5nZS5tYXhJcCgpXTtcblxuICBmb3IgKGNvbnN0IHN1Ym5ldCBvZiBhbGxTdWJuZXRzKSB7XG4gICAgY29uc3QgY2lkckJsb2NrID0gbmV3IENpZHJCbG9jayhzdWJuZXQuaXB2NENpZHJCbG9jayk7XG4gICAgaXBNYXAucHVzaChbY2lkckJsb2NrLm1pbklwKCksIGNpZHJCbG9jay5tYXhJcCgpXSk7XG4gIH1cblxuICBmb3IgKGNvbnN0IHJhbmdlIG9mIGlwTWFwKSB7XG4gICAgaWYgKGlucHV0UmFuZ2UucmFuZ2VzT3ZlcmxhcChyYW5nZSwgaW5wdXRJcE1hcCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgaWYgdGhlIHByb3ZpZGVkIElQdjYgQ0lEUiBibG9jayBvdmVybGFwcyB3aXRoIGV4aXN0aW5nIHN1Ym5ldCBDSURSIGJsb2NrcyB3aXRoaW4gdGhlIGdpdmVuIFZQQy5cbiAqXG4gKiBAcGFyYW0gdnBjIFRoZSBWUEMgaW5zdGFuY2UgdG8gY2hlY2sgYWdhaW5zdC5cbiAqIEBwYXJhbSBpcHY2Q2lkckJsb2NrIFRoZSBJUHY2IENJRFIgYmxvY2sgdG8gYmUgdmFsaWRhdGVkLlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgSVB2NiBDSURSIGJsb2NrIG92ZXJsYXBzIHdpdGggZXhpc3Rpbmcgc3VibmV0IENJRFIgYmxvY2tzLCBmYWxzZSBvdGhlcndpc2UuXG4gKiBAdGhyb3dzIEVycm9yIGlmIG5vIHN1Ym5ldHMgYXJlIGZvdW5kIGluIHRoZSBWUEMuXG4gKiBAaW50ZXJuYWxcbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVPdmVybGFwcGluZ0NpZHJSYW5nZXNpcHY2KHZwYzogSVZwY1YyLCBpcHY2Q2lkckJsb2NrOiBzdHJpbmcpOiBib29sZWFuIHtcblxuICBsZXQgYWxsU3VibmV0czogSVN1Ym5ldFYyW107XG4gIHRyeSB7XG4gICAgYWxsU3VibmV0cyA9IHZwYy5zZWxlY3RTdWJuZXRzKCkuc3VibmV0cztcbiAgfSBjYXRjaCAoZSkge1xuICAgICdObyBzdWJuZXRzIGluIFZQQyc7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgaXB2Nk1hcDogc3RyaW5nW109IFtdO1xuXG4gIGNvbnN0IGlucHV0UmFuZ2UgPSBuZXcgQ2lkckJsb2NrSXB2NihpcHY2Q2lkckJsb2NrKTtcblxuICBsZXQgcmVzdWx0IDogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIGZvciAoY29uc3Qgc3VibmV0IG9mIGFsbFN1Ym5ldHMpIHtcbiAgICBpZiAoc3VibmV0LmlwdjZDaWRyQmxvY2spIHtcbiAgICAgIGNvbnN0IGNpZHJCbG9jayA9IG5ldyBDaWRyQmxvY2tJcHY2KHN1Ym5ldC5pcHY2Q2lkckJsb2NrKTtcbiAgICAgIGlwdjZNYXAucHVzaChjaWRyQmxvY2suY2lkcik7XG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCByYW5nZSBvZiBpcHY2TWFwKSB7XG4gICAgaWYgKGlucHV0UmFuZ2UucmFuZ2VzT3ZlcmxhcChyYW5nZSwgaW5wdXRSYW5nZS5jaWRyKSkge1xuICAgICAgcmVzdWx0ID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuIl19
|
package/lib/util.d.ts
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { ISubnet } from 'aws-cdk-lib/aws-ec2';
|
|
2
|
+
/**
|
|
3
|
+
* Return a subnet name from its construct ID
|
|
4
|
+
*
|
|
5
|
+
* All subnet names look like NAME <> "Subnet" <> INDEX
|
|
6
|
+
*/
|
|
7
|
+
export declare function subnetGroupNameFromConstructId(subnet: ISubnet): string;
|
|
8
|
+
/**
|
|
9
|
+
* Make the subnet construct ID from a name and number
|
|
10
|
+
*/
|
|
11
|
+
export declare function subnetId(name: string, i: number): string;
|
|
12
|
+
/**
|
|
13
|
+
* Return the union of table IDs from all selected subnets
|
|
14
|
+
*/
|
|
15
|
+
export declare function allRouteTableIds(subnets: ISubnet[]): string[];
|
|
16
|
+
export declare function flatten<A>(xs: A[][]): A[];
|
|
17
|
+
/**
|
|
18
|
+
* NetworkUtils contains helpers to work with network constructs (subnets/ranges)
|
|
19
|
+
*/
|
|
20
|
+
export declare class NetworkUtils {
|
|
21
|
+
/**
|
|
22
|
+
* Validates an IPv4 address string.
|
|
23
|
+
*
|
|
24
|
+
* @param ipAddress The IPv4 address string to be validated.
|
|
25
|
+
* @returns True if the string is a valid IPv4 address, false otherwise.
|
|
26
|
+
* Validates an IPv4 string
|
|
27
|
+
*
|
|
28
|
+
* returns true of the string contains 4 numbers between 0-255 delimited by
|
|
29
|
+
* a `.` character
|
|
30
|
+
*/
|
|
31
|
+
static validIp(ipAddress: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Converts a string representation of an IPv4 address to its corresponding numerical value.
|
|
34
|
+
*
|
|
35
|
+
* Uses the formula:
|
|
36
|
+
* (first octet * 256³) + (second octet * 256²) + (third octet * 256) +
|
|
37
|
+
* (fourth octet)
|
|
38
|
+
*
|
|
39
|
+
* @param ipAddress the IP address (e.g. 174.66.173.168)
|
|
40
|
+
* @returns the integer value of the IP address (e.g 2923605416)
|
|
41
|
+
*/
|
|
42
|
+
static ipToNum(ipAddress: string): number;
|
|
43
|
+
/**
|
|
44
|
+
* Takes number and converts it to IPv4 address string
|
|
45
|
+
*
|
|
46
|
+
* Takes a number (e.g 2923605416) and converts it to an IPv4 address string
|
|
47
|
+
* currently only supports IPv4
|
|
48
|
+
*
|
|
49
|
+
* @param ipNum integer value of the IP address (e.g 2923605416)
|
|
50
|
+
* @returns IPv4 address (e.g. 174.66.173.168)
|
|
51
|
+
*/
|
|
52
|
+
static numToIp(ipNum: number): string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Exported class from VPC to support subnet filtering
|
|
56
|
+
* and CIDR validation
|
|
57
|
+
*/
|
|
58
|
+
export declare class CidrBlock {
|
|
59
|
+
/**
|
|
60
|
+
* Calculates the netmask for a given CIDR mask
|
|
61
|
+
*
|
|
62
|
+
* The netmask is a 32-bit binary value used to separate the network portion from the host portion of an IPv4 address.
|
|
63
|
+
* It is calculated based on the CIDR prefix length (the number of bits used to represent the network portion).
|
|
64
|
+
*
|
|
65
|
+
* For example:
|
|
66
|
+
* CidrBlock.calculateNetmask(24) returns '255.255.255.0'
|
|
67
|
+
*
|
|
68
|
+
* @param mask The CIDR prefix length (between 0 and 32) for which to calculate the netmask.
|
|
69
|
+
// Calculate the netmask by performing a bitwise NOT on the result of (2^32 - 2^(32 - mask))
|
|
70
|
+
* @returns The netmask string in IPv4 address format.
|
|
71
|
+
*/
|
|
72
|
+
static calculateNetmask(mask: number): string;
|
|
73
|
+
/**
|
|
74
|
+
* Calculates the number IP addresses in a CIDR Mask
|
|
75
|
+
*
|
|
76
|
+
* For example:
|
|
77
|
+
* CidrBlock.calculateNetsize(16) returns 65536
|
|
78
|
+
*
|
|
79
|
+
* @param mask The CIDR prefix length (between 0 and 32) for which to calculate the network size.
|
|
80
|
+
* CidrBlock.calculateNetsize(24) returns 256
|
|
81
|
+
*/
|
|
82
|
+
static calculateNetsize(mask: number): number;
|
|
83
|
+
/**
|
|
84
|
+
* IP address in the CIDR block.
|
|
85
|
+
*/
|
|
86
|
+
readonly cidr: string;
|
|
87
|
+
readonly mask: number;
|
|
88
|
+
readonly networkSize: number;
|
|
89
|
+
private readonly networkAddress;
|
|
90
|
+
constructor(cidr: string);
|
|
91
|
+
constructor(ipAddress: number, mask: number);
|
|
92
|
+
maxIp(): string;
|
|
93
|
+
minIp(): string;
|
|
94
|
+
minAddress(): number;
|
|
95
|
+
maxAddress(): number;
|
|
96
|
+
nextBlock(): CidrBlock;
|
|
97
|
+
containsCidr(other: CidrBlock): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Checks if two IP address ranges overlap.
|
|
100
|
+
*
|
|
101
|
+
* @param range1 The first IP address range represented as an array [start, end].
|
|
102
|
+
* @param range2 The second IP address range represented as an array [start, end].
|
|
103
|
+
* @returns True if the two IP address ranges overlap, false otherwise.
|
|
104
|
+
*
|
|
105
|
+
* Note: This method assumes that the start and end addresses are valid IPv4 addresses.
|
|
106
|
+
*/
|
|
107
|
+
rangesOverlap(range1: [string, string], range2: [string, string]): boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Class with helper functions to support
|
|
111
|
+
* Subnet Ipv6 Address Validation
|
|
112
|
+
*
|
|
113
|
+
* This class provides methods for working with IPv6 CIDR blocks, including calculating the minimum and maximum
|
|
114
|
+
* IP addresses in a CIDR block, and checking if two CIDR blocks overlap.
|
|
115
|
+
*/
|
|
116
|
+
export declare class CidrBlockIpv6 {
|
|
117
|
+
/**
|
|
118
|
+
* Ipv6 CIDR range
|
|
119
|
+
*/
|
|
120
|
+
cidr: string;
|
|
121
|
+
/**
|
|
122
|
+
* The CIDR prefix length (number of bits used for the network portion of the address).
|
|
123
|
+
*/
|
|
124
|
+
cidrPrefix: number;
|
|
125
|
+
private ipParts;
|
|
126
|
+
private networkBits;
|
|
127
|
+
private networkPart;
|
|
128
|
+
constructor(cidr: string);
|
|
129
|
+
private parseBigIntParts;
|
|
130
|
+
/**
|
|
131
|
+
* @returns Minimum IPv6 address for a provided CIDR
|
|
132
|
+
*/
|
|
133
|
+
minIp(): string;
|
|
134
|
+
/**
|
|
135
|
+
* @returns Maximum IPv6 address for a provided CIDR
|
|
136
|
+
*/
|
|
137
|
+
maxIp(): string;
|
|
138
|
+
private formatIPv6Part;
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
* @param range1 Ipv6 CIDR range to compare
|
|
142
|
+
* @param range2 Ipv6 CIDR range to compare
|
|
143
|
+
* @returns true if two ranges overlap, false otherwise
|
|
144
|
+
*/
|
|
145
|
+
rangesOverlap(range1: string, range2: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
*
|
|
148
|
+
* @param cidr
|
|
149
|
+
* @returns Range in the from of big int number [start, end]
|
|
150
|
+
*/
|
|
151
|
+
private getIPv6Range;
|
|
152
|
+
/**
|
|
153
|
+
* @param ipv6Address
|
|
154
|
+
* @returns Converts given ipv6 address range to big int number
|
|
155
|
+
*/
|
|
156
|
+
private ipv6ToNumber;
|
|
157
|
+
}
|