UNPKG

cdk-monitoring-constructs

Version:

[![NPM version](https://badge.fury.io/js/cdk-monitoring-constructs.svg)](https://badge.fury.io/js/cdk-monitoring-constructs) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.cdklabs/cdkmonitoringconstructs/badge.svg)](https://m

448 lines 59.2 kB
"use strict"; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.MonitoringAspect = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const apigw = require("aws-cdk-lib/aws-apigateway"); const apigwv2 = require("aws-cdk-lib/aws-apigatewayv2"); const appsync = require("aws-cdk-lib/aws-appsync"); const autoscaling = require("aws-cdk-lib/aws-autoscaling"); const acm = require("aws-cdk-lib/aws-certificatemanager"); const cloudfront = require("aws-cdk-lib/aws-cloudfront"); const codebuild = require("aws-cdk-lib/aws-codebuild"); const docdb = require("aws-cdk-lib/aws-docdb"); const dynamodb = require("aws-cdk-lib/aws-dynamodb"); const ecs = require("aws-cdk-lib/aws-ecs"); const ecsPatterns = require("aws-cdk-lib/aws-ecs-patterns"); const elasticsearch = require("aws-cdk-lib/aws-elasticsearch"); const glue = require("aws-cdk-lib/aws-glue"); const kinesis = require("aws-cdk-lib/aws-kinesis"); const kinesisanalytics = require("aws-cdk-lib/aws-kinesisanalytics"); const kinesisfirehose = require("aws-cdk-lib/aws-kinesisfirehose"); const lambda = require("aws-cdk-lib/aws-lambda"); const opensearch = require("aws-cdk-lib/aws-opensearchservice"); const rds = require("aws-cdk-lib/aws-rds"); const redshift = require("aws-cdk-lib/aws-redshift"); const s3 = require("aws-cdk-lib/aws-s3"); const secretsmanager = require("aws-cdk-lib/aws-secretsmanager"); const sns = require("aws-cdk-lib/aws-sns"); const sqs = require("aws-cdk-lib/aws-sqs"); const stepfunctions = require("aws-cdk-lib/aws-stepfunctions"); const synthetics = require("aws-cdk-lib/aws-synthetics"); const wafv2 = require("aws-cdk-lib/aws-wafv2"); const monitoring_1 = require("../monitoring"); /** * A CDK aspect that adds support for monitoring all resources within scope. */ class MonitoringAspect { constructor(monitoringFacade, props = {}) { this.monitoringFacade = monitoringFacade; this.props = props; /** * Whether or not we've added a monitoring to the scope for node independent monitorings. */ this.addedNodeIndependentMonitoringToScope = false; } visit(node) { this.monitorAcm(node); this.monitorApiGateway(node); this.monitorApiGatewayV2(node); this.monitorAppSync(node); this.monitorAuroraCluster(node); this.monitorAutoScalingGroup(node); this.monitorCloudFront(node); this.monitorCodeBuild(node); this.monitorDocumentDb(node); this.monitorDynamoDb(node); this.monitorFargateService(node); this.monitorFargateLoadBalancedService(node); this.monitorQueueProcessingFargateService(node); this.monitorGlue(node); this.monitorKinesisAnalytics(node); this.monitorKinesisDataStream(node); this.monitorKinesisDataStreamConsumer(node); this.monitorKinesisFirehose(node); this.monitorLambda(node); this.monitorOpenSearch(node); this.monitorRdsCluster(node); this.monitorRdsInstance(node); this.monitorRedshift(node); this.monitorS3(node); this.monitorSecretsManager(node); this.monitorSns(node); this.monitorSqs(node); this.monitorStepFunctions(node); this.monitorSyntheticsCanaries(node); this.monitorWebApplicationFirewallV2Acls(node); if (!this.addedNodeIndependentMonitoringToScope) { this.addedNodeIndependentMonitoringToScope = true; this.monitorEc2(); this.monitorBilling(); this.monitorElasticCache(); } } getMonitoringDetails(aspectOptions) { const isEnabled = aspectOptions?.enabled ?? true; const props = aspectOptions?.props; return [isEnabled, props]; } monitorAcm(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.acm); if (isEnabled && node instanceof acm.Certificate) { this.monitoringFacade.monitorCertificate({ certificate: node, alarmFriendlyName: node.node.path, ...props, }); } } monitorApiGateway(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.apiGateway); if (isEnabled && node instanceof apigw.RestApi) { this.monitoringFacade.monitorApiGateway({ api: node, apiStage: node.deploymentStage.stageName, ...props, }); } } monitorApiGatewayV2(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.apiGatewayV2); if (isEnabled && node instanceof apigwv2.HttpApi) { this.monitoringFacade.monitorApiGatewayV2HttpApi({ api: node, ...props, }); } } monitorAppSync(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.appSync); if (isEnabled && node instanceof appsync.GraphqlApi) { this.monitoringFacade.monitorAppSyncApi({ api: node, alarmFriendlyName: node.node.path, ...props, }); } } monitorAuroraCluster(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.auroraCluster); if (isEnabled && node instanceof rds.ServerlessCluster) { this.monitoringFacade.monitorAuroraCluster({ cluster: node, alarmFriendlyName: node.node.path, ...props, }); } } monitorAutoScalingGroup(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.autoScalingGroup); if (isEnabled && node instanceof autoscaling.AutoScalingGroup) { this.monitoringFacade.monitorAutoScalingGroup({ autoScalingGroup: node, ...props, }); } } monitorBilling() { const [isEnabled, props] = this.getMonitoringDetails(this.props.billing); if (isEnabled) { this.monitoringFacade.monitorBilling({ ...props, alarmFriendlyName: "Billing", }); } } monitorCloudFront(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.cloudFront); if (isEnabled && node instanceof cloudfront.Distribution) { this.monitoringFacade.monitorCloudFrontDistribution({ distribution: node, ...props, }); } } monitorCodeBuild(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.codeBuild); if (isEnabled && node instanceof codebuild.Project) { this.monitoringFacade.monitorCodeBuildProject({ project: node, ...props, }); } } monitorDocumentDb(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.documentDb); if (isEnabled && node instanceof docdb.DatabaseCluster) { this.monitoringFacade.monitorDocumentDbCluster({ cluster: node, alarmFriendlyName: node.node.path, ...props, }); } } monitorDynamoDb(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.dynamoDB); if (isEnabled && node instanceof dynamodb.Table) { this.monitoringFacade.monitorDynamoTable({ table: node, ...props, }); } } monitorEc2() { const [isEnabled, props] = this.getMonitoringDetails(this.props.ec2); if (isEnabled) { this.monitoringFacade.monitorEC2Instances({ ...props, }); } } monitorElasticCache() { const [isEnabled, props] = this.getMonitoringDetails(this.props.elasticCache); if (isEnabled) { this.monitoringFacade.monitorElastiCacheCluster({ clusterType: monitoring_1.ElastiCacheClusterType.MEMCACHED, ...props, }); this.monitoringFacade.monitorElastiCacheCluster({ clusterType: monitoring_1.ElastiCacheClusterType.REDIS, ...props, }); } } monitorFargateService(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.fargateService); if (isEnabled && node instanceof ecs.FargateService && !this.isInsideFargatePattern(node)) { this.monitoringFacade.monitorSimpleFargateService({ fargateService: node, ...props, }); } } monitorFargateLoadBalancedService(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.fargateLoadBalancedService); if (isEnabled && (node instanceof ecsPatterns.ApplicationLoadBalancedFargateService || node instanceof ecsPatterns.NetworkLoadBalancedFargateService)) { this.monitoringFacade.monitorFargateService({ fargateService: node, ...props, }); } } monitorQueueProcessingFargateService(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.queueProcessingFargateService); if (isEnabled && node instanceof ecsPatterns.QueueProcessingFargateService) { this.monitoringFacade.monitorQueueProcessingFargateService({ fargateService: node, ...props, }); } } /** * Returns true if the FargateService is owned by an L3 ecs-patterns * construct (ApplicationLoadBalancedFargateService, * NetworkLoadBalancedFargateService, QueueProcessingFargateService). * The L3 pattern has its own aspect hook, so monitoring the inner * service separately would duplicate alarms. */ isInsideFargatePattern(service) { const MAX_ANCESTOR_DEPTH = 3; let current = service.node.scope; for (let i = 0; i < MAX_ANCESTOR_DEPTH && current; i++) { if (current instanceof ecsPatterns.ApplicationLoadBalancedFargateService || current instanceof ecsPatterns.NetworkLoadBalancedFargateService || current instanceof ecsPatterns.QueueProcessingFargateService) { return true; } current = current.node.scope; } return false; } monitorGlue(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.glue); if (isEnabled && node instanceof glue.CfnJob) { this.monitoringFacade.monitorGlueJob({ jobName: node.name, ...props, }); } } monitorKinesisAnalytics(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisDataAnalytics); if (isEnabled && node instanceof kinesisanalytics.CfnApplication) { this.monitoringFacade.monitorKinesisDataAnalytics({ application: node.applicationName, alarmFriendlyName: node.node.path, ...props, }); } } monitorKinesisDataStream(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisDataStream); if (isEnabled && node instanceof kinesis.CfnStream) { this.monitoringFacade.monitorKinesisDataStream({ streamName: node.name, alarmFriendlyName: node.node.path, ...props, }); } } monitorKinesisDataStreamConsumer(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisDataStreamConsumer); if (isEnabled && node instanceof kinesis.CfnStreamConsumer) { const streamName = aws_cdk_lib_1.Arn.split(node.streamArn, aws_cdk_lib_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName; this.monitoringFacade.monitorKinesisDataStreamConsumer({ streamName, consumerName: node.consumerName, alarmFriendlyName: node.node.path, ...props, }); } } monitorKinesisFirehose(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisFirehose); if (isEnabled && node instanceof kinesisfirehose.CfnDeliveryStream) { this.monitoringFacade.monitorKinesisFirehose({ deliveryStreamName: node.deliveryStreamName, alarmFriendlyName: node.node.path, ...props, }); } } monitorLambda(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.lambda); if (isEnabled && node instanceof lambda.Function) { this.monitoringFacade.monitorLambdaFunction({ lambdaFunction: node, ...props, }); } } monitorOpenSearch(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.openSearch); if (isEnabled && (node instanceof elasticsearch.Domain || node instanceof elasticsearch.CfnDomain || node instanceof opensearch.Domain || node instanceof opensearch.CfnDomain)) { this.monitoringFacade.monitorOpenSearchCluster({ domain: node, ...props, }); } } monitorRdsCluster(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.rdsCluster ?? this.props.rds); if (isEnabled && node instanceof rds.DatabaseCluster) { this.monitoringFacade.monitorRdsCluster({ cluster: node, alarmFriendlyName: node.node.path, ...props, }); } } monitorRdsInstance(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.rdsInstance); if (isEnabled && node instanceof rds.DatabaseInstance) { this.monitoringFacade.monitorRdsInstance({ instance: node, alarmFriendlyName: node.node.path, ...props, }); } } monitorRedshift(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.redshift); if (isEnabled && this.isProbablyL2RedshiftCluster(node)) { const cfnCluster = node.cluster; this.monitoringFacade.monitorRedshiftCluster({ clusterIdentifier: cfnCluster.ref, alarmFriendlyName: cfnCluster.node.path, ...props, }); } } isProbablyL2RedshiftCluster(node) { return (node.cluster instanceof redshift.CfnCluster && !!node.clusterName && !!node.node?.path); } monitorS3(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.s3); if (isEnabled && node instanceof s3.Bucket) { this.monitoringFacade.monitorS3Bucket({ bucket: node, ...props, }); } } monitorSecretsManager(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.secretsManager); if (isEnabled && node instanceof secretsmanager.Secret) { this.monitoringFacade.monitorSecretsManagerSecret({ secret: node, ...props, }); } } monitorSns(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.sns); if (isEnabled && node instanceof sns.Topic) { this.monitoringFacade.monitorSnsTopic({ topic: node, ...props, }); } } monitorSqs(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.sqs); if (isEnabled && node instanceof sqs.Queue) { this.monitoringFacade.monitorSqsQueue({ queue: node, ...props, }); } } monitorStepFunctions(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.stepFunctions); if (isEnabled && node instanceof stepfunctions.StateMachine) { this.monitoringFacade.monitorStepFunction({ stateMachine: node, ...props, }); } } monitorSyntheticsCanaries(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.syntheticsCanaries); if (isEnabled && node instanceof synthetics.Canary) { this.monitoringFacade.monitorSyntheticsCanary({ canary: node, ...props, }); } } monitorWebApplicationFirewallV2Acls(node) { const [isEnabled, props] = this.getMonitoringDetails(this.props.webApplicationFirewallAclV2); if (isEnabled && node instanceof wafv2.CfnWebACL) { const regionProps = {}; if (node.scope === "REGIONAL") { regionProps.region = aws_cdk_lib_1.Stack.of(node).region; } this.monitoringFacade.monitorWebApplicationFirewallAclV2({ acl: node, ...regionProps, ...props, }); } } } exports.MonitoringAspect = MonitoringAspect; _a = JSII_RTTI_SYMBOL_1; MonitoringAspect[_a] = { fqn: "cdk-monitoring-constructs.MonitoringAspect", version: "10.0.0" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTW9uaXRvcmluZ0FzcGVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIk1vbml0b3JpbmdBc3BlY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBNkQ7QUFDN0Qsb0RBQW9EO0FBQ3BELHdEQUF3RDtBQUN4RCxtREFBbUQ7QUFDbkQsMkRBQTJEO0FBQzNELDBEQUEwRDtBQUMxRCx5REFBeUQ7QUFDekQsdURBQXVEO0FBQ3ZELCtDQUErQztBQUMvQyxxREFBcUQ7QUFDckQsMkNBQTJDO0FBQzNDLDREQUE0RDtBQUM1RCwrREFBK0Q7QUFDL0QsNkNBQTZDO0FBQzdDLG1EQUFtRDtBQUNuRCxxRUFBcUU7QUFDckUsbUVBQW1FO0FBQ25FLGlEQUFpRDtBQUNqRCxnRUFBZ0U7QUFDaEUsMkNBQTJDO0FBQzNDLHFEQUFxRDtBQUNyRCx5Q0FBeUM7QUFDekMsaUVBQWlFO0FBQ2pFLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsK0RBQStEO0FBQy9ELHlEQUF5RDtBQUN6RCwrQ0FBK0M7QUFRL0MsOENBQXVEO0FBRXZEOztHQUVHO0FBQ0gsTUFBYSxnQkFBZ0I7SUFNM0IsWUFDbUIsZ0JBQWtDLEVBQ2xDLFFBQStCLEVBQUU7UUFEakMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxVQUFLLEdBQUwsS0FBSyxDQUE0QjtRQVBwRDs7V0FFRztRQUNLLDBDQUFxQyxHQUFHLEtBQUssQ0FBQztJQUtuRCxDQUFDO0lBRUcsS0FBSyxDQUFDLElBQWdCO1FBQzNCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FB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QUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDN0MsQ0FBQztZQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxrQ0FBa0MsQ0FBQztnQkFDdkQsR0FBRyxFQUFFLElBQUk7Z0JBQ1QsR0FBRyxXQUFXO2dCQUNkLEdBQUcsS0FBSzthQUNULENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDOztBQWpmSCw0Q0FrZkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJQXNwZWN0LCBTdGFjaywgQXJuLCBBcm5Gb3JtYXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCAqIGFzIGFwaWd3IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXBpZ2F0ZXdheVwiO1xuaW1wb3J0ICogYXMgYXBpZ3d2MiBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXl2MlwiO1xuaW1wb3J0ICogYXMgYXBwc3luYyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwcHN5bmNcIjtcbmltcG9ydCAqIGFzIGF1dG9zY2FsaW5nIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXV0b3NjYWxpbmdcIjtcbmltcG9ydCAqIGFzIGFjbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlclwiO1xuaW1wb3J0ICogYXMgY2xvdWRmcm9udCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnRcIjtcbmltcG9ydCAqIGFzIGNvZGVidWlsZCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNvZGVidWlsZFwiO1xuaW1wb3J0ICogYXMgZG9jZGIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1kb2NkYlwiO1xuaW1wb3J0ICogYXMgZHluYW1vZGIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1keW5hbW9kYlwiO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWNzXCI7XG5pbXBvcnQgKiBhcyBlY3NQYXR0ZXJucyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjcy1wYXR0ZXJuc1wiO1xuaW1wb3J0ICogYXMgZWxhc3RpY3NlYXJjaCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVsYXN0aWNzZWFyY2hcIjtcbmltcG9ydCAqIGFzIGdsdWUgZnJvbSBcImF3cy1jZGstbGliL2F3cy1nbHVlXCI7XG5pbXBvcnQgKiBhcyBraW5lc2lzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mta2luZXNpc1wiO1xuaW1wb3J0ICogYXMga2luZXNpc2FuYWx5dGljcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWtpbmVzaXNhbmFseXRpY3NcIjtcbmltcG9ydCAqIGFzIGtpbmVzaXNmaXJlaG9zZSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWtpbmVzaXNmaXJlaG9zZVwiO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgKiBhcyBvcGVuc2VhcmNoIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtb3BlbnNlYXJjaHNlcnZpY2VcIjtcbmltcG9ydCAqIGFzIHJkcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXJkc1wiO1xuaW1wb3J0ICogYXMgcmVkc2hpZnQgZnJvbSBcImF3cy1jZGstbGliL2F3cy1yZWRzaGlmdFwiO1xuaW1wb3J0ICogYXMgczMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0ICogYXMgc2VjcmV0c21hbmFnZXIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zZWNyZXRzbWFuYWdlclwiO1xuaW1wb3J0ICogYXMgc25zIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc25zXCI7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zcXNcIjtcbmltcG9ydCAqIGFzIHN0ZXBmdW5jdGlvbnMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zdGVwZnVuY3Rpb25zXCI7XG5pbXBvcnQgKiBhcyBzeW50aGV0aWNzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc3ludGhldGljc1wiO1xuaW1wb3J0ICogYXMgd2FmdjIgZnJvbSBcImF3cy1jZGstbGliL2F3cy13YWZ2MlwiO1xuaW1wb3J0IHsgSUNvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5cbmltcG9ydCB7XG4gIE1vbml0b3JpbmdBc3BlY3RQcm9wcyxcbiAgQmFzZU1vbml0b3JpbmdBc3BlY3RUeXBlLFxufSBmcm9tIFwiLi9JTW9uaXRvcmluZ0FzcGVjdFwiO1xuaW1wb3J0IHsgTW9uaXRvcmluZ0ZhY2FkZSB9IGZyb20gXCIuL01vbml0b3JpbmdGYWNhZGVcIjtcbmltcG9ydCB7IEVsYXN0aUNhY2hlQ2x1c3RlclR5cGUgfSBmcm9tIFwiLi4vbW9uaXRvcmluZ1wiO1xuXG4vKipcbiAqIEEgQ0RLIGFzcGVjdCB0aGF0IGFkZHMgc3VwcG9ydCBmb3IgbW9uaXRvcmluZyBhbGwgcmVzb3VyY2VzIHdpdGhpbiBzY29wZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE1vbml0b3JpbmdBc3BlY3QgaW1wbGVtZW50cyBJQXNwZWN0IHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHdlJ3ZlIGFkZGVkIGEgbW9uaXRvcmluZyB0byB0aGUgc2NvcGUgZm9yIG5vZGUgaW5kZXBlbmRlbnQgbW9uaXRvcmluZ3MuXG4gICAqL1xuICBwcml2YXRlIGFkZGVkTm9kZUluZGVwZW5kZW50TW9uaXRvcmluZ1RvU2NvcGUgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1vbml0b3JpbmdGYWNhZGU6IE1vbml0b3JpbmdGYWNhZGUsXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9wczogTW9uaXRvcmluZ0FzcGVjdFByb3BzID0ge30sXG4gICkge31cblxuICBwdWJsaWMgdmlzaXQobm9kZTogSUNvbnN0cnVjdCk6IHZvaWQge1xuICAgIHRoaXMubW9uaXRvckFjbShub2RlKTtcbiAgICB0aGlzLm1vbml0b3JBcGlHYXRld2F5KG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckFwaUdhdGV3YXlWMihub2RlKTtcbiAgICB0aGlzLm1vbml0b3JBcHBTeW5jKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckF1cm9yYUNsdXN0ZXIobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yQXV0b1NjYWxpbmdHcm91cChub2RlKTtcbiAgICB0aGlzLm1vbml0b3JDbG91ZEZyb250KG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckNvZGVCdWlsZChub2RlKTtcbiAgICB0aGlzLm1vbml0b3JEb2N1bWVudERiKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckR5bmFtb0RiKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckZhcmdhdGVTZXJ2aWNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckZhcmdhdGVMb2FkQmFsYW5jZWRTZXJ2aWNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckdsdWUobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yS2luZXNpc0FuYWx5dGljcyhub2RlKTtcbiAgICB0aGlzLm1vbml0b3JLaW5lc2lzRGF0YVN0cmVhbShub2RlKTtcbiAgICB0aGlzLm1vbml0b3JLaW5lc2lzRGF0YVN0cmVhbUNvbnN1bWVyKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvcktpbmVzaXNGaXJlaG9zZShub2RlKTtcbiAgICB0aGlzLm1vbml0b3JMYW1iZGEobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yT3BlblNlYXJjaChub2RlKTtcbiAgICB0aGlzLm1vbml0b3JSZHNDbHVzdGVyKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclJkc0luc3RhbmNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclJlZHNoaWZ0KG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclMzKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclNlY3JldHNNYW5hZ2VyKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclNucyhub2RlKTtcbiAgICB0aGlzLm1vbml0b3JTcXMobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yU3RlcEZ1bmN0aW9ucyhub2RlKTtcbiAgICB0aGlzLm1vbml0b3JTeW50aGV0aWNzQ2FuYXJpZXMobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yV2ViQXBwbGljYXRpb25GaXJld2FsbFYyQWNscyhub2RlKTtcblxuICAgIGlmICghdGhpcy5hZGRlZE5vZGVJbmRlcGVuZGVudE1vbml0b3JpbmdUb1Njb3BlKSB7XG4gICAgICB0aGlzLmFkZGVkTm9kZUluZGVwZW5kZW50TW9uaXRvcmluZ1RvU2NvcGUgPSB0cnVlO1xuXG4gICAgICB0aGlzLm1vbml0b3JFYzIoKTtcbiAgICAgIHRoaXMubW9uaXRvckJpbGxpbmcoKTtcbiAgICAgIHRoaXMubW9uaXRvckVsYXN0aWNDYWNoZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0TW9uaXRvcmluZ0RldGFpbHM8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4+KFxuICAgIGFzcGVjdE9wdGlvbnM/OiBCYXNlTW9uaXRvcmluZ0FzcGVjdFR5cGUgJiB7IHByb3BzPzogVCB9LFxuICApOiBbYm9vbGVhbiwgVD9dIHtcbiAgICBjb25zdCBpc0VuYWJsZWQgPSBhc3BlY3RPcHRpb25zPy5lbmFibGVkID8/IHRydWU7XG4gICAgY29uc3QgcHJvcHMgPSBhc3BlY3RPcHRpb25zPy5wcm9wcztcbiAgICByZXR1cm4gW2lzRW5hYmxlZCwgcHJvcHNdO1xuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQWNtKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuYWNtKTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBhY20uQ2VydGlmaWNhdGUpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQ2VydGlmaWNhdGUoe1xuICAgICAgICBjZXJ0aWZpY2F0ZTogbm9kZSxcbiAgICAgICAgYWxhcm1GcmllbmRseU5hbWU6IG5vZGUubm9kZS5wYXRoLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckFwaUdhdGV3YXkobm9kZTogSUNvbnN0cnVjdCkge1xuICAgIGNvbnN0IFtpc0VuYWJsZWQsIHByb3BzXSA9IHRoaXMuZ2V0TW9uaXRvcmluZ0RldGFpbHModGhpcy5wcm9wcy5hcGlHYXRld2F5KTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBhcGlndy5SZXN0QXBpKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckFwaUdhdGV3YXkoe1xuICAgICAgICBhcGk6IG5vZGUsXG4gICAgICAgIGFwaVN0YWdlOiBub2RlLmRlcGxveW1lbnRTdGFnZS5zdGFnZU5hbWUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQXBpR2F0ZXdheVYyKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKFxuICAgICAgdGhpcy5wcm9wcy5hcGlHYXRld2F5VjIsXG4gICAgKTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBhcGlnd3YyLkh0dHBBcGkpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQXBpR2F0ZXdheVYySHR0cEFwaSh7XG4gICAgICAgIGFwaTogbm9kZSxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JBcHBTeW5jKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuYXBwU3luYyk7XG4gICAgaWYgKGlzRW5hYmxlZCAmJiBub2RlIGluc3RhbmNlb2YgYXBwc3luYy5HcmFwaHFsQXBpKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckFwcFN5bmNBcGkoe1xuICAgICAgICBhcGk6IG5vZGUsXG4gICAgICAgIGFsYXJtRnJpZW5kbHlOYW1lOiBub2RlLm5vZGUucGF0aCxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JBdXJvcmFDbHVzdGVyKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKFxuICAgICAgdGhpcy5wcm9wcy5hdXJvcmFDbHVzdGVyLFxuICAgICk7XG4gICAgaWYgKGlzRW5hYmxlZCAmJiBub2RlIGluc3RhbmNlb2YgcmRzLlNlcnZlcmxlc3NDbHVzdGVyKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckF1cm9yYUNsdXN0ZXIoe1xuICAgICAgICBjbHVzdGVyOiBub2RlLFxuICAgICAgICBhbGFybUZyaWVuZGx5TmFtZTogbm9kZS5ub2RlLnBhdGgsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQXV0b1NjYWxpbmdHcm91cChub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyhcbiAgICAgIHRoaXMucHJvcHMuYXV0b1NjYWxpbmdHcm91cCxcbiAgICApO1xuICAgIGlmIChpc0VuYWJsZWQgJiYgbm9kZSBpbnN0YW5jZW9mIGF1dG9zY2FsaW5nLkF1dG9TY2FsaW5nR3JvdXApIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQXV0b1NjYWxpbmdHcm91cCh7XG4gICAgICAgIGF1dG9TY2FsaW5nR3JvdXA6IG5vZGUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQmlsbGluZygpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuYmlsbGluZyk7XG4gICAgaWYgKGlzRW5hYmxlZCkge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JCaWxsaW5nKHtcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICAgIGFsYXJtRnJpZW5kbHlOYW1lOiBcIkJpbGxpbmdcIixcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckNsb3VkRnJvbnQobm9kZTogSUNvbnN0cnVjdCkge1xuICAgIGNvbnN0IFtpc0VuYWJsZWQsIHByb3BzXSA9IHRoaXMuZ2V0TW9uaXRvcmluZ0RldGFpbHModGhpcy5wcm9wcy5jbG91ZEZyb250KTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBjbG91ZGZyb250LkRpc3RyaWJ1dGlvbikge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JDbG91ZEZyb250RGlzdHJpYnV0aW9uKHtcbiAgICAgICAgZGlzdHJpYnV0aW9uOiBub2RlLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckNvZGVCdWlsZChub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyh0aGlzLnByb3BzLmNvZGVCdWlsZCk7XG4gICAgaWYgKGlzRW5hYmxlZCAmJiBub2RlIGluc3RhbmNlb2YgY29kZWJ1aWxkLlByb2plY3QpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQ29kZUJ1aWxkUHJvamVjdCh7XG4gICAgICAgIHByb2plY3Q6IG5vZGUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yRG9jdW1lbnREYihub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyh0aGlzLnByb3BzLmRvY3VtZW50RGIpO1xuICAgIGlmIChpc0VuYWJsZWQgJiYgbm9kZSBpbnN0YW5jZW9mIGRvY2RiLkRhdGFiYXNlQ2x1c3Rlcikge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JEb2N1bWVudERiQ2x1c3Rlcih7XG4gICAgICAgIGNsdXN0ZXI6IG5vZGUsXG4gICAgICAgIGFsYXJtRnJpZW5kbHlOYW1lOiBub2RlLm5vZGUucGF0aCxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JEeW5hbW9EYihub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyh0aGlzLnByb3BzLmR5bmFtb0RCKTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9kYi5UYWJsZSkge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JEeW5hbW9UYWJsZSh7XG4gICAgICAgIHRhYmxlOiBub2RlLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckVjMigpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuZWMyKTtcbiAgICBpZiAoaXNFbmFibGVkKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckVDMkluc3RhbmNlcyh7XG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yRWxhc3RpY0NhY2hlKCkge1xuICAgIGNvbnN0IFtpc0VuYWJsZWQsIHByb3BzXSA9IHRoaXMuZ2V0TW9uaXRvcmluZ0RldGFpbHMoXG4gICAgICB0aGlzLnByb3BzLmVsYXN0aWNDYWNoZSxcbiAgICApO1xuICAgIGlmIChpc0VuYWJsZWQpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yRWxhc3RpQ2FjaGVDbHVzdGVyKHtcbiAgICAgICAgY2x1c3RlclR5cGU6IEVsYXN0aUNhY2hlQ2x1c3RlclR5cGUuTUVNQ0FDSEVELFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JFbGFzdGlDYWNoZUNsdXN0ZXIoe1xuICAgICAgICBjbHVzdGVyVHlwZTogRWxhc3RpQ2FjaGVDbHVzdGVyVHlwZS5SRURJUyxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JGYXJnYXRlU2VydmljZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyhcbiAgICAgIHRoaXMucHJvcHMuZmFyZ2F0ZVNlcnZpY2UsXG4gICAgKTtcbiAgICBpZiAoXG4gICAgICBpc0VuYWJsZWQgJiZcbiAgICAgIG5vZGUgaW5zdGFuY2VvZiBlY3MuRmFyZ2F0ZVNlcnZpY2UgJiZcbiAgICAgICF0aGlzLmlzSW5zaWRlRmFyZ2F0ZVBhdHRlcm4obm9kZSlcbiAgICApIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yU2ltcGxlRmFyZ2F0ZVNlcnZpY2Uoe1xuICAgICAgICBmYXJnYXRlU2VydmljZTogbm9kZSxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JGYXJnYXRlTG9hZEJhbGFuY2VkU2VydmljZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyhcbiAgICAgIHRoaXMucHJvcHMuZmFyZ2F0ZUxvYWRCYWxhbmNlZFNlcnZpY2UsXG4gICAgKTtcbiAgICBpZiAoXG4gICAgICBpc0VuYWJsZWQgJiZcbiAgICAgIChub2RlIGluc3RhbmNlb2YgZWNzUGF0dGVybnMuQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSB8fFxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZWNzUGF0dGVybnMuTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlKVxuICAgICkge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JGYXJnYXRlU2VydmljZSh7XG4gICAgICAgIGZhcmdhdGVTZXJ2aWNlOiBub2RlLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvclF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKFxuICAgICAgdGhpcy5wcm9wcy5xdWV1ZVByb2Nlc3NpbmdGYXJnYXRlU2VydmljZSxcbiAgICApO1xuICAgIGlmIChcbiAgICAgIGlzRW5hYmxlZCAmJlxuICAgICAgbm9kZSBpbnN0YW5jZW9mIGVjc1BhdHRlcm5zLlF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlXG4gICAgKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvclF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlKHtcbiAgICAgICAgZmFyZ2F0ZVNlcnZpY2U6IG5vZGUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgRmFyZ2F0ZVNlcnZpY2UgaXMgb3duZWQgYnkgYW4gTDMgZWNzLXBhdHRlcm5zXG4gICAqIGNvbnN0cnVjdCAoQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSxcbiAgICogTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlLCBRdWV1ZVByb2Nlc3NpbmdGYXJnYXRlU2VydmljZSkuXG4gICAqIFRoZSBMMyBwYXR0ZXJuIGhhcyBpdHMgb3duIGFzcGVjdCBob29rLCBzbyBtb25pdG9yaW5nIHRoZSBpbm5lclxuICAgKiBzZXJ2aWNlIHNlcGFyYXRlbHkgd291bGQgZHVwbGljYXRlIGFsYXJtcy5cbiAgICovXG4gIHByaXZhdGUgaXNJbnNpZGVGYXJnYXRlUGF0dGVybihzZXJ2aWNlOiBlY3MuRmFyZ2F0ZVNlcnZpY2UpOiBib29sZWFuIHtcbiAgICBjb25zdCBNQVhfQU5DRVNUT1JfREVQVEggPSAzO1xuICAgIGxldCBjdXJyZW50OiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkID0gc2VydmljZS5ub2RlLnNjb3BlO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgTUFYX0FOQ0VTVE9SX0RFUFRIICYmIGN1cnJlbnQ7IGkrKykge1xuICAgICAgaWYgKFxuICAgICAgICBjdXJyZW50IGluc3RhbmNlb2YgZWNzUGF0dGVybnMuQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSB8fFxuICAgICAgICBjdXJyZW50IGluc3RhbmNlb2YgZWNzUGF0dGVybnMuTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlIHx8XG4gICAgICAgIGN1cnJlbnQgaW5zdGFuY2VvZiBlY3NQYXR0ZXJucy5RdWV1ZVByb2Nlc3NpbmdGYXJnYXRlU2VydmljZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuIC