aws-ddk-core
Version:
The AWS DataOps Development Kit is an open source development framework for customers that build data workflows and modern data architecture on AWS.
261 lines (257 loc) • 42.5 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CICDPipelineStack = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const codestarnotifications = require("aws-cdk-lib/aws-codestarnotifications");
const sns = require("aws-cdk-lib/aws-sns");
const pipelines = require("aws-cdk-lib/pipelines");
const actions_1 = require("./actions");
const utils_1 = require("./utils");
const base_1 = require("../base");
const config_1 = require("../config");
/**
* Create a stack that contains DDK Continuous Integration and Delivery (CI/CD) pipeline.
The pipeline is based on
[CDK self-mutating pipeline](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html)
but includes several DDK-specific features, including:
- Ability to configure some properties via JSON config e.g. manual approvals for application stages
- Defaults for source/synth - CodeCommit & cdk synth, with ability to override them
- Ability to connect to private artifactory to pull artifacts from at synth
- Security best practices - ensures pipeline buckets block non-SSL, and are KMS-encrypted with rotated keys
- Builder interface to avoid chunky constructor methods
The user should be able to reuse the pipeline in multiple DDK applications hoping to save LOC.
@example
const stack = new CICDPipelineStack(app, "dummy-pipeline", { environmentId: "dev", pipelineName: "dummy-pipeline" })
.addSourceAction({ repositoryName: "dummy-repository" })
.addSynthAction()
.buildPipeline()
.add_checks()
.addStage({ stageId: "dev", stage: devStage, manualApprovals: true })
.synth()
.add_notifications();
*/
class CICDPipelineStack extends base_1.BaseStack {
/**
* Creates a new CICD Pipeline stack.
*
* @param scope Parent of this stack, usually an `App` or a `Stage`, but could be any construct.
* @param id The construct ID of this stack. If `stackName` is not explicitly
* defined, this id (and any parent IDs) will be used to determine the
* physical ID of the stack.
* @param props Stack properties.
*/
constructor(scope, id, props) {
super(scope, id, props);
this.environmentId = props.environmentId;
this.pipelineName = props.pipelineName;
this.pipelineId = id;
const config = props.config ?? "./ddk.json";
this.config = new config_1.Configurator(this, config, this.environmentId);
this.cdkLanguage = props.cdkLanguage ?? "typescript";
}
/**
* Add source action.
*
* @param props Source action properties.
* @returns reference to this pipeline.
*/
addSourceAction(props) {
var branch = props.branch ?? "main";
this.sourceAction =
props.sourceAction ||
actions_1.CICDActions.getCodeCommitSourceAction(this, {
repositoryName: props.repositoryName,
branch: branch,
});
return this;
}
/**
* Build the pipeline structure.
* @param props Additional pipeline properties.
* @returns reference to this pipeline.
*/
buildPipeline(props = {}) {
if (this.synthAction === undefined) {
throw new Error("Pipeline cannot be built without a synth action.");
}
this.pipeline = new pipelines.CodePipeline(this, "DDKCodePipeline", {
synth: this.synthAction,
crossAccountKeys: true,
pipelineName: this.pipelineName,
...props,
});
return this;
}
/**
* Add synth action. During synth can connect and pull artifacts from a private artifactory.
* @param props Synth action properties.
* @returns reference to this pipeline.
*/
addSynthAction(props = {}) {
const languageInstallCommands = {
typescript: "npm install",
python: "pip install -r requirements.txt",
};
let languageInstallCommand = languageInstallCommands[this.cdkLanguage];
if (props.cdkLanguageCommandLineArguments) {
for (const [argument, value] of Object.entries(props.cdkLanguageCommandLineArguments)) {
languageInstallCommand += ` ${argument} ${value}`;
}
}
this.synthAction =
props.synthAction ||
actions_1.CICDActions.getSynthAction({
codePipelineSource: this.sourceAction,
cdkVersion: props.cdkVersion,
partition: this.partition,
region: this.region,
account: this.account,
env: props.env,
rolePolicyStatements: props.rolePolicyStatements,
codeartifactRepository: props.codeartifactRepository,
codeartifactDomain: props.codeartifactDomain,
codeartifactDomainOwner: props.codeartifactDomainOwner,
additionalInstallCommands: props.additionalInstallCommands
? [languageInstallCommand].concat(props.additionalInstallCommands)
: [languageInstallCommand],
});
return this;
}
/**
* Add application stage to the CICD pipeline. This stage deploys your application infrastructure.
* @param props Application stage properties.
* @returns reference to this pipeline.
*/
addStage(props) {
if (this.pipeline === undefined) {
throw new Error("`.buildPipeline()` needs to be called first before adding application stages to the pipeline.");
}
const manualApprovals = props.manualApprovals ?? this.config.getConfigAttribute("manual_approvals") ?? false;
if (manualApprovals) {
this.pipeline?.addStage(props.stage, {
pre: [new pipelines.ManualApprovalStep("PromoteTo" + utils_1.toTitleCase(props.stageId))],
});
}
else {
this.pipeline?.addStage(props.stage, {});
}
return this;
}
/**
* Add multiple application stages in parallel to the CICD pipeline.
* @param props Application wave properties.
* @returns reference to this pipeline.
*/
addWave(props) {
if (this.pipeline === undefined) {
throw new Error("`.buildPipeline()` needs to be called first before adding application stages to the pipeline.");
}
const manualApprovals = props.manualApprovals ?? this.config.getConfigAttribute("manual_approvals") ?? false;
var wave = new pipelines.Wave(props.stageId);
if (manualApprovals) {
wave.addPre(new pipelines.ManualApprovalStep("PromoteTo" + utils_1.toTitleCase(props.stageId)));
}
props.stages.forEach((stage) => {
wave.addStage(stage);
});
this.pipeline?.addWave(props.stageId, wave);
return this;
}
/**
* Add linting - cfn-nag, and bandit.
* @param props Security lint properties.
* @returns reference to this pipeline.
*/
addSecurityLintStage(props) {
if (this.sourceAction === undefined) {
throw new Error("Source Action Must Be configured before calling this method.");
}
if (this.pipeline?.cloudAssemblyFileSet === undefined) {
throw new Error("No cloudAssemblyFileSet configured, source action needs to be configured for this pipeline.");
}
var stageName = props.stageName ?? "SecurityLint";
var cloudAssemblyFileSet = props.cloudAssemblyFileSet ?? this.pipeline?.cloudAssemblyFileSet;
this.pipeline?.addWave(stageName, {
post: [
actions_1.CICDActions.getCfnNagAction(cloudAssemblyFileSet, "CFNNag", props.cfnNagFailBuild),
actions_1.CICDActions.getBanditAction(this.sourceAction),
],
});
return this;
}
/**
* Add test - e.g. pytest.
* @param props Test stage properties.
* @returns reference to this pipeline.
*/
addTestStage(props) {
var stageName = props.stageName ?? "Tests";
var cloudAssemblyFileSet = props.cloudAssemblyFileSet ?? this.pipeline?.cloudAssemblyFileSet;
var commands = props.commands ?? ["./test.sh"];
if (cloudAssemblyFileSet === undefined) {
throw new Error("No cloudAssemblyFileSet configured, source action needs to be configured for this pipeline.");
}
this.pipeline?.addWave(stageName || "Tests", {
post: [actions_1.CICDActions.getTestsAction(cloudAssemblyFileSet, commands)],
});
return this;
}
/**
* Add pipeline notifications.
* Create notification rule that sends events to the specified SNS topic.
* @param props Notification properties.
* @returns reference to this pipeline.
*/
addNotifications(props = {}) {
if (this.pipeline === undefined) {
throw new Error("`.buildPipeline()` needs to be called first before adding notifications to the pipeline.");
}
const topic = this.environmentId && this.config.getConfigAttribute("notifications_topic_arn")
? sns.Topic.fromTopicArn(this, "ExecutionFailedNotifications", this.config.getConfigAttribute("notifications_topic_arn"))
: new sns.Topic(this, "ExecutionFailedNotifications");
this.notificationRule =
props.notificationRule ??
new codestarnotifications.NotificationRule(this, "Notification", {
detailType: codestarnotifications.DetailType.BASIC,
events: ["codepipeline-pipeline-pipeline-execution-failed"],
source: this.pipeline?.pipeline,
targets: [topic],
});
return this;
}
/**
* Add checks to the pipeline (e.g. linting, security, tests...).
* @returns reference to this pipeline.
*/
addChecks() {
this.addSecurityLintStage({});
this.addTestStage({});
return this;
}
/**
* Add custom stage to the pipeline.
* @param props Properties for adding a custom stage.
* @returns reference to this pipeline.
*/
addCustomStage(props) {
this.pipeline?.addWave(props.stageName, {
post: props.steps,
});
return this;
}
/**
* Synthesize the pipeline.
* @returns reference to this pipeline.
*/
synth() {
this.pipeline?.buildPipeline();
this.pipelineKey = this.pipeline?.pipeline.artifactBucket.encryptionKey?.node.defaultChild;
this.pipelineKey.addPropertyOverride("EnableKeyRotation", true);
return this;
}
}
exports.CICDPipelineStack = CICDPipelineStack;
_a = JSII_RTTI_SYMBOL_1;
CICDPipelineStack[_a] = { fqn: "aws-ddk-core.CICDPipelineStack", version: "1.4.1" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZWxpbmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NpY2QvcGlwZWxpbmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBRUEsK0VBQStFO0FBRy9FLDJDQUEyQztBQUMzQyxtREFBbUQ7QUFFbkQsdUNBQXdDO0FBQ3hDLG1DQUFzQztBQUN0QyxrQ0FBb0Q7QUFDcEQsc0NBQXlDO0FBZ1J6Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBQ0gsTUFBYSxpQkFBa0IsU0FBUSxnQkFBUztJQWE5Qzs7Ozs7Ozs7T0FRRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBNkI7UUFDckUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFeEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQztRQUN2QyxJQUFJLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztRQUVyQixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLFlBQVksQ0FBQztRQUM1QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUkscUJBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUVqRSxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLElBQUksWUFBWSxDQUFDO0lBQ3ZELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGVBQWUsQ0FBQyxLQUF3QjtRQUN0QyxJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQztRQUNwQyxJQUFJLENBQUMsWUFBWTtZQUNmLEtBQUssQ0FBQyxZQUFZO2dCQUNsQixxQkFBVyxDQUFDLHlCQUF5QixDQUFDLElBQUksRUFBRTtvQkFDMUMsY0FBYyxFQUFFLEtB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QyxJQUFJLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFO1lBQ3RDLElBQUksRUFBRSxLQUFLLENBQUMsS0FBSztTQUNsQixDQUFDLENBQUM7UUFFSCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLO1FBQ0gsSUFBSSxDQUFDLFFBQVEsRUFBRSxhQUFhLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLGNBQWMsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFlBQTBCLENBQUM7UUFDekcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUVoRSxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7O0FBeFFILDhDQXlRQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCAqIGFzIGNvZGVwaXBlbGluZSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNvZGVwaXBlbGluZVwiO1xuaW1wb3J0ICogYXMgY29kZXN0YXJub3RpZmljYXRpb25zIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY29kZXN0YXJub3RpZmljYXRpb25zXCI7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCAqIGFzIGttcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWttc1wiO1xuaW1wb3J0ICogYXMgc25zIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc25zXCI7XG5pbXBvcnQgKiBhcyBwaXBlbGluZXMgZnJvbSBcImF3cy1jZGstbGliL3BpcGVsaW5lc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcbmltcG9ydCB7IENJQ0RBY3Rpb25zIH0gZnJvbSBcIi4vYWN0aW9uc1wiO1xuaW1wb3J0IHsgdG9UaXRsZUNhc2UgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgQmFzZVN0YWNrLCBCYXNlU3RhY2tQcm9wcyB9IGZyb20gXCIuLi9iYXNlXCI7XG5pbXBvcnQgeyBDb25maWd1cmF0b3IgfSBmcm9tIFwiLi4vY29uZmlnXCI7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgdGhlIHNvdXJjZSBhY3Rpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU291cmNlQWN0aW9uUHJvcHMge1xuICAvKipcbiAgICogT3ZlcnJpZGUgc291cmNlIGFjdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZUFjdGlvbj86IHBpcGVsaW5lcy5Db2RlUGlwZWxpbmVTb3VyY2U7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBTQ00gcmVwb3NpdG9yeS5cbiAgICovXG4gIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBCcmFuY2ggb2YgdGhlIFNDTSByZXBvc2l0b3J5LlxuICAgKi9cbiAgcmVhZG9ubHkgYnJhbmNoPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIHRoZSBzeW50aCBhY3Rpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3ludGhBY3Rpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBDREsgdmVyc2lvIHRvIHVzZSBkdXJpbmcgdGhlIHN5bnRoIGFjdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJsYXRlc3RcIlxuICAgKi9cbiAgcmVhZG9ubHkgY2RrVmVyc2lvbj86IHN0cmluZztcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIENvZGVBcnRpZmFjdCByZXBvc2l0b3J5IHRvIHB1bGwgYXJ0aWZhY3RzIGZyb20uXG4gICAqL1xuICByZWFkb25seSBjb2RlYXJ0aWZhY3RSZXBvc2l0b3J5Pzogc3RyaW5nO1xuICAvKipcbiAgICogIE5hbWUgb2YgdGhlIENvZGVBcnRpZmFjdCBkb21haW4uXG4gICAqL1xuICByZWFkb25seSBjb2RlYXJ0aWZhY3REb21haW4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBDb2RlQXJ0aWZhY3QgZG9tYWluIG93bmVyIGFjY291bnQuXG4gICAqL1xuICByZWFkb25seSBjb2RlYXJ0aWZhY3REb21haW5Pd25lcj86IHN0cmluZztcbiAgLyoqXG4gICAqIEVudmlyb25tZW50IHZhcmlhYmxlcyB0byBzZXQuXG4gICAqL1xuICByZWFkb25seSBlbnY/OiB7IFtrZXk6IHN0cmluZ106IGFueSB9O1xuICAvKipcbiAgICogQWRkaXRpb25hbCBwb2xpY2llcyB0byBhZGQgdG8gdGhlIHN5bnRoIGFjdGlvbiByb2xlLlxuICAgKi9cbiAgcmVhZG9ubHkgcm9sZVBvbGljeVN0YXRlbWVudHM/OiBpYW0uUG9saWN5U3RhdGVtZW50W107XG4gIC8qKlxuICAgKiAgT3ZlcnJpZGUgc3ludGggYWN0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgc3ludGhBY3Rpb24/OiBwaXBlbGluZXMuQ29kZUJ1aWxkU3RlcDtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgaW5zdGFsbCBjb21tYW5kcy5cbiAgICovXG4gIHJlYWRvbmx5IGFkZGl0aW9uYWxJbnN0YWxsQ29tbWFuZHM/OiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgY29tbWFuZCBsaW5lIGFyZ3VlbWVudHMgdG8gYXBwZW5kIHRvIHRoZSBpbnN0YWxsIGNvbW1hbmQgb2YgdGhlIGBjZGtfbGFuZ2F1Z2VgIHRoYXQgaXMgc3BlY2lmaWVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGNvbW1hbmQgbGluZSBhcmd1bWVudHMgYXJlIGFwcGVuZGVkXG4gICAqL1xuICByZWFkb25seSBjZGtMYW5ndWFnZUNvbW1hbmRMaW5lQXJndW1lbnRzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhZGRpbmcgYW4gYXBwbGljYXRpb24gc3RhZ2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkQXBwbGljYXRpb25TdGFnZVByb3BzIHtcbiAgLyoqXG4gICAqIElkZW50aWZpZXIgb2YgdGhlIHN0YWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhZ2VJZDogc3RyaW5nO1xuICAvKipcbiAgICogQXBwbGljYXRpb24gc3RhZ2UgaW5zdGFuY2UuXG4gICAqL1xuICByZWFkb25seSBzdGFnZTogY2RrLlN0YWdlO1xuICAvKipcbiAgICogQ29uZmlndXJlIG1hbnVhbCBhcHByb3ZhbHMuXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBtYW51YWxBcHByb3ZhbHM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGFkZGluZyBhbiBhcHBsaWNhdGlvbiB3YXZlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFkZEFwcGxpY2F0aW9uV2F2ZVByb3BzIHtcbiAgLyoqXG4gICAqIElkZW50aWZpZXIgb2YgdGhlIHdhdmUuXG4gICAqL1xuICByZWFkb25seSBzdGFnZUlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBBcHBsaWNhdGlvbiBzdGFnZSBpbnN0YW5jZS5cbiAgICovXG4gIHJlYWRvbmx5IHN0YWdlczogY2RrLlN0YWdlW107XG4gIC8qKlxuICAgKiBDb25maWd1cmUgbWFudWFsIGFwcHJvdmFscy5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IG1hbnVhbEFwcHJvdmFscz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYWRkaW5nIGEgc2VjdXJpdHkgbGludCBzdGFnZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGRTZWN1cml0eUxpbnRTdGFnZVByb3BzIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHN0YWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhZ2VOYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogQ2xvdWQgYXNzZW1ibHkgZmlsZSBzZXQgcHJvZHVjZXIuXG4gICAqL1xuICByZWFkb25seSBjbG91ZEFzc2VtYmx5RmlsZVNldD86IHBpcGVsaW5lcy5JRmlsZVNldFByb2R1Y2VyO1xuICAvKipcbiAgICogRmFpbCBDb2RlcGlwZWxpbmUgQnVpbGQgQWN0aW9uIG9uIGZhaWxlZCByZXN1bHRzIGZyb20gQ2ZuTmFnIHNjYW4uXG4gICAqL1xuICByZWFkb25seSBjZm5OYWdGYWlsQnVpbGQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGFkZGluZyBhIHRlc3Qgc3RhZ2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkVGVzdFN0YWdlUHJvcHMge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgc3RhZ2UuXG4gICAqL1xuICByZWFkb25seSBzdGFnZU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBDbG91ZCBhc3NlbWJseSBmaWxlIHNldC5cbiAgICovXG4gIHJlYWRvbmx5IGNsb3VkQXNzZW1ibHlGaWxlU2V0PzogcGlwZWxpbmVzLklGaWxlU2V0UHJvZHVjZXI7XG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGNvbW1hbmRzIHRvIHJ1biBpbiB0aGUgdGVzdC5cbiAgICogQGRlZmF1bHQgXCIuL3Rlc3Quc2hcIlxuICAgKi9cbiAgcmVhZG9ubHkgY29tbWFuZHM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhZGRpbmcgbm90aWZpY2F0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGROb3RpZmljYXRpb25zUHJvcHMge1xuICAvKipcbiAgICogT3ZlcnJpZGUgbm90aWZpY2F0aW9uIHJ1bGUuXG4gICAqL1xuICByZWFkb25seSBub3RpZmljYXRpb25SdWxlPzogY29kZXN0YXJub3RpZmljYXRpb25zLk5vdGlmaWNhdGlvblJ1bGU7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYWRkaW5nIGEgY3VzdG9tIHN0YWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFkZEN1c3RvbVN0YWdlUHJvcHMge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgc3RhZ2UuXG4gICAqL1xuICByZWFkb25seSBzdGFnZU5hbWU6IHN0cmluZztcbiAgLyoqXG4gICAqIFN0ZXBzIHRvIGFkZCB0byB0aGlzIHN0YWdlLiBMaXN0IG9mIFN0ZXAgb2JqZWN0cy5cbiAgICpcbiAgICogU2VlIFtEb2N1bWVudGF0aW9uIG9uIGF3c19jZGsucGlwZWxpbmVzLlN0ZXBdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jZGsvYXBpL3YxL3B5dGhvbi9hd3NfY2RrLnBpcGVsaW5lcy9TdGVwLmh0bWwpXG4gICAqIGZvciBtb3JlIGRldGFpbC5cbiAgICovXG4gIHJlYWRvbmx5IHN0ZXBzOiBwaXBlbGluZXMuU3RlcFtdO1xufVxuXG4vKipcbiAqIENJQ0QgUGlwZWxpbmUgU3RhY2sgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDSUNEUGlwZWxpbmVTdGFja1Byb3BzIGV4dGVuZHMgQmFzZVN0YWNrUHJvcHMge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgcGlwZWxpbmUuXG4gICAqL1xuICByZWFkb25seSBwaXBlbGluZU5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBMYW5ndWFnZSBvZiB0aGUgQ0RLIGNvbnN0cnVjdCBkZWZpbml0aW9ucy5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJ0eXBlc2NyaXB0XCJcbiAgICovXG4gIHJlYWRvbmx5IGNka0xhbmd1YWdlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFkZGl0aW9uYWwgcHJvcGVydGllcyBmb3IgYnVpbGRpbmcgdGhlIENvZGVQaXBlbGluZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGRpdGlvbmFsUGlwZWxpbmVQcm9wcyB7XG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGN1c3RvbWl6YXRpb25zIHRvIGFwcGx5IHRvIHRoZSBhc3NldCBwdWJsaXNoaW5nIENvZGVCdWlsZCBwcm9qZWN0c1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE9ubHkgYGNvZGVCdWlsZERlZmF1bHRzYCBhcmUgYXBwbGllZFxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRQdWJsaXNoaW5nQ29kZUJ1aWxkRGVmYXVsdHM/OiBwaXBlbGluZXMuQ29kZUJ1aWxkT3B0aW9ucztcbiAgLyoqXG4gICAqIENESyBDTEkgdmVyc2lvbiB0byB1c2UgaW4gc2VsZi1tdXRhdGlvbiBhbmQgYXNzZXQgcHVibGlzaGluZyBzdGVwc1xuICAgKlxuICAgKiBAZGVmYXVsdCBsYXRlc3QgdmVyc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgY2xpVmVyc2lvbj86IHN0cmluZztcbiAgLyoqXG4gICAqIEN1c3RvbWl6ZSB0aGUgQ29kZUJ1aWxkIHByb2plY3RzIGNyZWF0ZWQgZm9yIHRoaXMgcGlwZWxpbmVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgcHJvamVjdHMgcnVuIG5vbi1wcml2aWxlZ2VkIGJ1aWxkLCBTTUFMTCBpbnN0YW5jZSwgTGludXhCdWlsZEltYWdlLlNUQU5EQVJEXzZfMFxuICAgKi9cbiAgcmVhZG9ubHkgY29kZUJ1aWxkRGVmYXVsdHM/OiBwaXBlbGluZXMuQ29kZUJ1aWxkT3B0aW9ucztcbiAgLyoqXG4gICAqIEFuIGV4aXN0aW5nIFBpcGVsaW5lIHRvIGJlIHJldXNlZCBhbmQgYnVpbHQgdXBvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhIG5ldyB1bmRlcmx5aW5nIHBpcGVsaW5lIGlzIGNyZWF0ZWQuXG4gICAqL1xuICByZWFkb25seSBjb2RlUGlwZWxpbmU/OiBjb2RlcGlwZWxpbmUuUGlwZWxpbmU7XG4gIC8qKlxuICAgKiBBIGxpc3Qgb2YgY3JlZGVudGlhbHMgdXNlZCB0byBhdXRoZW50aWNhdGUgdG8gRG9ja2VyIHJlZ2lzdHJpZXMuXG4gICAqXG4gICAqIFNwZWNpZnkgYW55IGNyZWRlbnRpYWxzIG5lY2Vzc2FyeSB3aXRoaW4gdGhlIHBpcGVsaW5lIHRvIGJ1aWxkLCBzeW50aCwgdXBkYXRlLCBvciBwdWJsaXNoIGFzc2V0cy5cbiAgICpcbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIHJlYWRvbmx5IGRvY2tlckNyZWRlbnRpYWxzPzogcGlwZWxpbmVzLkRvY2tlckNyZWRlbnRpYWxbXTtcbiAgLyoqXG4gICAqIEVuYWJsZSBEb2NrZXIgZm9yIHRoZSBzZWxmLW11dGF0ZSBzdGVwXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkb2NrZXJFbmFibGVkRm9yU2VsZk11dGF0aW9uPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIEVuYWJsZSBEb2NrZXIgZm9yIHRoZSAnc3ludGgnIHN0ZXBcbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGRvY2tlckVuYWJsZWRGb3JTeW50aD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBQdWJsaXNoIGFzc2V0cyBpbiBtdWx0aXBsZSBDb2RlQnVpbGQgcHJvamVjdHNcblxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBwdWJsaXNoQXNzZXRzSW5QYXJhbGxlbD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBSZXVzZSB0aGUgc2FtZSBjcm9zcyByZWdpb24gc3VwcG9ydCBzdGFjayBmb3IgYWxsIHBpcGVsaW5lcyBpbiB0aGUgQXBwLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRydWUgKFVzZSB0aGUgc2FtZSBzdXBwb3J0IHN0YWNrIGZvciBhbGwgcGlwZWxpbmVzIGluIEFwcClcbiAgICovXG4gIHJlYWRvbmx5IHJldXNlQ3Jvc3NSZWdpb25TdXBwb3J0U3RhY2tzPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHBpcGVsaW5lIHdpbGwgdXBkYXRlIGl0c2VsZlxuICAgKlxuICAgKiBUaGlzIG5lZWRzIHRvIGJlIHNldCB0byBgdHJ1ZWAgdG8gYWxsb3cgdGhlIHBpcGVsaW5lIHRvIHJlY29uZmlndXJlXG4gICAqIGl0c2VsZiB3aGVuIGFzc2V0cyBvciBzdGFnZXMgYXJlIGJlaW5nIGFkZGVkIHRvIGl0LCBhbmQgYHRydWVgIGlzIHRoZVxuICAgKiByZWNvbW1lbmRlZCBzZXR0aW5nLlxuICAgKlxuICAgKiBZb3UgY2FuIHRlbXBvcmFyaWx5IHNldCB0aGlzIHRvIGBmYWxzZWAgd2hpbGUgeW91IGFyZSBpdGVyYXRpbmdcbiAgICogb24gdGhlIHBpcGVsaW5lIGl0c2VsZiBhbmQgcHJlZmVyIHRvIGRlcGxveSBjaGFuZ2VzIHVzaW5nIGBjZGsgZGVwbG95YC5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgc2VsZk11dGF0aW9uPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgY3VzdG9taXphdGlvbnMgdG8gYXBwbHkgdG8gdGhlIHNlbGYgbXV0YXRpb24gQ29kZUJ1aWxkIHByb2plY3RzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gT25seSBgY29kZUJ1aWxkRGVmYXVsdHNgIGFyZSBhcHBsaWVkXG4gICAqL1xuICByZWFkb25seSBzZWxmTXV0YXRpb25Db2RlQnVpbGREZWZhdWx0cz86IHBpcGVsaW5lcy5Db2RlQnVpbGRPcHRpb25zO1xuICAvKipcbiAgICogQWRkaXRpb25hbCBjdXN0b21pemF0aW9ucyB0byBhcHBseSB0byB0aGUgc3ludGhlc2l6ZSBDb2RlQnVpbGQgcHJvamVjdHNcbiAgICpcbiAgICogQGRlZmF1bHQgLSBPbmx5IGBjb2RlQnVpbGREZWZhdWx0c2AgYXJlIGFwcGxpZWRcbiAgICovXG4gIHJlYWRvbmx5IHN5bnRoQ29kZUJ1aWxkRGVmYXVsdHM/OiBwaXBlbGluZXMuQ29kZUJ1aWxkT3B0aW9ucztcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBzdGFjayB0aGF0IGNvbnRhaW5zIERESyBDb250aW51b3VzIEludGVncmF0aW9uIGFuZCBEZWxpdmVyeSAoQ0kvQ0QpIHBpcGVsaW5lLlxuXG4gIFRoZSBwaXBlbGluZSBpcyBiYXNlZCBvblxuICBbQ0RLIHNlbGYtbXV0YXRpbmcgcGlwZWxpbmVdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jZGsvYXBpL3YyL2RvY3MvYXdzLWNkay1saWIucGlwZWxpbmVzLXJlYWRtZS5odG1sKVxuICBidXQgaW5jbHVkZXMgc2V2ZXJhbCBEREstc3BlY2lmaWMgZmVhdHVyZXMsIGluY2x1ZGluZzpcblxuICAtIEFiaWxpdHkgdG8gY29uZmlndXJlIHNvbWUgcHJvcGVydGllcyB2aWEgSlNPTiBjb25maWcgZS5nLiBtYW51YWwgYXBwcm92YWxzIGZvciBhcHBsaWNhdGlvbiBzdGFnZXNcbiAgLSBEZWZhdWx0cyBmb3Igc291cmNlL3N5bnRoIC0gQ29kZUNvbW1pdCAmIGNkayBzeW50aCwgd2l0aCBhYmlsaXR5IHRvIG92ZXJyaWRlIHRoZW1cbiAgLSBBYmlsaXR5IHRvIGNvbm5lY3QgdG8gcHJpdmF0ZSBhcnRpZmFjdG9yeSB0byBwdWxsIGFydGlmYWN0cyBmcm9tIGF0IHN5bnRoXG4gIC0gU2VjdXJpdHkgYmVzdCBwcmFjdGljZXMgLSBlbnN1cmVzIHBpcGVsaW5lIGJ1Y2tldHMgYmxvY2sgbm9uLVNTTCwgYW5kIGFyZSBLTVMtZW5jcnlwdGVkIHdpdGggcm90YXRlZCBrZXlzXG4gIC0gQnVpbGRlciBpbnRlcmZhY2UgdG8gYXZvaWQgY2h1bmt5IGNvbnN0cnVjdG9yIG1ldGhvZHNcblxuICBUaGUgdXNlciBzaG91bGQgYmUgYWJsZSB0byByZXVzZSB0aGUgcGlwZWxpbmUgaW4gbXVsdGlwbGUgRERLIGFwcGxpY2F0aW9ucyBob3BpbmcgdG8gc2F2ZSBMT0MuXG5cbiAgQGV4YW1wbGVcbiAgY29uc3Qgc3RhY2sgPSBuZXcgQ0lDRFBpcGVsaW5lU3RhY2soYXBwLCBcImR1bW15LXBpcGVsaW5lXCIsIHsgZW52aXJvbm1lbnRJZDogXCJkZXZcIiwgcGlwZWxpbmVOYW1lOiBcImR1bW15LXBpcGVsaW5lXCIgfSlcbiAgICAuYWRkU291cmNlQWN0aW9uKHsgcmVwb3NpdG9yeU5hbWU6IFwiZHVtbXktcmVwb3NpdG9yeVwiIH0pXG4gICAgLmFkZFN5bnRoQWN0aW9uKClcbiAgICAuYnVpbGRQaXBlbGluZSgpXG4gICAgLmFkZF9jaGVja3MoKVxuICAgIC5hZGRTdGFnZSh7IHN0YWdlSWQ6IFwiZGV2XCIsIHN0YWdlOiBkZXZTdGFnZSwgbWFudWFsQXBwcm92YWxzOiB0cnVlIH0pXG4gICAgLnN5bnRoKClcbiAgICAuYWRkX25vdGlmaWNhdGlvbnMoKTtcbiAqL1xuZXhwb3J0IGNsYXNzIENJQ0RQaXBlbGluZVN0YWNrIGV4dGVuZHMgQmFzZVN0YWNrIHtcbiAgcmVhZG9ubHkgZW52aXJvbm1lbnRJZD86IHN0cmluZztcbiAgcmVhZG9ubHkgcGlwZWxpbmVOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBwaXBlbGluZUlkPzogc3RyaW5nO1xuICByZWFkb25seSBjb25maWc6IENvbmZpZ3VyYXRvcjtcbiAgcmVhZG9ubHkgY2RrTGFuZ3VhZ2U6IHN0cmluZztcblxuICBwdWJsaWMgbm90aWZpY2F0aW9uUnVsZT86IGNvZGVzdGFybm90aWZpY2F0aW9ucy5Ob3RpZmljYXRpb25SdWxlO1xuICBwdWJsaWMgcGlwZWxpbmU/OiBwaXBlbGluZXMuQ29kZVBpcGVsaW5lO1xuICBwdWJsaWMgcGlwZWxpbmVLZXk/OiBrbXMuQ2ZuS2V5O1xuICBwdWJsaWMgc291cmNlQWN0aW9uPzogcGlwZWxpbmVzLkNvZGVQaXBlbGluZVNvdXJjZTtcbiAgcHVibGljIHN5bnRoQWN0aW9uPzogcGlwZWxpbmVzLkNvZGVCdWlsZFN0ZXA7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgQ0lDRCBQaXBlbGluZSBzdGFjay5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFBhcmVudCBvZiB0aGlzIHN0YWNrLCB1c3VhbGx5IGFuIGBBcHBgIG9yIGEgYFN0YWdlYCwgYnV0IGNvdWxkIGJlIGFueSBjb25zdHJ1Y3QuXG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0IElEIG9mIHRoaXMgc3RhY2suIElmIGBzdGFja05hbWVgIGlzIG5vdCBleHBsaWNpdGx5XG4gICAqIGRlZmluZWQsIHRoaXMgaWQgKGFuZCBhbnkgcGFyZW50IElEcykgd2lsbCBiZSB1c2VkIHRvIGRldGVybWluZSB0aGVcbiAgICogcGh5c2ljYWwgSUQgb2YgdGhlIHN0YWNrLlxuICAgKiBAcGFyYW0gcHJvcHMgU3RhY2sgcHJvcGVydGllcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBDSUNEUGlwZWxpbmVTdGFja1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICB0aGlzLmVudmlyb25tZW50SWQgPSBwcm9wcy5lbnZpcm9ubWVudElkO1xuICAgIHRoaXMucGlwZWxpbmVOYW1lID0gcHJvcHMucGlwZWxpbmVOYW1lO1xuICAgIHRoaXMucGlwZWxpbmVJZCA9IGlkO1xuXG4gICAgY29uc3QgY29uZmlnID0gcHJvcHMuY29uZmlnID8/IFwiLi9kZGsuanNvblwiO1xuICAgIHRoaXMuY29uZmlnID0gbmV3IENvbmZpZ3VyYXRvcih0aGlzLCBjb25maWcsIHRoaXMuZW52aXJvbm1lbnRJZCk7XG5cbiAgICB0aGlzLmNka0xhbmd1YWdlID0gcHJvcHMuY2RrTGFuZ3VhZ2UgPz8gXCJ0eXBlc2NyaXB0XCI7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHNvdXJjZSBhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBTb3VyY2UgYWN0aW9uIHByb3BlcnRpZXMuXG4gICAqIEByZXR1cm5zIHJlZmVyZW5jZSB0byB0aGlzIHBpcGVsaW5lLlxuICAgKi9cbiAgYWRkU291cmNlQWN0aW9uKHByb3BzOiBTb3VyY2VBY3Rpb25Qcm9wcykge1xuICAgIHZhciBicmFuY2ggPSBwcm9wcy5icmFuY2ggPz8gXCJtYWluXCI7XG4gICAgdGhpcy5zb3VyY2VBY3Rpb24gPVxuICAgICAgcHJvcHMuc291cmNlQWN0aW9uIHx8XG4gICAgICBDSUNEQWN0aW9ucy5nZXRDb2RlQ29tbWl0U291cmNlQWN0aW9uKHRoaXMsIHtcbiAgICAgICAgcmVwb3NpdG9yeU5hbWU6IHByb3BzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICBicmFuY2g6IGJyYW5jaCxcbiAgICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHRoZSBwaXBlbGluZSBzdHJ1Y3R1cmUuXG4gICAqIEBwYXJhbSBwcm9wcyBBZGRpdGlvbmFsIHBpcGVsaW5lIHByb3BlcnRpZXMuXG4gICAqIEByZXR1cm5zIHJlZmVyZW5jZSB0byB0aGlzIHBpcGVsaW5lLlxuICAgKi9cbiAgYnVpbGRQaXBlbGluZShwcm9wczogQWRkaXRpb25hbFBpcGVsaW5lUHJvcHMgPSB7fSkge1xuICAgIGlmICh0aGlzLnN5bnRoQWN0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlBpcGVsaW5lIGNhbm5vdCBiZSBidWlsdCB3aXRob3V0IGEgc3ludGggYWN0aW9uLlwiKTtcbiAgICB9XG4gICAgdGhpcy5waXBlbGluZSA9IG5ldyBwaXBlbGluZXMuQ29kZVBpcGVsaW5lKHRoaXMsIFwiRERLQ29kZVBpcGVsaW5lXCIsIHtcbiAgICAgIHN5bnRoOiB0aGlzLnN5bnRoQWN0aW9uLFxuICAgICAgY3Jvc3NBY2NvdW50S2V5czogdHJ1ZSxcbiAgICAgIHBpcGVsaW5lTmFtZTogdGhpcy5waXBlbGluZU5hbWUsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgc3ludGggYWN0aW9uLiBEdXJpbmcgc3ludGggY2FuIGNvbm5lY3QgYW5kIHB1bGwgYXJ0aWZhY3RzIGZyb20gYSBwcml2YXRlIGFydGlmYWN0b3J5LlxuICAgKiBAcGFyYW0gcHJvcHMgU3ludGggYWN0aW9uIHByb3BlcnRpZXMuXG4gICAqIEByZXR1cm5zIHJlZmVyZW5jZSB0byB0aGlzIHBpcGVsaW5lLlxuICAgKi9cbiAgYWRkU3ludGhBY3Rpb24ocHJvcHM6IFN5bnRoQWN0aW9uUHJvcHMgPSB7fSkge1xuICAgIGNvbnN0IGxhbmd1YWdlSW5zdGFsbENvbW1hbmRzOiBhbnkgPSB7XG4gICAgICB0eXBlc2NyaXB0OiBcIm5wbSBpbnN0YWxsXCIsXG4gICAgICBweXRob246IFwicGlwIGluc3RhbGwgLXIgcmVxdWlyZW1lbnRzLnR4dFwiLFxuICAgIH07XG5cbiAgICBsZXQgbGFuZ3VhZ2VJbnN0YWxsQ29tbWFuZCA9IGxhbmd1YWdlSW5zdGFsbENvbW1hbmRzW3RoaXMuY2RrTGFuZ3VhZ2VdO1xuICAgIGlmIChwcm9wcy5jZGtMYW5ndWFnZUNvbW1hbmRMaW5lQXJndW1lbnRzKSB7XG4gICAgICBmb3IgKGNvbnN0IFthcmd1bWVudCwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHByb3BzLmNka0xhbmd1YWdlQ29tbWFuZExpbmVBcmd1bWVudHMpKSB7XG4gICAgICAgIGxhbmd1YWdlSW5zdGFsbENvbW1hbmQgKz0gYCAke2FyZ3VtZW50fSAke3ZhbHVlfWA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zeW50aEFjdGlvbiA9XG4gICAgICBwcm9wcy5zeW50aEFjdGlvbiB8fFxuICAgICAgQ0lDREFjdGlvbnMuZ2V0U3ludGhBY3Rpb24oe1xuICAgICAgICBjb2RlUGlwZWxpbmVTb3VyY2U6IHRoaXMuc291cmNlQWN0aW9uLFxuICAgICAgICBjZGtWZXJzaW9uOiBwcm9wcy5jZGtWZXJzaW9uLFxuICAgICAgICBwYXJ0aXRpb246IHRoaXMucGFydGl0aW9uLFxuICAgICAgICByZWdpb246IHRoaXMucmVnaW9uLFxuICAgICAgICBhY2NvdW50OiB0aGlzLmFjY291bnQsXG4gICAgICAgIGVudjogcHJvcHMuZW52LFxuICAgICAgICByb2xlUG9saWN5U3RhdGVtZW50czogcHJvcHMucm9sZVBvbGljeVN0YXRlbWVudHMsXG4gICAgICAgIGNvZGVhcnRpZmFjdFJlcG9zaXRvcnk6IHByb3BzLmNvZGVhcnRpZmFjdFJlcG9zaXRvcnksXG4gICAgICAgIGNvZGVhcnRpZmFjdERvbWFpbjogcHJvcHMuY29kZWFydGlmYWN0RG9tYWluLFxuICAgICAgICBjb2RlYXJ0aWZhY3REb21haW5Pd25lcjogcHJvcHMuY29kZWFydGlmYWN0RG9tYWluT3duZXIsXG4gICAgICAgIGFkZGl0aW9uYWxJbnN0YWxsQ29tbWFuZHM6IHByb3BzLmFkZGl0aW9uYWxJbnN0YWxsQ29tbWFuZHNcbiAgICAgICAgICA/IFtsYW5ndWFnZUluc3RhbGxDb21tYW5kXS5jb25jYXQocHJvcHMuYWRkaXRpb25hbEluc3RhbGxDb21tYW5kcylcbiAgICAgICAgICA6IFtsYW5ndWFnZUluc3RhbGxDb21tYW5kXSxcbiAgICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhcHBsaWNhdGlvbiBzdGFnZSB0byB0aGUgQ0lDRCBwaXBlbGluZS4gVGhpcyBzdGFnZSBkZXBsb3lzIHlvdXIgYXBwbGljYXRpb24gaW5mcmFzdHJ1Y3R1cmUuXG4gICAqIEBwYXJhbSBwcm9wcyBBcHBsaWNhdGlvbiBzdGFnZSBwcm9wZXJ0aWVzLlxuICAgKiBAcmV0dXJucyByZWZlcmVuY2UgdG8gdGhpcyBwaXBlbGluZS5cbiAgICovXG4gIGFkZFN0YWdlKHByb3BzOiBBZGRBcHBsaWNhdGlvblN0YWdlUHJvcHMpIHtcbiAgICBpZiAodGhpcy5waXBlbGluZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJgLmJ1aWxkUGlwZWxpbmUoKWAgbmVlZHMgdG8gYmUgY2FsbGVkIGZpcnN0IGJlZm9yZSBhZGRpbmcgYXBwbGljYXRpb24gc3RhZ2VzIHRvIHRoZSBwaXBlbGluZS5cIik7XG4gICAgfVxuICAgIGNvbnN0IG1hbnVhbEFwcHJvdmFscyA9IHByb3BzLm1hbnVhbEFwcHJvdmFscyA/PyB0aGlzLmNvbmZpZy5nZXRDb25maWdBdHRyaWJ1dGUoXCJtYW51YWxfYXBwcm92YWxzXCIpID8/IGZhbHNlO1xuXG4gICAgaWYgKG1hbnVhbEFwcHJvdmFscykge1xuICAgICAgdGhpcy5waXBlbGluZT8uYWRkU3RhZ2UocHJvcHMuc3RhZ2UsIHtcbiAgICAgICAgcHJlOiBbbmV3IHBpcGVsaW5lcy5NYW51YWxBcHByb3ZhbFN0ZXAoXCJQcm9tb3RlVG9cIiArIHRvVGl0bGVDYXNlKHByb3BzLnN0YWdlSWQpKV0sXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5waXBlbGluZT8uYWRkU3RhZ2UocHJvcHMuc3RhZ2UsIHt9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgbXVsdGlwbGUgYXBwbGljYXRpb24gc3RhZ2VzIGluIHBhcmFsbGVsIHRvIHRoZSBDSUNEIHBpcGVsaW5lLlxuICAgKiBAcGFyYW0gcHJvcHMgQXBwbGljYXRpb24gd2F2ZSBwcm9wZXJ0aWVzLlxuICAgKiBAcmV0dXJucyByZWZlcmVuY2UgdG8gdGhpcyBwaXBlbGluZS5cbiAgICovXG4gIGFkZFdhdmUocHJvcHM6IEFkZEFwcGxpY2F0aW9uV2F2ZVByb3BzKSB7XG4gICAgaWYgKHRoaXMucGlwZWxpbmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYC5idWlsZFBpcGVsaW5lKClgIG5lZWRzIHRvIGJlIGNhbGxlZCBmaXJzdCBiZWZvcmUgYWRkaW5nIGFwcGxpY2F0aW9uIHN0YWdlcyB0byB0aGUgcGlwZWxpbmUuXCIpO1xuICAgIH1cbiAgICBjb25zdCBtYW51YWxBcHByb3ZhbHMgPSBwcm9wcy5tYW51YWxBcHByb3ZhbHMgPz8gdGhpcy5jb25maWcuZ2V0Q29uZmlnQXR0cmlidXRlKFwibWFudWFsX2FwcHJvdmFsc1wiKSA/PyBmYWxzZTtcblxuICAgIHZhciB3YXZlID0gbmV3IHBpcGVsaW5lcy5XYXZlKHByb3BzLnN0YWdlSWQpO1xuICAgIGlmIChtYW51YWxBcHByb3ZhbHMpIHtcbiAgICAgIHdhdmUuYWRkUHJlKG5ldyBwaXBlbGluZXMuTWFudWFsQXBwcm92YWxTdGVwKFwiUHJvbW90ZVRvXCIgKyB0b1RpdGxlQ2FzZShwcm9wcy5zdGFnZUlkKSkpO1xuICAgIH1cblxuICAgIHByb3BzLnN0YWdlcy5mb3JFYWNoKChzdGFnZSkgPT4ge1xuICAgICAgd2F2ZS5hZGRTdGFnZShzdGFnZSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnBpcGVsaW5lPy5hZGRXYXZlKHByb3BzLnN0YWdlSWQsIHdhdmUpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBsaW50aW5nIC0gY2ZuLW5hZywgYW5kIGJhbmRpdC5cbiAgICogQHBhcmFtIHByb3BzIFNlY3VyaXR5IGxpbnQgcHJvcGVydGllcy5cbiAgICogQHJldHVybnMgcmVmZXJlbmNlIHRvIHRoaXMgcGlwZWxpbmUuXG4gICAqL1xuICBhZGRTZWN1cml0eUxpbnRTdGFnZShwcm9wczogQWRkU2VjdXJpdHlMaW50U3RhZ2VQcm9wcykge1xuICAgIGlmICh0aGlzLnNvdXJjZUFjdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTb3VyY2UgQWN0aW9uIE11c3QgQmUgY29uZmlndXJlZCBiZWZvcmUgY2FsbGluZyB0aGlzIG1ldGhvZC5cIik7XG4gICAgfVxuICAgIGlmICh0aGlzLnBpcGVsaW5lPy5jbG91ZEFzc2VtYmx5RmlsZVNldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBjbG91ZEFzc2VtYmx5RmlsZVNldCBjb25maWd1cmVkLCBzb3VyY2UgYWN0aW9uIG5lZWRzIHRvIGJlIGNvbmZpZ3VyZWQgZm9yIHRoaXMgcGlwZWxpbmUuXCIpO1xuICAgIH1cblxuICAgIHZhciBzdGFnZU5hbWUgPSBwcm9wcy5zdGFnZU5hbWUgPz8gXCJTZWN1cml0eUxpbnRcIjtcbiAgICB2YXIgY2xvdWRBc3NlbWJseUZpbGVTZXQgPSBwcm9wcy5jbG91ZEFzc2VtYmx5RmlsZVNldCA/PyB0aGlzLnBpcGVsaW5lPy5jbG91ZEFzc2VtYmx5RmlsZVNldDtcblxuICAgIHRoaXMucGlwZWxpbmU/LmFkZFdhdmUoc3RhZ2VOYW1lLCB7XG4gICAgICBwb3N0OiBbXG4gICAgICAgIENJQ0RBY3Rpb25zLmdldENmbk5hZ0FjdGlvbihjbG91ZEFzc2VtYmx5RmlsZVNldCwgXCJDRk5OYWdcIiwgcHJvcHMuY2ZuTmFnRmFpbEJ1aWxkKSxcbiAgICAgICAgQ0lDREFjdGlvbnMuZ2V0QmFuZGl0QWN0aW9uKHRoaXMuc291cmNlQWN0aW9uKSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgdGVzdCAtIGUuZy4gcHl0ZXN0LlxuICAgKiBAcGFyYW0gcHJvcHMgVGVzdCBzdGFnZSBwcm9wZXJ0aWVzLlxuICAgKiBAcmV0dXJucyByZWZlcmVuY2UgdG8gdGhpcyBwaXBlbGluZS5cbiAgICovXG4gIGFkZFRlc3RTdGFnZShwcm9wczogQWRkVGVzdFN0YWdlUHJvcHMpIHtcbiAgICB2YXIgc3RhZ2VOYW1lID0gcHJvcHMuc3RhZ2VOYW1lID8/IFwiVGVzdHNcIjtcbiAgICB2YXIgY2xvdWRBc3NlbWJseUZpbGVTZXQgPSBwcm9wcy5jbG91ZEFzc2VtYmx5RmlsZVNldCA/PyB0aGlzLnBpcGVsaW5lPy5jbG91ZEFzc2VtYmx5RmlsZVNldDtcbiAgICB2YXIgY29tbWFuZHMgPSBwcm9wcy5jb21tYW5kcyA/PyBbXCIuL3Rlc3Quc2hcIl07XG5cbiAgICBpZiAoY2xvdWRBc3NlbWJseUZpbGVTZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gY2xvdWRBc3NlbWJseUZpbGVTZXQgY29uZmlndXJlZCwgc291cmNlIGFjdGlvbiBuZWVkcyB0byBiZSBjb25maWd1cmVkIGZvciB0aGlzIHBpcGVsaW5lLlwiKTtcbiAgICB9XG5cbiAgICB0aGlzLnBpcGVsaW5lPy5hZGRXYXZlKHN0YWdlTmFtZSB8fCBcIlRlc3RzXCIsIHtcbiAgICAgIHBvc3Q6IFtDSUNEQWN0aW9ucy5nZXRUZXN0c0FjdGlvbihjbG91ZEFzc2VtYmx5RmlsZVNldCwgY29tbWFuZHMpXSxcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBwaXBlbGluZSBub3RpZmljYXRpb25zLlxuICAgKiBDcmVhdGUgbm90aWZpY2F0aW9uIHJ1bGUgdGhhdCBzZW5kcyBldmVudHMgdG8gdGhlIHNwZWNpZmllZCBTTlMgdG9waWMuXG4gICAqIEBwYXJhbSBwcm9wcyBOb3RpZmljYXRpb24gcHJvcGVydGllcy5cbiAgICogQHJldHVybnMgcmVmZXJlbmNlIHRvIHRoaXMgcGlwZWxpbmUuXG4gICAqL1xuICBhZGROb3RpZmljYXRpb25zKHByb3BzOiBBZGROb3RpZmljYXRpb25zUHJvcHMgPSB7fSkge1xuICAgIGlmICh0aGlzLnBpcGVsaW5lID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcImAuYnVpbGRQaXBlbGluZSgpYCBuZWVkcyB0byBiZSBjYWxsZWQgZmlyc3QgYmVmb3JlIGFkZGluZyBub3RpZmljYXRpb25zIHRvIHRoZSBwaXBlbGluZS5cIik7XG4gICAgfVxuXG4gICAgY29uc3QgdG9waWMgPVxuICAgICAgdGhpcy5lbnZpcm9ubWVudElkICYmIHRoaXMuY29uZmlnLmdldENvbmZpZ0F0dHJpYnV0ZShcIm5vdGlmaWNhdGlvbnNfdG9waWNfYXJuXCIpXG4gICAgICAgID8gc25zLlRvcGljLmZyb21Ub3BpY0FybihcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBcIkV4ZWN1dGlvbkZhaWxlZE5vdGlmaWNhdGlvbnNcIixcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmdldENvbmZpZ0F0dHJpYnV0ZShcIm5vdGlmaWNhdGlvbnNfdG9waWNfYXJuXCIpLFxuICAgICAgICAgIClcbiAgICAgICAgOiBuZXcgc25zLlRvcGljKHRoaXMsIFwiRXhlY3V0aW9uRmFpbGVkTm90aWZpY2F0aW9uc1wiKTtcbiAgICB0aGlzLm5vdGlmaWNhdGlvblJ1bGUgPVxuICAgICAgcHJvcHMubm90aWZpY2F0aW9uUnVsZSA/P1xuICAgICAgbmV3IGNvZGVzdGFybm90aWZpY2F0aW9ucy5Ob3RpZmljYXRpb25SdWxlKHRoaXMsIFwiTm90aWZpY2F0aW9uXCIsIHtcbiAgICAgICAgZGV0YWlsVHlwZTogY29kZXN0YXJub3RpZmljYXRpb25zLkRldGFpbFR5cGUuQkFTSUMsXG4gICAgICAgIGV2ZW50czogW1wiY29kZXBpcGVsaW5lLXBpcGVsaW5lLXBpcGVsaW5lLWV4ZWN1dGlvbi1mYWlsZWRcIl0sXG4gICAgICAgIHNvdXJjZTogdGhpcy5waXBlbGluZT8ucGlwZWxpbmUsXG4gICAgICAgIHRhcmdldHM6IFt0b3BpY10sXG4gICAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgY2hlY2tzIHRvIHRoZSBwaXBlbGluZSAoZS5nLiBsaW50aW5nLCBzZWN1cml0eSwgdGVzdHMuLi4pLlxuICAgKiBAcmV0dXJucyByZWZlcmVuY2UgdG8gdGhpcyBwaXBlbGluZS5cbiAgICovXG4gIGFkZENoZWNrcygpIHtcbiAgICB0aGlzLmFkZFNlY3VyaXR5TGludFN0YWdlKHt9KTtcbiAgICB0aGlzLmFkZFRlc3RTdGFnZSh7fSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGN1c3RvbSBzdGFnZSB0byB0aGUgcGlwZWxpbmUuXG4gICAqIEBwYXJhbSBwcm9wcyBQcm9wZXJ0aWVzIGZvciBhZGRpbmcgYSBjdXN0b20gc3RhZ2UuXG4gICAqIEByZXR1cm5zIHJlZmVyZW5jZSB0byB0aGlzIHBpcGVsaW5lLlxuICAgKi9cbiAgYWRkQ3VzdG9tU3RhZ2UocHJvcHM6IEFkZEN1c3RvbVN0YWdlUHJvcHMpIHtcbiAgICB0aGlzLnBpcGVsaW5lPy5hZGRXYXZlKHByb3BzLnN0YWdlTmFtZSwge1xuICAgICAgcG9zdDogcHJvcHMuc3RlcHMsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTeW50aGVzaXplIHRoZSBwaXBlbGluZS5cbiAgICogQHJldHVybnMgcmVmZXJlbmNlIHRvIHRoaXMgcGlwZWxpbmUuXG4gICAqL1xuICBzeW50aCgpIHtcbiAgICB0aGlzLnBpcGVsaW5lPy5idWlsZFBpcGVsaW5lKCk7XG4gICAgdGhpcy5waXBlbGluZUtleSA9IHRoaXMucGlwZWxpbmU/LnBpcGVsaW5lLmFydGlmYWN0QnVja2V0LmVuY3J5cHRpb25LZXk/Lm5vZGUuZGVmYXVsdENoaWxkIGFzIGttcy5DZm5LZXk7XG4gICAgdGhpcy5waXBlbGluZUtleS5hZGRQcm9wZXJ0eU92ZXJyaWRlKFwiRW5hYmxlS2V5Um90YXRpb25cIiwgdHJ1ZSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxufVxuIl19