UNPKG

@cdktf/hcl2cdk

Version:
415 lines (414 loc) 52 kB
"use strict"; 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 }); exports.referenceToAst = void 0; // Copyright (c) HashiCorp, Inc // SPDX-License-Identifier: MPL-2.0 const generator_1 = __importDefault(require("@babel/generator")); const t = __importStar(require("@babel/types")); const expressions_1 = require("../expressions"); const references_1 = require("../references"); const hcl2json_1 = require("@cdktf/hcl2json"); const utils_1 = require("../utils"); const nodeIds = [ "var.input", "module.vpc", "data.aws_s3_bucket.examplebucket", "aws_s3_bucket.examplebucket", "aws_s3_bucket.otherbucket", "var.users", "aws_kms_key.key", "local.service_name", ]; // Transforms a path with segments into literals describing the path function getPropertyAccessPath(input) { return input .split(/(\[|\]|\.)/g) .filter((p) => p.length > 0 && p !== "." && p !== "[" && p !== "]") .map((p) => (p.startsWith(`"`) && p.endsWith(`"`) ? p.slice(1, -1) : p)); } function referenceToAst(scope, ref) { const [resource, , ...selector] = ref.referencee.full.split("."); const variableReference = t.identifier((0, utils_1.camelCase)((0, references_1.referenceToVariableName)(scope, ref))); if (resource === "data") { selector.shift(); // remove the data part so that the name is not used in the selector } const accessor = selector.reduce((carry, member, index) => t.memberExpression(carry, t.identifier(index === 0 && resource === "module" ? (0, utils_1.camelCase)(member + "Output") : (0, utils_1.camelCase)(member))), variableReference); if (ref.useFqn) { return t.memberExpression(accessor, t.identifier("fqn")); } if (ref.isVariable) { return t.memberExpression(accessor, t.identifier("value")); } return accessor; } exports.referenceToAst = referenceToAst; describe("expressions", () => { describe("#extractReferencesFromExpression", () => { it("finds no references in literals", () => { return expect((0, references_1.extractReferencesFromExpression)("nothingtobeseen", nodeIds)).resolves.toEqual([]); }); it("finds no references in literals with functions", () => { return expect((0, references_1.extractReferencesFromExpression)("${foo(nothingtobeseen)}", nodeIds)).resolves.toEqual([]); }); it("finds no references in literals with functions and artihmetics", () => { return expect((0, references_1.extractReferencesFromExpression)("${foo(nothingtobeseen - 2) + 3}", nodeIds)).resolves.toEqual([]); }); it("finds plain var reference", () => { return expect((0, references_1.extractReferencesFromExpression)("${var.input}", nodeIds)).resolves.toEqual([ { referencee: { id: "var.input", full: "var.input" }, useFqn: false, isVariable: true, start: 2, end: 11, }, ]); }); it("finds plain module reference", () => { return expect((0, references_1.extractReferencesFromExpression)("${module.vpc.public_subnets}", nodeIds)).resolves.toEqual([ { referencee: { id: "module.vpc", full: "module.vpc.public_subnets", }, useFqn: false, isVariable: false, start: 2, end: 27, }, ]); }); it("finds plain data reference", () => { return expect((0, references_1.extractReferencesFromExpression)("${data.aws_s3_bucket.examplebucket.arn}", nodeIds)).resolves.toEqual([ { referencee: { id: "data.aws_s3_bucket.examplebucket", full: "data.aws_s3_bucket.examplebucket.arn", }, useFqn: false, isVariable: false, start: 2, end: 38, }, ]); }); it("finds plain local reference", () => { return expect((0, references_1.extractReferencesFromExpression)("${local.service_name}", nodeIds)).resolves.toEqual([ { referencee: { id: "local.service_name", full: "local.service_name", }, useFqn: false, isVariable: false, start: 2, end: 20, }, ]); }); it("finds plain resource reference", () => { return expect((0, references_1.extractReferencesFromExpression)("${aws_s3_bucket.examplebucket.id}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket.id", }, useFqn: false, isVariable: false, start: 2, end: 32, }, ]); }); it("finds plain resource references in artihmetics", () => { return expect((0, references_1.extractReferencesFromExpression)("${aws_s3_bucket.examplebucket.count + aws_s3_bucket.otherbucket.count }", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket.count", }, useFqn: false, isVariable: false, start: 2, end: 35, }, { referencee: { id: "aws_s3_bucket.otherbucket", full: "aws_s3_bucket.otherbucket.count", }, useFqn: false, isVariable: false, start: 38, end: 69, }, ]); }); it("use fqn for splat reference", () => { return expect((0, references_1.extractReferencesFromExpression)("${aws_s3_bucket.examplebucket.*.id}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: true, isVariable: false, start: 2, end: 29, }, ]); }); it("use no fqn if property is present on numeric access", () => { return expect((0, references_1.extractReferencesFromExpression)("${aws_s3_bucket.examplebucket.network_interface.0.access_config.0.assigned_nat_ip}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: true, isVariable: false, start: 2, end: 81, }, ]); }); it("detect splat reference within function", () => { return expect((0, references_1.extractReferencesFromExpression)("${toset(aws_s3_bucket.examplebucket.*)}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: true, isVariable: false, start: 8, end: 35, }, ]); }); it("finds all resources in conditional", () => { return expect((0, references_1.extractReferencesFromExpression)("${aws_kms_key.key.deletion_window_in_days > 3 ? aws_s3_bucket.examplebucket.id : []}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_kms_key.key", full: "aws_kms_key.key.deletion_window_in_days", }, useFqn: false, isVariable: false, start: 2, end: 41, }, { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket.id", }, useFqn: false, isVariable: false, start: 48, end: 78, }, ]); }); it("finds all resources in functions", () => { return expect((0, references_1.extractReferencesFromExpression)("${element(aws_s3_bucket.examplebucket, 0).id}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: false, isVariable: false, start: 10, end: 37, }, ]); }); it("finds all resources in functions with splat", () => { return expect((0, references_1.extractReferencesFromExpression)("${element(aws_s3_bucket.examplebucket.*.id, 0)}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: true, isVariable: false, start: 10, end: 37, }, ]); }); it("finds all resources in for loops", () => { return expect((0, references_1.extractReferencesFromExpression)("${{ for name, user in var.users : user.role => name...}}", nodeIds)).resolves.toEqual([ { referencee: { id: "var.users", full: "var.users" }, useFqn: false, isVariable: true, start: 22, end: 31, }, ]); }); it("finds resources with property access", () => { return expect((0, references_1.extractReferencesFromExpression)("${aws_s3_bucket.examplebucket[0].id}", nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: true, isVariable: false, start: 2, end: 35, }, ]); }); it("finds references within functions that use arrays and comments", () => { return expect((0, references_1.extractReferencesFromExpression)(`\${compact([ # The example "bucket" aws_s3_bucket.examplebucket, # The "Learn" single page application. This is not configured in all environments. var.input, ])}`, nodeIds)).resolves.toEqual([ { referencee: { id: "aws_s3_bucket.examplebucket", full: "aws_s3_bucket.examplebucket", }, useFqn: false, isVariable: false, start: 59, end: 86, }, { referencee: { id: "var.input", full: "var.input", }, useFqn: false, isVariable: true, start: 204, end: 213, }, ]); }); it("finds references for same referencees", () => { return expect((0, references_1.extractReferencesFromExpression)(`\${var.input == "test" ? "azure-ad-int" : "azure-ad-\${var.input}"}`, nodeIds)).resolves.toEqual([ { referencee: { id: "var.input", full: "var.input", }, useFqn: false, isVariable: true, start: 2, end: 11, }, { referencee: { id: "var.input", full: "var.input", }, useFqn: false, isVariable: true, start: 53, end: 62, }, ]); }); }); describe("#referenceToAst", () => { it("property access", () => { const scope = { providerSchema: { format_version: "0.1" }, providerGenerator: {}, constructs: new Set(), variables: {}, hasTokenBasedTypeCoercion: false, nodeIds: [], importables: [], topLevelConfig: {}, }; expect((0, generator_1.default)(t.program([ t.expressionStatement(referenceToAst(scope, { start: 0, end: 0, useFqn: false, isVariable: false, referencee: { id: "aws_kms_key.key", full: "aws_kms_key.key.deletion_window_in_days", }, })), ])).code).toMatchInlineSnapshot(`"key.deletionWindowInDays;"`); }); }); describe("#iteratorVariableToAst", () => { async function run(value) { const scope = { providerSchema: { format_version: "0.1" }, providerGenerator: {}, constructs: new Set(), variables: {}, hasTokenBasedTypeCoercion: false, nodeIds: [], importables: [], topLevelConfig: {}, }; const ast = await (0, hcl2json_1.getExpressionAst)("main.tf", value); return (0, generator_1.default)(t.program([ t.expressionStatement((0, expressions_1.dynamicVariableToAst)(scope, ast.children[0], "myIterator")), ])).code; } it("should convert iterator key accessor", async () => { expect(await run('"${each.key}"')).toMatchInlineSnapshot(`"myIterator.key;"`); }); it("should convert iterator value accessor", async () => { expect(await run('"${each.value}"')).toMatchInlineSnapshot(`"myIterator.value;"`); }); it("should convert iterator value deep accessor", async () => { expect(await run('"${each.value.list.map.name}"')).toMatchInlineSnapshot(`"Fn.lookupNested(myIterator.value, ["list", "map", "name"]);"`); }); it("should convert iterator value with map access", async () => { expect(await run('"${each.value[0]["map"]["name"]}"')).toMatchInlineSnapshot(`"Fn.lookupNested(myIterator.value, ["[0]", "[\\"map\\"]", "[\\"name\\"]"]);"`); }); }); describe("#getPropertyAccessPath", () => { it.each([ [".list.map.name", ["list", "map", "name"]], [`[0]["map"]["name"]`, ["0", "map", "name"]], [`[0].map["name"]`, ["0", "map", "name"]], ])("should return the correct path for %s", (input, expected) => { expect(getPropertyAccessPath(input)).toEqual(expected); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc2lvbnMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4cHJlc3Npb25zLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQkFBK0I7QUFDL0IsbUNBQW1DO0FBQ25DLGlFQUF3QztBQUN4QyxnREFBa0M7QUFDbEMsZ0RBQXNEO0FBRXRELDhDQUd1QjtBQUN2Qiw4Q0FBbUQ7QUFFbkQsb0NBQXFDO0FBRXJDLE1BQU0sT0FBTyxHQUFHO0lBQ2QsV0FBVztJQUNYLFlBQVk7SUFDWixrQ0FBa0M7SUFDbEMsNkJBQTZCO0lBQzdCLDJCQUEyQjtJQUMzQixXQUFXO0lBQ1gsaUJBQWlCO0lBQ2pCLG9CQUFvQjtDQUNyQixDQUFDO0FBRUYsb0VBQW9FO0FBQ3BFLFNBQVMscUJBQXFCLENBQUMsS0FBYTtJQUMxQyxPQUFPLEtBQUs7U0FDVCxLQUFLLENBQUMsYUFBYSxDQUFDO1NBQ3BCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUM7U0FDbEUsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM3RSxDQUFDO0FBRUQsU0FBZ0IsY0FBYyxDQUFDLEtBQW1CLEVBQUUsR0FBYztJQUNoRSxNQUFNLENBQUMsUUFBUSxFQUFFLEFBQUQsRUFBRyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEdBQUcs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QUFNLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDLENBQUMscUJBQXFCLENBQ3RFLCtEQUErRCxDQUNoRSxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0NBQStDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDN0QsTUFBTSxDQUNKLE1BQU0sR0FBRyxDQUFDLG1DQUFtQyxDQUFDLENBQy9DLENBQUMscUJBQXFCLENBQ3JCLDhFQUE4RSxDQUMvRSxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLEVBQUU7UUFDdEMsRUFBRSxDQUFDLElBQUksQ0FBQztZQUNOLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzNDLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVDLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQzFDLENBQUMsQ0FBQyx1Q0FBdUMsRUFBRSxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRTtZQUM5RCxNQUFNLENBQUMscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSBIYXNoaUNvcnAsIEluY1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1QTC0yLjBcbmltcG9ydCBnZW5lcmF0ZSBmcm9tIFwiQGJhYmVsL2dlbmVyYXRvclwiO1xuaW1wb3J0ICogYXMgdCBmcm9tIFwiQGJhYmVsL3R5cGVzXCI7XG5pbXBvcnQgeyBkeW5hbWljVmFyaWFibGVUb0FzdCB9IGZyb20gXCIuLi9leHByZXNzaW9uc1wiO1xuaW1wb3J0IHsgUHJvZ3JhbVNjb3BlLCBSZWZlcmVuY2UgfSBmcm9tIFwiLi4vdHlwZXNcIjtcbmltcG9ydCB7XG4gIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24sXG4gIHJlZmVyZW5jZVRvVmFyaWFibGVOYW1lLFxufSBmcm9tIFwiLi4vcmVmZXJlbmNlc1wiO1xuaW1wb3J0IHsgZ2V0RXhwcmVzc2lvbkFzdCB9IGZyb20gXCJAY2RrdGYvaGNsMmpzb25cIjtcbmltcG9ydCB7IFRGRXhwcmVzc2lvblN5bnRheFRyZWUgYXMgdGV4IH0gZnJvbSBcIkBjZGt0Zi9oY2wyanNvblwiO1xuaW1wb3J0IHsgY2FtZWxDYXNlIH0gZnJvbSBcIi4uL3V0aWxzXCI7XG5cbmNvbnN0IG5vZGVJZHMgPSBbXG4gIFwidmFyLmlucHV0XCIsXG4gIFwibW9kdWxlLnZwY1wiLFxuICBcImRhdGEuYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gIFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gIFwiYXdzX3MzX2J1Y2tldC5vdGhlcmJ1Y2tldFwiLFxuICBcInZhci51c2Vyc1wiLFxuICBcImF3c19rbXNfa2V5LmtleVwiLFxuICBcImxvY2FsLnNlcnZpY2VfbmFtZVwiLFxuXTtcblxuLy8gVHJhbnNmb3JtcyBhIHBhdGggd2l0aCBzZWdtZW50cyBpbnRvIGxpdGVyYWxzIGRlc2NyaWJpbmcgdGhlIHBhdGhcbmZ1bmN0aW9uIGdldFByb3BlcnR5QWNjZXNzUGF0aChpbnB1dDogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gaW5wdXRcbiAgICAuc3BsaXQoLyhcXFt8XFxdfFxcLikvZylcbiAgICAuZmlsdGVyKChwKSA9PiBwLmxlbmd0aCA+IDAgJiYgcCAhPT0gXCIuXCIgJiYgcCAhPT0gXCJbXCIgJiYgcCAhPT0gXCJdXCIpXG4gICAgLm1hcCgocCkgPT4gKHAuc3RhcnRzV2l0aChgXCJgKSAmJiBwLmVuZHNXaXRoKGBcImApID8gcC5zbGljZSgxLCAtMSkgOiBwKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWZlcmVuY2VUb0FzdChzY29wZTogUHJvZ3JhbVNjb3BlLCByZWY6IFJlZmVyZW5jZSkge1xuICBjb25zdCBbcmVzb3VyY2UsICwgLi4uc2VsZWN0b3JdID0gcmVmLnJlZmVyZW5jZWUuZnVsbC5zcGxpdChcIi5cIik7XG5cbiAgY29uc3QgdmFyaWFibGVSZWZlcmVuY2UgPSB0LmlkZW50aWZpZXIoXG4gICAgY2FtZWxDYXNlKHJlZmVyZW5jZVRvVmFyaWFibGVOYW1lKHNjb3BlLCByZWYpKSxcbiAgKTtcblxuICBpZiAocmVzb3VyY2UgPT09IFwiZGF0YVwiKSB7XG4gICAgc2VsZWN0b3Iuc2hpZnQoKTsgLy8gcmVtb3ZlIHRoZSBkYXRhIHBhcnQgc28gdGhhdCB0aGUgbmFtZSBpcyBub3QgdXNlZCBpbiB0aGUgc2VsZWN0b3JcbiAgfVxuXG4gIGNvbnN0IGFjY2Vzc29yID0gc2VsZWN0b3IucmVkdWNlKFxuICAgIChjYXJyeSwgbWVtYmVyLCBpbmRleCkgPT5cbiAgICAgIHQubWVtYmVyRXhwcmVzc2lvbihcbiAgICAgICAgY2FycnksXG4gICAgICAgIHQuaWRlbnRpZmllcihcbiAgICAgICAgICBpbmRleCA9PT0gMCAmJiByZXNvdXJjZSA9PT0gXCJtb2R1bGVcIlxuICAgICAgICAgICAgPyBjYW1lbENhc2UobWVtYmVyICsgXCJPdXRwdXRcIilcbiAgICAgICAgICAgIDogY2FtZWxDYXNlKG1lbWJlciksXG4gICAgICAgICksXG4gICAgICApLFxuICAgIHZhcmlhYmxlUmVmZXJlbmNlIGFzIHQuRXhwcmVzc2lvbixcbiAgKTtcblxuICBpZiAocmVmLnVzZUZxbikge1xuICAgIHJldHVybiB0Lm1lbWJlckV4cHJlc3Npb24oYWNjZXNzb3IsIHQuaWRlbnRpZmllcihcImZxblwiKSk7XG4gIH1cblxuICBpZiAocmVmLmlzVmFyaWFibGUpIHtcbiAgICByZXR1cm4gdC5tZW1iZXJFeHByZXNzaW9uKGFjY2Vzc29yLCB0LmlkZW50aWZpZXIoXCJ2YWx1ZVwiKSk7XG4gIH1cbiAgcmV0dXJuIGFjY2Vzc29yO1xufVxuXG5kZXNjcmliZShcImV4cHJlc3Npb25zXCIsICgpID0+IHtcbiAgZGVzY3JpYmUoXCIjZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvblwiLCAoKSA9PiB7XG4gICAgaXQoXCJmaW5kcyBubyByZWZlcmVuY2VzIGluIGxpdGVyYWxzXCIsICgpID0+IHtcbiAgICAgIHJldHVybiBleHBlY3QoXG4gICAgICAgIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24oXCJub3RoaW5ndG9iZXNlZW5cIiwgbm9kZUlkcyksXG4gICAgICApLnJlc29sdmVzLnRvRXF1YWwoW10pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJmaW5kcyBubyByZWZlcmVuY2VzIGluIGxpdGVyYWxzIHdpdGggZnVuY3Rpb25zXCIsICgpID0+IHtcbiAgICAgIHJldHVybiBleHBlY3QoXG4gICAgICAgIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24oXCIke2Zvbyhub3RoaW5ndG9iZXNlZW4pfVwiLCBub2RlSWRzKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIG5vIHJlZmVyZW5jZXMgaW4gbGl0ZXJhbHMgd2l0aCBmdW5jdGlvbnMgYW5kIGFydGlobWV0aWNzXCIsICgpID0+IHtcbiAgICAgIHJldHVybiBleHBlY3QoXG4gICAgICAgIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24oXG4gICAgICAgICAgXCIke2Zvbyhub3RoaW5ndG9iZXNlZW4gLSAyKSArIDN9XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIHBsYWluIHZhciByZWZlcmVuY2VcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcIiR7dmFyLmlucHV0fVwiLCBub2RlSWRzKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7IGlkOiBcInZhci5pbnB1dFwiLCBmdWxsOiBcInZhci5pbnB1dFwiIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiB0cnVlLFxuICAgICAgICAgIHN0YXJ0OiAyLFxuICAgICAgICAgIGVuZDogMTEsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZmluZHMgcGxhaW4gbW9kdWxlIHJlZmVyZW5jZVwiLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KFxuICAgICAgICBleHRyYWN0UmVmZXJlbmNlc0Zyb21FeHByZXNzaW9uKFxuICAgICAgICAgIFwiJHttb2R1bGUudnBjLnB1YmxpY19zdWJuZXRzfVwiLFxuICAgICAgICAgIG5vZGVJZHMsXG4gICAgICAgICksXG4gICAgICApLnJlc29sdmVzLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwibW9kdWxlLnZwY1wiLFxuICAgICAgICAgICAgZnVsbDogXCJtb2R1bGUudnBjLnB1YmxpY19zdWJuZXRzXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IGZhbHNlLFxuICAgICAgICAgIGlzVmFyaWFibGU6IGZhbHNlLFxuICAgICAgICAgIHN0YXJ0OiAyLFxuICAgICAgICAgIGVuZDogMjcsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZmluZHMgcGxhaW4gZGF0YSByZWZlcmVuY2VcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBcIiR7ZGF0YS5hd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuYXJufVwiLFxuICAgICAgICAgIG5vZGVJZHMsXG4gICAgICAgICksXG4gICAgICApLnJlc29sdmVzLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwiZGF0YS5hd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiZGF0YS5hd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuYXJuXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IGZhbHNlLFxuICAgICAgICAgIGlzVmFyaWFibGU6IGZhbHNlLFxuICAgICAgICAgIHN0YXJ0OiAyLFxuICAgICAgICAgIGVuZDogMzgsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZmluZHMgcGxhaW4gbG9jYWwgcmVmZXJlbmNlXCIsICgpID0+IHtcbiAgICAgIHJldHVybiBleHBlY3QoXG4gICAgICAgIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24oXCIke2xvY2FsLnNlcnZpY2VfbmFtZX1cIiwgbm9kZUlkcyksXG4gICAgICApLnJlc29sdmVzLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwibG9jYWwuc2VydmljZV9uYW1lXCIsXG4gICAgICAgICAgICBmdWxsOiBcImxvY2FsLnNlcnZpY2VfbmFtZVwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogMixcbiAgICAgICAgICBlbmQ6IDIwLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIHBsYWluIHJlc291cmNlIHJlZmVyZW5jZVwiLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KFxuICAgICAgICBleHRyYWN0UmVmZXJlbmNlc0Zyb21FeHByZXNzaW9uKFxuICAgICAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuaWR9XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgICAgICBpZDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LmlkXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IGZhbHNlLFxuICAgICAgICAgIGlzVmFyaWFibGU6IGZhbHNlLFxuICAgICAgICAgIHN0YXJ0OiAyLFxuICAgICAgICAgIGVuZDogMzIsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZmluZHMgcGxhaW4gcmVzb3VyY2UgcmVmZXJlbmNlcyBpbiBhcnRpaG1ldGljc1wiLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KFxuICAgICAgICBleHRyYWN0UmVmZXJlbmNlc0Zyb21FeHByZXNzaW9uKFxuICAgICAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuY291bnQgKyBhd3NfczNfYnVja2V0Lm90aGVyYnVja2V0LmNvdW50IH1cIixcbiAgICAgICAgICBub2RlSWRzLFxuICAgICAgICApLFxuICAgICAgKS5yZXNvbHZlcy50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHJlZmVyZW5jZWU6IHtcbiAgICAgICAgICAgIGlkOiBcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiLFxuICAgICAgICAgICAgZnVsbDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuY291bnRcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVzZUZxbjogZmFsc2UsXG4gICAgICAgICAgaXNWYXJpYWJsZTogZmFsc2UsXG4gICAgICAgICAgc3RhcnQ6IDIsXG4gICAgICAgICAgZW5kOiAzNSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHJlZmVyZW5jZWU6IHtcbiAgICAgICAgICAgIGlkOiBcImF3c19zM19idWNrZXQub3RoZXJidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiYXdzX3MzX2J1Y2tldC5vdGhlcmJ1Y2tldC5jb3VudFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogMzgsXG4gICAgICAgICAgZW5kOiA2OSxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJ1c2UgZnFuIGZvciBzcGxhdCByZWZlcmVuY2VcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0LiouaWR9XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgICAgICBpZDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IHRydWUsXG4gICAgICAgICAgaXNWYXJpYWJsZTogZmFsc2UsXG4gICAgICAgICAgc3RhcnQ6IDIsXG4gICAgICAgICAgZW5kOiAyOSxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJ1c2Ugbm8gZnFuIGlmIHByb3BlcnR5IGlzIHByZXNlbnQgb24gbnVtZXJpYyBhY2Nlc3NcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBcIiR7YXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0Lm5ldHdvcmtfaW50ZXJmYWNlLjAuYWNjZXNzX2NvbmZpZy4wLmFzc2lnbmVkX25hdF9pcH1cIixcbiAgICAgICAgICBub2RlSWRzLFxuICAgICAgICApLFxuICAgICAgKS5yZXNvbHZlcy50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHJlZmVyZW5jZWU6IHtcbiAgICAgICAgICAgIGlkOiBcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiLFxuICAgICAgICAgICAgZnVsbDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVzZUZxbjogdHJ1ZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogMixcbiAgICAgICAgICBlbmQ6IDgxLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImRldGVjdCBzcGxhdCByZWZlcmVuY2Ugd2l0aGluIGZ1bmN0aW9uXCIsICgpID0+IHtcbiAgICAgIHJldHVybiBleHBlY3QoXG4gICAgICAgIGV4dHJhY3RSZWZlcmVuY2VzRnJvbUV4cHJlc3Npb24oXG4gICAgICAgICAgXCIke3Rvc2V0KGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC4qKX1cIixcbiAgICAgICAgICBub2RlSWRzLFxuICAgICAgICApLFxuICAgICAgKS5yZXNvbHZlcy50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHJlZmVyZW5jZWU6IHtcbiAgICAgICAgICAgIGlkOiBcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiLFxuICAgICAgICAgICAgZnVsbDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVzZUZxbjogdHJ1ZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogOCxcbiAgICAgICAgICBlbmQ6IDM1LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIGFsbCByZXNvdXJjZXMgaW4gY29uZGl0aW9uYWxcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBcIiR7YXdzX2ttc19rZXkua2V5LmRlbGV0aW9uX3dpbmRvd19pbl9kYXlzID4gMyA/IGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5pZCA6IFtdfVwiLFxuICAgICAgICAgIG5vZGVJZHMsXG4gICAgICAgICksXG4gICAgICApLnJlc29sdmVzLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwiYXdzX2ttc19rZXkua2V5XCIsXG4gICAgICAgICAgICBmdWxsOiBcImF3c19rbXNfa2V5LmtleS5kZWxldGlvbl93aW5kb3dfaW5fZGF5c1wiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogMixcbiAgICAgICAgICBlbmQ6IDQxLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gICAgICAgICAgICBmdWxsOiBcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldC5pZFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogNDgsXG4gICAgICAgICAgZW5kOiA3OCxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJmaW5kcyBhbGwgcmVzb3VyY2VzIGluIGZ1bmN0aW9uc1wiLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KFxuICAgICAgICBleHRyYWN0UmVmZXJlbmNlc0Zyb21FeHByZXNzaW9uKFxuICAgICAgICAgIFwiJHtlbGVtZW50KGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldCwgMCkuaWR9XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgICAgICBpZDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IGZhbHNlLFxuICAgICAgICAgIGlzVmFyaWFibGU6IGZhbHNlLFxuICAgICAgICAgIHN0YXJ0OiAxMCxcbiAgICAgICAgICBlbmQ6IDM3LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIGFsbCByZXNvdXJjZXMgaW4gZnVuY3Rpb25zIHdpdGggc3BsYXRcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBcIiR7ZWxlbWVudChhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXQuKi5pZCwgMCl9XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgICAgICBpZDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IHRydWUsXG4gICAgICAgICAgaXNWYXJpYWJsZTogZmFsc2UsXG4gICAgICAgICAgc3RhcnQ6IDEwLFxuICAgICAgICAgIGVuZDogMzcsXG4gICAgICAgIH0sXG4gICAgICBdKTtcbiAgICB9KTtcblxuICAgIGl0KFwiZmluZHMgYWxsIHJlc291cmNlcyBpbiBmb3IgbG9vcHNcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBcIiR7eyBmb3IgbmFtZSwgdXNlciBpbiB2YXIudXNlcnMgOiB1c2VyLnJvbGUgPT4gbmFtZS4uLn19XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7IGlkOiBcInZhci51c2Vyc1wiLCBmdWxsOiBcInZhci51c2Vyc1wiIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiB0cnVlLFxuICAgICAgICAgIHN0YXJ0OiAyMixcbiAgICAgICAgICBlbmQ6IDMxLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIHJlc291cmNlcyB3aXRoIHByb3BlcnR5IGFjY2Vzc1wiLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KFxuICAgICAgICBleHRyYWN0UmVmZXJlbmNlc0Zyb21FeHByZXNzaW9uKFxuICAgICAgICAgIFwiJHthd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRbMF0uaWR9XCIsXG4gICAgICAgICAgbm9kZUlkcyxcbiAgICAgICAgKSxcbiAgICAgICkucmVzb2x2ZXMudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgICAgICBpZDogXCJhd3NfczNfYnVja2V0LmV4YW1wbGVidWNrZXRcIixcbiAgICAgICAgICAgIGZ1bGw6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1c2VGcW46IHRydWUsXG4gICAgICAgICAgaXNWYXJpYWJsZTogZmFsc2UsXG4gICAgICAgICAgc3RhcnQ6IDIsXG4gICAgICAgICAgZW5kOiAzNSxcbiAgICAgICAgfSxcbiAgICAgIF0pO1xuICAgIH0pO1xuXG4gICAgaXQoXCJmaW5kcyByZWZlcmVuY2VzIHdpdGhpbiBmdW5jdGlvbnMgdGhhdCB1c2UgYXJyYXlzIGFuZCBjb21tZW50c1wiLCAoKSA9PiB7XG4gICAgICByZXR1cm4gZXhwZWN0KFxuICAgICAgICBleHRyYWN0UmVmZXJlbmNlc0Zyb21FeHByZXNzaW9uKFxuICAgICAgICAgIGBcXCR7Y29tcGFjdChbXG4gICAgICAgICAgICAjIFRoZSBleGFtcGxlIFwiYnVja2V0XCJcbiAgICAgICAgICAgIGF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldCxcbiAgICAgICAgXG4gICAgICAgICAgICAjIFRoZSBcIkxlYXJuXCIgc2luZ2xlIHBhZ2UgYXBwbGljYXRpb24uIFRoaXMgaXMgbm90IGNvbmZpZ3VyZWQgaW4gYWxsIGVudmlyb25tZW50cy5cbiAgICAgICAgICAgIHZhci5pbnB1dCxcbiAgICAgICAgICBdKX1gLFxuICAgICAgICAgIG5vZGVJZHMsXG4gICAgICAgICksXG4gICAgICApLnJlc29sdmVzLnRvRXF1YWwoW1xuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwiYXdzX3MzX2J1Y2tldC5leGFtcGxlYnVja2V0XCIsXG4gICAgICAgICAgICBmdWxsOiBcImF3c19zM19idWNrZXQuZXhhbXBsZWJ1Y2tldFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICBzdGFydDogNTksXG4gICAgICAgICAgZW5kOiA4NixcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHJlZmVyZW5jZWU6IHtcbiAgICAgICAgICAgIGlkOiBcInZhci5pbnB1dFwiLFxuICAgICAgICAgICAgZnVsbDogXCJ2YXIuaW5wdXRcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVzZUZxbjogZmFsc2UsXG4gICAgICAgICAgaXNWYXJpYWJsZTogdHJ1ZSxcbiAgICAgICAgICBzdGFydDogMjA0LFxuICAgICAgICAgIGVuZDogMjEzLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG5cbiAgICBpdChcImZpbmRzIHJlZmVyZW5jZXMgZm9yIHNhbWUgcmVmZXJlbmNlZXNcIiwgKCkgPT4ge1xuICAgICAgcmV0dXJuIGV4cGVjdChcbiAgICAgICAgZXh0cmFjdFJlZmVyZW5jZXNGcm9tRXhwcmVzc2lvbihcbiAgICAgICAgICBgXFwke3Zhci5pbnB1dCA9PSBcInRlc3RcIiA/IFwiYXp1cmUtYWQtaW50XCIgOiBcImF6dXJlLWFkLVxcJHt2YXIuaW5wdXR9XCJ9YCxcbiAgICAgICAgICBub2RlSWRzLFxuICAgICAgICApLFxuICAgICAgKS5yZXNvbHZlcy50b0VxdWFsKFtcbiAgICAgICAge1xuICAgICAgICAgIHJlZmVyZW5jZWU6IHtcbiAgICAgICAgICAgIGlkOiBcInZhci5pbnB1dFwiLFxuICAgICAgICAgICAgZnVsbDogXCJ2YXIuaW5wdXRcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVzZUZxbjogZmFsc2UsXG4gICAgICAgICAgaXNWYXJpYWJsZTogdHJ1ZSxcbiAgICAgICAgICBzdGFydDogMixcbiAgICAgICAgICBlbmQ6IDExLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgcmVmZXJlbmNlZToge1xuICAgICAgICAgICAgaWQ6IFwidmFyLmlucHV0XCIsXG4gICAgICAgICAgICBmdWxsOiBcInZhci5pbnB1dFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICBpc1ZhcmlhYmxlOiB0cnVlLFxuICAgICAgICAgIHN0YXJ0OiA1MyxcbiAgICAgICAgICBlbmQ6IDYyLFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiI3JlZmVyZW5jZVRvQXN0XCIsICgpID0+IHtcbiAgICBpdChcInByb3BlcnR5IGFjY2Vzc1wiLCAoKSA9PiB7XG4gICAgICBjb25zdCBzY29wZTogUHJvZ3JhbVNjb3BlID0ge1xuICAgICAgICBwcm92aWRlclNjaGVtYTogeyBmb3JtYXRfdmVyc2lvbjogXCIwLjFcIiB9LFxuICAgICAgICBwcm92aWRlckdlbmVyYXRvcjoge30sXG4gICAgICAgIGNvbnN0cnVjdHM6IG5ldyBTZXQ8c3RyaW5nPigpLFxuICAgICAgICB2YXJpYWJsZXM6IHt9LFxuICAgICAgICBoYXNUb2tlbkJhc2VkVHlwZUNvZXJjaW9uOiBmYWxzZSxcbiAgICAgICAgbm9kZUlkczogW10sXG4gICAgICAgIGltcG9ydGFibGVzOiBbXSxcbiAgICAgICAgdG9wTGV2ZWxDb25maWc6IHt9LFxuICAgICAgfTtcbiAgICAgIGV4cGVjdChcbiAgICAgICAgZ2VuZXJhdGUoXG4gICAgICAgICAgdC5wcm9ncmFtKFtcbiAgICAgICAgICAgIHQuZXhwcmVzc2lvblN0YXRlbWVudChcbiAgICAgICAgICAgICAgcmVmZXJlbmNlVG9Bc3Qoc2NvcGUsIHtcbiAgICAgICAgICAgICAgICBzdGFydDogMCxcbiAgICAgICAgICAgICAgICBlbmQ6IDAsXG4gICAgICAgICAgICAgICAgdXNlRnFuOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc1ZhcmlhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICByZWZlcmVuY2VlOiB7XG4gICAgICAgICAgICAgICAgICBpZDogXCJhd3Nfa21zX2tleS5rZXlcIixcbiAgICAgICAgICAgICAgICAgIGZ1bGw6IFwiYXdzX2ttc19rZXkua2V5LmRlbGV0aW9uX3dpbmRvd19pbl9kYXlzXCIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0pIGFzIGFueSxcbiAgICAgICAgKS5jb2RlLFxuICAgICAgKS50b01hdGNoSW5saW5lU25hcHNob3QoYFwia2V5LmRlbGV0aW9uV2luZG93SW5EYXlzO1wiYCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKFwiI2l0ZXJhdG9yVmFyaWFibGVUb0FzdFwiLCAoKSA9PiB7XG4gICAgYXN5bmMgZnVuY3Rpb24gcnVuKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IHNjb3BlOiBQcm9ncmFtU2NvcGUgPSB7XG4gICAgICAgIHByb3ZpZGVyU2NoZW1hOiB7IGZvcm1hdF92ZXJzaW9uOiBcIjAuMVwiIH0sXG4gICAgICAgIHByb3ZpZGVyR2VuZXJhdG9yOiB7fSxcbiAgICAgICAgY29uc3RydWN0czogbmV3IFNldDxzdHJpbmc+KCksXG4gICAgICAgIHZhcmlhYmxlczoge30sXG4gICAgICAgIGhhc1Rva2VuQmFzZWRUeXBlQ29lcmNpb246IGZhbHNlLFxuICAgICAgICBub2RlSWRzOiBbXSxcbiAgICAgICAgaW1wb3J0YWJsZXM6IFtdLFxuICAgICAgICB0b3BMZXZlbENvbmZpZzoge30sXG4gICAgICB9O1xuICAgICAgY29uc3QgYXN0ID0gYXdhaXQgZ2V0RXhwcmVzc2lvbkFzdChcIm1haW4udGZcIiwgdmFsdWUpO1xuICAgICAgcmV0dXJuIGdlbmVyYXRlKFxuICAgICAgICB0LnByb2dyYW0oW1xuICAgICAgICAgIHQuZXhwcmVzc2lvblN0YXRlbWVudChcbiAgICAgICAgICAgIGR5bmFtaWNWYXJpYWJsZVRvQXN0KFxuICAgICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgICAgYXN0IS5jaGlsZH