@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/util.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*eslint no-bitwise: ["error", { "allow": ["~", "|", "<<", "&"] }] */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.CidrBlockIpv6 = exports.CidrBlock = exports.NetworkUtils = exports.flatten = exports.allRouteTableIds = exports.subnetId = exports.subnetGroupNameFromConstructId = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Return a subnet name from its construct ID
|
|
7
|
+
*
|
|
8
|
+
* All subnet names look like NAME <> "Subnet" <> INDEX
|
|
9
|
+
*/
|
|
10
|
+
function subnetGroupNameFromConstructId(subnet) {
|
|
11
|
+
return subnet.node.id.replace(/Subnet\d+$/, '');
|
|
12
|
+
}
|
|
13
|
+
exports.subnetGroupNameFromConstructId = subnetGroupNameFromConstructId;
|
|
14
|
+
/**
|
|
15
|
+
* Make the subnet construct ID from a name and number
|
|
16
|
+
*/
|
|
17
|
+
function subnetId(name, i) {
|
|
18
|
+
return `${name}Subnet${i + 1}`;
|
|
19
|
+
}
|
|
20
|
+
exports.subnetId = subnetId;
|
|
21
|
+
/**
|
|
22
|
+
* Return the union of table IDs from all selected subnets
|
|
23
|
+
*/
|
|
24
|
+
function allRouteTableIds(subnets) {
|
|
25
|
+
const ret = new Set();
|
|
26
|
+
for (const subnet of subnets) {
|
|
27
|
+
if (subnet.routeTable && subnet.routeTable.routeTableId) {
|
|
28
|
+
ret.add(subnet.routeTable.routeTableId);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return Array.from(ret);
|
|
32
|
+
}
|
|
33
|
+
exports.allRouteTableIds = allRouteTableIds;
|
|
34
|
+
function flatten(xs) {
|
|
35
|
+
return Array.prototype.concat.apply([], xs);
|
|
36
|
+
}
|
|
37
|
+
exports.flatten = flatten;
|
|
38
|
+
/**
|
|
39
|
+
* NetworkUtils contains helpers to work with network constructs (subnets/ranges)
|
|
40
|
+
*/
|
|
41
|
+
class NetworkUtils {
|
|
42
|
+
/**
|
|
43
|
+
* Validates an IPv4 address string.
|
|
44
|
+
*
|
|
45
|
+
* @param ipAddress The IPv4 address string to be validated.
|
|
46
|
+
* @returns True if the string is a valid IPv4 address, false otherwise.
|
|
47
|
+
* Validates an IPv4 string
|
|
48
|
+
*
|
|
49
|
+
* returns true of the string contains 4 numbers between 0-255 delimited by
|
|
50
|
+
* a `.` character
|
|
51
|
+
*/
|
|
52
|
+
static validIp(ipAddress) {
|
|
53
|
+
const octets = ipAddress.split('.');
|
|
54
|
+
if (octets.length !== 4) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return octets.map((octet) => parseInt(octet, 10)).
|
|
58
|
+
every((octet) => octet >= 0 && octet <= 255);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Converts a string representation of an IPv4 address to its corresponding numerical value.
|
|
62
|
+
*
|
|
63
|
+
* Uses the formula:
|
|
64
|
+
* (first octet * 256³) + (second octet * 256²) + (third octet * 256) +
|
|
65
|
+
* (fourth octet)
|
|
66
|
+
*
|
|
67
|
+
* @param ipAddress the IP address (e.g. 174.66.173.168)
|
|
68
|
+
* @returns the integer value of the IP address (e.g 2923605416)
|
|
69
|
+
*/
|
|
70
|
+
static ipToNum(ipAddress) {
|
|
71
|
+
if (!this.validIp(ipAddress)) {
|
|
72
|
+
throw new Error(`${ipAddress} is not valid`);
|
|
73
|
+
}
|
|
74
|
+
return ipAddress
|
|
75
|
+
.split('.')
|
|
76
|
+
.reduce((p, c, i) => p + parseInt(c, 10) * 256 ** (3 - i), 0);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Takes number and converts it to IPv4 address string
|
|
80
|
+
*
|
|
81
|
+
* Takes a number (e.g 2923605416) and converts it to an IPv4 address string
|
|
82
|
+
* currently only supports IPv4
|
|
83
|
+
*
|
|
84
|
+
* @param ipNum integer value of the IP address (e.g 2923605416)
|
|
85
|
+
* @returns IPv4 address (e.g. 174.66.173.168)
|
|
86
|
+
*/
|
|
87
|
+
static numToIp(ipNum) {
|
|
88
|
+
// this all because bitwise math is signed
|
|
89
|
+
let remaining = ipNum;
|
|
90
|
+
const address = new Array();
|
|
91
|
+
for (let i = 0; i < 4; i++) {
|
|
92
|
+
if (remaining !== 0) {
|
|
93
|
+
address.push(Math.floor(remaining / 256 ** (3 - i)));
|
|
94
|
+
remaining = remaining % 256 ** (3 - i);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
address.push(0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const ipAddress = address.join('.');
|
|
101
|
+
if (!this.validIp(ipAddress)) {
|
|
102
|
+
throw new Error(`${ipAddress} is not a valid IP Address`);
|
|
103
|
+
}
|
|
104
|
+
return ipAddress;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.NetworkUtils = NetworkUtils;
|
|
108
|
+
/**
|
|
109
|
+
* Exported class from VPC to support subnet filtering
|
|
110
|
+
* and CIDR validation
|
|
111
|
+
*/
|
|
112
|
+
class CidrBlock {
|
|
113
|
+
/**
|
|
114
|
+
* Calculates the netmask for a given CIDR mask
|
|
115
|
+
*
|
|
116
|
+
* The netmask is a 32-bit binary value used to separate the network portion from the host portion of an IPv4 address.
|
|
117
|
+
* It is calculated based on the CIDR prefix length (the number of bits used to represent the network portion).
|
|
118
|
+
*
|
|
119
|
+
* For example:
|
|
120
|
+
* CidrBlock.calculateNetmask(24) returns '255.255.255.0'
|
|
121
|
+
*
|
|
122
|
+
* @param mask The CIDR prefix length (between 0 and 32) for which to calculate the netmask.
|
|
123
|
+
// Calculate the netmask by performing a bitwise NOT on the result of (2^32 - 2^(32 - mask))
|
|
124
|
+
* @returns The netmask string in IPv4 address format.
|
|
125
|
+
*/
|
|
126
|
+
static calculateNetmask(mask) {
|
|
127
|
+
return NetworkUtils.numToIp(2 ** 32 - 2 ** (32 - mask));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Calculates the number IP addresses in a CIDR Mask
|
|
131
|
+
*
|
|
132
|
+
* For example:
|
|
133
|
+
* CidrBlock.calculateNetsize(16) returns 65536
|
|
134
|
+
*
|
|
135
|
+
* @param mask The CIDR prefix length (between 0 and 32) for which to calculate the network size.
|
|
136
|
+
* CidrBlock.calculateNetsize(24) returns 256
|
|
137
|
+
*/
|
|
138
|
+
static calculateNetsize(mask) {
|
|
139
|
+
return 2 ** (32 - mask);
|
|
140
|
+
}
|
|
141
|
+
constructor(ipAddressOrCidr, mask) {
|
|
142
|
+
if (typeof ipAddressOrCidr === 'string') {
|
|
143
|
+
this.mask = parseInt(ipAddressOrCidr.split('/')[1], 10);
|
|
144
|
+
this.networkAddress = NetworkUtils.ipToNum(ipAddressOrCidr.split('/')[0]) +
|
|
145
|
+
CidrBlock.calculateNetsize(this.mask) - 1;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
if (typeof mask === 'number') {
|
|
149
|
+
this.mask = mask;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// this should be impossible
|
|
153
|
+
this.mask = 16;
|
|
154
|
+
}
|
|
155
|
+
this.networkAddress = ipAddressOrCidr + CidrBlock.calculateNetsize(this.mask) - 1;
|
|
156
|
+
this.networkSize = 2 ** (32 - this.mask);
|
|
157
|
+
}
|
|
158
|
+
this.networkSize = 2 ** (32 - this.mask);
|
|
159
|
+
this.cidr = `${this.minIp()}/${this.mask}`;
|
|
160
|
+
}
|
|
161
|
+
/*
|
|
162
|
+
* The maximum IP in the CIDR Block e.g. '10.0.8.255'
|
|
163
|
+
*/
|
|
164
|
+
maxIp() {
|
|
165
|
+
// min + (2^(32-mask)) - 1 [zero needs to count]
|
|
166
|
+
return NetworkUtils.numToIp(this.maxAddress());
|
|
167
|
+
}
|
|
168
|
+
/*
|
|
169
|
+
* Checks if this CIDR block fully contains the provided CIDR block.
|
|
170
|
+
*
|
|
171
|
+
* @param other The CIDR block to check for containment.
|
|
172
|
+
* @returns True if this CIDR block fully contains the provided CIDR block, false otherwise.
|
|
173
|
+
*
|
|
174
|
+
* The minimum IP in the CIDR Block e.g. '10.0.0.0'
|
|
175
|
+
*/
|
|
176
|
+
minIp() {
|
|
177
|
+
return NetworkUtils.numToIp(this.minAddress());
|
|
178
|
+
}
|
|
179
|
+
/*
|
|
180
|
+
* Returns the number representation for the minimum IPv4 address
|
|
181
|
+
*/
|
|
182
|
+
minAddress() {
|
|
183
|
+
const div = this.networkAddress % this.networkSize;
|
|
184
|
+
return this.networkAddress - div;
|
|
185
|
+
}
|
|
186
|
+
/*
|
|
187
|
+
* Returns the number representation for the maximum IPv4 address
|
|
188
|
+
*/
|
|
189
|
+
maxAddress() {
|
|
190
|
+
/**
|
|
191
|
+
* The maximum IP address in the CIDR block is calculated as the minimum address + (2^(32-mask)) - 1.
|
|
192
|
+
* This is because the minimum address represents the network address, and the maximum address is the broadcast address.
|
|
193
|
+
*/
|
|
194
|
+
// min + (2^(32-mask)) - 1 [zero needs to count]
|
|
195
|
+
return this.minAddress() + this.networkSize - 1;
|
|
196
|
+
}
|
|
197
|
+
/*
|
|
198
|
+
* Returns the next consecutive CIDR block of the same mask size following this CIDR block.
|
|
199
|
+
*
|
|
200
|
+
* For example, if this CIDR block is '10.0.0.0/24', the next block would be '10.0.1.0/24'.
|
|
201
|
+
*
|
|
202
|
+
* Returns the next CIDR Block of the same mask size
|
|
203
|
+
*/
|
|
204
|
+
nextBlock() {
|
|
205
|
+
return new CidrBlock(this.maxAddress() + 1, this.mask);
|
|
206
|
+
}
|
|
207
|
+
/*
|
|
208
|
+
* Returns true if this CidrBlock fully contains the provided CidrBlock
|
|
209
|
+
*/
|
|
210
|
+
containsCidr(other) {
|
|
211
|
+
return (this.maxAddress() >= other.maxAddress()) &&
|
|
212
|
+
(this.minAddress() <= other.minAddress());
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Checks if two IP address ranges overlap.
|
|
216
|
+
*
|
|
217
|
+
* @param range1 The first IP address range represented as an array [start, end].
|
|
218
|
+
* @param range2 The second IP address range represented as an array [start, end].
|
|
219
|
+
* @returns True if the two IP address ranges overlap, false otherwise.
|
|
220
|
+
*
|
|
221
|
+
* Note: This method assumes that the start and end addresses are valid IPv4 addresses.
|
|
222
|
+
*/
|
|
223
|
+
rangesOverlap(range1, range2) {
|
|
224
|
+
const [start1, end1] = range1;
|
|
225
|
+
const [start2, end2] = range2;
|
|
226
|
+
// Check if ranges overlap
|
|
227
|
+
return start1 <= end2 && start2 <= end1;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
exports.CidrBlock = CidrBlock;
|
|
231
|
+
/**
|
|
232
|
+
* Class with helper functions to support
|
|
233
|
+
* Subnet Ipv6 Address Validation
|
|
234
|
+
*
|
|
235
|
+
* This class provides methods for working with IPv6 CIDR blocks, including calculating the minimum and maximum
|
|
236
|
+
* IP addresses in a CIDR block, and checking if two CIDR blocks overlap.
|
|
237
|
+
*/
|
|
238
|
+
class CidrBlockIpv6 {
|
|
239
|
+
constructor(cidr) {
|
|
240
|
+
this.formatIPv6Part = (part) => part.toString(16).padStart(4, '0');
|
|
241
|
+
this.cidr = cidr;
|
|
242
|
+
const [ipAddress, prefix] = cidr.split('/');
|
|
243
|
+
this.cidrPrefix = parseInt(prefix, 10);
|
|
244
|
+
this.ipParts = this.parseBigIntParts(ipAddress);
|
|
245
|
+
this.networkBits = this.cidrPrefix;
|
|
246
|
+
this.networkPart = this.ipParts.slice(0, Math.ceil(this.networkBits / 16));
|
|
247
|
+
}
|
|
248
|
+
parseBigIntParts(ipAddress) {
|
|
249
|
+
return ipAddress.split(':').map((part) => BigInt(`0x${part.padStart(4, '0')}` || '0'));
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* @returns Minimum IPv6 address for a provided CIDR
|
|
253
|
+
*/
|
|
254
|
+
minIp() {
|
|
255
|
+
const startIP = [...this.networkPart];
|
|
256
|
+
for (let i = this.networkPart.length; i < 8; i++) {
|
|
257
|
+
startIP.push(BigInt(0));
|
|
258
|
+
}
|
|
259
|
+
return startIP.map(this.formatIPv6Part).join(':');
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* @returns Maximum IPv6 address for a provided CIDR
|
|
263
|
+
*/
|
|
264
|
+
maxIp() {
|
|
265
|
+
const endIP = [...this.networkPart];
|
|
266
|
+
const hostPart = Array(8 - this.networkPart.length).fill(BigInt(0xffff));
|
|
267
|
+
endIP.push(...hostPart);
|
|
268
|
+
return endIP.map(this.formatIPv6Part).join(':');
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
*
|
|
272
|
+
* @param range1 Ipv6 CIDR range to compare
|
|
273
|
+
* @param range2 Ipv6 CIDR range to compare
|
|
274
|
+
* @returns true if two ranges overlap, false otherwise
|
|
275
|
+
*/
|
|
276
|
+
rangesOverlap(range1, range2) {
|
|
277
|
+
const [start1, end1] = this.getIPv6Range(range1);
|
|
278
|
+
const [start2, end2] = this.getIPv6Range(range2);
|
|
279
|
+
return (start1 <= end2) && (start2 <= end1);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
*
|
|
283
|
+
* @param cidr
|
|
284
|
+
* @returns Range in the from of big int number [start, end]
|
|
285
|
+
*/
|
|
286
|
+
getIPv6Range(cidr) {
|
|
287
|
+
const [ipv6Address, prefixLength] = cidr.split('/');
|
|
288
|
+
const ipv6Number = this.ipv6ToNumber(ipv6Address);
|
|
289
|
+
const mask = (BigInt(1) << BigInt(128 - Number(prefixLength))) - BigInt(1);
|
|
290
|
+
const networkPrefix = ipv6Number & ~mask;
|
|
291
|
+
const start = networkPrefix;
|
|
292
|
+
const end = networkPrefix | mask;
|
|
293
|
+
return [start, end];
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* @param ipv6Address
|
|
297
|
+
* @returns Converts given ipv6 address range to big int number
|
|
298
|
+
*/
|
|
299
|
+
ipv6ToNumber(ipv6Address) {
|
|
300
|
+
const blocks = this.parseBigIntParts(ipv6Address);
|
|
301
|
+
let ipv6Number = BigInt(0);
|
|
302
|
+
for (const block of blocks) {
|
|
303
|
+
/* tslint:disable:no-bitwise */
|
|
304
|
+
ipv6Number = (ipv6Number << BigInt(16)) + block;
|
|
305
|
+
}
|
|
306
|
+
return ipv6Number;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
exports.CidrBlockIpv6 = CidrBlockIpv6;
|
|
310
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLHFFQUFxRTs7O0FBSXJFOzs7O0dBSUc7QUFDSCxTQUFnQiw4QkFBOEIsQ0FBQyxNQUFlO0lBQzVELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBRkQsd0VBRUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFFBQVEsQ0FBQyxJQUFZLEVBQUUsQ0FBUztJQUM5QyxPQUFPLEdBQUcsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztBQUNqQyxDQUFDO0FBRkQsNEJBRUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLE9BQWtCO0lBQ2pELE1BQU0sR0FBRyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDOUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM3QixJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4RCxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDMUMsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDekIsQ0FBQztBQVJELDRDQVFDO0FBRUQsU0FBZ0IsT0FBTyxDQUFJLEVBQVM7SUFDbEMsT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFGRCwwQkFFQztBQUVEOztHQUVHO0FBQ0gsTUFBYSxZQUFZO0lBRXZCOzs7Ozs7Ozs7T0FTRztJQUNJLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FB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TSxDQUFDLENBQUMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxhQUFhLEdBQUcsVUFBVSxHQUFHLENBQUMsSUFBSSxDQUFDO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQztRQUM1QixNQUFNLEdBQUcsR0FBRyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBRWpDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7S0FDckI7SUFFRDs7O09BR0c7SUFDSyxZQUFZLENBQUMsV0FBbUI7UUFDdEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2xELElBQUksVUFBVSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixLQUFLLE1BQU0sS0FBSyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQzNCLCtCQUErQjtZQUMvQixVQUFVLEdBQUcsQ0FBQyxVQUFVLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQ2xELENBQUM7UUFDRCxPQUFPLFVBQVUsQ0FBQztLQUNuQjtDQUNGO0FBN0ZELHNDQTZGQyIsInNvdXJjZXNDb250ZW50IjpbIi8qZXNsaW50IG5vLWJpdHdpc2U6IFtcImVycm9yXCIsIHsgXCJhbGxvd1wiOiBbXCJ+XCIsIFwifFwiLCBcIjw8XCIsIFwiJlwiXSB9XSAqL1xuXG5pbXBvcnQgeyBJU3VibmV0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5cbi8qKlxuICogUmV0dXJuIGEgc3VibmV0IG5hbWUgZnJvbSBpdHMgY29uc3RydWN0IElEXG4gKlxuICogQWxsIHN1Ym5ldCBuYW1lcyBsb29rIGxpa2UgTkFNRSA8PiBcIlN1Ym5ldFwiIDw+IElOREVYXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdWJuZXRHcm91cE5hbWVGcm9tQ29uc3RydWN0SWQoc3VibmV0OiBJU3VibmV0KSB7XG4gIHJldHVybiBzdWJuZXQubm9kZS5pZC5yZXBsYWNlKC9TdWJuZXRcXGQrJC8sICcnKTtcbn1cblxuLyoqXG4gKiBNYWtlIHRoZSBzdWJuZXQgY29uc3RydWN0IElEIGZyb20gYSBuYW1lIGFuZCBudW1iZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1Ym5ldElkKG5hbWU6IHN0cmluZywgaTogbnVtYmVyKSB7XG4gIHJldHVybiBgJHtuYW1lfVN1Ym5ldCR7aSArIDF9YDtcbn1cblxuLyoqXG4gKiBSZXR1cm4gdGhlIHVuaW9uIG9mIHRhYmxlIElEcyBmcm9tIGFsbCBzZWxlY3RlZCBzdWJuZXRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGxSb3V0ZVRhYmxlSWRzKHN1Ym5ldHM6IElTdWJuZXRbXSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgcmV0ID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3Qgc3VibmV0IG9mIHN1Ym5ldHMpIHtcbiAgICBpZiAoc3VibmV0LnJvdXRlVGFibGUgJiYgc3VibmV0LnJvdXRlVGFibGUucm91dGVUYWJsZUlkKSB7XG4gICAgICByZXQuYWRkKHN1Ym5ldC5yb3V0ZVRhYmxlLnJvdXRlVGFibGVJZCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBBcnJheS5mcm9tKHJldCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmbGF0dGVuPEE+KHhzOiBBW11bXSk6IEFbXSB7XG4gIHJldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KFtdLCB4cyk7XG59XG5cbi8qKlxuICogTmV0d29ya1V0aWxzIGNvbnRhaW5zIGhlbHBlcnMgdG8gd29yayB3aXRoIG5ldHdvcmsgY29uc3RydWN0cyAoc3VibmV0cy9yYW5nZXMpXG4gKi9cbmV4cG9ydCBjbGFzcyBOZXR3b3JrVXRpbHMge1xuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgYW4gSVB2NCBhZGRyZXNzIHN0cmluZy5cbiAgICpcbiAgICogQHBhcmFtIGlwQWRkcmVzcyBUaGUgSVB2NCBhZGRyZXNzIHN0cmluZyB0byBiZSB2YWxpZGF0ZWQuXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHN0cmluZyBpcyBhIHZhbGlkIElQdjQgYWRkcmVzcywgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgKiBWYWxpZGF0ZXMgYW4gSVB2NCBzdHJpbmdcbiAgICpcbiAgICogcmV0dXJucyB0cnVlIG9mIHRoZSBzdHJpbmcgY29udGFpbnMgNCBudW1iZXJzIGJldHdlZW4gMC0yNTUgZGVsaW1pdGVkIGJ5XG4gICAqIGEgYC5gIGNoYXJhY3RlclxuICAgKi9cbiAgcHVibGljIHN0YXRpYyB2YWxpZElwKGlwQWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb2N0ZXRzID0gaXBBZGRyZXNzLnNwbGl0KCcuJyk7XG4gICAgaWYgKG9jdGV0cy5sZW5ndGggIT09IDQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG9jdGV0cy5tYXAoKG9jdGV0OiBzdHJpbmcpID0+IHBhcnNlSW50KG9jdGV0LCAxMCkpLlxuICAgICAgZXZlcnkoKG9jdGV0OiBudW1iZXIpID0+IG9jdGV0ID49IDAgJiYgb2N0ZXQgPD0gMjU1KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhbiBJUHY0IGFkZHJlc3MgdG8gaXRzIGNvcnJlc3BvbmRpbmcgbnVtZXJpY2FsIHZhbHVlLlxuICAgKlxuICAgKiBVc2VzIHRoZSBmb3JtdWxhOlxuICAgKiAoZmlyc3Qgb2N0ZXQgKiAyNTbCsykgKyAoc2Vjb25kIG9jdGV0ICogMjU2wrIpICsgKHRoaXJkIG9jdGV0ICogMjU2KSArXG4gICAqIChmb3VydGggb2N0ZXQpXG4gICAqXG4gICAqIEBwYXJhbSAgaXBBZGRyZXNzIHRoZSBJUCBhZGRyZXNzIChlLmcuIDE3NC42Ni4xNzMuMTY4KVxuICAgKiBAcmV0dXJucyB0aGUgaW50ZWdlciB2YWx1ZSBvZiB0aGUgSVAgYWRkcmVzcyAoZS5nIDI5MjM2MDU0MTYpXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGlwVG9OdW0oaXBBZGRyZXNzOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGlmICghdGhpcy52YWxpZElwKGlwQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtpcEFkZHJlc3N9IGlzIG5vdCB2YWxpZGApO1xuICAgIH1cblxuICAgIHJldHVybiBpcEFkZHJlc3NcbiAgICAgIC5zcGxpdCgnLicpXG4gICAgICAucmVkdWNlKFxuICAgICAgICAocDogbnVtYmVyLCBjOiBzdHJpbmcsIGk6IG51bWJlcikgPT4gcCArIHBhcnNlSW50KGMsIDEwKSAqIDI1NiAqKiAoMyAtIGkpLFxuICAgICAgICAwLFxuICAgICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUYWtlcyBudW1iZXIgYW5kIGNvbnZlcnRzIGl0IHRvIElQdjQgYWRkcmVzcyBzdHJpbmdcbiAgICpcbiAgICogVGFrZXMgYSBudW1iZXIgKGUuZyAyOTIzNjA1NDE2KSBhbmQgY29udmVydHMgaXQgdG8gYW4gSVB2NCBhZGRyZXNzIHN0cmluZ1xuICAgKiBjdXJyZW50bHkgb25seSBzdXBwb3J0cyBJUHY0XG4gICAqXG4gICAqIEBwYXJhbSBpcE51bSBpbnRlZ2VyIHZhbHVlIG9mIHRoZSBJUCBhZGRyZXNzIChlLmcgMjkyMzYwNTQxNilcbiAgICogQHJldHVybnMgSVB2NCBhZGRyZXNzIChlLmcuIDE3NC42Ni4xNzMuMTY4KVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBudW1Ub0lwKGlwTnVtOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIC8vIHRoaXMgYWxsIGJlY2F1c2UgYml0d2lzZSBtYXRoIGlzIHNpZ25lZFxuICAgIGxldCByZW1haW5pbmcgPSBpcE51bTtcbiAgICBjb25zdCBhZGRyZXNzID0gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgICAgaWYgKHJlbWFpbmluZyAhPT0gMCkge1xuICAgICAgICBhZGRyZXNzLnB1c2goTWF0aC5mbG9vcihyZW1haW5pbmcgLyAyNTYgKiogKDMgLSBpKSkpO1xuICAgICAgICByZW1haW5pbmcgPSByZW1haW5pbmcgJSAyNTYgKiogKDMgLSBpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFkZHJlc3MucHVzaCgwKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgaXBBZGRyZXNzOiBzdHJpbmcgPSBhZGRyZXNzLmpvaW4oJy4nKTtcbiAgICBpZiAoICF0aGlzLnZhbGlkSXAoaXBBZGRyZXNzKSApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgJHtpcEFkZHJlc3N9IGlzIG5vdCBhIHZhbGlkIElQIEFkZHJlc3NgKTtcbiAgICB9XG4gICAgcmV0dXJuIGlwQWRkcmVzcztcbiAgfVxufVxuXG4vKipcbiAqIEV4cG9ydGVkIGNsYXNzIGZyb20gVlBDIHRvIHN1cHBvcnQgc3VibmV0IGZpbHRlcmluZ1xuICogYW5kIENJRFIgdmFsaWRhdGlvblxuICovXG5leHBvcnQgY2xhc3MgQ2lkckJsb2NrIHtcblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgbmV0bWFzayBmb3IgYSBnaXZlbiBDSURSIG1hc2tcbiAgICpcbiAgICogVGhlIG5ldG1hc2sgaXMgYSAzMi1iaXQgYmluYXJ5IHZhbHVlIHVzZWQgdG8gc2VwYXJhdGUgdGhlIG5ldHdvcmsgcG9ydGlvbiBmcm9tIHRoZSBob3N0IHBvcnRpb24gb2YgYW4gSVB2NCBhZGRyZXNzLlxuICAgKiBJdCBpcyBjYWxjdWxhdGVkIGJhc2VkIG9uIHRoZSBDSURSIHByZWZpeCBsZW5ndGggKHRoZSBudW1iZXIgb2YgYml0cyB1c2VkIHRvIHJlcHJlc2VudCB0aGUgbmV0d29yayBwb3J0aW9uKS5cbiAgICpcbiAgICogRm9yIGV4YW1wbGU6XG4gICAqIENpZHJCbG9jay5jYWxjdWxhdGVOZXRtYXNrKDI0KSByZXR1cm5zICcyNTUuMjU1LjI1NS4wJ1xuICAgKlxuICAgKiBAcGFyYW0gbWFzayBUaGUgQ0lEUiBwcmVmaXggbGVuZ3RoIChiZXR3ZWVuIDAgYW5kIDMyKSBmb3Igd2hpY2ggdG8gY2FsY3VsYXRlIHRoZSBuZXRtYXNrLlxuICAgIC8vIENhbGN1bGF0ZSB0aGUgbmV0bWFzayBieSBwZXJmb3JtaW5nIGEgYml0d2lzZSBOT1Qgb24gdGhlIHJlc3VsdCBvZiAoMl4zMiAtIDJeKDMyIC0gbWFzaykpXG4gICAqIEByZXR1cm5zIFRoZSBuZXRtYXNrIHN0cmluZyBpbiBJUHY0IGFkZHJlc3MgZm9ybWF0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjYWxjdWxhdGVOZXRtYXNrKG1hc2s6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIE5ldHdvcmtVdGlscy5udW1Ub0lwKDIgKiogMzIgLSAyICoqICgzMiAtIG1hc2spKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIHRoZSBudW1iZXIgSVAgYWRkcmVzc2VzIGluIGEgQ0lEUiBNYXNrXG4gICAqXG4gICAqIEZvciBleGFtcGxlOlxuICAgKiBDaWRyQmxvY2suY2FsY3VsYXRlTmV0c2l6ZSgxNikgcmV0dXJucyA2NTUzNlxuICAgKlxuICAgKiBAcGFyYW0gbWFzayBUaGUgQ0lEUiBwcmVmaXggbGVuZ3RoIChiZXR3ZWVuIDAgYW5kIDMyKSBmb3Igd2hpY2ggdG8gY2FsY3VsYXRlIHRoZSBuZXR3b3JrIHNpemUuXG4gICAqIENpZHJCbG9jay5jYWxjdWxhdGVOZXRzaXplKDI0KSByZXR1cm5zIDI1NlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjYWxjdWxhdGVOZXRzaXplKG1hc2s6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIDIgKiogKDMyIC0gbWFzayk7XG4gIH1cblxuICAvKipcbiAgICogSVAgYWRkcmVzcyBpbiB0aGUgQ0lEUiBibG9jay5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjaWRyOiBzdHJpbmc7XG5cbiAgLypcbiAgICogVGhlIENJRFIgbWFzayBlLmcuIGZvciBDSURSICcxMC4wLjAuMC8yMScgcmV0dXJucyAyMVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG1hc2s6IG51bWJlcjtcblxuICAvKlxuICAgKiBUaGUgdG90YWwgbnVtYmVyIG9mIElQIGFkZHJlc3NlcyBpbiB0aGUgQ0lEUlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5ldHdvcmtTaXplOiBudW1iZXI7XG5cbiAgLypcbiAgICogVGhlIG5ldHdvcmsgYWRkcmVzcyBwcm92aWRlZCBpbiBDSURSIGNyZWF0aW9uIG9mZnNldCBieSB0aGUgTmV0c2l6ZSAtMVxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBuZXR3b3JrQWRkcmVzczogbnVtYmVyO1xuXG4gIC8qXG4gICAqIFBhcnNlcyBlaXRoZXIgQ0lEUiBub3RhdGlvbiBTdHJpbmcgb3IgdHdvIG51bWJlcnMgcmVwcmVzZW50aW5nIHRoZSBJUFxuICAgKiBzcGFjZVxuICAgKlxuICAgKiBjaWRyIGV4cGVjdHMgYSBzdHJpbmcgJzEwLjAuMC4wLzE2J1xuICAgKiBpcEFkZHJlc3MgZXhwZWN0cyBhIG51bWJlclxuICAgKiBtYXNrIGV4cGVjdHMgYSBudW1iZXJcbiAgICpcbiAgICogSWYgdGhlIGdpdmVuIGBjaWRyYCBvciBgaXBBZGRyZXNzYCBpcyBub3QgdGhlIGJlZ2lubmluZyBvZiB0aGUgYmxvY2ssXG4gICAqIHRoZW4gdGhlIG5leHQgYXZhaWxhYmxlIGJsb2NrIHdpbGwgYmUgcmV0dXJuZWQuIEZvciBleGFtcGxlLCBpZlxuICAgKiBgMTAuMC4zLjEvMjhgIGlzIGdpdmVuIHRoZSByZXR1cm5lZCBibG9jayB3aWxsIHJlcHJlc2VudCBgMTAuMC4zLjE2LzI4YC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGNpZHI6IHN0cmluZylcbiAgY29uc3RydWN0b3IoaXBBZGRyZXNzOiBudW1iZXIsIG1hc2s6IG51bWJlcilcbiAgY29uc3RydWN0b3IoaXBBZGRyZXNzT3JDaWRyOiBzdHJpbmcgfCBudW1iZXIsIG1hc2s/OiBudW1iZXIpIHtcbiAgICBpZiAodHlwZW9mIGlwQWRkcmVzc09yQ2lkciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMubWFzayA9IHBhcnNlSW50KGlwQWRkcmVzc09yQ2lkci5zcGxpdCgnLycpWzFdLCAxMCk7XG4gICAgICB0aGlzLm5ldHdvcmtBZGRyZXNzID0gTmV0d29ya1V0aWxzLmlwVG9OdW0oaXBBZGRyZXNzT3JDaWRyLnNwbGl0KCcvJylbMF0pICtcbiAgICAgICAgQ2lkckJsb2NrLmNhbGN1bGF0ZU5ldHNpemUodGhpcy5tYXNrKSAtIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2YgbWFzayA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgdGhpcy5tYXNrID0gbWFzaztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoaXMgc2hvdWxkIGJlIGltcG9zc2libGVcbiAgICAgICAgdGhpcy5tYXNrID0gMTY7XG4gICAgICB9XG4gICAgICB0aGlzLm5ldHdvcmtBZGRyZXNzID0gaXBBZGRyZXNzT3JDaWRyICsgQ2lkckJsb2NrLmNhbGN1bGF0ZU5ldHNpemUodGhpcy5tYXNrKSAtIDE7XG4gICAgICB0aGlzLm5ldHdvcmtTaXplID0gMiAqKiAoMzIgLSB0aGlzLm1hc2spO1xuICAgIH1cbiAgICB0aGlzLm5ldHdvcmtTaXplID0gMiAqKiAoMzIgLSB0aGlzLm1hc2spO1xuICAgIHRoaXMuY2lkciA9IGAke3RoaXMubWluSXAoKX0vJHt0aGlzLm1hc2t9YDtcbiAgfVxuXG4gIC8qXG4gICAqIFRoZSBtYXhpbXVtIElQIGluIHRoZSBDSURSIEJsb2NrIGUuZy4gJzEwLjAuOC4yNTUnXG4gICAqL1xuICBwdWJsaWMgbWF4SXAoKTogc3RyaW5nIHtcbiAgICAvLyBtaW4gKyAoMl4oMzItbWFzaykpIC0gMSBbemVybyBuZWVkcyB0byBjb3VudF1cbiAgICByZXR1cm4gTmV0d29ya1V0aWxzLm51bVRvSXAodGhpcy5tYXhBZGRyZXNzKCkpO1xuICB9XG5cbiAgLypcbiAgICogQ2hlY2tzIGlmIHRoaXMgQ0lEUiBibG9jayBmdWxseSBjb250YWlucyB0aGUgcHJvdmlkZWQgQ0lEUiBibG9jay5cbiAgICpcbiAgICogQHBhcmFtIG90aGVyIFRoZSBDSURSIGJsb2NrIHRvIGNoZWNrIGZvciBjb250YWlubWVudC5cbiAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGlzIENJRFIgYmxvY2sgZnVsbHkgY29udGFpbnMgdGhlIHByb3ZpZGVkIENJRFIgYmxvY2ssIGZhbHNlIG90aGVyd2lzZS5cbiAgICpcbiAgICogVGhlIG1pbmltdW0gSVAgaW4gdGhlIENJRFIgQmxvY2sgZS5nLiAnMTAuMC4wLjAnXG4gICAqL1xuICBwdWJsaWMgbWluSXAoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gTmV0d29ya1V0aWxzLm51bVRvSXAodGhpcy5taW5BZGRyZXNzKCkpO1xuICB9XG5cbiAgLypcbiAgICogUmV0dXJucyB0aGUgbnVtYmVyIHJlcHJlc2VudGF0aW9uIGZvciB0aGUgbWluaW11bSBJUHY0IGFkZHJlc3NcbiAgICovXG4gIHB1YmxpYyBtaW5BZGRyZXNzKCk6IG51bWJlciB7XG4gICAgY29uc3QgZGl2ID0gdGhpcy5uZXR3b3JrQWRkcmVzcyAlIHRoaXMubmV0d29ya1NpemU7XG4gICAgcmV0dXJuIHRoaXMubmV0d29ya0FkZHJlc3MgLSBkaXY7XG4gIH1cblxuICAvKlxuICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgcmVwcmVzZW50YXRpb24gZm9yIHRoZSBtYXhpbXVtIElQdjQgYWRkcmVzc1xuICAgKi9cbiAgcHVibGljIG1heEFkZHJlc3MoKTogbnVtYmVyIHtcbiAgICAvKipcbiAgICAgKiBUaGUgbWF4aW11bSBJUCBhZGRyZXNzIGluIHRoZSBDSURSIGJsb2NrIGlzIGNhbGN1bGF0ZWQgYXMgdGhlIG1pbmltdW0gYWRkcmVzcyArICgyXigzMi1tYXNrKSkgLSAxLlxuICAgICAqIFRoaXMgaXMgYmVjYXVzZSB0aGUgbWluaW11bSBhZGRyZXNzIHJlcHJlc2VudHMgdGhlIG5ldHdvcmsgYWRkcmVzcywgYW5kIHRoZSBtYXhpbXVtIGFkZHJlc3MgaXMgdGhlIGJyb2FkY2FzdCBhZGRyZXNzLlxuICAgICAqL1xuICAgIC8vIG1pbiArICgyXigzMi1tYXNrKSkgLSAxIFt6ZXJvIG5lZWRzIHRvIGNvdW50XVxuICAgIHJldHVybiB0aGlzLm1pbkFkZHJlc3MoKSArIHRoaXMubmV0d29ya1NpemUgLSAxO1xuICB9XG5cbiAgLypcbiAgICogUmV0dXJucyB0aGUgbmV4dCBjb25zZWN1dGl2ZSBDSURSIGJsb2NrIG9mIHRoZSBzYW1lIG1hc2sgc2l6ZSBmb2xsb3dpbmcgdGhpcyBDSURSIGJsb2NrLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgaWYgdGhpcyBDSURSIGJsb2NrIGlzICcxMC4wLjAuMC8yNCcsIHRoZSBuZXh0IGJsb2NrIHdvdWxkIGJlICcxMC4wLjEuMC8yNCcuXG4gICAqXG4gICAqIFJldHVybnMgdGhlIG5leHQgQ0lEUiBCbG9jayBvZiB0aGUgc2FtZSBtYXNrIHNpemVcbiAgICovXG4gIHB1YmxpYyBuZXh0QmxvY2soKTogQ2lkckJsb2NrIHtcbiAgICByZXR1cm4gbmV3IENpZHJCbG9jayh0aGlzLm1heEFkZHJlc3MoKSArIDEsIHRoaXMubWFzayk7XG4gIH1cblxuICAvKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBDaWRyQmxvY2sgZnVsbHkgY29udGFpbnMgdGhlIHByb3ZpZGVkIENpZHJCbG9ja1xuICAgKi9cbiAgcHVibGljIGNvbnRhaW5zQ2lkcihvdGhlcjogQ2lkckJsb2NrKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh0aGlzLm1heEFkZHJlc3MoKSA+PSBvdGhlci5tYXhBZGRyZXNzKCkpICYmXG4gICAgICAodGhpcy5taW5BZGRyZXNzKCkgPD0gb3RoZXIubWluQWRkcmVzcygpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdHdvIElQIGFkZHJlc3MgcmFuZ2VzIG92ZXJsYXAuXG4gICAqXG4gICAqIEBwYXJhbSByYW5nZTEgVGhlIGZpcnN0IElQIGFkZHJlc3MgcmFuZ2UgcmVwcmVzZW50ZWQgYXMgYW4gYXJyYXkgW3N0YXJ0LCBlbmRdLlxuICAgKiBAcGFyYW0gcmFuZ2UyIFRoZSBzZWNvbmQgSVAgYWRkcmVzcyByYW5nZSByZXByZXNlbnRlZCBhcyBhbiBhcnJheSBbc3RhcnQsIGVuZF0uXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHR3byBJUCBhZGRyZXNzIHJhbmdlcyBvdmVybGFwLCBmYWxzZSBvdGhlcndpc2UuXG4gICAqXG4gICAqIE5vdGU6IFRoaXMgbWV0aG9kIGFzc3VtZXMgdGhhdCB0aGUgc3RhcnQgYW5kIGVuZCBhZGRyZXNzZXMgYXJlIHZhbGlkIElQdjQgYWRkcmVzc2VzLlxuICAgKi9cbiAgcHVibGljIHJhbmdlc092ZXJsYXAocmFuZ2UxOiBbc3RyaW5nLCBzdHJpbmddLCByYW5nZTI6IFtzdHJpbmcsIHN0cmluZ10pOiBib29sZWFuIHtcbiAgICBjb25zdCBbc3RhcnQxLCBlbmQxXSA9IHJhbmdlMTtcbiAgICBjb25zdCBbc3RhcnQyLCBlbmQyXSA9IHJhbmdlMjtcblxuICAgIC8vIENoZWNrIGlmIHJhbmdlcyBvdmVybGFwXG4gICAgcmV0dXJuIHN0YXJ0MSA8PSBlbmQyICYmIHN0YXJ0MiA8PSBlbmQxO1xuICB9XG5cbn1cblxuLyoqXG4gKiBDbGFzcyB3aXRoIGhlbHBlciBmdW5jdGlvbnMgdG8gc3VwcG9ydFxuICogU3VibmV0IElwdjYgQWRkcmVzcyBWYWxpZGF0aW9uXG4gKlxuICogVGhpcyBjbGFzcyBwcm92aWRlcyBtZXRob2RzIGZvciB3b3JraW5nIHdpdGggSVB2NiBDSURSIGJsb2NrcywgaW5jbHVkaW5nIGNhbGN1bGF0aW5nIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtXG4gKiBJUCBhZGRyZXNzZXMgaW4gYSBDSURSIGJsb2NrLCBhbmQgY2hlY2tpbmcgaWYgdHdvIENJRFIgYmxvY2tzIG92ZXJsYXAuXG4gKi9cbmV4cG9ydCBjbGFzcyBDaWRyQmxvY2tJcHY2IHtcblxuICAvKipcbiAgICogSXB2NiBDSURSIHJhbmdlXG4gICAqL1xuICBwdWJsaWMgY2lkcjogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIENJRFIgcHJlZml4IGxlbmd0aCAobnVtYmVyIG9mIGJpdHMgdXNlZCBmb3IgdGhlIG5ldHdvcmsgcG9ydGlvbiBvZiB0aGUgYWRkcmVzcykuXG4gICAqL1xuICBwdWJsaWMgY2lkclByZWZpeDogbnVtYmVyO1xuICBwcml2YXRlIGlwUGFydHM6IGJpZ2ludFtdO1xuICBwcml2YXRlIG5ldHdvcmtCaXRzOiBudW1iZXI7XG4gIHByaXZhdGUgbmV0d29ya1BhcnQ6IGJpZ2ludFtdO1xuXG4gIGNvbnN0cnVjdG9yKGNpZHI6IHN0cmluZykge1xuICAgIHRoaXMuY2lkciA9IGNpZHI7XG4gICAgY29uc3QgW2lwQWRkcmVzcywgcHJlZml4XSA9IGNpZHIuc3BsaXQoJy8nKTtcbiAgICB0aGlzLmNpZHJQcmVmaXggPSBwYXJzZUludChwcmVmaXgsIDEwKTtcbiAgICB0aGlzLmlwUGFydHMgPSB0aGlzLnBhcnNlQmlnSW50UGFydHMoaXBBZGRyZXNzKTtcbiAgICB0aGlzLm5ldHdvcmtCaXRzID0gdGhpcy5jaWRyUHJlZml4O1xuICAgIHRoaXMubmV0d29ya1BhcnQgPSB0aGlzLmlwUGFydHMuc2xpY2UoMCwgTWF0aC5jZWlsKHRoaXMubmV0d29ya0JpdHMgLyAxNikpO1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUJpZ0ludFBhcnRzKGlwQWRkcmVzczogc3RyaW5nKTogYmlnaW50W10ge1xuICAgIHJldHVybiBpcEFkZHJlc3Muc3BsaXQoJzonKS5tYXAoKHBhcnQpID0+IEJpZ0ludChgMHgke3BhcnQucGFkU3RhcnQoNCwgJzAnKX1gIHx8ICcwJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIE1pbmltdW0gSVB2NiBhZGRyZXNzIGZvciBhIHByb3ZpZGVkIENJRFJcbiAgICovXG4gIHB1YmxpYyBtaW5JcCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IHN0YXJ0SVAgPSBbLi4udGhpcy5uZXR3b3JrUGFydF07XG4gICAgZm9yIChsZXQgaSA9IHRoaXMubmV0d29ya1BhcnQubGVuZ3RoOyBpIDwgODsgaSsrKSB7XG4gICAgICBzdGFydElQLnB1c2goQmlnSW50KDApKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0YXJ0SVAubWFwKHRoaXMuZm9ybWF0SVB2NlBhcnQpLmpvaW4oJzonKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyBNYXhpbXVtIElQdjYgYWRkcmVzcyBmb3IgYSBwcm92aWRlZCBDSURSXG4gICAqL1xuICBwdWJsaWMgbWF4SXAoKTogc3RyaW5nIHtcbiAgICBjb25zdCBlbmRJUCA9IFsuLi50aGlzLm5ldHdvcmtQYXJ0XTtcbiAgICBjb25zdCBob3N0UGFydCA9IEFycmF5KDggLSB0aGlzLm5ldHdvcmtQYXJ0Lmxlbmd0aCkuZmlsbChCaWdJbnQoMHhmZmZmKSk7XG4gICAgZW5kSVAucHVzaCguLi5ob3N0UGFydCk7XG5cbiAgICByZXR1cm4gZW5kSVAubWFwKHRoaXMuZm9ybWF0SVB2NlBhcnQpLmpvaW4oJzonKTtcbiAgfVxuXG4gIHByaXZhdGUgZm9ybWF0SVB2NlBhcnQgPSAocGFydDogYmlnaW50KSA9PiBwYXJ0LnRvU3RyaW5nKDE2KS5wYWRTdGFydCg0LCAnMCcpO1xuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gcmFuZ2UxIElwdjYgQ0lEUiByYW5nZSB0byBjb21wYXJlXG4gICAqIEBwYXJhbSByYW5nZTIgSXB2NiBDSURSIHJhbmdlIHRvIGNvbXBhcmVcbiAgICogQHJldHVybnMgdHJ1ZSBpZiB0d28gcmFuZ2VzIG92ZXJsYXAsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgcHVibGljIHJhbmdlc092ZXJsYXAocmFuZ2UxOiBzdHJpbmcsIHJhbmdlMjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3QgW3N0YXJ0MSwgZW5kMV0gPSB0aGlzLmdldElQdjZSYW5nZShyYW5nZTEpO1xuICAgIGNvbnN0IFtzdGFydDIsIGVuZDJdID0gdGhpcy5nZXRJUHY2UmFuZ2UocmFuZ2UyKTtcblxuICAgIHJldHVybiAoc3RhcnQxIDw9IGVuZDIpICYmIChzdGFydDIgPD0gZW5kMSk7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIGNpZHJcbiAgICogQHJldHVybnMgUmFuZ2UgaW4gdGhlIGZyb20gb2YgYmlnIGludCBudW1iZXIgW3N0YXJ0LCBlbmRdXG4gICAqL1xuICBwcml2YXRlIGdldElQdjZSYW5nZShjaWRyOiBzdHJpbmcpOiBbYmlnaW50LCBiaWdpbnRdIHtcbiAgICBjb25zdCBbaXB2NkFkZHJlc3MsIHByZWZpeExlbmd0aF0gPSBjaWRyLnNwbGl0KCcvJyk7XG4gICAgY29uc3QgaXB2Nk51bWJlciA9IHRoaXMuaXB2NlRvTnVtYmVyKGlwdjZBZGRyZXNzKTtcbiAgICBjb25zdCBtYXNrID0gKEJpZ0ludCgxKSA8PCBCaWdJbnQoMTI4IC0gTnVtYmVyKHByZWZpeExlbmd0aCkpKSAtIEJpZ0ludCgxKTtcbiAgICBjb25zdCBuZXR3b3JrUHJlZml4ID0gaXB2Nk51bWJlciAmIH5tYXNrO1xuICAgIGNvbnN0IHN0YXJ0ID0gbmV0d29ya1ByZWZpeDtcbiAgICBjb25zdCBlbmQgPSBuZXR3b3JrUHJlZml4IHwgbWFzaztcblxuICAgIHJldHVybiBbc3RhcnQsIGVuZF07XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIGlwdjZBZGRyZXNzXG4gICAqIEByZXR1cm5zIENvbnZlcnRzIGdpdmVuIGlwdjYgYWRkcmVzcyByYW5nZSB0byBiaWcgaW50IG51bWJlclxuICAgKi9cbiAgcHJpdmF0ZSBpcHY2VG9OdW1iZXIoaXB2NkFkZHJlc3M6IHN0cmluZyk6IGJpZ2ludCB7XG4gICAgY29uc3QgYmxvY2tzID0gdGhpcy5wYXJzZUJpZ0ludFBhcnRzKGlwdjZBZGRyZXNzKTtcbiAgICBsZXQgaXB2Nk51bWJlciA9IEJpZ0ludCgwKTtcbiAgICBmb3IgKGNvbnN0IGJsb2NrIG9mIGJsb2Nrcykge1xuICAgICAgLyogdHNsaW50OmRpc2FibGU6bm8tYml0d2lzZSAqL1xuICAgICAgaXB2Nk51bWJlciA9IChpcHY2TnVtYmVyIDw8IEJpZ0ludCgxNikpICsgYmxvY2s7XG4gICAgfVxuICAgIHJldHVybiBpcHY2TnVtYmVyO1xuICB9XG59XG5cbiJdfQ==
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Resource } from 'aws-cdk-lib';
|
|
2
|
+
import { IVpc, ISubnet, SubnetSelection, SelectedSubnets, EnableVpnGatewayOptions, VpnConnectionOptions, VpnConnection, ClientVpnEndpointOptions, ClientVpnEndpoint, InterfaceVpcEndpointOptions, InterfaceVpcEndpoint, GatewayVpcEndpointOptions, GatewayVpcEndpoint, FlowLogOptions, FlowLog, CfnVPCCidrBlock } from 'aws-cdk-lib/aws-ec2';
|
|
3
|
+
import { IDependable } from 'constructs';
|
|
4
|
+
/**
|
|
5
|
+
* Placeholder to see what extra props we might need,
|
|
6
|
+
* will be added to original IVPC
|
|
7
|
+
*/
|
|
8
|
+
export interface IVpcV2 extends IVpc {
|
|
9
|
+
/**
|
|
10
|
+
* The secondary CIDR blocks associated with the VPC.
|
|
11
|
+
*
|
|
12
|
+
* For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-resize}.
|
|
13
|
+
*/
|
|
14
|
+
readonly secondaryCidrBlock: CfnVPCCidrBlock[];
|
|
15
|
+
/**
|
|
16
|
+
* The primary IPv4 CIDR block associated with the VPC.
|
|
17
|
+
* Needed in order to validate the vpc range of subnet
|
|
18
|
+
* current prop vpcCidrBlock refers to the token value
|
|
19
|
+
* For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-sizing-ipv4}.
|
|
20
|
+
*/
|
|
21
|
+
readonly ipv4CidrBlock: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Base class for creating a VPC (Virtual Private Cloud) in AWS.
|
|
25
|
+
*
|
|
26
|
+
* For more information, see the {@link https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html|AWS CDK Documentation on VPCs}.
|
|
27
|
+
*/
|
|
28
|
+
export declare abstract class VpcV2Base extends Resource implements IVpcV2 {
|
|
29
|
+
/**
|
|
30
|
+
* Identifier for this VPC
|
|
31
|
+
*/
|
|
32
|
+
abstract readonly vpcId: string;
|
|
33
|
+
/**
|
|
34
|
+
* Arn of this VPC
|
|
35
|
+
*/
|
|
36
|
+
abstract readonly vpcArn: string;
|
|
37
|
+
/**
|
|
38
|
+
* CIDR range for this VPC
|
|
39
|
+
*/
|
|
40
|
+
abstract readonly vpcCidrBlock: string;
|
|
41
|
+
/**
|
|
42
|
+
* List of public subnets in this VPC
|
|
43
|
+
*/
|
|
44
|
+
readonly publicSubnets: ISubnet[];
|
|
45
|
+
/**
|
|
46
|
+
* List of private subnets in this VPC
|
|
47
|
+
*/
|
|
48
|
+
readonly privateSubnets: ISubnet[];
|
|
49
|
+
/**
|
|
50
|
+
* List of isolated subnets in this VPC
|
|
51
|
+
*/
|
|
52
|
+
abstract readonly isolatedSubnets: ISubnet[];
|
|
53
|
+
/**
|
|
54
|
+
* AZs for this VPC
|
|
55
|
+
*/
|
|
56
|
+
readonly availabilityZones: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Dependable that can be depended upon to force internet connectivity established on the VPC
|
|
59
|
+
*/
|
|
60
|
+
abstract readonly internetConnectivityEstablished: IDependable;
|
|
61
|
+
/**
|
|
62
|
+
* Secondary IPs for the VPC, can be multiple Ipv4 or Ipv6
|
|
63
|
+
* Ipv4 should be within RFC#1918 range
|
|
64
|
+
*/
|
|
65
|
+
abstract readonly secondaryCidrBlock: CfnVPCCidrBlock[];
|
|
66
|
+
/**
|
|
67
|
+
* The primary IPv4 CIDR block associated with the VPC.
|
|
68
|
+
* Needed in order to validate the vpc range of subnet
|
|
69
|
+
* current prop vpcCidrBlock refers to the token value
|
|
70
|
+
* For more information, see the {@link https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html#vpc-sizing-ipv4}.
|
|
71
|
+
*/
|
|
72
|
+
abstract readonly ipv4CidrBlock: string;
|
|
73
|
+
/**
|
|
74
|
+
* If this is set to true, don't error out on trying to select subnets
|
|
75
|
+
*/
|
|
76
|
+
protected incompleteSubnetDefinition: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Mutable private field for the vpnGatewayId
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
protected _vpnGatewayId?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Return information on the subnets appropriate for the given selection strategy
|
|
85
|
+
*
|
|
86
|
+
* Requires that at least one subnet is matched, throws a descriptive
|
|
87
|
+
* error message otherwise.
|
|
88
|
+
*/
|
|
89
|
+
selectSubnets(selection?: SubnetSelection): SelectedSubnets;
|
|
90
|
+
/**
|
|
91
|
+
* Adds a VPN Gateway to this VPC
|
|
92
|
+
*/
|
|
93
|
+
enableVpnGateway(options: EnableVpnGatewayOptions): void;
|
|
94
|
+
/**
|
|
95
|
+
* Adds a new VPN connection to this VPC
|
|
96
|
+
*/
|
|
97
|
+
addVpnConnection(id: string, options: VpnConnectionOptions): VpnConnection;
|
|
98
|
+
/**
|
|
99
|
+
* Adds a new client VPN endpoint to this VPC
|
|
100
|
+
*/
|
|
101
|
+
addClientVpnEndpoint(id: string, options: ClientVpnEndpointOptions): ClientVpnEndpoint;
|
|
102
|
+
/**
|
|
103
|
+
* Adds a new interface endpoint to this VPC
|
|
104
|
+
*/
|
|
105
|
+
addInterfaceEndpoint(id: string, options: InterfaceVpcEndpointOptions): InterfaceVpcEndpoint;
|
|
106
|
+
/**
|
|
107
|
+
* Adds a new gateway endpoint to this VPC
|
|
108
|
+
*/
|
|
109
|
+
addGatewayEndpoint(id: string, options: GatewayVpcEndpointOptions): GatewayVpcEndpoint;
|
|
110
|
+
/**
|
|
111
|
+
* Adds a new flow log to this VPC
|
|
112
|
+
*/
|
|
113
|
+
addFlowLog(id: string, options?: FlowLogOptions): FlowLog;
|
|
114
|
+
/**
|
|
115
|
+
* Returns the id of the VPN Gateway (if enabled)
|
|
116
|
+
*/
|
|
117
|
+
get vpnGatewayId(): string | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* Return the subnets appropriate for the placement strategy
|
|
120
|
+
*/
|
|
121
|
+
protected selectSubnetObjects(selection?: SubnetSelection): ISubnet[];
|
|
122
|
+
private applySubnetFilters;
|
|
123
|
+
private selectSubnetObjectsByName;
|
|
124
|
+
private selectSubnetObjectsByType;
|
|
125
|
+
/**
|
|
126
|
+
* Validate the fields in a SubnetSelection object, and reify defaults if necessary
|
|
127
|
+
*
|
|
128
|
+
* In case of default selection, select the first type of PRIVATE, ISOLATED,
|
|
129
|
+
* PUBLIC (in that order) that has any subnets.
|
|
130
|
+
*/
|
|
131
|
+
private reifySelectionDefaults;
|
|
132
|
+
}
|