@aws-solutions-constructs/core
Version:
Core CDK Construct for patterns library
212 lines • 33.5 kB
JavaScript
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
* with the License. A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
* OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObtainAlb = ObtainAlb;
exports.AddListener = AddListener;
exports.AddLambdaTarget = AddLambdaTarget;
exports.AddFargateTarget = AddFargateTarget;
exports.GetActiveListener = GetActiveListener;
exports.CheckAlbProps = CheckAlbProps;
/*
* The functions found here in the core library are for internal use and can be changed
* or removed outside of a major release. We recommend against calling them directly from client code.
*/
const elb = require("aws-cdk-lib/aws-elasticloadbalancingv2");
const aws_elasticloadbalancingv2_1 = require("aws-cdk-lib/aws-elasticloadbalancingv2");
const elbt = require("aws-cdk-lib/aws-elasticloadbalancingv2-targets");
const utils_1 = require("./utils");
const alb_defaults_1 = require("./alb-defaults");
const s3_bucket_helper_1 = require("./s3-bucket-helper");
const s3_bucket_defaults_1 = require("./s3-bucket-defaults");
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*
* Returns the correct ALB Load Balancer to use in this construct, either an existing
* one provided as an argument or create new one otherwise.
*/
function ObtainAlb(scope, id, props) {
let loadBalancer;
if (props.existingLoadBalancerObj) {
loadBalancer = props.existingLoadBalancerObj;
}
else {
const consolidatedProps = (0, utils_1.consolidateProps)({}, props.loadBalancerProps, { vpc: props.vpc, internetFacing: props.publicApi });
loadBalancer = new elb.ApplicationLoadBalancer(scope, `${id}-alb`, consolidatedProps);
if (props.logAccessLogs === undefined || props.logAccessLogs === true) {
const consolidatedLoggingBucketProps = (0, utils_1.consolidateProps)((0, s3_bucket_defaults_1.DefaultS3Props)(), props.loggingBucketProps);
const loggingBucket = (0, s3_bucket_helper_1.createAlbLoggingBucket)(scope, id, consolidatedLoggingBucketProps);
loadBalancer.logAccessLogs(loggingBucket);
}
}
return loadBalancer;
}
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*/
function AddListener(scope, id, loadBalancer, listenerProps) {
const consolidatedListenerProps = (0, utils_1.consolidateProps)((0, alb_defaults_1.DefaultListenerProps)(loadBalancer), listenerProps);
// create the listener
const listener = new elb.ApplicationListener(scope, `${id}-listener`, consolidatedListenerProps);
loadBalancer.listeners.push(listener);
if (consolidatedListenerProps.protocol === elb.ApplicationProtocol.HTTP) {
// This will use core.printWarning in the actual construct
(0, utils_1.printWarning)("AWS recommends encrypting traffic to an Application Load Balancer using HTTPS.");
if (listenerProps.certificates?.length > 0) {
throw new Error("HTTP listeners cannot use a certificate");
}
}
else {
if (!listenerProps.certificates || listenerProps.certificates.length === 0) {
throw new Error("A listener using HTTPS protocol requires a certificate");
}
listener.addCertificates(`${id}-cert`, listenerProps.certificates);
}
if (consolidatedListenerProps.protocol === elb.ApplicationProtocol.HTTPS) {
const opt = {
port: "443",
protocol: "HTTPS",
};
// NOSONAR: (typescript:S5332)
// This listener is explicitly created to redirect non TLS connections
// The lack of SSL/TLS is intentional
const httpListener = new elb.ApplicationListener(scope, `${id}-redirect`, {
loadBalancer,
protocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTP, // NOSONAR
defaultAction: aws_elasticloadbalancingv2_1.ListenerAction.redirect(opt),
});
loadBalancer.listeners.push(httpListener);
}
return listener;
}
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*
* Creates a Target Group for Lambda functions and adds the
* provided functions as a target to that group. Then adds
* the new Target Group to the provided Listener.
*/
function AddLambdaTarget(scope, id, currentListener, lambdaFunction, ruleProps, targetProps) {
// Create the target and assign it to a new target group
const lambdaTarget = new elbt.LambdaTarget(lambdaFunction);
const newTargetGroup = new elb.ApplicationTargetGroup(scope, `${id}-tg`, {
targets: [lambdaTarget],
targetGroupName: targetProps ? targetProps.targetGroupName : undefined,
healthCheck: targetProps ? targetProps.healthCheck : undefined
});
// The interface AddRuleProps includes conditions and priority, combine that
// with targetGroups and we can assemble AddApplicationTargetGroupProps
const consolidatedTargetProps = (0, utils_1.consolidateProps)({}, ruleProps, { targetGroups: [newTargetGroup] });
currentListener.addTargetGroups(`${scope.node.id}-targets`, consolidatedTargetProps);
newTargetGroup.setAttribute('stickiness.enabled', undefined);
return newTargetGroup;
}
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*/
function AddFargateTarget(scope, id, currentListener, fargateService, ruleProps, targetProps) {
if (targetProps?.protocol !== elb.ApplicationProtocol.HTTPS) {
(0, utils_1.printWarning)('AWS recommends using HTTPS protocol for Target Groups in production applications');
}
const newTargetGroup = new elb.ApplicationTargetGroup(scope, `${id}-tg`, targetProps);
// The interface AddRuleProps includes conditions and priority, combine that
// with targetGroups and we can assemble an AddApplicationTargetGroupProps object
const consolidatedTargetProps = (0, utils_1.consolidateProps)({ targetGroups: [newTargetGroup] }, ruleProps);
currentListener.addTargetGroups(`${scope.node.id}-targets`, consolidatedTargetProps);
newTargetGroup.addTarget(fargateService);
return newTargetGroup;
}
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*
* Looks for the listener associated with Target Groups
* If there is a single listener, this returns it whether it is HTTP or HTTPS
* If there are 2 listeners, it finds the HTTPS listener (we assume the HTTP listener redirects to HTTPS)
*/
function GetActiveListener(listeners) {
let listener;
if (listeners.length === 0) {
throw new Error(`There are no listeners in the ALB`);
}
if (listeners.length === 1) {
listener = listeners[0];
}
else {
listener = listeners.find(i => i.node.children[0].protocol === "HTTPS");
}
return listener;
}
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*/
function CheckAlbProps(props) {
let errorMessages = '';
let errorFound = false;
if (props.loadBalancerProps && props.existingLoadBalancerObj) {
errorMessages += 'Error - Either provide loadBalancerProps or existingLoadBalancerObj, but not both.\n';
errorFound = true;
}
if ((props?.logAlbAccessLogs === false) && (props.albLoggingBucketProps)) {
errorMessages += 'Error - If logAlbAccessLogs is false, supplying albLoggingBucketProps is invalid.\n';
errorFound = true;
}
if (props.listenerProps?.certificateArns) {
errorMessages += "certificateArns is deprecated. Please supply certificates using props.listenerProps.certificates\n";
errorFound = true;
}
if (ValidateAddListenerProps(props)) {
errorMessages += "When adding the first listener and target to a load balancer, listenerProps must be specified and include at least a certificate or protocol: HTTP\n";
errorFound = true;
}
if (props.existingLoadBalancerObj &&
props.existingLoadBalancerObj.listeners.length > 0 &&
props.listenerProps) {
errorFound = true;
errorMessages += "This load balancer already has a listener, listenerProps may not be specified\n";
}
if (props.existingLoadBalancerObj &&
props.existingLoadBalancerObj.listeners.length > 0 &&
!props.ruleProps) {
errorFound = true;
errorMessages += "When adding a second target to an existing listener, there must be rules provided\n";
}
// Check construct specific invalid inputs
if (props.existingLoadBalancerObj && !props.existingVpc) {
errorFound = true;
errorMessages += "An existing ALB is already in a VPC, that VPC must be provided in props.existingVpc for the rest of the construct to use.\n";
}
if (props.loadBalancerProps?.vpc) {
// Only reason this should exist is to enable specifying ALB network configuration. There must still
// be a construct VPC and they must match
if ((!props.existingVpc) || (props.existingVpc.vpcId !== props.loadBalancerProps?.vpc.vpcId)) {
errorFound = true;
errorMessages += 'Any existing VPC must be defined in the construct props (props.existingVpc). A VPC specified in the loadBalancerProps must be the same VPC';
}
}
if (props.existingLoadBalancerObj) {
(0, utils_1.printWarning)("The public/private property of an existing ALB must match the props.publicApi setting provided.");
}
if (errorFound) {
throw new Error(errorMessages);
}
}
function ValidateAddListenerProps(props) {
if (((props.existingLoadBalancerObj &&
props.existingLoadBalancerObj.listeners.length === 0) ||
!props.existingLoadBalancerObj) &&
!props.listenerProps) {
return true;
}
return false;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxiLWhlbHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFsYi1oZWxwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7OztHQVdHOztBQW1DSCw4QkF1QkM7QUFLRCxrQ0FzREM7QUFTRCwwQ0F3QkM7QUFLRCw0Q0F1QkM7QUFTRCw4Q0FZQztBQUtELHNDQW1FQztBQTdRRDs7O0dBR0c7QUFFSCw4REFBOEQ7QUFNOUQsdUZBQThGO0FBQzlGLHVFQUF1RTtBQUN2RSxtQ0FBeUQ7QUFDekQsaURBQXNEO0FBQ3RELHlEQUE0RDtBQUM1RCw2REFBc0Q7QUFXdEQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixTQUFTLENBQ3ZCLEtBQWdCLEVBQ2hCLEVBQVUsRUFDVixLQUFxQjtJQUVyQixJQUFJLFlBQXlDLENBQUM7SUFFOUMsSUFBSSxLQUFLLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUNsQyxZQUFZLEdBQUcsS0FBSyxDQUFDLHVCQUF1QixDQUFDO0lBQy9DLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxpQkFBaUIsR0FBRyxJQUFBLHdCQUFnQixFQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxjQUFjLEVBQUUsS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDN0gsWUFBWSxHQUFHLElBQUksR0FBRyxDQUFDLHVCQUF1QixDQUM1QyxLQUFLLEVBQ0wsR0FBRyxFQUFFLE1BQU0sRUFDWCxpQkFBaUIsQ0FDbEIsQ0FBQztRQUNGLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUN0RSxNQUFNLDhCQUE4QixHQUFHLElBQUEsd0JBQWdCLEVBQUMsSUFBQSxtQ0FBYyxHQUFFLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDcEcsTUFBTSxhQUFh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QztZQUNsQixhQUFhLElBQUksNElBQTRJLENBQUM7UUFDaEssQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ2xDLElBQUEsb0JBQVksRUFDVixpR0FBaUcsQ0FDbEcsQ0FBQztJQUNKLENBQUM7SUFFRCxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNqQyxDQUFDO0FBRUgsQ0FBQztBQUVELFNBQVMsd0JBQXdCLENBQUMsS0FBVTtJQUMxQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsdUJBQXVCO1FBQ2pDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxTQUFTLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztRQUNyRCxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQztRQUNqQyxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNyQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKlxuICogIFRoZSBmdW5jdGlvbnMgZm91bmQgaGVyZSBpbiB0aGUgY29yZSBsaWJyYXJ5IGFyZSBmb3IgaW50ZXJuYWwgdXNlIGFuZCBjYW4gYmUgY2hhbmdlZFxuICogIG9yIHJlbW92ZWQgb3V0c2lkZSBvZiBhIG1ham9yIHJlbGVhc2UuIFdlIHJlY29tbWVuZCBhZ2FpbnN0IGNhbGxpbmcgdGhlbSBkaXJlY3RseSBmcm9tIGNsaWVudCBjb2RlLlxuICovXG5cbmltcG9ydCAqIGFzIGVsYiBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVsYXN0aWNsb2FkYmFsYW5jaW5ndjJcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1lYzJcIjtcbmltcG9ydCAqIGFzIHMzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCAqIGFzIGVjcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjc1wiO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgeyBBcHBsaWNhdGlvblByb3RvY29sLCBMaXN0ZW5lckFjdGlvbiwgfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVsYXN0aWNsb2FkYmFsYW5jaW5ndjJcIjtcbmltcG9ydCAqIGFzIGVsYnQgZnJvbSBcImF3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyLXRhcmdldHNcIjtcbmltcG9ydCB7IHByaW50V2FybmluZywgY29uc29saWRhdGVQcm9wcyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBEZWZhdWx0TGlzdGVuZXJQcm9wcyB9IGZyb20gXCIuL2FsYi1kZWZhdWx0c1wiO1xuaW1wb3J0IHsgY3JlYXRlQWxiTG9nZ2luZ0J1Y2tldCB9IGZyb20gXCIuL3MzLWJ1Y2tldC1oZWxwZXJcIjtcbmltcG9ydCB7IERlZmF1bHRTM1Byb3BzIH0gZnJvbSBcIi4vczMtYnVja2V0LWRlZmF1bHRzXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT2J0YWluQWxiUHJvcHMge1xuICByZWFkb25seSB2cGM6IGVjMi5JVnBjLFxuICByZWFkb25seSBwdWJsaWNBcGk6IGJvb2xlYW4sXG4gIHJlYWRvbmx5IGV4aXN0aW5nTG9hZEJhbGFuY2VyT2JqPzogZWxiLkFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLFxuICByZWFkb25seSBsb2FkQmFsYW5jZXJQcm9wcz86IGVsYi5BcHBsaWNhdGlvbkxvYWRCYWxhbmNlclByb3BzIHwgYW55LFxuICByZWFkb25seSBsb2dBY2Nlc3NMb2dzPzogYm9vbGVhbixcbiAgcmVhZG9ubHkgbG9nZ2luZ0J1Y2tldFByb3BzPzogczMuQnVja2V0UHJvcHNcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWwgVGhpcyBpcyBhbiBpbnRlcm5hbCBjb3JlIGZ1bmN0aW9uIGFuZCBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSBieSBTb2x1dGlvbnMgQ29uc3RydWN0cyBjbGllbnRzLlxuICpcbiAqIFJldHVybnMgdGhlIGNvcnJlY3QgQUxCIExvYWQgQmFsYW5jZXIgdG8gdXNlIGluIHRoaXMgY29uc3RydWN0LCBlaXRoZXIgYW4gZXhpc3RpbmdcbiAqIG9uZSBwcm92aWRlZCBhcyBhbiBhcmd1bWVudCBvciBjcmVhdGUgIG5ldyBvbmUgb3RoZXJ3aXNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT2J0YWluQWxiKFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogc3RyaW5nLFxuICBwcm9wczogT2J0YWluQWxiUHJvcHNcbik6IGVsYi5BcHBsaWNhdGlvbkxvYWRCYWxhbmNlciB7XG4gIGxldCBsb2FkQmFsYW5jZXI6IGVsYi5BcHBsaWNhdGlvbkxvYWRCYWxhbmNlcjtcblxuICBpZiAocHJvcHMuZXhpc3RpbmdMb2FkQmFsYW5jZXJPYmopIHtcbiAgICBsb2FkQmFsYW5jZXIgPSBwcm9wcy5leGlzdGluZ0xvYWRCYWxhbmNlck9iajtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBjb25zb2xpZGF0ZWRQcm9wcyA9IGNvbnNvbGlkYXRlUHJvcHMoe30sIHByb3BzLmxvYWRCYWxhbmNlclByb3BzLCB7IHZwYzogcHJvcHMudnBjLCBpbnRlcm5ldEZhY2luZzogcHJvcHMucHVibGljQXBpIH0pO1xuICAgIGxvYWRCYWxhbmNlciA9IG5ldyBlbGIuQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIoXG4gICAgICBzY29wZSxcbiAgICAgIGAke2lkfS1hbGJgLFxuICAgICAgY29uc29saWRhdGVkUHJvcHNcbiAgICApO1xuICAgIGlmIChwcm9wcy5sb2dBY2Nlc3NMb2dzID09PSB1bmRlZmluZWQgfHwgcHJvcHMubG9nQWNjZXNzTG9ncyA9PT0gdHJ1ZSkge1xuICAgICAgY29uc3QgY29uc29saWRhdGVkTG9nZ2luZ0J1Y2tldFByb3BzID0gY29uc29saWRhdGVQcm9wcyhEZWZhdWx0UzNQcm9wcygpLCBwcm9wcy5sb2dnaW5nQnVja2V0UHJvcHMpO1xuICAgICAgY29uc3QgbG9nZ2luZ0J1Y2tldCA9IGNyZWF0ZUFsYkxvZ2dpbmdCdWNrZXQoc2NvcGUsIGlkLCBjb25zb2xpZGF0ZWRMb2dnaW5nQnVja2V0UHJvcHMpO1xuICAgICAgbG9hZEJhbGFuY2VyLmxvZ0FjY2Vzc0xvZ3MobG9nZ2luZ0J1Y2tldCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBsb2FkQmFsYW5jZXI7XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFkZExpc3RlbmVyKFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogc3RyaW5nLFxuICBsb2FkQmFsYW5jZXI6IGVsYi5BcHBsaWNhdGlvbkxvYWRCYWxhbmNlcixcbiAgbGlzdGVuZXJQcm9wczogZWxiLkFwcGxpY2F0aW9uTGlzdGVuZXJQcm9wcyB8IGFueVxuKTogZWxiLkFwcGxpY2F0aW9uTGlzdGVuZXIge1xuICBjb25zdCBjb25zb2xpZGF0ZWRMaXN0ZW5lclByb3BzOiBlbGIuQXBwbGljYXRpb25MaXN0ZW5lclByb3BzID0gY29uc29saWRhdGVQcm9wcyhEZWZhdWx0TGlzdGVuZXJQcm9wcyhsb2FkQmFsYW5jZXIpLCBsaXN0ZW5lclByb3BzKTtcblxuICAvLyAgY3JlYXRlIHRoZSBsaXN0ZW5lclxuICBjb25zdCBsaXN0ZW5lciA9IG5ldyBlbGIuQXBwbGljYXRpb25MaXN0ZW5lcihcbiAgICBzY29wZSxcbiAgICBgJHtpZH0tbGlzdGVuZXJgLFxuICAgIGNvbnNvbGlkYXRlZExpc3RlbmVyUHJvcHNcbiAgKTtcbiAgbG9hZEJhbGFuY2VyLmxpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTtcblxuICBpZiAoY29uc29saWRhdGVkTGlzdGVuZXJQcm9wcy5wcm90b2NvbCA9PT0gZWxiLkFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUCkge1xuICAgIC8vIFRoaXMgd2lsbCB1c2UgY29yZS5wcmludFdhcm5pbmcgaW4gdGhlIGFjdHVhbCBjb25zdHJ1Y3RcbiAgICBwcmludFdhcm5pbmcoXG4gICAgICBcIkFXUyByZWNvbW1lbmRzIGVuY3J5cHRpbmcgdHJhZmZpYyB0byBhbiBBcHBsaWNhdGlvbiBMb2FkIEJhbGFuY2VyIHVzaW5nIEhUVFBTLlwiXG4gICAgKTtcbiAgICBpZiAobGlzdGVuZXJQcm9wcy5jZXJ0aWZpY2F0ZXM/Lmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkhUVFAgbGlzdGVuZXJzIGNhbm5vdCB1c2UgYSBjZXJ0aWZpY2F0ZVwiKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFsaXN0ZW5lclByb3BzLmNlcnRpZmljYXRlcyB8fCBsaXN0ZW5lclByb3BzLmNlcnRpZmljYXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkEgbGlzdGVuZXIgdXNpbmcgSFRUUFMgcHJvdG9jb2wgcmVxdWlyZXMgYSBjZXJ0aWZpY2F0ZVwiKTtcbiAgICB9XG5cbiAgICBsaXN0ZW5lci5hZGRDZXJ0aWZpY2F0ZXMoYCR7aWR9LWNlcnRgLCBsaXN0ZW5lclByb3BzLmNlcnRpZmljYXRlcyk7XG4gIH1cblxuICBpZiAoY29uc29saWRhdGVkTGlzdGVuZXJQcm9wcy5wcm90b2NvbCA9PT0gZWxiLkFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFMpIHtcbiAgICBjb25zdCBvcHQ6IGVsYi5SZWRpcmVjdE9wdGlvbnMgPSB7XG4gICAgICBwb3J0OiBcIjQ0M1wiLFxuICAgICAgcHJvdG9jb2w6IFwiSFRUUFNcIixcbiAgICB9O1xuXG4gICAgLy8gTk9TT05BUjogKHR5cGVzY3JpcHQ6UzUzMzIpXG4gICAgLy8gVGhpcyBsaXN0ZW5lciBpcyBleHBsaWNpdGx5IGNyZWF0ZWQgdG8gcmVkaXJlY3Qgbm9uIFRMUyBjb25uZWN0aW9uc1xuICAgIC8vIFRoZSBsYWNrIG9mIFNTTC9UTFMgaXMgaW50ZW50aW9uYWxcbiAgICBjb25zdCBodHRwTGlzdGVuZXIgPSBuZXcgZWxiLkFwcGxpY2F0aW9uTGlzdGVuZXIoXG4gICAgICBzY29wZSxcbiAgICAgIGAke2lkfS1yZWRpcmVjdGAsXG4gICAgICB7XG4gICAgICAgIGxvYWRCYWxhbmNlcixcbiAgICAgICAgcHJvdG9jb2w6IEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUCwgLy8gTk9TT05BUlxuICAgICAgICBkZWZhdWx0QWN0aW9uOiBMaXN0ZW5lckFjdGlvbi5yZWRpcmVjdChvcHQpLFxuICAgICAgfVxuICAgICk7XG4gICAgbG9hZEJhbGFuY2VyLmxpc3RlbmVycy5wdXNoKGh0dHBMaXN0ZW5lcik7XG4gIH1cblxuICByZXR1cm4gbGlzdGVuZXI7XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqXG4gKiBDcmVhdGVzIGEgVGFyZ2V0IEdyb3VwIGZvciBMYW1iZGEgZnVuY3Rpb25zIGFuZCBhZGRzIHRoZVxuICogcHJvdmlkZWQgZnVuY3Rpb25zIGFzIGEgdGFyZ2V0IHRvIHRoYXQgZ3JvdXAuIFRoZW4gYWRkc1xuICogdGhlIG5ldyBUYXJnZXQgR3JvdXAgdG8gdGhlIHByb3ZpZGVkIExpc3RlbmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQWRkTGFtYmRhVGFyZ2V0KFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogc3RyaW5nLFxuICBjdXJyZW50TGlzdGVuZXI6IGVsYi5BcHBsaWNhdGlvbkxpc3RlbmVyLFxuICBsYW1iZGFGdW5jdGlvbjogbGFtYmRhLklGdW5jdGlvbixcbiAgcnVsZVByb3BzPzogZWxiLkFkZFJ1bGVQcm9wcyxcbiAgdGFyZ2V0UHJvcHM/OiBlbGIuQXBwbGljYXRpb25UYXJnZXRHcm91cFByb3BzLFxuKTogZWxiLkFwcGxpY2F0aW9uVGFyZ2V0R3JvdXAgIHtcblxuICAvLyAgQ3JlYXRlIHRoZSB0YXJnZXQgYW5kIGFzc2lnbiBpdCB0byBhIG5ldyB0YXJnZXQgZ3JvdXBcbiAgY29uc3QgbGFtYmRhVGFyZ2V0ID0gbmV3IGVsYnQuTGFtYmRhVGFyZ2V0KGxhbWJkYUZ1bmN0aW9uKTtcbiAgY29uc3QgbmV3VGFyZ2V0R3JvdXAgPSBuZXcgZWxiLkFwcGxpY2F0aW9uVGFyZ2V0R3JvdXAoc2NvcGUsIGAke2lkfS10Z2AsIHtcbiAgICB0YXJnZXRzOiBbbGFtYmRhVGFyZ2V0XSxcbiAgICB0YXJnZXRHcm91cE5hbWU6IHRhcmdldFByb3BzID8gdGFyZ2V0UHJvcHMudGFyZ2V0R3JvdXBOYW1lIDogdW5kZWZpbmVkLFxuICAgIGhlYWx0aENoZWNrOiB0YXJnZXRQcm9wcyA/IHRhcmdldFByb3BzLmhlYWx0aENoZWNrIDogdW5kZWZpbmVkXG4gIH0pO1xuXG4gIC8vIFRoZSBpbnRlcmZhY2UgQWRkUnVsZVByb3BzIGluY2x1ZGVzIGNvbmRpdGlvbnMgYW5kIHByaW9yaXR5LCBjb21iaW5lIHRoYXRcbiAgLy8gd2l0aCB0YXJnZXRHcm91cHMgYW5kIHdlIGNhbiBhc3NlbWJsZSBBZGRBcHBsaWNhdGlvblRhcmdldEdyb3VwUHJvcHNcbiAgY29uc3QgY29uc29saWRhdGVkVGFyZ2V0UHJvcHMgPSBjb25zb2xpZGF0ZVByb3BzKHt9LCBydWxlUHJvcHMsIHsgdGFyZ2V0R3JvdXBzOiBbbmV3VGFyZ2V0R3JvdXBdIH0pO1xuICBjdXJyZW50TGlzdGVuZXIuYWRkVGFyZ2V0R3JvdXBzKGAke3Njb3BlLm5vZGUuaWR9LXRhcmdldHNgLCBjb25zb2xpZGF0ZWRUYXJnZXRQcm9wcyk7XG5cbiAgbmV3VGFyZ2V0R3JvdXAuc2V0QXR0cmlidXRlKCdzdGlja2luZXNzLmVuYWJsZWQnLCB1bmRlZmluZWQpO1xuICByZXR1cm4gbmV3VGFyZ2V0R3JvdXA7XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFkZEZhcmdhdGVUYXJnZXQoXG4gIHNjb3BlOiBDb25zdHJ1Y3QsXG4gIGlkOiBzdHJpbmcsXG4gIGN1cnJlbnRMaXN0ZW5lcjogZWxiLkFwcGxpY2F0aW9uTGlzdGVuZXIsXG4gIGZhcmdhdGVTZXJ2aWNlOiBlY3MuRmFyZ2F0ZVNlcnZpY2UsXG4gIHJ1bGVQcm9wcz86IGVsYi5BZGRSdWxlUHJvcHMsXG4gIHRhcmdldFByb3BzPzogZWxiLkFwcGxpY2F0aW9uVGFyZ2V0R3JvdXBQcm9wcyxcbik6IGVsYi5BcHBsaWNhdGlvblRhcmdldEdyb3VwICB7XG5cbiAgaWYgKHRhcmdldFByb3BzPy5wcm90b2NvbCAhPT0gZWxiLkFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFMpIHtcbiAgICBwcmludFdhcm5pbmcoJ0FXUyByZWNvbW1lbmRzIHVzaW5nIEhUVFBTIHByb3RvY29sIGZvciBUYXJnZXQgR3JvdXBzIGluIHByb2R1Y3Rpb24gYXBwbGljYXRpb25zJyk7XG4gIH1cblxuICBjb25zdCBuZXdUYXJnZXRHcm91cCA9IG5ldyBlbGIuQXBwbGljYXRpb25UYXJnZXRHcm91cChzY29wZSwgYCR7aWR9LXRnYCwgdGFyZ2V0UHJvcHMpO1xuXG4gIC8vIFRoZSBpbnRlcmZhY2UgQWRkUnVsZVByb3BzIGluY2x1ZGVzIGNvbmRpdGlvbnMgYW5kIHByaW9yaXR5LCBjb21iaW5lIHRoYXRcbiAgLy8gd2l0aCB0YXJnZXRHcm91cHMgYW5kIHdlIGNhbiBhc3NlbWJsZSBhbiBBZGRBcHBsaWNhdGlvblRhcmdldEdyb3VwUHJvcHMgb2JqZWN0XG4gIGNvbnN0IGNvbnNvbGlkYXRlZFRhcmdldFByb3BzID0gY29uc29saWRhdGVQcm9wcyh7IHRhcmdldEdyb3VwczogW25ld1RhcmdldEdyb3VwXSB9LCBydWxlUHJvcHMpO1xuXG4gIGN1cnJlbnRMaXN0ZW5lci5hZGRUYXJnZXRHcm91cHMoYCR7c2NvcGUubm9kZS5pZH0tdGFyZ2V0c2AsIGNvbnNvbGlkYXRlZFRhcmdldFByb3BzKTtcbiAgbmV3VGFyZ2V0R3JvdXAuYWRkVGFyZ2V0KGZhcmdhdGVTZXJ2aWNlKTtcblxuICByZXR1cm4gbmV3VGFyZ2V0R3JvdXA7XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqXG4gKiBMb29rcyBmb3IgdGhlIGxpc3RlbmVyIGFzc29jaWF0ZWQgd2l0aCBUYXJnZXQgR3JvdXBzXG4gKiBJZiB0aGVyZSBpcyBhIHNpbmdsZSBsaXN0ZW5lciwgdGhpcyByZXR1cm5zIGl0IHdoZXRoZXIgaXQgaXMgSFRUUCBvciBIVFRQU1xuICogSWYgdGhlcmUgYXJlIDIgbGlzdGVuZXJzLCBpdCBmaW5kcyB0aGUgSFRUUFMgbGlzdGVuZXIgKHdlIGFzc3VtZSB0aGUgSFRUUCBsaXN0ZW5lciByZWRpcmVjdHMgdG8gSFRUUFMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRBY3RpdmVMaXN0ZW5lcihsaXN0ZW5lcnM6IGVsYi5BcHBsaWNhdGlvbkxpc3RlbmVyW10pOiBlbGIuQXBwbGljYXRpb25MaXN0ZW5lciB7XG4gIGxldCBsaXN0ZW5lcjogZWxiLkFwcGxpY2F0aW9uTGlzdGVuZXI7XG5cbiAgaWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDAgKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBUaGVyZSBhcmUgbm8gbGlzdGVuZXJzIGluIHRoZSBBTEJgKTtcbiAgfVxuICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMSApIHtcbiAgICBsaXN0ZW5lciA9IGxpc3RlbmVyc1swXTtcbiAgfSBlbHNlIHtcbiAgICBsaXN0ZW5lciA9IGxpc3RlbmVycy5maW5kKGkgPT4gKGkubm9kZS5jaGlsZHJlblswXSBhcyBlbGIuQ2ZuTGlzdGVuZXIpLnByb3RvY29sID09PSBcIkhUVFBTXCIpIGFzIGVsYi5BcHBsaWNhdGlvbkxpc3RlbmVyO1xuICB9XG4gIHJldHVybiBsaXN0ZW5lcjtcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWwgVGhpcyBpcyBhbiBpbnRlcm5hbCBjb3JlIGZ1bmN0aW9uIGFuZCBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSBieSBTb2x1dGlvbnMgQ29uc3RydWN0cyBjbGllbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2hlY2tBbGJQcm9wcyhwcm9wczogYW55KSB7XG4gIGxldCBlcnJvck1lc3NhZ2VzID0gJyc7XG4gIGxldCBlcnJvckZvdW5kID0gZmFsc2U7XG5cbiAgaWYgKHByb3BzLmxvYWRCYWxhbmNlclByb3BzICYmIHByb3BzLmV4aXN0aW5nTG9hZEJhbGFuY2VyT2JqKSB7XG4gICAgZXJyb3JNZXNzYWdlcyArPSAnRXJyb3IgLSBFaXRoZXIgcHJvdmlkZSBsb2FkQmFsYW5jZXJQcm9wcyBvciBleGlzdGluZ0xvYWRCYWxhbmNlck9iaiwgYnV0IG5vdCBib3RoLlxcbic7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gIH1cblxuICBpZiAoKHByb3BzPy5sb2dBbGJBY2Nlc3NMb2dzID09PSBmYWxzZSkgJiYgKHByb3BzLmFsYkxvZ2dpbmdCdWNrZXRQcm9wcykpIHtcbiAgICBlcnJvck1lc3NhZ2VzICs9ICdFcnJvciAtIElmIGxvZ0FsYkFjY2Vzc0xvZ3MgaXMgZmFsc2UsIHN1cHBseWluZyBhbGJMb2dnaW5nQnVja2V0UHJvcHMgaXMgaW52YWxpZC5cXG4nO1xuICAgIGVycm9yRm91bmQgPSB0cnVlO1xuICB9XG5cbiAgaWYgKHByb3BzLmxpc3RlbmVyUHJvcHM/LmNlcnRpZmljYXRlQXJucykge1xuICAgIGVycm9yTWVzc2FnZXMgKz0gXCJjZXJ0aWZpY2F0ZUFybnMgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHN1cHBseSBjZXJ0aWZpY2F0ZXMgdXNpbmcgcHJvcHMubGlzdGVuZXJQcm9wcy5jZXJ0aWZpY2F0ZXNcXG5cIjtcbiAgICBlcnJvckZvdW5kID0gdHJ1ZTtcbiAgfVxuXG4gIGlmIChWYWxpZGF0ZUFkZExpc3RlbmVyUHJvcHMocHJvcHMpKSB7XG4gICAgZXJyb3JNZXNzYWdlcyArPSBcIldoZW4gYWRkaW5nIHRoZSBmaXJzdCBsaXN0ZW5lciBhbmQgdGFyZ2V0IHRvIGEgbG9hZCBiYWxhbmNlciwgbGlzdGVuZXJQcm9wcyBtdXN0IGJlIHNwZWNpZmllZCBhbmQgaW5jbHVkZSBhdCBsZWFzdCBhIGNlcnRpZmljYXRlIG9yIHByb3RvY29sOiBIVFRQXFxuXCI7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gIH1cblxuICBpZiAoXG4gICAgcHJvcHMuZXhpc3RpbmdMb2FkQmFsYW5jZXJPYmogJiZcbiAgICBwcm9wcy5leGlzdGluZ0xvYWRCYWxhbmNlck9iai5saXN0ZW5lcnMubGVuZ3RoID4gMCAmJlxuICAgIHByb3BzLmxpc3RlbmVyUHJvcHNcbiAgKSB7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gICAgZXJyb3JNZXNzYWdlcyArPSBcIlRoaXMgbG9hZCBiYWxhbmNlciBhbHJlYWR5IGhhcyBhIGxpc3RlbmVyLCBsaXN0ZW5lclByb3BzIG1heSBub3QgYmUgc3BlY2lmaWVkXFxuXCI7XG4gIH1cblxuICBpZiAoXG4gICAgcHJvcHMuZXhpc3RpbmdMb2FkQmFsYW5jZXJPYmogJiZcbiAgICBwcm9wcy5leGlzdGluZ0xvYWRCYWxhbmNlck9iai5saXN0ZW5lcnMubGVuZ3RoID4gMCAmJlxuICAgICFwcm9wcy5ydWxlUHJvcHNcbiAgKSB7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gICAgZXJyb3JNZXNzYWdlcyArPSBcIldoZW4gYWRkaW5nIGEgc2Vjb25kIHRhcmdldCB0byBhbiBleGlzdGluZyBsaXN0ZW5lciwgdGhlcmUgbXVzdCBiZSBydWxlcyBwcm92aWRlZFxcblwiO1xuICB9XG5cbiAgLy8gQ2hlY2sgY29uc3RydWN0IHNwZWNpZmljIGludmFsaWQgaW5wdXRzXG4gIGlmIChwcm9wcy5leGlzdGluZ0xvYWRCYWxhbmNlck9iaiAmJiAhcHJvcHMuZXhpc3RpbmdWcGMpIHtcbiAgICBlcnJvckZvdW5kID0gdHJ1ZTtcbiAgICBlcnJvck1lc3NhZ2VzICs9IFwiQW4gZXhpc3RpbmcgQUxCIGlzIGFscmVhZHkgaW4gYSBWUEMsIHRoYXQgVlBDIG11c3QgYmUgcHJvdmlkZWQgaW4gcHJvcHMuZXhpc3RpbmdWcGMgZm9yIHRoZSByZXN0IG9mIHRoZSBjb25zdHJ1Y3QgdG8gdXNlLlxcblwiO1xuICB9XG5cbiAgaWYgKHByb3BzLmxvYWRCYWxhbmNlclByb3BzPy52cGMpIHtcbiAgICAvLyBPbmx5IHJlYXNvbiB0aGlzIHNob3VsZCBleGlzdCBpcyB0byBlbmFibGUgc3BlY2lmeWluZyBBTEIgbmV0d29yayBjb25maWd1cmF0aW9uLiBUaGVyZSBtdXN0IHN0aWxsXG4gICAgLy8gYmUgYSBjb25zdHJ1Y3QgVlBDIGFuZCAgdGhleSBtdXN0IG1hdGNoXG4gICAgaWYgKCghcHJvcHMuZXhpc3RpbmdWcGMpIHx8IChwcm9wcy5leGlzdGluZ1ZwYy52cGNJZCAhPT0gcHJvcHMubG9hZEJhbGFuY2VyUHJvcHM/LnZwYy52cGNJZCkpIHtcbiAgICAgIGVycm9yRm91bmQgPSB0cnVlO1xuICAgICAgZXJyb3JNZXNzYWdlcyArPSAnQW55IGV4aXN0aW5nIFZQQyBtdXN0IGJlIGRlZmluZWQgaW4gdGhlIGNvbnN0cnVjdCBwcm9wcyAocHJvcHMuZXhpc3RpbmdWcGMpLiBBIFZQQyBzcGVjaWZpZWQgaW4gdGhlIGxvYWRCYWxhbmNlclByb3BzIG11c3QgYmUgdGhlIHNhbWUgVlBDJztcbiAgICB9XG4gIH1cblxuICBpZiAocHJvcHMuZXhpc3RpbmdMb2FkQmFsYW5jZXJPYmopIHtcbiAgICBwcmludFdhcm5pbmcoXG4gICAgICBcIlRoZSBwdWJsaWMvcHJpdmF0ZSBwcm9wZXJ0eSBvZiBhbiBleGlzdGluZyBBTEIgbXVzdCBtYXRjaCB0aGUgcHJvcHMucHVibGljQXBpIHNldHRpbmcgcHJvdmlkZWQuXCJcbiAgICApO1xuICB9XG5cbiAgaWYgKGVycm9yRm91bmQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlcyk7XG4gIH1cblxufVxuXG5mdW5jdGlvbiBWYWxpZGF0ZUFkZExpc3RlbmVyUHJvcHMocHJvcHM6IGFueSkge1xuICBpZiAoKChwcm9wcy5leGlzdGluZ0xvYWRCYWxhbmNlck9iaiAmJlxuICAgIHByb3BzLmV4aXN0aW5nTG9hZEJhbGFuY2VyT2JqLmxpc3RlbmVycy5sZW5ndGggPT09IDApIHx8XG4gICAgIXByb3BzLmV4aXN0aW5nTG9hZEJhbGFuY2VyT2JqKSAmJlxuICAhcHJvcHMubGlzdGVuZXJQcm9wcykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==
;