@fjall/components-infrastructure 0.77.4 → 0.78.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/lib/app.d.ts +8 -5
  2. package/dist/lib/app.js +19 -7
  3. package/dist/lib/patterns/aws/buildkite.js +4 -7
  4. package/dist/lib/patterns/aws/compute.d.ts +479 -48
  5. package/dist/lib/patterns/aws/compute.js +307 -94
  6. package/dist/lib/patterns/aws/database.d.ts +1 -0
  7. package/dist/lib/patterns/aws/database.js +4 -1
  8. package/dist/lib/patterns/aws/hostedZone.js +4 -7
  9. package/dist/lib/patterns/aws/loadBalancer.d.ts +163 -0
  10. package/dist/lib/patterns/aws/loadBalancer.js +278 -0
  11. package/dist/lib/patterns/aws/network.d.ts +1 -0
  12. package/dist/lib/patterns/aws/network.js +2 -1
  13. package/dist/lib/resources/aws/compute/capacityProviderDrainWaiter.d.ts +20 -0
  14. package/dist/lib/resources/aws/compute/capacityProviderDrainWaiter.js +180 -0
  15. package/dist/lib/resources/aws/compute/ecs.d.ts +294 -57
  16. package/dist/lib/resources/aws/compute/ecs.js +745 -261
  17. package/dist/lib/resources/aws/compute/ecsFreeTier.js +1 -1
  18. package/dist/lib/resources/aws/compute/ecsSpot.js +1 -1
  19. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.d.ts +20 -0
  20. package/dist/lib/resources/aws/compute/utilities/capacityProviderDrainWaiter.js +180 -0
  21. package/dist/lib/resources/aws/database/rdsAurora.d.ts +1 -0
  22. package/dist/lib/resources/aws/database/rdsAurora.js +2 -2
  23. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +1 -0
  24. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +2 -1
  25. package/dist/lib/resources/aws/database/rdsDeletionWaiter.d.ts +33 -0
  26. package/dist/lib/resources/aws/database/rdsDeletionWaiter.js +74 -0
  27. package/dist/lib/resources/aws/database/rdsInstance.d.ts +1 -0
  28. package/dist/lib/resources/aws/database/rdsInstance.js +3 -3
  29. package/dist/lib/resources/aws/networking/vpc.d.ts +1 -0
  30. package/dist/lib/resources/aws/networking/vpc.js +4 -3
  31. package/dist/lib/resources/aws/networking/vpcEndpoint.d.ts +2 -2
  32. package/dist/lib/resources/aws/networking/vpcEndpoint.js +1 -1
  33. package/dist/lib/resources/aws/networking/vpcEndpoints.d.ts +71 -0
  34. package/dist/lib/resources/aws/networking/vpcEndpoints.js +125 -0
  35. package/dist/lib/resources/aws/secrets/kms.d.ts +14 -0
  36. package/dist/lib/resources/aws/secrets/kms.js +5 -2
  37. package/dist/lib/resources/aws/secrets/secret.js +1 -1
  38. package/dist/lib/utils/standardTagsAspect.d.ts +26 -12
  39. package/dist/lib/utils/standardTagsAspect.js +67 -477
  40. package/dist/lib/utils/tagResource.d.ts +18 -3
  41. package/dist/lib/utils/tagResource.js +23 -6
  42. package/package.json +3 -3
  43. package/dist/lib/aspects/resourceInventory.d.ts +0 -41
  44. package/dist/lib/aspects/resourceInventory.js +0 -56
  45. package/dist/lib/config/audit.d.ts +0 -18
  46. package/dist/lib/config/audit.js +0 -22
  47. package/dist/lib/patterns/aws/auditRole.d.ts +0 -44
  48. package/dist/lib/patterns/aws/auditRole.js +0 -58
  49. package/dist/lib/patterns/aws/basicApp.d.ts +0 -0
  50. package/dist/lib/patterns/aws/basicApp.js +0 -150
  51. package/dist/lib/patterns/aws/ec2.d.ts +0 -43
  52. package/dist/lib/patterns/aws/ec2.js +0 -123
  53. package/dist/lib/patterns/aws/freeTierApp.d.ts +0 -44
  54. package/dist/lib/patterns/aws/freeTierApp.js +0 -83
  55. package/dist/lib/patterns/aws/spotInstanceApp.d.ts +0 -45
  56. package/dist/lib/patterns/aws/spotInstanceApp.js +0 -85
  57. package/dist/lib/resources/aws/audit/auditRole.d.ts +0 -32
  58. package/dist/lib/resources/aws/audit/auditRole.js +0 -46
  59. package/dist/lib/resources/aws/database/databaseFreeTier.d.ts +0 -15
  60. package/dist/lib/resources/aws/database/databaseFreeTier.js +0 -29
  61. package/dist/lib/resources/aws/database/rdsFreeTier.d.ts +0 -37
  62. package/dist/lib/resources/aws/database/rdsFreeTier.js +0 -84
  63. package/dist/lib/utils/getCidr.d.ts +0 -8
  64. package/dist/lib/utils/getCidr.js +0 -40
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoadBalancer = exports.LoadBalancerFactory = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const aws_elasticloadbalancingv2_1 = require("aws-cdk-lib/aws-elasticloadbalancingv2");
6
+ const aws_certificatemanager_1 = require("aws-cdk-lib/aws-certificatemanager");
7
+ const aws_route53_1 = require("aws-cdk-lib/aws-route53");
8
+ const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
9
+ const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
10
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
11
+ const cfnOutput_1 = require("../../resources/aws/utilities/cfnOutput");
12
+ const hostedZone_1 = require("./hostedZone");
13
+ /**
14
+ * Validates load balancer props and logs warnings for misconfigured options.
15
+ */
16
+ function validateLoadBalancerProps(props) {
17
+ if (props.healthCheck) {
18
+ if (props.healthCheck.interval !== undefined) {
19
+ if (props.healthCheck.interval < 5 || props.healthCheck.interval > 300) {
20
+ throw new Error("Health check interval must be between 5 and 300 seconds.");
21
+ }
22
+ }
23
+ if (props.healthCheck.timeout !== undefined) {
24
+ if (props.healthCheck.timeout < 2 || props.healthCheck.timeout > 120) {
25
+ throw new Error("Health check timeout must be between 2 and 120 seconds.");
26
+ }
27
+ }
28
+ }
29
+ }
30
+ /**
31
+ * Factory for creating LoadBalancer constructs.
32
+ *
33
+ * @example
34
+ * // Simple HTTP load balancer
35
+ * const alb = app.addCompute(
36
+ * LoadBalancerFactory.build("MainALB", {})
37
+ * );
38
+ *
39
+ * @example
40
+ * // HTTPS load balancer with domain
41
+ * const alb = app.addCompute(
42
+ * LoadBalancerFactory.build("MainALB", {
43
+ * domain: "app.example.com"
44
+ * })
45
+ * );
46
+ *
47
+ * @example
48
+ * // Internal load balancer
49
+ * const alb = app.addCompute(
50
+ * LoadBalancerFactory.build("InternalALB", {
51
+ * public: false
52
+ * })
53
+ * );
54
+ */
55
+ class LoadBalancerFactory {
56
+ static build(id, props) {
57
+ return (app, scope) => {
58
+ validateLoadBalancerProps(props);
59
+ const resolvedProps = {
60
+ ...props,
61
+ vpc: props.vpc || app.getVpc()
62
+ };
63
+ return new LoadBalancer(scope, id, resolvedProps);
64
+ };
65
+ }
66
+ }
67
+ exports.LoadBalancerFactory = LoadBalancerFactory;
68
+ /**
69
+ * Application Load Balancer construct that can be shared across multiple ECS services.
70
+ *
71
+ * Use LoadBalancerFactory.build() to create instances via app.addCompute().
72
+ */
73
+ class LoadBalancer extends constructs_1.Construct {
74
+ constructor(scope, id, props) {
75
+ super(scope, id);
76
+ this.defaultHealthCheck = props.healthCheck || {};
77
+ this.isHttps = !!props.domain;
78
+ // Create security group
79
+ this.securityGroup = new aws_ec2_1.SecurityGroup(this, "SecurityGroup", {
80
+ vpc: props.vpc,
81
+ description: `Security group for ${id} load balancer`,
82
+ allowAllOutbound: true
83
+ });
84
+ // Allow inbound traffic
85
+ const inboundPort = this.isHttps ? 443 : 80;
86
+ this.securityGroup.addIngressRule({ connections: { allowFromAnyIpv4: () => { } } }, aws_ec2_1.Port.tcp(inboundPort), `Allow inbound ${this.isHttps ? "HTTPS" : "HTTP"}`);
87
+ // Create ALB
88
+ const loadBalancerName = this.truncateName(`${id}ALB`, 32);
89
+ this.alb = new aws_elasticloadbalancingv2_1.ApplicationLoadBalancer(this, "ALB", {
90
+ vpc: props.vpc,
91
+ internetFacing: props.public !== false,
92
+ securityGroup: this.securityGroup,
93
+ loadBalancerName,
94
+ vpcSubnets: {
95
+ subnetType: props.public !== false ? aws_ec2_1.SubnetType.PUBLIC : aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS
96
+ }
97
+ });
98
+ // Set up domain if configured
99
+ if (props.domain) {
100
+ const domainConfig = this.normaliseDomainConfig(props.domain);
101
+ this.setupDomain(domainConfig);
102
+ }
103
+ // Create listener
104
+ if (this.isHttps && this.certificate) {
105
+ this.listener = this.alb.addListener("Listener", {
106
+ port: 443,
107
+ protocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTPS,
108
+ certificates: [this.certificate]
109
+ });
110
+ // Add HTTP redirect
111
+ this.alb.addListener("HttpRedirect", {
112
+ port: 80,
113
+ protocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTP,
114
+ defaultAction: {
115
+ redirect: {
116
+ protocol: "HTTPS",
117
+ port: "443",
118
+ permanent: true
119
+ }
120
+ }
121
+ });
122
+ }
123
+ else {
124
+ this.listener = this.alb.addListener("Listener", {
125
+ port: 80,
126
+ protocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTP
127
+ });
128
+ }
129
+ // Add default action (returns 503 if no targets match)
130
+ this.listener.addAction("DefaultAction", {
131
+ action: {
132
+ fixedResponse: {
133
+ statusCode: 503,
134
+ contentType: "text/plain",
135
+ messageBody: "No service available"
136
+ }
137
+ }
138
+ });
139
+ // Set URL
140
+ this.url = this.isHttps
141
+ ? `https://${this.alb.loadBalancerDnsName}`
142
+ : `http://${this.alb.loadBalancerDnsName}`;
143
+ // Set up connections
144
+ this.connections = new aws_ec2_1.Connections({
145
+ securityGroups: [this.securityGroup],
146
+ defaultPort: aws_ec2_1.Port.tcp(inboundPort)
147
+ });
148
+ // Outputs
149
+ new cfnOutput_1.CfnOutput(this, "LoadBalancerDnsName", {
150
+ key: `${id}LoadBalancerDnsName`,
151
+ exportName: `${id}LoadBalancerDnsName`,
152
+ value: this.alb.loadBalancerDnsName
153
+ });
154
+ new cfnOutput_1.CfnOutput(this, "LoadBalancerUrl", {
155
+ key: `${id}LoadBalancerUrl`,
156
+ exportName: `${id}LoadBalancerUrl`,
157
+ value: this.url,
158
+ description: `Load Balancer URL for ${id}`
159
+ });
160
+ new cfnOutput_1.CfnOutput(this, "LoadBalancerArn", {
161
+ key: `${id}LoadBalancerArn`,
162
+ exportName: `${id}LoadBalancerArn`,
163
+ value: this.alb.loadBalancerArn,
164
+ description: `Load Balancer ARN for ${id}`
165
+ });
166
+ }
167
+ /**
168
+ * Register a target group with routing rules.
169
+ * Called internally by EcsCluster when loadBalancer.target is specified.
170
+ *
171
+ * @param targetGroup - The target group to register
172
+ * @param routing - Routing configuration (path, host, priority)
173
+ */
174
+ registerTargetGroup(targetGroup, routing) {
175
+ const conditions = [];
176
+ if (routing.path) {
177
+ const paths = Array.isArray(routing.path) ? routing.path : [routing.path];
178
+ conditions.push(aws_elasticloadbalancingv2_1.ListenerCondition.pathPatterns(paths));
179
+ }
180
+ if (routing.host) {
181
+ const hosts = Array.isArray(routing.host) ? routing.host : [routing.host];
182
+ conditions.push(aws_elasticloadbalancingv2_1.ListenerCondition.hostHeaders(hosts));
183
+ }
184
+ if (conditions.length === 0) {
185
+ throw new Error("At least one routing condition (path or host) must be specified.");
186
+ }
187
+ this.listener.addTargetGroups(`Rule${routing.priority}`, {
188
+ targetGroups: [targetGroup],
189
+ conditions,
190
+ priority: routing.priority
191
+ });
192
+ }
193
+ /**
194
+ * Create a target group for an ECS service.
195
+ * Returns the target group for the service to register with.
196
+ *
197
+ * @param id - Unique identifier for the target group
198
+ * @param port - Container port
199
+ * @param vpc - VPC for the target group
200
+ * @param healthCheckPath - Optional health check path override
201
+ */
202
+ createTargetGroup(id, port, vpc, healthCheckPath) {
203
+ const targetGroup = new aws_elasticloadbalancingv2_1.ApplicationTargetGroup(this, `${id}TargetGroup`, {
204
+ vpc,
205
+ port,
206
+ protocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTP,
207
+ targetType: aws_elasticloadbalancingv2_1.TargetType.IP,
208
+ healthCheck: {
209
+ path: healthCheckPath || this.defaultHealthCheck.path || "/",
210
+ interval: aws_cdk_lib_1.Duration.seconds(this.defaultHealthCheck.interval || 30),
211
+ timeout: aws_cdk_lib_1.Duration.seconds(this.defaultHealthCheck.timeout || 5),
212
+ healthyThresholdCount: this.defaultHealthCheck.healthyThreshold || 2,
213
+ unhealthyThresholdCount: this.defaultHealthCheck.unhealthyThreshold || 3
214
+ }
215
+ });
216
+ return targetGroup;
217
+ }
218
+ /**
219
+ * Allow traffic from this load balancer to a connectable resource.
220
+ */
221
+ allowTo(connectable, port) {
222
+ this.connections.allowTo(connectable, port || connectable.connections.defaultPort || aws_ec2_1.Port.allTcp());
223
+ }
224
+ normaliseDomainConfig(domain) {
225
+ if (typeof domain === "string") {
226
+ return { name: domain };
227
+ }
228
+ return domain;
229
+ }
230
+ setupDomain(config) {
231
+ // Get or create hosted zone
232
+ if (config.hostedZone) {
233
+ this.hostedZone = config.hostedZone.getInternalHostedZone();
234
+ }
235
+ else {
236
+ const hostedZone = new hostedZone_1.HostedZone(this, "HostedZone", {
237
+ zoneName: config.name
238
+ });
239
+ this.hostedZone = hostedZone.getInternalHostedZone();
240
+ }
241
+ // Get or create certificate
242
+ if (config.certificate) {
243
+ this.certificate = config.certificate;
244
+ }
245
+ else {
246
+ this.certificate = new aws_certificatemanager_1.Certificate(this, "Certificate", {
247
+ domainName: config.name,
248
+ validation: aws_certificatemanager_1.CertificateValidation.fromDns(this.hostedZone)
249
+ });
250
+ }
251
+ // Create DNS record pointing to ALB
252
+ new aws_route53_1.ARecord(this, "AliasRecord", {
253
+ zone: this.hostedZone,
254
+ recordName: config.name,
255
+ target: aws_route53_1.RecordTarget.fromAlias(new aws_route53_targets_1.LoadBalancerTarget(this.alb))
256
+ });
257
+ }
258
+ truncateName(name, maxLength) {
259
+ if (name.length <= maxLength) {
260
+ return name;
261
+ }
262
+ return name.substring(0, maxLength).replace(/-+$/, "");
263
+ }
264
+ /**
265
+ * Get the DNS name of the load balancer.
266
+ */
267
+ getDnsName() {
268
+ return this.alb.loadBalancerDnsName;
269
+ }
270
+ /**
271
+ * Get the ARN of the load balancer.
272
+ */
273
+ getArn() {
274
+ return this.alb.loadBalancerArn;
275
+ }
276
+ }
277
+ exports.LoadBalancer = LoadBalancer;
278
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZEJhbGFuY2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vbGliL3BhdHRlcm5zL2F3cy9sb2FkQmFsYW5jZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQXVDO0FBQ3ZDLHVGQVFnRDtBQUNoRCwrRUFHNEM7QUFDNUMseURBQWtGO0FBQ2xGLHlFQUFxRTtBQUNyRSxpREFPNkI7QUFDN0IsNkNBQXVDO0FBR3ZDLHVFQUFvRTtBQUNwRSw2Q0FBNkQ7QUFxRjdEOztHQUVHO0FBQ0gsU0FBUyx5QkFBeUIsQ0FBQyxLQUF5QjtJQUMxRCxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN0QixJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzdDLElBQUksS0FBSyxDQUFDLFdBQVcsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsUUFBUSxHQUFHLEdBQUcsRUFBRSxDQUFDO2dCQUN2RSxNQUFNLElBQUksS0FBSyxDQUNiLDBEQUEwRCxDQUMzRCxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzVDLElBQUksS0FBSyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsT0FBTyxHQUFHLEdBQUcsRUFBRSxDQUFDO2dCQUNyRSxNQUFNLElBQUksS0FBSyxDQUNiLHlEQUF5RCxDQUMxRCxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3Qkc7QUFDSCxNQUFhLG1CQUFtQjtJQUM5QixNQUFNLENBQUMsS0FBSyxDQUFDLEVBQVUsRUFBRSxLQUF5QjtRQUNoRCxPQUFPLENBQUMsR0FBUSxF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ZXNDb250ZW50IjpbImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQge1xuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcixcbiAgQXBwbGljYXRpb25MaXN0ZW5lcixcbiAgQXBwbGljYXRpb25Qcm90b2NvbCxcbiAgQXBwbGljYXRpb25UYXJnZXRHcm91cCxcbiAgTGlzdGVuZXJDb25kaXRpb24sXG4gIFRhcmdldFR5cGUsXG4gIHR5cGUgSUFwcGxpY2F0aW9uVGFyZ2V0R3JvdXBcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyXCI7XG5pbXBvcnQge1xuICBDZXJ0aWZpY2F0ZSxcbiAgQ2VydGlmaWNhdGVWYWxpZGF0aW9uXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyXCI7XG5pbXBvcnQgeyBBUmVjb3JkLCBSZWNvcmRUYXJnZXQsIHR5cGUgSUhvc3RlZFpvbmUgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXJvdXRlNTNcIjtcbmltcG9ydCB7IExvYWRCYWxhbmNlclRhcmdldCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtcm91dGU1My10YXJnZXRzXCI7XG5pbXBvcnQge1xuICBDb25uZWN0aW9ucyxcbiAgdHlwZSBJQ29ubmVjdGFibGUsXG4gIHR5cGUgSVZwYyxcbiAgUG9ydCxcbiAgU2VjdXJpdHlHcm91cCxcbiAgU3VibmV0VHlwZVxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuaW1wb3J0IHsgRHVyYXRpb24gfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcblxuaW1wb3J0IHR5cGUgQXBwIGZyb20gXCIuLi8uLi9hcHBcIjtcbmltcG9ydCB7IENmbk91dHB1dCB9IGZyb20gXCIuLi8uLi9yZXNvdXJjZXMvYXdzL3V0aWxpdGllcy9jZm5PdXRwdXRcIjtcbmltcG9ydCB7IEhvc3RlZFpvbmUgYXMgRmphbGxIb3N0ZWRab25lIH0gZnJvbSBcIi4vaG9zdGVkWm9uZVwiO1xuXG4vKipcbiAqIFJvdXRpbmcgY29uZmlndXJhdGlvbiBmb3IgcmVnaXN0ZXJpbmcgc2VydmljZXMgd2l0aCB0aGUgbG9hZCBiYWxhbmNlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2FkQmFsYW5jZXJSb3V0aW5nQ29uZmlnIHtcbiAgLyoqXG4gICAqIFBhdGggcGF0dGVybihzKSB0byBtYXRjaC4gRXhhbXBsZXM6IFwiL2FwaS8qXCIsIFtcIi9hcGkvKlwiLCBcIi92MS8qXCJdXG4gICAqL1xuICBwYXRoPzogc3RyaW5nIHwgc3RyaW5nW107XG4gIC8qKlxuICAgKiBIb3N0IHBhdHRlcm4ocykgdG8gbWF0Y2guIEV4YW1wbGVzOiBcImFwaS5leGFtcGxlLmNvbVwiLCBbXCJhcGkuZXhhbXBsZS5jb21cIiwgXCJ3d3cuZXhhbXBsZS5jb21cIl1cbiAgICovXG4gIGhvc3Q/OiBzdHJpbmcgfCBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIFByaW9yaXR5IGZvciB0aGlzIHJvdXRpbmcgcnVsZS4gTG93ZXIgbnVtYmVycyA9IGhpZ2hlciBwcmlvcml0eS5cbiAgICogTXVzdCBiZSB1bmlxdWUgcGVyIGxpc3RlbmVyLiBSYW5nZTogMS01MDAwMC5cbiAgICovXG4gIHByaW9yaXR5OiBudW1iZXI7XG4gIC8qKlxuICAgKiBIZWFsdGggY2hlY2sgcGF0aCBmb3IgdGhpcyB0YXJnZXQgZ3JvdXAuIERlZmF1bHQ6IFwiL1wiXG4gICAqL1xuICBoZWFsdGhDaGVja1BhdGg/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogSGVhbHRoIGNoZWNrIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBsb2FkIGJhbGFuY2VyLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExvYWRCYWxhbmNlckhlYWx0aENoZWNrQ29uZmlnIHtcbiAgLyoqIEhlYWx0aCBjaGVjayBwYXRoLiBEZWZhdWx0OiBcIi9cIiAqL1xuICBwYXRoPzogc3RyaW5nO1xuICAvKiogSW50ZXJ2YWwgYmV0d2VlbiBoZWFsdGggY2hlY2tzIGluIHNlY29uZHMuIERlZmF1bHQ6IDMwICovXG4gIGludGVydmFsPzogbnVtYmVyO1xuICAvKiogSGVhbHRoIGNoZWNrIHRpbWVvdXQgaW4gc2Vjb25kcy4gRGVmYXVsdDogNSAqL1xuICB0aW1lb3V0PzogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIGNvbnNlY3V0aXZlIHN1Y2Nlc3NlcyBiZWZvcmUgaGVhbHRoeS4gRGVmYXVsdDogMiAqL1xuICBoZWFsdGh5VGhyZXNob2xkPzogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIGNvbnNlY3V0aXZlIGZhaWx1cmVzIGJlZm9yZSB1bmhlYWx0aHkuIERlZmF1bHQ6IDMgKi9cbiAgdW5oZWFsdGh5VGhyZXNob2xkPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIERvbWFpbiBjb25maWd1cmF0aW9uIGZvciBIVFRQUyBhbmQgRE5TLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIExvYWRCYWxhbmNlckRvbWFpbkNvbmZpZyB7XG4gIC8qKiBEb21haW4gbmFtZSAoZS5nLiwgXCJhcGkuZXhhbXBsZS5jb21cIikgKi9cbiAgbmFtZTogc3RyaW5nO1xuICAvKiogRXhpc3RpbmcgaG9zdGVkIHpvbmUuIElmIG9taXR0ZWQsIGNyZWF0ZXMgbmV3IG9uZS4gKi9cbiAgaG9zdGVkWm9uZT86IEZqYWxsSG9zdGVkWm9uZTtcbiAgLyoqIEV4aXN0aW5nIGNlcnRpZmljYXRlLiBJZiBvbWl0dGVkLCBjcmVhdGVzIG5ldyBvbmUgd2l0aCBETlMgdmFsaWRhdGlvbi4gKi9cbiAgY2VydGlmaWNhdGU/OiBDZXJ0aWZpY2F0ZTtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBMb2FkQmFsYW5jZXJGYWN0b3J5LmJ1aWxkKClcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJTG9hZEJhbGFuY2VyUHJvcHMge1xuICAvKiogVlBDIHRvIHBsYWNlIHRoZSBsb2FkIGJhbGFuY2VyIGluLiBEZWZhdWx0OiBhcHAncyBkZWZhdWx0IFZQQyAqL1xuICB2cGM/OiBJVnBjO1xuICAvKipcbiAgICogRG9tYWluIGNvbmZpZ3VyYXRpb24gZm9yIEhUVFBTLlxuICAgKiAtIHN0cmluZzogRG9tYWluIG5hbWUgKGNyZWF0ZXMgaG9zdGVkIHpvbmUgYW5kIGNlcnRpZmljYXRlKVxuICAgKiAtIExvYWRCYWxhbmNlckRvbWFpbkNvbmZpZzogRnVsbCBjb25maWd1cmF0aW9uXG4gICAqIC0gT21pdDogSFRUUCBvbmx5XG4gICAqL1xuICBkb21haW4/OiBzdHJpbmcgfCBMb2FkQmFsYW5jZXJEb21haW5Db25maWc7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBsb2FkIGJhbGFuY2VyIGlzIGludGVybmV0LWZhY2luZy5cbiAgICogRGVmYXVsdDogdHJ1ZVxuICAgKi9cbiAgcHVibGljPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIERlZmF1bHQgaGVhbHRoIGNoZWNrIGNvbmZpZ3VyYXRpb24uXG4gICAqIEluZGl2aWR1YWwgc2VydmljZXMgY2FuIG92ZXJyaWRlIHRoaXMuXG4gICAqL1xuICBoZWFsdGhDaGVjaz86IExvYWRCYWxhbmNlckhlYWx0aENoZWNrQ29uZmlnO1xufVxuXG4vKipcbiAqIEludGVybmFsIHByb3BzIHdpdGggcmVzb2x2ZWQgVlBDLlxuICovXG5pbnRlcmZhY2UgTG9hZEJhbGFuY2VyUHJvcHNSZXNvbHZlZCBleHRlbmRzIElMb2FkQmFsYW5jZXJQcm9wcyB7XG4gIHZwYzogSVZwYztcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgbG9hZCBiYWxhbmNlciBwcm9wcyBhbmQgbG9ncyB3YXJuaW5ncyBmb3IgbWlzY29uZmlndXJlZCBvcHRpb25zLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUxvYWRCYWxhbmNlclByb3BzKHByb3BzOiBJTG9hZEJhbGFuY2VyUHJvcHMpOiB2b2lkIHtcbiAgaWYgKHByb3BzLmhlYWx0aENoZWNrKSB7XG4gICAgaWYgKHByb3BzLmhlYWx0aENoZWNrLmludGVydmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChwcm9wcy5oZWFsdGhDaGVjay5pbnRlcnZhbCA8IDUgfHwgcHJvcHMuaGVhbHRoQ2hlY2suaW50ZXJ2YWwgPiAzMDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiSGVhbHRoIGNoZWNrIGludGVydmFsIG11c3QgYmUgYmV0d2VlbiA1IGFuZCAzMDAgc2Vjb25kcy5cIlxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAocHJvcHMuaGVhbHRoQ2hlY2sudGltZW91dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAocHJvcHMuaGVhbHRoQ2hlY2sudGltZW91dCA8IDIgfHwgcHJvcHMuaGVhbHRoQ2hlY2sudGltZW91dCA+IDEyMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgXCJIZWFsdGggY2hlY2sgdGltZW91dCBtdXN0IGJlIGJldHdlZW4gMiBhbmQgMTIwIHNlY29uZHMuXCJcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBGYWN0b3J5IGZvciBjcmVhdGluZyBMb2FkQmFsYW5jZXIgY29uc3RydWN0cy5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gU2ltcGxlIEhUVFAgbG9hZCBiYWxhbmNlclxuICogY29uc3QgYWxiID0gYXBwLmFkZENvbXB1dGUoXG4gKiAgIExvYWRCYWxhbmNlckZhY3RvcnkuYnVpbGQoXCJNYWluQUxCXCIsIHt9KVxuICogKTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gSFRUUFMgbG9hZCBiYWxhbmNlciB3aXRoIGRvbWFpblxuICogY29uc3QgYWxiID0gYXBwLmFkZENvbXB1dGUoXG4gKiAgIExvYWRCYWxhbmNlckZhY3RvcnkuYnVpbGQoXCJNYWluQUxCXCIsIHtcbiAqICAgICBkb21haW46IFwiYXBwLmV4YW1wbGUuY29tXCJcbiAqICAgfSlcbiAqICk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIEludGVybmFsIGxvYWQgYmFsYW5jZXJcbiAqIGNvbnN0IGFsYiA9IGFwcC5hZGRDb21wdXRlKFxuICogICBMb2FkQmFsYW5jZXJGYWN0b3J5LmJ1aWxkKFwiSW50ZXJuYWxBTEJcIiwge1xuICogICAgIHB1YmxpYzogZmFsc2VcbiAqICAgfSlcbiAqICk7XG4gKi9cbmV4cG9ydCBjbGFzcyBMb2FkQmFsYW5jZXJGYWN0b3J5IHtcbiAgc3RhdGljIGJ1aWxkKGlkOiBzdHJpbmcsIHByb3BzOiBJTG9hZEJhbGFuY2VyUHJvcHMpIHtcbiAgICByZXR1cm4gKGFwcDogQXBwLCBzY29wZTogQ29uc3RydWN0KTogTG9hZEJhbGFuY2VyID0+IHtcbiAgICAgIHZhbGlkYXRlTG9hZEJhbGFuY2VyUHJvcHMocHJvcHMpO1xuXG4gICAgICBjb25zdCByZXNvbHZlZFByb3BzOiBMb2FkQmFsYW5jZXJQcm9wc1Jlc29sdmVkID0ge1xuICAgICAgICAuLi5wcm9wcyxcbiAgICAgICAgdnBjOiBwcm9wcy52cGMgfHwgYXBwLmdldFZwYygpXG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gbmV3IExvYWRCYWxhbmNlcihzY29wZSwgaWQsIHJlc29sdmVkUHJvcHMpO1xuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBBcHBsaWNhdGlvbiBMb2FkIEJhbGFuY2VyIGNvbnN0cnVjdCB0aGF0IGNhbiBiZSBzaGFyZWQgYWNyb3NzIG11bHRpcGxlIEVDUyBzZXJ2aWNlcy5cbiAqXG4gKiBVc2UgTG9hZEJhbGFuY2VyRmFjdG9yeS5idWlsZCgpIHRvIGNyZWF0ZSBpbnN0YW5jZXMgdmlhIGFwcC5hZGRDb21wdXRlKCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2FkQmFsYW5jZXIgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJQ29ubmVjdGFibGUge1xuICBwdWJsaWMgcmVhZG9ubHkgYWxiOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcjtcbiAgcHVibGljIHJlYWRvbmx5IGxpc3RlbmVyOiBBcHBsaWNhdGlvbkxpc3RlbmVyO1xuICBwdWJsaWMgcmVhZG9ubHkgc2VjdXJpdHlHcm91cDogU2VjdXJpdHlHcm91cDtcbiAgcHVibGljIHJlYWRvbmx5IHVybDogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgY29ubmVjdGlvbnM6IENvbm5lY3Rpb25zO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaG9zdGVkWm9uZT86IElIb3N0ZWRab25lO1xuICBwcml2YXRlIHJlYWRvbmx5IGNlcnRpZmljYXRlPzogQ2VydGlmaWNhdGU7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdEhlYWx0aENoZWNrOiBMb2FkQmFsYW5jZXJIZWFsdGhDaGVja0NvbmZpZztcbiAgcHJpdmF0ZSByZWFkb25seSBpc0h0dHBzOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBMb2FkQmFsYW5jZXJQcm9wc1Jlc29sdmVkKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHRoaXMuZGVmYXVsdEhlYWx0aENoZWNrID0gcHJvcHMuaGVhbHRoQ2hlY2sgfHwge307XG4gICAgdGhpcy5pc0h0dHBzID0gISFwcm9wcy5kb21haW47XG5cbiAgICAvLyBDcmVhdGUgc2VjdXJpdHkgZ3JvdXBcbiAgICB0aGlzLnNlY3VyaXR5R3JvdXAgPSBuZXcgU2VjdXJpdHlHcm91cCh0aGlzLCBcIlNlY3VyaXR5R3JvdXBcIiwge1xuICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICBkZXNjcmlwdGlvbjogYFNlY3VyaXR5IGdyb3VwIGZvciAke2lkfSBsb2FkIGJhbGFuY2VyYCxcbiAgICAgIGFsbG93QWxsT3V0Ym91bmQ6IHRydWVcbiAgICB9KTtcblxuICAgIC8vIEFsbG93IGluYm91bmQgdHJhZmZpY1xuICAgIGNvbnN0IGluYm91bmRQb3J0ID0gdGhpcy5pc0h0dHBzID8gNDQzIDogODA7XG4gICAgdGhpcy5zZWN1cml0eUdyb3VwLmFkZEluZ3Jlc3NSdWxlKFxuICAgICAgeyBjb25uZWN0aW9uczogeyBhbGxvd0Zyb21BbnlJcHY0OiAoKSA9PiB7fSB9IH0gYXMgYW55LFxuICAgICAgUG9ydC50Y3AoaW5ib3VuZFBvcnQpLFxuICAgICAgYEFsbG93IGluYm91bmQgJHt0aGlzLmlzSHR0cHMgPyBcIkhUVFBTXCIgOiBcIkhUVFBcIn1gXG4gICAgKTtcblxuICAgIC8vIENyZWF0ZSBBTEJcbiAgICBjb25zdCBsb2FkQmFsYW5jZXJOYW1lID0gdGhpcy50cnVuY2F0ZU5hbWUoYCR7aWR9QUxCYCwgMzIpO1xuICAgIHRoaXMuYWxiID0gbmV3IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyKHRoaXMsIFwiQUxCXCIsIHtcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgaW50ZXJuZXRGYWNpbmc6IHByb3BzLnB1YmxpYyAhPT0gZmFsc2UsXG4gICAgICBzZWN1cml0eUdyb3VwOiB0aGlzLnNlY3VyaXR5R3JvdXAsXG4gICAgICBsb2FkQmFsYW5jZXJOYW1lLFxuICAgICAgdnBjU3VibmV0czoge1xuICAgICAgICBzdWJuZXRUeXBlOlxuICAgICAgICAgIHByb3BzLnB1YmxpYyAhPT0gZmFsc2UgPyBTdWJuZXRUeXBlLlBVQkxJQyA6IFN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX0VHUkVTU1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gU2V0IHVwIGRvbWFpbiBpZiBjb25maWd1cmVkXG4gICAgaWYgKHByb3BzLmRvbWFpbikge1xuICAgICAgY29uc3QgZG9tYWluQ29uZmlnID0gdGhpcy5ub3JtYWxpc2VEb21haW5Db25maWcocHJvcHMuZG9tYWluKTtcbiAgICAgIHRoaXMuc2V0dXBEb21haW4oZG9tYWluQ29uZmlnKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgbGlzdGVuZXJcbiAgICBpZiAodGhpcy5pc0h0dHBzICYmIHRoaXMuY2VydGlmaWNhdGUpIHtcbiAgICAgIHRoaXMubGlzdGVuZXIgPSB0aGlzLmFsYi5hZGRMaXN0ZW5lcihcIkxpc3RlbmVyXCIsIHtcbiAgICAgICAgcG9ydDogNDQzLFxuICAgICAgICBwcm90b2NvbDogQXBwbGljYXRpb25Qcm90b2NvbC5IVFRQUyxcbiAgICAgICAgY2VydGlmaWNhdGVzOiBbdGhpcy5jZXJ0aWZpY2F0ZV1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBBZGQgSFRUUCByZWRpcmVjdFxuICAgICAgdGhpcy5hbGIuYWRkTGlzdGVuZXIoXCJIdHRwUmVkaXJlY3RcIiwge1xuICAgICAgICBwb3J0OiA4MCxcbiAgICAgICAgcHJvdG9jb2w6IEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUCxcbiAgICAgICAgZGVmYXVsdEFjdGlvbjoge1xuICAgICAgICAgIHJlZGlyZWN0OiB7XG4gICAgICAgICAgICBwcm90b2NvbDogXCJIVFRQU1wiLFxuICAgICAgICAgICAgcG9ydDogXCI0NDNcIixcbiAgICAgICAgICAgIHBlcm1hbmVudDogdHJ1ZVxuICAgICAgICAgIH1cbiAgICAgICAgfSBhcyBhbnlcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmxpc3RlbmVyID0gdGhpcy5hbGIuYWRkTGlzdGVuZXIoXCJMaXN0ZW5lclwiLCB7XG4gICAgICAgIHBvcnQ6IDgwLFxuICAgICAgICBwcm90b2NvbDogQXBwbGljYXRpb25Qcm90b2NvbC5IVFRQXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBBZGQgZGVmYXVsdCBhY3Rpb24gKHJldHVybnMgNTAzIGlmIG5vIHRhcmdldHMgbWF0Y2gpXG4gICAgdGhpcy5saXN0ZW5lci5hZGRBY3Rpb24oXCJEZWZhdWx0QWN0aW9uXCIsIHtcbiAgICAgIGFjdGlvbjoge1xuICAgICAgICBmaXhlZFJlc3BvbnNlOiB7XG4gICAgICAgICAgc3RhdHVzQ29kZTogNTAzLFxuICAgICAgICAgIGNvbnRlbnRUeXBlOiBcInRleHQvcGxhaW5cIixcbiAgICAgICAgICBtZXNzYWdlQm9keTogXCJObyBzZXJ2aWNlIGF2YWlsYWJsZVwiXG4gICAgICAgIH1cbiAgICAgIH0gYXMgYW55XG4gICAgfSk7XG5cbiAgICAvLyBTZXQgVVJMXG4gICAgdGhpcy51cmwgPSB0aGlzLmlzSHR0cHNcbiAgICAgID8gYGh0dHBzOi8vJHt0aGlzLmFsYi5sb2FkQmFsYW5jZXJEbnNOYW1lfWBcbiAgICAgIDogYGh0dHA6Ly8ke3RoaXMuYWxiLmxvYWRCYWxhbmNlckRuc05hbWV9YDtcblxuICAgIC8vIFNldCB1cCBjb25uZWN0aW9uc1xuICAgIHRoaXMuY29ubmVjdGlvbnMgPSBuZXcgQ29ubmVjdGlvbnMoe1xuICAgICAgc2VjdXJpdHlHcm91cHM6IFt0aGlzLnNlY3VyaXR5R3JvdXBdLFxuICAgICAgZGVmYXVsdFBvcnQ6IFBvcnQudGNwKGluYm91bmRQb3J0KVxuICAgIH0pO1xuXG4gICAgLy8gT3V0cHV0c1xuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJMb2FkQmFsYW5jZXJEbnNOYW1lXCIsIHtcbiAgICAgIGtleTogYCR7aWR9TG9hZEJhbGFuY2VyRG5zTmFtZWAsXG4gICAgICBleHBvcnROYW1lOiBgJHtpZH1Mb2FkQmFsYW5jZXJEbnNOYW1lYCxcbiAgICAgIHZhbHVlOiB0aGlzLmFsYi5sb2FkQmFsYW5jZXJEbnNOYW1lXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsIFwiTG9hZEJhbGFuY2VyVXJsXCIsIHtcbiAgICAgIGtleTogYCR7aWR9TG9hZEJhbGFuY2VyVXJsYCxcbiAgICAgIGV4cG9ydE5hbWU6IGAke2lkfUxvYWRCYWxhbmNlclVybGAsXG4gICAgICB2YWx1ZTogdGhpcy51cmwsXG4gICAgICBkZXNjcmlwdGlvbjogYExvYWQgQmFsYW5jZXIgVVJMIGZvciAke2lkfWBcbiAgICB9KTtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgXCJMb2FkQmFsYW5jZXJBcm5cIiwge1xuICAgICAga2V5OiBgJHtpZH1Mb2FkQmFsYW5jZXJBcm5gLFxuICAgICAgZXhwb3J0TmFtZTogYCR7aWR9TG9hZEJhbGFuY2VyQXJuYCxcbiAgICAgIHZhbHVlOiB0aGlzLmFsYi5sb2FkQmFsYW5jZXJBcm4sXG4gICAgICBkZXNjcmlwdGlvbjogYExvYWQgQmFsYW5jZXIgQVJOIGZvciAke2lkfWBcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIHRhcmdldCBncm91cCB3aXRoIHJvdXRpbmcgcnVsZXMuXG4gICAqIENhbGxlZCBpbnRlcm5hbGx5IGJ5IEVjc0NsdXN0ZXIgd2hlbiBsb2FkQmFsYW5jZXIudGFyZ2V0IGlzIHNwZWNpZmllZC5cbiAgICpcbiAgICogQHBhcmFtIHRhcmdldEdyb3VwIC0gVGhlIHRhcmdldCBncm91cCB0byByZWdpc3RlclxuICAgKiBAcGFyYW0gcm91dGluZyAtIFJvdXRpbmcgY29uZmlndXJhdGlvbiAocGF0aCwgaG9zdCwgcHJpb3JpdHkpXG4gICAqL1xuICBwdWJsaWMgcmVnaXN0ZXJUYXJnZXRHcm91cChcbiAgICB0YXJnZXRHcm91cDogSUFwcGxpY2F0aW9uVGFyZ2V0R3JvdXAsXG4gICAgcm91dGluZzogTG9hZEJhbGFuY2VyUm91dGluZ0NvbmZpZ1xuICApOiB2b2lkIHtcbiAgICBjb25zdCBjb25kaXRpb25zOiBMaXN0ZW5lckNvbmRpdGlvbltdID0gW107XG5cbiAgICBpZiAocm91dGluZy5wYXRoKSB7XG4gICAgICBjb25zdCBwYXRocyA9IEFycmF5LmlzQXJyYXkocm91dGluZy5wYXRoKSA/IHJvdXRpbmcucGF0aCA6IFtyb3V0aW5nLnBhdGhdO1xuICAgICAgY29uZGl0aW9ucy5wdXNoKExpc3RlbmVyQ29uZGl0aW9uLnBhdGhQYXR0ZXJucyhwYXRocykpO1xuICAgIH1cblxuICAgIGlmIChyb3V0aW5nLmhvc3QpIHtcbiAgICAgIGNvbnN0IGhvc3RzID0gQXJyYXkuaXNBcnJheShyb3V0aW5nLmhvc3QpID8gcm91dGluZy5ob3N0IDogW3JvdXRpbmcuaG9zdF07XG4gICAgICBjb25kaXRpb25zLnB1c2goTGlzdGVuZXJDb25kaXRpb24uaG9zdEhlYWRlcnMoaG9zdHMpKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZGl0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJBdCBsZWFzdCBvbmUgcm91dGluZyBjb25kaXRpb24gKHBhdGggb3IgaG9zdCkgbXVzdCBiZSBzcGVjaWZpZWQuXCJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5saXN0ZW5lci5hZGRUYXJnZXRHcm91cHMoYFJ1bGUke3JvdXRpbmcucHJpb3JpdHl9YCwge1xuICAgICAgdGFyZ2V0R3JvdXBzOiBbdGFyZ2V0R3JvdXBdLFxuICAgICAgY29uZGl0aW9ucyxcbiAgICAgIHByaW9yaXR5OiByb3V0aW5nLnByaW9yaXR5XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgdGFyZ2V0IGdyb3VwIGZvciBhbiBFQ1Mgc2VydmljZS5cbiAgICogUmV0dXJucyB0aGUgdGFyZ2V0IGdyb3VwIGZvciB0aGUgc2VydmljZSB0byByZWdpc3RlciB3aXRoLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHRhcmdldCBncm91cFxuICAgKiBAcGFyYW0gcG9ydCAtIENvbnRhaW5lciBwb3J0XG4gICAqIEBwYXJhbSB2cGMgLSBWUEMgZm9yIHRoZSB0YXJnZXQgZ3JvdXBcbiAgICogQHBhcmFtIGhlYWx0aENoZWNrUGF0aCAtIE9wdGlvbmFsIGhlYWx0aCBjaGVjayBwYXRoIG92ZXJyaWRlXG4gICAqL1xuICBwdWJsaWMgY3JlYXRlVGFyZ2V0R3JvdXAoXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwb3J0OiBudW1iZXIsXG4gICAgdnBjOiBJVnBjLFxuICAgIGhlYWx0aENoZWNrUGF0aD86IHN0cmluZ1xuICApOiBBcHBsaWNhdGlvblRhcmdldEdyb3VwIHtcbiAgICBjb25zdCB0YXJnZXRHcm91cCA9IG5ldyBBcHBsaWNhdGlvblRhcmdldEdyb3VwKHRoaXMsIGAke2lkfVRhcmdldEdyb3VwYCwge1xuICAgICAgdnBjLFxuICAgICAgcG9ydCxcbiAgICAgIHByb3RvY29sOiBBcHBsaWNhdGlvblByb3RvY29sLkhUVFAsXG4gICAgICB0YXJnZXRUeXBlOiBUYXJnZXRUeXBlLklQLFxuICAgICAgaGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgcGF0aDogaGVhbHRoQ2hlY2tQYXRoIHx8IHRoaXMuZGVmYXVsdEhlYWx0aENoZWNrLnBhdGggfHwgXCIvXCIsXG4gICAgICAgIGludGVydmFsOiBEdXJhdGlvbi5zZWNvbmRzKFxuICAgICAgICAgIHRoaXMuZGVmYXVsdEhlYWx0aENoZWNrLmludGVydmFsIHx8IDMwXG4gICAgICAgICksXG4gICAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoXG4gICAgICAgICAgdGhpcy5kZWZhdWx0SGVhbHRoQ2hlY2sudGltZW91dCB8fCA1XG4gICAgICAgICksXG4gICAgICAgIGhlYWx0aHlUaHJlc2hvbGRDb3VudDogdGhpcy5kZWZhdWx0SGVhbHRoQ2hlY2suaGVhbHRoeVRocmVzaG9sZCB8fCAyLFxuICAgICAgICB1bmhlYWx0aHlUaHJlc2hvbGRDb3VudDogdGhpcy5kZWZhdWx0SGVhbHRoQ2hlY2sudW5oZWFsdGh5VGhyZXNob2xkIHx8IDNcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB0YXJnZXRHcm91cDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvdyB0cmFmZmljIGZyb20gdGhpcyBsb2FkIGJhbGFuY2VyIHRvIGEgY29ubmVjdGFibGUgcmVzb3VyY2UuXG4gICAqL1xuICBwdWJsaWMgYWxsb3dUbyhjb25uZWN0YWJsZTogSUNvbm5lY3RhYmxlLCBwb3J0PzogUG9ydCk6IHZvaWQge1xuICAgIHRoaXMuY29ubmVjdGlvbnMuYWxsb3dUbyhcbiAgICAgIGNvbm5lY3RhYmxlLFxuICAgICAgcG9ydCB8fCBjb25uZWN0YWJsZS5jb25uZWN0aW9ucy5kZWZhdWx0UG9ydCB8fCBQb3J0LmFsbFRjcCgpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgbm9ybWFsaXNlRG9tYWluQ29uZmlnKFxuICAgIGRvbWFpbjogc3RyaW5nIHwgTG9hZEJhbGFuY2VyRG9tYWluQ29uZmlnXG4gICk6IExvYWRCYWxhbmNlckRvbWFpbkNvbmZpZyB7XG4gICAgaWYgKHR5cGVvZiBkb21haW4gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHJldHVybiB7IG5hbWU6IGRvbWFpbiB9O1xuICAgIH1cbiAgICByZXR1cm4gZG9tYWluO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cERvbWFpbihjb25maWc6IExvYWRCYWxhbmNlckRvbWFpbkNvbmZpZyk6IHZvaWQge1xuICAgIC8vIEdldCBvciBjcmVhdGUgaG9zdGVkIHpvbmVcbiAgICBpZiAoY29uZmlnLmhvc3RlZFpvbmUpIHtcbiAgICAgICh0aGlzIGFzIGFueSkuaG9zdGVkWm9uZSA9IGNvbmZpZy5ob3N0ZWRab25lLmdldEludGVybmFsSG9zdGVkWm9uZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBob3N0ZWRab25lID0gbmV3IEZqYWxsSG9zdGVkWm9uZSh0aGlzLCBcIkhvc3RlZFpvbmVcIiwge1xuICAgICAgICB6b25lTmFtZTogY29uZmlnLm5hbWVcbiAgICAgIH0pO1xuICAgICAgKHRoaXMgYXMgYW55KS5ob3N0ZWRab25lID0gaG9zdGVkWm9uZS5nZXRJbnRlcm5hbEhvc3RlZFpvbmUoKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgb3IgY3JlYXRlIGNlcnRpZmljYXRlXG4gICAgaWYgKGNvbmZpZy5jZXJ0aWZpY2F0ZSkge1xuICAgICAgKHRoaXMgYXMgYW55KS5jZXJ0aWZpY2F0ZSA9IGNvbmZpZy5jZXJ0aWZpY2F0ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgKHRoaXMgYXMgYW55KS5jZXJ0aWZpY2F0ZSA9IG5ldyBDZXJ0aWZpY2F0ZSh0aGlzLCBcIkNlcnRpZmljYXRlXCIsIHtcbiAgICAgICAgZG9tYWluTmFtZTogY29uZmlnLm5hbWUsXG4gICAgICAgIHZhbGlkYXRpb246IENlcnRpZmljYXRlVmFsaWRhdGlvbi5mcm9tRG5zKHRoaXMuaG9zdGVkWm9uZSlcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBETlMgcmVjb3JkIHBvaW50aW5nIHRvIEFMQlxuICAgIG5ldyBBUmVjb3JkKHRoaXMsIFwiQWxpYXNSZWNvcmRcIiwge1xuICAgICAgem9uZTogdGhpcy5ob3N0ZWRab25lISxcbiAgICAgIHJlY29yZE5hbWU6IGNvbmZpZy5uYW1lLFxuICAgICAgdGFyZ2V0OiBSZWNvcmRUYXJnZXQuZnJvbUFsaWFzKG5ldyBMb2FkQmFsYW5jZXJUYXJnZXQodGhpcy5hbGIpKVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB0cnVuY2F0ZU5hbWUobmFtZTogc3RyaW5nLCBtYXhMZW5ndGg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKG5hbWUubGVuZ3RoIDw9IG1heExlbmd0aCkge1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuICAgIHJldHVybiBuYW1lLnN1YnN0cmluZygwLCBtYXhMZW5ndGgpLnJlcGxhY2UoLy0rJC8sIFwiXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgRE5TIG5hbWUgb2YgdGhlIGxvYWQgYmFsYW5jZXIuXG4gICAqL1xuICBwdWJsaWMgZ2V0RG5zTmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmFsYi5sb2FkQmFsYW5jZXJEbnNOYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgQVJOIG9mIHRoZSBsb2FkIGJhbGFuY2VyLlxuICAgKi9cbiAgcHVibGljIGdldEFybigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmFsYi5sb2FkQmFsYW5jZXJBcm47XG4gIH1cbn1cbiJdfQ==
@@ -53,6 +53,7 @@ export interface TransitGatewayConfig {
53
53
  * { maxAzs: 3, natGateways: { count: 3 }, vpcEndpoints: { interface: { ecr: true } } }
54
54
  */
55
55
  export interface INetworkProps {
56
+ vpcName?: string;
56
57
  maxAzs?: number;
57
58
  cidrMask?: number;
58
59
  natGateways?: NatConfig | false;
@@ -44,6 +44,7 @@ class Network extends constructs_1.Construct {
44
44
  ipv4IpamPoolId = aws_cdk_lib_1.Fn.importValue(`IpamPoolId${accountId}${regionSuffix}`);
45
45
  }
46
46
  const vpcProps = {
47
+ vpcName: props.vpcName,
47
48
  accountId,
48
49
  region,
49
50
  ipv4IpamPoolId,
@@ -96,4 +97,4 @@ class Network extends constructs_1.Construct {
96
97
  }
97
98
  }
98
99
  exports.Network = Network;
99
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29yay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9wYXR0ZXJucy9hd3MvbmV0d29yay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQ0FBdUM7QUFDdkMsNkNBQWlDO0FBSWpDLDREQUF3RTtBQXNFeEUsU0FBUyxvQkFBb0IsQ0FBQyxLQUFvQjtJQUNoRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3pFLE9BQU8sQ0FBQyxJQUFJLENBQ1YsNkRBQTZELEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FDN0UsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUNFLE9BQU8sS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRO1FBQ3JDLEtBQUssQ0FBQyxXQUFXLEtBQUssSUFBSTtRQUMxQixLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssS0FBSyxTQUFTLEVBQ3JDLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUNqQyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQ1YseUNBQXlDLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxxQkFBcUIsTUFBTSxJQUFJLENBQ2hHLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSyxDQUFDLGNBQWMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDckQsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBYSxjQUFjO0lBQ3pCLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFB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QUFLLENBQUM7UUFFbkMscUNBQXFDO1FBQ3JDLElBQUksTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3pCLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ25ELENBQUM7UUFFRCxPQUFPO1lBQ0wsT0FBTyxFQUNMLE1BQU0sQ0FBQyxPQUFPLEtBQUssS0FBSztnQkFDdEIsQ0FBQyxDQUFDLEtBQUs7Z0JBQ1AsQ0FBQyxDQUFDO29CQUNFLEVBQUUsRUFBRSxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxJQUFJO29CQUM5QixRQUFRLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxRQUFRLElBQUksSUFBSTtpQkFDM0M7WUFDUCxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVM7U0FDakUsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNO1FBQ0osT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ2xCLENBQUM7Q0FDRjtBQXJHRCwwQkFxR0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgRm4gfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IHR5cGUgSVZwYyB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCI7XG5cbmltcG9ydCB0eXBlIEFwcCBmcm9tIFwiLi4vLi4vYXBwXCI7XG5pbXBvcnQgeyBWcGMsIHR5cGUgVnBjUHJvcHMgfSBmcm9tIFwiLi4vLi4vcmVzb3VyY2VzL2F3cy9uZXR3b3JraW5nL3ZwY1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE5hdENvbmZpZyB7XG4gIGNvdW50PzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEZsb3dMb2dDb25maWcge1xuICBkZXN0aW5hdGlvbj86IFwiY2xvdWR3YXRjaFwiIHwgXCJzM1wiO1xuICByZXRlbnRpb25EYXlzPzogbnVtYmVyO1xuICB0cmFmZmljVHlwZT86IFwiQUxMXCIgfCBcIkFDQ0VQVFwiIHwgXCJSRUpFQ1RcIjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHYXRld2F5RW5kcG9pbnRzQ29uZmlnIHtcbiAgczM/OiBib29sZWFuO1xuICBkeW5hbW9kYj86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW50ZXJmYWNlRW5kcG9pbnRzQ29uZmlnIHtcbiAgZWNyPzogYm9vbGVhbjtcbiAgc2VjcmV0c01hbmFnZXI/OiBib29sZWFuO1xuICBrbXM/OiBib29sZWFuO1xuICBjbG91ZHdhdGNoTG9ncz86IGJvb2xlYW47XG4gIHNzbT86IGJvb2xlYW47XG4gIHN0cz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVnBjRW5kcG9pbnRzQ29uZmlnIHtcbiAgZ2F0ZXdheT86IEdhdGV3YXlFbmRwb2ludHNDb25maWcgfCBmYWxzZTtcbiAgaW50ZXJmYWNlPzogSW50ZXJmYWNlRW5kcG9pbnRzQ29uZmlnIHwgZmFsc2U7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VibmV0Q29uZmlnIHtcbiAgY2lkck1hc2s/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VibmV0c0NvbmZpZyB7XG4gIHB1YmxpYz86IFN1Ym5ldENvbmZpZztcbiAgcHJpdmF0ZT86IFN1Ym5ldENvbmZpZztcbiAgaXNvbGF0ZWQ/OiBTdWJuZXRDb25maWcgfCBmYWxzZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2l0R2F0ZXdheUNvbmZpZyB7XG4gIGlkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogTmV0d29yayAoVlBDKSBjb25maWd1cmF0aW9uLlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBNaW5pbWFsIGNvc3QgVlBDIChubyBOQVQsIGdhdGV3YXkgZW5kcG9pbnRzIG9ubHkpXG4gKiB7IG5hdEdhdGV3YXlzOiBmYWxzZSB9XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFByb2R1Y3Rpb24gVlBDIHdpdGggMSBOQVQgZ2F0ZXdheVxuICogeyBuYXRHYXRld2F5czogeyBjb3VudDogMSB9LCBmbG93TG9nczoge30gfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBIaWdoLWF2YWlsYWJpbGl0eSBWUEMgd2l0aCBpbnRlcmZhY2UgZW5kcG9pbnRzXG4gKiB7IG1heEF6czogMywgbmF0R2F0ZXdheXM6IHsgY291bnQ6IDMgfSwgdnBjRW5kcG9pbnRzOiB7IGludGVyZmFjZTogeyBlY3I6IHRydWUgfSB9IH1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJTmV0d29ya1Byb3BzIHtcbiAgbWF4QXpzPzogbnVtYmVyO1xuICBjaWRyTWFzaz86IG51bWJlcjtcbiAgbmF0R2F0ZXdheXM/OiBOYXRDb25maWcgfCBmYWxzZTtcbiAgZmxvd0xvZ3M/OiBGbG93TG9nQ29uZmlnIHwgZmFsc2U7XG4gIHZwY0VuZHBvaW50cz86IFZwY0VuZHBvaW50c0NvbmZpZyB8IGZhbHNlO1xuICBzdWJuZXRzPzogU3VibmV0c0NvbmZpZztcbiAgdHJhbnNpdEdhdGV3YXk/OiBUcmFuc2l0R2F0ZXdheUNvbmZpZztcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVOZXR3b3JrUHJvcHMocHJvcHM6IElOZXR3b3JrUHJvcHMpOiB2b2lkIHtcbiAgaWYgKHByb3BzLm1heEF6cyAhPT0gdW5kZWZpbmVkICYmIChwcm9wcy5tYXhBenMgPCAxIHx8IHByb3BzLm1heEF6cyA+IDMpKSB7XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgYFtGamFsbF0gV2FybmluZzogJ21heEF6cycgc2hvdWxkIGJlIGJldHdlZW4gMSBhbmQgMy4gR290OiAke3Byb3BzLm1heEF6c30uYFxuICAgICk7XG4gIH1cblxuICBpZiAoXG4gICAgdHlwZW9mIHByb3BzLm5hdEdhdGV3YXlzID09PSBcIm9iamVjdFwiICYmXG4gICAgcHJvcHMubmF0R2F0ZXdheXMgIT09IG51bGwgJiZcbiAgICBwcm9wcy5uYXRHYXRld2F5cy5jb3VudCAhPT0gdW5kZWZpbmVkXG4gICkge1xuICAgIGNvbnN0IG1heEF6cyA9IHByb3BzLm1heEF6cyA/PyAzO1xuICAgIGlmIChwcm9wcy5uYXRHYXRld2F5cy5jb3VudCA+IG1heEF6cykge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgW0ZqYWxsXSBXYXJuaW5nOiAnbmF0R2F0ZXdheXMuY291bnQnICgke3Byb3BzLm5hdEdhdGV3YXlzLmNvdW50fSkgZXhjZWVkcyBtYXhBenMgKCR7bWF4QXpzfSkuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAocHJvcHMudHJhbnNpdEdhdGV3YXkgJiYgIXByb3BzLnRyYW5zaXRHYXRld2F5LmlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiVHJhbnNpdCBHYXRld2F5IGNvbmZpZ3VyYXRpb24gcmVxdWlyZXMgJ2lkJy5cIik7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5ldHdvcmtGYWN0b3J5IHtcbiAgc3RhdGljIGJ1aWxkKGlkOiBzdHJpbmcsIHByb3BzOiBJTmV0d29ya1Byb3BzKSB7XG4gICAgcmV0dXJuIChhcHA6IEFwcCwgc2NvcGU6IENvbnN0cnVjdCkgPT4ge1xuICAgICAgdmFsaWRhdGVOZXR3b3JrUHJvcHMocHJvcHMpO1xuICAgICAgcmV0dXJuIG5ldyBOZXR3b3JrKHNjb3BlLCBpZCwgcHJvcHMsIGFwcCk7XG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTmV0d29yayBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSB2cGM6IFZwYztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogSU5ldHdvcmtQcm9wcywgYXBwOiBBcHApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuICAgIHRoaXMudnBjID0gdGhpcy5jcmVhdGVWcGMoaWQsIHByb3BzLCBhcHApO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVWcGMoaWQ6IHN0cmluZywgcHJvcHM6IElOZXR3b3JrUHJvcHMsIGFwcDogQXBwKTogVnBjIHtcbiAgICBjb25zdCBhY2NvdW50SWQgPVxuICAgICAgYXBwLm5vZGUudHJ5R2V0Q29udGV4dChcImFjY291bnRJZFwiKSB8fCBwcm9jZXNzLmVudi5DREtfREVGQVVMVF9BQ0NPVU5UO1xuICAgIGNvbnN0IHJlZ2lvbiA9IHByb2Nlc3MuZW52LkNES19ERUZBVUxUX1JFR0lPTjtcbiAgICBjb25zdCBpc01hbmFnZWRBY2NvdW50ID1cbiAgICAgIGFwcC5ub2RlLnRyeUdldENvbnRleHQoXCJtYW5hZ2VkQWNjb3VudFwiKSA9PT0gXCJ0cnVlXCI7XG5cbiAgICBsZXQgaXB2NElwYW1Qb29sSWQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAoaXNNYW5hZ2VkQWNjb3VudCAmJiBhY2NvdW50SWQgJiYgcmVnaW9uKSB7XG4gICAgICBjb25zdCByZWdpb25TdWZmaXggPSByZWdpb24ucmVwbGFjZSgvLS9nLCBcIlwiKTtcbiAgICAgIGlwdjRJcGFtUG9vbElkID0gRm4uaW1wb3J0VmFsdWUoYElwYW1Qb29sSWQke2FjY291bnRJZH0ke3JlZ2lvblN1ZmZpeH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCB2cGNQcm9wczogVnBjUHJvcHMgPSB7XG4gICAgICBhY2NvdW50SWQsXG4gICAgICByZWdpb24sXG4gICAgICBpcHY0SXBhbVBvb2xJZCxcbiAgICAgIG1heEF6czogcHJvcHMubWF4QXpzLFxuICAgICAgdnBjQ2lkck1hc2s6IHByb3BzLmNpZHJNYXNrLFxuICAgICAgc3VibmV0Q2lkck1hc2s6IHByb3BzLnN1Ym5ldHM/LnByaXZhdGU/LmNpZHJNYXNrLFxuICAgICAgbmF0R2F0ZXdheUNvbmZpZzogdGhpcy5yZXNvbHZlTmF0Q29uZmlnKHByb3BzLm5hdEdhdGV3YXlzKSxcbiAgICAgIGZsb3dMb2dDb25maWc6IHRoaXMucmVzb2x2ZUZsb3dMb2dDb25maWcocHJvcHMuZmxvd0xvZ3MpLFxuICAgICAgZW5kcG9pbnRzQ29uZmlnOiB0aGlzLnJlc29sdmVFbmRwb2ludHNDb25maWcocHJvcHMudnBjRW5kcG9pbnRzKVxuICAgIH07XG5cbiAgICByZXR1cm4gbmV3IFZwYyh0aGlzLCBpZCwgdnBjUHJvcHMpO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlTmF0Q29uZmlnKFxuICAgIGNvbmZpZzogTmF0Q29uZmlnIHwgZmFsc2UgfCB1bmRlZmluZWRcbiAgKTogeyBjb3VudD86IG51bWJlciB9IHwgZmFsc2UgfCB1bmRlZmluZWQge1xuICAgIGlmIChjb25maWcgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoY29uZmlnID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB7IGNvdW50OiBjb25maWcuY291bnQgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZUZsb3dMb2dDb25maWcoY29uZmlnOiBGbG93TG9nQ29uZmlnIHwgZmFsc2UgfCB1bmRlZmluZWQpOlxuICAgIHwge1xuICAgICAgICBkZXN0aW5hdGlvbj86IFwiY2xvdWR3YXRjaFwiIHwgXCJzM1wiO1xuICAgICAgICByZXRlbnRpb25EYXlzPzogbnVtYmVyO1xuICAgICAgICB0cmFmZmljVHlwZT86IFwiQUxMXCIgfCBcIkFDQ0VQVFwiIHwgXCJSRUpFQ1RcIjtcbiAgICAgIH1cbiAgICB8IGZhbHNlXG4gICAgfCB1bmRlZmluZWQge1xuICAgIGlmIChjb25maWcgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoY29uZmlnID09PSBmYWxzZSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB7XG4gICAgICBkZXN0aW5hdGlvbjogY29uZmlnLmRlc3RpbmF0aW9uLFxuICAgICAgcmV0ZW50aW9uRGF5czogY29uZmlnLnJldGVudGlvbkRheXMsXG4gICAgICB0cmFmZmljVHlwZTogY29uZmlnLnRyYWZmaWNUeXBlXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZUVuZHBvaW50c0NvbmZpZyhcbiAgICBjb25maWc6IFZwY0VuZHBvaW50c0NvbmZpZyB8IGZhbHNlIHwgdW5kZWZpbmVkXG4gICk6XG4gICAgfCB7XG4gICAgICAgIGdhdGV3YXk/OiB7IHMzPzogYm9vbGVhbjsgZHluYW1vZGI/OiBib29sZWFuIH0gfCBmYWxzZTtcbiAgICAgICAgaW50ZXJmYWNlPzpcbiAgICAgICAgICB8IHtcbiAgICAgICAgICAgICAgZWNyPzogYm9vbGVhbjtcbiAgICAgICAgICAgICAgc2VjcmV0c01hbmFnZXI/OiBib29sZWFuO1xuICAgICAgICAgICAgICBrbXM/OiBib29sZWFuO1xuICAgICAgICAgICAgICBjbG91ZHdhdGNoTG9ncz86IGJvb2xlYW47XG4gICAgICAgICAgICAgIHNzbT86IGJvb2xlYW47XG4gICAgICAgICAgICAgIHN0cz86IGJvb2xlYW47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfCBmYWxzZTtcbiAgICAgIH1cbiAgICB8IGZhbHNlXG4gICAgfCB1bmRlZmluZWQge1xuICAgIGlmIChjb25maWcgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBEZWZhdWx0OiBnYXRld2F5IGVuZHBvaW50cyBlbmFibGVkXG4gICAgaWYgKGNvbmZpZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4geyBnYXRld2F5OiB7IHMzOiB0cnVlLCBkeW5hbW9kYjogdHJ1ZSB9IH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGdhdGV3YXk6XG4gICAgICAgIGNvbmZpZy5nYXRld2F5ID09PSBmYWxzZVxuICAgICAgICAgID8gZmFsc2VcbiAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgczM6IGNvbmZpZy5nYXRld2F5Py5zMyA/PyB0cnVlLFxuICAgICAgICAgICAgICBkeW5hbW9kYjogY29uZmlnLmdhdGV3YXk/LmR5bmFtb2RiID8/IHRydWVcbiAgICAgICAgICAgIH0sXG4gICAgICBpbnRlcmZhY2U6IGNvbmZpZy5pbnRlcmZhY2UgPT09IGZhbHNlID8gZmFsc2UgOiBjb25maWcuaW50ZXJmYWNlXG4gICAgfTtcbiAgfVxuXG4gIGdldFZwYygpOiBJVnBjIHtcbiAgICByZXR1cm4gdGhpcy52cGM7XG4gIH1cbn1cbiJdfQ==
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV0d29yay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2xpYi9wYXR0ZXJucy9hd3MvbmV0d29yay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQ0FBdUM7QUFDdkMsNkNBQWlDO0FBSWpDLDREQUF3RTtBQXVFeEUsU0FBUyxvQkFBb0IsQ0FBQyxLQUFvQjtJQUNoRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3pFLE9BQU8sQ0FBQyxJQUFJLENBQ1YsNkRBQTZELEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FDN0UsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUNFLE9BQU8sS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRO1FBQ3JDLEtBQUssQ0FBQyxXQUFXLEtBQUssSUFBSTtRQUMxQixLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssS0FBSyxTQUFTLEVBQ3JDLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUNqQyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQ1YseUNBQXlDLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxxQkFBcUIsTUFBTSxJQUFJLENBQ2hHLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSyxDQUFDLGNBQWMsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDckQsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBYSxjQUFjO0lBQ3pCLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFB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SUFBSSxNQUFNLEtBQUssS0FBSztZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRW5DLHFDQUFxQztRQUNyQyxJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN6QixPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNuRCxDQUFDO1FBRUQsT0FBTztZQUNMLE9BQU8sRUFDTCxNQUFNLENBQUMsT0FBTyxLQUFLLEtBQUs7Z0JBQ3RCLENBQUMsQ0FBQyxLQUFLO2dCQUNQLENBQUMsQ0FBQztvQkFDRSxFQUFFLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxFQUFFLElBQUksSUFBSTtvQkFDOUIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsUUFBUSxJQUFJLElBQUk7aUJBQzNDO1lBQ1AsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTO1NBQ2pFLENBQUM7SUFDSixDQUFDO0lBRUQsTUFBTTtRQUNKLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNsQixDQUFDO0NBQ0Y7QUF0R0QsMEJBc0dDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IEZuIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyB0eXBlIElWcGMgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuXG5pbXBvcnQgdHlwZSBBcHAgZnJvbSBcIi4uLy4uL2FwcFwiO1xuaW1wb3J0IHsgVnBjLCB0eXBlIFZwY1Byb3BzIH0gZnJvbSBcIi4uLy4uL3Jlc291cmNlcy9hd3MvbmV0d29ya2luZy92cGNcIjtcblxuZXhwb3J0IGludGVyZmFjZSBOYXRDb25maWcge1xuICBjb3VudD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGbG93TG9nQ29uZmlnIHtcbiAgZGVzdGluYXRpb24/OiBcImNsb3Vkd2F0Y2hcIiB8IFwiczNcIjtcbiAgcmV0ZW50aW9uRGF5cz86IG51bWJlcjtcbiAgdHJhZmZpY1R5cGU/OiBcIkFMTFwiIHwgXCJBQ0NFUFRcIiB8IFwiUkVKRUNUXCI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2F0ZXdheUVuZHBvaW50c0NvbmZpZyB7XG4gIHMzPzogYm9vbGVhbjtcbiAgZHluYW1vZGI/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEludGVyZmFjZUVuZHBvaW50c0NvbmZpZyB7XG4gIGVjcj86IGJvb2xlYW47XG4gIHNlY3JldHNNYW5hZ2VyPzogYm9vbGVhbjtcbiAga21zPzogYm9vbGVhbjtcbiAgY2xvdWR3YXRjaExvZ3M/OiBib29sZWFuO1xuICBzc20/OiBib29sZWFuO1xuICBzdHM/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZwY0VuZHBvaW50c0NvbmZpZyB7XG4gIGdhdGV3YXk/OiBHYXRld2F5RW5kcG9pbnRzQ29uZmlnIHwgZmFsc2U7XG4gIGludGVyZmFjZT86IEludGVyZmFjZUVuZHBvaW50c0NvbmZpZyB8IGZhbHNlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN1Ym5ldENvbmZpZyB7XG4gIGNpZHJNYXNrPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN1Ym5ldHNDb25maWcge1xuICBwdWJsaWM/OiBTdWJuZXRDb25maWc7XG4gIHByaXZhdGU/OiBTdWJuZXRDb25maWc7XG4gIGlzb2xhdGVkPzogU3VibmV0Q29uZmlnIHwgZmFsc2U7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNpdEdhdGV3YXlDb25maWcge1xuICBpZDogc3RyaW5nO1xufVxuXG4vKipcbiAqIE5ldHdvcmsgKFZQQykgY29uZmlndXJhdGlvbi5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gTWluaW1hbCBjb3N0IFZQQyAobm8gTkFULCBnYXRld2F5IGVuZHBvaW50cyBvbmx5KVxuICogeyBuYXRHYXRld2F5czogZmFsc2UgfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBQcm9kdWN0aW9uIFZQQyB3aXRoIDEgTkFUIGdhdGV3YXlcbiAqIHsgbmF0R2F0ZXdheXM6IHsgY291bnQ6IDEgfSwgZmxvd0xvZ3M6IHt9IH1cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gSGlnaC1hdmFpbGFiaWxpdHkgVlBDIHdpdGggaW50ZXJmYWNlIGVuZHBvaW50c1xuICogeyBtYXhBenM6IDMsIG5hdEdhdGV3YXlzOiB7IGNvdW50OiAzIH0sIHZwY0VuZHBvaW50czogeyBpbnRlcmZhY2U6IHsgZWNyOiB0cnVlIH0gfSB9XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSU5ldHdvcmtQcm9wcyB7XG4gIHZwY05hbWU/OiBzdHJpbmc7XG4gIG1heEF6cz86IG51bWJlcjtcbiAgY2lkck1hc2s/OiBudW1iZXI7XG4gIG5hdEdhdGV3YXlzPzogTmF0Q29uZmlnIHwgZmFsc2U7XG4gIGZsb3dMb2dzPzogRmxvd0xvZ0NvbmZpZyB8IGZhbHNlO1xuICB2cGNFbmRwb2ludHM/OiBWcGNFbmRwb2ludHNDb25maWcgfCBmYWxzZTtcbiAgc3VibmV0cz86IFN1Ym5ldHNDb25maWc7XG4gIHRyYW5zaXRHYXRld2F5PzogVHJhbnNpdEdhdGV3YXlDb25maWc7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlTmV0d29ya1Byb3BzKHByb3BzOiBJTmV0d29ya1Byb3BzKTogdm9pZCB7XG4gIGlmIChwcm9wcy5tYXhBenMgIT09IHVuZGVmaW5lZCAmJiAocHJvcHMubWF4QXpzIDwgMSB8fCBwcm9wcy5tYXhBenMgPiAzKSkge1xuICAgIGNvbnNvbGUud2FybihcbiAgICAgIGBbRmphbGxdIFdhcm5pbmc6ICdtYXhBenMnIHNob3VsZCBiZSBiZXR3ZWVuIDEgYW5kIDMuIEdvdDogJHtwcm9wcy5tYXhBenN9LmBcbiAgICApO1xuICB9XG5cbiAgaWYgKFxuICAgIHR5cGVvZiBwcm9wcy5uYXRHYXRld2F5cyA9PT0gXCJvYmplY3RcIiAmJlxuICAgIHByb3BzLm5hdEdhdGV3YXlzICE9PSBudWxsICYmXG4gICAgcHJvcHMubmF0R2F0ZXdheXMuY291bnQgIT09IHVuZGVmaW5lZFxuICApIHtcbiAgICBjb25zdCBtYXhBenMgPSBwcm9wcy5tYXhBenMgPz8gMztcbiAgICBpZiAocHJvcHMubmF0R2F0ZXdheXMuY291bnQgPiBtYXhBenMpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFtGamFsbF0gV2FybmluZzogJ25hdEdhdGV3YXlzLmNvdW50JyAoJHtwcm9wcy5uYXRHYXRld2F5cy5jb3VudH0pIGV4Y2VlZHMgbWF4QXpzICgke21heEF6c30pLmBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3BzLnRyYW5zaXRHYXRld2F5ICYmICFwcm9wcy50cmFuc2l0R2F0ZXdheS5pZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlRyYW5zaXQgR2F0ZXdheSBjb25maWd1cmF0aW9uIHJlcXVpcmVzICdpZCcuXCIpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOZXR3b3JrRmFjdG9yeSB7XG4gIHN0YXRpYyBidWlsZChpZDogc3RyaW5nLCBwcm9wczogSU5ldHdvcmtQcm9wcykge1xuICAgIHJldHVybiAoYXBwOiBBcHAsIHNjb3BlOiBDb25zdHJ1Y3QpID0+IHtcbiAgICAgIHZhbGlkYXRlTmV0d29ya1Byb3BzKHByb3BzKTtcbiAgICAgIHJldHVybiBuZXcgTmV0d29yayhzY29wZSwgaWQsIHByb3BzLCBhcHApO1xuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5ldHdvcmsgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgcmVhZG9ubHkgdnBjOiBWcGM7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IElOZXR3b3JrUHJvcHMsIGFwcDogQXBwKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICB0aGlzLnZwYyA9IHRoaXMuY3JlYXRlVnBjKGlkLCBwcm9wcywgYXBwKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVnBjKGlkOiBzdHJpbmcsIHByb3BzOiBJTmV0d29ya1Byb3BzLCBhcHA6IEFwcCk6IFZwYyB7XG4gICAgY29uc3QgYWNjb3VudElkID1cbiAgICAgIGFwcC5ub2RlLnRyeUdldENvbnRleHQoXCJhY2NvdW50SWRcIikgfHwgcHJvY2Vzcy5lbnYuQ0RLX0RFRkFVTFRfQUNDT1VOVDtcbiAgICBjb25zdCByZWdpb24gPSBwcm9jZXNzLmVudi5DREtfREVGQVVMVF9SRUdJT047XG4gICAgY29uc3QgaXNNYW5hZ2VkQWNjb3VudCA9XG4gICAgICBhcHAubm9kZS50cnlHZXRDb250ZXh0KFwibWFuYWdlZEFjY291bnRcIikgPT09IFwidHJ1ZVwiO1xuXG4gICAgbGV0IGlwdjRJcGFtUG9vbElkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGlzTWFuYWdlZEFjY291bnQgJiYgYWNjb3VudElkICYmIHJlZ2lvbikge1xuICAgICAgY29uc3QgcmVnaW9uU3VmZml4ID0gcmVnaW9uLnJlcGxhY2UoLy0vZywgXCJcIik7XG4gICAgICBpcHY0SXBhbVBvb2xJZCA9IEZuLmltcG9ydFZhbHVlKGBJcGFtUG9vbElkJHthY2NvdW50SWR9JHtyZWdpb25TdWZmaXh9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgdnBjUHJvcHM6IFZwY1Byb3BzID0ge1xuICAgICAgdnBjTmFtZTogcHJvcHMudnBjTmFtZSxcbiAgICAgIGFjY291bnRJZCxcbiAgICAgIHJlZ2lvbixcbiAgICAgIGlwdjRJcGFtUG9vbElkLFxuICAgICAgbWF4QXpzOiBwcm9wcy5tYXhBenMsXG4gICAgICB2cGNDaWRyTWFzazogcHJvcHMuY2lkck1hc2ssXG4gICAgICBzdWJuZXRDaWRyTWFzazogcHJvcHMuc3VibmV0cz8ucHJpdmF0ZT8uY2lkck1hc2ssXG4gICAgICBuYXRHYXRld2F5Q29uZmlnOiB0aGlzLnJlc29sdmVOYXRDb25maWcocHJvcHMubmF0R2F0ZXdheXMpLFxuICAgICAgZmxvd0xvZ0NvbmZpZzogdGhpcy5yZXNvbHZlRmxvd0xvZ0NvbmZpZyhwcm9wcy5mbG93TG9ncyksXG4gICAgICBlbmRwb2ludHNDb25maWc6IHRoaXMucmVzb2x2ZUVuZHBvaW50c0NvbmZpZyhwcm9wcy52cGNFbmRwb2ludHMpXG4gICAgfTtcblxuICAgIHJldHVybiBuZXcgVnBjKHRoaXMsIGlkLCB2cGNQcm9wcyk7XG4gIH1cblxuICBwcml2YXRlIHJlc29sdmVOYXRDb25maWcoXG4gICAgY29uZmlnOiBOYXRDb25maWcgfCBmYWxzZSB8IHVuZGVmaW5lZFxuICApOiB7IGNvdW50PzogbnVtYmVyIH0gfCBmYWxzZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGNvbmZpZyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChjb25maWcgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHsgY291bnQ6IGNvbmZpZy5jb3VudCB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlRmxvd0xvZ0NvbmZpZyhjb25maWc6IEZsb3dMb2dDb25maWcgfCBmYWxzZSB8IHVuZGVmaW5lZCk6XG4gICAgfCB7XG4gICAgICAgIGRlc3RpbmF0aW9uPzogXCJjbG91ZHdhdGNoXCIgfCBcInMzXCI7XG4gICAgICAgIHJldGVudGlvbkRheXM/OiBudW1iZXI7XG4gICAgICAgIHRyYWZmaWNUeXBlPzogXCJBTExcIiB8IFwiQUNDRVBUXCIgfCBcIlJFSkVDVFwiO1xuICAgICAgfVxuICAgIHwgZmFsc2VcbiAgICB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGNvbmZpZyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmIChjb25maWcgPT09IGZhbHNlKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlc3RpbmF0aW9uOiBjb25maWcuZGVzdGluYXRpb24sXG4gICAgICByZXRlbnRpb25EYXlzOiBjb25maWcucmV0ZW50aW9uRGF5cyxcbiAgICAgIHRyYWZmaWNUeXBlOiBjb25maWcudHJhZmZpY1R5cGVcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlRW5kcG9pbnRzQ29uZmlnKFxuICAgIGNvbmZpZzogVnBjRW5kcG9pbnRzQ29uZmlnIHwgZmFsc2UgfCB1bmRlZmluZWRcbiAgKTpcbiAgICB8IHtcbiAgICAgICAgZ2F0ZXdheT86IHsgczM/OiBib29sZWFuOyBkeW5hbW9kYj86IGJvb2xlYW4gfSB8IGZhbHNlO1xuICAgICAgICBpbnRlcmZhY2U/OlxuICAgICAgICAgIHwge1xuICAgICAgICAgICAgICBlY3I/OiBib29sZWFuO1xuICAgICAgICAgICAgICBzZWNyZXRzTWFuYWdlcj86IGJvb2xlYW47XG4gICAgICAgICAgICAgIGttcz86IGJvb2xlYW47XG4gICAgICAgICAgICAgIGNsb3Vkd2F0Y2hMb2dzPzogYm9vbGVhbjtcbiAgICAgICAgICAgICAgc3NtPzogYm9vbGVhbjtcbiAgICAgICAgICAgICAgc3RzPzogYm9vbGVhbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB8IGZhbHNlO1xuICAgICAgfVxuICAgIHwgZmFsc2VcbiAgICB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGNvbmZpZyA9PT0gZmFsc2UpIHJldHVybiBmYWxzZTtcblxuICAgIC8vIERlZmF1bHQ6IGdhdGV3YXkgZW5kcG9pbnRzIGVuYWJsZWRcbiAgICBpZiAoY29uZmlnID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB7IGdhdGV3YXk6IHsgczM6IHRydWUsIGR5bmFtb2RiOiB0cnVlIH0gfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZ2F0ZXdheTpcbiAgICAgICAgY29uZmlnLmdhdGV3YXkgPT09IGZhbHNlXG4gICAgICAgICAgPyBmYWxzZVxuICAgICAgICAgIDoge1xuICAgICAgICAgICAgICBzMzogY29uZmlnLmdhdGV3YXk/LnMzID8/IHRydWUsXG4gICAgICAgICAgICAgIGR5bmFtb2RiOiBjb25maWcuZ2F0ZXdheT8uZHluYW1vZGIgPz8gdHJ1ZVxuICAgICAgICAgICAgfSxcbiAgICAgIGludGVyZmFjZTogY29uZmlnLmludGVyZmFjZSA9PT0gZmFsc2UgPyBmYWxzZSA6IGNvbmZpZy5pbnRlcmZhY2VcbiAgICB9O1xuICB9XG5cbiAgZ2V0VnBjKCk6IElWcGMge1xuICAgIHJldHVybiB0aGlzLnZwYztcbiAgfVxufVxuIl19
@@ -0,0 +1,20 @@
1
+ import { Construct } from "constructs";
2
+ /**
3
+ * Props for CapacityProviderDrainWaiter
4
+ */
5
+ interface CapacityProviderDrainWaiterProps {
6
+ /** The ECS cluster name */
7
+ clusterName: string;
8
+ /** The capacity provider name to wait for */
9
+ capacityProviderName: string;
10
+ }
11
+ /**
12
+ * Custom resource that waits for ECS services to drain before allowing
13
+ * capacity provider disassociation.
14
+ *
15
+ * @see https://github.com/aws/aws-cdk/issues/14732
16
+ */
17
+ export declare class CapacityProviderDrainWaiter extends Construct {
18
+ constructor(scope: Construct, id: string, props: CapacityProviderDrainWaiterProps);
19
+ }
20
+ export {};
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CapacityProviderDrainWaiter = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
6
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
7
+ const constructs_1 = require("constructs");
8
+ const customResource_1 = require("../utilities/customResource");
9
+ /**
10
+ * Custom resource that waits for ECS services to drain before allowing
11
+ * capacity provider disassociation.
12
+ *
13
+ * @see https://github.com/aws/aws-cdk/issues/14732
14
+ */
15
+ class CapacityProviderDrainWaiter extends constructs_1.Construct {
16
+ constructor(scope, id, props) {
17
+ super(scope, id);
18
+ const { clusterName, capacityProviderName } = props;
19
+ // Lambda inline code for the custom resource handler
20
+ const handlerCode = `
21
+ const { ECSClient, ListServicesCommand, DescribeServicesCommand, PutClusterCapacityProvidersCommand, DescribeClustersCommand } = require("@aws-sdk/client-ecs");
22
+
23
+ const ecsClient = new ECSClient({});
24
+ const POLL_INTERVAL_MS = 5000;
25
+ const MAX_WAIT_MS = 300000; // 5 minutes
26
+
27
+ async function sleep(ms) {
28
+ return new Promise(resolve => setTimeout(resolve, ms));
29
+ }
30
+
31
+ async function getClusterCapacityProviders(clusterName) {
32
+ const response = await ecsClient.send(new DescribeClustersCommand({
33
+ clusters: [clusterName]
34
+ }));
35
+ return response.clusters?.[0]?.capacityProviders || [];
36
+ }
37
+
38
+ async function waitForServicesDrained(clusterName, capacityProviderName) {
39
+ const startTime = Date.now();
40
+
41
+ while (Date.now() - startTime < MAX_WAIT_MS) {
42
+ // List all services in the cluster
43
+ const listResponse = await ecsClient.send(new ListServicesCommand({
44
+ cluster: clusterName,
45
+ maxResults: 100
46
+ }));
47
+
48
+ const serviceArns = listResponse.serviceArns || [];
49
+
50
+ if (serviceArns.length === 0) {
51
+ console.log("No services found in cluster - drain complete");
52
+ return true;
53
+ }
54
+
55
+ // Describe services to check running counts
56
+ const describeResponse = await ecsClient.send(new DescribeServicesCommand({
57
+ cluster: clusterName,
58
+ services: serviceArns
59
+ }));
60
+
61
+ const activeServices = (describeResponse.services || []).filter(svc => {
62
+ // Check if service uses this capacity provider
63
+ const usesCapacityProvider = (svc.capacityProviderStrategy || [])
64
+ .some(strategy => strategy.capacityProvider === capacityProviderName);
65
+
66
+ // Only care about services using this capacity provider that still have running tasks
67
+ return usesCapacityProvider && svc.runningCount > 0;
68
+ });
69
+
70
+ if (activeServices.length === 0) {
71
+ console.log("All services using capacity provider have drained");
72
+ return true;
73
+ }
74
+
75
+ console.log(\`Waiting for \${activeServices.length} services to drain: \${activeServices.map(s => s.serviceName).join(", ")}\`);
76
+ await sleep(POLL_INTERVAL_MS);
77
+ }
78
+
79
+ console.log("Timeout waiting for services to drain, proceeding anyway");
80
+ return false;
81
+ }
82
+
83
+ async function disassociateCapacityProvider(clusterName, capacityProviderName) {
84
+ try {
85
+ // Get current capacity providers
86
+ const currentProviders = await getClusterCapacityProviders(clusterName);
87
+
88
+ // Filter out the one we want to remove
89
+ const remainingProviders = currentProviders.filter(cp => cp !== capacityProviderName);
90
+
91
+ if (remainingProviders.length === currentProviders.length) {
92
+ console.log(\`Capacity provider \${capacityProviderName} not associated with cluster\`);
93
+ return true;
94
+ }
95
+
96
+ // Ensure we keep at least FARGATE as a provider (required by ECS)
97
+ if (remainingProviders.length === 0) {
98
+ remainingProviders.push("FARGATE");
99
+ }
100
+
101
+ console.log(\`Disassociating \${capacityProviderName} from cluster. Remaining: \${remainingProviders.join(", ")}\`);
102
+
103
+ await ecsClient.send(new PutClusterCapacityProvidersCommand({
104
+ cluster: clusterName,
105
+ capacityProviders: remainingProviders,
106
+ defaultCapacityProviderStrategy: []
107
+ }));
108
+
109
+ console.log("Successfully disassociated capacity provider");
110
+ return true;
111
+ } catch (error) {
112
+ // If cluster or capacity provider doesn't exist, that's fine (already deleted)
113
+ if (error.name === "ClusterNotFoundException" ||
114
+ error.name === "ResourceNotFoundException" ||
115
+ error.message?.includes("does not exist")) {
116
+ console.log("Cluster or capacity provider not found - already cleaned up");
117
+ return true;
118
+ }
119
+ throw error;
120
+ }
121
+ }
122
+
123
+ exports.handler = async (event) => {
124
+ console.log("Event:", JSON.stringify(event, null, 2));
125
+
126
+ const clusterName = event.ResourceProperties.ClusterName;
127
+ const capacityProviderName = event.ResourceProperties.CapacityProviderName;
128
+ const requestType = event.RequestType;
129
+
130
+ try {
131
+ if (requestType === "Delete") {
132
+ console.log(\`Handling DELETE for capacity provider \${capacityProviderName} in cluster \${clusterName}\`);
133
+
134
+ // Wait for services to drain
135
+ await waitForServicesDrained(clusterName, capacityProviderName);
136
+
137
+ // Disassociate capacity provider from cluster
138
+ await disassociateCapacityProvider(clusterName, capacityProviderName);
139
+ }
140
+
141
+ // Return success for all request types
142
+ return {
143
+ PhysicalResourceId: \`\${clusterName}-\${capacityProviderName}-drain-waiter\`,
144
+ Data: {
145
+ Message: \`\${requestType} completed successfully\`
146
+ }
147
+ };
148
+ } catch (error) {
149
+ console.error("Error:", error);
150
+ throw error;
151
+ }
152
+ };
153
+ `;
154
+ new customResource_1.CustomResource(this, "DrainWaiter", {
155
+ runtime: aws_lambda_1.Runtime.NODEJS_22_X,
156
+ inlineCode: handlerCode,
157
+ timeout: aws_cdk_lib_1.Duration.minutes(6),
158
+ lambdaDescription: `Waits for ECS services to drain before capacity provider disassociation`,
159
+ roleDescription: `Role for ${clusterName} capacity provider drain waiter`,
160
+ inlinePolicy: [
161
+ new aws_iam_1.PolicyStatement({
162
+ effect: aws_iam_1.Effect.ALLOW,
163
+ actions: [
164
+ "ecs:ListServices",
165
+ "ecs:DescribeServices",
166
+ "ecs:DescribeClusters",
167
+ "ecs:PutClusterCapacityProviders"
168
+ ],
169
+ resources: ["*"]
170
+ })
171
+ ],
172
+ properties: {
173
+ ClusterName: clusterName,
174
+ CapacityProviderName: capacityProviderName
175
+ }
176
+ });
177
+ }
178
+ }
179
+ exports.CapacityProviderDrainWaiter = CapacityProviderDrainWaiter;
180
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwYWNpdHlQcm92aWRlckRyYWluV2FpdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGliL3Jlc291cmNlcy9hd3MvY29tcHV0ZS9jYXBhY2l0eVByb3ZpZGVyRHJhaW5XYWl0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXVDO0FBQ3ZDLGlEQUE4RDtBQUM5RCx1REFBaUQ7QUFDakQsMkNBQXVDO0FBQ3ZDLGdFQUE2RDtBQVk3RDs7Ozs7R0FLRztBQUNILE1BQWEsMkJBQTRCLFNBQVEsc0JBQVM7SUFDeEQsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ1YsS0FBdUM7UUFFdkMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixNQUFNLEVBQUUsV0FBVyxFQUFFLG9CQUFvQixFQUFFLEdBQUcsS0FBSyxDQUFDO1FBRXBELHFEQUFxRDtRQUNyRCxNQUFNLFdBQVcsR0FBRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXFJdkIsQ0FBQztRQUVFLElBQUksK0JBQWMsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO1lBQ3RDLE9BQU8sRUFBRSxvQkFBTyxDQUFDLFdBQVc7WUFDNUIsVUFBVSxFQUFFLFdBQVc7WUFDdkIsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUM1QixpQkFBaUIsRUFBRSx5RUFBeUU7WUFDNUYsZUFBZSxFQUFFLFlBQVksV0FBVyxpQ0FBaUM7WUFDekUsWUFBWSxFQUFFO2dCQUNaLElBQUkseUJBQWUsQ0FBQztvQkFDbEIsTUFBTSxFQUFFLGdCQUFNLENBQUMsS0FBSztvQkFDcEIsT0FBTyxFQUFFO3dCQUNQLGtCQUFrQjt3QkFDbEIsc0JBQXNCO3dCQUN0QixzQkFBc0I7d0JBQ3RCLGlDQUFpQztxQkFDbEM7b0JBQ0QsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDO2lCQUNqQixDQUFDO2FBQ0g7WUFDRCxVQUFVLEVBQUU7Z0JBQ1YsV0FBVyxFQUFFLFdBQVc7Z0JBQ3hCLG9CQUFvQixFQUFFLG9CQUFvQjthQUMzQztTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQTFLRCxrRUEwS0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEdXJhdGlvbiB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgUG9saWN5U3RhdGVtZW50LCBFZmZlY3QgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiO1xuaW1wb3J0IHsgUnVudGltZSB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHsgQ3VzdG9tUmVzb3VyY2UgfSBmcm9tIFwiLi4vdXRpbGl0aWVzL2N1c3RvbVJlc291cmNlXCI7XG5cbi8qKlxuICogUHJvcHMgZm9yIENhcGFjaXR5UHJvdmlkZXJEcmFpbldhaXRlclxuICovXG5pbnRlcmZhY2UgQ2FwYWNpdHlQcm92aWRlckRyYWluV2FpdGVyUHJvcHMge1xuICAvKiogVGhlIEVDUyBjbHVzdGVyIG5hbWUgKi9cbiAgY2x1c3Rlck5hbWU6IHN0cmluZztcbiAgLyoqIFRoZSBjYXBhY2l0eSBwcm92aWRlciBuYW1lIHRvIHdhaXQgZm9yICovXG4gIGNhcGFjaXR5UHJvdmlkZXJOYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ3VzdG9tIHJlc291cmNlIHRoYXQgd2FpdHMgZm9yIEVDUyBzZXJ2aWNlcyB0byBkcmFpbiBiZWZvcmUgYWxsb3dpbmdcbiAqIGNhcGFjaXR5IHByb3ZpZGVyIGRpc2Fzc29jaWF0aW9uLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL2lzc3Vlcy8xNDczMlxuICovXG5leHBvcnQgY2xhc3MgQ2FwYWNpdHlQcm92aWRlckRyYWluV2FpdGVyIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBDYXBhY2l0eVByb3ZpZGVyRHJhaW5XYWl0ZXJQcm9wc1xuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3QgeyBjbHVzdGVyTmFtZSwgY2FwYWNpdHlQcm92aWRlck5hbWUgfSA9IHByb3BzO1xuXG4gICAgLy8gTGFtYmRhIGlubGluZSBjb2RlIGZvciB0aGUgY3VzdG9tIHJlc291cmNlIGhhbmRsZXJcbiAgICBjb25zdCBoYW5kbGVyQ29kZSA9IGBcbmNvbnN0IHsgRUNTQ2xpZW50LCBMaXN0U2VydmljZXNDb21tYW5kLCBEZXNjcmliZVNlcnZpY2VzQ29tbWFuZCwgUHV0Q2x1c3RlckNhcGFjaXR5UHJvdmlkZXJzQ29tbWFuZCwgRGVzY3JpYmVDbHVzdGVyc0NvbW1hbmQgfSA9IHJlcXVpcmUoXCJAYXdzLXNkay9jbGllbnQtZWNzXCIpO1xuXG5jb25zdCBlY3NDbGllbnQgPSBuZXcgRUNTQ2xpZW50KHt9KTtcbmNvbnN0IFBPTExfSU5URVJWQUxfTVMgPSA1MDAwO1xuY29uc3QgTUFYX1dBSVRfTVMgPSAzMDAwMDA7IC8vIDUgbWludXRlc1xuXG5hc3luYyBmdW5jdGlvbiBzbGVlcChtcykge1xuICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldENsdXN0ZXJDYXBhY2l0eVByb3ZpZGVycyhjbHVzdGVyTmFtZSkge1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGVjc0NsaWVudC5zZW5kKG5ldyBEZXNjcmliZUNsdXN0ZXJzQ29tbWFuZCh7XG4gICAgY2x1c3RlcnM6IFtjbHVzdGVyTmFtZV1cbiAgfSkpO1xuICByZXR1cm4gcmVzcG9uc2UuY2x1c3RlcnM/LlswXT8uY2FwYWNpdHlQcm92aWRlcnMgfHwgW107XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JTZXJ2aWNlc0RyYWluZWQoY2x1c3Rlck5hbWUsIGNhcGFjaXR5UHJvdmlkZXJOYW1lKSB7XG4gIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgd2hpbGUgKERhdGUubm93KCkgLSBzdGFydFRpbWUgPCBNQVhfV0FJVF9NUykge1xuICAgIC8vIExpc3QgYWxsIHNlcnZpY2VzIGluIHRoZSBjbHVzdGVyXG4gICAgY29uc3QgbGlzdFJlc3BvbnNlID0gYXdhaXQgZWNzQ2xpZW50LnNlbmQobmV3IExpc3RTZXJ2aWNlc0NvbW1hbmQoe1xuICAgICAgY2x1c3RlcjogY2x1c3Rlck5hbWUsXG4gICAgICBtYXhSZXN1bHRzOiAxMDBcbiAgICB9KSk7XG5cbiAgICBjb25zdCBzZXJ2aWNlQXJucyA9IGxpc3RSZXNwb25zZS5zZXJ2aWNlQXJucyB8fCBbXTtcblxuICAgIGlmIChzZXJ2aWNlQXJucy5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiTm8gc2VydmljZXMgZm91bmQgaW4gY2x1c3RlciAtIGRyYWluIGNvbXBsZXRlXCIpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gRGVzY3JpYmUgc2VydmljZXMgdG8gY2hlY2sgcnVubmluZyBjb3VudHNcbiAgICBjb25zdCBkZXNjcmliZVJlc3BvbnNlID0gYXdhaXQgZWNzQ2xpZW50LnNlbmQobmV3IERlc2NyaWJlU2VydmljZXNDb21tYW5kKHtcbiAgICAgIGNsdXN0ZXI6IGNsdXN0ZXJOYW1lLFxuICAgICAgc2VydmljZXM6IHNlcnZpY2VBcm5zXG4gICAgfSkpO1xuXG4gICAgY29uc3QgYWN0aXZlU2VydmljZXMgPSAoZGVzY3JpYmVSZXNwb25zZS5zZXJ2aWNlcyB8fCBbXSkuZmlsdGVyKHN2YyA9PiB7XG4gICAgICAvLyBDaGVjayBpZiBzZXJ2aWNlIHVzZXMgdGhpcyBjYXBhY2l0eSBwcm92aWRlclxuICAgICAgY29uc3QgdXNlc0NhcGFjaXR5UHJvdmlkZXIgPSAoc3ZjLmNhcGFjaXR5UHJvdmlkZXJTdHJhdGVneSB8fCBbXSlcbiAgICAgICAgLnNvbWUoc3RyYXRlZ3kgPT4gc3RyYXRlZ3kuY2FwYWNpdHlQcm92aWRlciA9PT0gY2FwYWNpdHlQcm92aWRlck5hbWUpO1xuXG4gICAgICAvLyBPbmx5IGNhcmUgYWJvdXQgc2VydmljZXMgdXNpbmcgdGhpcyBjYXBhY2l0eSBwcm92aWRlciB0aGF0IHN0aWxsIGhhdmUgcnVubmluZyB0YXNrc1xuICAgICAgcmV0dXJuIHVzZXNDYXBhY2l0eVByb3ZpZGVyICYmIHN2Yy5ydW5uaW5nQ291bnQgPiAwO1xuICAgIH0pO1xuXG4gICAgaWYgKGFjdGl2ZVNlcnZpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29uc29sZS5sb2coXCJBbGwgc2VydmljZXMgdXNpbmcgY2FwYWNpdHkgcHJvdmlkZXIgaGF2ZSBkcmFpbmVkXCIpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coXFxgV2FpdGluZyBmb3IgXFwke2FjdGl2ZVNlcnZpY2VzLmxlbmd0aH0gc2VydmljZXMgdG8gZHJhaW46IFxcJHthY3RpdmVTZXJ2aWNlcy5tYXAocyA9PiBzLnNlcnZpY2VOYW1lKS5qb2luKFwiLCBcIil9XFxgKTtcbiAgICBhd2FpdCBzbGVlcChQT0xMX0lOVEVSVkFMX01TKTtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKFwiVGltZW91dCB3YWl0aW5nIGZvciBzZXJ2aWNlcyB0byBkcmFpbiwgcHJvY2VlZGluZyBhbnl3YXlcIik7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGlzYXNzb2NpYXRlQ2FwYWNpdHlQcm92aWRlcihjbHVzdGVyTmFtZSwgY2FwYWNpdHlQcm92aWRlck5hbWUpIHtcbiAgdHJ5IHtcbiAgICAvLyBHZXQgY3VycmVudCBjYXBhY2l0eSBwcm92aWRlcnNcbiAgICBjb25zdCBjdXJyZW50UHJvdmlkZXJzID0gYXdhaXQgZ2V0Q2x1c3RlckNhcGFjaXR5UHJvdmlkZXJzKGNsdXN0ZXJOYW1lKTtcblxuICAgIC8vIEZpbHRlciBvdXQgdGhlIG9uZSB3ZSB3YW50IHRvIHJlbW92ZVxuICAgIGNvbnN0IHJlbWFpbmluZ1Byb3ZpZGVycyA9IGN1cnJlbnRQcm92aWRlcnMuZmlsdGVyKGNwID0+IGNwICE9PSBjYXBhY2l0eVByb3ZpZGVyTmFtZSk7XG5cbiAgICBpZiAocmVtYWluaW5nUHJvdmlkZXJzLmxlbmd0aCA9PT0gY3VycmVudFByb3ZpZGVycy5sZW5ndGgpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxcYENhcGFjaXR5IHByb3ZpZGVyIFxcJHtjYXBhY2l0eVByb3ZpZGVyTmFtZX0gbm90IGFzc29jaWF0ZWQgd2l0aCBjbHVzdGVyXFxgKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIEVuc3VyZSB3ZSBrZWVwIGF0IGxlYXN0IEZBUkdBVEUgYXMgYSBwcm92aWRlciAocmVxdWlyZWQgYnkgRUNTKVxuICAgIGlmIChyZW1haW5pbmdQcm92aWRlcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZW1haW5pbmdQcm92aWRlcnMucHVzaChcIkZBUkdBVEVcIik7XG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coXFxgRGlzYXNzb2NpYXRpbmcgXFwke2NhcGFjaXR5UHJvdmlkZXJOYW1lfSBmcm9tIGNsdXN0ZXIuIFJlbWFpbmluZzogXFwke3JlbWFpbmluZ1Byb3ZpZGVycy5qb2luKFwiLCBcIil9XFxgKTtcblxuICAgIGF3YWl0IGVjc0NsaWVudC5zZW5kKG5ldyBQdXRDbHVzdGVyQ2FwYWNpdHlQcm92aWRlcnNDb21tYW5kKHtcbiAgICAgIGNsdXN0ZXI6IGNsdXN0ZXJOYW1lLFxuICAgICAgY2FwYWNpdHlQcm92aWRlcnM6IHJlbWFpbmluZ1Byb3ZpZGVycyxcbiAgICAgIGRlZmF1bHRDYXBhY2l0eVByb3ZpZGVyU3RyYXRlZ3k6IFtdXG4gICAgfSkpO1xuXG4gICAgY29uc29sZS5sb2coXCJTdWNjZXNzZnVsbHkgZGlzYXNzb2NpYXRlZCBjYXBhY2l0eSBwcm92aWRlclwiKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBJZiBjbHVzdGVyIG9yIGNhcGFjaXR5IHByb3ZpZGVyIGRvZXNuJ3QgZXhpc3QsIHRoYXQncyBmaW5lIChhbHJlYWR5IGRlbGV0ZWQpXG4gICAgaWYgKGVycm9yLm5hbWUgPT09IFwiQ2x1c3Rlck5vdEZvdW5kRXhjZXB0aW9uXCIgfHxcbiAgICAgICAgZXJyb3IubmFtZSA9PT0gXCJSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uXCIgfHxcbiAgICAgICAgZXJyb3IubWVzc2FnZT8uaW5jbHVkZXMoXCJkb2VzIG5vdCBleGlzdFwiKSkge1xuICAgICAgY29uc29sZS5sb2coXCJDbHVzdGVyIG9yIGNhcGFjaXR5IHByb3ZpZGVyIG5vdCBmb3VuZCAtIGFscmVhZHkgY2xlYW5lZCB1cFwiKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG5leHBvcnRzLmhhbmRsZXIgPSBhc3luYyAoZXZlbnQpID0+IHtcbiAgY29uc29sZS5sb2coXCJFdmVudDpcIiwgSlNPTi5zdHJpbmdpZnkoZXZlbnQsIG51bGwsIDIpKTtcblxuICBjb25zdCBjbHVzdGVyTmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5DbHVzdGVyTmFtZTtcbiAgY29uc3QgY2FwYWNpdHlQcm92aWRlck5hbWUgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuQ2FwYWNpdHlQcm92aWRlck5hbWU7XG4gIGNvbnN0IHJlcXVlc3RUeXBlID0gZXZlbnQuUmVxdWVzdFR5cGU7XG5cbiAgdHJ5IHtcbiAgICBpZiAocmVxdWVzdFR5cGUgPT09IFwiRGVsZXRlXCIpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxcYEhhbmRsaW5nIERFTEVURSBmb3IgY2FwYWNpdHkgcHJvdmlkZXIgXFwke2NhcGFjaXR5UHJvdmlkZXJOYW1lfSBpbiBjbHVzdGVyIFxcJHtjbHVzdGVyTmFtZX1cXGApO1xuXG4gICAgICAvLyBXYWl0IGZvciBzZXJ2aWNlcyB0byBkcmFpblxuICAgICAgYXdhaXQgd2FpdEZvclNlcnZpY2VzRHJhaW5lZChjbHVzdGVyTmFtZSwgY2FwYWNpdHlQcm92aWRlck5hbWUpO1xuXG4gICAgICAvLyBEaXNhc3NvY2lhdGUgY2FwYWNpdHkgcHJvdmlkZXIgZnJvbSBjbHVzdGVyXG4gICAgICBhd2FpdCBkaXNhc3NvY2lhdGVDYXBhY2l0eVByb3ZpZGVyKGNsdXN0ZXJOYW1lLCBjYXBhY2l0eVByb3ZpZGVyTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIHN1Y2Nlc3MgZm9yIGFsbCByZXF1ZXN0IHR5cGVzXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogXFxgXFwke2NsdXN0ZXJOYW1lfS1cXCR7Y2FwYWNpdHlQcm92aWRlck5hbWV9LWRyYWluLXdhaXRlclxcYCxcbiAgICAgIERhdGE6IHtcbiAgICAgICAgTWVzc2FnZTogXFxgXFwke3JlcXVlc3RUeXBlfSBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XFxgXG4gICAgICB9XG4gICAgfTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKFwiRXJyb3I6XCIsIGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufTtcbmA7XG5cbiAgICBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgXCJEcmFpbldhaXRlclwiLCB7XG4gICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgaW5saW5lQ29kZTogaGFuZGxlckNvZGUsXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5taW51dGVzKDYpLFxuICAgICAgbGFtYmRhRGVzY3JpcHRpb246IGBXYWl0cyBmb3IgRUNTIHNlcnZpY2VzIHRvIGRyYWluIGJlZm9yZSBjYXBhY2l0eSBwcm92aWRlciBkaXNhc3NvY2lhdGlvbmAsXG4gICAgICByb2xlRGVzY3JpcHRpb246IGBSb2xlIGZvciAke2NsdXN0ZXJOYW1lfSBjYXBhY2l0eSBwcm92aWRlciBkcmFpbiB3YWl0ZXJgLFxuICAgICAgaW5saW5lUG9saWN5OiBbXG4gICAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAgIFwiZWNzOkxpc3RTZXJ2aWNlc1wiLFxuICAgICAgICAgICAgXCJlY3M6RGVzY3JpYmVTZXJ2aWNlc1wiLFxuICAgICAgICAgICAgXCJlY3M6RGVzY3JpYmVDbHVzdGVyc1wiLFxuICAgICAgICAgICAgXCJlY3M6UHV0Q2x1c3RlckNhcGFjaXR5UHJvdmlkZXJzXCJcbiAgICAgICAgICBdLFxuICAgICAgICAgIHJlc291cmNlczogW1wiKlwiXVxuICAgICAgICB9KVxuICAgICAgXSxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgQ2x1c3Rlck5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgICAgICBDYXBhY2l0eVByb3ZpZGVyTmFtZTogY2FwYWNpdHlQcm92aWRlck5hbWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19