UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

287 lines 45.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VpcNetworkContextProviderPlugin = void 0; const cx_api_1 = require("@aws-cdk/cx-api"); const sdk_provider_1 = require("../api/aws-auth/sdk-provider"); const logging_1 = require("../logging"); const error_1 = require("../toolkit/error"); class VpcNetworkContextProviderPlugin { constructor(aws) { this.aws = aws; } async getValue(args) { const ec2 = (await (0, sdk_provider_1.initContextProviderSdk)(this.aws, args)).ec2(); const vpcId = await this.findVpc(ec2, args); return this.readVpcProps(ec2, vpcId, args); } async findVpc(ec2, args) { // Build request filter (map { Name -> Value } to list of [{ Name, Values }]) const filters = Object.entries(args.filter).map(([tag, value]) => ({ Name: tag, Values: [value] })); (0, logging_1.debug)(`Listing VPCs in ${args.account}:${args.region}`); const response = await ec2.describeVpcs({ Filters: filters }); const vpcs = response.Vpcs || []; if (vpcs.length === 0) { throw new error_1.ContextProviderError(`Could not find any VPCs matching ${JSON.stringify(args)}`); } if (vpcs.length > 1) { throw new error_1.ContextProviderError(`Found ${vpcs.length} VPCs matching ${JSON.stringify(args)}; please narrow the search criteria`); } return vpcs[0]; } async readVpcProps(ec2, vpc, args) { const vpcId = vpc.VpcId; (0, logging_1.debug)(`Describing VPC ${vpcId}`); const filters = { Filters: [{ Name: 'vpc-id', Values: [vpcId] }] }; const subnetsResponse = await ec2.describeSubnets(filters); const listedSubnets = subnetsResponse.Subnets || []; const routeTablesResponse = await ec2.describeRouteTables(filters); const routeTables = new RouteTables(routeTablesResponse.RouteTables || []); // Now comes our job to separate these subnets out into AZs and subnet groups (Public, Private, Isolated) // We have the following attributes to go on: // - Type tag, we tag subnets with their type. In absence of this tag, we // determine the subnet must be Public if either: // a) it has the property MapPublicIpOnLaunch // b) it has a route to an Internet Gateway // If both of the above is false but the subnet has a route to a NAT Gateway // and the destination CIDR block is "0.0.0.0/0", we assume it to be a Private subnet. // Anything else is considered Isolated. // - Name tag, we tag subnets with their subnet group name. In absence of this tag, // we use the type as the name. const azs = Array.from(new Set(listedSubnets.map((s) => s.AvailabilityZone))); azs.sort(); const subnets = listedSubnets.map((subnet) => { let type = getTag('aws-cdk:subnet-type', subnet.Tags); if (type === undefined && subnet.MapPublicIpOnLaunch) { type = SubnetType.Public; } if (type === undefined && routeTables.hasRouteToIgw(subnet.SubnetId)) { type = SubnetType.Public; } if (type === undefined && routeTables.hasRouteToNatGateway(subnet.SubnetId)) { type = SubnetType.Private; } if (type === undefined && routeTables.hasRouteToTransitGateway(subnet.SubnetId)) { type = SubnetType.Private; } if (type === undefined) { type = SubnetType.Isolated; } if (!isValidSubnetType(type)) { // eslint-disable-next-line max-len throw new error_1.ContextProviderError(`Subnet ${subnet.SubnetArn} has invalid subnet type ${type} (must be ${SubnetType.Public}, ${SubnetType.Private} or ${SubnetType.Isolated})`); } if (args.subnetGroupNameTag && !getTag(args.subnetGroupNameTag, subnet.Tags)) { throw new error_1.ContextProviderError(`Invalid subnetGroupNameTag: Subnet ${subnet.SubnetArn} does not have an associated tag with Key='${args.subnetGroupNameTag}'`); } const name = getTag(args.subnetGroupNameTag || 'aws-cdk:subnet-name', subnet.Tags) || type; const routeTableId = routeTables.routeTableIdForSubnetId(subnet.SubnetId); if (!routeTableId) { throw new error_1.ContextProviderError(`Subnet ${subnet.SubnetArn} does not have an associated route table (and there is no "main" table)`); } return { az: subnet.AvailabilityZone, cidr: subnet.CidrBlock, type, name, subnetId: subnet.SubnetId, routeTableId, }; }); let grouped; let assymetricSubnetGroups; if (args.returnAsymmetricSubnets) { grouped = { azs: [], groups: [] }; assymetricSubnetGroups = groupAsymmetricSubnets(subnets); } else { grouped = groupSubnets(subnets); assymetricSubnetGroups = undefined; } // Find attached+available VPN gateway for this VPC const vpnGatewayResponse = (args.returnVpnGateways ?? true) ? await ec2.describeVpnGateways({ Filters: [ { Name: 'attachment.vpc-id', Values: [vpcId], }, { Name: 'attachment.state', Values: ['attached'], }, { Name: 'state', Values: ['available'], }, ], }) : undefined; const vpnGatewayId = vpnGatewayResponse?.VpnGateways?.length === 1 ? vpnGatewayResponse.VpnGateways[0].VpnGatewayId : undefined; return { vpcId, vpcCidrBlock: vpc.CidrBlock, ownerAccountId: vpc.OwnerId, availabilityZones: grouped.azs, isolatedSubnetIds: collapse(flatMap(findGroups(SubnetType.Isolated, grouped), (group) => group.subnets.map((s) => s.subnetId))), isolatedSubnetNames: collapse(flatMap(findGroups(SubnetType.Isolated, grouped), (group) => (group.name ? [group.name] : []))), isolatedSubnetRouteTableIds: collapse(flatMap(findGroups(SubnetType.Isolated, grouped), (group) => group.subnets.map((s) => s.routeTableId))), privateSubnetIds: collapse(flatMap(findGroups(SubnetType.Private, grouped), (group) => group.subnets.map((s) => s.subnetId))), privateSubnetNames: collapse(flatMap(findGroups(SubnetType.Private, grouped), (group) => (group.name ? [group.name] : []))), privateSubnetRouteTableIds: collapse(flatMap(findGroups(SubnetType.Private, grouped), (group) => group.subnets.map((s) => s.routeTableId))), publicSubnetIds: collapse(flatMap(findGroups(SubnetType.Public, grouped), (group) => group.subnets.map((s) => s.subnetId))), publicSubnetNames: collapse(flatMap(findGroups(SubnetType.Public, grouped), (group) => (group.name ? [group.name] : []))), publicSubnetRouteTableIds: collapse(flatMap(findGroups(SubnetType.Public, grouped), (group) => group.subnets.map((s) => s.routeTableId))), vpnGatewayId, subnetGroups: assymetricSubnetGroups, }; } } exports.VpcNetworkContextProviderPlugin = VpcNetworkContextProviderPlugin; class RouteTables { constructor(tables) { this.tables = tables; this.mainRouteTable = this.tables.find((table) => !!table.Associations && table.Associations.some((assoc) => !!assoc.Main)); } routeTableIdForSubnetId(subnetId) { const table = this.tableForSubnet(subnetId); return (table && table.RouteTableId) || (this.mainRouteTable && this.mainRouteTable.RouteTableId); } /** * Whether the given subnet has a route to a NAT Gateway */ hasRouteToNatGateway(subnetId) { const table = this.tableForSubnet(subnetId) || this.mainRouteTable; return (!!table && !!table.Routes && table.Routes.some((route) => !!route.NatGatewayId && route.DestinationCidrBlock === '0.0.0.0/0')); } /** * Whether the given subnet has a route to a Transit Gateway */ hasRouteToTransitGateway(subnetId) { const table = this.tableForSubnet(subnetId) || this.mainRouteTable; return (!!table && !!table.Routes && table.Routes.some((route) => !!route.TransitGatewayId && route.DestinationCidrBlock === '0.0.0.0/0')); } /** * Whether the given subnet has a route to an IGW */ hasRouteToIgw(subnetId) { const table = this.tableForSubnet(subnetId) || this.mainRouteTable; return (!!table && !!table.Routes && table.Routes.some((route) => !!route.GatewayId && route.GatewayId.startsWith('igw-'))); } tableForSubnet(subnetId) { return this.tables.find((table) => !!table.Associations && table.Associations.some((assoc) => assoc.SubnetId === subnetId)); } } /** * Return the value of a tag from a set of tags */ function getTag(name, tags) { for (const tag of tags || []) { if (tag.Key === name) { return tag.Value; } } return undefined; } /** * Group subnets of the same type together, and order by AZ */ function groupSubnets(subnets) { const grouping = {}; for (const subnet of subnets) { const key = [subnet.type, subnet.name].toString(); if (!(key in grouping)) { grouping[key] = []; } grouping[key].push(subnet); } const groups = Object.values(grouping).map((sns) => { sns.sort((a, b) => a.az.localeCompare(b.az)); return { type: sns[0].type, name: sns[0].name, subnets: sns, }; }); const azs = groups[0].subnets.map((s) => s.az); for (const group of groups) { const groupAZs = group.subnets.map((s) => s.az); if (!arraysEqual(groupAZs, azs)) { throw new error_1.ContextProviderError(`Not all subnets in VPC have the same AZs: ${groupAZs} vs ${azs}`); } } return { azs, groups }; } function groupAsymmetricSubnets(subnets) { const grouping = {}; for (const subnet of subnets) { const key = [subnet.type, subnet.name].toString(); if (!(key in grouping)) { grouping[key] = []; } grouping[key].push(subnet); } return Object.values(grouping).map((subnetArray) => { subnetArray.sort((subnet1, subnet2) => subnet1.az.localeCompare(subnet2.az)); return { name: subnetArray[0].name, type: subnetTypeToVpcSubnetType(subnetArray[0].type), subnets: subnetArray.map((subnet) => ({ subnetId: subnet.subnetId, cidr: subnet.cidr, availabilityZone: subnet.az, routeTableId: subnet.routeTableId, })), }; }); } function subnetTypeToVpcSubnetType(type) { switch (type) { case SubnetType.Isolated: return cx_api_1.VpcSubnetGroupType.ISOLATED; case SubnetType.Private: return cx_api_1.VpcSubnetGroupType.PRIVATE; case SubnetType.Public: return cx_api_1.VpcSubnetGroupType.PUBLIC; } } var SubnetType; (function (SubnetType) { SubnetType["Public"] = "Public"; SubnetType["Private"] = "Private"; SubnetType["Isolated"] = "Isolated"; })(SubnetType || (SubnetType = {})); function isValidSubnetType(val) { return val === SubnetType.Public || val === SubnetType.Private || val === SubnetType.Isolated; } function arraysEqual(as, bs) { if (as.length !== bs.length) { return false; } for (let i = 0; i < as.length; i++) { if (as[i] !== bs[i]) { return false; } } return true; } function findGroups(type, groups) { return groups.groups.filter((g) => g.type === type); } function flatMap(xs, fn) { const ret = new Array(); for (const x of xs) { ret.push(...fn(x)); } return ret; } function collapse(xs) { if (xs.length > 0) { return xs; } return undefined; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidnBjcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInZwY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsNENBQW1HO0FBR25HLCtEQUF3RjtBQUV4Rix3Q0FBbUM7QUFDbkMsNENBQXdEO0FBQ3hELE1BQWEsK0JBQStCO0lBQzFDLFlBQTZCLEdBQWdCO1FBQWhCLFFBQUcsR0FBSCxHQUFHLENBQWE7SUFBRyxDQUFDO0lBRTFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBcUI7UUFDekMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLElBQUEscUNBQXNCLEVBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBRWpFLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFNUMsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUVPLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBZSxFQUFFLElBQXFCO1FBQzFELDZFQUE2RTtRQUM3RSxNQUFNLE9BQU8sR0FBYSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFOUcsSUFBQSxlQUFLLEVBQUMsbUJBQW1CLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDeEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxD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QUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDbEIsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgVnBjQ29udGV4dFF1ZXJ5IH0gZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCB7IHR5cGUgVnBjQ29udGV4dFJlc3BvbnNlLCB0eXBlIFZwY1N1Ym5ldEdyb3VwLCBWcGNTdWJuZXRHcm91cFR5cGUgfSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHR5cGUgeyBGaWx0ZXIsIFJvdXRlVGFibGUsIFRhZywgVnBjIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVjMic7XG5pbXBvcnQgdHlwZSB7IElFQzJDbGllbnQgfSBmcm9tICcuLi9hcGknO1xuaW1wb3J0IHsgdHlwZSBTZGtQcm92aWRlciwgaW5pdENvbnRleHRQcm92aWRlclNkayB9IGZyb20gJy4uL2FwaS9hd3MtYXV0aC9zZGstcHJvdmlkZXInO1xuaW1wb3J0IHsgQ29udGV4dFByb3ZpZGVyUGx1Z2luIH0gZnJvbSAnLi4vYXBpL3BsdWdpbic7XG5pbXBvcnQgeyBkZWJ1ZyB9IGZyb20gJy4uL2xvZ2dpbmcnO1xuaW1wb3J0IHsgQ29udGV4dFByb3ZpZGVyRXJyb3IgfSBmcm9tICcuLi90b29sa2l0L2Vycm9yJztcbmV4cG9ydCBjbGFzcyBWcGNOZXR3b3JrQ29udGV4dFByb3ZpZGVyUGx1Z2luIGltcGxlbWVudHMgQ29udGV4dFByb3ZpZGVyUGx1Z2luIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBhd3M6IFNka1Byb3ZpZGVyKSB7fVxuXG4gIHB1YmxpYyBhc3luYyBnZXRWYWx1ZShhcmdzOiBWcGNDb250ZXh0UXVlcnkpIHtcbiAgICBjb25zdCBlYzIgPSAoYXdhaXQgaW5pdENvbnRleHRQcm92aWRlclNkayh0aGlzLmF3cywgYXJncykpLmVjMigpO1xuXG4gICAgY29uc3QgdnBjSWQgPSBhd2FpdCB0aGlzLmZpbmRWcGMoZWMyLCBhcmdzKTtcblxuICAgIHJldHVybiB0aGlzLnJlYWRWcGNQcm9wcyhlYzIsIHZwY0lkLCBhcmdzKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmluZFZwYyhlYzI6IElFQzJDbGllbnQsIGFyZ3M6IFZwY0NvbnRleHRRdWVyeSk6IFByb21pc2U8VnBjPiB7XG4gICAgLy8gQnVpbGQgcmVxdWVzdCBmaWx0ZXIgKG1hcCB7IE5hbWUgLT4gVmFsdWUgfSB0byBsaXN0IG9mIFt7IE5hbWUsIFZhbHVlcyB9XSlcbiAgICBjb25zdCBmaWx0ZXJzOiBGaWx0ZXJbXSA9IE9iamVjdC5lbnRyaWVzKGFyZ3MuZmlsdGVyKS5tYXAoKFt0YWcsIHZhbHVlXSkgPT4gKHsgTmFtZTogdGFnLCBWYWx1ZXM6IFt2YWx1ZV0gfSkpO1xuXG4gICAgZGVidWcoYExpc3RpbmcgVlBDcyBpbiAke2FyZ3MuYWNjb3VudH06JHthcmdzLnJlZ2lvbn1gKTtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGVjMi5kZXNjcmliZVZwY3MoeyBGaWx0ZXJzOiBmaWx0ZXJzIH0pO1xuXG4gICAgY29uc3QgdnBjcyA9IHJlc3BvbnNlLlZwY3MgfHwgW107XG4gICAgaWYgKHZwY3MubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgQ29udGV4dFByb3ZpZGVyRXJyb3IoYENvdWxkIG5vdCBmaW5kIGFueSBWUENzIG1hdGNoaW5nICR7SlNPTi5zdHJpbmdpZnkoYXJncyl9YCk7XG4gICAgfVxuICAgIGlmICh2cGNzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZXh0UHJvdmlkZXJFcnJvcihgRm91bmQgJHt2cGNzLmxlbmd0aH0gVlBDcyBtYXRjaGluZyAke0pTT04uc3RyaW5naWZ5KGFyZ3MpfTsgcGxlYXNlIG5hcnJvdyB0aGUgc2VhcmNoIGNyaXRlcmlhYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZwY3NbMF07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlYWRWcGNQcm9wcyhlYzI6IElFQzJDbGllbnQsIHZwYzogVnBjLCBhcmdzOiBWcGNDb250ZXh0UXVlcnkpOiBQcm9taXNlPFZwY0NvbnRleHRSZXNwb25zZT4ge1xuICAgIGNvbnN0IHZwY0lkID0gdnBjLlZwY0lkITtcblxuICAgIGRlYnVnKGBEZXNjcmliaW5nIFZQQyAke3ZwY0lkfWApO1xuXG4gICAgY29uc3QgZmlsdGVycyA9IHsgRmlsdGVyczogW3sgTmFtZTogJ3ZwYy1pZCcsIFZhbHVlczogW3ZwY0lkXSB9XSB9O1xuXG4gICAgY29uc3Qgc3VibmV0c1Jlc3BvbnNlID0gYXdhaXQgZWMyLmRlc2NyaWJlU3VibmV0cyhmaWx0ZXJzKTtcbiAgICBjb25zdCBsaXN0ZWRTdWJuZXRzID0gc3VibmV0c1Jlc3BvbnNlLlN1Ym5ldHMgfHwgW107XG5cbiAgICBjb25zdCByb3V0ZVRhYmxlc1Jlc3BvbnNlID0gYXdhaXQgZWMyLmRlc2NyaWJlUm91dGVUYWJsZXMoZmlsdGVycyk7XG4gICAgY29uc3Qgcm91dGVUYWJsZXMgPSBuZXcgUm91dGVUYWJsZXMocm91dGVUYWJsZXNSZXNwb25zZS5Sb3V0ZVRhYmxlcyB8fCBbXSk7XG5cbiAgICAvLyBOb3cgY29tZXMgb3VyIGpvYiB0byBzZXBhcmF0ZSB0aGVzZSBzdWJuZXRzIG91dCBpbnRvIEFacyBhbmQgc3VibmV0IGdyb3VwcyAoUHVibGljLCBQcml2YXRlLCBJc29sYXRlZClcbiAgICAvLyBXZSBoYXZlIHRoZSBmb2xsb3dpbmcgYXR0cmlidXRlcyB0byBnbyBvbjpcbiAgICAvLyAtIFR5cGUgdGFnLCB3ZSB0YWcgc3VibmV0cyB3aXRoIHRoZWlyIHR5cGUuIEluIGFic2VuY2Ugb2YgdGhpcyB0YWcsIHdlXG4gICAgLy8gICBkZXRlcm1pbmUgdGhlIHN1Ym5ldCBtdXN0IGJlIFB1YmxpYyBpZiBlaXRoZXI6XG4gICAgLy8gICBhKSBpdCBoYXMgdGhlIHByb3BlcnR5IE1hcFB1YmxpY0lwT25MYXVuY2hcbiAgICAvLyAgIGIpIGl0IGhhcyBhIHJvdXRlIHRvIGFuIEludGVybmV0IEdhdGV3YXlcbiAgICAvLyAgIElmIGJvdGggb2YgdGhlIGFib3ZlIGlzIGZhbHNlIGJ1dCB0aGUgc3VibmV0IGhhcyBhIHJvdXRlIHRvIGEgTkFUIEdhdGV3YXlcbiAgICAvLyAgIGFuZCB0aGUgZGVzdGluYXRpb24gQ0lEUiBibG9jayBpcyBcIjAuMC4wLjAvMFwiLCB3ZSBhc3N1bWUgaXQgdG8gYmUgYSBQcml2YXRlIHN1Ym5ldC5cbiAgICAvLyAgIEFueXRoaW5nIGVsc2UgaXMgY29uc2lkZXJlZCBJc29sYXRlZC5cbiAgICAvLyAtIE5hbWUgdGFnLCB3ZSB0YWcgc3VibmV0cyB3aXRoIHRoZWlyIHN1Ym5ldCBncm91cCBuYW1lLiBJbiBhYnNlbmNlIG9mIHRoaXMgdGFnLFxuICAgIC8vICAgd2UgdXNlIHRoZSB0eXBlIGFzIHRoZSBuYW1lLlxuXG4gICAgY29uc3QgYXpzID0gQXJyYXkuZnJvbShuZXcgU2V0PHN0cmluZz4obGlzdGVkU3VibmV0cy5tYXAoKHMpID0+IHMuQXZhaWxhYmlsaXR5Wm9uZSEpKSk7XG4gICAgYXpzLnNvcnQoKTtcblxuICAgIGNvbnN0IHN1Ym5ldHM6IFN1Ym5ldFtdID0gbGlzdGVkU3VibmV0cy5tYXAoKHN1Ym5ldCkgPT4ge1xuICAgICAgbGV0IHR5cGUgPSBnZXRUYWcoJ2F3cy1jZGs6c3VibmV0LXR5cGUnLCBzdWJuZXQuVGFncyk7XG4gICAgICBpZiAodHlwZSA9PT0gdW5kZWZpbmVkICYmIHN1Ym5ldC5NYXBQdWJsaWNJcE9uTGF1bmNoKSB7XG4gICAgICAgIHR5cGUgPSBTdWJuZXRUeXBlLlB1YmxpYztcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlID09PSB1bmRlZmluZWQgJiYgcm91dGVUYWJsZXMuaGFzUm91dGVUb0lndyhzdWJuZXQuU3VibmV0SWQpKSB7XG4gICAgICAgIHR5cGUgPSBTdWJuZXRUeXBlLlB1YmxpYztcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlID09PSB1bmRlZmluZWQgJiYgcm91dGVUYWJsZXMuaGFzUm91dGVUb05hdEdhdGV3YXkoc3VibmV0LlN1Ym5ldElkKSkge1xuICAgICAgICB0eXBlID0gU3VibmV0VHlwZS5Qcml2YXRlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGUgPT09IHVuZGVmaW5lZCAmJiByb3V0ZVRhYmxlcy5oYXNSb3V0ZVRvVHJhbnNpdEdhdGV3YXkoc3VibmV0LlN1Ym5ldElkKSkge1xuICAgICAgICB0eXBlID0gU3VibmV0VHlwZS5Qcml2YXRlO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0eXBlID0gU3VibmV0VHlwZS5Jc29sYXRlZDtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpc1ZhbGlkU3VibmV0VHlwZSh0eXBlKSkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgICB0aHJvdyBuZXcgQ29udGV4dFByb3ZpZGVyRXJyb3IoXG4gICAgICAgICAgYFN1Ym5ldCAke3N1Ym5ldC5TdWJuZXRBcm59IGhhcyBpbnZhbGlkIHN1Ym5ldCB0eXBlICR7dHlwZX0gKG11c3QgYmUgJHtTdWJuZXRUeXBlLlB1YmxpY30sICR7U3VibmV0VHlwZS5Qcml2YXRlfSBvciAke1N1Ym5ldFR5cGUuSXNvbGF0ZWR9KWAsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChhcmdzLnN1Ym5ldEdyb3VwTmFtZVRhZyAmJiAhZ2V0VGFnKGFyZ3Muc3VibmV0R3JvdXBOYW1lVGFnLCBzdWJuZXQuVGFncykpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbnRleHRQcm92aWRlckVycm9yKFxuICAgICAgICAgIGBJbnZhbGlkIHN1Ym5ldEdyb3VwTmFtZVRhZzogU3VibmV0ICR7c3VibmV0LlN1Ym5ldEFybn0gZG9lcyBub3QgaGF2ZSBhbiBhc3NvY2lhdGVkIHRhZyB3aXRoIEtleT0nJHthcmdzLnN1Ym5ldEdyb3VwTmFtZVRhZ30nYCxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmFtZSA9IGdldFRhZyhhcmdzLnN1Ym5ldEdyb3VwTmFtZVRhZyB8fCAnYXdzLWNkazpzdWJuZXQtbmFtZScsIHN1Ym5ldC5UYWdzKSB8fCB0eXBlO1xuICAgICAgY29uc3Qgcm91dGVUYWJsZUlkID0gcm91dGVUYWJsZXMucm91dGVUYWJsZUlkRm9yU3VibmV0SWQoc3VibmV0LlN1Ym5ldElkKTtcblxuICAgICAgaWYgKCFyb3V0ZVRhYmxlSWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbnRleHRQcm92aWRlckVycm9yKFxuICAgICAgICAgIGBTdWJuZXQgJHtzdWJuZXQuU3VibmV0QXJufSBkb2VzIG5vdCBoYXZlIGFuIGFzc29jaWF0ZWQgcm91dGUgdGFibGUgKGFuZCB0aGVyZSBpcyBubyBcIm1haW5cIiB0YWJsZSlgLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBhejogc3VibmV0LkF2YWlsYWJpbGl0eVpvbmUhLFxuICAgICAgICBjaWRyOiBzdWJuZXQuQ2lkckJsb2NrISxcbiAgICAgICAgdHlwZSxcbiAgICAgICAgbmFtZSxcbiAgICAgICAgc3VibmV0SWQ6IHN1Ym5ldC5TdWJuZXRJZCEsXG4gICAgICAgIHJvdXRlVGFibGVJZCxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBsZXQgZ3JvdXBlZDogU3VibmV0R3JvdXBzO1xuICAgIGxldCBhc3N5bWV0cmljU3VibmV0R3JvdXBzOiBWcGNTdWJuZXRHcm91cFtdIHwgdW5kZWZpbmVkO1xuICAgIGlmIChhcmdzLnJldHVybkFzeW1tZXRyaWNTdWJuZXRzKSB7XG4gICAgICBncm91cGVkID0geyBhenM6IFtdLCBncm91cHM6IFtdIH07XG4gICAgICBhc3N5bWV0cmljU3VibmV0R3JvdXBzID0gZ3JvdXBBc3ltbWV0cmljU3VibmV0cyhzdWJuZXRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZ3JvdXBlZCA9IGdyb3VwU3VibmV0cyhzdWJuZXRzKTtcbiAgICAgIGFzc3ltZXRyaWNTdWJuZXRHcm91cHMgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gRmluZCBhdHRhY2hlZCthdmFpbGFibGUgVlBOIGdhdGV3YXkgZm9yIHRoaXMgVlBDXG4gICAgY29uc3QgdnBuR2F0ZXdheVJlc3BvbnNlID1cbiAgICAgIChhcmdzLnJldHVyblZwbkdhdGV3YXlzID8/IHRydWUpXG4gICAgICAgID8gYXdhaXQgZWMyLmRlc2NyaWJlVnBuR2F0ZXdheXMoe1xuICAgICAgICAgIEZpbHRlcnM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgTmFtZTogJ2F0dGFjaG1lbnQudnBjLWlkJyxcbiAgICAgICAgICAgICAgVmFsdWVzOiBbdnBjSWRdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgTmFtZTogJ2F0dGFjaG1lbnQuc3RhdGUnLFxuICAgICAgICAgICAgICBWYWx1ZXM6IFsnYXR0YWNoZWQnXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIE5hbWU6ICdzdGF0ZScsXG4gICAgICAgICAgICAgIFZhbHVlczogWydhdmFpbGFibGUnXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSlcbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgdnBuR2F0ZXdheUlkID1cbiAgICAgIHZwbkdhdGV3YXlSZXNwb25zZT8uVnBuR2F0ZXdheXM/Lmxlbmd0aCA9PT0gMSA/IHZwbkdhdGV3YXlSZXNwb25zZS5WcG5HYXRld2F5c1swXS5WcG5HYXRld2F5SWQgOiB1bmRlZmluZWQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdnBjSWQsXG4gICAgICB2cGNDaWRyQmxvY2s6IHZwYy5DaWRyQmxvY2shLFxuICAgICAgb3duZXJBY2NvdW50SWQ6IHZwYy5Pd25lcklkLFxuICAgICAgYXZhaWxhYmlsaXR5Wm9uZXM6IGdyb3VwZWQuYXpzLFxuICAgICAgaXNvbGF0ZWRTdWJuZXRJZHM6IGNvbGxhcHNlKFxuICAgICAgICBmbGF0TWFwKGZpbmRHcm91cHMoU3VibmV0VHlwZS5Jc29sYXRlZCwgZ3JvdXBlZCksIChncm91cCkgPT4gZ3JvdXAuc3VibmV0cy5tYXAoKHMpID0+IHMuc3VibmV0SWQpKSxcbiAgICAgICksXG4gICAgICBpc29sYXRlZFN1Ym5ldE5hbWVzOiBjb2xsYXBzZShcbiAgICAgICAgZmxhdE1hcChmaW5kR3JvdXBzKFN1Ym5ldFR5cGUuSXNvbGF0ZWQsIGdyb3VwZWQpLCAoZ3JvdXApID0+IChncm91cC5uYW1lID8gW2dyb3VwLm5hbWVdIDogW10pKSxcbiAgICAgICksXG4gICAgICBpc29sYXRlZFN1Ym5ldFJvdXRlVGFibGVJZHM6IGNvbGxhcHNlKFxuICAgICAgICBmbGF0TWFwKGZpbmRHcm91cHMoU3VibmV0VHlwZS5Jc29sYXRlZCwgZ3JvdXBlZCksIChncm91cCkgPT4gZ3JvdXAuc3VibmV0cy5tYXAoKHMpID0+IHMucm91dGVUYWJsZUlkKSksXG4gICAgICApLFxuICAgICAgcHJpdmF0ZVN1Ym5ldElkczogY29sbGFwc2UoXG4gICAgICAgIGZsYXRNYXAoZmluZEdyb3VwcyhTdWJuZXRUeXBlLlByaXZhdGUsIGdyb3VwZWQpLCAoZ3JvdXApID0+IGdyb3VwLnN1Ym5ldHMubWFwKChzKSA9PiBzLnN1Ym5ldElkKSksXG4gICAgICApLFxuICAgICAgcHJpdmF0ZVN1Ym5ldE5hbWVzOiBjb2xsYXBzZShcbiAgICAgICAgZmxhdE1hcChmaW5kR3JvdXBzKFN1Ym5ldFR5cGUuUHJpdmF0ZSwgZ3JvdXBlZCksIChncm91cCkgPT4gKGdyb3VwLm5hbWUgPyBbZ3JvdXAubmFtZV0gOiBbXSkpLFxuICAgICAgKSxcbiAgICAgIHByaXZhdGVTdWJuZXRSb3V0ZVRhYmxlSWRzOiBjb2xsYXBzZShcbiAgICAgICAgZmxhdE1hcChmaW5kR3JvdXBzKFN1Ym5ldFR5cGUuUHJpdmF0ZSwgZ3JvdXBlZCksIChncm91cCkgPT4gZ3JvdXAuc3VibmV0cy5tYXAoKHMpID0+IHMucm91dGVUYWJsZUlkKSksXG4gICAgICApLFxuICAgICAgcHVibGljU3VibmV0SWRzOiBjb2xsYXBzZShcbiAgICAgICAgZmxhdE1hcChmaW5kR3JvdXBzKFN1Ym5ldFR5cGUuUHVibGljLCBncm91cGVkKSwgKGdyb3VwKSA9PiBncm91cC5zdWJuZXRzLm1hcCgocykgPT4gcy5zdWJuZXRJZCkpLFxuICAgICAgKSxcbiAgICAgIHB1YmxpY1N1Ym5ldE5hbWVzOiBjb2xsYXBzZShcbiAgICAgICAgZmxhdE1hcChmaW5kR3JvdXBzKFN1Ym5ldFR5cGUuUHVibGljLCBncm91cGVkKSwgKGdyb3VwKSA9PiAoZ3JvdXAubmFtZSA/IFtncm91cC5uYW1lXSA6IFtdKSksXG4gICAgICApLFxuICAgICAgcHVibGljU3VibmV0Um91dGVUYWJsZUlkczogY29sbGFwc2UoXG4gICAgICAgIGZsYXRNYXAoZmluZEdyb3VwcyhTdWJuZXRUeXBlLlB1YmxpYywgZ3JvdXBlZCksIChncm91cCkgPT4gZ3JvdXAuc3VibmV0cy5tYXAoKHMpID0+IHMucm91dGVUYWJsZUlkKSksXG4gICAgICApLFxuICAgICAgdnBuR2F0ZXdheUlkLFxuICAgICAgc3VibmV0R3JvdXBzOiBhc3N5bWV0cmljU3VibmV0R3JvdXBzLFxuICAgIH07XG4gIH1cbn1cblxuY2xhc3MgUm91dGVUYWJsZXMge1xuICBwdWJsaWMgcmVhZG9ubHkgbWFpblJvdXRlVGFibGU/OiBSb3V0ZVRhYmxlO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgdGFibGVzOiBSb3V0ZVRhYmxlW10pIHtcbiAgICB0aGlzLm1haW5Sb3V0ZVRhYmxlID0gdGhpcy50YWJsZXMuZmluZChcbiAgICAgICh0YWJsZSkgPT4gISF0YWJsZS5Bc3NvY2lhdGlvbnMgJiYgdGFibGUuQXNzb2NpYXRpb25zLnNvbWUoKGFzc29jKSA9PiAhIWFzc29jLk1haW4pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgcm91dGVUYWJsZUlkRm9yU3VibmV0SWQoc3VibmV0SWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgdGFibGUgPSB0aGlzLnRhYmxlRm9yU3VibmV0KHN1Ym5ldElkKTtcbiAgICByZXR1cm4gKHRhYmxlICYmIHRhYmxlLlJvdXRlVGFibGVJZCkgfHwgKHRoaXMubWFpblJvdXRlVGFibGUgJiYgdGhpcy5tYWluUm91dGVUYWJsZS5Sb3V0ZVRhYmxlSWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGdpdmVuIHN1Ym5ldCBoYXMgYSByb3V0ZSB0byBhIE5BVCBHYXRld2F5XG4gICAqL1xuICBwdWJsaWMgaGFzUm91dGVUb05hdEdhdGV3YXkoc3VibmV0SWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZUZvclN1Ym5ldChzdWJuZXRJZCkgfHwgdGhpcy5tYWluUm91dGVUYWJsZTtcblxuICAgIHJldHVybiAoXG4gICAgICAhIXRhYmxlICYmXG4gICAgICAhIXRhYmxlLlJvdXRlcyAmJlxuICAgICAgdGFibGUuUm91dGVzLnNvbWUoKHJvdXRlKSA9PiAhIXJvdXRlLk5hdEdhdGV3YXlJZCAmJiByb3V0ZS5EZXN0aW5hdGlvbkNpZHJCbG9jayA9PT0gJzAuMC4wLjAvMCcpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBnaXZlbiBzdWJuZXQgaGFzIGEgcm91dGUgdG8gYSBUcmFuc2l0IEdhdGV3YXlcbiAgICovXG4gIHB1YmxpYyBoYXNSb3V0ZVRvVHJhbnNpdEdhdGV3YXkoc3VibmV0SWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZUZvclN1Ym5ldChzdWJuZXRJZCkgfHwgdGhpcy5tYWluUm91dGVUYWJsZTtcblxuICAgIHJldHVybiAoXG4gICAgICAhIXRhYmxlICYmXG4gICAgICAhIXRhYmxlLlJvdXRlcyAmJlxuICAgICAgdGFibGUuUm91dGVzLnNvbWUoKHJvdXRlKSA9PiAhIXJvdXRlLlRyYW5zaXRHYXRld2F5SWQgJiYgcm91dGUuRGVzdGluYXRpb25DaWRyQmxvY2sgPT09ICcwLjAuMC4wLzAnKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGUgZ2l2ZW4gc3VibmV0IGhhcyBhIHJvdXRlIHRvIGFuIElHV1xuICAgKi9cbiAgcHVibGljIGhhc1JvdXRlVG9JZ3coc3VibmV0SWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy50YWJsZUZvclN1Ym5ldChzdWJuZXRJZCkgfHwgdGhpcy5tYWluUm91dGVUYWJsZTtcblxuICAgIHJldHVybiAoXG4gICAgICAhIXRhYmxlICYmICEhdGFibGUuUm91dGVzICYmIHRhYmxlLlJvdXRlcy5zb21lKChyb3V0ZSkgPT4gISFyb3V0ZS5HYXRld2F5SWQgJiYgcm91dGUuR2F0ZXdheUlkLnN0YXJ0c1dpdGgoJ2lndy0nKSlcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHRhYmxlRm9yU3VibmV0KHN1Ym5ldElkOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdGhpcy50YWJsZXMuZmluZChcbiAgICAgICh0YWJsZSkgPT4gISF0YWJsZS5Bc3NvY2lhdGlvbnMgJiYgdGFibGUuQXNzb2NpYXRpb25zLnNvbWUoKGFzc29jKSA9PiBhc3NvYy5TdWJuZXRJZCA9PT0gc3VibmV0SWQpLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXR1cm4gdGhlIHZhbHVlIG9mIGEgdGFnIGZyb20gYSBzZXQgb2YgdGFnc1xuICovXG5mdW5jdGlvbiBnZXRUYWcobmFtZTogc3RyaW5nLCB0YWdzPzogVGFnW10pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IHRhZyBvZiB0YWdzIHx8IFtdKSB7XG4gICAgaWYgKHRhZy5LZXkgPT09IG5hbWUpIHtcbiAgICAgIHJldHVybiB0YWcuVmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogR3JvdXAgc3VibmV0cyBvZiB0aGUgc2FtZSB0eXBlIHRvZ2V0aGVyLCBhbmQgb3JkZXIgYnkgQVpcbiAqL1xuZnVuY3Rpb24gZ3JvdXBTdWJuZXRzKHN1Ym5ldHM6IFN1Ym5ldFtdKTogU3VibmV0R3JvdXBzIHtcbiAgY29uc3QgZ3JvdXBpbmc6IHsgW2tleTogc3RyaW5nXTogU3VibmV0W10gfSA9IHt9O1xuICBmb3IgKGNvbnN0IHN1Ym5ldCBvZiBzdWJuZXRzKSB7XG4gICAgY29uc3Qga2V5ID0gW3N1Ym5ldC50eXBlLCBzdWJuZXQubmFtZV0udG9TdHJpbmcoKTtcbiAgICBpZiAoIShrZXkgaW4gZ3JvdXBpbmcpKSB7XG4gICAgICBncm91cGluZ1trZXldID0gW107XG4gICAgfVxuICAgIGdyb3VwaW5nW2tleV0ucHVzaChzdWJuZXQpO1xuICB9XG5cbiAgY29uc3QgZ3JvdXBzID0gT2JqZWN0LnZhbHVlcyhncm91cGluZykubWFwKChzbnMpID0+IHtcbiAgICBzbnMuc29ydCgoYTogU3VibmV0LCBiOiBTdWJuZXQpID0+IGEuYXoubG9jYWxlQ29tcGFyZShiLmF6KSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IHNuc1swXS50eXBlLFxuICAgICAgbmFtZTogc25zWzBdLm5hbWUsXG4gICAgICBzdWJuZXRzOiBzbnMsXG4gICAgfTtcbiAgfSk7XG5cbiAgY29uc3QgYXpzID0gZ3JvdXBzWzBdLnN1Ym5ldHMubWFwKChzKSA9PiBzLmF6KTtcblxuICBmb3IgKGNvbnN0IGdyb3VwIG9mIGdyb3Vwcykge1xuICAgIGNvbnN0IGdyb3VwQVpzID0gZ3JvdXAuc3VibmV0cy5tYXAoKHMpID0+IHMuYXopO1xuICAgIGlmICghYXJyYXlzRXF1YWwoZ3JvdXBBWnMsIGF6cykpIHtcbiAgICAgIHRocm93IG5ldyBDb250ZXh0UHJvdmlkZXJFcnJvcihgTm90IGFsbCBzdWJuZXRzIGluIFZQQyBoYXZlIHRoZSBzYW1lIEFaczogJHtncm91cEFac30gdnMgJHthenN9YCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgYXpzLCBncm91cHMgfTtcbn1cblxuZnVuY3Rpb24gZ3JvdXBBc3ltbWV0cmljU3VibmV0cyhzdWJuZXRzOiBTdWJuZXRbXSk6IFZwY1N1Ym5ldEdyb3VwW10ge1xuICBjb25zdCBncm91cGluZzogeyBba2V5OiBzdHJpbmddOiBTdWJuZXRbXSB9ID0ge307XG4gIGZvciAoY29uc3Qgc3VibmV0IG9mIHN1Ym5ldHMpIHtcbiAgICBjb25zdCBrZXkgPSBbc3VibmV0LnR5cGUsIHN1Ym5ldC5uYW1lXS50b1N0cmluZygpO1xuICAgIGlmICghKGtleSBpbiBncm91cGluZykpIHtcbiAgICAgIGdyb3VwaW5nW2tleV0gPSBbXTtcbiAgICB9XG4gICAgZ3JvdXBpbmdba2V5XS5wdXNoKHN1Ym5ldCk7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhncm91cGluZykubWFwKChzdWJuZXRBcnJheSkgPT4ge1xuICAgIHN1Ym5ldEFycmF5LnNvcnQoKHN1Ym5ldDE6IFN1Ym5ldCwgc3VibmV0MjogU3VibmV0KSA9PiBzdWJuZXQxLmF6LmxvY2FsZUNvbXBhcmUoc3VibmV0Mi5heikpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IHN1Ym5ldEFycmF5WzBdLm5hbWUsXG4gICAgICB0eXBlOiBzdWJuZXRUeXBlVG9WcGNTdWJuZXRUeXBlKHN1Ym5ldEFycmF5WzBdLnR5cGUpLFxuICAgICAgc3VibmV0czogc3VibmV0QXJyYXkubWFwKChzdWJuZXQpID0+ICh7XG4gICAgICAgIHN1Ym5ldElkOiBzdWJuZXQuc3VibmV0SWQsXG4gICAgICAgIGNpZHI6IHN1Ym5ldC5jaWRyLFxuICAgICAgICBhdmFpbGFiaWxpdHlab25lOiBzdWJuZXQuYXosXG4gICAgICAgIHJvdXRlVGFibGVJZDogc3VibmV0LnJvdXRlVGFibGVJZCxcbiAgICAgIH0pKSxcbiAgICB9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gc3VibmV0VHlwZVRvVnBjU3VibmV0VHlwZSh0eXBlOiBTdWJuZXRUeXBlKTogVnBjU3VibmV0R3JvdXBUeXBlIHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSBTdWJuZXRUeXBlLklzb2xhdGVkOlxuICAgICAgcmV0dXJuIFZwY1N1Ym5ldEdyb3VwVHlwZS5JU09MQVRFRDtcbiAgICBjYXNlIFN1Ym5ldFR5cGUuUHJpdmF0ZTpcbiAgICAgIHJldHVybiBWcGNTdWJuZXRHcm91cFR5cGUuUFJJVkFURTtcbiAgICBjYXNlIFN1Ym5ldFR5cGUuUHVibGljOlxuICAgICAgcmV0dXJuIFZwY1N1Ym5ldEdyb3VwVHlwZS5QVUJMSUM7XG4gIH1cbn1cblxuZW51bSBTdWJuZXRUeXBlIHtcbiAgUHVibGljID0gJ1B1YmxpYycsXG4gIFByaXZhdGUgPSAnUHJpdmF0ZScsXG4gIElzb2xhdGVkID0gJ0lzb2xhdGVkJyxcbn1cblxuZnVuY3Rpb24gaXNWYWxpZFN1Ym5ldFR5cGUodmFsOiBzdHJpbmcpOiB2YWwgaXMgU3VibmV0VHlwZSB7XG4gIHJldHVybiB2YWwgPT09IFN1Ym5ldFR5cGUuUHVibGljIHx8IHZhbCA9PT0gU3VibmV0VHlwZS5Qcml2YXRlIHx8IHZhbCA9PT0gU3VibmV0VHlwZS5Jc29sYXRlZDtcbn1cblxuaW50ZXJmYWNlIFN1Ym5ldCB7XG4gIGF6OiBzdHJpbmc7XG4gIGNpZHI6IHN0cmluZztcbiAgdHlwZTogU3VibmV0VHlwZTtcbiAgbmFtZTogc3RyaW5nO1xuICByb3V0ZVRhYmxlSWQ6IHN0cmluZztcbiAgc3VibmV0SWQ6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFN1Ym5ldEdyb3VwIHtcbiAgdHlwZTogU3VibmV0VHlwZTtcbiAgbmFtZTogc3RyaW5nO1xuICBzdWJuZXRzOiBTdWJuZXRbXTtcbn1cblxuaW50ZXJmYWNlIFN1Ym5ldEdyb3VwcyB7XG4gIGF6czogc3RyaW5nW107XG4gIGdyb3VwczogU3VibmV0R3JvdXBbXTtcbn1cblxuZnVuY3Rpb24gYXJyYXlzRXF1YWwoYXM6IHN0cmluZ1tdLCBiczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgaWYgKGFzLmxlbmd0aCAhPT0gYnMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChhc1tpXSAhPT0gYnNbaV0pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gZmluZEdyb3Vwcyh0eXBlOiBTdWJuZXRUeXBlLCBncm91cHM6IFN1Ym5ldEdyb3Vwcyk6IFN1Ym5ldEdyb3VwW10ge1xuICByZXR1cm4gZ3JvdXBzLmdyb3Vwcy5maWx0ZXIoKGcpID0+IGcudHlwZSA9PT0gdHlwZSk7XG59XG5cbmZ1bmN0aW9uIGZsYXRNYXA8VCwgVT4oeHM6IFRbXSwgZm46ICh4OiBUKSA9PiBVW10pOiBVW10ge1xuICBjb25zdCByZXQgPSBuZXcgQXJyYXk8VT4oKTtcbiAgZm9yIChjb25zdCB4IG9mIHhzKSB7XG4gICAgcmV0LnB1c2goLi4uZm4oeCkpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIGNvbGxhcHNlPFQ+KHhzOiBUW10pOiBUW10gfCB1bmRlZmluZWQge1xuICBpZiAoeHMubGVuZ3RoID4gMCkge1xuICAgIHJldHVybiB4cztcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuIl19