UNPKG

@aws/cloudfront-hosting-toolkit

Version:

CloudFront Hosting Toolkit offers the convenience of a managed frontend hosting service while retaining full control over the hosting and deployment infrastructure to make it your own.

203 lines (200 loc) 37.8 kB
#!/usr/bin/env node "use strict"; /* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const helper_1 = require("../utils/helper"); const awsSDKUtil_1 = __importStar(require("../utils/awsSDKUtil")); const fs_1 = __importDefault(require("fs")); const constants_1 = require("../shared/constants"); const prompt_questions_1 = require("../utils/prompt_questions"); const AdmZip = require("adm-zip"); async function handleDeployCommand() { await (0, awsSDKUtil_1.default)(); const configFile = process.cwd() + "/" + constants_1.TOOL_NAME + "/" + constants_1.CONFIG_FILE_NAME; const buildFile = process.cwd() + "/" + constants_1.TOOL_NAME + "/" + constants_1.BUILD_FILE_NAME; if (!fs_1.default.existsSync(configFile) || !fs_1.default.existsSync(buildFile)) { console.error(`${constants_1.ERROR_PREFIX} Oops. It appears that you haven't executed the "${constants_1.TOOL_NAME} init" command, resulting in the absence of any configuration files:`); console.error(`> ${configFile}`); console.error(`> ${buildFile}`); console.log(`\nPlease run '${constants_1.TOOL_NAME} init' first.\n`); process.exit(1); } var counter = 1; const hostingConfiguration = await (0, helper_1.loadHostingConfiguration)(); var certificateArnCmdParam = ""; if (hostingConfiguration.domainName) { console.log(`\n --> ${counter++}. Setting up a SSL/TLS certificate with AWS Certificate Manager (ACM) \n`); let { certificateArn, status } = await (0, awsSDKUtil_1.checkCertificateExists)(hostingConfiguration.domainName); console.log("status=" + status); if (!certificateArn) { certificateArn = await (0, awsSDKUtil_1.createACMCertificate)(hostingConfiguration.domainName); if (certificateArn) { await (0, awsSDKUtil_1.waitCertificateToBeIssued)(certificateArn, hostingConfiguration.hostedZoneId); } } else { console.log("The certificate for this domain has already been created. "); if (status != "ISSUED") { console.log("Certificate is not ready to be used. Waiting ..."); await (0, awsSDKUtil_1.waitCertificateToBeIssued)(certificateArn, hostingConfiguration.hostedZoneId); } else { console.log("\nThe certificate is ready to be used."); } } certificateArnCmdParam = `--context certificate-arn=${certificateArn}`; } console.log(`\n --> ${counter++}. Bootstrapping your AWS account \n`); const configFilePath = (0, helper_1.getCLIExecutionFolder)() + "/" + constants_1.TOOL_NAME; const bootstrapCmd = `npx cdk bootstrap --context config-path=${configFilePath} ${certificateArnCmdParam}`; await (0, helper_1.executeCommands)(bootstrapCmd, (0, helper_1.getCLIInstallationFolder)()); if ((0, helper_1.isRepoConfig)(hostingConfiguration)) { console.log(`\n --> ${counter++}. Create resources for connecting your AWS account to your GitHub repository. \n`); const createConnectionCmd = `npx cdk deploy ${(0, helper_1.calculateConnectionStackName)(hostingConfiguration.repoUrl, hostingConfiguration.branchName)} --context config-path=${configFilePath} ${certificateArnCmdParam} `; await (0, helper_1.executeCommands)(createConnectionCmd, (0, helper_1.getCLIInstallationFolder)()); const getPendingConnections = await (0, awsSDKUtil_1.pendingConnections)(); if (getPendingConnections) { //there are connection in PENDING STATE, wait for the user to validate them await connection_prompt(counter++); } } else if ((0, helper_1.isS3Config)(hostingConfiguration)) { //check if the S3 bucket exists const bucketExists = await (0, awsSDKUtil_1.checkBucketExists)(hostingConfiguration.s3bucket); if (!bucketExists) { console.error(`\n${constants_1.ERROR_PREFIX} The specified bucket '${hostingConfiguration.s3bucket}' doesn't exist in the current region. Please rerun '${constants_1.TOOL_NAME} init' or create a bucket with that name in the current region.\n`); process.exit(1); } } else { console.error(`${constants_1.ERROR_PREFIX} Exiting due to an invalid configuration file.`); process.exit(1); } console.log(`\n --> ${counter++}. Deploy the hosting infrastructure within your AWS account \n`); console.log("Please wait while deploying the infrastructure, it may take a few minutes."); const createInfrastructureCmd = `npx cdk deploy ${(0, helper_1.calculateMainStackName)(hostingConfiguration)} --context config-path=${configFilePath} --require-approval never ${certificateArnCmdParam}`; await (0, helper_1.executeCommands)(createInfrastructureCmd, (0, helper_1.getCLIInstallationFolder)()); console.log("\n_____________________________________________________________________\n"); const domainName = await (0, awsSDKUtil_1.getSSMParameter)(constants_1.SSM_DOMAIN_STR); const pipelineName = await (0, awsSDKUtil_1.getSSMParameter)(constants_1.SSM_PIPELINENAME_STR); if (domainName) { console.log("\nThe Origin paired with its associated CloudFront domain name:\n"); console.log(`> ${(0, helper_1.isRepoConfig)(hostingConfiguration) ? "Code Repository" : "S3 Source Code"}: ${(0, helper_1.isRepoConfig)(hostingConfiguration) ? hostingConfiguration.repoUrl : hostingConfiguration.s3bucket + "/" + hostingConfiguration.s3path}`); console.log(`> Hosting: https://${domainName} \n`); if (hostingConfiguration.domainName) { if (hostingConfiguration.hostedZoneId) { const cFCNAMEExists = await (0, awsSDKUtil_1.checkCFARecordExists)(hostingConfiguration.domainName, domainName, hostingConfiguration.hostedZoneId); if (!cFCNAMEExists) { const associate = await (0, helper_1.startPrompt)(prompt_questions_1.cloudFrontAssociationQuestion); if (associate.value == "yes") { await (0, awsSDKUtil_1.createCFARecord)(hostingConfiguration.domainName, domainName, hostingConfiguration.hostedZoneId); } } else { console.log(`> Domain name '${hostingConfiguration.domainName}' is already associated with the CloudFront distribution.\n`); } } else { console.log(`\nJust a few more steps to get your domain name up and running!`); console.log(`\nTo make your domain name point to your CloudFront distribution, you need to configure a CNAME entry in the authoritative DNS server of your domain. This is a simple process that usually takes just a few minutes.`); console.log("Here's what you need to do:"); console.log("> Log in to your DNS provider."); console.log("> Find the section for creating new DNS records."); console.log("> Create a new CNAME record with the following information:"); console.log(`> Host name: ${hostingConfiguration.domainName}`); console.log(`> Target: ${domainName}`); console.log("> Save your changes."); console.log("\n"); console.log("> That's it! Once you've saved your changes, your domain name will start pointing to your CloudFront distribution."); console.log("\n\n"); } } if ((0, helper_1.isRepoConfig)(hostingConfiguration)) { console.log("\nIn the future, whenever you push changes to your Github repository, an automatic pipeline will be triggered to deploy the new version."); } else { console.log("\nIn the future, whenever you upload a zip file to the designated S3 Bucket, an automated process will be initiated to deploy the latest version."); } console.log("\n_____________________________________________________________________\n\n"); console.log("The hosting infrastructure for your project has been successfully deployed on your AWS account"); console.log("\n"); console.log("The deployment consists of the following AWS CloudFormation stack(s):"); if ((0, helper_1.isRepoConfig)(hostingConfiguration)) { console.log(`> ${(0, helper_1.calculateConnectionStackName)(hostingConfiguration.repoUrl, hostingConfiguration.branchName)}`); } console.log(`> ${(0, helper_1.calculateMainStackName)(hostingConfiguration)}\n`); console.log(`The following AWS CodePipeline has been created for automatic deployment upon Git push execution:`); console.log(`> ${pipelineName}\n`); console.log("You can review the resources deployed by logging into the AWS Management Console at https://aws.amazon.com/console \n"); await (0, awsSDKUtil_1.startPipelineExecution)(); await (0, helper_1.checkPipelineStatus)(); } else { console.error(`${constants_1.ERROR_PREFIX} No domain names available due to missing information in SSM.`); process.exit(1); } } exports.default = handleDeployCommand; async function connection_prompt(counter) { const connectionRegion = await (0, awsSDKUtil_1.getSSMParameter)(constants_1.SSM_CONNECTION_REGION_STR); const connectionName = await (0, awsSDKUtil_1.getSSMParameter)(constants_1.SSM_CONNECTION_NAME_STR); console.log(`\n --> ${counter}. Configure github connection\n`); console.log("You need to complete Github authentication using the AWS Console."); console.log("To do so, follow these steps:\n"); console.log(" 1. Open the following page: "); console.log(" https://" + connectionRegion + ".console.aws.amazon.com/codesuite/settings/connections"); console.log(" 2. In the connection list, look out for connection name: " + connectionName); console.log(" 3. For this connection with Status=Pending, complete the connection by following these instructions:"); console.log(" - Select the pending connection " + connectionName + "."); console.log(" - Click on Update a pending connection."); console.log(" - In the new popup window, under Github apps, choose an app installation, or create a new app by selecting Install a new app."); console.log(" - If you have already installed an app, select the app, click on Connect, and refresh the page if needed. The status of the connection should be Available."); console.log(" - If you choose to Install a new app, follow the on-screen instructions to authenticate your Github account, click on Connect, and refresh the page if needed. The status of the connection should be Available."); console.log("\n"); await (0, helper_1.startPrompt)(prompt_questions_1.continueConfirmationQuestion); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwbG95LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0VBY0U7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFRiw0Q0FZeUI7QUFDekIsa0VBVzZCO0FBQzdCLDRDQUFvQjtBQUNwQixtREFTNkI7QUFDN0IsZ0VBR21DO0FBQ25DLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQVFuQixLQUFLLFVBQVUsbUJBQW1CO0lBQy9DLE1BQU0sSUFBQSxvQkFBa0IsR0FBRSxDQUFDO0lBRTNCLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxHQUFHLEdBQUcscUJBQVMsR0FBRyxHQUFHLEdBQUcsNEJBQWdCLENBQUM7SUFDNUUsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLEdBQUcsR0FBRyxxQkFBUyxHQUFHLEdBQUcsR0FBRywyQkFBZSxDQUFDO0lBRTFFLElBQUksQ0FBQyxZQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsWUFBRSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQzVELE9BQU8sQ0FBQyxLQUFLLENBQ1gsR0FBRyx3QkFBWSxvREFBb0QscUJBQVMsc0VBQXNFLENBQ25KLENBQUM7UUFDRixPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUN2QyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixxQkFBUyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3pELE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsQ0FBQztJQUVELElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztJQUNoQixN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QUFDLEdBQUcsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO0lBQzVELE9BQU8sQ0FBQyxHQUFHLENBQ1Qsb0lBQW9JLENBQ3JJLENBQUM7SUFDRixPQUFPLENBQUMsR0FBRyxDQUNULGtLQUFrSyxDQUNuSyxDQUFDO0lBQ0YsT0FBTyxDQUFDLEdBQUcsQ0FDVCx1TkFBdU4sQ0FDeE4sQ0FBQztJQUNGLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbEIsTUFBTSxJQUFBLG9CQUFXLEVBQUMsK0NBQTRCLENBQUMsQ0FBQztBQUNsRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiIyEvdXNyL2Jpbi9lbnYgbm9kZVxuLypcbiAgQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gIFxuICBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpLlxuICBZb3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICBcbiAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICBcbiAgVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IHtcbiAgc3RhcnRQcm9tcHQsXG4gIGV4ZWN1dGVDb21tYW5kcyxcbiAgZ2V0QnVpbGRDb25maWdTM0ZvbGRlcixcbiAgZ2V0Q0xJSW5zdGFsbGF0aW9uRm9sZGVyLFxuICBnZXRDTElFeGVjdXRpb25Gb2xkZXIsXG4gIGNoZWNrUGlwZWxpbmVTdGF0dXMsXG4gIGxvYWRIb3N0aW5nQ29uZmlndXJhdGlvbixcbiAgaXNSZXBvQ29uZmlnLFxuICBpc1MzQ29uZmlnLFxuICBjYWxjdWxhdGVDb25uZWN0aW9uU3RhY2tOYW1lLFxuICBjYWxjdWxhdGVNYWluU3RhY2tOYW1lLFxufSBmcm9tIFwiLi4vdXRpbHMvaGVscGVyXCI7XG5pbXBvcnQgY2hlY2tBV1NDb25uZWN0aW9uLCB7XG4gIGNoZWNrQnVja2V0RXhpc3RzLFxuICBjaGVja0NlcnRpZmljYXRlRXhpc3RzLFxuICBjaGVja0NGQVJlY29yZEV4aXN0cyxcbiAgY3JlYXRlQUNNQ2VydGlmaWNhdGUsXG4gIGNyZWF0ZUNGQVJlY29yZCxcbiAgZ2V0UGlwZWxpbmVTdGF0dXMsXG4gIGdldFNTTVBhcmFtZXRlcixcbiAgcGVuZGluZ0Nvbm5lY3Rpb25zLFxuICBzdGFydFBpcGVsaW5lRXhlY3V0aW9uLFxuICB3YWl0Q2VydGlmaWNhdGVUb0JlSXNzdWVkLFxufSBmcm9tIFwiLi4vdXRpbHMvYXdzU0RLVXRpbFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHtcbiAgQlVJTERfRklMRV9OQU1FLFxuICBDT05GSUdfRklMRV9OQU1FLFxuICBFUlJPUl9QUkVGSVgsXG4gIFNTTV9DT05ORUNUSU9OX05BTUVfU1RSLFxuICBTU01fQ09OTkVDVElPTl9SRUdJT05fU1RSLFxuICBTU01fRE9NQUlOX1NUUixcbiAgU1NNX1BJUEVMSU5FTkFNRV9TVFIsXG4gIFRPT0xfTkFNRSxcbn0gZnJvbSBcIi4uL3NoYXJlZC9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIGNsb3VkRnJvbnRBc3NvY2lhdGlvblF1ZXN0aW9uLFxuICBjb250aW51ZUNvbmZpcm1hdGlvblF1ZXN0aW9uLFxufSBmcm9tIFwiLi4vdXRpbHMvcHJvbXB0X3F1ZXN0aW9uc1wiO1xuY29uc3QgQWRtWmlwID0gcmVxdWlyZShcImFkbS16aXBcIik7XG5cbmludGVyZmFjZSBDb21tYW5kIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgY21kOiBhbnk7XG59XG5cblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlRGVwbG95Q29tbWFuZCgpIHtcbiAgYXdhaXQgY2hlY2tBV1NDb25uZWN0aW9uKCk7XG5cbiAgY29uc3QgY29uZmlnRmlsZSA9IHByb2Nlc3MuY3dkKCkgKyBcIi9cIiArIFRPT0xfTkFNRSArIFwiL1wiICsgQ09ORklHX0ZJTEVfTkFNRTtcbiAgY29uc3QgYnVpbGRGaWxlID0gcHJvY2Vzcy5jd2QoKSArIFwiL1wiICsgVE9PTF9OQU1FICsgXCIvXCIgKyBCVUlMRF9GSUxFX05BTUU7XG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKGNvbmZpZ0ZpbGUpIHx8ICFmcy5leGlzdHNTeW5jKGJ1aWxkRmlsZSkpIHtcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgYCR7RVJST1JfUFJFRklYfSBPb3BzLiBJdCBhcHBlYXJzIHRoYXQgeW91IGhhdmVuJ3QgZXhlY3V0ZWQgdGhlIFwiJHtUT09MX05BTUV9IGluaXRcIiBjb21tYW5kLCByZXN1bHRpbmcgaW4gdGhlIGFic2VuY2Ugb2YgYW55IGNvbmZpZ3VyYXRpb24gZmlsZXM6YFxuICAgICk7XG4gICAgY29uc29sZS5lcnJvcihgPiAgICAgICAke2NvbmZpZ0ZpbGV9YCk7XG4gICAgY29uc29sZS5lcnJvcihgPiAgICAgICAke2J1aWxkRmlsZX1gKTtcbiAgICBjb25zb2xlLmxvZyhgXFxuUGxlYXNlIHJ1biAnJHtUT09MX05BTUV9IGluaXQnIGZpcnN0LlxcbmApO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuXG4gIHZhciBjb3VudGVyID0gMTtcbiAgY29uc3QgaG9zdGluZ0NvbmZpZ3VyYXRpb24gPSBhd2FpdCBsb2FkSG9zdGluZ0NvbmZpZ3VyYXRpb24oKTtcblxuICB2YXIgY2VydGlmaWNhdGVBcm5DbWRQYXJhbSA9IFwiXCI7XG4gIGlmIChob3N0aW5nQ29uZmlndXJhdGlvbi5kb21haW5OYW1lKSB7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBgXFxuIC0tPiAke2NvdW50ZXIrK30uIFNldHRpbmcgdXAgYSBTU0wvVExTIGNlcnRpZmljYXRlIHdpdGggQVdTIENlcnRpZmljYXRlIE1hbmFnZXIgKEFDTSkgXFxuYFxuICAgICk7XG5cbiAgICBsZXQgeyBjZXJ0aWZpY2F0ZUFybiwgc3RhdHVzIH0gPSBhd2FpdCBjaGVja0NlcnRpZmljYXRlRXhpc3RzKFxuICAgICAgaG9zdGluZ0NvbmZpZ3VyYXRpb24uZG9tYWluTmFtZVxuICAgICk7XG4gICAgICBjb25zb2xlLmxvZyhcInN0YXR1cz1cIitzdGF0dXMpXG4gICAgaWYgKCFjZXJ0aWZpY2F0ZUFybikge1xuICAgICAgY2VydGlmaWNhdGVBcm4gPSBhd2FpdCBjcmVhdGVBQ01DZXJ0aWZpY2F0ZShcbiAgICAgICAgaG9zdGluZ0NvbmZpZ3VyYXRpb24uZG9tYWluTmFtZVxuICAgICAgKTtcblxuICAgICAgaWYgKGNlcnRpZmljYXRlQXJuKSB7XG4gICAgICAgIGF3YWl0IHdhaXRDZXJ0aWZpY2F0ZVRvQmVJc3N1ZWQoXG4gICAgICAgICAgY2VydGlmaWNhdGVBcm4sXG4gICAgICAgICAgaG9zdGluZ0NvbmZpZ3VyYXRpb24uaG9zdGVkWm9uZUlkXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiVGhlIGNlcnRpZmljYXRlIGZvciB0aGlzIGRvbWFpbiBoYXMgYWxyZWFkeSBiZWVuIGNyZWF0ZWQuIFwiKTtcblxuICAgICAgaWYgKHN0YXR1cyAhPSBcIklTU1VFRFwiKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiQ2VydGlmaWNhdGUgaXMgbm90IHJlYWR5IHRvIGJlIHVzZWQuIFdhaXRpbmcgLi4uXCIpO1xuICAgICAgICBhd2FpdCB3YWl0Q2VydGlmaWNhdGVUb0JlSXNzdWVkKFxuICAgICAgICAgIGNlcnRpZmljYXRlQXJuLFxuICAgICAgICAgIGhvc3RpbmdDb25maWd1cmF0aW9uLmhvc3RlZFpvbmVJZFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJcXG5UaGUgY2VydGlmaWNhdGUgaXMgcmVhZHkgdG8gYmUgdXNlZC5cIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY2VydGlmaWNhdGVBcm5DbWRQYXJhbSA9IGAtLWNvbnRleHQgY2VydGlmaWNhdGUtYXJuPSR7Y2VydGlmaWNhdGVBcm59YDtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKGBcXG4gLS0+ICR7Y291bnRlcisrfS4gQm9vdHN0cmFwcGluZyB5b3VyIEFXUyBhY2NvdW50IFxcbmApO1xuICBjb25zdCBjb25maWdGaWxlUGF0aCA9IGdldENMSUV4ZWN1dGlvbkZvbGRlcigpICsgXCIvXCIgKyBUT09MX05BTUU7XG5cbiAgY29uc3QgYm9vdHN0cmFwQ21kID1gbnB4IGNkayBib290c3RyYXAgLS1jb250ZXh0IGNvbmZpZy1wYXRoPSR7Y29uZmlnRmlsZVBhdGh9ICR7Y2VydGlmaWNhdGVBcm5DbWRQYXJhbX1gO1xuICBhd2FpdCBleGVjdXRlQ29tbWFuZHMoYm9vdHN0cmFwQ21kLCBnZXRDTElJbnN0YWxsYXRpb25Gb2xkZXIoKSk7XG5cbiAgaWYgKGlzUmVwb0NvbmZpZyhob3N0aW5nQ29uZmlndXJhdGlvbikpIHtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBcXG4gLS0+ICR7Y291bnRlcisrfS4gQ3JlYXRlIHJlc291cmNlcyBmb3IgY29ubmVjdGluZyB5b3VyIEFXUyBhY2NvdW50IHRvIHlvdXIgR2l0SHViIHJlcG9zaXRvcnkuIFxcbmBcbiAgICApO1xuICAgIGNvbnN0IGNyZWF0ZUNvbm5lY3Rpb25DbWQ9IGBucHggY2RrIGRlcGxveSAgJHtjYWxjdWxhdGVDb25uZWN0aW9uU3RhY2tOYW1lKFxuICAgICAgICBob3N0aW5nQ29uZmlndXJhdGlvbi5yZXBvVXJsLFxuICAgICAgICBob3N0aW5nQ29uZmlndXJhdGlvbi5icmFuY2hOYW1lXG4gICAgICApfSAtLWNvbnRleHQgY29uZmlnLXBhdGg9JHtjb25maWdGaWxlUGF0aH0gICR7Y2VydGlmaWNhdGVBcm5DbWRQYXJhbX0gYDtcbiAgICBhd2FpdCBleGVjdXRlQ29tbWFuZHMoY3JlYXRlQ29ubmVjdGlvbkNtZCwgZ2V0Q0xJSW5zdGFsbGF0aW9uRm9sZGVyKCkpO1xuXG4gICAgY29uc3QgZ2V0UGVuZGluZ0Nvbm5lY3Rpb25zID0gYXdhaXQgcGVuZGluZ0Nvbm5lY3Rpb25zKCk7XG5cbiAgICBpZiAoZ2V0UGVuZGluZ0Nvbm5lY3Rpb25zKSB7XG4gICAgICAvL3RoZXJlIGFyZSBjb25uZWN0aW9uIGluIFBFTkRJTkcgU1RBVEUsIHdhaXQgZm9yIHRoZSB1c2VyIHRvIHZhbGlkYXRlIHRoZW1cbiAgICAgIGF3YWl0IGNvbm5lY3Rpb25fcHJvbXB0KGNvdW50ZXIrKyk7XG4gICAgfVxuICAgIFxuICB9IGVsc2UgaWYgKGlzUzNDb25maWcoaG9zdGluZ0NvbmZpZ3VyYXRpb24pKSB7XG4gICAgLy9jaGVjayBpZiB0aGUgUzMgYnVja2V0IGV4aXN0c1xuICAgIGNvbnN0IGJ1Y2tldEV4aXN0cyA9IGF3YWl0IGNoZWNrQnVja2V0RXhpc3RzKGhvc3RpbmdDb25maWd1cmF0aW9uLnMzYnVja2V0KTtcbiAgICBpZiAoIWJ1Y2tldEV4aXN0cykge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgYFxcbiR7RVJST1JfUFJFRklYfSBUaGUgc3BlY2lmaWVkIGJ1Y2tldCAnJHtob3N0aW5nQ29uZmlndXJhdGlvbi5zM2J1Y2tldH0nIGRvZXNuJ3QgZXhpc3QgaW4gdGhlIGN1cnJlbnQgcmVnaW9uLiBQbGVhc2UgcmVydW4gJyR7VE9PTF9OQU1FfSBpbml0JyBvciBjcmVhdGUgYSBidWNrZXQgd2l0aCB0aGF0IG5hbWUgaW4gdGhlIGN1cnJlbnQgcmVnaW9uLlxcbmBcbiAgICAgICk7XG4gICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBgJHtFUlJPUl9QUkVGSVh9IEV4aXRpbmcgZHVlIHRvIGFuIGludmFsaWQgY29uZmlndXJhdGlvbiBmaWxlLmBcbiAgICApO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKFxuICAgIGBcXG4gLS0+ICR7Y291bnRlcisrfS4gRGVwbG95IHRoZSBob3N0aW5nIGluZnJhc3RydWN0dXJlIHdpdGhpbiB5b3VyIEFXUyBhY2NvdW50IFxcbmBcbiAgKTtcblxuICBjb25zb2xlLmxvZyhcbiAgICBcIlBsZWFzZSB3YWl0IHdoaWxlIGRlcGxveWluZyB0aGUgaW5mcmFzdHJ1Y3R1cmUsIGl0IG1heSB0YWtlIGEgZmV3IG1pbnV0ZXMuXCJcbiAgKTtcblxuICBjb25zdCBjcmVhdGVJbmZyYXN0cnVjdHVyZUNtZCA9IGBucHggY2RrIGRlcGxveSAke2NhbGN1bGF0ZU1haW5TdGFja05hbWUoXG4gICAgICBob3N0aW5nQ29uZmlndXJhdGlvblxuICAgICl9ICAtLWNvbnRleHQgY29uZmlnLXBhdGg9JHtjb25maWdGaWxlUGF0aH0gLS1yZXF1aXJlLWFwcHJvdmFsIG5ldmVyICR7Y2VydGlmaWNhdGVBcm5DbWRQYXJhbX1gO1xuICBhd2FpdCBleGVjdXRlQ29tbWFuZHMoY3JlYXRlSW5mcmFzdHJ1Y3R1cmVDbWQsIGdldENMSUluc3RhbGxhdGlvbkZvbGRlcigpKTtcbiAgY29uc29sZS5sb2coXG4gICAgXCJcXG5fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19cXG5cIlxuICApO1xuXG4gIGNvbnN0IGRvbWFpbk5hbWUgPSBhd2FpdCBnZXRTU01QYXJhbWV0ZXIoU1NNX0RPTUFJTl9TVFIpO1xuICBjb25zdCBwaXBlbGluZU5hbWUgPSBhd2FpdCBnZXRTU01QYXJhbWV0ZXIoU1NNX1BJUEVMSU5FTkFNRV9TVFIpO1xuXG4gIGlmIChkb21haW5OYW1lKSB7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBcIlxcblRoZSBPcmlnaW4gcGFpcmVkIHdpdGggaXRzIGFzc29jaWF0ZWQgQ2xvdWRGcm9udCBkb21haW4gbmFtZTpcXG5cIlxuICAgICk7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBgPiAgICAgICAke1xuICAgICAgICBpc1JlcG9Db25maWcoaG9zdGluZ0NvbmZpZ3VyYXRpb24pXG4gICAgICAgICAgPyBcIkNvZGUgUmVwb3NpdG9yeVwiXG4gICAgICAgICAgOiBcIlMzIFNvdXJjZSBDb2RlXCJcbiAgICAgIH06ICR7XG4gICAgICAgIGlzUmVwb0NvbmZpZyhob3N0aW5nQ29uZmlndXJhdGlvbilcbiAgICAgICAgICA/IGhvc3RpbmdDb25maWd1cmF0aW9uLnJlcG9VcmxcbiAgICAgICAgICA6IGhvc3RpbmdDb25maWd1cmF0aW9uLnMzYnVja2V0ICsgXCIvXCIgKyBob3N0aW5nQ29uZmlndXJhdGlvbi5zM3BhdGhcbiAgICAgIH1gXG4gICAgKTtcblxuICAgIGNvbnNvbGUubG9nKGA+ICAgICAgIEhvc3Rpbmc6IGh0dHBzOi8vJHtkb21haW5OYW1lfSBcXG5gKTtcblxuICAgIGlmIChob3N0aW5nQ29uZmlndXJhdGlvbi5kb21haW5OYW1lKSB7XG4gICAgICBpZiAoaG9zdGluZ0NvbmZpZ3VyYXRpb24uaG9zdGVkWm9uZUlkKSB7XG4gICAgICAgIGNvbnN0IGNGQ05BTUVFeGlzdHMgPSBhd2FpdCBjaGVja0NGQVJlY29yZEV4aXN0cyhcbiAgICAgICAgICBob3N0aW5nQ29uZmlndXJhdGlvbi5kb21haW5OYW1lLFxuICAgICAgICAgIGRvbWFpbk5hbWUsXG4gICAgICAgICAgaG9zdGluZ0NvbmZpZ3VyYXRpb24uaG9zdGVkWm9uZUlkXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKCFjRkNOQU1FRXhpc3RzKSB7XG4gICAgICAgICAgY29uc3QgYXNzb2NpYXRlID0gYXdhaXQgc3RhcnRQcm9tcHQoY2xvdWRGcm9udEFzc29jaWF0aW9uUXVlc3Rpb24pO1xuICAgICAgICAgIGlmIChhc3NvY2lhdGUudmFsdWUgPT0gXCJ5ZXNcIikge1xuICAgICAgICAgICAgYXdhaXQgY3JlYXRlQ0ZBUmVjb3JkKFxuICAgICAgICAgICAgICBob3N0aW5nQ29uZmlndXJhdGlvbi5kb21haW5OYW1lLFxuICAgICAgICAgICAgICBkb21haW5OYW1lLFxuICAgICAgICAgICAgICBob3N0aW5nQ29uZmlndXJhdGlvbi5ob3N0ZWRab25lSWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgYD4gICAgICAgRG9tYWluIG5hbWUgJyR7aG9zdGluZ0NvbmZpZ3VyYXRpb24uZG9tYWluTmFtZX0nIGlzIGFscmVhZHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbi5cXG5gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBcXG5KdXN0IGEgZmV3IG1vcmUgc3RlcHMgdG8gZ2V0IHlvdXIgZG9tYWluIG5hbWUgdXAgYW5kIHJ1bm5pbmchYFxuICAgICAgICApO1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgXFxuVG8gbWFrZSB5b3VyIGRvbWFpbiBuYW1lIHBvaW50IHRvIHlvdXIgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24sIHlvdSBuZWVkIHRvIGNvbmZpZ3VyZSBhIENOQU1FIGVudHJ5IGluIHRoZSBhdXRob3JpdGF0aXZlIEROUyBzZXJ2ZXIgb2YgeW91ciBkb21haW4uIFRoaXMgaXMgYSBzaW1wbGUgcHJvY2VzcyB0aGF0IHVzdWFsbHkgdGFrZXMganVzdCBhIGZldyBtaW51dGVzLmBcbiAgICAgICAgKTtcbiAgICAgICAgY29uc29sZS5sb2coXCJIZXJlJ3Mgd2hhdCB5b3UgbmVlZCB0byBkbzpcIik7XG5cbiAgICAgICAgY29uc29sZS5sb2coXCI+ICAgICAgIExvZyBpbiB0byB5b3VyIEROUyBwcm92aWRlci5cIik7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiPiAgICAgICBGaW5kIHRoZSBzZWN0aW9uIGZvciBjcmVhdGluZyBuZXcgRE5TIHJlY29yZHMuXCIpO1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBcIj4gICAgICAgQ3JlYXRlIGEgbmV3IENOQU1FIHJlY29yZCB3aXRoIHRoZSBmb2xsb3dpbmcgaW5mb3JtYXRpb246XCJcbiAgICAgICAgKTtcbiAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgYD4gICAgICAgICAgIEhvc3QgbmFtZTogJHtob3N0aW5nQ29uZmlndXJhdGlvbi5kb21haW5OYW1lfWBcbiAgICAgICAgKTtcbiAgICAgICAgY29uc29sZS5sb2coYD4gICAgICAgICAgIFRhcmdldDogJHtkb21haW5OYW1lfWApO1xuICAgICAgICBjb25zb2xlLmxvZyhcIj4gICAgICAgU2F2ZSB5b3VyIGNoYW5nZXMuXCIpO1xuXG4gICAgICAgIGNvbnNvbGUubG9nKFwiXFxuXCIpO1xuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBcIj4gICAgICAgVGhhdCdzIGl0ISBPbmNlIHlvdSd2ZSBzYXZlZCB5b3VyIGNoYW5nZXMsIHlvdXIgZG9tYWluIG5hbWUgd2lsbCBzdGFydCBwb2ludGluZyB0byB5b3VyIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uLlwiXG4gICAgICAgICk7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiXFxuXFxuXCIpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaXNSZXBvQ29uZmlnKGhvc3RpbmdDb25maWd1cmF0aW9uKSkge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgIFwiXFxuSW4gdGhlIGZ1dHVyZSwgd2hlbmV2ZXIgeW91IHB1c2ggY2hhbmdlcyB0byB5b3VyIEdpdGh1YiByZXBvc2l0b3J5LCBhbiBhdXRvbWF0aWMgcGlwZWxpbmUgd2lsbCBiZSB0cmlnZ2VyZWQgdG8gZGVwbG95IHRoZSBuZXcgdmVyc2lvbi5cIlxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5sb2coXG4gICAgICAgIFwiXFxuSW4gdGhlIGZ1dHVyZSwgd2hlbmV2ZXIgeW91IHVwbG9hZCBhIHppcCBmaWxlIHRvIHRoZSBkZXNpZ25hdGVkIFMzIEJ1Y2tldCwgYW4gYXV0b21hdGVkIHByb2Nlc3Mgd2lsbCBiZSBpbml0aWF0ZWQgdG8gZGVwbG95IHRoZSBsYXRlc3QgdmVyc2lvbi5cIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIFwiXFxuX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXFxuXFxuXCJcbiAgICApO1xuXG4gICAgY29uc29sZS5sb2coXG4gICAgICBcIlRoZSBob3N0aW5nIGluZnJhc3RydWN0dXJlIGZvciB5b3VyIHByb2plY3QgaGFzIGJlZW4gc3VjY2Vzc2Z1bGx5IGRlcGxveWVkIG9uIHlvdXIgQVdTIGFjY291bnRcIlxuICAgICk7XG4gICAgY29uc29sZS5sb2coXCJcXG5cIik7XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIFwiVGhlIGRlcGxveW1lbnQgY29uc2lzdHMgb2YgdGhlIGZvbGxvd2luZyBBV1MgQ2xvdWRGb3JtYXRpb24gc3RhY2socyk6XCJcbiAgICApO1xuICAgIGlmIChpc1JlcG9Db25maWcoaG9zdGluZ0NvbmZpZ3VyYXRpb24pKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYD4gICAgICAgICAgICR7Y2FsY3VsYXRlQ29ubmVjdGlvblN0YWNrTmFtZShcbiAgICAgICAgICBob3N0aW5nQ29uZmlndXJhdGlvbi5yZXBvVXJsLFxuICAgICAgICAgIGhvc3RpbmdDb25maWd1cmF0aW9uLmJyYW5jaE5hbWVcbiAgICAgICAgKX1gXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgPiAgICAgICAgICAgJHtjYWxjdWxhdGVNYWluU3RhY2tOYW1lKGhvc3RpbmdDb25maWd1cmF0aW9uKX1cXG5gKTtcblxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFRoZSBmb2xsb3dpbmcgQVdTIENvZGVQaXBlbGluZSBoYXMgYmVlbiBjcmVhdGVkIGZvciBhdXRvbWF0aWMgZGVwbG95bWVudCB1cG9uIEdpdCBwdXNoIGV4ZWN1dGlvbjpgXG4gICAgKTtcbiAgICBjb25zb2xlLmxvZyhgPiAgICAgICAgICAgJHtwaXBlbGluZU5hbWV9XFxuYCk7XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIFwiWW91IGNhbiByZXZpZXcgdGhlIHJlc291cmNlcyBkZXBsb3llZCBieSBsb2dnaW5nIGludG8gdGhlIEFXUyBNYW5hZ2VtZW50IENvbnNvbGUgYXQgaHR0cHM6Ly9hd3MuYW1hem9uLmNvbS9jb25zb2xlIFxcblwiXG4gICAgKTtcbiAgICBhd2FpdCBzdGFydFBpcGVsaW5lRXhlY3V0aW9uKCk7XG4gICAgYXdhaXQgY2hlY2tQaXBlbGluZVN0YXR1cygpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICBgJHtFUlJPUl9QUkVGSVh9IE5vIGRvbWFpbiBuYW1lcyBhdmFpbGFibGUgZHVlIHRvIG1pc3NpbmcgaW5mb3JtYXRpb24gaW4gU1NNLmBcbiAgICApO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjb25uZWN0aW9uX3Byb21wdChjb3VudGVyOiBudW1iZXIpIHtcbiAgY29uc3QgY29ubmVjdGlvblJlZ2lvbiA9IGF3YWl0IGdldFNTTVBhcmFtZXRlcihTU01fQ09OTkVDVElPTl9SRUdJT05fU1RSKTtcbiAgY29uc3QgY29ubmVjdGlvbk5hbWUgPSBhd2FpdCBnZXRTU01QYXJhbWV0ZXIoU1NNX0NPTk5FQ1RJT05fTkFNRV9TVFIpO1xuXG4gIGNvbnNvbGUubG9nKGBcXG4gLS0+ICR7Y291bnRlcn0uIENvbmZpZ3VyZSBnaXRodWIgY29ubmVjdGlvblxcbmApO1xuXG4gIGNvbnNvbGUubG9nKFxuICAgIFwiWW91IG5lZWQgdG8gY29tcGxldGUgR2l0aHViIGF1dGhlbnRpY2F0aW9uIHVzaW5nIHRoZSBBV1MgQ29uc29sZS5cIlxuICApO1xuICBjb25zb2xlLmxvZyhcIlRvIGRvIHNvLCBmb2xsb3cgdGhlc2Ugc3RlcHM6XFxuXCIpO1xuICBjb25zb2xlLmxvZyhcIiAxLiBPcGVuIHRoZSBmb2xsb3dpbmcgcGFnZTogXCIpO1xuICBjb25zb2xlLmxvZyhcbiAgICBcIiAgICBodHRwczovL1wiICtcbiAgICAgIGNvbm5lY3Rpb25SZWdpb24gK1xuICAgICAgXCIuY29uc29sZS5hd3MuYW1hem9uLmNvbS9jb2Rlc3VpdGUvc2V0dGluZ3MvY29ubmVjdGlvbnNcIlxuICApO1xuXG4gIGNvbnNvbGUubG9nKFxuICAgIFwiIDIuIEluIHRoZSBjb25uZWN0aW9uIGxpc3QsIGxvb2sgb3V0IGZvciBjb25uZWN0aW9uIG5hbWU6IFwiICtcbiAgICAgIGNvbm5lY3Rpb25OYW1lXG4gICk7XG4gIGNvbnNvbGUubG9nKFxuICAgIFwiIDMuIEZvciB0aGlzIGNvbm5lY3Rpb24gd2l0aCBTdGF0dXM9UGVuZGluZywgY29tcGxldGUgdGhlIGNvbm5lY3Rpb24gYnkgZm9sbG93aW5nIHRoZXNlIGluc3RydWN0aW9uczpcIlxuICApO1xuICBjb25zb2xlLmxvZyhcIiAgICAgLSBTZWxlY3QgdGhlIHBlbmRpbmcgY29ubmVjdGlvbiAgXCIgKyBjb25uZWN0aW9uTmFtZSArIFwiLlwiKTtcbiAgY29uc29sZS5sb2coXCIgICAgIC0gQ2xpY2sgb24gVXBkYXRlIGEgcGVuZGluZyBjb25uZWN0aW9uLlwiKTtcbiAgY29uc29sZS5sb2coXG4gICAgXCIgICAgIC0gSW4gdGhlIG5ldyBwb3B1cCB3aW5kb3csIHVuZGVyIEdpdGh1YiBhcHBzLCBjaG9vc2UgYW4gYXBwIGluc3RhbGxhdGlvbiwgb3IgY3JlYXRlIGEgbmV3IGFwcCBieSBzZWxlY3RpbmcgSW5zdGFsbCBhIG5ldyBhcHAuXCJcbiAgKTtcbiAgY29uc29sZS5sb2coXG4gICAgXCIgICAgIC0gSWYgeW91IGhhdmUgYWxyZWFkeSBpbnN0YWxsZWQgYW4gYXBwLCBzZWxlY3QgdGhlIGFwcCwgY2xpY2sgb24gQ29ubmVjdCwgYW5kIHJlZnJlc2ggdGhlIHBhZ2UgaWYgbmVlZGVkLiBUaGUgc3RhdHVzIG9mIHRoZSBjb25uZWN0aW9uIHNob3VsZCBiZSBBdmFpbGFibGUuXCJcbiAgKTtcbiAgY29uc29sZS5sb2coXG4gICAgXCIgICAgIC0gSWYgeW91IGNob29zZSB0byBJbnN0YWxsIGEgbmV3IGFwcCwgZm9sbG93IHRoZSBvbi1zY3JlZW4gaW5zdHJ1Y3Rpb25zIHRvIGF1dGhlbnRpY2F0ZSB5b3VyIEdpdGh1YiBhY2NvdW50LCBjbGljayBvbiBDb25uZWN0LCBhbmQgcmVmcmVzaCB0aGUgcGFnZSBpZiBuZWVkZWQuIFRoZSBzdGF0dXMgb2YgdGhlIGNvbm5lY3Rpb24gc2hvdWxkIGJlIEF2YWlsYWJsZS5cIlxuICApO1xuICBjb25zb2xlLmxvZyhcIlxcblwiKTtcblxuICBhd2FpdCBzdGFydFByb21wdChjb250aW51ZUNvbmZpcm1hdGlvblF1ZXN0aW9uKTtcbn1cbiJdfQ==