@aws-solutions-constructs/aws-route53-apigateway 1.138.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.
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
6
+ * with the License. A copy of the License is located at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
11
+ * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
12
+ * and limitations under the License.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ // Imports
16
+ const core_1 = require("@aws-cdk/core");
17
+ const core_2 = require("@aws-solutions-constructs/core");
18
+ const defaults = require("@aws-solutions-constructs/core");
19
+ // Setup
20
+ const app = new core_1.App();
21
+ const stack = new core_1.Stack(app, core_2.generateIntegStackName(__filename), {});
22
+ stack.templateOptions.description = 'Dummy Integration Test for aws-route53-apigateway';
23
+ // This is an dummy integ test in order to bypass the CodeBuild integ test scans.
24
+ // Route53ToApiGateway construct requires a legitimate DNS and certificate to be deployed.
25
+ // If a fake DNS and certificate is provided, the deployment will hang and cause it to fail.
26
+ // Legitimate DNS and certificate cannot be provided in integ tests as it is user specific
27
+ // and will need to be regenerated.
28
+ // Create dummy integ with at least one resource to pass CFN scan
29
+ const [restApi] = defaults.RegionalRestApi(stack);
30
+ restApi.root.addMethod('GET');
31
+ // Synth
32
+ app.synth();
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWcuZHVtbXlUZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW50ZWcuZHVtbXlUZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7R0FXRzs7QUFFSCxVQUFVO0FBQ1Ysd0NBQTJDO0FBQzNDLHlEQUF3RTtBQUN4RSwyREFBMkQ7QUFFM0QsUUFBUTtBQUNSLE1BQU0sR0FBRyxHQUFHLElBQUksVUFBRyxFQUFFLENBQUM7QUFDdEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxZQUFLLENBQUMsR0FBRyxFQUFFLDZCQUFzQixDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBRXJFLEtBQUssQ0FBQyxlQUFlLENBQUMsV0FBVyxHQUFHLG1EQUFtRCxDQUFDO0FBRXhGLGlGQUFpRjtBQUNqRiwwRkFBMEY7QUFDMUYsNEZBQTRGO0FBQzVGLDBGQUEwRjtBQUMxRixtQ0FBbUM7QUFFbkMsaUVBQWlFO0FBQ2pFLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ2xELE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBRTlCLFFBQVE7QUFDUixHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgMjAyMiBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpLiBZb3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlXG4gKiAgd2l0aCB0aGUgTGljZW5zZS4gQSBjb3B5IG9mIHRoZSBMaWNlbnNlIGlzIGxvY2F0ZWQgYXRcbiAqXG4gKiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqICBvciBpbiB0aGUgJ2xpY2Vuc2UnIGZpbGUgYWNjb21wYW55aW5nIHRoaXMgZmlsZS4gVGhpcyBmaWxlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICdBUyBJUycgQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFU1xuICogIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGV4cHJlc3Mgb3IgaW1wbGllZC4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXG4gKiAgYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8vIEltcG9ydHNcbmltcG9ydCB7IEFwcCwgU3RhY2sgfSBmcm9tIFwiQGF3cy1jZGsvY29yZVwiO1xuaW1wb3J0IHsgZ2VuZXJhdGVJbnRlZ1N0YWNrTmFtZSB9IGZyb20gJ0Bhd3Mtc29sdXRpb25zLWNvbnN0cnVjdHMvY29yZSc7XG5pbXBvcnQgKiBhcyBkZWZhdWx0cyBmcm9tICdAYXdzLXNvbHV0aW9ucy1jb25zdHJ1Y3RzL2NvcmUnO1xuXG4vLyBTZXR1cFxuY29uc3QgYXBwID0gbmV3IEFwcCgpO1xuY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soYXBwLCBnZW5lcmF0ZUludGVnU3RhY2tOYW1lKF9fZmlsZW5hbWUpLCB7fSk7XG5cbnN0YWNrLnRlbXBsYXRlT3B0aW9ucy5kZXNjcmlwdGlvbiA9ICdEdW1teSBJbnRlZ3JhdGlvbiBUZXN0IGZvciBhd3Mtcm91dGU1My1hcGlnYXRld2F5JztcblxuLy8gVGhpcyBpcyBhbiBkdW1teSBpbnRlZyB0ZXN0IGluIG9yZGVyIHRvIGJ5cGFzcyB0aGUgQ29kZUJ1aWxkIGludGVnIHRlc3Qgc2NhbnMuXG4vLyBSb3V0ZTUzVG9BcGlHYXRld2F5IGNvbnN0cnVjdCByZXF1aXJlcyBhIGxlZ2l0aW1hdGUgRE5TIGFuZCBjZXJ0aWZpY2F0ZSB0byBiZSBkZXBsb3llZC5cbi8vIElmIGEgZmFrZSBETlMgYW5kIGNlcnRpZmljYXRlIGlzIHByb3ZpZGVkLCB0aGUgZGVwbG95bWVudCB3aWxsIGhhbmcgYW5kIGNhdXNlIGl0IHRvIGZhaWwuXG4vLyBMZWdpdGltYXRlIEROUyBhbmQgY2VydGlmaWNhdGUgY2Fubm90IGJlIHByb3ZpZGVkIGluIGludGVnIHRlc3RzIGFzIGl0IGlzIHVzZXIgc3BlY2lmaWNcbi8vIGFuZCB3aWxsIG5lZWQgdG8gYmUgcmVnZW5lcmF0ZWQuXG5cbi8vIENyZWF0ZSBkdW1teSBpbnRlZyB3aXRoIGF0IGxlYXN0IG9uZSByZXNvdXJjZSB0byBwYXNzIENGTiBzY2FuXG5jb25zdCBbcmVzdEFwaV0gPSBkZWZhdWx0cy5SZWdpb25hbFJlc3RBcGkoc3RhY2spO1xucmVzdEFwaS5yb290LmFkZE1ldGhvZCgnR0VUJyk7XG5cbi8vIFN5bnRoXG5hcHAuc3ludGgoKTtcbiJdfQ==
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
5
+ * with the License. A copy of the License is located at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
10
+ * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+ import "@aws-cdk/assert/jest";
@@ -0,0 +1,287 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
6
+ * with the License. A copy of the License is located at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
11
+ * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
12
+ * and limitations under the License.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ // Imports
16
+ const cdk = require("@aws-cdk/core");
17
+ const lib_1 = require("../lib");
18
+ const route53 = require("@aws-cdk/aws-route53");
19
+ const defaults = require("@aws-solutions-constructs/core");
20
+ const acm = require("@aws-cdk/aws-certificatemanager");
21
+ require("@aws-cdk/assert/jest");
22
+ // Deploying Public/Private Existing Hosted Zones
23
+ function deployApi(stack, publicApi) {
24
+ const [restApi] = defaults.RegionalRestApi(stack);
25
+ restApi.root.addMethod('GET');
26
+ const domainName = "www.test-example.com";
27
+ let newZone;
28
+ if (publicApi) {
29
+ newZone = new route53.PublicHostedZone(stack, "new-zone", {
30
+ zoneName: domainName,
31
+ });
32
+ }
33
+ else {
34
+ const vpc = defaults.buildVpc(stack, {
35
+ defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(),
36
+ constructVpcProps: {
37
+ enableDnsHostnames: true,
38
+ enableDnsSupport: true,
39
+ cidr: "172.168.0.0/16",
40
+ },
41
+ });
42
+ newZone = new route53.PrivateHostedZone(stack, "new-zone", {
43
+ zoneName: domainName,
44
+ vpc
45
+ });
46
+ }
47
+ const certificate = acm.Certificate.fromCertificateArn(stack, "fake-cert", "arn:aws:acm:us-east-1:123456789012:certificate/11112222-3333-1234-1234-123456789012");
48
+ // Definitions
49
+ const props = {
50
+ publicApi,
51
+ existingHostedZoneInterface: newZone,
52
+ existingApiGatewayInterface: restApi,
53
+ existingCertificateInterface: certificate,
54
+ };
55
+ return new lib_1.Route53ToApiGateway(stack, "api-stack", props);
56
+ }
57
+ // --------------------------------------------------------------
58
+ // Check for pattern props
59
+ // --------------------------------------------------------------
60
+ test("Test for default params construct props", () => {
61
+ // Initial Setup
62
+ const stack = new cdk.Stack();
63
+ const construct = deployApi(stack, false);
64
+ // Assertion
65
+ expect(construct.apiGateway).not.toBeNull();
66
+ expect(construct.hostedZone).not.toBeNull();
67
+ expect(construct.vpc).not.toBeNull();
68
+ expect(construct.certificate).not.toBeNull();
69
+ });
70
+ // --------------------------------------------------------------
71
+ // Check for errors when creating a private hosted zone
72
+ // --------------------------------------------------------------
73
+ test("Test for errors when creating a private hosted zone", () => {
74
+ // Initial Setup
75
+ const stack = new cdk.Stack();
76
+ const [restApi] = defaults.RegionalRestApi(stack);
77
+ const domainName = "www.test-example.com";
78
+ const vpc = defaults.buildVpc(stack, {
79
+ defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(),
80
+ constructVpcProps: {
81
+ enableDnsHostnames: true,
82
+ enableDnsSupport: true,
83
+ cidr: "172.168.0.0/16",
84
+ },
85
+ });
86
+ const newZone = new route53.PrivateHostedZone(stack, "new-zone", {
87
+ zoneName: domainName,
88
+ vpc
89
+ });
90
+ const certificate = acm.Certificate.fromCertificateArn(stack, "fake-cert", "arn:aws:acm:us-east-1:123456789012:certificate/11112222-3333-1234-1234-123456789012");
91
+ let app = () => new lib_1.Route53ToApiGateway(stack, "api-stack1", {
92
+ publicApi: true,
93
+ existingApiGatewayInterface: restApi,
94
+ existingCertificateInterface: certificate
95
+ });
96
+ // Assertion 1
97
+ expect(app).toThrowError("Public APIs require an existingHostedZone be passed in the Props object.");
98
+ app = () => new lib_1.Route53ToApiGateway(stack, "api-stack2", {
99
+ publicApi: false,
100
+ existingApiGatewayInterface: restApi,
101
+ existingCertificateInterface: certificate
102
+ });
103
+ // Assertion 2
104
+ expect(app).toThrowError("Must provide either existingHostedZoneInterface or privateHostedZoneProps.");
105
+ app = () => new lib_1.Route53ToApiGateway(stack, "api-stack3", {
106
+ publicApi: false,
107
+ privateHostedZoneProps: {
108
+ zoneName: "test-example.com",
109
+ vpc,
110
+ },
111
+ existingApiGatewayInterface: restApi,
112
+ existingCertificateInterface: certificate
113
+ });
114
+ // Assertion 3
115
+ expect(app).toThrowError("All VPC specs must be provided at the Construct level in Route53ToApiGatewayProps");
116
+ app = () => new lib_1.Route53ToApiGateway(stack, "api-stack4", {
117
+ publicApi: false,
118
+ existingHostedZoneInterface: newZone,
119
+ existingVpc: vpc,
120
+ existingApiGatewayInterface: restApi,
121
+ existingCertificateInterface: certificate
122
+ });
123
+ // Assertion 4
124
+ expect(app).toThrowError("Cannot provide an existing VPC to an existing Private Hosted Zone.");
125
+ app = () => new lib_1.Route53ToApiGateway(stack, "api-stack5", {
126
+ publicApi: false,
127
+ existingHostedZoneInterface: newZone,
128
+ existingApiGatewayInterface: restApi,
129
+ privateHostedZoneProps: {
130
+ domainName: "test-example.com"
131
+ },
132
+ existingCertificateInterface: certificate
133
+ });
134
+ // Assertion 5
135
+ expect(app).toThrowError("Must provide either existingHostedZoneInterface or privateHostedZoneProps, but not both.");
136
+ app = () => new lib_1.Route53ToApiGateway(stack, "api-stack6", {
137
+ publicApi: false,
138
+ privateHostedZoneProps: {
139
+ domainName: "test.example.com"
140
+ },
141
+ existingApiGatewayInterface: restApi,
142
+ existingCertificateInterface: certificate
143
+ });
144
+ // Assertion 6
145
+ expect(app).toThrowError('Must supply zoneName for Private Hosted Zone Props.');
146
+ app = () => new lib_1.Route53ToApiGateway(stack, "api-stack7", {
147
+ publicApi: false,
148
+ privateHostedZoneProps: {
149
+ zoneName: "test.example.com"
150
+ },
151
+ existingApiGatewayInterface: restApi,
152
+ existingCertificateInterface: certificate
153
+ });
154
+ // Assertion 7
155
+ expect(app).toThrowError('Must specify an existingVPC for the Private Hosted Zone in the construct props.');
156
+ });
157
+ // --------------------------------------------------------------
158
+ // Check for providing private hosted zone props
159
+ // --------------------------------------------------------------
160
+ test("Test for providing private hosted zone props", () => {
161
+ // Initial Setup
162
+ const stack = new cdk.Stack();
163
+ const [restApi] = defaults.RegionalRestApi(stack);
164
+ restApi.root.addMethod('GET');
165
+ const domainName = "www.private-zone.com";
166
+ const vpc = defaults.buildVpc(stack, {
167
+ defaultVpcProps: defaults.DefaultPublicPrivateVpcProps(),
168
+ constructVpcProps: {
169
+ enableDnsHostnames: true,
170
+ enableDnsSupport: true,
171
+ cidr: "172.168.0.0/16",
172
+ },
173
+ });
174
+ const certificate = acm.Certificate.fromCertificateArn(stack, "fake-cert", "arn:aws:acm:us-east-1:123456789012:certificate/11112222-3333-1234-1234-123456789012");
175
+ new lib_1.Route53ToApiGateway(stack, "api-stack1", {
176
+ publicApi: false,
177
+ existingApiGatewayInterface: restApi,
178
+ privateHostedZoneProps: {
179
+ zoneName: domainName,
180
+ },
181
+ existingVpc: vpc,
182
+ existingCertificateInterface: certificate
183
+ });
184
+ expect(stack).toHaveResource("AWS::Route53::HostedZone", {
185
+ Name: "www.private-zone.com.",
186
+ VPCs: [
187
+ {
188
+ VPCId: {
189
+ Ref: "Vpc8378EB38",
190
+ },
191
+ VPCRegion: {
192
+ Ref: "AWS::Region",
193
+ },
194
+ },
195
+ ],
196
+ });
197
+ });
198
+ // --------------------------------------------------------------
199
+ // Check for A record creation in Public Hosted Zone
200
+ // --------------------------------------------------------------
201
+ test("Integration test for A record creation in Public Hosted Zone ", () => {
202
+ // Initial Setup
203
+ const stack = new cdk.Stack();
204
+ deployApi(stack, true);
205
+ // Assertions
206
+ expect(stack).toHaveResource("AWS::Route53::RecordSet", {
207
+ Name: "www.test-example.com.",
208
+ Type: "A",
209
+ AliasTarget: {
210
+ DNSName: {
211
+ "Fn::GetAtt": [
212
+ "RestApiCustomDomainName94F28E16",
213
+ "RegionalDomainName",
214
+ ],
215
+ },
216
+ HostedZoneId: {
217
+ "Fn::GetAtt": [
218
+ "RestApiCustomDomainName94F28E16",
219
+ "RegionalHostedZoneId",
220
+ ],
221
+ },
222
+ },
223
+ HostedZoneId: {
224
+ Ref: "newzone1D011936",
225
+ },
226
+ });
227
+ expect(stack).toHaveResource("AWS::ApiGateway::RestApi", {
228
+ EndpointConfiguration: {
229
+ Types: [
230
+ "REGIONAL"
231
+ ]
232
+ },
233
+ Name: "RestApi"
234
+ });
235
+ });
236
+ // --------------------------------------------------------------
237
+ // Check for A record creation in Private Hosted Zone
238
+ // --------------------------------------------------------------
239
+ test("Integration test for A record creation in Private Hosted Zone ", () => {
240
+ // Initial Setup
241
+ const stack = new cdk.Stack();
242
+ deployApi(stack, false);
243
+ // Assertions
244
+ expect(stack).toHaveResource("AWS::Route53::RecordSet", {
245
+ Name: "www.test-example.com.",
246
+ Type: "A",
247
+ AliasTarget: {
248
+ DNSName: {
249
+ "Fn::GetAtt": [
250
+ "RestApiCustomDomainName94F28E16",
251
+ "RegionalDomainName",
252
+ ],
253
+ },
254
+ HostedZoneId: {
255
+ "Fn::GetAtt": [
256
+ "RestApiCustomDomainName94F28E16",
257
+ "RegionalHostedZoneId",
258
+ ],
259
+ },
260
+ },
261
+ HostedZoneId: {
262
+ Ref: "newzone1D011936",
263
+ },
264
+ });
265
+ expect(stack).toHaveResource("AWS::Route53::HostedZone", {
266
+ Name: "www.test-example.com.",
267
+ VPCs: [
268
+ {
269
+ VPCId: {
270
+ Ref: "Vpc8378EB38",
271
+ },
272
+ VPCRegion: {
273
+ Ref: "AWS::Region",
274
+ },
275
+ },
276
+ ],
277
+ });
278
+ expect(stack).toHaveResource("AWS::ApiGateway::RestApi", {
279
+ EndpointConfiguration: {
280
+ Types: [
281
+ "REGIONAL"
282
+ ]
283
+ },
284
+ Name: "RestApi"
285
+ });
286
+ });
287
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5yb3V0ZTUzLWFwaWdhdGV3YXkudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3Qucm91dGU1My1hcGlnYXRld2F5LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7OztHQVdHOztBQUVILFVBQVU7QUFDVixxQ0FBcUM7QUFDckMsZ0NBQXVFO0FBQ3ZFLGdEQUFnRDtBQUNoRCwyREFBMkQ7QUFDM0QsdURBQXVEO0FBQ3ZELGdDQUE4QjtBQUU5QixpREFBaUQ7QUFDakQsU0FBUyxTQUFTLENBQ2hCLEtBQWdCLEVBQ2hCLFNBQWtCO0lBRWxCLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xELE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTlCLE1BQU0sVUFBVSxHQUFHLHNCQUFzQixDQUFDO0lBRTFDLElBQUksT0FBNkQsQ0FBQztJQUVsRSxJQUFJLFNBQVMsRUFBRTtRQUNiLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFO1lBQ3hELFFBQVEsRUFBRSxVQUFVO1NBQ3JCLENBQUMsQ0FBQztLQUNKO1NBQU07UUFDTCxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRTtZQUNuQyxlQUFlLEVBQUUsUUFBUSxDQUFDLDRCQUE0QixFQUFFO1lBQ3hELGlCQUFpQixFQUFFO2dCQUNqQixrQkFBa0IsRUFBRSxJQUFJO2dCQUN4QixnQkFBZ0IsRUFBRSxJQUFJO2dCQUN0QixJQUFJLEVBQUUsZ0JBQWdCO2FBQ3ZCO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUU7WUFDekQsUUFBUSxFQUFFLFVBQVU7WUFDcEIsR0FBRztTQUNK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QjtTQUN2QjtLQUNGLENBQUMsQ0FBQztJQUVILE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxjQUFjLENBQUMsMEJBQTBCLEVBQUU7UUFDdkQsSUFBSSxFQUFFLHVCQUF1QjtRQUM3QixJQUFJLEVBQUU7WUFDSjtnQkFDRSxLQUFLLEVBQUU7b0JBQ0wsR0FBRyxFQUFFLGFBQWE7aUJBQ25CO2dCQUNELFNBQVMsRUFBRTtvQkFDVCxHQUFHLEVBQUUsYUFBYTtpQkFDbkI7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLGNBQWMsQ0FBQywwQkFBMEIsRUFBRTtRQUN2RCxxQkFBcUIsRUFBRTtZQUNyQixLQUFLLEVBQUU7Z0JBQ0wsVUFBVTthQUNYO1NBQ0Y7UUFDRCxJQUFJLEVBQUUsU0FBUztLQUNoQixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogIENvcHlyaWdodCAyMDIyIEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikuIFlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqICB3aXRoIHRoZSBMaWNlbnNlLiBBIGNvcHkgb2YgdGhlIExpY2Vuc2UgaXMgbG9jYXRlZCBhdFxuICpcbiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogIG9yIGluIHRoZSAnbGljZW5zZScgZmlsZSBhY2NvbXBhbnlpbmcgdGhpcyBmaWxlLiBUaGlzIGZpbGUgaXMgZGlzdHJpYnV0ZWQgb24gYW4gJ0FTIElTJyBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTXG4gKiAgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcbiAqICBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLy8gSW1wb3J0c1xuaW1wb3J0ICogYXMgY2RrIGZyb20gXCJAYXdzLWNkay9jb3JlXCI7XG5pbXBvcnQgeyBSb3V0ZTUzVG9BcGlHYXRld2F5LCBSb3V0ZTUzVG9BcGlHYXRld2F5UHJvcHMgfSBmcm9tIFwiLi4vbGliXCI7XG5pbXBvcnQgKiBhcyByb3V0ZTUzIGZyb20gXCJAYXdzLWNkay9hd3Mtcm91dGU1M1wiO1xuaW1wb3J0ICogYXMgZGVmYXVsdHMgZnJvbSBcIkBhd3Mtc29sdXRpb25zLWNvbnN0cnVjdHMvY29yZVwiO1xuaW1wb3J0ICogYXMgYWNtIGZyb20gXCJAYXdzLWNkay9hd3MtY2VydGlmaWNhdGVtYW5hZ2VyXCI7XG5pbXBvcnQgXCJAYXdzLWNkay9hc3NlcnQvamVzdFwiO1xuXG4vLyBEZXBsb3lpbmcgUHVibGljL1ByaXZhdGUgRXhpc3RpbmcgSG9zdGVkIFpvbmVzXG5mdW5jdGlvbiBkZXBsb3lBcGkoXG4gIHN0YWNrOiBjZGsuU3RhY2ssXG4gIHB1YmxpY0FwaTogYm9vbGVhblxuKSB7XG4gIGNvbnN0IFtyZXN0QXBpXSA9IGRlZmF1bHRzLlJlZ2lvbmFsUmVzdEFwaShzdGFjayk7XG4gIHJlc3RBcGkucm9vdC5hZGRNZXRob2QoJ0dFVCcpO1xuXG4gIGNvbnN0IGRvbWFpbk5hbWUgPSBcInd3dy50ZXN0LWV4YW1wbGUuY29tXCI7XG5cbiAgbGV0IG5ld1pvbmU6IHJvdXRlNTMuUHVibGljSG9zdGVkWm9uZSB8IHJvdXRlNTMuUHJpdmF0ZUhvc3RlZFpvbmU7XG5cbiAgaWYgKHB1YmxpY0FwaSkge1xuICAgIG5ld1pvbmUgPSBuZXcgcm91dGU1My5QdWJsaWNIb3N0ZWRab25lKHN0YWNrLCBcIm5ldy16b25lXCIsIHtcbiAgICAgIHpvbmVOYW1lOiBkb21haW5OYW1lLFxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHZwYyA9IGRlZmF1bHRzLmJ1aWxkVnBjKHN0YWNrLCB7XG4gICAgICBkZWZhdWx0VnBjUHJvcHM6IGRlZmF1bHRzLkRlZmF1bHRQdWJsaWNQcml2YXRlVnBjUHJvcHMoKSxcbiAgICAgIGNvbnN0cnVjdFZwY1Byb3BzOiB7XG4gICAgICAgIGVuYWJsZURuc0hvc3RuYW1lczogdHJ1ZSxcbiAgICAgICAgZW5hYmxlRG5zU3VwcG9ydDogdHJ1ZSxcbiAgICAgICAgY2lkcjogXCIxNzIuMTY4LjAuMC8xNlwiLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIG5ld1pvbmUgPSBuZXcgcm91dGU1My5Qcml2YXRlSG9zdGVkWm9uZShzdGFjaywgXCJuZXctem9uZVwiLCB7XG4gICAgICB6b25lTmFtZTogZG9tYWluTmFtZSxcbiAgICAgIHZwY1xuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgY2VydGlmaWNhdGUgPSBhY20uQ2VydGlmaWNhdGUuZnJvbUNlcnRpZmljYXRlQXJuKFxuICAgIHN0YWNrLFxuICAgIFwiZmFrZS1jZXJ0XCIsXG4gICAgXCJhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzExMTEyMjIyLTMzMzMtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMlwiXG4gICk7XG5cbiAgLy8gRGVmaW5pdGlvbnNcbiAgY29uc3QgcHJvcHM6IFJvdXRlNTNUb0FwaUdhdGV3YXlQcm9wcyA9IHtcbiAgICBwdWJsaWNBcGksXG4gICAgZXhpc3RpbmdIb3N0ZWRab25lSW50ZXJmYWNlOiBuZXdab25lLFxuICAgIGV4aXN0aW5nQXBpR2F0ZXdheUludGVyZmFjZTogcmVzdEFwaSxcbiAgICBleGlzdGluZ0NlcnRpZmljYXRlSW50ZXJmYWNlOiBjZXJ0aWZpY2F0ZSxcbiAgfTtcblxuICByZXR1cm4gbmV3IFJvdXRlNTNUb0FwaUdhdGV3YXkoc3RhY2ssIFwiYXBpLXN0YWNrXCIsIHByb3BzKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENoZWNrIGZvciBwYXR0ZXJuIHByb3BzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxudGVzdChcIlRlc3QgZm9yIGRlZmF1bHQgcGFyYW1zIGNvbnN0cnVjdCBwcm9wc1wiLCAoKSA9PiB7XG4gIC8vIEluaXRpYWwgU2V0dXBcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IGNvbnN0cnVjdCA9IGRlcGxveUFwaShzdGFjaywgZmFsc2UpO1xuXG4gIC8vIEFzc2VydGlvblxuICBleHBlY3QoY29uc3RydWN0LmFwaUdhdGV3YXkpLm5vdC50b0JlTnVsbCgpO1xuICBleHBlY3QoY29uc3RydWN0Lmhvc3RlZFpvbmUpLm5vdC50b0JlTnVsbCgpO1xuICBleHBlY3QoY29uc3RydWN0LnZwYykubm90LnRvQmVOdWxsKCk7XG4gIGV4cGVjdChjb25zdHJ1Y3QuY2VydGlmaWNhdGUpLm5vdC50b0JlTnVsbCgpO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDaGVjayBmb3IgZXJyb3JzIHdoZW4gY3JlYXRpbmcgYSBwcml2YXRlIGhvc3RlZCB6b25lXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxudGVzdChcIlRlc3QgZm9yIGVycm9ycyB3aGVuIGNyZWF0aW5nIGEgcHJpdmF0ZSBob3N0ZWQgem9uZVwiLCAoKSA9PiB7XG4gIC8vIEluaXRpYWwgU2V0dXBcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGNvbnN0IFtyZXN0QXBpXSA9IGRlZmF1bHRzLlJlZ2lvbmFsUmVzdEFwaShzdGFjayk7XG4gIGNvbnN0IGRvbWFpbk5hbWUgPSBcInd3dy50ZXN0LWV4YW1wbGUuY29tXCI7XG5cbiAgY29uc3QgdnBjID0gZGVmYXVsdHMuYnVpbGRWcGMoc3RhY2ssIHtcbiAgICBkZWZhdWx0VnBjUHJvcHM6IGRlZmF1bHRzLkRlZmF1bHRQdWJsaWNQcml2YXRlVnBjUHJvcHMoKSxcbiAgICBjb25zdHJ1Y3RWcGNQcm9wczoge1xuICAgICAgZW5hYmxlRG5zSG9zdG5hbWVzOiB0cnVlLFxuICAgICAgZW5hYmxlRG5zU3VwcG9ydDogdHJ1ZSxcbiAgICAgIGNpZHI6IFwiMTcyLjE2OC4wLjAvMTZcIixcbiAgICB9LFxuICB9KTtcblxuICBjb25zdCBuZXdab25lID0gbmV3IHJvdXRlNTMuUHJpdmF0ZUhvc3RlZFpvbmUoc3RhY2ssIFwibmV3LXpvbmVcIiwge1xuICAgIHpvbmVOYW1lOiBkb21haW5OYW1lLFxuICAgIHZwY1xuICB9KTtcblxuICBjb25zdCBjZXJ0aWZpY2F0ZSA9IGFjbS5DZXJ0aWZpY2F0ZS5mcm9tQ2VydGlmaWNhdGVBcm4oXG4gICAgc3RhY2ssXG4gICAgXCJmYWtlLWNlcnRcIixcbiAgICBcImFybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTExMTIyMjItMzMzMy0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyXCJcbiAgKTtcblxuICBsZXQgYXBwID0gKCkgPT5cbiAgICBuZXcgUm91dGU1M1RvQXBpR2F0ZXdheShzdGFjaywgXCJhcGktc3RhY2sxXCIsIHtcbiAgICAgIHB1YmxpY0FwaTogdHJ1ZSxcbiAgICAgIGV4aXN0aW5nQXBpR2F0ZXdheUludGVyZmFjZTogcmVzdEFwaSxcbiAgICAgIGV4aXN0aW5nQ2VydGlmaWNhdGVJbnRlcmZhY2U6IGNlcnRpZmljYXRlXG4gICAgfSk7XG4gIC8vIEFzc2VydGlvbiAxXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcihcbiAgICBcIlB1YmxpYyBBUElzIHJlcXVpcmUgYW4gZXhpc3RpbmdIb3N0ZWRab25lIGJlIHBhc3NlZCBpbiB0aGUgUHJvcHMgb2JqZWN0LlwiXG4gICk7XG5cbiAgYXBwID0gKCkgPT5cbiAgICBuZXcgUm91dGU1M1RvQXBpR2F0ZXdheShzdGFjaywgXCJhcGktc3RhY2syXCIsIHtcbiAgICAgIHB1YmxpY0FwaTogZmFsc2UsXG4gICAgICBleGlzdGluZ0FwaUdhdGV3YXlJbnRlcmZhY2U6IHJlc3RBcGksXG4gICAgICBleGlzdGluZ0NlcnRpZmljYXRlSW50ZXJmYWNlOiBjZXJ0aWZpY2F0ZVxuICAgIH0pO1xuXG4gIC8vIEFzc2VydGlvbiAyXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcihcbiAgICBcIk11c3QgcHJvdmlkZSBlaXRoZXIgZXhpc3RpbmdIb3N0ZWRab25lSW50ZXJmYWNlIG9yIHByaXZhdGVIb3N0ZWRab25lUHJvcHMuXCJcbiAgKTtcblxuICBhcHAgPSAoKSA9PlxuICAgIG5ldyBSb3V0ZTUzVG9BcGlHYXRld2F5KHN0YWNrLCBcImFwaS1zdGFjazNcIiwge1xuICAgICAgcHVibGljQXBpOiBmYWxzZSxcbiAgICAgIHByaXZhdGVIb3N0ZWRab25lUHJvcHM6IHtcbiAgICAgICAgem9uZU5hbWU6IFwidGVzdC1leGFtcGxlLmNvbVwiLFxuICAgICAgICB2cGMsXG4gICAgICB9LFxuICAgICAgZXhpc3RpbmdBcGlHYXRld2F5SW50ZXJmYWNlOiByZXN0QXBpLFxuICAgICAgZXhpc3RpbmdDZXJ0aWZpY2F0ZUludGVyZmFjZTogY2VydGlmaWNhdGVcbiAgICB9KTtcblxuICAvLyBBc3NlcnRpb24gM1xuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoXG4gICAgXCJBbGwgVlBDIHNwZWNzIG11c3QgYmUgcHJvdmlkZWQgYXQgdGhlIENvbnN0cnVjdCBsZXZlbCBpbiBSb3V0ZTUzVG9BcGlHYXRld2F5UHJvcHNcIlxuICApO1xuXG4gIGFwcCA9ICgpID0+XG4gICAgbmV3IFJvdXRlNTNUb0FwaUdhdGV3YXkoc3RhY2ssIFwiYXBpLXN0YWNrNFwiLCB7XG4gICAgICBwdWJsaWNBcGk6IGZhbHNlLFxuICAgICAgZXhpc3RpbmdIb3N0ZWRab25lSW50ZXJmYWNlOiBuZXdab25lLFxuICAgICAgZXhpc3RpbmdWcGM6IHZwYyxcbiAgICAgIGV4aXN0aW5nQXBpR2F0ZXdheUludGVyZmFjZTogcmVzdEFwaSxcbiAgICAgIGV4aXN0aW5nQ2VydGlmaWNhdGVJbnRlcmZhY2U6IGNlcnRpZmljYXRlXG4gICAgfSk7XG5cbiAgLy8gQXNzZXJ0aW9uIDRcbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKFxuICAgIFwiQ2Fubm90IHByb3ZpZGUgYW4gZXhpc3RpbmcgVlBDIHRvIGFuIGV4aXN0aW5nIFByaXZhdGUgSG9zdGVkIFpvbmUuXCJcbiAgKTtcblxuICBhcHAgPSAoKSA9PlxuICAgIG5ldyBSb3V0ZTUzVG9BcGlHYXRld2F5KHN0YWNrLCBcImFwaS1zdGFjazVcIiwge1xuICAgICAgcHVibGljQXBpOiBmYWxzZSxcbiAgICAgIGV4aXN0aW5nSG9zdGVkWm9uZUludGVyZmFjZTogbmV3Wm9uZSxcbiAgICAgIGV4aXN0aW5nQXBpR2F0ZXdheUludGVyZmFjZTogcmVzdEFwaSxcbiAgICAgIHByaXZhdGVIb3N0ZWRab25lUHJvcHM6IHtcbiAgICAgICAgZG9tYWluTmFtZTogXCJ0ZXN0LWV4YW1wbGUuY29tXCJcbiAgICAgIH0sXG4gICAgICBleGlzdGluZ0NlcnRpZmljYXRlSW50ZXJmYWNlOiBjZXJ0aWZpY2F0ZVxuICAgIH0pO1xuXG4gIC8vIEFzc2VydGlvbiA1XG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcihcbiAgICBcIk11c3QgcHJvdmlkZSBlaXRoZXIgZXhpc3RpbmdIb3N0ZWRab25lSW50ZXJmYWNlIG9yIHByaXZhdGVIb3N0ZWRab25lUHJvcHMsIGJ1dCBub3QgYm90aC5cIlxuICApO1xuXG4gIGFwcCA9ICgpID0+XG4gICAgbmV3IFJvdXRlNTNUb0FwaUdhdGV3YXkoc3RhY2ssIFwiYXBpLXN0YWNrNlwiLCB7XG4gICAgICBwdWJsaWNBcGk6IGZhbHNlLFxuICAgICAgcHJpdmF0ZUhvc3RlZFpvbmVQcm9wczoge1xuICAgICAgICBkb21haW5OYW1lOiBcInRlc3QuZXhhbXBsZS5jb21cIlxuICAgICAgfSxcbiAgICAgIGV4aXN0aW5nQXBpR2F0ZXdheUludGVyZmFjZTogcmVzdEFwaSxcbiAgICAgIGV4aXN0aW5nQ2VydGlmaWNhdGVJbnRlcmZhY2U6IGNlcnRpZmljYXRlXG4gICAgfSk7XG5cbiAgLy8gQXNzZXJ0aW9uIDZcbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKFxuICAgICdNdXN0IHN1cHBseSB6b25lTmFtZSBmb3IgUHJpdmF0ZSBIb3N0ZWQgWm9uZSBQcm9wcy4nXG4gICk7XG5cbiAgYXBwID0gKCkgPT5cbiAgICBuZXcgUm91dGU1M1RvQXBpR2F0ZXdheShzdGFjaywgXCJhcGktc3RhY2s3XCIsIHtcbiAgICAgIHB1YmxpY0FwaTogZmFsc2UsXG4gICAgICBwcml2YXRlSG9zdGVkWm9uZVByb3BzOiB7XG4gICAgICAgIHpvbmVOYW1lOiBcInRlc3QuZXhhbXBsZS5jb21cIlxuICAgICAgfSxcbiAgICAgIGV4aXN0aW5nQXBpR2F0ZXdheUludGVyZmFjZTogcmVzdEFwaSxcbiAgICAgIGV4aXN0aW5nQ2VydGlmaWNhdGVJbnRlcmZhY2U6IGNlcnRpZmljYXRlXG4gICAgfSk7XG5cbiAgLy8gQXNzZXJ0aW9uIDdcbiAgZXhwZWN0KGFwcCkudG9UaHJvd0Vycm9yKFxuICAgICdNdXN0IHNwZWNpZnkgYW4gZXhpc3RpbmdWUEMgZm9yIHRoZSBQcml2YXRlIEhvc3RlZCBab25lIGluIHRoZSBjb25zdHJ1Y3QgcHJvcHMuJ1xuICApO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBDaGVjayBmb3IgcHJvdmlkaW5nIHByaXZhdGUgaG9zdGVkIHpvbmUgcHJvcHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG50ZXN0KFwiVGVzdCBmb3IgcHJvdmlkaW5nIHByaXZhdGUgaG9zdGVkIHpvbmUgcHJvcHNcIiwgKCkgPT4ge1xuICAvLyBJbml0aWFsIFNldHVwXG4gIGNvbnN0IHN0YWNrID0gbmV3IGNkay5TdGFjaygpO1xuICBjb25zdCBbcmVzdEFwaV0gPSBkZWZhdWx0cy5SZWdpb25hbFJlc3RBcGkoc3RhY2spO1xuICByZXN0QXBpLnJvb3QuYWRkTWV0aG9kKCdHRVQnKTtcblxuICBjb25zdCBkb21haW5OYW1lID0gXCJ3d3cucHJpdmF0ZS16b25lLmNvbVwiO1xuXG4gIGNvbnN0IHZwYyA9IGRlZmF1bHRzLmJ1aWxkVnBjKHN0YWNrLCB7XG4gICAgZGVmYXVsdFZwY1Byb3BzOiBkZWZhdWx0cy5EZWZhdWx0UHVibGljUHJpdmF0ZVZwY1Byb3BzKCksXG4gICAgY29uc3RydWN0VnBjUHJvcHM6IHtcbiAgICAgIGVuYWJsZURuc0hvc3RuYW1lczogdHJ1ZSxcbiAgICAgIGVuYWJsZURuc1N1cHBvcnQ6IHRydWUsXG4gICAgICBjaWRyOiBcIjE3Mi4xNjguMC4wLzE2XCIsXG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3QgY2VydGlmaWNhdGUgPSBhY20uQ2VydGlmaWNhdGUuZnJvbUNlcnRpZmljYXRlQXJuKFxuICAgIHN0YWNrLFxuICAgIFwiZmFrZS1jZXJ0XCIsXG4gICAgXCJhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzExMTEyMjIyLTMzMzMtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMlwiXG4gICk7XG5cbiAgbmV3IFJvdXRlNTNUb0FwaUdhdGV3YXkoc3RhY2ssIFwiYXBpLXN0YWNrMVwiLCB7XG4gICAgcHVibGljQXBpOiBmYWxzZSxcbiAgICBleGlzdGluZ0FwaUdhdGV3YXlJbnRlcmZhY2U6IHJlc3RBcGksXG4gICAgcHJpdmF0ZUhvc3RlZFpvbmVQcm9wczoge1xuICAgICAgem9uZU5hbWU6IGRvbWFpbk5hbWUsXG4gICAgfSxcbiAgICBleGlzdGluZ1ZwYzogdnBjLFxuICAgIGV4aXN0aW5nQ2VydGlmaWNhdGVJbnRlcmZhY2U6IGNlcnRpZmljYXRlXG4gIH0pO1xuXG4gIGV4cGVjdChzdGFjaykudG9IYXZlUmVzb3VyY2UoXCJBV1M6OlJvdXRlNTM6Okhvc3RlZFpvbmVcIiwge1xuICAgIE5hbWU6IFwid3d3LnByaXZhdGUtem9uZS5jb20uXCIsXG4gICAgVlBDczogW1xuICAgICAge1xuICAgICAgICBWUENJZDoge1xuICAgICAgICAgIFJlZjogXCJWcGM4Mzc4RUIzOFwiLFxuICAgICAgICB9LFxuICAgICAgICBWUENSZWdpb246IHtcbiAgICAgICAgICBSZWY6IFwiQVdTOjpSZWdpb25cIixcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG59KTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENoZWNrIGZvciBBIHJlY29yZCBjcmVhdGlvbiBpbiBQdWJsaWMgSG9zdGVkIFpvbmVcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG50ZXN0KFwiSW50ZWdyYXRpb24gdGVzdCBmb3IgQSByZWNvcmQgY3JlYXRpb24gaW4gUHVibGljIEhvc3RlZCBab25lIFwiLCAoKSA9PiB7XG4gIC8vIEluaXRpYWwgU2V0dXBcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKCk7XG4gIGRlcGxveUFwaShzdGFjaywgdHJ1ZSk7XG5cbiAgLy8gQXNzZXJ0aW9uc1xuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlKFwiQVdTOjpSb3V0ZTUzOjpSZWNvcmRTZXRcIiwge1xuICAgIE5hbWU6IFwid3d3LnRlc3QtZXhhbXBsZS5jb20uXCIsXG4gICAgVHlwZTogXCJBXCIsXG4gICAgQWxpYXNUYXJnZXQ6IHtcbiAgICAgIEROU05hbWU6IHtcbiAgICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgICBcIlJlc3RBcGlDdXN0b21Eb21haW5OYW1lOTRGMjhFMTZcIixcbiAgICAgICAgICBcIlJlZ2lvbmFsRG9tYWluTmFtZVwiLFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIEhvc3RlZFpvbmVJZDoge1xuICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgIFwiUmVzdEFwaUN1c3RvbURvbWFpbk5hbWU5NEYyOEUxNlwiLFxuICAgICAgICAgIFwiUmVnaW9uYWxIb3N0ZWRab25lSWRcIixcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBIb3N0ZWRab25lSWQ6IHtcbiAgICAgIFJlZjogXCJuZXd6b25lMUQwMTE5MzZcIixcbiAgICB9LFxuICB9KTtcblxuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlKFwiQVdTOjpBcGlHYXRld2F5OjpSZXN0QXBpXCIsIHtcbiAgICBFbmRwb2ludENvbmZpZ3VyYXRpb246IHtcbiAgICAgIFR5cGVzOiBbXG4gICAgICAgIFwiUkVHSU9OQUxcIlxuICAgICAgXVxuICAgIH0sXG4gICAgTmFtZTogXCJSZXN0QXBpXCJcbiAgfSk7XG59KTtcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENoZWNrIGZvciBBIHJlY29yZCBjcmVhdGlvbiBpbiBQcml2YXRlIEhvc3RlZCBab25lXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxudGVzdChcIkludGVncmF0aW9uIHRlc3QgZm9yIEEgcmVjb3JkIGNyZWF0aW9uIGluIFByaXZhdGUgSG9zdGVkIFpvbmUgXCIsICgpID0+IHtcbiAgLy8gSW5pdGlhbCBTZXR1cFxuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soKTtcbiAgZGVwbG95QXBpKHN0YWNrLCBmYWxzZSk7XG5cbiAgLy8gQXNzZXJ0aW9uc1xuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlKFwiQVdTOjpSb3V0ZTUzOjpSZWNvcmRTZXRcIiwge1xuICAgIE5hbWU6IFwid3d3LnRlc3QtZXhhbXBsZS5jb20uXCIsXG4gICAgVHlwZTogXCJBXCIsXG4gICAgQWxpYXNUYXJnZXQ6IHtcbiAgICAgIEROU05hbWU6IHtcbiAgICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgICBcIlJlc3RBcGlDdXN0b21Eb21haW5OYW1lOTRGMjhFMTZcIixcbiAgICAgICAgICBcIlJlZ2lvbmFsRG9tYWluTmFtZVwiLFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICAgIEhvc3RlZFpvbmVJZDoge1xuICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgIFwiUmVzdEFwaUN1c3RvbURvbWFpbk5hbWU5NEYyOEUxNlwiLFxuICAgICAgICAgIFwiUmVnaW9uYWxIb3N0ZWRab25lSWRcIixcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBIb3N0ZWRab25lSWQ6IHtcbiAgICAgIFJlZjogXCJuZXd6b25lMUQwMTE5MzZcIixcbiAgICB9LFxuICB9KTtcblxuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlKFwiQVdTOjpSb3V0ZTUzOjpIb3N0ZWRab25lXCIsIHtcbiAgICBOYW1lOiBcInd3dy50ZXN0LWV4YW1wbGUuY29tLlwiLFxuICAgIFZQQ3M6IFtcbiAgICAgIHtcbiAgICAgICAgVlBDSWQ6IHtcbiAgICAgICAgICBSZWY6IFwiVnBjODM3OEVCMzhcIixcbiAgICAgICAgfSxcbiAgICAgICAgVlBDUmVnaW9uOiB7XG4gICAgICAgICAgUmVmOiBcIkFXUzo6UmVnaW9uXCIsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIGV4cGVjdChzdGFjaykudG9IYXZlUmVzb3VyY2UoXCJBV1M6OkFwaUdhdGV3YXk6OlJlc3RBcGlcIiwge1xuICAgIEVuZHBvaW50Q29uZmlndXJhdGlvbjoge1xuICAgICAgVHlwZXM6IFtcbiAgICAgICAgXCJSRUdJT05BTFwiXG4gICAgICBdXG4gICAgfSxcbiAgICBOYW1lOiBcIlJlc3RBcGlcIlxuICB9KTtcbn0pOyJdfQ==