UNPKG

aws-delivlib

Version:

A fabulous library for defining continuous pipelines for building, testing and releasing code libraries.

377 lines • 60.7 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Pipeline = void 0; const aws_cdk_lib_1 = require("aws-cdk-lib"); const constructs_1 = require("constructs"); const auto_build_1 = require("./auto-build"); const build_env_1 = require("./build-env"); const canary_1 = require("./canary"); const change_controller_1 = require("./change-controller"); const chime_notifier_1 = require("./chime-notifier"); const pipeline_watcher_1 = require("./pipeline-watcher"); const publishing = __importStar(require("./publishing")); const pull_request_1 = require("./pull-request"); const repo_1 = require("./repo"); const shellable_1 = require("./shellable"); const signing = __importStar(require("./signing")); const util_1 = require("./util"); const PUBLISH_STAGE_NAME = 'Publish'; const SIGNING_STAGE_NAME = 'Sign'; const TEST_STAGE_NAME = 'Test'; const METRIC_NAMESPACE = 'CDK/Delivlib'; const FAILURE_METRIC_NAME = 'Failures'; /** * Defines a delivlib CI/CD pipeline. */ class Pipeline extends constructs_1.Construct { constructor(parent, name, props) { super(parent, name); this.stages = {}; this.concurrency = props.concurrency; this.repo = props.repo; this.dryRun = !!props.dryRun; this.pipeline = new aws_cdk_lib_1.aws_codepipeline.Pipeline(this, 'BuildPipeline', { pipelineName: props.pipelineName, restartExecutionOnUpdate: props.restartExecutionOnUpdate === undefined ? true : props.restartExecutionOnUpdate, }); // We will use the pipeline name if given, but we can't use the Ref if not given // because that would create cyclic references. Fall back to construct path if anonymous. this.descrPipelineName = props.pipelineName ?? this.node.path; this.branch = props.branch || 'master'; this.sourceArtifact = props.repo.createSourceStage(this.pipeline, this.branch); this.buildEnvironment = (0, build_env_1.createBuildEnvironment)(props); this.buildSpec = props.buildSpec; let buildProjectName = props.buildProjectName; if (buildProjectName === undefined && props.pipelineName !== undefined) { buildProjectName = `${props.pipelineName}-Build`; } this.buildProject = new aws_cdk_lib_1.aws_codebuild.PipelineProject(this, 'BuildProject', { description: `Pipeline ${this.descrPipelineName}: build step`, projectName: buildProjectName, environment: this.buildEnvironment, buildSpec: this.buildSpec, timeout: props.buildTimeout ?? aws_cdk_lib_1.Duration.hours(8), ssmSessionPermissions: true, }); this.buildRole = this.buildProject.role; this.buildRole.addManagedPolicy(aws_cdk_lib_1.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonElasticContainerRegistryPublicReadOnly')); const buildStage = this.getOrCreateStage('Build'); const buildOutput = new aws_cdk_lib_1.aws_codepipeline.Artifact(); buildStage.addAction(new aws_cdk_lib_1.aws_codepipeline_actions.CodeBuildAction({ actionName: 'Build', project: this.buildProject, input: this.sourceArtifact, outputs: [buildOutput], })); this.buildOutput = buildOutput; this.defaultArtifact = buildOutput; if (props.notificationEmail) { this.notify = new aws_cdk_lib_1.aws_sns.Topic(this, 'NotificationsTopic'); this.notify.addSubscription(new aws_cdk_lib_1.aws_sns_subscriptions.EmailSubscription(props.notificationEmail)); } // add a failure alarm for the entire pipeline. this.failureAlarm = this.addFailureAlarm(props.title); // emit an SNS notification every time build fails. this.addBuildFailureNotification(this.buildProject, `${props.title} build failed`); // Also emit to Chime webhooks if configured if (props.chimeFailureWebhooks) { new chime_notifier_1.ChimeNotifier(this, 'ChimeNotifier', { pipeline: this.pipeline, message: props.chimeMessage, webhookUrls: props.chimeFailureWebhooks, }); } if (props.autoBuild) { this.autoBuildProject = this.autoBuild(props.autoBuildOptions).project; } } /** * Signing output artifact */ get signingOutput() { return this._signingOutput; } notifyOnFailure(notification) { notification.bind({ pipeline: this, }); } /** * Add an action to run a shell script to the pipeline * * @return The Shellable and the Action added to the pipeline. */ addShellable(stageName, id, options) { const stage = this.getOrCreateStage(stageName); const sh = new shellable_1.Shellable(this, id, options); const action = sh.addToPipeline(stage, options.actionName || `Action${id}`, options.inputArtifact || this.defaultArtifact, this.determineRunOrderForNewAction(stage)); if (options.failureNotification) { this.addBuildFailureNotification(sh.project, options.failureNotification); } return { shellable: sh, action }; } addTest(id, props) { return this.addShellable(TEST_STAGE_NAME, id, { actionName: `Test${id}`, failureNotification: `Test ${id} failed`, ...props, }); } /** * Convenience/discovery method that defines a canary test in your account. * @param id the construct id * @param props canary options */ addCanary(id, props) { return new canary_1.Canary(this, `Canary${id}`, props); } addPublish(publisher, options = {}) { const publishStageName = options.stageName ?? PUBLISH_STAGE_NAME; if (!this.firstPublishStageName) { this.firstPublishStageName = publishStageName; } const stage = this.getOrCreateStage(publishStageName); publisher.addToPipeline(stage, `${publisher.node.id}Publish`, { inputArtifact: options.inputArtifact || this.defaultArtifact, runOrder: this.determineRunOrderForNewAction(stage), }); } /** * Adds a change control policy to block transitions into the publish stage during certain time windows. * @param options the options to configure the change control policy. */ addChangeControl(options = {}) { const publishStage = this.getStage(this.firstPublishStageName ?? PUBLISH_STAGE_NAME); if (!publishStage) { throw new Error(`This pipeline does not have a ${PUBLISH_STAGE_NAME} stage yet. Add one first.`); } return new change_controller_1.ChangeController(this, 'ChangeController', { ...options, pipelineStage: publishStage, }); } addSigning(signer, options = {}) { const signingStageName = options.stageName ?? SIGNING_STAGE_NAME; const stage = this.getOrCreateStage(signingStageName); this._signingOutput = signer.addToPipeline(stage, `${signer.node.id}Sign`, { inputArtifact: options.inputArtifact || this.defaultArtifact, runOrder: this.determineRunOrderForNewAction(stage), }); this.defaultArtifact = this._signingOutput; } signNuGetWithSigner(options) { this.addSigning(new signing.SignNuGetWithSigner(this, 'NuGetSigning', { ...options, }), options); } publishToNpm(options) { this.addPublish(new publishing.PublishToNpmProject(this, 'Npm', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to NPM`, dryRun: this.dryRun, ...options, }), options); } publishToMaven(options) { this.addPublish(new publishing.PublishToMavenProject(this, 'Maven', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to Maven`, dryRun: this.dryRun, ...options, }), options); } publishToNuGet(options) { this.addPublish(new publishing.PublishToNuGetProject(this, 'NuGet', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to NuGet`, dryRun: this.dryRun, ...options, }), options); } publishToGitHubPages(options) { this.addPublish(new publishing.PublishDocsToGitHubProject(this, 'GitHubPages', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to GitHub Pages`, dryRun: this.dryRun, ...options, }), options); } publishToGitHub(options) { this.addPublish(new publishing.PublishToGitHub(this, 'GitHub', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to GitHub`, dryRun: this.dryRun, ...options, }), options); } publishToPyPI(options) { this.addPublish(new publishing.PublishToPyPi(this, 'PyPI', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to PyPI`, dryRun: this.dryRun, ...options, }), options); } publishToS3(id, options) { this.addPublish(new publishing.PublishToS3(this, id, { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish to S3 (${options.bucket.bucketName})`, dryRun: this.dryRun, ...options, }), options); } /** * Publish Golang code from `go` directory in build artifact to a GitHub repository. */ publishToGolang(options) { this.addPublish(new publishing.PublishToGolang(this, 'Golang', { description: options.description ?? `Pipeline ${this.descrPipelineName}: publish Golang`, dryRun: this.dryRun, ...options, })); } /** * Enables automatic bumps for the source repo. * @param options Options for auto bump (see AutoBumpOptions for description of defaults) */ autoBump(options) { if (!repo_1.WritableGitHubRepo.isWritableGitHubRepo(this.repo)) { throw new Error('"repo" must be a WritableGitHubRepo in order to enable auto-bump'); } const autoBump = new pull_request_1.AutoBump(this, 'AutoBump', { repo: this.repo, ...options, }); return autoBump; } /** * Enables automatic merge backs for the source repo. * @param options Options for auto bump (see AutoMergeBackPipelineOptions for description of defaults) */ autoMergeBack(options) { if (!repo_1.WritableGitHubRepo.isWritableGitHubRepo(this.repo)) { throw new Error('"repo" must be a WritableGitHubRepo in order to enable auto-merge-back'); } const mergeBack = new pull_request_1.AutoMergeBack(this, 'MergeBack', { repo: this.repo, ...options, projectDescription: options?.projectDescription ?? `Pipeline ${this.descrPipelineName}: merge-back step`, }); if (options?.stage) { const afterStage = this.getStage(options.stage.after); if (!afterStage) { throw new Error(`'options.stage.after' must be configured to an existing stage: ${options.stage.after}`); } const stage = this.getOrCreateStage(options.stage.name ?? 'MergeBack', { justAfter: afterStage }); stage.addAction(new aws_cdk_lib_1.aws_codepipeline_actions.CodeBuildAction({ actionName: 'CreateMergeBackPullRequest', project: mergeBack.pr.project, input: this.sourceArtifact, })); } } /** * Enables automatic builds of pull requests in the Github repository and posts the * results back as a comment with a public link to the build logs. */ autoBuild(options = {}) { return new auto_build_1.AutoBuild(this, 'AutoBuild', { environment: this.buildEnvironment, repo: this.repo, buildSpec: options.buildSpec || this.buildSpec, ...options, }); } /** * The metric that tracks pipeline failures. */ metricFailures(options) { return new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: METRIC_NAMESPACE, metricName: FAILURE_METRIC_NAME, dimensionsMap: { Pipeline: this.pipeline.pipelineName, }, statistic: 'Sum', ...options, }); } /** * The metrics that track failure of each action within the pipeline. */ metricActionFailures(options) { return (0, util_1.flatMap)(this.pipeline.stages, stage => stage.actions.map(action => { return new aws_cdk_lib_1.aws_cloudwatch.Metric({ namespace: METRIC_NAMESPACE, metricName: FAILURE_METRIC_NAME, dimensionsMap: { Pipeline: this.pipeline.pipelineName, Action: action.actionProperties.actionName, }, statistic: 'Sum', ...options, }); })); } addManualApprovalToStage(stageName, props) { const stage = this.getOrCreateStage(stageName); stage.addAction(new aws_cdk_lib_1.aws_codepipeline_actions.ManualApprovalAction(props ?? { actionName: 'ManualApprovalAction', })); } addFailureAlarm(title) { return new pipeline_watcher_1.PipelineWatcher(this, 'PipelineWatcher', { pipeline: this.pipeline, metricNamespace: METRIC_NAMESPACE, failureMetricName: FAILURE_METRIC_NAME, title, }).alarm; } addBuildFailureNotification(buildProject, message) { if (!this.notify) { return; } buildProject.onBuildFailed('OnBuildFailed').addTarget(new aws_cdk_lib_1.aws_events_targets.SnsTopic(this.notify, { message: aws_cdk_lib_1.aws_events.RuleTargetInput.fromText(message), })); } /** * @returns the stage or undefined if the stage doesn't exist */ getStage(stageName) { return this.stages[stageName]; } getOrCreateStage(stageName, placement) { // otherwise, group all actions so they run concurrently. let stage = this.getStage(stageName); if (!stage) { stage = this.pipeline.addStage({ stageName, placement, }); this.stages[stageName] = stage; } return stage; } determineRunOrderForNewAction(stage) { return (0, util_1.determineRunOrder)(stage.actions.length, this.concurrency); } } exports.Pipeline = Pipeline; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwaXBlbGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDZDQVdxQjtBQUNyQiwyQ0FBbUQ7QUFFbkQsNkNBQTJEO0FBQzNELDJDQUFxRDtBQUNyRCxxQ0FBK0M7QUFDL0MsMkRBQXVEO0FBQ3ZELHFEQUFpRDtBQUNqRCx5REFBcUQ7QUFDckQseURBQTJDO0FBQzNDLGlEQUF3RTtBQUV4RSxpQ0FBbUQ7QUFDbkQsMkNBQXdEO0FBQ3hELG1EQUFxQztBQUNyQyxpQ0FBb0Q7QUFFcEQsTUFBTSxrQkFBa0IsR0FBRyxTQUFTLENBQUM7QUFDckMsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLENBQUM7QUFDbEMsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDO0FBQy9CLE1BQU0sZ0JBQWdCLEdBQUcsY0FBYyxDQUFDO0FBQ3hDLE1BQU0sbUJBQW1CLEdBQUcsVUFBVSxDQUFDO0FBd0p2Qzs7R0FFRztBQUNILE1BQWEsUUFBUyxTQUFRLHNCQUFTO0lBa0NyQyxZQUFZLE1BQWlCLEVBQUUsSUFBWSxFQUFFLEtBQW9CO1FBQy9ELEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFaZCxXQUFNLEdBQXlDLEVBQUcsQ0FBQztRQWN6RCxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFDckMsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFFN0IsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLDhCQUFTLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxlQUFlLEVBQUU7WUFDNUQsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZO1lBQ2hDLHdCQUF3QixFQUFFLEtBQUssQ0FBQyx3QkFBd0Is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ZTtRQUNoRixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixPQUFPO1NBQ1I7UUFFRCxZQUFZLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLGdDQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDN0YsT0FBTyxFQUFFLHdCQUFNLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7U0FDbEQsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRUQ7O09BRUc7SUFDSyxRQUFRLENBQUMsU0FBaUI7UUFDaEMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxTQUFpQixFQUFFLFNBQW9DO1FBQzlFLHlEQUF5RDtRQUN6RCxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7Z0JBQzdCLFNBQVM7Z0JBQ1QsU0FBUzthQUNWLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFDO1NBQ2hDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sNkJBQTZCLENBQUMsS0FBdUI7UUFDM0QsT0FBTyxJQUFBLHdCQUFpQixFQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNuRSxDQUFDO0NBQ0Y7QUFwYUQsNEJBb2FDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRHVyYXRpb24sXG4gIGF3c19jbG91ZHdhdGNoIGFzIGNsb3Vkd2F0Y2gsXG4gIGF3c19jb2RlYnVpbGQgYXMgY2J1aWxkLFxuICBhd3NfY29kZXBpcGVsaW5lIGFzIGNwaXBlbGluZSxcbiAgYXdzX2NvZGVwaXBlbGluZV9hY3Rpb25zIGFzIGNwaXBlbGluZV9hY3Rpb25zLFxuICBhd3NfZXZlbnRzIGFzIGV2ZW50cyxcbiAgYXdzX2V2ZW50c190YXJnZXRzIGFzIGV2ZW50c190YXJnZXRzLFxuICBhd3NfaWFtIGFzIGlhbSwgYXdzX3MzIGFzIHMzLFxuICBhd3Nfc25zIGFzIHNucyxcbiAgYXdzX3Nuc19zdWJzY3JpcHRpb25zIGFzIHNuc19zdWJzLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuaW1wb3J0IHsgQXV0b0J1aWxkLCBBdXRvQnVpbGRPcHRpb25zIH0gZnJvbSAnLi9hdXRvLWJ1aWxkJztcbmltcG9ydCB7IGNyZWF0ZUJ1aWxkRW52aXJvbm1lbnQgfSBmcm9tICcuL2J1aWxkLWVudic7XG5pbXBvcnQgeyBDYW5hcnksIENhbmFyeVByb3BzIH0gZnJvbSAnLi9jYW5hcnknO1xuaW1wb3J0IHsgQ2hhbmdlQ29udHJvbGxlciB9IGZyb20gJy4vY2hhbmdlLWNvbnRyb2xsZXInO1xuaW1wb3J0IHsgQ2hpbWVOb3RpZmllciB9IGZyb20gJy4vY2hpbWUtbm90aWZpZXInO1xuaW1wb3J0IHsgUGlwZWxpbmVXYXRjaGVyIH0gZnJvbSAnLi9waXBlbGluZS13YXRjaGVyJztcbmltcG9ydCAqIGFzIHB1Ymxpc2hpbmcgZnJvbSAnLi9wdWJsaXNoaW5nJztcbmltcG9ydCB7IEF1dG9CdW1wLCBBdXRvTWVyZ2VCYWNrLCBBdXRvQnVtcFByb3BzIH0gZnJvbSAnLi9wdWxsLXJlcXVlc3QnO1xuaW1wb3J0IHsgQXV0b01lcmdlQmFja1BpcGVsaW5lT3B0aW9ucyB9IGZyb20gJy4vcHVsbC1yZXF1ZXN0L21lcmdlLWJhY2snO1xuaW1wb3J0IHsgSVJlcG8sIFdyaXRhYmxlR2l0SHViUmVwbyB9IGZyb20gJy4vcmVwbyc7XG5pbXBvcnQgeyBTaGVsbGFibGUsIFNoZWxsYWJsZVByb3BzIH0gZnJvbSAnLi9zaGVsbGFibGUnO1xuaW1wb3J0ICogYXMgc2lnbmluZyBmcm9tICcuL3NpZ25pbmcnO1xuaW1wb3J0IHsgZGV0ZXJtaW5lUnVuT3JkZXIsIGZsYXRNYXAgfSBmcm9tICcuL3V0aWwnO1xuXG5jb25zdCBQVUJMSVNIX1NUQUdFX05BTUUgPSAnUHVibGlzaCc7XG5jb25zdCBTSUdOSU5HX1NUQUdFX05BTUUgPSAnU2lnbic7XG5jb25zdCBURVNUX1NUQUdFX05BTUUgPSAnVGVzdCc7XG5jb25zdCBNRVRSSUNfTkFNRVNQQUNFID0gJ0NESy9EZWxpdmxpYic7XG5jb25zdCBGQUlMVVJFX01FVFJJQ19OQU1FID0gJ0ZhaWx1cmVzJztcblxuZXhwb3J0IGludGVyZmFjZSBQaXBlbGluZVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgcmVwb3NpdG9yeSB0byBidWlsZCAoZS5nLiBHaXRIdWJSZXBvKS5cbiAgICovXG4gIHJlYWRvbmx5IHJlcG86IElSZXBvO1xuXG4gIC8qKlxuICAgKiBBIGRpc3BsYXkgbmFtZSBmb3IgdGhpcyBwaXBlbGluZS5cbiAgICovXG4gIHJlYWRvbmx5IHRpdGxlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHBoeXNpY2FsIG5hbWUgZm9yIHRoaXMgcGlwZWxpbmUuXG4gICAqIEBkZWZhdWx0IC0gYSBuZXcgbmFtZSB3aWxsIGJlIGdlbmVyYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHBpcGVsaW5lTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQnJhbmNoIHRvIGJ1aWxkLlxuICAgKiBAZGVmYXVsdCBtYXN0ZXJcbiAgICovXG4gIHJlYWRvbmx5IGJyYW5jaD86IHN0cmluZztcblxuICAvKipcbiAgICogRW1haWwgdG8gc2VuZCBmYWlsdXJlIG5vdGlmaWNhdGlvbnMuXG4gICAqIEBkZWZhdWx0IC0gTm8gZW1haWwgbm90aWZpY2F0aW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgbm90aWZpY2F0aW9uRW1haWw/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBpbWFnZSB1c2VkIGZvciB0aGUgYnVpbGRzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBqc2lpL3N1cGVyY2hhaW4gKHNlZSBkb2NzKVxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRJbWFnZT86IGNidWlsZC5JQnVpbGRJbWFnZTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIENvZGVCdWlsZCBwcm9qZWN0IHRoYXQgd2lsbCBiZSBwYXJ0IG9mIHRoaXMgcGlwZWxpbmUuXG4gICAqIEBkZWZhdWx0IC0gYCR7cGlwZWxpbmVOYW1lfS1CdWlsZGAsIGlmIGBwaXBlbGluZU5hbWVgIHByb3BlcnR5IGlzIHNwZWNpZmllZDsgYXV0b21hdGljYWxseSBnZW5lcmF0ZWQsIG90aGVyd2lzZS5cbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkUHJvamVjdE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIGNvbXB1dGUgdG8gdXNlIGZvciB0aGlzIGJ1aWxkLlxuICAgKiBTZWUgdGhlIHtAbGluayBDb21wdXRlVHlwZX0gZW51bSBmb3IgdGhlIHBvc3NpYmxlIHZhbHVlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgdGFrZW4gZnJvbSB7QGxpbmsgI2J1aWxkSW1hZ2UjZGVmYXVsdENvbXB1dGVUeXBlfVxuICAgKi9cbiAgcmVhZG9ubHkgY29tcHV0ZVR5cGU/OiBjYnVpbGQuQ29tcHV0ZVR5cGU7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyBob3cgdGhlIHByb2plY3QgYnVpbGRzIERvY2tlciBpbWFnZXMuIFNwZWNpZnkgdHJ1ZSB0byBlbmFibGVcbiAgICogcnVubmluZyB0aGUgRG9ja2VyIGRhZW1vbiBpbnNpZGUgYSBEb2NrZXIgY29udGFpbmVyLiBUaGlzIHZhbHVlIG11c3QgYmVcbiAgICogc2V0IHRvIHRydWUgb25seSBpZiB0aGlzIGJ1aWxkIHByb2plY3Qgd2lsbCBiZSB1c2VkIHRvIGJ1aWxkIERvY2tlclxuICAgKiBpbWFnZXMsIGFuZCB0aGUgc3BlY2lmaWVkIGJ1aWxkIGVudmlyb25tZW50IGltYWdlIGlzIG5vdCBvbmUgcHJvdmlkZWQgYnlcbiAgICogQVdTIENvZGVCdWlsZCB3aXRoIERvY2tlciBzdXBwb3J0LiBPdGhlcndpc2UsIGFsbCBhc3NvY2lhdGVkIGJ1aWxkcyB0aGF0XG4gICAqIGF0dGVtcHQgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgRG9ja2VyIGRhZW1vbiB3aWxsIGZhaWwuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBwcml2aWxlZ2VkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHBhc3MgdG8gYnVpbGRcbiAgICovXG4gIHJlYWRvbmx5IGVudmlyb25tZW50PzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogT3B0aW9uYWwgYnVpbGRzcGVjLCBhcyBhbiBhbHRlcm5hdGl2ZSB0byBhIGJ1aWxkc3BlYy55bWwgZmlsZVxuICAgKi9cbiAgcmVhZG9ubHkgYnVpbGRTcGVjPzogY2J1aWxkLkJ1aWxkU3BlYztcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgdG8gcmUtcnVuIHRoZSBwaXBlbGluZSBhZnRlciB5b3UndmUgdXBkYXRlZCBpdC5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdGFydEV4ZWN1dGlvbk9uVXBkYXRlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIHRoZSBjb25jdXJyZW5jeSBsaW1pdCB0ZXN0IGFuZCBwdWJsaXNoIHN0YWdlcy5cbiAgICpcbiAgICogRm9yIGV4YW1wbGUsIGlmIHRoaXMgdmFsdWUgaXMgMiwgdGhlbiBvbmx5IHR3byBhY3Rpb25zIHdpbGwgZXhlY3V0ZSBjb25jdXJyZW50bHkuXG4gICAqIElmIHRoaXMgdmFsdWUgaXMgMSwgdGhlIHBpcGVsaW5lIHdpbGwgbm90IGhhdmUgYW55IGNvbmN1cnJlbnQgZXhlY3V0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGxpbWl0XG4gICAqL1xuICByZWFkb25seSBjb25jdXJyZW5jeT86IG51bWJlcjtcblxuICAvKipcbiAgICogU2V0IHRoZSBkZWZhdWx0IGRyeVJ1biBmb3IgYWxsIHB1Ymxpc2hpbmcgc3RlcHNcbiAgICpcbiAgICogKENhbiBzdGlsbCBiZSBjaGFuZ2VkIHdoZW4gYWRkaW5nIGEgc3RlcCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkcnlSdW4/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBdXRvbWF0aWNhbGx5IGJ1aWxkIGNvbW1pdHMgdGhhdCBhcmUgcHVzaGVkIHRvIHRoaXMgcmVwb3NpdG9yeSwgaW5jbHVkaW5nIFBSIGJ1aWxkcyBvbiBnaXRodWIuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBhdXRvQnVpbGQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBPcHRpb25zIGZvciBhdXRvLWJ1aWxkXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gJ2F1dG9CdWlsZE9wdGlvbnMucHVibGljTG9ncycgd2lsbCBiZSBzZXQgdG8gaXRzIGRlZmF1bHQuICdhdXRvQnVpbGRPcHRpb25zLmJ1aWxkc3BlYycgd2lsbCBiZSBjb25maWd1cmVkIHRvIG1hdGNoIHdpdGggdGhlXG4gICAqICdidWlsZFNwZWMnIHByb3BlcnR5LlxuICAgKi9cbiAgcmVhZG9ubHkgYXV0b0J1aWxkT3B0aW9ucz86IEF1dG9CdWlsZE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFBvc3QgYSBub3RpZmljYXRpb24gdG8gdGhlIGdpdmVuIENoaW1lIHdlYmhvb2tzIGlmIHRoZSBwaXBlbGluZSBmYWlsc1xuICAgKiBAZGVmYXVsdCAtIG5vIENoaW1lIG5vdGlmaWNhdGlvbnMgb24gcGlwZWxpbmUgZmFpbHVyZVxuICAgKiBAZGVwcmVjYXRlZCAtIHVzZSBgbm90aWZ5T25GYWlsdXJlKClgIGluc3RlYWQgaW4gY29tYmluYXRpb24gd2l0aCBgUGlwZWxpbmVOb3RpZmljYXRpb24uY2hpbWUoKWAuXG4gICAqL1xuICByZWFkb25seSBjaGltZUZhaWx1cmVXZWJob29rcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgQ2hpbWUgbWVzc2FnZSB0byBwb3N0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSBkZWZhdWx0IG1lc3NhZ2VcbiAgICovXG4gIHJlYWRvbmx5IGNoaW1lTWVzc2FnZT86IHN0cmluZztcblxuICAvKipcbiAgICogQnVpbGQgdGltZW91dFxuICAgKlxuICAgKiBIb3cgbG9uZyB0aGUgYnVpbGQgY2FuIHRha2UgYXQgbWF4aW11bSAoYmVmb3JlIGZhaWxpbmcgd2l0aCBhbiBlcnJvcikuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRHVyYXRpb24uaG91cnMoOClcbiAgICovXG4gIHJlYWRvbmx5IGJ1aWxkVGltZW91dD86IER1cmF0aW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBpcGVsaW5lTm90aWZpY2F0aW9uQmluZE9wdGlvbnMge1xuICByZWFkb25seSBwaXBlbGluZTogUGlwZWxpbmU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVBpcGVsaW5lTm90aWZpY2F0aW9uIHtcbiAgYmluZChwaXBlbGluZTogUGlwZWxpbmVOb3RpZmljYXRpb25CaW5kT3B0aW9ucyk6IHZvaWQ7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgYW4gYXV0byBidW1wIGZvciB0aGlzIHBpcGVsaW5lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dG9CdW1wT3B0aW9ucyBleHRlbmRzIE9taXQ8QXV0b0J1bXBQcm9wcywgJ3JlcG8nPiB7XG59XG5cbi8qKlxuICogRGVmaW5lcyBhIGRlbGl2bGliIENJL0NEIHBpcGVsaW5lLlxuICovXG5leHBvcnQgY2xhc3MgUGlwZWxpbmUgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgYnVpbGRSb2xlPzogaWFtLklSb2xlO1xuICBwdWJsaWMgcmVhZG9ubHkgZmFpbHVyZUFsYXJtOiBjbG91ZHdhdGNoLkFsYXJtO1xuICBwdWJsaWMgcmVhZG9ubHkgYnVpbGRPdXRwdXQ6IGNwaXBlbGluZS5BcnRpZmFjdDtcbiAgcHVibGljIHJlYWRvbmx5IHNvdXJjZUFydGlmYWN0OiBjcGlwZWxpbmUuQXJ0aWZhY3Q7XG5cbiAgLyoqXG4gICAqIFRoZSBwcmltYXJ5IENvZGVCdWlsZCBwcm9qZWN0IG9mIHRoaXMgcGlwZWxpbmUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYnVpbGRQcm9qZWN0OiBjYnVpbGQuSVByb2plY3Q7XG5cbiAgLyoqXG4gICAqIFRoZSBhdXRvIGJ1aWxkIHByb2plY3QuIHVuZGVmaW5lZCBpZiAnYXV0b0J1aWxkJyBpcyBkaXNhYmxlZCBmb3IgdGhpcyBwaXBlbGluZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhdXRvQnVpbGRQcm9qZWN0PzogY2J1aWxkLlByb2plY3Q7XG5cbiAgLypcbiAgICogVGhlIHVuZGVybHlpbmcgQ29kZVBpcGVsaW5lIFBpcGVsaW5lIG9iamVjdCB0aGF0IG1vZGVscyB0aGlzIHBpcGVsaW5lLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBpcGVsaW5lOiBjcGlwZWxpbmUuUGlwZWxpbmU7XG4gIHByaXZhdGUgcmVhZG9ubHkgYnJhbmNoOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgbm90aWZ5Pzogc25zLlRvcGljO1xuICBwcml2YXRlIGRlZmF1bHRBcnRpZmFjdDogY3BpcGVsaW5lLkFydGlmYWN0O1xuICBwcml2YXRlIHN0YWdlczogeyBbbmFtZTogc3RyaW5nXTogY3BpcGVsaW5lLklTdGFnZSB9ID0geyB9O1xuICBwcml2YXRlIF9zaWduaW5nT3V0cHV0PzogY3BpcGVsaW5lLkFydGlmYWN0O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY29uY3VycmVuY3k/OiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVwbzogSVJlcG87XG4gIHByaXZhdGUgcmVhZG9ubHkgZHJ5UnVuOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IGJ1aWxkRW52aXJvbm1lbnQ6IGNidWlsZC5CdWlsZEVudmlyb25tZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGJ1aWxkU3BlYz86IGNidWlsZC5CdWlsZFNwZWM7XG4gIHByaXZhdGUgZmlyc3RQdWJsaXNoU3RhZ2VOYW1lPzogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc2NyUGlwZWxpbmVOYW1lOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IocGFyZW50OiBDb25zdHJ1Y3QsIG5hbWU6IHN0cmluZywgcHJvcHM6IFBpcGVsaW5lUHJvcHMpIHtcbiAgICBzdXBlcihwYXJlbnQsIG5hbWUpO1xuXG4gICAgdGhpcy5jb25jdXJyZW5jeSA9IHByb3BzLmNvbmN1cnJlbmN5O1xuICAgIHRoaXMucmVwbyA9IHByb3BzLnJlcG87XG4gICAgdGhpcy5kcnlSdW4gPSAhIXByb3BzLmRyeVJ1bjtcblxuICAgIHRoaXMucGlwZWxpbmUgPSBuZXcgY3BpcGVsaW5lLlBpcGVsaW5lKHRoaXMsICdCdWlsZFBpcGVsaW5lJywge1xuICAgICAgcGlwZWxpbmVOYW1lOiBwcm9wcy5waXBlbGluZU5hbWUsXG4gICAgICByZXN0YXJ0RXhlY3V0aW9uT25VcGRhdGU6IHByb3BzLnJlc3RhcnRFeGVjdXRpb25PblVwZGF0ZSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHByb3BzLnJlc3RhcnRFeGVjdXRpb25PblVwZGF0ZSxcbiAgICB9KTtcbiAgICAvLyBXZSB3aWxsIHVzZSB0aGUgcGlwZWxpbmUgbmFtZSBpZiBnaXZlbiwgYnV0IHdlIGNhbid0IHVzZSB0aGUgUmVmIGlmIG5vdCBnaXZlblxuICAgIC8vIGJlY2F1c2UgdGhhdCB3b3VsZCBjcmVhdGUgY3ljbGljIHJlZmVyZW5jZXMuIEZhbGwgYmFjayB0byBjb25zdHJ1Y3QgcGF0aCBpZiBhbm9ueW1vdXMuXG4gICAgdGhpcy5kZXNjclBpcGVsaW5lTmFtZSA9IHByb3BzLnBpcGVsaW5lTmFtZSA/PyB0aGlzLm5vZGUucGF0aDtcblxuICAgIHRoaXMuYnJhbmNoID0gcHJvcHMuYnJhbmNoIHx8ICdtYXN0ZXInO1xuICAgIHRoaXMuc291cmNlQXJ0aWZhY3QgPSBwcm9wcy5yZXBvLmNyZWF0ZVNvdXJjZVN0YWdlKHRoaXMucGlwZWxpbmUsIHRoaXMuYnJhbmNoKTtcblxuICAgIHRoaXMuYnVpbGRFbnZpcm9ubWVudCA9IGNyZWF0ZUJ1aWxkRW52aXJvbm1lbnQocHJvcHMpO1xuICAgIHRoaXMuYnVpbGRTcGVjID0gcHJvcHMuYnVpbGRTcGVjO1xuXG4gICAgbGV0IGJ1aWxkUHJvamVjdE5hbWUgPSBwcm9wcy5idWlsZFByb2plY3ROYW1lO1xuICAgIGlmIChidWlsZFByb2plY3ROYW1lID09PSB1bmRlZmluZWQgJiYgcHJvcHMucGlwZWxpbmVOYW1lICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJ1aWxkUHJvamVjdE5hbWUgPSBgJHtwcm9wcy5waXBlbGluZU5hbWV9LUJ1aWxkYDtcbiAgICB9XG4gICAgdGhpcy5idWlsZFByb2plY3QgPSBuZXcgY2J1aWxkLlBpcGVsaW5lUHJvamVjdCh0aGlzLCAnQnVpbGRQcm9qZWN0Jywge1xuICAgICAgZGVzY3JpcHRpb246IGBQaXBlbGluZSAke3RoaXMuZGVzY3JQaXBlbGluZU5hbWV9OiBidWlsZCBzdGVwYCxcbiAgICAgIHByb2plY3ROYW1lOiBidWlsZFByb2plY3ROYW1lLFxuICAgICAgZW52aXJvbm1lbnQ6IHRoaXMuYnVpbGRFbnZpcm9ubWVudCxcbiAgICAgIGJ1aWxkU3BlYzogdGhpcy5idWlsZFNwZWMsXG4gICAgICB0aW1lb3V0OiBwcm9wcy5idWlsZFRpbWVvdXQgPz8gRHVyYXRpb24uaG91cnMoOCksXG4gICAgICBzc21TZXNzaW9uUGVybWlzc2lvbnM6IHRydWUsXG4gICAgfSk7XG5cbiAgICB0aGlzLmJ1aWxkUm9sZSA9IHRoaXMuYnVpbGRQcm9qZWN0LnJvbGU7XG4gICAgdGhpcy5idWlsZFJvbGUhLmFkZE1hbmFnZWRQb2xpY3koaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FbGFzdGljQ29udGFpbmVyUmVnaXN0cnlQdWJsaWNSZWFkT25seScpKTtcblxuICAgIGNvbnN0IGJ1aWxkU3RhZ2UgPSB0aGlzLmdldE9yQ3JlYXRlU3RhZ2UoJ0J1aWxkJyk7XG4gICAgY29uc3QgYnVpbGRPdXRwdXQgPSBuZXcgY3BpcGVsaW5lLkFydGlmYWN0KCk7XG4gICAgYnVpbGRTdGFnZS5hZGRBY3Rpb24obmV3IGNwaXBlbGluZV9hY3Rpb25zLkNvZGVCdWlsZEFjdGlvbih7XG4gICAgICBhY3Rpb25OYW1lOiAnQnVpbGQnLFxuICAgICAgcHJvamVjdDogdGhpcy5idWlsZFByb2plY3QsXG4gICAgICBpbnB1dDogdGhpcy5zb3VyY2VBcnRpZmFjdCxcbiAgICAgIG91dHB1dHM6IFtidWlsZE91dHB1dF0sXG4gICAgfSkpO1xuICAgIHRoaXMuYnVpbGRPdXRwdXQgPSBidWlsZE91dHB1dDtcbiAgICB0aGlzLmRlZmF1bHRBcnRpZmFjdCA9IGJ1aWxkT3V0cHV0O1xuXG4gICAgaWYgKHByb3BzLm5vdGlmaWNhdGlvbkVtYWlsKSB7XG4gICAgICB0aGlzLm5vdGlmeSA9IG5ldyBzbnMuVG9waWModGhpcywgJ05vdGlmaWNhdGlvbnNUb3BpYycpO1xuICAgICAgdGhpcy5ub3RpZnkuYWRkU3Vic2NyaXB0aW9uKG5ldyBzbnNfc3Vicy5FbWFpbFN1YnNjcmlwdGlvbihwcm9wcy5ub3RpZmljYXRpb25FbWFpbCkpO1xuICAgIH1cblxuICAgIC8vIGFkZCBhIGZhaWx1cmUgYWxhcm0gZm9yIHRoZSBlbnRpcmUgcGlwZWxpbmUuXG4gICAgdGhpcy5mYWlsdXJlQWxhcm0gPSB0aGlzLmFkZEZhaWx1cmVBbGFybShwcm9wcy50aXRsZSk7XG5cbiAgICAvLyBlbWl0IGFuIFNOUyBub3RpZmljYXRpb24gZXZlcnkgdGltZSBidWlsZCBmYWlscy5cbiAgICB0aGlzLmFkZEJ1aWxkRmFpbHVyZU5vdGlmaWNhdGlvbih0aGlzLmJ1aWxkUHJvamVjdCwgYCR7cHJvcHMudGl0bGV9IGJ1aWxkIGZhaWxlZGApO1xuXG4gICAgLy8gQWxzbyBlbWl0IHRvIENoaW1lIHdlYmhvb2tzIGlmIGNvbmZpZ3VyZWRcbiAgICBpZiAocHJvcHMuY2hpbWVGYWlsdXJlV2ViaG9va3MpIHtcbiAgICAgIG5ldyBDaGltZU5vdGlmaWVyKHRoaXMsICdDaGltZU5vdGlmaWVyJywge1xuICAgICAgICBwaXBlbGluZTogdGhpcy5waXBlbGluZSxcbiAgICAgICAgbWVzc2FnZTogcHJvcHMuY2hpbWVNZXNzYWdlLFxuICAgICAgICB3ZWJob29rVXJsczogcHJvcHMuY2hpbWVGYWlsdXJlV2ViaG9va3MsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMuYXV0b0J1aWxkKSB7XG4gICAgICB0aGlzLmF1dG9CdWlsZFByb2plY3QgPSB0aGlzLmF1dG9CdWlsZChwcm9wcy5hdXRvQnVpbGRPcHRpb25zKS5wcm9qZWN0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduaW5nIG91dHB1dCBhcnRpZmFjdFxuICAgKi9cbiAgcHVibGljIGdldCBzaWduaW5nT3V0cHV0KCkge1xuICAgIHJldHVybiB0aGlzLl9zaWduaW5nT3V0cHV0O1xuICB9XG5cbiAgcHVibGljIG5vdGlmeU9uRmFpbHVyZShub3RpZmljYXRpb246IElQaXBlbGluZU5vdGlmaWNhdGlvbikge1xuICAgIG5vdGlmaWNhdGlvbi5iaW5kKHtcbiAgICAgIHBpcGVsaW5lOiB0aGlzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBhY3Rpb24gdG8gcnVuIGEgc2hlbGwgc2NyaXB0IHRvIHRoZSBwaXBlbGluZVxuICAgKlxuICAgKiBAcmV0dXJuIFRoZSBTaGVsbGFibGUgYW5kIHRoZSBBY3Rpb24gYWRkZWQgdG8gdGhlIHBpcGVsaW5lLlxuICAgKi9cbiAgcHVibGljIGFkZFNoZWxsYWJsZShcbiAgICBzdGFnZU5hbWU6IHN0cmluZyxcbiAgICBpZDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IEFkZFNoZWxsYWJsZU9wdGlvbnMsXG4gICk6IHsgc2hlbGxhYmxlOiBTaGVsbGFibGU7IGFjdGlvbjogY3BpcGVsaW5lX2FjdGlvbnMuQ29kZUJ1aWxkQWN0aW9uIH0ge1xuICAgIGNvbnN0IHN0YWdlID0gdGhpcy5nZXRPckNyZWF0ZVN0YWdlKHN0YWdlTmFtZSk7XG5cbiAgICBjb25zdCBzaCA9IG5ldyBTaGVsbGFibGUodGhpcywgaWQsIG9wdGlvbnMpO1xuICAgIGNvbnN0IGFjdGlvbiA9IHNoLmFkZFRvUGlwZWxpbmUoXG4gICAgICBzdGFnZSxcbiAgICAgIG9wdGlvbnMuYWN0aW9uTmFtZSB8fCBgQWN0aW9uJHtpZH1gLFxuICAgICAgb3B0aW9ucy5pbnB1dEFydGlmYWN0IHx8IHRoaXMuZGVmYXVsdEFydGlmYWN0LFxuICAgICAgdGhpcy5kZXRlcm1pbmVSdW5PcmRlckZvck5ld0FjdGlvbihzdGFnZSkpO1xuXG4gICAgaWYgKG9wdGlvbnMuZmFpbHVyZU5vdGlmaWNhdGlvbikge1xuICAgICAgdGhpcy5hZGRCdWlsZEZhaWx1cmVOb3RpZmljYXRpb24oc2gucHJvamVjdCwgb3B0aW9ucy5mYWlsdXJlTm90aWZpY2F0aW9uKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBzaGVsbGFibGU6IHNoLCBhY3Rpb24gfTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUZXN0KGlkOiBzdHJpbmcsIHByb3BzOiBTaGVsbGFibGVQcm9wcyk6IHsgc2hlbGxhYmxlOiBTaGVsbGFibGU7IGFjdGlvbjogY3BpcGVsaW5lX2FjdGlvbnMuQ29kZUJ1aWxkQWN0aW9uIH0ge1xuICAgIHJldHVybiB0aGlzLmFkZFNoZWxsYWJsZShURVNUX1NUQUdFX05BTUUsIGlkLCB7XG4gICAgICBhY3Rpb25OYW1lOiBgVGVzdCR7aWR9YCxcbiAgICAgIGZhaWx1cmVOb3RpZmljYXRpb246IGBUZXN0ICR7aWR9IGZhaWxlZGAsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZW5pZW5jZS9kaXNjb3ZlcnkgbWV0aG9kIHRoYXQgZGVmaW5lcyBhIGNhbmFyeSB0ZXN0IGluIHlvdXIgYWNjb3VudC5cbiAgICogQHBhcmFtIGlkIHRoZSBjb25zdHJ1Y3QgaWRcbiAgICogQHBhcmFtIHByb3BzIGNhbmFyeSBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgYWRkQ2FuYXJ5KGlkOiBzdHJpbmcsIHByb3BzOiBDYW5hcnlQcm9wcykge1xuICAgIHJldHVybiBuZXcgQ2FuYXJ5KHRoaXMsIGBDYW5hcnkke2lkfWAsIHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRQdWJsaXNoKHB1Ymxpc2hlcjogSVB1Ymxpc2hlciwgb3B0aW9uczogQWRkUHVibGlzaE9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHB1Ymxpc2hTdGFnZU5hbWUgPSBvcHRpb25zLnN0YWdlTmFtZSA/PyBQVUJMSVNIX1NUQUdFX05BTUU7XG4gICAgaWYgKCF0aGlzLmZpcnN0UHVibGlzaFN0YWdlTmFtZSkge1xuICAgICAgdGhpcy5maXJzdFB1Ymxpc2hTdGFnZU5hbWUgPSBwdWJsaXNoU3RhZ2VOYW1lO1xuICAgIH1cbiAgICBjb25zdCBzdGFnZSA9IHRoaXMuZ2V0T3JDcmVhdGVTdGFnZShwdWJsaXNoU3RhZ2VOYW1lKTtcblxuICAgIHB1Ymxpc2hlci5hZGRUb1BpcGVsaW5lKHN0YWdlLCBgJHtwdWJsaXNoZXIubm9kZS5pZH1QdWJsaXNoYCwge1xuICAgICAgaW5wdXRBcnRpZmFjdDogb3B0aW9ucy5pbnB1dEFydGlmYWN0IHx8IHRoaXMuZGVmYXVsdEFydGlmYWN0LFxuICAgICAgcnVuT3JkZXI6IHRoaXMuZGV0ZXJtaW5lUnVuT3JkZXJGb3JOZXdBY3Rpb24oc3RhZ2UpLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjaGFuZ2UgY29udHJvbCBwb2xpY3kgdG8gYmxvY2sgdHJhbnNpdGlvbnMgaW50byB0aGUgcHVibGlzaCBzdGFnZSBkdXJpbmcgY2VydGFpbiB0aW1lIHdpbmRvd3MuXG4gICAqIEBwYXJhbSBvcHRpb25zIHRoZSBvcHRpb25zIHRvIGNvbmZpZ3VyZSB0aGUgY2hhbmdlIGNvbnRyb2wgcG9saWN5LlxuICAgKi9cbiAgcHVibGljIGFkZENoYW5nZUNvbnRyb2wob3B0aW9uczogQWRkQ2hhbmdlQ29udHJvbE9wdGlvbnMgPSB7IH0pOiBDaGFuZ2VDb250cm9sbGVyIHtcbiAgICBjb25zdCBwdWJsaXNoU3RhZ2UgPSB0aGlzLmdldFN0YWdlKHRoaXMuZmlyc3RQdWJsaXNoU3RhZ2VOYW1lID8/IFBVQkxJU0hfU1RBR0VfTkFNRSk7XG4gICAgaWYgKCFwdWJsaXNoU3RhZ2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhpcyBwaXBlbGluZSBkb2VzIG5vdCBoYXZlIGEgJHtQVUJMSVNIX1NUQUdFX05BTUV9IHN0YWdlIHlldC4gQWRkIG9uZSBmaXJzdC5gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENoYW5nZUNvbnRyb2xsZXIodGhpcywgJ0NoYW5nZUNvbnRyb2xsZXInLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgcGlwZWxpbmVTdGFnZTogcHVibGlzaFN0YWdlLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZFNpZ25pbmcoc2lnbmVyOiBzaWduaW5nLklTaWduZXIsIG9wdGlvbnM6IHNpZ25pbmcuQWRkU2lnbmluZ09wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHNpZ25pbmdTdGFnZU5hbWUgPSBvcHRpb25zLnN0YWdlTmFtZSA/PyBTSUdOSU5HX1NUQUdFX05BTUU7XG4gICAgY29uc3Qgc3RhZ2UgPSB0aGlzLmdldE9yQ3JlYXRlU3RhZ2Uoc2lnbmluZ1N0YWdlTmFtZSk7XG5cbiAgICB0aGlzLl9zaWduaW5nT3V0cHV0ID0gc2lnbmVyLmFkZFRvUGlwZWxpbmUoc3RhZ2UsIGAke3NpZ25lci5ub2RlLmlkfVNpZ25gLCB7XG4gICAgICBpbnB1dEFydGlmYWN0OiBvcHRpb25zLmlucHV0QXJ0aWZhY3QgfHwgdGhpcy5kZWZhdWx0QXJ0aWZhY3QsXG4gICAgICBydW5PcmRlcjogdGhpcy5kZXRlcm1pbmVSdW5PcmRlckZvck5ld0FjdGlvbihzdGFnZSksXG4gICAgfSk7XG4gICAgdGhpcy5kZWZhdWx0QXJ0aWZhY3QgPSB0aGlzLl9zaWduaW5nT3V0cHV0O1xuICB9XG5cbiAgcHVibGljIHNpZ25OdUdldFdpdGhTaWduZXIob3B0aW9uczogc2lnbmluZy5TaWduTnVHZXRXaXRoU2lnbmVyUHJvcHMgJiBzaWduaW5nLkFkZFNpZ25pbmdPcHRpb25zKSB7XG4gICAgdGhpcy5hZGRTaWduaW5nKG5ldyBzaWduaW5nLlNpZ25OdUdldFdpdGhTaWduZXIodGhpcywgJ051R2V0U2lnbmluZycsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfSksIG9wdGlvbnMpO1xuICB9XG5cbiAgcHVibGljIHB1Ymxpc2hUb05wbShvcHRpb25zOiBwdWJsaXNoaW5nLlB1Ymxpc2hUb05wbVByb2plY3RQcm9wcyAmIEFkZFB1Ymxpc2hPcHRpb25zKSB7XG4gICAgdGhpcy5hZGRQdWJsaXNoKG5ldyBwdWJsaXNoaW5nLlB1Ymxpc2hUb05wbVByb2plY3QodGhpcywgJ05wbScsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBvcHRpb25zLmRlc2NyaXB0aW9uID8/IGBQaXBlbGluZSAke3RoaXMuZGVzY3JQaXBlbGluZU5hbWV9OiBwdWJsaXNoIHRvIE5QTWAsXG4gICAgICBkcnlSdW46IHRoaXMuZHJ5UnVuLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KSwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgcHVibGlzaFRvTWF2ZW4ob3B0aW9uczogcHVibGlzaGluZy5QdWJsaXNoVG9NYXZlblByb2plY3RQcm9wcyAmIEFkZFB1Ymxpc2hPcHRpb25zKSB7XG4gICAgdGhpcy5hZGRQdWJsaXNoKG5ldyBwdWJsaXNoaW5nLlB1Ymxpc2hUb01hdmVuUHJvamVjdCh0aGlzLCAnTWF2ZW4nLCB7XG4gICAgICBkZXNjcmlwdGlvbjogb3B0aW9ucy5kZXNjcmlwdGlvbiA/PyBgUGlwZWxpbmUgJHt0aGlzLmRlc2NyUGlwZWxpbmVOYW1lfTogcHVibGlzaCB0byBNYXZlbmAsXG4gICAgICBkcnlSdW46IHRoaXMuZHJ5UnVuLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KSwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgcHVibGlzaFRvTnVHZXQob3B0aW9uczogcHVibGlzaGluZy5QdWJsaXNoVG9OdUdldFByb2plY3RQcm9wcyAmIEFkZFB1Ymxpc2hPcHRpb25zKSB7XG4gICAgdGhpcy5hZGRQdWJsaXNoKG5ldyBwdWJsaXNoaW5nLlB1Ymxpc2hUb051R2V0UHJvamVjdCh0aGlzLCAnTnVHZXQnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogb3B0aW9ucy5kZXNjcmlwdGlvbiA/PyBgUGlwZWxpbmUgJHt0aGlzLmRlc2NyUGlwZWxpbmVOYW1lfTogcHVibGlzaCB0byBOdUdldGAsXG4gICAgICBkcnlSdW46IHRoaXMuZHJ5UnVuLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KSwgb3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgcHVibGlzaFRvR2l0SHViUGFnZXMob3B0aW9uczogcHVibGlzaGluZy5QdWJsaXNoRG9jc1RvR2l0SHViUHJvamVjdFByb3BzICYgQWRkUHVibGlzaE9wdGlvbnMpIHtcbiAgICB0aGlzLmFkZFB1Ymxpc2gobmV3IHB1Ymxpc2hpbmcuUHVibGlzaERvY3NUb0dpdEh1YlByb2plY3QodGhpcywgJ0dpdEh1YlBhZ2VzJywge1xuICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMuZGVzY3JpcHRpb24gPz8gYFBpcGVsaW5lICR7dGhpcy5kZXNjclBpcGVsaW5lTmFtZX06IHB1Ymxpc2ggdG8gR2l0SHViIFBhZ2VzYCxcbiAgICAgIGRyeVJ1bjogdGhpcy5kcnlSdW4sXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pLCBvcHRpb25zKTtcbiAgfVxuXG4gIHB1YmxpYyBwdWJsaXNoVG9HaXRIdWIob3B0aW9uczogcHVibGlzaGluZy5QdWJsaXNoVG9HaXRIdWJQcm9wcyAmIEFkZFB1Ymxpc2hPcHRpb25zKSB7XG4gICAgdGhpcy5hZGRQdWJsaXNoKG5ldyBwdWJsaXNoaW5nLlB1Ymxpc2hUb0dpdEh1Yih0aGlzLCAnR2l0SHViJywge1xuICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnMuZGVzY3JpcHRpb24gPz8gYFBpcGVsaW5lICR7dGhpcy5kZXNjclBpcGVsaW5lTmFtZX06IHB1Ymxpc2ggdG8gR2l0SHViYCxcbiAgICAgIGRyeVJ1bjogdGhpcy5kcnlSdW4sXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pLCBvcHRpb25zKTtcbiAgfVxuXG4gIH