@aws-solutions-constructs/core
Version:
Core CDK Construct for patterns library
154 lines • 24.6 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.idPlaceholder = void 0;
exports.buildStateMachine = buildStateMachine;
exports.buildStepFunctionCWAlarms = buildStepFunctionCWAlarms;
exports.CheckStateMachineProps = CheckStateMachineProps;
const cdk = require("aws-cdk-lib");
const smDefaults = require("./step-function-defaults");
const sfn = require("aws-cdk-lib/aws-stepfunctions");
const utils_1 = require("./utils");
const cloudwatch = require("aws-cdk-lib/aws-cloudwatch");
const cloudwatch_log_group_helper_1 = require("./cloudwatch-log-group-helper");
/*
* the id parameter was added to buildStateMachine() long after the original implementation,
* this value can be used for the new parameter and ensure behavior is the same.
* (if we just require an id, the state machine name will be changed and it will be a
* destructive change)
*/
exports.idPlaceholder = undefined;
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*
* Builds and returns a StateMachine.
* @param scope - the construct to which the StateMachine should be attached to.
* @param stateMachineProps - user-specified properties to override the default properties.
*/
function buildStateMachine(scope, id, props) {
let logGroup;
let consolidatedStateMachineProps;
// If they sent a logGroup in stateMachineProps
if (props.stateMachineProps.logs?.destination) {
logGroup = props.stateMachineProps.logs?.destination;
consolidatedStateMachineProps = props.stateMachineProps;
}
else {
// Three possibilities
// 1) logGroupProps not provided - create logGroupProps with just logGroupName
// 2) logGroupProps provided with no logGroupName - override logGroupProps.logGroupName
// 3) logGroupProps provided with logGroupName - pass unaltered logGroupProps
let consolidatedLogGroupProps = props.logGroupProps;
if (!consolidatedLogGroupProps) {
consolidatedLogGroupProps = {};
}
if (!consolidatedLogGroupProps?.logGroupName) {
const logGroupPrefix = '/aws/vendedlogs/states/constructs/';
const nameParts = [
cdk.Stack.of(scope).stackName, // Name of the stack
id ?? scope.node.id, // Use the ID from client if provided, otherwise use the construct ID
'StateMachineLog' // Literal string for log group name portion
];
const logGroupName = (0, utils_1.generatePhysicalLogGroupName)(logGroupPrefix, nameParts);
consolidatedLogGroupProps = (0, utils_1.overrideProps)(consolidatedLogGroupProps, { logGroupName });
}
// Create new Cloudwatch log group for Step function State Machine
logGroup = (0, cloudwatch_log_group_helper_1.buildLogGroup)(scope, `StateMachineLogGroup${(id ?? '')}`, consolidatedLogGroupProps);
// Override the defaults with the user provided props
consolidatedStateMachineProps = (0, utils_1.overrideProps)(smDefaults.DefaultStateMachineProps(logGroup), props.stateMachineProps);
}
// Override the Cloudwatch permissions to make it more fine grained
const newStateMachine = new sfn.StateMachine(scope, `StateMachine${(id ?? '')}`, consolidatedStateMachineProps);
// If the client did not pass a role we got the default role and will trim the privileges
if (!props.stateMachineProps.role) {
const role = newStateMachine.node.findChild('Role');
const cfnDefaultPolicy = role.node.findChild('DefaultPolicy').node.defaultChild;
// Override Cfn Nag warning W12: IAM policy should not allow * resource
(0, utils_1.addCfnSuppressRules)(cfnDefaultPolicy, [
{
id: 'W12',
reason: `These are CDK defaults. The 'LogDelivery' actions do not support resource-level authorizations. Any logging is done by State Machine code`
}
]);
}
const createCloudWatchAlarms = (props.createCloudWatchAlarms === undefined || props.createCloudWatchAlarms);
const cloudWatchAlarms = createCloudWatchAlarms ? buildStepFunctionCWAlarms(scope, props.cloudWatchAlarmsPrefix, newStateMachine) : undefined;
return {
stateMachine: newStateMachine,
logGroup,
cloudWatchAlarms
};
}
/**
* @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
*/
function buildStepFunctionCWAlarms(scope, id, sm) {
// Setup CW Alarms for State Machine
const alarms = new Array();
const prefix = id ?? "";
// Sum of number of executions that failed is >= 1 for 5 minutes, 1 consecutive time
alarms.push(new cloudwatch.Alarm(scope, `${prefix}ExecutionFailedAlarm`, {
metric: sm.metricFailed({
statistic: 'Sum',
period: cdk.Duration.seconds(300),
}),
threshold: 1,
evaluationPeriods: 1,
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
alarmDescription: 'Alarm for the number of executions that failed exceeded the threshold of 1. '
}));
// Sum of number of executions that failed maximum is >= 1 for 5 minute, 1 consecutive time
alarms.push(new cloudwatch.Alarm(scope, `${prefix}ExecutionThrottledAlarm`, {
metric: sm.metricThrottled({
statistic: 'Sum',
period: cdk.Duration.seconds(300),
}),
threshold: 1,
evaluationPeriods: 1,
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
alarmDescription: 'Alarm for the number of executions that throttled exceeded the threshold of 1. '
}));
// Number of executions that aborted maximum is >= 1 for 5 minute, 1 consecutive time
alarms.push(new cloudwatch.Alarm(scope, `${prefix}ExecutionAbortedAlarm`, {
metric: sm.metricAborted({
statistic: 'Maximum',
period: cdk.Duration.seconds(300),
}),
threshold: 1,
evaluationPeriods: 1,
comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
alarmDescription: 'Alarm for the number of executions that aborted exceeded the threshold of 1. '
}));
return alarms;
}
function CheckStateMachineProps(propsObject) {
let errorMessages = '';
let errorFound = false;
if ((propsObject.createCloudWatchAlarms === false) && propsObject.cloudWatchAlarmsPrefix) {
errorMessages += 'Error - cloudWatchAlarmsPrefix is invalid when createCloudWatchAlarms is false\n';
errorFound = true;
}
if ((propsObject.existingStateMachineObj) &&
(propsObject.stateMachineProps ||
(propsObject.createCloudWatchAlarms !== undefined) ||
propsObject.cloudWatchAlarmsPrefix ||
propsObject.logGroupProps)) {
errorMessages += 'ERROR - If existingStateMachine is provided, no other state machine props are allowed\n';
errorFound = true;
}
if (errorFound) {
throw new Error(errorMessages);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1mdW5jdGlvbi1oZWxwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdGVwLWZ1bmN0aW9uLWhlbHBlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7OztBQThDSCw4Q0E4REM7QUFLRCw4REEwQ0M7QUFVRCx3REFzQkM7QUFsTEQsbUNBQW1DO0FBQ25DLHVEQUF1RDtBQUN2RCxxREFBcUQ7QUFDckQsbUNBQTJGO0FBRTNGLHlEQUF5RDtBQUN6RCwrRUFBOEQ7QUFJOUQ7Ozs7O0dBS0c7QUFDVSxRQUFBLGFBQWEsR0FBRyxTQUFTLENBQUM7QUFjdkM7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsS0FBZ0IsRUFBRSxFQUFzQixFQUFFLEtBQTRCO0lBRXRHLElBQUksUUFBd0IsQ0FBQztJQUM3QixJQUFJLDZCQUE2QixDQUFDO0lBRWxDLCtDQUErQztJQUMvQyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDOUMsUUFBUSxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDO1FBQ3JELDZCQUE2QixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztJQUMxRCxDQUFDO1NBQU0sQ0FBQztRQUNOLHNCQUFzQjtRQUN0Qiw4RUFBOEU7UUFDOUUsdUZBQXVGO1FBQ3ZGLDZFQUE2RTtRQUM3RSxJQUFJLHlCQUF5QixHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUM7UUFFcEQsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7WUFDL0IseUJBQXlCLEdBQUcsRUFBRSxDQUFDO1FBQ2pDLENBQUM7UUFFRCxJQUFJLENBQUMseUJBQXlCLEVBQUUsWUFBWSxFQUFFLENBQUM7WUFDN0MsTUFBTSxjQUFjLEdBQUcsb0NBQW9DLENBQUM7WUFDNUQsTUFBTSxTQUFTLEdBQWE7Z0JBQzFCLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFB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QWEsSUFBSSxrRkFBa0YsQ0FBQztRQUNwRyxVQUFVLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxJQUFJLENBQUMsV0FBVyxDQUFDLHVCQUF1QixDQUFDO1FBQ3ZDLENBQUMsV0FBVyxDQUFDLGlCQUFpQjtZQUM1QixDQUFDLFdBQVcsQ0FBQyxzQkFBc0IsS0FBSyxTQUFTLENBQUM7WUFDbEQsV0FBVyxDQUFDLHNCQUFzQjtZQUNsQyxXQUFXLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztRQUUvQixhQUFhLElBQUkseUZBQXlGLENBQUM7UUFDM0csVUFBVSxHQUFHLElBQUksQ0FBQztJQUNwQixDQUFDO0lBRUQsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNmLE1BQU0sSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDakMsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG4vKlxuICogIFRoZSBmdW5jdGlvbnMgZm91bmQgaGVyZSBpbiB0aGUgY29yZSBsaWJyYXJ5IGFyZSBmb3IgaW50ZXJuYWwgdXNlIGFuZCBjYW4gYmUgY2hhbmdlZFxuICogIG9yIHJlbW92ZWQgb3V0c2lkZSBvZiBhIG1ham9yIHJlbGVhc2UuIFdlIHJlY29tbWVuZCBhZ2FpbnN0IGNhbGxpbmcgdGhlbSBkaXJlY3RseSBmcm9tIGNsaWVudCBjb2RlLlxuICovXG5cbi8vIEltcG9ydHNcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIHNtRGVmYXVsdHMgZnJvbSAnLi9zdGVwLWZ1bmN0aW9uLWRlZmF1bHRzJztcbmltcG9ydCAqIGFzIHNmbiBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgeyBvdmVycmlkZVByb3BzLCBhZGRDZm5TdXBwcmVzc1J1bGVzLCBnZW5lcmF0ZVBoeXNpY2FsTG9nR3JvdXBOYW1lIH0gZnJvbSAnLi91dGlscyc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBjbG91ZHdhdGNoIGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoJztcbmltcG9ydCB7IGJ1aWxkTG9nR3JvdXAgfSBmcm9tICcuL2Nsb3Vkd2F0Y2gtbG9nLWdyb3VwLWhlbHBlcic7XG4vLyBOb3RlOiBUbyBlbnN1cmUgQ0RLdjIgY29tcGF0aWJpbGl0eSwga2VlcCB0aGUgaW1wb3J0IHN0YXRlbWVudCBmb3IgQ29uc3RydWN0IHNlcGFyYXRlXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuLypcbiAqIHRoZSBpZCBwYXJhbWV0ZXIgd2FzIGFkZGVkIHRvIGJ1aWxkU3RhdGVNYWNoaW5lKCkgbG9uZyBhZnRlciB0aGUgb3JpZ2luYWwgaW1wbGVtZW50YXRpb24sXG4gKiB0aGlzIHZhbHVlIGNhbiBiZSB1c2VkIGZvciB0aGUgbmV3IHBhcmFtZXRlciBhbmQgZW5zdXJlIGJlaGF2aW9yIGlzIHRoZSBzYW1lLlxuICogKGlmIHdlIGp1c3QgcmVxdWlyZSBhbiBpZCwgdGhlIHN0YXRlIG1hY2hpbmUgbmFtZSB3aWxsIGJlIGNoYW5nZWQgYW5kIGl0IHdpbGwgYmUgYVxuICogZGVzdHJ1Y3RpdmUgY2hhbmdlKVxuICovXG5leHBvcnQgY29uc3QgaWRQbGFjZWhvbGRlciA9IHVuZGVmaW5lZDtcblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZFN0YXRlTWFjaW5lUHJvcHMge1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmVQcm9wczogc2ZuLlN0YXRlTWFjaGluZVByb3BzLFxuICByZWFkb25seSBsb2dHcm91cFByb3BzPzogbG9ncy5Mb2dHcm91cFByb3BzLFxuICByZWFkb25seSBjcmVhdGVDbG91ZFdhdGNoQWxhcm1zPzogYm9vbGVhbixcbiAgcmVhZG9ubHkgY2xvdWRXYXRjaEFsYXJtc1ByZWZpeD86IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkU3RhdGVNYWNoaW5lUmVzcG9uc2Uge1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmU6IHNmbi5TdGF0ZU1hY2hpbmUsXG4gIHJlYWRvbmx5IGxvZ0dyb3VwOiBsb2dzLklMb2dHcm91cCxcbiAgcmVhZG9ubHkgY2xvdWRXYXRjaEFsYXJtcz86IGNsb3Vkd2F0Y2guQWxhcm1bXVxufVxuLyoqXG4gKiBAaW50ZXJuYWwgVGhpcyBpcyBhbiBpbnRlcm5hbCBjb3JlIGZ1bmN0aW9uIGFuZCBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSBieSBTb2x1dGlvbnMgQ29uc3RydWN0cyBjbGllbnRzLlxuICpcbiAqIEJ1aWxkcyBhbmQgcmV0dXJucyBhIFN0YXRlTWFjaGluZS5cbiAqIEBwYXJhbSBzY29wZSAtIHRoZSBjb25zdHJ1Y3QgdG8gd2hpY2ggdGhlIFN0YXRlTWFjaGluZSBzaG91bGQgYmUgYXR0YWNoZWQgdG8uXG4gKiBAcGFyYW0gc3RhdGVNYWNoaW5lUHJvcHMgLSB1c2VyLXNwZWNpZmllZCBwcm9wZXJ0aWVzIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IHByb3BlcnRpZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFN0YXRlTWFjaGluZShzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nIHwgdW5kZWZpbmVkLCBwcm9wczogQnVpbGRTdGF0ZU1hY2luZVByb3BzKTogQnVpbGRTdGF0ZU1hY2hpbmVSZXNwb25zZSB7XG5cbiAgbGV0IGxvZ0dyb3VwOiBsb2dzLklMb2dHcm91cDtcbiAgbGV0IGNvbnNvbGlkYXRlZFN0YXRlTWFjaGluZVByb3BzO1xuXG4gIC8vIElmIHRoZXkgc2VudCBhIGxvZ0dyb3VwIGluIHN0YXRlTWFjaGluZVByb3BzXG4gIGlmIChwcm9wcy5zdGF0ZU1hY2hpbmVQcm9wcy5sb2dzPy5kZXN0aW5hdGlvbikge1xuICAgIGxvZ0dyb3VwID0gcHJvcHMuc3RhdGVNYWNoaW5lUHJvcHMubG9ncz8uZGVzdGluYXRpb247XG4gICAgY29uc29saWRhdGVkU3RhdGVNYWNoaW5lUHJvcHMgPSBwcm9wcy5zdGF0ZU1hY2hpbmVQcm9wcztcbiAgfSBlbHNlIHtcbiAgICAvLyBUaHJlZSBwb3NzaWJpbGl0aWVzXG4gICAgLy8gMSkgbG9nR3JvdXBQcm9wcyBub3QgcHJvdmlkZWQgLSBjcmVhdGUgbG9nR3JvdXBQcm9wcyB3aXRoIGp1c3QgbG9nR3JvdXBOYW1lXG4gICAgLy8gMikgbG9nR3JvdXBQcm9wcyBwcm92aWRlZCB3aXRoIG5vIGxvZ0dyb3VwTmFtZSAtIG92ZXJyaWRlIGxvZ0dyb3VwUHJvcHMubG9nR3JvdXBOYW1lXG4gICAgLy8gMykgbG9nR3JvdXBQcm9wcyBwcm92aWRlZCB3aXRoIGxvZ0dyb3VwTmFtZSAtIHBhc3MgdW5hbHRlcmVkIGxvZ0dyb3VwUHJvcHNcbiAgICBsZXQgY29uc29saWRhdGVkTG9nR3JvdXBQcm9wcyA9IHByb3BzLmxvZ0dyb3VwUHJvcHM7XG5cbiAgICBpZiAoIWNvbnNvbGlkYXRlZExvZ0dyb3VwUHJvcHMpIHtcbiAgICAgIGNvbnNvbGlkYXRlZExvZ0dyb3VwUHJvcHMgPSB7fTtcbiAgICB9XG5cbiAgICBpZiAoIWNvbnNvbGlkYXRlZExvZ0dyb3VwUHJvcHM/LmxvZ0dyb3VwTmFtZSkge1xuICAgICAgY29uc3QgbG9nR3JvdXBQcmVmaXggPSAnL2F3cy92ZW5kZWRsb2dzL3N0YXRlcy9jb25zdHJ1Y3RzLyc7XG4gICAgICBjb25zdCBuYW1lUGFydHM6IHN0cmluZ1tdID0gW1xuICAgICAgICBjZGsuU3RhY2sub2Yoc2NvcGUpLnN0YWNrTmFtZSwgLy8gTmFtZSBvZiB0aGUgc3RhY2tcbiAgICAgICAgaWQgPz8gc2NvcGUubm9kZS5pZCwgICAgICAgICAgIC8vIFVzZSB0aGUgSUQgZnJvbSBjbGllbnQgaWYgcHJvdmlkZWQsIG90aGVyd2lzZSB1c2UgdGhlIGNvbnN0cnVjdCBJRFxuICAgICAgICAnU3RhdGVNYWNoaW5lTG9nJyAgICAgICAgICAgICAgLy8gTGl0ZXJhbCBzdHJpbmcgZm9yIGxvZyBncm91cCBuYW1lIHBvcnRpb25cbiAgICAgIF07XG5cbiAgICAgIGNvbnN0IGxvZ0dyb3VwTmFtZSA9IGdlbmVyYXRlUGh5c2ljYWxMb2dHcm91cE5hbWUobG9nR3JvdXBQcmVmaXgsIG5hbWVQYXJ0cyk7XG4gICAgICBjb25zb2xpZGF0ZWRMb2dHcm91cFByb3BzID0gb3ZlcnJpZGVQcm9wcyhjb25zb2xpZGF0ZWRMb2dHcm91cFByb3BzLCB7IGxvZ0dyb3VwTmFtZSB9KTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgbmV3IENsb3Vkd2F0Y2ggbG9nIGdyb3VwIGZvciBTdGVwIGZ1bmN0aW9uIFN0YXRlIE1hY2hpbmVcbiAgICBsb2dHcm91cCA9IGJ1aWxkTG9nR3JvdXAoc2NvcGUsIGBTdGF0ZU1hY2hpbmVMb2dHcm91cCR7KGlkID8/ICcnKX1gLCBjb25zb2xpZGF0ZWRMb2dHcm91cFByb3BzKTtcblxuICAgIC8vIE92ZXJyaWRlIHRoZSBkZWZhdWx0cyB3aXRoIHRoZSB1c2VyIHByb3ZpZGVkIHByb3BzXG4gICAgY29uc29saWRhdGVkU3RhdGVNYWNoaW5lUHJvcHMgPSBvdmVycmlkZVByb3BzKHNtRGVmYXVsdHMuRGVmYXVsdFN0YXRlTWFjaGluZVByb3BzKGxvZ0dyb3VwKSwgcHJvcHMuc3RhdGVNYWNoaW5lUHJvcHMpO1xuICB9XG5cbiAgLy8gT3ZlcnJpZGUgdGhlIENsb3Vkd2F0Y2ggcGVybWlzc2lvbnMgdG8gbWFrZSBpdCBtb3JlIGZpbmUgZ3JhaW5lZFxuICBjb25zdCBuZXdTdGF0ZU1hY2hpbmUgPSBuZXcgc2ZuLlN0YXRlTWFjaGluZShzY29wZSwgYFN0YXRlTWFjaGluZSR7KGlkID8/ICcnKX1gLCBjb25zb2xpZGF0ZWRTdGF0ZU1hY2hpbmVQcm9wcyk7XG5cbiAgLy8gSWYgdGhlIGNsaWVudCBkaWQgbm90IHBhc3MgYSByb2xlIHdlIGdvdCB0aGUgZGVmYXVsdCByb2xlIGFuZCB3aWxsIHRyaW0gdGhlIHByaXZpbGVnZXNcbiAgaWYgKCFwcm9wcy5zdGF0ZU1hY2hpbmVQcm9wcy5yb2xlKSB7XG4gICAgY29uc3Qgcm9sZSA9IG5ld1N0YXRlTWFjaGluZS5ub2RlLmZpbmRDaGlsZCgnUm9sZScpIGFzIGlhbS5Sb2xlO1xuICAgIGNvbnN0IGNmbkRlZmF1bHRQb2xpY3kgPSByb2xlLm5vZGUuZmluZENoaWxkKCdEZWZhdWx0UG9saWN5Jykubm9kZS5kZWZhdWx0Q2hpbGQgYXMgYW55O1xuICAgIC8vIE92ZXJyaWRlIENmbiBOYWcgd2FybmluZyBXMTI6IElBTSBwb2xpY3kgc2hvdWxkIG5vdCBhbGxvdyAqIHJlc291cmNlXG4gICAgYWRkQ2ZuU3VwcHJlc3NSdWxlcyhjZm5EZWZhdWx0UG9saWN5LCBbXG4gICAgICB7XG4gICAgICAgIGlkOiAnVzEyJyxcbiAgICAgICAgcmVhc29uOiBgVGhlc2UgYXJlIENESyBkZWZhdWx0cy4gVGhlICdMb2dEZWxpdmVyeScgYWN0aW9ucyBkbyBub3Qgc3VwcG9ydCByZXNvdXJjZS1sZXZlbCBhdXRob3JpemF0aW9ucy4gQW55IGxvZ2dpbmcgaXMgZG9uZSBieSBTdGF0ZSBNYWNoaW5lIGNvZGVgXG4gICAgICB9XG4gICAgXSk7XG4gIH1cbiAgY29uc3QgY3JlYXRlQ2xvdWRXYXRjaEFsYXJtczogYm9vbGVhbiA9IChwcm9wcy5jcmVhdGVDbG91ZFdhdGNoQWxhcm1zID09PSB1bmRlZmluZWQgfHwgcHJvcHMuY3JlYXRlQ2xvdWRXYXRjaEFsYXJtcyk7XG4gIGNvbnN0IGNsb3VkV2F0Y2hBbGFybXMgPSBjcmVhdGVDbG91ZFdhdGNoQWxhcm1zID8gYnVpbGRTdGVwRnVuY3Rpb25DV0FsYXJtcyhzY29wZSwgcHJvcHMuY2xvdWRXYXRjaEFsYXJtc1ByZWZpeCwgbmV3U3RhdGVNYWNoaW5lKSA6IHVuZGVmaW5lZDtcblxuICByZXR1cm4ge1xuICAgIHN0YXRlTWFjaGluZTogbmV3U3RhdGVNYWNoaW5lLFxuICAgIGxvZ0dyb3VwLFxuICAgIGNsb3VkV2F0Y2hBbGFybXNcbiAgfTtcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWwgVGhpcyBpcyBhbiBpbnRlcm5hbCBjb3JlIGZ1bmN0aW9uIGFuZCBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSBieSBTb2x1dGlvbnMgQ29uc3RydWN0cyBjbGllbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRTdGVwRnVuY3Rpb25DV0FsYXJtcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nIHwgdW5kZWZpbmVkLCBzbTogc2ZuLlN0YXRlTWFjaGluZSk6IGNsb3Vkd2F0Y2guQWxhcm1bXSB7XG4gIC8vIFNldHVwIENXIEFsYXJtcyBmb3IgU3RhdGUgTWFjaGluZVxuICBjb25zdCBhbGFybXM6IGNsb3Vkd2F0Y2guQWxhcm1bXSA9IG5ldyBBcnJheSgpO1xuICBjb25zdCBwcmVmaXggPSBpZCA/PyBcIlwiO1xuXG4gIC8vIFN1bSBvZiBudW1iZXIgb2YgZXhlY3V0aW9ucyB0aGF0IGZhaWxlZCBpcyA+PSAxIGZvciA1IG1pbnV0ZXMsIDEgY29uc2VjdXRpdmUgdGltZVxuICBhbGFybXMucHVzaChuZXcgY2xvdWR3YXRjaC5BbGFybShzY29wZSwgYCR7cHJlZml4fUV4ZWN1dGlvbkZhaWxlZEFsYXJtYCwge1xuICAgIG1ldHJpYzogc20ubWV0cmljRmFpbGVkKHtcbiAgICAgIHN0YXRpc3RpYzogJ1N1bScsXG4gICAgICBwZXJpb2Q6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDMwMCksXG4gICAgfSksXG4gICAgdGhyZXNob2xkOiAxLFxuICAgIGV2YWx1YXRpb25QZXJpb2RzOiAxLFxuICAgIGNvbXBhcmlzb25PcGVyYXRvcjogY2xvdWR3YXRjaC5Db21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRCxcbiAgICBhbGFybURlc2NyaXB0aW9uOiAnQWxhcm0gZm9yIHRoZSBudW1iZXIgb2YgZXhlY3V0aW9ucyB0aGF0IGZhaWxlZCBleGNlZWRlZCB0aGUgdGhyZXNob2xkIG9mIDEuICdcbiAgfSkpO1xuXG4gIC8vIFN1bSBvZiBudW1iZXIgb2YgZXhlY3V0aW9ucyB0aGF0IGZhaWxlZCBtYXhpbXVtIGlzID49IDEgZm9yIDUgbWludXRlLCAxIGNvbnNlY3V0aXZlIHRpbWVcbiAgYWxhcm1zLnB1c2gobmV3IGNsb3Vkd2F0Y2guQWxhcm0oc2NvcGUsIGAke3ByZWZpeH1FeGVjdXRpb25UaHJvdHRsZWRBbGFybWAsIHtcbiAgICBtZXRyaWM6IHNtLm1ldHJpY1Rocm90dGxlZCh7XG4gICAgICBzdGF0aXN0aWM6ICdTdW0nLFxuICAgICAgcGVyaW9kOiBjZGsuRHVyYXRpb24uc2Vjb25kcygzMDApLFxuICAgIH0pLFxuICAgIHRocmVzaG9sZDogMSxcbiAgICBldmFsdWF0aW9uUGVyaW9kczogMSxcbiAgICBjb21wYXJpc29uT3BlcmF0b3I6IGNsb3Vkd2F0Y2guQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgYWxhcm1EZXNjcmlwdGlvbjogJ0FsYXJtIGZvciB0aGUgbnVtYmVyIG9mIGV4ZWN1dGlvbnMgdGhhdCB0aHJvdHRsZWQgZXhjZWVkZWQgdGhlIHRocmVzaG9sZCBvZiAxLiAnXG4gIH0pKTtcblxuICAvLyBOdW1iZXIgb2YgZXhlY3V0aW9ucyB0aGF0IGFib3J0ZWQgbWF4aW11bSBpcyA+PSAxIGZvciA1IG1pbnV0ZSwgMSBjb25zZWN1dGl2ZSB0aW1lXG4gIGFsYXJtcy5wdXNoKG5ldyBjbG91ZHdhdGNoLkFsYXJtKHNjb3BlLCBgJHtwcmVmaXh9RXhlY3V0aW9uQWJvcnRlZEFsYXJtYCwge1xuICAgIG1ldHJpYzogc20ubWV0cmljQWJvcnRlZCh7XG4gICAgICBzdGF0aXN0aWM6ICdNYXhpbXVtJyxcbiAgICAgIHBlcmlvZDogY2RrLkR1cmF0aW9uLnNlY29uZHMoMzAwKSxcbiAgICB9KSxcbiAgICB0aHJlc2hvbGQ6IDEsXG4gICAgZXZhbHVhdGlvblBlcmlvZHM6IDEsXG4gICAgY29tcGFyaXNvbk9wZXJhdG9yOiBjbG91ZHdhdGNoLkNvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fT1JfRVFVQUxfVE9fVEhSRVNIT0xELFxuICAgIGFsYXJtRGVzY3JpcHRpb246ICdBbGFybSBmb3IgdGhlIG51bWJlciBvZiBleGVjdXRpb25zIHRoYXQgYWJvcnRlZCBleGNlZWRlZCB0aGUgdGhyZXNob2xkIG9mIDEuICdcbiAgfSkpO1xuXG4gIHJldHVybiBhbGFybXM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhdGVNYWNoaW5lUHJvcHMge1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmVQcm9wcz86IHNmbi5TdGF0ZU1hY2hpbmVQcm9wcztcbiAgcmVhZG9ubHkgZXhpc3RpbmdTdGF0ZU1hY2hpbmVPYmo/OiBzZm4uU3RhdGVNYWNoaW5lO1xuICByZWFkb25seSBjcmVhdGVDbG91ZFdhdGNoQWxhcm1zPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgY2xvdWRXYXRjaEFsYXJtc1ByZWZpeD86IHN0cmluZ1xuICByZWFkb25seSBsb2dHcm91cFByb3BzPzogbG9ncy5Mb2dHcm91cFByb3BzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gQ2hlY2tTdGF0ZU1hY2hpbmVQcm9wcyhwcm9wc09iamVjdDogU3RhdGVNYWNoaW5lUHJvcHMgfCBhbnkpIHtcbiAgbGV0IGVycm9yTWVzc2FnZXMgPSAnJztcbiAgbGV0IGVycm9yRm91bmQgPSBmYWxzZTtcblxuICBpZiAoKHByb3BzT2JqZWN0LmNyZWF0ZUNsb3VkV2F0Y2hBbGFybXMgPT09IGZhbHNlKSAmJiBwcm9wc09iamVjdC5jbG91ZFdhdGNoQWxhcm1zUHJlZml4KSB7XG4gICAgZXJyb3JNZXNzYWdlcyArPSAnRXJyb3IgLSBjbG91ZFdhdGNoQWxhcm1zUHJlZml4IGlzIGludmFsaWQgd2hlbiBjcmVhdGVDbG91ZFdhdGNoQWxhcm1zIGlzIGZhbHNlXFxuJztcbiAgICBlcnJvckZvdW5kID0gdHJ1ZTtcbiAgfVxuXG4gIGlmICgocHJvcHNPYmplY3QuZXhpc3RpbmdTdGF0ZU1hY2hpbmVPYmopICYmXG4gICAgKHByb3BzT2JqZWN0LnN0YXRlTWFjaGluZVByb3BzIHx8XG4gICAgICAocHJvcHNPYmplY3QuY3JlYXRlQ2xvdWRXYXRjaEFsYXJtcyAhPT0gdW5kZWZpbmVkKSB8fFxuICAgICAgcHJvcHNPYmplY3QuY2xvdWRXYXRjaEFsYXJtc1ByZWZpeCB8fFxuICAgICAgcHJvcHNPYmplY3QubG9nR3JvdXBQcm9wcykpIHtcblxuICAgIGVycm9yTWVzc2FnZXMgKz0gJ0VSUk9SIC0gSWYgZXhpc3RpbmdTdGF0ZU1hY2hpbmUgaXMgcHJvdmlkZWQsIG5vIG90aGVyIHN0YXRlIG1hY2hpbmUgcHJvcHMgYXJlIGFsbG93ZWRcXG4nO1xuICAgIGVycm9yRm91bmQgPSB0cnVlO1xuICB9XG5cbiAgaWYgKGVycm9yRm91bmQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlcyk7XG4gIH1cbn1cbiJdfQ==
;