@sitblueprint/website-construct 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/docs/CHANGELOG.md +26 -0
- package/lambda/index.d.ts +11 -0
- package/lambda/index.js +238 -0
- package/lambda/index.ts +335 -0
- package/lib/index.d.ts +44 -0
- package/lib/index.js +173 -10
- package/lib/index.ts +250 -8
- package/package.json +5 -5
- package/test/website-construct.test.js +212 -8
- package/test/website-construct.test.ts +229 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sitblueprint/website-construct",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "A reusable AWS CDK construct for deploying static websites with optional custom domain support.",
|
|
5
5
|
"author": "Miguel Merlin <mmerlin@stevens.edu>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/jest": "^29.5.14",
|
|
34
|
-
"@types/node": "
|
|
35
|
-
"aws-cdk-lib": "2.
|
|
34
|
+
"@types/node": "24.10.1",
|
|
35
|
+
"aws-cdk-lib": "2.237.1",
|
|
36
36
|
"constructs": "^10.0.0",
|
|
37
37
|
"jest": "^29.7.0",
|
|
38
38
|
"prettier": "^3.6.2",
|
|
39
39
|
"ts-jest": "^29.2.5",
|
|
40
|
-
"typescript": "~5.
|
|
40
|
+
"typescript": "~5.9.3"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"aws-cdk-lib": "2.
|
|
43
|
+
"aws-cdk-lib": "2.237.1",
|
|
44
44
|
"constructs": "^10.0.0"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
36
|
const assertions_1 = require("aws-cdk-lib/assertions");
|
|
27
37
|
const cdk = __importStar(require("aws-cdk-lib"));
|
|
@@ -226,6 +236,74 @@ describe("Website", () => {
|
|
|
226
236
|
Name: "example.com.",
|
|
227
237
|
});
|
|
228
238
|
});
|
|
239
|
+
test("configures CloudFront with both subdomain and root domain aliases when includeRootDomain is true", () => {
|
|
240
|
+
const dualDomainConfig = {
|
|
241
|
+
domainName: "example.com",
|
|
242
|
+
subdomainName: "www",
|
|
243
|
+
certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012",
|
|
244
|
+
includeRootDomain: true,
|
|
245
|
+
};
|
|
246
|
+
const props = {
|
|
247
|
+
bucketName: "test-website-bucket",
|
|
248
|
+
indexFile: "index.html",
|
|
249
|
+
errorFile: "error.html",
|
|
250
|
+
domainConfig: dualDomainConfig,
|
|
251
|
+
};
|
|
252
|
+
new lib_1.Website(stack, "TestWebsite", props);
|
|
253
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
254
|
+
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
255
|
+
DistributionConfig: {
|
|
256
|
+
Aliases: ["www.example.com", "example.com"],
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
test("creates two Route53 A records when includeRootDomain is true", () => {
|
|
261
|
+
const dualDomainConfig = {
|
|
262
|
+
domainName: "example.com",
|
|
263
|
+
subdomainName: "www",
|
|
264
|
+
certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012",
|
|
265
|
+
includeRootDomain: true,
|
|
266
|
+
};
|
|
267
|
+
const props = {
|
|
268
|
+
bucketName: "test-website-bucket",
|
|
269
|
+
indexFile: "index.html",
|
|
270
|
+
errorFile: "error.html",
|
|
271
|
+
domainConfig: dualDomainConfig,
|
|
272
|
+
};
|
|
273
|
+
new lib_1.Website(stack, "TestWebsite", props);
|
|
274
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
275
|
+
template.resourceCountIs("AWS::Route53::RecordSet", 2);
|
|
276
|
+
template.hasResourceProperties("AWS::Route53::RecordSet", {
|
|
277
|
+
Name: "www.example.com.",
|
|
278
|
+
Type: "A",
|
|
279
|
+
});
|
|
280
|
+
template.hasResourceProperties("AWS::Route53::RecordSet", {
|
|
281
|
+
Name: "example.com.",
|
|
282
|
+
Type: "A",
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
test("ignores includeRootDomain if subdomain is empty to avoid duplicates", () => {
|
|
286
|
+
const domainConfigWithoutSub = {
|
|
287
|
+
domainName: "example.com",
|
|
288
|
+
subdomainName: "",
|
|
289
|
+
certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012",
|
|
290
|
+
includeRootDomain: true,
|
|
291
|
+
};
|
|
292
|
+
const props = {
|
|
293
|
+
bucketName: "test-website-bucket",
|
|
294
|
+
indexFile: "index.html",
|
|
295
|
+
errorFile: "error.html",
|
|
296
|
+
domainConfig: domainConfigWithoutSub,
|
|
297
|
+
};
|
|
298
|
+
new lib_1.Website(stack, "TestWebsite", props);
|
|
299
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
300
|
+
template.resourceCountIs("AWS::Route53::RecordSet", 1);
|
|
301
|
+
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
302
|
+
DistributionConfig: {
|
|
303
|
+
Aliases: ["example.com"],
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
});
|
|
229
307
|
});
|
|
230
308
|
describe("Private methods", () => {
|
|
231
309
|
test("_getFullDomainName returns correct domain with subdomain", () => {
|
|
@@ -289,4 +367,130 @@ describe("Website", () => {
|
|
|
289
367
|
});
|
|
290
368
|
});
|
|
291
369
|
});
|
|
292
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic2l0ZS1jb25zdHJ1Y3QudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnNpdGUtY29uc3RydWN0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHVEQUF5RDtBQUN6RCxpREFBbUM7QUFDbkMsZ0NBQTZEO0FBRTdELFFBQVEsQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFO0lBQ3ZCLElBQUksR0FBWSxDQUFDO0lBQ2pCLElBQUksS0FBZ0IsQ0FBQztJQUVyQixVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsR0FBRyxHQUFHLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFdBQVcsRUFBRTtZQUN0QyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUU7U0FDdEQsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQ25CLDBFQUEwRSxFQUMxRTtZQUNFLEVBQUUsRUFBRSwyQkFBMkI7WUFDL0IsSUFBSSxFQUFFLGNBQWM7U0FDckIsQ0FDRixDQUFDO0lBQ0osQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMscUJBQXFCLEVBQUUsR0FBRyxFQUFFO1FBQ25DLElBQUksQ0FBQyw0Q0FBNEMsRUFBRSxHQUFHLEVBQUU7WUFDdEQsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLGlCQUFpQixFQUFFO2dCQUNoRCxvQkFBb0IsRUFBRTtvQkFDcEIsYUFBYSxFQUFFLFlBQVk7b0JBQzNCLGFBQWEsRUFBRSxZQUFZO2lCQUM1QjtnQkFDRCxnQkFBZ0IsRUFBRTtvQkFDaEIsaUNBQWlDLEVBQUU7d0JBQ2pDOzRCQUNFLDZCQUE2QixFQUFFO2dDQUM3QixZQUFZLEVBQUUsUUFBUTs2QkFDdkI7eUJBQ0Y7cUJBQ0Y7aUJBQ0Y7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQywyQ0FBMkMsRUFBRSxHQUFHLEVBQUU7WUFDckQsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsUUFBUSxDQUFDLHFCQUFxQixDQUM1QixpREFBaUQsRUFDakQ7Z0JBQ0Usb0NBQW9DLEVBQUU7b0JBQ3BDLE9BQU8sRUFBRSxrQkFBSyxDQUFDLFFBQVEsRUFBRTtpQkFDMUI7YUFDRixDQUNGLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyw0REFBNEQsRUFBRSxHQUFHLEVBQUU7WUFDdEUsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLCtCQUErQixFQUFFO2dCQUM5RCxrQkFBa0IsRUFBRTtvQkFDbEIsb0JBQW9CLEVBQUU7d0JBQ3BCLG9CQUFvQixFQUFFLG1CQUFtQjtxQkFDMUM7b0JBQ0Qsb0JBQW9CLEVBQUU7d0JBQ3BCOzRCQUNFLFNBQVMsRUFBRSxHQUFHOzRCQUNkLFlBQVksRUFBRSxHQUFHOzRCQUNqQixnQkFBZ0IsRUFBRSxXQUFXOzRCQUM3QixrQkFBa0IsRUFBRSxJQUFJO3lCQUN6QjtxQkFDRjtvQkFDRCxVQUFVLEVBQUUsZ0JBQWdCO29CQUM1QixPQUFPLEVBQUUsSUFBSTtpQkFDZDthQUNGLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGlDQUFpQyxFQUFFLEdBQUcsRUFBRTtZQUMzQyxNQUFNLEtBQUssR0FBaUI7Z0JBQzFCLFVBQVUsRUFBRSxxQkFBcUI7Z0JBQ2pDLFNBQVMsRUFBRSxZQUFZO2dCQUN2QixTQUFTLEVBQUUsWUFBWTthQUN4QixDQUFDO1lBRUYsTUFBTSxPQUFPLEdBQUcsSUFBSSxhQUFPLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUV6RCxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsaUNBQWlDLEVBQUUsR0FBRyxFQUFFO1FBQy9DLElBQUksQ0FBQywwQ0FBMEMsRUFBRSxHQUFHLEVBQUU7WUFDcEQsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7Z0JBQ3ZCLHdCQUF3QixFQUFFLGtCQUFrQjthQUM3QyxDQUFDO1lBRUYsSUFBSSxhQUFPLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUV6QyxNQUFNLFFBQVEsR0FBRyxxQkFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUUzQyxRQUFRLENBQUMscUJBQXFCLENBQUMsK0JBQStCLEVBQUU7Z0JBQzlELGtCQUFrQixFQUFFO29CQUNsQixvQkFBb0IsRUFBRTt3QkFDcEI7NEJBQ0UsU0FBUyxFQUFFLEdBQUc7NEJBQ2QsWUFBWSxFQUFFLEdBQUc7NEJBQ2pCLGdCQUFnQixFQUFFLGtCQUFrQjs0QkFDcEMsa0JBQWtCLEVBQUUsSUFBSTt5QkFDekI7cUJBQ0Y7aUJBQ0Y7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxxRUFBcUUsRUFBRSxHQUFHLEVBQUU7WUFDL0UsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLCtCQUErQixFQUFFO2dCQUM5RCxrQkFBa0IsRUFBRTtvQkFDbEIsb0JBQW9CLEVBQUU7d0JBQ3BCOzRCQUNFLFNBQVMsRUFBRSxHQUFHOzRCQUNkLFlBQVksRUFBRSxHQUFHOzRCQUNqQixnQkFBZ0IsRUFBRSxXQUFXOzRCQUM3QixrQkFBa0IsRUFBRSxJQUFJO3lCQUN6QjtxQkFDRjtpQkFDRjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO1FBQ3BDLE1BQU0sWUFBWSxHQUFpQjtZQUNqQyxVQUFVLEVBQUUsYUFBYTtZQUN6QixhQUFhLEVBQUUsS0FBSztZQUNwQixjQUFjLEVBQ1oscUZBQXFGO1NBQ3hGLENBQUM7UUFFRixJQUFJLENBQUMsdURBQXVELEVBQUUsR0FBRyxFQUFFO1lBQ2pFLE1BQU0sS0FBSyxHQUFpQjtnQkFDMUIsVUFBVSxFQUFFLHFCQUFxQjtnQkFDakMsU0FBUyxFQUFFLFlBQVk7Z0JBQ3ZCLFNBQVMsRUFBRSxZQUFZO2dCQUN2QixZQUFZO2FBQ2IsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLCtCQUErQixFQUFFO2dCQUM5RCxrQkFBa0IsRUFBRTtvQkFDbEIsT0FBTyxFQUFFLENBQUMsaUJBQWlCLENBQUM7b0JBQzVCLGlCQUFpQixFQUFFO3dCQUNqQixpQkFBaUIsRUFBRSxZQUFZLENBQUMsY0FBYzt3QkFDOUMsZ0JBQWdCLEVBQUUsVUFBVTtxQkFDN0I7aUJBQ0Y7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyx5REFBeUQsRUFBRSxHQUFHLEVBQUU7WUFDbkUsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7Z0JBQ3ZCLFlBQVk7YUFDYixDQUFDO1lBRUYsSUFBSSxhQUFPLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUV6QyxNQUFNLFFBQVEsR0FBRyxxQkFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUUzQyxRQUFRLENBQUMscUJBQXFCLENBQUMseUJBQXlCLEVBQUU7Z0JBQ3hELElBQUksRUFBRSxHQUFHO2dCQUNULElBQUksRUFBRSxrQkFBa0I7Z0JBQ3hCLFdBQVcsRUFBRTtvQkFDWCxPQUFPLEVBQUUsa0JBQUssQ0FBQyxRQUFRLEVBQUU7b0JBQ3pCLFlBQVksRUFBRSxrQkFBSyxDQUFDLFFBQVEsRUFBRTtpQkFDL0I7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxrQ0FBa0MsRUFBRSxHQUFHLEVBQUU7WUFDNUMsTUFBTSxzQkFBc0IsR0FBaUI7Z0JBQzNDLFVBQVUsRUFBRSxhQUFhO2dCQUN6QixhQUFhLEVBQUUsRUFBRTtnQkFDakIsY0FBYyxFQUNaLHFGQUFxRjthQUN4RixDQUFDO1lBRUYsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUscUJBQXFCO2dCQUNqQyxTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7Z0JBQ3ZCLFlBQVksRUFBRSxzQkFBc0I7YUFDckMsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFM0MsUUFBUSxDQUFDLHFCQUFxQixDQUFDLCtCQUErQixFQUFFO2dCQUM5RCxrQkFBa0IsRUFBRTtvQkFDbEIsT0FBTyxFQUFFLENBQUMsYUFBYSxDQUFDO2lCQUN6QjthQUNGLENBQUMsQ0FBQztZQUVILFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQyx5QkFBeUIsRUFBRTtnQkFDeEQsSUFBSSxFQUFFLEdBQUc7Z0JBQ1QsSUFBSSxFQUFFLGNBQWM7YUFDckIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxpQkFBaUIsRUFBRSxHQUFHLEVBQUU7UUFDL0IsSUFBSSxDQUFDLDBEQUEwRCxFQUFFLEdBQUcsRUFBRTtZQUNwRSxNQUFNLEtBQUssR0FBaUI7Z0JBQzFCLFVBQVUsRUFBRSxhQUFhO2dCQUN6QixTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLE1BQU0sU0FBUyxHQUFHLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFM0QsNkRBQTZEO1lBQzdELE1BQU0saUJBQWlCLEdBQUksU0FBaUIsQ0FBQyxrQkFBa0IsQ0FBQztZQUVoRSxNQUFNLFlBQVksR0FBaUI7Z0JBQ2pDLFVBQVUsRUFBRSxhQUFhO2dCQUN6QixhQUFhLEVBQUUsTUFBTTtnQkFDckIsY0FBYyxFQUFFLFVBQVU7YUFDM0IsQ0FBQztZQUVGLE1BQU0sTUFBTSxHQUFHLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQy9DLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxnRUFBZ0UsRUFBRSxHQUFHLEVBQUU7WUFDMUUsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUsYUFBYTtnQkFDekIsU0FBUyxFQUFFLFlBQVk7Z0JBQ3ZCLFNBQVMsRUFBRSxZQUFZO2FBQ3hCLENBQUM7WUFFRixNQUFNLFNBQVMsR0FBRyxJQUFJLGFBQU8sQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRTNELE1BQU0saUJBQWlCLEdBQUksU0FBaUIsQ0FBQyxrQkFBa0IsQ0FBQztZQUVoRSxNQUFNLFlBQVksR0FBaUI7Z0JBQ2pDLFVBQVUsRUFBRSxhQUFhO2dCQUN6QixhQUFhLEVBQUUsRUFBRTtnQkFDakIsY0FBYyxFQUFFLFVBQVU7YUFDM0IsQ0FBQztZQUVGLE1BQU0sTUFBTSxHQUFHLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQy9DLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDckMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFO1FBQzFCLElBQUksQ0FBQywrQkFBK0IsRUFBRSxHQUFHLEVBQUU7WUFDekMsTUFBTSxLQUFLLEdBQWlCO2dCQUMxQixVQUFVLEVBQUUsZ0JBQWdCO2dCQUM1QixTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLE1BQU0sQ0FBQyxHQUFHLEVBQUU7Z0JBQ1YsSUFBSSxhQUFPLENBQUMsS0FBSyxFQUFFLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMzQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUM7WUFFakIsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0MsUUFBUSxDQUFDLGVBQWUsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvQyxRQUFRLENBQUMsZUFBZSxDQUFDLCtCQUErQixFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzdELFFBQVEsQ0FBQyxlQUFlLENBQ3RCLGlEQUFpRCxFQUNqRCxDQUFDLENBQ0YsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHNFQUFzRSxFQUFFLEdBQUcsRUFBRTtZQUNoRixNQUFNLEtBQUssR0FBaUI7Z0JBQzFCLFVBQVUsRUFBRSxhQUFhO2dCQUN6QixTQUFTLEVBQUUsWUFBWTtnQkFDdkIsU0FBUyxFQUFFLFlBQVk7YUFDeEIsQ0FBQztZQUVGLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFFekMsTUFBTSxRQUFRLEdBQUcscUJBQVEsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0MsUUFBUSxDQUFDLGVBQWUsQ0FBQyx5QkFBeUIsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN6RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBUZW1wbGF0ZSwgTWF0Y2ggfSBmcm9tIFwiYXdzLWNkay1saWIvYXNzZXJ0aW9uc1wiO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0IHsgV2Vic2l0ZSwgV2Vic2l0ZVByb3BzLCBEb21haW5Db25maWcgfSBmcm9tIFwiLi4vbGliXCI7XG5cbmRlc2NyaWJlKFwiV2Vic2l0ZVwiLCAoKSA9PiB7XG4gIGxldCBhcHA6IGNkay5BcHA7XG4gIGxldCBzdGFjazogY2RrLlN0YWNrO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGFwcCA9IG5ldyBjZGsuQXBwKCk7XG4gICAgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKGFwcCwgXCJUZXN0U3RhY2tcIiwge1xuICAgICAgZW52OiB7IGFjY291bnQ6IFwiMTIzNDU2Nzg5MDEyXCIsIHJlZ2lvbjogXCJ1cy1lYXN0LTFcIiB9LFxuICAgIH0pO1xuICAgIHN0YWNrLm5vZGUuc2V0Q29udGV4dChcbiAgICAgIFwiaG9zdGVkLXpvbmU6YWNjb3VudD0xMjM0NTY3ODkwMTI6ZG9tYWluTmFtZT1leGFtcGxlLmNvbTpyZWdpb249dXMtZWFzdC0xXCIsXG4gICAgICB7XG4gICAgICAgIElkOiBcIi9ob3N0ZWR6b25lL1oxMjM0NTY3ODkwMTJcIixcbiAgICAgICAgTmFtZTogXCJleGFtcGxlLmNvbS5cIixcbiAgICAgIH0sXG4gICAgKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJCYXNpYyBmdW5jdGlvbmFsaXR5XCIsICgpID0+IHtcbiAgICB0ZXN0KFwiY3JlYXRlcyBTMyBidWNrZXQgd2l0aCBiYXNpYyBjb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC13ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgICAgIFdlYnNpdGVDb25maWd1cmF0aW9uOiB7XG4gICAgICAgICAgSW5kZXhEb2N1bWVudDogXCJpbmRleC5odG1sXCIsXG4gICAgICAgICAgRXJyb3JEb2N1bWVudDogXCJlcnJvci5odG1sXCIsXG4gICAgICAgIH0sXG4gICAgICAgIEJ1Y2tldEVuY3J5cHRpb246IHtcbiAgICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb246IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQ6IHtcbiAgICAgICAgICAgICAgICBTU0VBbGdvcml0aG06IFwiQUVTMjU2XCIsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJjcmVhdGVzIENsb3VkRnJvbnQgT3JpZ2luIEFjY2VzcyBJZGVudGl0eVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3Qtd2Vic2l0ZS1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXG4gICAgICAgIFwiQVdTOjpDbG91ZEZyb250OjpDbG91ZEZyb250T3JpZ2luQWNjZXNzSWRlbnRpdHlcIixcbiAgICAgICAge1xuICAgICAgICAgIENsb3VkRnJvbnRPcmlnaW5BY2Nlc3NJZGVudGl0eUNvbmZpZzoge1xuICAgICAgICAgICAgQ29tbWVudDogTWF0Y2guYW55VmFsdWUoKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJjcmVhdGVzIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uIHdpdGggY29ycmVjdCBjb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC13ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICAgICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgRGVmYXVsdENhY2hlQmVoYXZpb3I6IHtcbiAgICAgICAgICAgIFZpZXdlclByb3RvY29sUG9saWN5OiBcInJlZGlyZWN0LXRvLWh0dHBzXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBDdXN0b21FcnJvclJlc3BvbnNlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBFcnJvckNvZGU6IDQwNCxcbiAgICAgICAgICAgICAgUmVzcG9uc2VDb2RlOiA0MDQsXG4gICAgICAgICAgICAgIFJlc3BvbnNlUGFnZVBhdGg6IFwiLzQwNC5odG1sXCIsXG4gICAgICAgICAgICAgIEVycm9yQ2FjaGluZ01pblRUTDogMTgwMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBQcmljZUNsYXNzOiBcIlByaWNlQ2xhc3NfMTAwXCIsXG4gICAgICAgICAgRW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImV4cG9zZXMgQ2xvdWRGcm9udCBkaXN0cmlidXRpb25cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCB3ZWJzaXRlID0gbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBleHBlY3Qod2Vic2l0ZS5kaXN0cmlidXRpb24pLnRvQmVEZWZpbmVkKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiQ3VzdG9tIGVycm9yIHBhZ2UgY29uZmlndXJhdGlvblwiLCAoKSA9PiB7XG4gICAgdGVzdChcInVzZXMgY3VzdG9tIG5vdCBmb3VuZCByZXNwb25zZSBwYWdlIHBhdGhcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICAgIG5vdEZvdW5kUmVzcG9uc2VQYWdlUGF0aDogXCIvY3VzdG9tLTQwNC5odG1sXCIsXG4gICAgICB9O1xuXG4gICAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBDdXN0b21FcnJvclJlc3BvbnNlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBFcnJvckNvZGU6IDQwNCxcbiAgICAgICAgICAgICAgUmVzcG9uc2VDb2RlOiA0MDQsXG4gICAgICAgICAgICAgIFJlc3BvbnNlUGFnZVBhdGg6IFwiL2N1c3RvbS00MDQuaHRtbFwiLFxuICAgICAgICAgICAgICBFcnJvckNhY2hpbmdNaW5UVEw6IDE4MDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJ1c2VzIGRlZmF1bHQgNDA0Lmh0bWwgd2hlbiBub3RGb3VuZFJlc3BvbnNlUGFnZVBhdGggaXMgbm90IHByb3ZpZGVkXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC13ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICAgICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgQ3VzdG9tRXJyb3JSZXNwb25zZXM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgRXJyb3JDb2RlOiA0MDQsXG4gICAgICAgICAgICAgIFJlc3BvbnNlQ29kZTogNDA0LFxuICAgICAgICAgICAgICBSZXNwb25zZVBhZ2VQYXRoOiBcIi80MDQuaHRtbFwiLFxuICAgICAgICAgICAgICBFcnJvckNhY2hpbmdNaW5UVEw6IDE4MDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJEb21haW4gY29uZmlndXJhdGlvblwiLCAoKSA9PiB7XG4gICAgY29uc3QgZG9tYWluQ29uZmlnOiBEb21haW5Db25maWcgPSB7XG4gICAgICBkb21haW5OYW1lOiBcImV4YW1wbGUuY29tXCIsXG4gICAgICBzdWJkb21haW5OYW1lOiBcInd3d1wiLFxuICAgICAgY2VydGlmaWNhdGVBcm46XG4gICAgICAgIFwiYXJuOmF3czphY206dXMtZWFzdC0xOjEyMzQ1Njc4OTAxMjpjZXJ0aWZpY2F0ZS8xMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwMTJcIixcbiAgICB9O1xuXG4gICAgdGVzdChcImNvbmZpZ3VyZXMgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gd2l0aCBjdXN0b20gZG9tYWluXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC13ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgICBkb21haW5Db25maWcsXG4gICAgICB9O1xuXG4gICAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBBbGlhc2VzOiBbXCJ3d3cuZXhhbXBsZS5jb21cIl0sXG4gICAgICAgICAgVmlld2VyQ2VydGlmaWNhdGU6IHtcbiAgICAgICAgICAgIEFjbUNlcnRpZmljYXRlQXJuOiBkb21haW5Db25maWcuY2VydGlmaWNhdGVBcm4sXG4gICAgICAgICAgICBTc2xTdXBwb3J0TWV0aG9kOiBcInNuaS1vbmx5XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImNyZWF0ZXMgUm91dGU1MyBBIHJlY29yZCB3aGVuIGRvbWFpbiBjb25maWcgaXMgcHJvdmlkZWRcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICAgIGRvbWFpbkNvbmZpZyxcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlJvdXRlNTM6OlJlY29yZFNldFwiLCB7XG4gICAgICAgIFR5cGU6IFwiQVwiLFxuICAgICAgICBOYW1lOiBcInd3dy5leGFtcGxlLmNvbS5cIixcbiAgICAgICAgQWxpYXNUYXJnZXQ6IHtcbiAgICAgICAgICBETlNOYW1lOiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgICAgICAgIEhvc3RlZFpvbmVJZDogTWF0Y2guYW55VmFsdWUoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImhhbmRsZXMgZG9tYWluIHdpdGhvdXQgc3ViZG9tYWluXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGRvbWFpbkNvbmZpZ1dpdGhvdXRTdWI6IERvbWFpbkNvbmZpZyA9IHtcbiAgICAgICAgZG9tYWluTmFtZTogXCJleGFtcGxlLmNvbVwiLFxuICAgICAgICBzdWJkb21haW5OYW1lOiBcIlwiLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjpcbiAgICAgICAgICBcImFybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyXCIsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3Qtd2Vic2l0ZS1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgICAgZG9tYWluQ29uZmlnOiBkb21haW5Db25maWdXaXRob3V0U3ViLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIHtcbiAgICAgICAgRGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgICAgQWxpYXNlczogW1wiZXhhbXBsZS5jb21cIl0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpSb3V0ZTUzOjpSZWNvcmRTZXRcIiwge1xuICAgICAgICBUeXBlOiBcIkFcIixcbiAgICAgICAgTmFtZTogXCJleGFtcGxlLmNvbS5cIixcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIlByaXZhdGUgbWV0aG9kc1wiLCAoKSA9PiB7XG4gICAgdGVzdChcIl9nZXRGdWxsRG9tYWluTmFtZSByZXR1cm5zIGNvcnJlY3QgZG9tYWluIHdpdGggc3ViZG9tYWluXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgLy8gQWNjZXNzIHByaXZhdGUgbWV0aG9kIHRocm91Z2ggYnJhY2tldCBub3RhdGlvbiBmb3IgdGVzdGluZ1xuICAgICAgY29uc3QgZ2V0RnVsbERvbWFpbk5hbWUgPSAoY29uc3RydWN0IGFzIGFueSkuX2dldEZ1bGxEb21haW5OYW1lO1xuXG4gICAgICBjb25zdCBkb21haW5Db25maWc6IERvbWFpbkNvbmZpZyA9IHtcbiAgICAgICAgZG9tYWluTmFtZTogXCJleGFtcGxlLmNvbVwiLFxuICAgICAgICBzdWJkb21haW5OYW1lOiBcImJsb2dcIixcbiAgICAgICAgY2VydGlmaWNhdGVBcm46IFwiYXJuOnRlc3RcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGdldEZ1bGxEb21haW5OYW1lKGRvbWFpbkNvbmZpZyk7XG4gICAgICBleHBlY3QocmVzdWx0KS50b0JlKFwiYmxvZy5leGFtcGxlLmNvbVwiKTtcbiAgICB9KTtcblxuICAgIHRlc3QoXCJfZ2V0RnVsbERvbWFpbk5hbWUgcmV0dXJucyByb290IGRvbWFpbiB3aGVuIHN1YmRvbWFpbiBpcyBlbXB0eVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3QtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBjb25zdHJ1Y3QgPSBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IGdldEZ1bGxEb21haW5OYW1lID0gKGNvbnN0cnVjdCBhcyBhbnkpLl9nZXRGdWxsRG9tYWluTmFtZTtcblxuICAgICAgY29uc3QgZG9tYWluQ29uZmlnOiBEb21haW5Db25maWcgPSB7XG4gICAgICAgIGRvbWFpbk5hbWU6IFwiZXhhbXBsZS5jb21cIixcbiAgICAgICAgc3ViZG9tYWluTmFtZTogXCJcIixcbiAgICAgICAgY2VydGlmaWNhdGVBcm46IFwiYXJuOnRlc3RcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGdldEZ1bGxEb21haW5OYW1lKGRvbWFpbkNvbmZpZyk7XG4gICAgICBleHBlY3QocmVzdWx0KS50b0JlKFwiZXhhbXBsZS5jb21cIik7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiRWRnZSBjYXNlc1wiLCAoKSA9PiB7XG4gICAgdGVzdChcImhhbmRsZXMgbWluaW1hbCBjb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwibWluaW1hbC1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIGV4cGVjdCgoKSA9PiB7XG4gICAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcbiAgICAgIH0pLm5vdC50b1Rocm93KCk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICAgIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCAxKTtcbiAgICAgIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6Q2xvdWRGcm9udDo6RGlzdHJpYnV0aW9uXCIsIDEpO1xuICAgICAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFxuICAgICAgICBcIkFXUzo6Q2xvdWRGcm9udDo6Q2xvdWRGcm9udE9yaWdpbkFjY2Vzc0lkZW50aXR5XCIsXG4gICAgICAgIDEsXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImRvZXMgbm90IGNyZWF0ZSBSb3V0ZTUzIHJlc291cmNlcyB3aGVuIGRvbWFpbiBjb25maWcgaXMgbm90IHByb3ZpZGVkXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpSb3V0ZTUzOjpSZWNvcmRTZXRcIiwgMCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
370
|
+
describe("Preview config on Website", () => {
|
|
371
|
+
let app;
|
|
372
|
+
let stack;
|
|
373
|
+
beforeEach(() => {
|
|
374
|
+
app = new cdk.App();
|
|
375
|
+
stack = new cdk.Stack(app, "PreviewTestStack", {
|
|
376
|
+
env: { account: "123456789012", region: "us-east-1" },
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
test("creates two preview buckets by default when previewConfig is enabled", () => {
|
|
380
|
+
const website = new lib_1.Website(stack, "PreviewEnabledWebsite", {
|
|
381
|
+
bucketName: "website-bucket",
|
|
382
|
+
indexFile: "index.html",
|
|
383
|
+
errorFile: "error.html",
|
|
384
|
+
previewConfig: {
|
|
385
|
+
bucketPrefix: "preview-bucket",
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
389
|
+
template.resourceCountIs("AWS::S3::Bucket", 3);
|
|
390
|
+
expect(website.previewEnvironment).toBeDefined();
|
|
391
|
+
});
|
|
392
|
+
test("creates requested number of preview buckets from previewConfig", () => {
|
|
393
|
+
new lib_1.Website(stack, "PreviewEnabledWebsite", {
|
|
394
|
+
bucketName: "website-bucket",
|
|
395
|
+
indexFile: "index.html",
|
|
396
|
+
errorFile: "error.html",
|
|
397
|
+
previewConfig: {
|
|
398
|
+
bucketPrefix: "preview-bucket",
|
|
399
|
+
bucketCount: 3,
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
403
|
+
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
404
|
+
});
|
|
405
|
+
test("reuses website index and error files for preview buckets", () => {
|
|
406
|
+
new lib_1.Website(stack, "PreviewEnabledWebsite", {
|
|
407
|
+
bucketName: "website-bucket",
|
|
408
|
+
indexFile: "app.html",
|
|
409
|
+
errorFile: "fallback.html",
|
|
410
|
+
previewConfig: {
|
|
411
|
+
bucketPrefix: "preview-bucket",
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
415
|
+
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
416
|
+
BucketName: "preview-bucket-0",
|
|
417
|
+
WebsiteConfiguration: {
|
|
418
|
+
IndexDocument: "app.html",
|
|
419
|
+
ErrorDocument: "fallback.html",
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
423
|
+
BucketName: "preview-bucket-1",
|
|
424
|
+
WebsiteConfiguration: {
|
|
425
|
+
IndexDocument: "app.html",
|
|
426
|
+
ErrorDocument: "fallback.html",
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
test("creates lease table with repo-pr lookup index when preview is enabled", () => {
|
|
431
|
+
new lib_1.Website(stack, "PreviewEnabledWebsite", {
|
|
432
|
+
bucketName: "website-bucket",
|
|
433
|
+
indexFile: "index.html",
|
|
434
|
+
errorFile: "error.html",
|
|
435
|
+
previewConfig: {
|
|
436
|
+
bucketPrefix: "preview-bucket",
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
440
|
+
template.hasResourceProperties("AWS::DynamoDB::Table", {
|
|
441
|
+
KeySchema: [
|
|
442
|
+
{
|
|
443
|
+
AttributeName: "slotId",
|
|
444
|
+
KeyType: "HASH",
|
|
445
|
+
},
|
|
446
|
+
],
|
|
447
|
+
GlobalSecondaryIndexes: [
|
|
448
|
+
{
|
|
449
|
+
IndexName: "RepoPrKeyIndex",
|
|
450
|
+
KeySchema: [
|
|
451
|
+
{
|
|
452
|
+
AttributeName: "repoPrKey",
|
|
453
|
+
KeyType: "HASH",
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
Projection: {
|
|
457
|
+
ProjectionType: "ALL",
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
],
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
test("creates lease API routes when preview is enabled", () => {
|
|
464
|
+
new lib_1.Website(stack, "PreviewEnabledWebsite", {
|
|
465
|
+
bucketName: "website-bucket",
|
|
466
|
+
indexFile: "index.html",
|
|
467
|
+
errorFile: "error.html",
|
|
468
|
+
previewConfig: {
|
|
469
|
+
bucketPrefix: "preview-bucket",
|
|
470
|
+
},
|
|
471
|
+
});
|
|
472
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
473
|
+
template.hasResourceProperties("AWS::ApiGateway::Resource", {
|
|
474
|
+
PathPart: "claim",
|
|
475
|
+
});
|
|
476
|
+
template.hasResourceProperties("AWS::ApiGateway::Resource", {
|
|
477
|
+
PathPart: "heartbeat",
|
|
478
|
+
});
|
|
479
|
+
template.hasResourceProperties("AWS::ApiGateway::Resource", {
|
|
480
|
+
PathPart: "release",
|
|
481
|
+
});
|
|
482
|
+
template.resourceCountIs("AWS::ApiGateway::Method", 3);
|
|
483
|
+
});
|
|
484
|
+
test("does not create preview resources when previewConfig is omitted", () => {
|
|
485
|
+
const website = new lib_1.Website(stack, "WebsiteWithoutPreview", {
|
|
486
|
+
bucketName: "website-bucket",
|
|
487
|
+
indexFile: "index.html",
|
|
488
|
+
errorFile: "error.html",
|
|
489
|
+
});
|
|
490
|
+
const template = assertions_1.Template.fromStack(stack);
|
|
491
|
+
template.resourceCountIs("AWS::DynamoDB::Table", 0);
|
|
492
|
+
template.resourceCountIs("AWS::ApiGateway::RestApi", 0);
|
|
493
|
+
expect(website.previewEnvironment).toBeUndefined();
|
|
494
|
+
});
|
|
495
|
+
});
|
|
496
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic2l0ZS1jb25zdHJ1Y3QudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnNpdGUtY29uc3RydWN0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx1REFBeUQ7QUFDekQsaURBQW1DO0FBQ25DLGdDQUE2RDtBQUU3RCxRQUFRLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRTtJQUN2QixJQUFJLEdBQVksQ0FBQztJQUNqQixJQUFJLEtBQWdCLENBQUM7SUFFckIsVUFBVSxDQUFDLEdBQUcsRUFBRTtRQUNkLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNwQixLQUFLLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUU7WUFDdEMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFO1NBQ3RELENBQUMsQ0FBQztRQUNILEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUNuQiwwRUFBMEUsRUFDMUU7WUFDRSxFQUFFLEVBQUUsMkJBQTJCO1lBQy9CLElBQUksRUFBRSxjQUFjO1NBQ3JCLENBQ0YsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLHFCQUFxQixFQUFFLEdBQUcsRUFBRTtRQUNuQyxJQUFJLENBQUMsNENBQTRDLEVBQUUsR0FBRyxFQUFFO1lBQ3RELE1BQU0sS0FBSyxHQUFpQjtnQkFDMUIsVUFBVSxFQUFFLHFCQUFxQjtnQkFDakMsU0FBUyxFQUFFLFlBQVk7Z0JBQ3ZCLFNBQVMsRUFBRSxZQUFZO2FBQ3hCLENBQUM7WUFFRixJQUFJLGFBQU8sQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRXpDLE1BQU0sUUFBUSxHQUFHLHFCQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxD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QUM7SUFDekQsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsaUVBQWlFLEVBQUUsR0FBRyxFQUFFO1FBQzNFLE1BQU0sT0FBTyxHQUFHLElBQUksYUFBTyxDQUFDLEtBQUssRUFBRSx1QkFBdUIsRUFBRTtZQUMxRCxVQUFVLEVBQUUsZ0JBQWdCO1lBQzVCLFNBQVMsRUFBRSxZQUFZO1lBQ3ZCLFNBQVMsRUFBRSxZQUFZO1NBQ3hCLENBQUMsQ0FBQztRQUVILE1BQU0sUUFBUSxHQUFHLHFCQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNDLFFBQVEsQ0FBQyxlQUFlLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEQsUUFBUSxDQUFDLGVBQWUsQ0FBQywwQkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN4RCxNQUFNLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDckQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRlbXBsYXRlLCBNYXRjaCB9IGZyb20gXCJhd3MtY2RrLWxpYi9hc3NlcnRpb25zXCI7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBXZWJzaXRlLCBXZWJzaXRlUHJvcHMsIERvbWFpbkNvbmZpZyB9IGZyb20gXCIuLi9saWJcIjtcblxuZGVzY3JpYmUoXCJXZWJzaXRlXCIsICgpID0+IHtcbiAgbGV0IGFwcDogY2RrLkFwcDtcbiAgbGV0IHN0YWNrOiBjZGsuU3RhY2s7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgYXBwID0gbmV3IGNkay5BcHAoKTtcbiAgICBzdGFjayA9IG5ldyBjZGsuU3RhY2soYXBwLCBcIlRlc3RTdGFja1wiLCB7XG4gICAgICBlbnY6IHsgYWNjb3VudDogXCIxMjM0NTY3ODkwMTJcIiwgcmVnaW9uOiBcInVzLWVhc3QtMVwiIH0sXG4gICAgfSk7XG4gICAgc3RhY2subm9kZS5zZXRDb250ZXh0KFxuICAgICAgXCJob3N0ZWQtem9uZTphY2NvdW50PTEyMzQ1Njc4OTAxMjpkb21haW5OYW1lPWV4YW1wbGUuY29tOnJlZ2lvbj11cy1lYXN0LTFcIixcbiAgICAgIHtcbiAgICAgICAgSWQ6IFwiL2hvc3RlZHpvbmUvWjEyMzQ1Njc4OTAxMlwiLFxuICAgICAgICBOYW1lOiBcImV4YW1wbGUuY29tLlwiLFxuICAgICAgfSxcbiAgICApO1xuICB9KTtcblxuICBkZXNjcmliZShcIkJhc2ljIGZ1bmN0aW9uYWxpdHlcIiwgKCkgPT4ge1xuICAgIHRlc3QoXCJjcmVhdGVzIFMzIGJ1Y2tldCB3aXRoIGJhc2ljIGNvbmZpZ3VyYXRpb25cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICB9O1xuXG4gICAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpTMzo6QnVja2V0XCIsIHtcbiAgICAgICAgV2Vic2l0ZUNvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgICBJbmRleERvY3VtZW50OiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgICBFcnJvckRvY3VtZW50OiBcImVycm9yLmh0bWxcIixcbiAgICAgICAgfSxcbiAgICAgICAgQnVja2V0RW5jcnlwdGlvbjoge1xuICAgICAgICAgIFNlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdDoge1xuICAgICAgICAgICAgICAgIFNTRUFsZ29yaXRobTogXCJBRVMyNTZcIixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImNyZWF0ZXMgQ2xvdWRGcm9udCBPcmlnaW4gQWNjZXNzIElkZW50aXR5XCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC13ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcbiAgICAgICAgXCJBV1M6OkNsb3VkRnJvbnQ6OkNsb3VkRnJvbnRPcmlnaW5BY2Nlc3NJZGVudGl0eVwiLFxuICAgICAgICB7XG4gICAgICAgICAgQ2xvdWRGcm9udE9yaWdpbkFjY2Vzc0lkZW50aXR5Q29uZmlnOiB7XG4gICAgICAgICAgICBDb21tZW50OiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImNyZWF0ZXMgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gd2l0aCBjb3JyZWN0IGNvbmZpZ3VyYXRpb25cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICB9O1xuXG4gICAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBEZWZhdWx0Q2FjaGVCZWhhdmlvcjoge1xuICAgICAgICAgICAgVmlld2VyUHJvdG9jb2xQb2xpY3k6IFwicmVkaXJlY3QtdG8taHR0cHNcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIEN1c3RvbUVycm9yUmVzcG9uc2VzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIEVycm9yQ29kZTogNDA0LFxuICAgICAgICAgICAgICBSZXNwb25zZUNvZGU6IDQwNCxcbiAgICAgICAgICAgICAgUmVzcG9uc2VQYWdlUGF0aDogXCIvNDA0Lmh0bWxcIixcbiAgICAgICAgICAgICAgRXJyb3JDYWNoaW5nTWluVFRMOiAxODAwLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIFByaWNlQ2xhc3M6IFwiUHJpY2VDbGFzc18xMDBcIixcbiAgICAgICAgICBFbmFibGVkOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiZXhwb3NlcyBDbG91ZEZyb250IGRpc3RyaWJ1dGlvblwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3Qtd2Vic2l0ZS1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHdlYnNpdGUgPSBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGV4cGVjdCh3ZWJzaXRlLmRpc3RyaWJ1dGlvbikudG9CZURlZmluZWQoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJDdXN0b20gZXJyb3IgcGFnZSBjb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICB0ZXN0KFwidXNlcyBjdXN0b20gbm90IGZvdW5kIHJlc3BvbnNlIHBhZ2UgcGF0aFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3Qtd2Vic2l0ZS1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgICAgbm90Rm91bmRSZXNwb25zZVBhZ2VQYXRoOiBcIi9jdXN0b20tNDA0Lmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgICAgIEN1c3RvbUVycm9yUmVzcG9uc2VzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIEVycm9yQ29kZTogNDA0LFxuICAgICAgICAgICAgICBSZXNwb25zZUNvZGU6IDQwNCxcbiAgICAgICAgICAgICAgUmVzcG9uc2VQYWdlUGF0aDogXCIvY3VzdG9tLTQwNC5odG1sXCIsXG4gICAgICAgICAgICAgIEVycm9yQ2FjaGluZ01pblRUTDogMTgwMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdChcInVzZXMgZGVmYXVsdCA0MDQuaHRtbCB3aGVuIG5vdEZvdW5kUmVzcG9uc2VQYWdlUGF0aCBpcyBub3QgcHJvdmlkZWRcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICB9O1xuXG4gICAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBDdXN0b21FcnJvclJlc3BvbnNlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBFcnJvckNvZGU6IDQwNCxcbiAgICAgICAgICAgICAgUmVzcG9uc2VDb2RlOiA0MDQsXG4gICAgICAgICAgICAgIFJlc3BvbnNlUGFnZVBhdGg6IFwiLzQwNC5odG1sXCIsXG4gICAgICAgICAgICAgIEVycm9yQ2FjaGluZ01pblRUTDogMTgwMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZShcIkRvbWFpbiBjb25maWd1cmF0aW9uXCIsICgpID0+IHtcbiAgICBjb25zdCBkb21haW5Db25maWc6IERvbWFpbkNvbmZpZyA9IHtcbiAgICAgIGRvbWFpbk5hbWU6IFwiZXhhbXBsZS5jb21cIixcbiAgICAgIHN1YmRvbWFpbk5hbWU6IFwid3d3XCIsXG4gICAgICBjZXJ0aWZpY2F0ZUFybjpcbiAgICAgICAgXCJhcm46YXdzOmFjbTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOmNlcnRpZmljYXRlLzEyMzQ1Njc4LTEyMzQtMTIzNC0xMjM0LTEyMzQ1Njc4OTAxMlwiLFxuICAgIH07XG5cbiAgICB0ZXN0KFwiY29uZmlndXJlcyBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbiB3aXRoIGN1c3RvbSBkb21haW5cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICAgIGRvbWFpbkNvbmZpZyxcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgICAgIEFsaWFzZXM6IFtcInd3dy5leGFtcGxlLmNvbVwiXSxcbiAgICAgICAgICBWaWV3ZXJDZXJ0aWZpY2F0ZToge1xuICAgICAgICAgICAgQWNtQ2VydGlmaWNhdGVBcm46IGRvbWFpbkNvbmZpZy5jZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgICAgIFNzbFN1cHBvcnRNZXRob2Q6IFwic25pLW9ubHlcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiY3JlYXRlcyBSb3V0ZTUzIEEgcmVjb3JkIHdoZW4gZG9tYWluIGNvbmZpZyBpcyBwcm92aWRlZFwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3Qtd2Vic2l0ZS1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgICAgZG9tYWluQ29uZmlnLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6Um91dGU1Mzo6UmVjb3JkU2V0XCIsIHtcbiAgICAgICAgVHlwZTogXCJBXCIsXG4gICAgICAgIE5hbWU6IFwid3d3LmV4YW1wbGUuY29tLlwiLFxuICAgICAgICBBbGlhc1RhcmdldDoge1xuICAgICAgICAgIEROU05hbWU6IE1hdGNoLmFueVZhbHVlKCksXG4gICAgICAgICAgSG9zdGVkWm9uZUlkOiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiaGFuZGxlcyBkb21haW4gd2l0aG91dCBzdWJkb21haW5cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgZG9tYWluQ29uZmlnV2l0aG91dFN1YjogRG9tYWluQ29uZmlnID0ge1xuICAgICAgICBkb21haW5OYW1lOiBcImV4YW1wbGUuY29tXCIsXG4gICAgICAgIHN1YmRvbWFpbk5hbWU6IFwiXCIsXG4gICAgICAgIGNlcnRpZmljYXRlQXJuOlxuICAgICAgICAgIFwiYXJuOmF3czphY206dXMtZWFzdC0xOjEyMzQ1Njc4OTAxMjpjZXJ0aWZpY2F0ZS8xMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwMTJcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC13ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgICBkb21haW5Db25maWc6IGRvbWFpbkNvbmZpZ1dpdGhvdXRTdWIsXG4gICAgICB9O1xuXG4gICAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJUZXN0V2Vic2l0ZVwiLCBwcm9wcyk7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwge1xuICAgICAgICBEaXN0cmlidXRpb25Db25maWc6IHtcbiAgICAgICAgICBBbGlhc2VzOiBbXCJleGFtcGxlLmNvbVwiXSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OlJvdXRlNTM6OlJlY29yZFNldFwiLCB7XG4gICAgICAgIFR5cGU6IFwiQVwiLFxuICAgICAgICBOYW1lOiBcImV4YW1wbGUuY29tLlwiLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiY29uZmlndXJlcyBDbG91ZEZyb250IHdpdGggYm90aCBzdWJkb21haW4gYW5kIHJvb3QgZG9tYWluIGFsaWFzZXMgd2hlbiBpbmNsdWRlUm9vdERvbWFpbiBpcyB0cnVlXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGR1YWxEb21haW5Db25maWc6IERvbWFpbkNvbmZpZyA9IHtcbiAgICAgICAgZG9tYWluTmFtZTogXCJleGFtcGxlLmNvbVwiLFxuICAgICAgICBzdWJkb21haW5OYW1lOiBcInd3d1wiLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjpcbiAgICAgICAgICBcImFybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyXCIsXG4gICAgICAgIGluY2x1ZGVSb290RG9tYWluOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICAgIGRvbWFpbkNvbmZpZzogZHVhbERvbWFpbkNvbmZpZyxcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgICAgIEFsaWFzZXM6IFtcInd3dy5leGFtcGxlLmNvbVwiLCBcImV4YW1wbGUuY29tXCJdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiY3JlYXRlcyB0d28gUm91dGU1MyBBIHJlY29yZHMgd2hlbiBpbmNsdWRlUm9vdERvbWFpbiBpcyB0cnVlXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGR1YWxEb21haW5Db25maWc6IERvbWFpbkNvbmZpZyA9IHtcbiAgICAgICAgZG9tYWluTmFtZTogXCJleGFtcGxlLmNvbVwiLFxuICAgICAgICBzdWJkb21haW5OYW1lOiBcInd3d1wiLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjpcbiAgICAgICAgICBcImFybjphd3M6YWNtOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Y2VydGlmaWNhdGUvMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MDEyXCIsXG4gICAgICAgIGluY2x1ZGVSb290RG9tYWluOiB0cnVlLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LXdlYnNpdGUtYnVja2V0XCIsXG4gICAgICAgIGluZGV4RmlsZTogXCJpbmRleC5odG1sXCIsXG4gICAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICAgIGRvbWFpbkNvbmZpZzogZHVhbERvbWFpbkNvbmZpZyxcbiAgICAgIH07XG5cbiAgICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gICAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlJvdXRlNTM6OlJlY29yZFNldFwiLCAyKTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpSb3V0ZTUzOjpSZWNvcmRTZXRcIiwge1xuICAgICAgICBOYW1lOiBcInd3dy5leGFtcGxlLmNvbS5cIixcbiAgICAgICAgVHlwZTogXCJBXCIsXG4gICAgICB9KTtcblxuICAgICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpSb3V0ZTUzOjpSZWNvcmRTZXRcIiwge1xuICAgICAgICBOYW1lOiBcImV4YW1wbGUuY29tLlwiLFxuICAgICAgICBUeXBlOiBcIkFcIixcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGVzdChcImlnbm9yZXMgaW5jbHVkZVJvb3REb21haW4gaWYgc3ViZG9tYWluIGlzIGVtcHR5IHRvIGF2b2lkIGR1cGxpY2F0ZXNcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgZG9tYWluQ29uZmlnV2l0aG91dFN1YjogRG9tYWluQ29uZmlnID0ge1xuICAgICAgICBkb21haW5OYW1lOiBcImV4YW1wbGUuY29tXCIsXG4gICAgICAgIHN1YmRvbWFpbk5hbWU6IFwiXCIsXG4gICAgICAgIGNlcnRpZmljYXRlQXJuOlxuICAgICAgICAgIFwiYXJuOmF3czphY206dXMtZWFzdC0xOjEyMzQ1Njc4OTAxMjpjZXJ0aWZpY2F0ZS8xMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwMTJcIixcbiAgICAgICAgaW5jbHVkZVJvb3REb21haW46IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBwcm9wczogV2Vic2l0ZVByb3BzID0ge1xuICAgICAgICBidWNrZXROYW1lOiBcInRlc3Qtd2Vic2l0ZS1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgICAgZG9tYWluQ29uZmlnOiBkb21haW5Db25maWdXaXRob3V0U3ViLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbiAgICAgIHRlbXBsYXRlLnJlc291cmNlQ291bnRJcyhcIkFXUzo6Um91dGU1Mzo6UmVjb3JkU2V0XCIsIDEpO1xuXG4gICAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkNsb3VkRnJvbnQ6OkRpc3RyaWJ1dGlvblwiLCB7XG4gICAgICAgIERpc3RyaWJ1dGlvbkNvbmZpZzoge1xuICAgICAgICAgIEFsaWFzZXM6IFtcImV4YW1wbGUuY29tXCJdLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiUHJpdmF0ZSBtZXRob2RzXCIsICgpID0+IHtcbiAgICB0ZXN0KFwiX2dldEZ1bGxEb21haW5OYW1lIHJldHVybnMgY29ycmVjdCBkb21haW4gd2l0aCBzdWJkb21haW5cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgY29uc3RydWN0ID0gbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICAvLyBBY2Nlc3MgcHJpdmF0ZSBtZXRob2QgdGhyb3VnaCBicmFja2V0IG5vdGF0aW9uIGZvciB0ZXN0aW5nXG4gICAgICBjb25zdCBnZXRGdWxsRG9tYWluTmFtZSA9IChjb25zdHJ1Y3QgYXMgYW55KS5fZ2V0RnVsbERvbWFpbk5hbWU7XG5cbiAgICAgIGNvbnN0IGRvbWFpbkNvbmZpZzogRG9tYWluQ29uZmlnID0ge1xuICAgICAgICBkb21haW5OYW1lOiBcImV4YW1wbGUuY29tXCIsXG4gICAgICAgIHN1YmRvbWFpbk5hbWU6IFwiYmxvZ1wiLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjogXCJhcm46dGVzdFwiLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gZ2V0RnVsbERvbWFpbk5hbWUoZG9tYWluQ29uZmlnKTtcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvQmUoXCJibG9nLmV4YW1wbGUuY29tXCIpO1xuICAgIH0pO1xuXG4gICAgdGVzdChcIl9nZXRGdWxsRG9tYWluTmFtZSByZXR1cm5zIHJvb3QgZG9tYWluIHdoZW4gc3ViZG9tYWluIGlzIGVtcHR5XCIsICgpID0+IHtcbiAgICAgIGNvbnN0IHByb3BzOiBXZWJzaXRlUHJvcHMgPSB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFwidGVzdC1idWNrZXRcIixcbiAgICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGNvbnN0cnVjdCA9IG5ldyBXZWJzaXRlKHN0YWNrLCBcIlRlc3RXZWJzaXRlXCIsIHByb3BzKTtcblxuICAgICAgY29uc3QgZ2V0RnVsbERvbWFpbk5hbWUgPSAoY29uc3RydWN0IGFzIGFueSkuX2dldEZ1bGxEb21haW5OYW1lO1xuXG4gICAgICBjb25zdCBkb21haW5Db25maWc6IERvbWFpbkNvbmZpZyA9IHtcbiAgICAgICAgZG9tYWluTmFtZTogXCJleGFtcGxlLmNvbVwiLFxuICAgICAgICBzdWJkb21haW5OYW1lOiBcIlwiLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjogXCJhcm46dGVzdFwiLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gZ2V0RnVsbERvbWFpbk5hbWUoZG9tYWluQ29uZmlnKTtcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvQmUoXCJleGFtcGxlLmNvbVwiKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoXCJFZGdlIGNhc2VzXCIsICgpID0+IHtcbiAgICB0ZXN0KFwiaGFuZGxlcyBtaW5pbWFsIGNvbmZpZ3VyYXRpb25cIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJtaW5pbWFsLWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgZXhwZWN0KCgpID0+IHtcbiAgICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuICAgICAgfSkubm90LnRvVGhyb3coKTtcblxuICAgICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgICAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpTMzo6QnVja2V0XCIsIDEpO1xuICAgICAgdGVtcGxhdGUucmVzb3VyY2VDb3VudElzKFwiQVdTOjpDbG91ZEZyb250OjpEaXN0cmlidXRpb25cIiwgMSk7XG4gICAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXG4gICAgICAgIFwiQVdTOjpDbG91ZEZyb250OjpDbG91ZEZyb250T3JpZ2luQWNjZXNzSWRlbnRpdHlcIixcbiAgICAgICAgMSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KFwiZG9lcyBub3QgY3JlYXRlIFJvdXRlNTMgcmVzb3VyY2VzIHdoZW4gZG9tYWluIGNvbmZpZyBpcyBub3QgcHJvdmlkZWRcIiwgKCkgPT4ge1xuICAgICAgY29uc3QgcHJvcHM6IFdlYnNpdGVQcm9wcyA9IHtcbiAgICAgICAgYnVja2V0TmFtZTogXCJ0ZXN0LWJ1Y2tldFwiLFxuICAgICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgICBlcnJvckZpbGU6IFwiZXJyb3IuaHRtbFwiLFxuICAgICAgfTtcblxuICAgICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiVGVzdFdlYnNpdGVcIiwgcHJvcHMpO1xuXG4gICAgICBjb25zdCB0ZW1wbGF0ZSA9IFRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG4gICAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlJvdXRlNTM6OlJlY29yZFNldFwiLCAwKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoXCJQcmV2aWV3IGNvbmZpZyBvbiBXZWJzaXRlXCIsICgpID0+IHtcbiAgbGV0IGFwcDogY2RrLkFwcDtcbiAgbGV0IHN0YWNrOiBjZGsuU3RhY2s7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgYXBwID0gbmV3IGNkay5BcHAoKTtcbiAgICBzdGFjayA9IG5ldyBjZGsuU3RhY2soYXBwLCBcIlByZXZpZXdUZXN0U3RhY2tcIiwge1xuICAgICAgZW52OiB7IGFjY291bnQ6IFwiMTIzNDU2Nzg5MDEyXCIsIHJlZ2lvbjogXCJ1cy1lYXN0LTFcIiB9LFxuICAgIH0pO1xuICB9KTtcblxuICB0ZXN0KFwiY3JlYXRlcyB0d28gcHJldmlldyBidWNrZXRzIGJ5IGRlZmF1bHQgd2hlbiBwcmV2aWV3Q29uZmlnIGlzIGVuYWJsZWRcIiwgKCkgPT4ge1xuICAgIGNvbnN0IHdlYnNpdGUgPSBuZXcgV2Vic2l0ZShzdGFjaywgXCJQcmV2aWV3RW5hYmxlZFdlYnNpdGVcIiwge1xuICAgICAgYnVja2V0TmFtZTogXCJ3ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICBwcmV2aWV3Q29uZmlnOiB7XG4gICAgICAgIGJ1Y2tldFByZWZpeDogXCJwcmV2aWV3LWJ1Y2tldFwiLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgMyk7XG4gICAgZXhwZWN0KHdlYnNpdGUucHJldmlld0Vudmlyb25tZW50KS50b0JlRGVmaW5lZCgpO1xuICB9KTtcblxuICB0ZXN0KFwiY3JlYXRlcyByZXF1ZXN0ZWQgbnVtYmVyIG9mIHByZXZpZXcgYnVja2V0cyBmcm9tIHByZXZpZXdDb25maWdcIiwgKCkgPT4ge1xuICAgIG5ldyBXZWJzaXRlKHN0YWNrLCBcIlByZXZpZXdFbmFibGVkV2Vic2l0ZVwiLCB7XG4gICAgICBidWNrZXROYW1lOiBcIndlYnNpdGUtYnVja2V0XCIsXG4gICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICAgIHByZXZpZXdDb25maWc6IHtcbiAgICAgICAgYnVja2V0UHJlZml4OiBcInByZXZpZXctYnVja2V0XCIsXG4gICAgICAgIGJ1Y2tldENvdW50OiAzLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OlMzOjpCdWNrZXRcIiwgNCk7XG4gIH0pO1xuXG4gIHRlc3QoXCJyZXVzZXMgd2Vic2l0ZSBpbmRleCBhbmQgZXJyb3IgZmlsZXMgZm9yIHByZXZpZXcgYnVja2V0c1wiLCAoKSA9PiB7XG4gICAgbmV3IFdlYnNpdGUoc3RhY2ssIFwiUHJldmlld0VuYWJsZWRXZWJzaXRlXCIsIHtcbiAgICAgIGJ1Y2tldE5hbWU6IFwid2Vic2l0ZS1idWNrZXRcIixcbiAgICAgIGluZGV4RmlsZTogXCJhcHAuaHRtbFwiLFxuICAgICAgZXJyb3JGaWxlOiBcImZhbGxiYWNrLmh0bWxcIixcbiAgICAgIHByZXZpZXdDb25maWc6IHtcbiAgICAgICAgYnVja2V0UHJlZml4OiBcInByZXZpZXctYnVja2V0XCIsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgICBCdWNrZXROYW1lOiBcInByZXZpZXctYnVja2V0LTBcIixcbiAgICAgIFdlYnNpdGVDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIEluZGV4RG9jdW1lbnQ6IFwiYXBwLmh0bWxcIixcbiAgICAgICAgRXJyb3JEb2N1bWVudDogXCJmYWxsYmFjay5odG1sXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6UzM6OkJ1Y2tldFwiLCB7XG4gICAgICBCdWNrZXROYW1lOiBcInByZXZpZXctYnVja2V0LTFcIixcbiAgICAgIFdlYnNpdGVDb25maWd1cmF0aW9uOiB7XG4gICAgICAgIEluZGV4RG9jdW1lbnQ6IFwiYXBwLmh0bWxcIixcbiAgICAgICAgRXJyb3JEb2N1bWVudDogXCJmYWxsYmFjay5odG1sXCIsXG4gICAgICB9LFxuICAgIH0pO1xuICB9KTtcblxuICB0ZXN0KFwiY3JlYXRlcyBsZWFzZSB0YWJsZSB3aXRoIHJlcG8tcHIgbG9va3VwIGluZGV4IHdoZW4gcHJldmlldyBpcyBlbmFibGVkXCIsICgpID0+IHtcbiAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJQcmV2aWV3RW5hYmxlZFdlYnNpdGVcIiwge1xuICAgICAgYnVja2V0TmFtZTogXCJ3ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICBwcmV2aWV3Q29uZmlnOiB7XG4gICAgICAgIGJ1Y2tldFByZWZpeDogXCJwcmV2aWV3LWJ1Y2tldFwiLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkR5bmFtb0RCOjpUYWJsZVwiLCB7XG4gICAgICBLZXlTY2hlbWE6IFtcbiAgICAgICAge1xuICAgICAgICAgIEF0dHJpYnV0ZU5hbWU6IFwic2xvdElkXCIsXG4gICAgICAgICAgS2V5VHlwZTogXCJIQVNIXCIsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgR2xvYmFsU2Vjb25kYXJ5SW5kZXhlczogW1xuICAgICAgICB7XG4gICAgICAgICAgSW5kZXhOYW1lOiBcIlJlcG9QcktleUluZGV4XCIsXG4gICAgICAgICAgS2V5U2NoZW1hOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIEF0dHJpYnV0ZU5hbWU6IFwicmVwb1ByS2V5XCIsXG4gICAgICAgICAgICAgIEtleVR5cGU6IFwiSEFTSFwiLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIFByb2plY3Rpb246IHtcbiAgICAgICAgICAgIFByb2plY3Rpb25UeXBlOiBcIkFMTFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9KTtcblxuICB0ZXN0KFwiY3JlYXRlcyBsZWFzZSBBUEkgcm91dGVzIHdoZW4gcHJldmlldyBpcyBlbmFibGVkXCIsICgpID0+IHtcbiAgICBuZXcgV2Vic2l0ZShzdGFjaywgXCJQcmV2aWV3RW5hYmxlZFdlYnNpdGVcIiwge1xuICAgICAgYnVja2V0TmFtZTogXCJ3ZWJzaXRlLWJ1Y2tldFwiLFxuICAgICAgaW5kZXhGaWxlOiBcImluZGV4Lmh0bWxcIixcbiAgICAgIGVycm9yRmlsZTogXCJlcnJvci5odG1sXCIsXG4gICAgICBwcmV2aWV3Q29uZmlnOiB7XG4gICAgICAgIGJ1Y2tldFByZWZpeDogXCJwcmV2aWV3LWJ1Y2tldFwiLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkFwaUdhdGV3YXk6OlJlc291cmNlXCIsIHtcbiAgICAgIFBhdGhQYXJ0OiBcImNsYWltXCIsXG4gICAgfSk7XG4gICAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpBcGlHYXRld2F5OjpSZXNvdXJjZVwiLCB7XG4gICAgICBQYXRoUGFydDogXCJoZWFydGJlYXRcIixcbiAgICB9KTtcbiAgICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkFwaUdhdGV3YXk6OlJlc291cmNlXCIsIHtcbiAgICAgIFBhdGhQYXJ0OiBcInJlbGVhc2VcIixcbiAgICB9KTtcbiAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OkFwaUdhdGV3YXk6Ok1ldGhvZFwiLCAzKTtcbiAgfSk7XG5cbiAgdGVzdChcImRvZXMgbm90IGNyZWF0ZSBwcmV2aWV3IHJlc291cmNlcyB3aGVuIHByZXZpZXdDb25maWcgaXMgb21pdHRlZFwiLCAoKSA9PiB7XG4gICAgY29uc3Qgd2Vic2l0ZSA9IG5ldyBXZWJzaXRlKHN0YWNrLCBcIldlYnNpdGVXaXRob3V0UHJldmlld1wiLCB7XG4gICAgICBidWNrZXROYW1lOiBcIndlYnNpdGUtYnVja2V0XCIsXG4gICAgICBpbmRleEZpbGU6IFwiaW5kZXguaHRtbFwiLFxuICAgICAgZXJyb3JGaWxlOiBcImVycm9yLmh0bWxcIixcbiAgICB9KTtcblxuICAgIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcbiAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OkR5bmFtb0RCOjpUYWJsZVwiLCAwKTtcbiAgICB0ZW1wbGF0ZS5yZXNvdXJjZUNvdW50SXMoXCJBV1M6OkFwaUdhdGV3YXk6OlJlc3RBcGlcIiwgMCk7XG4gICAgZXhwZWN0KHdlYnNpdGUucHJldmlld0Vudmlyb25tZW50KS50b0JlVW5kZWZpbmVkKCk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -249,6 +249,95 @@ describe("Website", () => {
|
|
|
249
249
|
Name: "example.com.",
|
|
250
250
|
});
|
|
251
251
|
});
|
|
252
|
+
|
|
253
|
+
test("configures CloudFront with both subdomain and root domain aliases when includeRootDomain is true", () => {
|
|
254
|
+
const dualDomainConfig: DomainConfig = {
|
|
255
|
+
domainName: "example.com",
|
|
256
|
+
subdomainName: "www",
|
|
257
|
+
certificateArn:
|
|
258
|
+
"arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012",
|
|
259
|
+
includeRootDomain: true,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const props: WebsiteProps = {
|
|
263
|
+
bucketName: "test-website-bucket",
|
|
264
|
+
indexFile: "index.html",
|
|
265
|
+
errorFile: "error.html",
|
|
266
|
+
domainConfig: dualDomainConfig,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
new Website(stack, "TestWebsite", props);
|
|
270
|
+
|
|
271
|
+
const template = Template.fromStack(stack);
|
|
272
|
+
|
|
273
|
+
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
274
|
+
DistributionConfig: {
|
|
275
|
+
Aliases: ["www.example.com", "example.com"],
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
test("creates two Route53 A records when includeRootDomain is true", () => {
|
|
281
|
+
const dualDomainConfig: DomainConfig = {
|
|
282
|
+
domainName: "example.com",
|
|
283
|
+
subdomainName: "www",
|
|
284
|
+
certificateArn:
|
|
285
|
+
"arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012",
|
|
286
|
+
includeRootDomain: true,
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
const props: WebsiteProps = {
|
|
290
|
+
bucketName: "test-website-bucket",
|
|
291
|
+
indexFile: "index.html",
|
|
292
|
+
errorFile: "error.html",
|
|
293
|
+
domainConfig: dualDomainConfig,
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
new Website(stack, "TestWebsite", props);
|
|
297
|
+
|
|
298
|
+
const template = Template.fromStack(stack);
|
|
299
|
+
|
|
300
|
+
template.resourceCountIs("AWS::Route53::RecordSet", 2);
|
|
301
|
+
|
|
302
|
+
template.hasResourceProperties("AWS::Route53::RecordSet", {
|
|
303
|
+
Name: "www.example.com.",
|
|
304
|
+
Type: "A",
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
template.hasResourceProperties("AWS::Route53::RecordSet", {
|
|
308
|
+
Name: "example.com.",
|
|
309
|
+
Type: "A",
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test("ignores includeRootDomain if subdomain is empty to avoid duplicates", () => {
|
|
314
|
+
const domainConfigWithoutSub: DomainConfig = {
|
|
315
|
+
domainName: "example.com",
|
|
316
|
+
subdomainName: "",
|
|
317
|
+
certificateArn:
|
|
318
|
+
"arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012",
|
|
319
|
+
includeRootDomain: true,
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const props: WebsiteProps = {
|
|
323
|
+
bucketName: "test-website-bucket",
|
|
324
|
+
indexFile: "index.html",
|
|
325
|
+
errorFile: "error.html",
|
|
326
|
+
domainConfig: domainConfigWithoutSub,
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
new Website(stack, "TestWebsite", props);
|
|
330
|
+
|
|
331
|
+
const template = Template.fromStack(stack);
|
|
332
|
+
|
|
333
|
+
template.resourceCountIs("AWS::Route53::RecordSet", 1);
|
|
334
|
+
|
|
335
|
+
template.hasResourceProperties("AWS::CloudFront::Distribution", {
|
|
336
|
+
DistributionConfig: {
|
|
337
|
+
Aliases: ["example.com"],
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
});
|
|
252
341
|
});
|
|
253
342
|
|
|
254
343
|
describe("Private methods", () => {
|
|
@@ -331,3 +420,143 @@ describe("Website", () => {
|
|
|
331
420
|
});
|
|
332
421
|
});
|
|
333
422
|
});
|
|
423
|
+
|
|
424
|
+
describe("Preview config on Website", () => {
|
|
425
|
+
let app: cdk.App;
|
|
426
|
+
let stack: cdk.Stack;
|
|
427
|
+
|
|
428
|
+
beforeEach(() => {
|
|
429
|
+
app = new cdk.App();
|
|
430
|
+
stack = new cdk.Stack(app, "PreviewTestStack", {
|
|
431
|
+
env: { account: "123456789012", region: "us-east-1" },
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
test("creates two preview buckets by default when previewConfig is enabled", () => {
|
|
436
|
+
const website = new Website(stack, "PreviewEnabledWebsite", {
|
|
437
|
+
bucketName: "website-bucket",
|
|
438
|
+
indexFile: "index.html",
|
|
439
|
+
errorFile: "error.html",
|
|
440
|
+
previewConfig: {
|
|
441
|
+
bucketPrefix: "preview-bucket",
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const template = Template.fromStack(stack);
|
|
446
|
+
template.resourceCountIs("AWS::S3::Bucket", 3);
|
|
447
|
+
expect(website.previewEnvironment).toBeDefined();
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
test("creates requested number of preview buckets from previewConfig", () => {
|
|
451
|
+
new Website(stack, "PreviewEnabledWebsite", {
|
|
452
|
+
bucketName: "website-bucket",
|
|
453
|
+
indexFile: "index.html",
|
|
454
|
+
errorFile: "error.html",
|
|
455
|
+
previewConfig: {
|
|
456
|
+
bucketPrefix: "preview-bucket",
|
|
457
|
+
bucketCount: 3,
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
const template = Template.fromStack(stack);
|
|
462
|
+
template.resourceCountIs("AWS::S3::Bucket", 4);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("reuses website index and error files for preview buckets", () => {
|
|
466
|
+
new Website(stack, "PreviewEnabledWebsite", {
|
|
467
|
+
bucketName: "website-bucket",
|
|
468
|
+
indexFile: "app.html",
|
|
469
|
+
errorFile: "fallback.html",
|
|
470
|
+
previewConfig: {
|
|
471
|
+
bucketPrefix: "preview-bucket",
|
|
472
|
+
},
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
const template = Template.fromStack(stack);
|
|
476
|
+
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
477
|
+
BucketName: "preview-bucket-0",
|
|
478
|
+
WebsiteConfiguration: {
|
|
479
|
+
IndexDocument: "app.html",
|
|
480
|
+
ErrorDocument: "fallback.html",
|
|
481
|
+
},
|
|
482
|
+
});
|
|
483
|
+
template.hasResourceProperties("AWS::S3::Bucket", {
|
|
484
|
+
BucketName: "preview-bucket-1",
|
|
485
|
+
WebsiteConfiguration: {
|
|
486
|
+
IndexDocument: "app.html",
|
|
487
|
+
ErrorDocument: "fallback.html",
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
test("creates lease table with repo-pr lookup index when preview is enabled", () => {
|
|
493
|
+
new Website(stack, "PreviewEnabledWebsite", {
|
|
494
|
+
bucketName: "website-bucket",
|
|
495
|
+
indexFile: "index.html",
|
|
496
|
+
errorFile: "error.html",
|
|
497
|
+
previewConfig: {
|
|
498
|
+
bucketPrefix: "preview-bucket",
|
|
499
|
+
},
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
const template = Template.fromStack(stack);
|
|
503
|
+
template.hasResourceProperties("AWS::DynamoDB::Table", {
|
|
504
|
+
KeySchema: [
|
|
505
|
+
{
|
|
506
|
+
AttributeName: "slotId",
|
|
507
|
+
KeyType: "HASH",
|
|
508
|
+
},
|
|
509
|
+
],
|
|
510
|
+
GlobalSecondaryIndexes: [
|
|
511
|
+
{
|
|
512
|
+
IndexName: "RepoPrKeyIndex",
|
|
513
|
+
KeySchema: [
|
|
514
|
+
{
|
|
515
|
+
AttributeName: "repoPrKey",
|
|
516
|
+
KeyType: "HASH",
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
Projection: {
|
|
520
|
+
ProjectionType: "ALL",
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
],
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
test("creates lease API routes when preview is enabled", () => {
|
|
528
|
+
new Website(stack, "PreviewEnabledWebsite", {
|
|
529
|
+
bucketName: "website-bucket",
|
|
530
|
+
indexFile: "index.html",
|
|
531
|
+
errorFile: "error.html",
|
|
532
|
+
previewConfig: {
|
|
533
|
+
bucketPrefix: "preview-bucket",
|
|
534
|
+
},
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
const template = Template.fromStack(stack);
|
|
538
|
+
template.hasResourceProperties("AWS::ApiGateway::Resource", {
|
|
539
|
+
PathPart: "claim",
|
|
540
|
+
});
|
|
541
|
+
template.hasResourceProperties("AWS::ApiGateway::Resource", {
|
|
542
|
+
PathPart: "heartbeat",
|
|
543
|
+
});
|
|
544
|
+
template.hasResourceProperties("AWS::ApiGateway::Resource", {
|
|
545
|
+
PathPart: "release",
|
|
546
|
+
});
|
|
547
|
+
template.resourceCountIs("AWS::ApiGateway::Method", 3);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
test("does not create preview resources when previewConfig is omitted", () => {
|
|
551
|
+
const website = new Website(stack, "WebsiteWithoutPreview", {
|
|
552
|
+
bucketName: "website-bucket",
|
|
553
|
+
indexFile: "index.html",
|
|
554
|
+
errorFile: "error.html",
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
const template = Template.fromStack(stack);
|
|
558
|
+
template.resourceCountIs("AWS::DynamoDB::Table", 0);
|
|
559
|
+
template.resourceCountIs("AWS::ApiGateway::RestApi", 0);
|
|
560
|
+
expect(website.previewEnvironment).toBeUndefined();
|
|
561
|
+
});
|
|
562
|
+
});
|