@cdklabs/cdk-amazonmq
Version:
<!--BEGIN STABILITY BANNER-->
160 lines • 25.8 kB
JavaScript
;
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RabbitMqCustomResource = exports.RabbitMqCustomResourcePolicy = exports.HttpMethods = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
const crypto_1 = require("crypto");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
const custom_resources_1 = require("aws-cdk-lib/custom-resources");
const constructs_1 = require("constructs");
const rabbitmq_custom_resource_singleton_function_1 = require("./rabbitmq-custom-resource-singleton-function");
const HASH_LEN = 16;
/**
* All http request methods
*/
var HttpMethods;
(function (HttpMethods) {
HttpMethods["GET"] = "GET";
HttpMethods["POST"] = "POST";
HttpMethods["PUT"] = "PUT";
HttpMethods["DELETE"] = "DELETE";
})(HttpMethods || (exports.HttpMethods = HttpMethods = {}));
/**
* The IAM Policy that will be applied to the calls.
*/
class RabbitMqCustomResourcePolicy {
/**
* Explicit IAM Policy Statements.
*
* @param statements the statements to propagate to the SDK calls.
*/
static fromStatements(statements) {
return new RabbitMqCustomResourcePolicy(statements);
}
/**
* @param statements statements for explicit policy.
* @param resources resources for auto-generated from SDK calls.
*/
constructor(statements) {
this.statements = statements;
}
}
exports.RabbitMqCustomResourcePolicy = RabbitMqCustomResourcePolicy;
_a = JSII_RTTI_SYMBOL_1;
RabbitMqCustomResourcePolicy[_a] = { fqn: "@cdklabs/cdk-amazonmq.RabbitMqCustomResourcePolicy", version: "0.1.8" };
/**
* Use this constant to configure access to any resource.
*/
RabbitMqCustomResourcePolicy.ANY_RESOURCE = ["*"];
/**
* @experimental
*
* Defines a custom resource that is materialized using specific RabbitMQ Management HTTP API calls.
*
* Use this to interact with the Amazon MQ for RabbitMQ broker. You can specify exactly which calls are invoked for the 'CREATE', 'UPDATE' and 'DELETE' life cycle events.
*/
class RabbitMqCustomResource extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
if (!props.onCreate && !props.onUpdate && !props.onDelete) {
throw new Error("At least `onCreate`, `onUpdate` or `onDelete` must be specified.");
}
if (props.onCreate && !props.onCreate.physicalResourceId) {
throw new Error("'physicalResourceId' must be specified for 'onCreate' call.");
}
if (!props.onCreate &&
props.onUpdate &&
!props.onUpdate.physicalResourceId) {
throw new Error("'physicalResourceId' must be specified for 'onUpdate' call when 'onCreate' is omitted.");
}
let securityGroups = props.vpc
? props.securityGroups || [
new aws_ec2_1.SecurityGroup(this, "ProviderSG", { vpc: props.vpc }),
]
: undefined;
const uuid = this.renderUniqueId(props.broker, props.credentials, props.vpc, props.vpcSubnets, props.securityGroups);
const provider = new rabbitmq_custom_resource_singleton_function_1.RabbitMqCustomResourceSingletonFunction(this, "Provider", {
uuid,
vpc: props.vpc,
vpcSubnets: props.vpcSubnets,
securityGroups: securityGroups,
...(props.logRetention ? { logRetention: props.logRetention } : {}),
logGroup: props.logGroup,
timeout: props.timeout || aws_cdk_lib_1.Duration.minutes(1),
initialPolicy: props.policy?.statements,
});
const onUpdate = props.onUpdate && this.formatSdkCall(props.onUpdate);
const onCreate = (props.onCreate && this.formatSdkCall(props.onCreate)) || onUpdate;
const onDelete = props.onDelete && this.formatSdkCall(props.onDelete);
this.resource = new aws_cdk_lib_1.CustomResource(this, `Resource${uuid}`, {
resourceType: "Custom::RMQAPI",
serviceToken: provider.functionArn,
pascalCaseProperties: true,
properties: {
url: props.broker.endpoints.console.url,
credentials: props.credentials.secretArn,
create: onCreate,
update: onUpdate,
delete: onDelete,
},
});
this.connections = new aws_ec2_1.Connections({
securityGroups,
});
props.credentials.grantRead(provider);
this.grantPrincipal = provider.grantPrincipal;
}
getResponseField(key) {
return this.resource.getAttString(key);
}
getResponseFieldReference(key) {
return this.resource.getAtt(key);
}
formatSdkCall(sdkCall) {
const { logging, ...call } = sdkCall;
const renderedLogging = (logging ?? custom_resources_1.Logging.all())._render(this);
return this.encodeJson({
...call,
...renderedLogging,
});
}
encodeJson(obj) {
return aws_cdk_lib_1.Lazy.uncachedString({
produce: () => aws_cdk_lib_1.Stack.of(this).toJsonString(obj),
});
}
renderUniqueId(broker, creds, vpc, subnets, securityGroups) {
let hashContent = "";
const resourceBroker = broker;
hashContent += aws_cdk_lib_1.Names.uniqueId(resourceBroker);
hashContent += aws_cdk_lib_1.Names.uniqueId(creds);
if (vpc) {
hashContent += aws_cdk_lib_1.Names.uniqueId(vpc);
if (subnets) {
hashContent += vpc
.selectSubnets(subnets)
.subnets.map((s) => aws_cdk_lib_1.Names.uniqueId(s))
.join("");
}
if (securityGroups) {
hashContent += securityGroups.map((sg) => aws_cdk_lib_1.Names.uniqueId(sg)).join("");
}
}
// INFO: run this through the CDK team as in the S3 Bucket Deployment implementation there is no hashing, just verbatim value addition
// see: https://github.com/aws/aws-cdk/blob/318eae6c9eca456e0c34ed21855dad9d2bfa2a0f/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts#L556
return (0, crypto_1.createHash)("sha256")
.update(hashContent)
.digest("hex")
.slice(0, HASH_LEN)
.toUpperCase();
}
}
exports.RabbitMqCustomResource = RabbitMqCustomResource;
_b = JSII_RTTI_SYMBOL_1;
RabbitMqCustomResource[_b] = { fqn: "@cdklabs/cdk-amazonmq.RabbitMqCustomResource", version: "0.1.8" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFiYml0bXEtY3VzdG9tLXJlc291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3JhYmJpdG1xL2N1c3RvbS1yZXNvdXJjZS9yYWJiaXRtcS1jdXN0b20tcmVzb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQTs7O0VBR0U7QUFFRixtQ0FBb0M7QUFDcEMsNkNBUXFCO0FBQ3JCLGlEQU82QjtBQVM3QixtRUFBMkU7QUFDM0UsMkNBQXVDO0FBRXZDLCtHQUF3RztBQUV4RyxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUM7QUFFcEI7O0dBRUc7QUFDSCxJQUFZLFdBS1g7QUFMRCxXQUFZLFdBQVc7SUFDckIsMEJBQVcsQ0FBQTtJQUNYLDRCQUFhLENBQUE7SUFDYiwwQkFBVyxDQUFBO0lBQ1gsZ0NBQWlCLENBQUE7QUFDbkIsQ0FBQyxFQUxXLFdBQVcsMkJBQVgsV0FBVyxRQUt0QjtBQW9ERDs7R0FFRztBQUNILE1BQWEsNEJBQTRCO0lBTXZDOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsY0FBYyxDQUFDLFVBQTZCO1FBQ3hELE9BQU8sSUFBSSw0QkFBNEIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsWUFBb0MsVUFBNkI7UUFBN0IsZUFBVSxHQUFWLFVBQVUsQ0FBbUI7SUFBRyxDQUFDOztBQW5CdkUsb0VBb0JDOzs7QUFuQkM7O0dBRUc7QUFDb0IseUNBQVksR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBcUc5Qzs7Ozs7O0dBTUc7QUFDSCxNQUFhLHNCQUNYLFNBQVEsc0JBQVM7SUFTakIsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ1YsS0FBa0M7UUFFbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLElBQUksQ0FBQyxLQUFLLENBQUMs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QUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ1IsV0FBVyxJQUFJLG1CQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25DLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ1osV0FBVyxJQUFJLEdBQUc7cUJBQ2YsYUFBYSxDQUFDLE9BQU8sQ0FBQztxQkFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsbUJBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7cUJBQ3JDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNkLENBQUM7WUFDRCxJQUFJLGNBQWMsRUFBRSxDQUFDO2dCQUNuQixXQUFXLElBQUksY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsbUJBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDekUsQ0FBQztRQUNILENBQUM7UUFFRCxzSUFBc0k7UUFDdEkseUpBQXlKO1FBRXpKLE9BQU8sSUFBQSxtQkFBVSxFQUFDLFFBQVEsQ0FBQzthQUN4QixNQUFNLENBQUMsV0FBVyxDQUFDO2FBQ25CLE1BQU0sQ0FBQyxLQUFLLENBQUM7YUFDYixLQUFLLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQzthQUNsQixXQUFXLEVBQUUsQ0FBQztJQUNuQixDQUFDOztBQXRKSCx3REF1SkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuKi9cblxuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJjcnlwdG9cIjtcbmltcG9ydCB7XG4gIEN1c3RvbVJlc291cmNlLFxuICBEdXJhdGlvbixcbiAgSVJlc291cmNlLFxuICBMYXp5LFxuICBOYW1lcyxcbiAgUmVmZXJlbmNlLFxuICBTdGFjayxcbn0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQge1xuICBDb25uZWN0aW9ucyxcbiAgSUNvbm5lY3RhYmxlLFxuICBJU2VjdXJpdHlHcm91cCxcbiAgSVZwYyxcbiAgU2VjdXJpdHlHcm91cCxcbiAgU3VibmV0U2VsZWN0aW9uLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjMlwiO1xuaW1wb3J0IHtcbiAgSUdyYW50YWJsZSxcbiAgSVByaW5jaXBhbCxcbiAgSVJvbGUsXG4gIFBvbGljeVN0YXRlbWVudCxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7IExvZ0dyb3VwLCBSZXRlbnRpb25EYXlzIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1sb2dzXCI7XG5pbXBvcnQgeyBJU2VjcmV0IH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zZWNyZXRzbWFuYWdlclwiO1xuaW1wb3J0IHsgTG9nZ2luZywgUGh5c2ljYWxSZXNvdXJjZUlkIH0gZnJvbSBcImF3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXNcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBJUmFiYml0TXFCcm9rZXIgfSBmcm9tIFwiLi4vcmFiYml0bXEtYnJva2VyXCI7XG5pbXBvcnQgeyBSYWJiaXRNcUN1c3RvbVJlc291cmNlU2luZ2xldG9uRnVuY3Rpb24gfSBmcm9tIFwiLi9yYWJiaXRtcS1jdXN0b20tcmVzb3VyY2Utc2luZ2xldG9uLWZ1bmN0aW9uXCI7XG5cbmNvbnN0IEhBU0hfTEVOID0gMTY7XG5cbi8qKlxuICogQWxsIGh0dHAgcmVxdWVzdCBtZXRob2RzXG4gKi9cbmV4cG9ydCBlbnVtIEh0dHBNZXRob2RzIHtcbiAgR0VUID0gXCJHRVRcIixcbiAgUE9TVCA9IFwiUE9TVFwiLFxuICBQVVQgPSBcIlBVVFwiLFxuICBERUxFVEUgPSBcIkRFTEVURVwiLFxufVxuXG4vKipcbiAqIEEgUmFiYml0TVEgTWFuYWdlbWVudCBIVFRQIEFQSSBjYWxsXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmFiYml0TXFBcGlDYWxsIHtcbiAgLyoqXG4gICAqIFRoZSBSYWJiaXRNUSBNYW5hZ2VtZW50IEhUVFAgQVBJIGNhbGwgcGF0aC5cbiAgICovXG4gIHJlYWRvbmx5IHBhdGg6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEhUVFAgTWV0aG9kIHVzZWQgd2hlbiBpbnZva2luZyB0aGUgUmFiYml0TVEgTWFuYWdlbWVudCBIVFRQIEFQSSBjYWxsLlxuICAgKiBAZGVmYXVsdCBHRVRcbiAgICovXG4gIHJlYWRvbmx5IG1ldGhvZD86IEh0dHBNZXRob2RzO1xuXG4gIC8qKlxuICAgKiBUaGUgcGF5bG9hZCBleHBlY3RlZCBieSB0aGUgUmFiYml0TVEgTWFuYWdlbWVudCBIVFRQIEFQSSBjYWxsLlxuICAgKi9cbiAgcmVhZG9ubHkgcGF5bG9hZD86IHsgW2tleTogc3RyaW5nXTogYW55IH07XG4gIC8qKlxuICAgKiBUaGUgcGh5c2ljYWwgcmVzb3VyY2UgaWQgb2YgdGhlIGN1c3RvbSByZXNvdXJjZSBmb3IgdGhpcyBjYWxsLlxuICAgKiBNYW5kYXRvcnkgZm9yIG9uQ3JlYXRlIGNhbGwuXG4gICAqIEluIG9uVXBkYXRlLCB5b3UgY2FuIG9taXQgdGhpcyB0byBwYXNzdGhyb3VnaCBpdCBmcm9tIHJlcXVlc3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gcGh5c2ljYWwgcmVzb3VyY2UgaWRcbiAgICovXG4gIHJlYWRvbmx5IHBoeXNpY2FsUmVzb3VyY2VJZD86IFBoeXNpY2FsUmVzb3VyY2VJZDtcblxuICAvKipcbiAgICogUmVzdHJpY3QgdGhlIGRhdGEgcmV0dXJuZWQgYnkgdGhlIGN1c3RvbSByZXNvdXJjZSB0byBzcGVjaWZpYyBwYXRocyBpbiB0aGUgQVBJIHJlc3BvbnNlLlxuICAgKlxuICAgKiBVc2UgdGhpcyB0byBsaW1pdCB0aGUgZGF0YSByZXR1cm5lZCBieSB0aGUgY3VzdG9tIHJlc291cmNlIGlmIHdvcmtpbmcgd2l0aCBBUEkgY2FsbHMgdGhhdCBjb3VsZCBwb3RlbnRpYWxseSByZXN1bHQgaW4gY3VzdG9tIHJlc3BvbnNlIG9iamVjdHMgZXhjZWVkaW5nIHRoZSBoYXJkIGxpbWl0IG9mIDQwOTYgYnl0ZXMuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRQYXRocz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogQSBwcm9wZXJ0eSB1c2VkIHRvIGNvbmZpZ3VyZSBsb2dnaW5nIGR1cmluZyBsYW1iZGEgZnVuY3Rpb24gZXhlY3V0aW9uLlxuICAgKlxuICAgKiBOb3RlOiBUaGUgZGVmYXVsdCBMb2dnaW5nIGNvbmZpZ3VyYXRpb24gaXMgYWxsLiBUaGlzIGNvbmZpZ3VyYXRpb24gd2lsbCBlbmFibGUgbG9nZ2luZyBvbiBhbGwgbG9nZ2VkIGRhdGFcbiAgICogaW4gdGhlIGxhbWJkYSBoYW5kbGVyLiBUaGlzIGluY2x1ZGVzOlxuICAgKiAgLSBUaGUgZXZlbnQgb2JqZWN0IHRoYXQgaXMgcmVjZWl2ZWQgYnkgdGhlIGxhbWJkYSBoYW5kbGVyXG4gICAqICAtIFRoZSByZXNwb25zZSByZWNlaXZlZCBhZnRlciBtYWtpbmcgYSBBUEkgY2FsbFxuICAgKiAgLSBUaGUgcmVzcG9uc2Ugb2JqZWN0IHRoYXQgdGhlIGxhbWJkYSBoYW5kbGVyIHdpbGwgcmV0dXJuXG4gICAqICAtIFNESyB2ZXJzaW9uaW5nIGluZm9ybWF0aW9uXG4gICAqICAtIENhdWdodCBhbmQgdW5jYXVnaHQgZXJyb3JzXG4gICAqXG4gICAqIEBkZWZhdWx0IExvZ2dpbmcuYWxsKClcbiAgICovXG4gIHJlYWRvbmx5IGxvZ2dpbmc/OiBMb2dnaW5nO1xufVxuXG4vKipcbiAqIFRoZSBJQU0gUG9saWN5IHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBjYWxscy5cbiAqL1xuZXhwb3J0IGNsYXNzIFJhYmJpdE1xQ3VzdG9tUmVzb3VyY2VQb2xpY3kge1xuICAvKipcbiAgICogVXNlIHRoaXMgY29uc3RhbnQgdG8gY29uZmlndXJlIGFjY2VzcyB0byBhbnkgcmVzb3VyY2UuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEFOWV9SRVNPVVJDRSA9IFtcIipcIl07XG5cbiAgLyoqXG4gICAqIEV4cGxpY2l0IElBTSBQb2xpY3kgU3RhdGVtZW50cy5cbiAgICpcbiAgICogQHBhcmFtIHN0YXRlbWVudHMgdGhlIHN0YXRlbWVudHMgdG8gcHJvcGFnYXRlIHRvIHRoZSBTREsgY2FsbHMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21TdGF0ZW1lbnRzKHN0YXRlbWVudHM6IFBvbGljeVN0YXRlbWVudFtdKSB7XG4gICAgcmV0dXJuIG5ldyBSYWJiaXRNcUN1c3RvbVJlc291cmNlUG9saWN5KHN0YXRlbWVudHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBzdGF0ZW1lbnRzIHN0YXRlbWVudHMgZm9yIGV4cGxpY2l0IHBvbGljeS5cbiAgICogQHBhcmFtIHJlc291cmNlcyByZXNvdXJjZXMgZm9yIGF1dG8tZ2VuZXJhdGVkIGZyb20gU0RLIGNhbGxzLlxuICAgKi9cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgc3RhdGVtZW50czogUG9saWN5U3RhdGVtZW50W10pIHt9XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgUmFiYml0TXFDdXN0b21SZXNvdXJjZS5cbiAqXG4gKiBOb3RlIHRoYXQgYXQgbGVhc3Qgb25DcmVhdGUsIG9uVXBkYXRlIG9yIG9uRGVsZXRlIG11c3QgYmUgc3BlY2lmaWVkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJhYmJpdE1xQ3VzdG9tUmVzb3VyY2VQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgYnJva2VyIHRvIHNlbmQgcmVxdWVzdHMgdG8uXG4gICAqL1xuICByZWFkb25seSBicm9rZXI6IElSYWJiaXRNcUJyb2tlcjtcblxuICAvKipcbiAgICogVGhlIHNlY3JldCBjb250YWluaW5nIHRoZSBicm9rZXIgbG9naW4gY3JlZGVudGlhbHMuXG4gICAqL1xuICByZWFkb25seSBjcmVkZW50aWFsczogSVNlY3JldDtcblxuICAvKipcbiAgICogVGhlIFJhYmJpdE1RIE1hbmFnZW1lbnQgSFRUUCBBUEkgY2FsbCB0byBtYWtlIHdoZW4gdGhlIHJlc291cmNlIGlzIGNyZWF0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgY2FsbCB3aGVuIHRoZSByZXNvdXJjZSBpcyB1cGRhdGVkXG4gICAqL1xuICByZWFkb25seSBvbkNyZWF0ZT86IFJhYmJpdE1xQXBpQ2FsbDtcblxuICAvKipcbiAgICogVGhlIFJhYmJpdE1RIE1hbmFnZW1lbnQgSFRUUCBBUEkgY2FsbCB0byBtYWtlIHdoZW4gdGhlIHJlc291cmNlIGlzIHVwZGF0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBjYWxsXG4gICAqL1xuICByZWFkb25seSBvblVwZGF0ZT86IFJhYmJpdE1xQXBpQ2FsbDtcblxuICAvKipcbiAgICogVGhlIFJhYmJpdE1RIE1hbmFnZW1lbnQgSFRUUCBBUEkgY2FsbCB0byBtYWtlIHdoZW4gdGhlIHJlc291cmNlIGlzIHVwZGF0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBjYWxsXG4gICAqL1xuICByZWFkb25seSBvbkRlbGV0ZT86IFJhYmJpdE1xQXBpQ2FsbDtcblxuICAvKipcbiAgICogVGhlIHZwYyB0byBjb25uZWN0IHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogSVZwYztcblxuICAvKipcbiAgICogVGhlIHZwYyBzdWJuZXRzIHRvIGNvbm5lY3QgdG8uXG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogU3VibmV0U2VsZWN0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VjdXJpdHkgZ3JvdXBzIHRvIGFzc2lnbiB0byB0aGUgZnVuY3Rpb24uXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3Vwcz86IFNlY3VyaXR5R3JvdXBbXTtcblxuICAvKipcbiAgICogTG9nR3JvdXAgcmV0ZW50aW9uIHRvIHVzZSBmb3IgdGhlIGZ1bmN0aW9uXG4gICAqXG4gICAqIEBkZWZhdWx0IFJldGVudGlvbkRheXMuSU5GSU5JVEVcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGxvZ0dyb3VwIGluc3RlYWRcbiAgICovXG4gIHJlYWRvbmx5IGxvZ1JldGVudGlvbj86IFJldGVudGlvbkRheXM7XG5cbiAgLyoqXG4gICAqIFRoZSBsb2dHcm91cCB0byB1c2UgZm9yIHRoZSBmdW5jdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgbG9nR3JvdXA/OiBMb2dHcm91cDtcblxuICAvKipcbiAgICogVGhlIHRpbWVvdXQgZm9yIHRoZSBjdXN0b20gcmVzb3VyY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IER1cmF0aW9uLm1pbnV0ZXMoMSlcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXQ/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogVGhlIGV4ZWN1dGlvbiByb2xlIGZvciB0aGUgZnVuY3Rpb24uXG4gICAqL1xuICByZWFkb25seSByb2xlPzogSVJvbGU7XG5cbiAgLyoqXG4gICAqIFRoZSBwb2xpY2llcyB0byBhdHRhY2ggdG8gdGhlIGZ1bmN0aW9uJ3Mgcm9sZVxuICAgKi9cbiAgcmVhZG9ubHkgcG9saWN5PzogUmFiYml0TXFDdXN0b21SZXNvdXJjZVBvbGljeTtcbn1cblxuLyoqXG4gKiBAZXhwZXJpbWVudGFsXG4gKlxuICogRGVmaW5lcyBhIGN1c3RvbSByZXNvdXJjZSB0aGF0IGlzIG1hdGVyaWFsaXplZCB1c2luZyBzcGVjaWZpYyBSYWJiaXRNUSBNYW5hZ2VtZW50IEhUVFAgQVBJIGNhbGxzLlxuICpcbiAqIFVzZSB0aGlzIHRvIGludGVyYWN0IHdpdGggdGhlIEFtYXpvbiBNUSBmb3IgUmFiYml0TVEgYnJva2VyLiBZb3UgY2FuIHNwZWNpZnkgZXhhY3RseSB3aGljaCBjYWxscyBhcmUgaW52b2tlZCBmb3IgdGhlICdDUkVBVEUnLCAnVVBEQVRFJyBhbmQgJ0RFTEVURScgbGlmZSBjeWNsZSBldmVudHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBSYWJiaXRNcUN1c3RvbVJlc291cmNlXG4gIGV4dGVuZHMgQ29uc3RydWN0XG4gIGltcGxlbWVudHMgSUNvbm5lY3RhYmxlLCBJR3JhbnRhYmxlXG57XG4gIHB1YmxpYyByZWFkb25seSBjb25uZWN0aW9uczogQ29ubmVjdGlvbnM7XG5cbiAgcHVibGljIHJlYWRvbmx5IGdyYW50UHJpbmNpcGFsOiBJUHJpbmNpcGFsO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVzb3VyY2U6IEN1c3RvbVJlc291cmNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcm9wczogUmFiYml0TXFDdXN0b21SZXNvdXJjZVByb3BzLFxuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgaWYgKCFwcm9wcy5vbkNyZWF0ZSAmJiAhcHJvcHMub25VcGRhdGUgJiYgIXByb3BzLm9uRGVsZXRlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQXQgbGVhc3QgYG9uQ3JlYXRlYCwgYG9uVXBkYXRlYCBvciBgb25EZWxldGVgIG11c3QgYmUgc3BlY2lmaWVkLlwiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMub25DcmVhdGUgJiYgIXByb3BzLm9uQ3JlYXRlLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIidwaHlzaWNhbFJlc291cmNlSWQnIG11c3QgYmUgc3BlY2lmaWVkIGZvciAnb25DcmVhdGUnIGNhbGwuXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgICFwcm9wcy5vbkNyZWF0ZSAmJlxuICAgICAgcHJvcHMub25VcGRhdGUgJiZcbiAgICAgICFwcm9wcy5vblVwZGF0ZS5waHlzaWNhbFJlc291cmNlSWRcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCIncGh5c2ljYWxSZXNvdXJjZUlkJyBtdXN0IGJlIHNwZWNpZmllZCBmb3IgJ29uVXBkYXRlJyBjYWxsIHdoZW4gJ29uQ3JlYXRlJyBpcyBvbWl0dGVkLlwiLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsZXQgc2VjdXJpdHlHcm91cHMgPSBwcm9wcy52cGNcbiAgICAgID8gcHJvcHMuc2VjdXJpdHlHcm91cHMgfHwgW1xuICAgICAgICAgIG5ldyBTZWN1cml0eUdyb3VwKHRoaXMsIFwiUHJvdmlkZXJTR1wiLCB7IHZwYzogcHJvcHMudnBjIH0pLFxuICAgICAgICBdXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHV1aWQgPSB0aGlzLnJlbmRlclVuaXF1ZUlkKFxuICAgICAgcHJvcHMuYnJva2VyLFxuICAgICAgcHJvcHMuY3JlZGVudGlhbHMsXG4gICAgICBwcm9wcy52cGMsXG4gICAgICBwcm9wcy52cGNTdWJuZXRzLFxuICAgICAgcHJvcHMuc2VjdXJpdHlHcm91cHMsXG4gICAgKTtcblxuICAgIGNvbnN0IHByb3ZpZGVyID0gbmV3IFJhYmJpdE1xQ3VzdG9tUmVzb3VyY2VTaW5nbGV0b25GdW5jdGlvbihcbiAgICAgIHRoaXMsXG4gICAgICBcIlByb3ZpZGVyXCIsXG4gICAgICB7XG4gICAgICAgIHV1aWQsXG4gICAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgICB2cGNTdWJuZXRzOiBwcm9wcy52cGNTdWJuZXRzLFxuICAgICAgICBzZWN1cml0eUdyb3Vwczogc2VjdXJpdHlHcm91cHMsXG4gICAgICAgIC4uLihwcm9wcy5sb2dSZXRlbnRpb24gPyB7IGxvZ1JldGVudGlvbjogcHJvcHMubG9nUmV0ZW50aW9uIH0gOiB7fSksXG4gICAgICAgIGxvZ0dyb3VwOiBwcm9wcy5sb2dHcm91cCxcbiAgICAgICAgdGltZW91dDogcHJvcHMudGltZW91dCB8fCBEdXJhdGlvbi5taW51dGVzKDEpLFxuICAgICAgICBpbml0aWFsUG9saWN5OiBwcm9wcy5wb2xpY3k/LnN0YXRlbWVudHMsXG4gICAgICB9LFxuICAgICk7XG5cbiAgICBjb25zdCBvblVwZGF0ZSA9IHByb3BzLm9uVXBkYXRlICYmIHRoaXMuZm9ybWF0U2RrQ2FsbChwcm9wcy5vblVwZGF0ZSk7XG4gICAgY29uc3Qgb25DcmVhdGUgPVxuICAgICAgKHByb3BzLm9uQ3JlYXRlICYmIHRoaXMuZm9ybWF0U2RrQ2FsbChwcm9wcy5vbkNyZWF0ZSkpIHx8IG9uVXBkYXRlO1xuICAgIGNvbnN0IG9uRGVsZXRlID0gcHJvcHMub25EZWxldGUgJiYgdGhpcy5mb3JtYXRTZGtDYWxsKHByb3BzLm9uRGVsZXRlKTtcblxuICAgIHRoaXMucmVzb3VyY2UgPSBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgYFJlc291cmNlJHt1dWlkfWAsIHtcbiAgICAgIHJlc291cmNlVHlwZTogXCJDdXN0b206OlJNUUFQSVwiLFxuICAgICAgc2VydmljZVRva2VuOiBwcm92aWRlci5mdW5jdGlvbkFybixcbiAgICAgIHBhc2NhbENhc2VQcm9wZXJ0aWVzOiB0cnVlLFxuICAgICAgcHJvcGVydGllczoge1xuICAgICAgICB1cmw6IHByb3BzLmJyb2tlci5lbmRwb2ludHMuY29uc29sZS51cmwsXG4gICAgICAgIGNyZWRlbnRpYWxzOiBwcm9wcy5jcmVkZW50aWFscy5zZWNyZXRBcm4sXG4gICAgICAgIGNyZWF0ZTogb25DcmVhdGUsXG4gICAgICAgIHVwZGF0ZTogb25VcGRhdGUsXG4gICAgICAgIGRlbGV0ZTogb25EZWxldGUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy5jb25uZWN0aW9ucyA9IG5ldyBDb25uZWN0aW9ucyh7XG4gICAgICBzZWN1cml0eUdyb3VwcyxcbiAgICB9KTtcblxuICAgIHByb3BzLmNyZWRlbnRpYWxzLmdyYW50UmVhZChwcm92aWRlcik7XG5cbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gcHJvdmlkZXIuZ3JhbnRQcmluY2lwYWw7XG4gIH1cblxuICBwdWJsaWMgZ2V0UmVzcG9uc2VGaWVsZChrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucmVzb3VyY2UuZ2V0QXR0U3RyaW5nKGtleSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0UmVzcG9uc2VGaWVsZFJlZmVyZW5jZShrZXk6IHN0cmluZyk6IFJlZmVyZW5jZSB7XG4gICAgcmV0dXJuIHRoaXMucmVzb3VyY2UuZ2V0QXR0KGtleSk7XG4gIH1cblxuICBwcml2YXRlIGZvcm1hdFNka0NhbGwoc2RrQ2FsbDogUmFiYml0TXFBcGlDYWxsKSB7XG4gICAgY29uc3QgeyBsb2dnaW5nLCAuLi5jYWxsIH0gPSBzZGtDYWxsO1xuICAgIGNvbnN0IHJlbmRlcmVkTG9nZ2luZyA9IChsb2dnaW5nID8/IExvZ2dpbmcuYWxsKCkpLl9yZW5kZXIodGhpcyk7XG4gICAgcmV0dXJuIHRoaXMuZW5jb2RlSnNvbih7XG4gICAgICAuLi5jYWxsLFxuICAgICAgLi4ucmVuZGVyZWRMb2dnaW5nLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBlbmNvZGVKc29uKG9iajogYW55KSB7XG4gICAgcmV0dXJuIExhenkudW5jYWNoZWRTdHJpbmcoe1xuICAgICAgcHJvZHVjZTogKCkgPT4gU3RhY2sub2YodGhpcykudG9Kc29uU3RyaW5nKG9iaiksXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlclVuaXF1ZUlkKFxuICAgIGJyb2tlcjogSVJhYmJpdE1xQnJva2VyLFxuICAgIGNyZWRzOiBJU2VjcmV0LFxuICAgIHZwYz86IElWcGMsXG4gICAgc3VibmV0cz86IFN1Ym5ldFNlbGVjdGlvbixcbiAgICBzZWN1cml0eUdyb3Vwcz86IElTZWN1cml0eUdyb3VwW10sXG4gICkge1xuICAgIGxldCBoYXNoQ29udGVudCA9IFwiXCI7XG4gICAgY29uc3QgcmVzb3VyY2VCcm9rZXIgPSBicm9rZXIgYXMgSVJlc291cmNlO1xuICAgIGhhc2hDb250ZW50ICs9IE5hbWVzLnVuaXF1ZUlkKHJlc291cmNlQnJva2VyKTtcbiAgICBoYXNoQ29udGVudCArPSBOYW1lcy51bmlxdWVJZChjcmVkcyk7XG4gICAgaWYgKHZwYykge1xuICAgICAgaGFzaENvbnRlbnQgKz0gTmFtZXMudW5pcXVlSWQodnBjKTtcbiAgICAgIGlmIChzdWJuZXRzKSB7XG4gICAgICAgIGhhc2hDb250ZW50ICs9IHZwY1xuICAgICAgICAgIC5zZWxlY3RTdWJuZXRzKHN1Ym5ldHMpXG4gICAgICAgICAgLnN1Ym5ldHMubWFwKChzKSA9PiBOYW1lcy51bmlxdWVJZChzKSlcbiAgICAgICAgICAuam9pbihcIlwiKTtcbiAgICAgIH1cbiAgICAgIGlmIChzZWN1cml0eUdyb3Vwcykge1xuICAgICAgICBoYXNoQ29udGVudCArPSBzZWN1cml0eUdyb3Vwcy5tYXAoKHNnKSA9PiBOYW1lcy51bmlxdWVJZChzZykpLmpvaW4oXCJcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSU5GTzogcnVuIHRoaXMgdGhyb3VnaCB0aGUgQ0RLIHRlYW0gYXMgaW4gdGhlIFMzIEJ1Y2tldCBEZXBsb3ltZW50IGltcGxlbWVudGF0aW9uIHRoZXJlIGlzIG5vIGhhc2hpbmcsIGp1c3QgdmVyYmF0aW0gdmFsdWUgYWRkaXRpb25cbiAgICAvLyBzZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9ibG9iLzMxOGVhZTZjOWVjYTQ1NmUwYzM0ZWQyMTg1NWRhZDlkMmJmYTJhMGYvcGFja2FnZXMvYXdzLWNkay1saWIvYXdzLXMzLWRlcGxveW1lbnQvbGliL2J1Y2tldC1kZXBsb3ltZW50LnRzI0w1NTZcblxuICAgIHJldHVybiBjcmVhdGVIYXNoKFwic2hhMjU2XCIpXG4gICAgICAudXBkYXRlKGhhc2hDb250ZW50KVxuICAgICAgLmRpZ2VzdChcImhleFwiKVxuICAgICAgLnNsaWNlKDAsIEhBU0hfTEVOKVxuICAgICAgLnRvVXBwZXJDYXNlKCk7XG4gIH1cbn1cbiJdfQ==