UNPKG

cdk-lambda-subminute

Version:

A construct for deploying a Lambda function that can be invoked every time unit less than one minute.

164 lines 27.6 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.SubminuteStateMachine = exports.IteratorLambda = exports.LambdaSubminute = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const fs = require("fs"); const path = require("path"); const cdk = require("aws-cdk-lib"); const events = require("aws-cdk-lib/aws-events"); const targets = require("aws-cdk-lib/aws-events-targets"); const iam = require("aws-cdk-lib/aws-iam"); const aws_lambda_1 = require("aws-cdk-lib/aws-lambda"); const aws_lambda_nodejs_1 = require("aws-cdk-lib/aws-lambda-nodejs"); const aws_logs_1 = require("aws-cdk-lib/aws-logs"); const sfn = require("aws-cdk-lib/aws-stepfunctions"); const tasks = require("aws-cdk-lib/aws-stepfunctions-tasks"); const constructs_1 = require("constructs"); class LambdaSubminute extends constructs_1.Construct { constructor(parent, name, props) { super(parent, name); const iterator = new IteratorLambda(this, 'IteratorLambda', { targetFunction: props.targetFunction }); this.iteratorFunction = iterator.function; const subminuteStateMachine = new SubminuteStateMachine(this, 'SubminuteStateMachine', { stateMachineName: 'lambda-subminute-statemachine', targetFunction: props.targetFunction, iteratorFunction: this.iteratorFunction, intervalTime: props.intervalTime ?? 10, frequency: props.frequency ?? 6, }); this.stateMachineArn = subminuteStateMachine.stateMachine.stateMachineArn; const startRule = new events.Rule(this, 'StartSubminuteStateMachine', { schedule: events.Schedule.expression(props.cronjobExpression ?? 'cron(50/1 15-17 ? * * *)'), ruleName: 'subminute-statemachine-lambda-rule', description: `A rule to run the subminute state machine, i.e. ${subminuteStateMachine.stateMachine.stateMachineName}`, }); startRule.addTarget(new targets.SfnStateMachine(subminuteStateMachine.stateMachine, { input: events.RuleTargetInput.fromObject({ iterator: { index: 0, count: 6, }, }), })); } } exports.LambdaSubminute = LambdaSubminute; _a = JSII_RTTI_SYMBOL_1; LambdaSubminute[_a] = { fqn: "cdk-lambda-subminute.LambdaSubminute", version: "2.0.671" }; class IteratorLambda extends constructs_1.Construct { constructor(scope, name, props) { super(scope, name); const iteratorLambdaRole = new iam.Role(this, 'IteratorLambdaRole', { assumedBy: new iam.CompositePrincipal(new iam.ServicePrincipal('lambda.amazonaws.com')), description: 'An execution role for a Lambda function to invoke a target Lambda Function per time unit less than one minute', managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'), iam.ManagedPolicy.fromAwsManagedPolicyName('AWSXRayDaemonWriteAccess'), iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'), ], roleName: 'Lambda-Iterator-Role', }); cdk.DockerVolumeConsistency.CONSISTENT; iteratorLambdaRole.addToPolicy(new iam.PolicyStatement({ sid: 'TargetLambdaPermission', effect: iam.Effect.ALLOW, actions: ['lambda:InvokeFunction'], resources: [props.targetFunction.functionArn], })); this.function = new aws_lambda_nodejs_1.NodejsFunction(this, 'Iterator', { functionName: 'lambda-subminute-iterator', description: 'A function for breaking the limit of 1 minute with the CloudWatch Rules.', logRetention: aws_logs_1.RetentionDays.THREE_MONTHS, runtime: aws_lambda_1.Runtime.NODEJS_18_X, entry: fs.existsSync(path.join(__dirname, 'resources/iterator/iterator_agent.ts')) ? path.join(__dirname, 'resources/iterator/iterator_agent.ts') : path.join(__dirname, 'resources/iterator/iterator_agent.js'), handler: 'lambdaHandler', environment: { TARGET_FN_NAME: props.targetFunction.functionName, }, memorySize: 128, role: iteratorLambdaRole, timeout: cdk.Duration.seconds(58), // 1 min tracing: aws_lambda_1.Tracing.ACTIVE, }); } } exports.IteratorLambda = IteratorLambda; _b = JSII_RTTI_SYMBOL_1; IteratorLambda[_b] = { fqn: "cdk-lambda-subminute.IteratorLambda", version: "2.0.671" }; class SubminuteStateMachine extends constructs_1.Construct { constructor(scope, id, props) { super(scope, id); /** * Creates a state machine for breaking the limit of 1 minute with the CloudWatch Rules. * * @param iteratorFunction The iterator Lambda function for the target Labmda funciton. * @param intervalTime Seconds for an interval, the product of `frequency` and `intervalTime` should be approximagely 1 minute. * @param frequency How many times you intent to execute in a minute. * @returns THe job definition for the state machine. */ this.createJobDefinition = (iteratorFunction, intervalTime, frequency) => { const configureCount = new sfn.Pass(this, 'ConfigureCount', { result: sfn.Result.fromObject({ index: 0, count: frequency, }), resultPath: '$.iterator', }); const iterator = new tasks.LambdaInvoke(this, 'Iterator', { lambdaFunction: iteratorFunction, resultPath: '$.iterator', resultSelector: { 'index.$': '$.Payload.index', 'count.$': '$.Payload.count', 'continue.$': '$.Payload.continue', }, }); const wait = new sfn.Wait(this, 'Wait for the target Lambda function finished', { time: sfn.WaitTime.duration(cdk.Duration.seconds(intervalTime)), }); wait.next(iterator); const done = new sfn.Pass(this, 'Done'); const isCountReached = new sfn.Choice(this, 'IsCountReached'); isCountReached.when(sfn.Condition.booleanEquals('$.iterator.continue', true), wait); isCountReached.otherwise(done); const jobDefinition = configureCount.next(iterator).next(isCountReached); return jobDefinition; }; /** * Creates a role and corresponding policies for the subminute state machine. * * @param targetFunctionArn the ARN of the Lambda function that executes your intention. * @param iteratorFunctionArn the ARN of the iterator Lambda function for the target Lambda function. * @returns the role as the documentation indicates. */ this._createWorkFlowRole = (targetFunctionArn, iteratorFunctionArn) => { const workFlowExecutionRole = new iam.Role(this, 'StepFunctionExecutionRole', { assumedBy: new iam.ServicePrincipal('states.amazonaws.com'), description: 'Execute a workflow related to executing a Lambda function per time unit less than 1 minute.', }); workFlowExecutionRole.addToPolicy(new iam.PolicyStatement({ sid: 'LambdaInvokePermissions', effect: iam.Effect.ALLOW, actions: ['lambda:InvokeFunction'], resources: [ targetFunctionArn, iteratorFunctionArn, ], })); return workFlowExecutionRole; }; const stateMachineRole = this._createWorkFlowRole(props.targetFunction.functionArn, props.iteratorFunction.functionArn); const jobDefinition = this.createJobDefinition(props.iteratorFunction, props.intervalTime, props.frequency); const stateMachine = new sfn.StateMachine(this, 'StateMachine', { stateMachineName: props.stateMachineName, definition: jobDefinition, role: stateMachineRole, }); this.stateMachine = stateMachine; } } exports.SubminuteStateMachine = SubminuteStateMachine; _c = JSII_RTTI_SYMBOL_1; SubminuteStateMachine[_c] = { fqn: "cdk-lambda-subminute.SubminuteStateMachine", version: "2.0.671" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RrLWxhbWJkYS1zdWJtaW51dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY2RrLWxhbWJkYS1zdWJtaW51dGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLG1DQUFtQztBQUNuQyxpREFBa0Q7QUFDbEQsMERBQTJEO0FBQzNELDJDQUEyQztBQUUzQyx1REFBcUU7QUFDckUscUVBQStEO0FBQy9ELG1EQUFxRDtBQUNyRCxxREFBcUQ7QUFDckQsNkRBQTZEO0FBQzdELDJDQUF1QztBQTRCdkMsTUFBYSxlQUFnQixTQUFRLHNCQUFTO0lBUzVDLFlBQVksTUFBaUIsRUFBRSxJQUFZLEVBQUUsS0FBMkI7UUFDdEUsS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNwQixNQUFNLFFBQVEsR0FBRyxJQUFJLGNBQWMsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxjQUFjLEVBQUUsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7UUFDdEcsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDMUMsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLHFCQUFxQixDQUFDLElBQUksRUFBRSx1QkFBdUIsRUFBRTtZQUNyRixnQkFBZ0IsRUFBRSwrQkFBK0I7WUFDakQsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO1lBQ3BDLGdCQUFnQixFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDdkMsWUFBWSxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksRUFBRTtZQUN0QyxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDO1NBQ2hDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxlQUFlLEdBQUcscUJBQXFCLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQztRQUUxRSxNQUFNLFNBQVMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENB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QyxLQUFLLENBQUMsY0FBYyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDeEUsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsWUFBWSxFQUFFLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM1RyxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRTtZQUM5RCxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO1lBQ3hDLFVBQVUsRUFBRSxhQUFhO1lBQ3pCLElBQUksRUFBRSxnQkFBZ0I7U0FDdkIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7SUFDbkMsQ0FBQzs7QUFiSCxzREE2RUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCBldmVudHMgPSByZXF1aXJlKCdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzJyk7XG5pbXBvcnQgdGFyZ2V0cyA9IHJlcXVpcmUoJ2F3cy1jZGstbGliL2F3cy1ldmVudHMtdGFyZ2V0cycpO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuXG5pbXBvcnQgeyBJRnVuY3Rpb24sIFJ1bnRpbWUsIFRyYWNpbmcgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IE5vZGVqc0Z1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0IHsgUmV0ZW50aW9uRGF5cyB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHNmbiBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucyc7XG5pbXBvcnQgKiBhcyB0YXNrcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3RlcGZ1bmN0aW9ucy10YXNrcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcblxuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFTdWJtaW51dGVQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgaXMgZ29pbmcgdG8gYmUgZXhlY3V0ZWQgcGVyIHRpbWUgdW5pdCBsZXNzIHRoYW4gb25lIG1pbnV0ZS5cbiAgICovXG4gIHJlYWRvbmx5IHRhcmdldEZ1bmN0aW9uOiBJRnVuY3Rpb247XG4gIC8qKlxuICAgKiBBIHBhdHRlcm4geW91IHdhbnQgdGhpcyBzdGF0ZW1hY2hpbmUgdG8gYmUgZXhlY3V0ZWQuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L2V2ZW50cy9TY2hlZHVsZWRFdmVudHMuaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCBjcm9uKDUwLzEgMTUtMTcgPyAqICogKikgVVRDKzAgYmVpbmcgcnVuIGV2ZXJ5IG1pbnV0ZSBzdGFydGluZyBmcm9tIDE1OjAwIFBNIHRvIDE3OjAwIFBNLlxuICAgKi9cbiAgcmVhZG9ubHkgY3JvbmpvYkV4cHJlc3Npb24/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBIb3cgbWFueSB0aW1lcyB5b3UgaW50ZW50IHRvIGV4ZWN1dGUgaW4gYSBtaW51dGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDZcbiAgICovXG4gIHJlYWRvbmx5IGZyZXF1ZW5jeT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFNlY29uZHMgZm9yIGFuIGludGVydmFsLCB0aGUgcHJvZHVjdCBvZiBgZnJlcXVlbmN5YCBhbmQgYGludGVydmFsVGltZWAgc2hvdWxkIGJlIGFwcHJveGltYWdlbHkgMSBtaW51dGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEwXG4gICAqL1xuICByZWFkb25seSBpbnRlcnZhbFRpbWU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBMYW1iZGFTdWJtaW51dGUgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICAvKipcbiAgICogVGhlIExhbWJkYSBmdW5jdGlvbiB0aGF0IHBsYXlzIHRoZSByb2xlIG9mIHRoZSBpdGVyYXRvci5cbiAgICovXG4gIHJlYWRvbmx5IGl0ZXJhdG9yRnVuY3Rpb246IElGdW5jdGlvbjtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIHN0YXRlIG1hY2hpbmUgdGhhdCBleGVjdXRlcyB0aGUgdGFyZ2V0IExhbWJkYSBmdW5jdGlvbiBwZXIgdGltZSB1bml0IGxlc3MgdGhhbiBvbmUgbWludXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGVNYWNoaW5lQXJuOiBzdHJpbmc7XG4gIGNvbnN0cnVjdG9yKHBhcmVudDogQ29uc3RydWN0LCBuYW1lOiBzdHJpbmcsIHByb3BzOiBMYW1iZGFTdWJtaW51dGVQcm9wcykge1xuICAgIHN1cGVyKHBhcmVudCwgbmFtZSk7XG4gICAgY29uc3QgaXRlcmF0b3IgPSBuZXcgSXRlcmF0b3JMYW1iZGEodGhpcywgJ0l0ZXJhdG9yTGFtYmRhJywgeyB0YXJnZXRGdW5jdGlvbjogcHJvcHMudGFyZ2V0RnVuY3Rpb24gfSk7XG4gICAgdGhpcy5pdGVyYXRvckZ1bmN0aW9uID0gaXRlcmF0b3IuZnVuY3Rpb247XG4gICAgY29uc3Qgc3VibWludXRlU3RhdGVNYWNoaW5lID0gbmV3IFN1Ym1pbnV0ZVN0YXRlTWFjaGluZSh0aGlzLCAnU3VibWludXRlU3RhdGVNYWNoaW5lJywge1xuICAgICAgc3RhdGVNYWNoaW5lTmFtZTogJ2xhbWJkYS1zdWJtaW51dGUtc3RhdGVtYWNoaW5lJyxcbiAgICAgIHRhcmdldEZ1bmN0aW9uOiBwcm9wcy50YXJnZXRGdW5jdGlvbixcbiAgICAgIGl0ZXJhdG9yRnVuY3Rpb246IHRoaXMuaXRlcmF0b3JGdW5jdGlvbixcbiAgICAgIGludGVydmFsVGltZTogcHJvcHMuaW50ZXJ2YWxUaW1lID8/IDEwLFxuICAgICAgZnJlcXVlbmN5OiBwcm9wcy5mcmVxdWVuY3kgPz8gNixcbiAgICB9KTtcbiAgICB0aGlzLnN0YXRlTWFjaGluZUFybiA9IHN1Ym1pbnV0ZVN0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmUuc3RhdGVNYWNoaW5lQXJuO1xuXG4gICAgY29uc3Qgc3RhcnRSdWxlID0gbmV3IGV2ZW50cy5SdWxlKHRoaXMsICdTdGFydFN1Ym1pbnV0ZVN0YXRlTWFjaGluZScsIHtcbiAgICAgIHNjaGVkdWxlOiBldmVudHMuU2NoZWR1bGUuZXhwcmVzc2lvbihwcm9wcy5jcm9uam9iRXhwcmVzc2lvbiA/PyAnY3Jvbig1MC8xIDE1LTE3ID8gKiAqICopJyksXG4gICAgICBydWxlTmFtZTogJ3N1Ym1pbnV0ZS1zdGF0ZW1hY2hpbmUtbGFtYmRhLXJ1bGUnLFxuICAgICAgZGVzY3JpcHRpb246IGBBIHJ1bGUgdG8gcnVuIHRoZSBzdWJtaW51dGUgc3RhdGUgbWFjaGluZSwgaS5lLiAke3N1Ym1pbnV0ZVN0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmUuc3RhdGVNYWNoaW5lTmFtZX1gLFxuICAgIH0pO1xuICAgIHN0YXJ0UnVsZS5hZGRUYXJnZXQobmV3IHRhcmdldHMuU2ZuU3RhdGVNYWNoaW5lKFxuICAgICAgc3VibWludXRlU3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZSwge1xuICAgICAgICBpbnB1dDogZXZlbnRzLlJ1bGVUYXJnZXRJbnB1dC5mcm9tT2JqZWN0KHtcbiAgICAgICAgICBpdGVyYXRvcjoge1xuICAgICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgICBjb3VudDogNixcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgIH0pKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEl0ZXJhdG9yTGFtYmRhUHJvcHMge1xuICAvKipcbiAgICAgKiBUaGUgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgaXMgZ29pbmcgdG8gYmUgZXhlY3V0ZWQgcGVyIHRpbWUgdW5pdCBsZXNzIHRoYW4gb25lIG1pbnV0ZS5cbiAgICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0RnVuY3Rpb246IElGdW5jdGlvbjtcbn1cblxuZXhwb3J0IGNsYXNzIEl0ZXJhdG9yTGFtYmRhIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAgICogQSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBwbGF5cyB0aGUgcm9sZSBvZiB0aGUgaXRlcmF0b3IuXG4gICAgICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uOiBJRnVuY3Rpb247XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIG5hbWU6IHN0cmluZywgcHJvcHM6IEl0ZXJhdG9yTGFtYmRhUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgbmFtZSk7XG4gICAgY29uc3QgaXRlcmF0b3JMYW1iZGFSb2xlID0gbmV3IGlhbS5Sb2xlKHRoaXMsICdJdGVyYXRvckxhbWJkYVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uQ29tcG9zaXRlUHJpbmNpcGFsKFxuICAgICAgICBuZXcgaWFtLlNlcnZpY2VQcmluY2lwYWwoJ2xhbWJkYS5hbWF6b25hd3MuY29tJyksXG4gICAgICApLFxuICAgICAgZGVzY3JpcHRpb246ICdBbiBleGVjdXRpb24gcm9sZSBmb3IgYSBMYW1iZGEgZnVuY3Rpb24gdG8gaW52b2tlIGEgdGFyZ2V0IExhbWJkYSBGdW5jdGlvbiBwZXIgdGltZSB1bml0IGxlc3MgdGhhbiBvbmUgbWludXRlJyxcbiAgICAgIG1hbmFnZWRQb2xpY2llczogW1xuICAgICAgICBpYW0uTWFuYWdlZFBvbGljeS5mcm9tQXdzTWFuYWdlZFBvbGljeU5hbWUoJ3NlcnZpY2Utcm9sZS9BV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUnKSxcbiAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBV1NYUmF5RGFlbW9uV3JpdGVBY2Nlc3MnKSxcbiAgICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhVlBDQWNjZXNzRXhlY3V0aW9uUm9sZScpLFxuICAgICAgXSxcbiAgICAgIHJvbGVOYW1lOiAnTGFtYmRhLUl0ZXJhdG9yLVJvbGUnLFxuICAgIH0pO1xuICAgIGNkay5Eb2NrZXJWb2x1bWVDb25zaXN0ZW5jeS5DT05TSVNURU5UO1xuXG5cbiAgICBpdGVyYXRvckxhbWJkYVJvbGUuYWRkVG9Qb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiAnVGFyZ2V0TGFtYmRhUGVybWlzc2lvbicsXG4gICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICBhY3Rpb25zOiBbJ2xhbWJkYTpJbnZva2VGdW5jdGlvbiddLFxuICAgICAgcmVzb3VyY2VzOiBbcHJvcHMudGFyZ2V0RnVuY3Rpb24uZnVuY3Rpb25Bcm5dLFxuICAgIH0pKTtcblxuICAgIHRoaXMuZnVuY3Rpb24gPSBuZXcgTm9kZWpzRnVuY3Rpb24odGhpcywgJ0l0ZXJhdG9yJywge1xuICAgICAgZnVuY3Rpb25OYW1lOiAnbGFtYmRhLXN1Ym1pbnV0ZS1pdGVyYXRvcicsXG4gICAgICBkZXNjcmlwdGlvbjogJ0EgZnVuY3Rpb24gZm9yIGJyZWFraW5nIHRoZSBsaW1pdCBvZiAxIG1pbnV0ZSB3aXRoIHRoZSBDbG91ZFdhdGNoIFJ1bGVzLicsXG4gICAgICBsb2dSZXRlbnRpb246IFJldGVudGlvbkRheXMuVEhSRUVfTU9OVEhTLFxuICAgICAgcnVudGltZTogUnVudGltZS5OT0RFSlNfMThfWCxcbiAgICAgIGVudHJ5OiBmcy5leGlzdHNTeW5jKHBhdGguam9pbihfX2Rpcm5hbWUsICdyZXNvdXJjZXMvaXRlcmF0b3IvaXRlcmF0b3JfYWdlbnQudHMnKSkgPyBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2l0ZXJhdG9yL2l0ZXJhdG9yX2FnZW50LnRzJykgOiBwYXRoLmpvaW4oX19kaXJuYW1lLCAncmVzb3VyY2VzL2l0ZXJhdG9yL2l0ZXJhdG9yX2FnZW50LmpzJyksXG4gICAgICBoYW5kbGVyOiAnbGFtYmRhSGFuZGxlcicsXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBUQVJHRVRfRk5fTkFNRTogcHJvcHMudGFyZ2V0RnVuY3Rpb24uZnVuY3Rpb25OYW1lLFxuICAgICAgfSxcbiAgICAgIG1lbW9yeVNpemU6IDEyOCxcbiAgICAgIHJvbGU6IGl0ZXJhdG9yTGFtYmRhUm9sZSxcbiAgICAgIHRpbWVvdXQ6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDU4KSwgLy8gMSBtaW5cbiAgICAgIHRyYWNpbmc6IFRyYWNpbmcuQUNUSVZFLFxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VibWludXRlU3RhdGVNYWNoaW5lUHJvcHMge1xuICAvKipcbiAgICogdGhlIG5hbWUgb2YgdGhlIHN0YXRlIG1hY2hpbmUuXG4gICAqL1xuICByZWFkb25seSBzdGF0ZU1hY2hpbmVOYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiB0aGUgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgeW91ciBpbnRlbnRpb24uXG4gICAqL1xuICByZWFkb25seSB0YXJnZXRGdW5jdGlvbjogSUZ1bmN0aW9uO1xuICAvKipcbiAgICogdGhlIGl0ZXJhdG9yIExhbWJkYSBmdW5jdGlvbiBmb3IgdGhlIHRhcmdldCBMYW1iZGEgZnVuY3Rpb24uXG4gICAqL1xuICByZWFkb25seSBpdGVyYXRvckZ1bmN0aW9uOiBJRnVuY3Rpb247XG4gIC8qKlxuICAgKiBTZWNvbmRzIGZvciBhbiBpbnRlcnZhbCwgdGhlIHByb2R1Y3Qgb2YgYGZyZXF1ZW5jeWAgYW5kIGBpbnRlcnZhbFRpbWVgIHNob3VsZCBiZSBhcHByb3hpbWFnZWx5IDEgbWludXRlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxMFxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJ2YWxUaW1lOiBudW1iZXI7XG4gIC8qKlxuICAgKiBIb3cgbWFueSB0aW1lcyB5b3UgaW50ZW50IHRvIGV4ZWN1dGUgaW4gYSBtaW51dGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDZcbiAgICovXG4gIHJlYWRvbmx5IGZyZXF1ZW5jeTogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgU3VibWludXRlU3RhdGVNYWNoaW5lIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcmVhZG9ubHkgc3RhdGVNYWNoaW5lOiBzZm4uU3RhdGVNYWNoaW5lO1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogU3VibWludXRlU3RhdGVNYWNoaW5lUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuICAgIGNvbnN0IHN0YXRlTWFjaGluZVJvbGUgPSB0aGlzLl9jcmVhdGVXb3JrRmxvd1JvbGUoXG4gICAgICBwcm9wcy50YXJnZXRGdW5jdGlvbi5mdW5jdGlvbkFybiwgcHJvcHMuaXRlcmF0b3JGdW5jdGlvbi5mdW5jdGlvbkFybik7XG4gICAgY29uc3Qgam9iRGVmaW5pdGlvbiA9IHRoaXMuY3JlYXRlSm9iRGVmaW5pdGlvbihwcm9wcy5pdGVyYXRvckZ1bmN0aW9uLCBwcm9wcy5pbnRlcnZhbFRpbWUsIHByb3BzLmZyZXF1ZW5jeSk7XG4gICAgY29uc3Qgc3RhdGVNYWNoaW5lID0gbmV3IHNmbi5TdGF0ZU1hY2hpbmUodGhpcywgJ1N0YXRlTWFjaGluZScsIHtcbiAgICAgIHN0YXRlTWFjaGluZU5hbWU6IHByb3BzLnN0YXRlTWFjaGluZU5hbWUsXG4gICAgICBkZWZpbml0aW9uOiBqb2JEZWZpbml0aW9uLFxuICAgICAgcm9sZTogc3RhdGVNYWNoaW5lUm9sZSxcbiAgICB9KTtcbiAgICB0aGlzLnN0YXRlTWFjaGluZSA9IHN0YXRlTWFjaGluZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgc3RhdGUgbWFjaGluZSBmb3IgYnJlYWtpbmcgdGhlIGxpbWl0IG9mIDEgbWludXRlIHdpdGggdGhlIENsb3VkV2F0Y2ggUnVsZXMuXG4gICAqXG4gICAqIEBwYXJhbSBpdGVyYXRvckZ1bmN0aW9uIFRoZSBpdGVyYXRvciBMYW1iZGEgZnVuY3Rpb24gZm9yIHRoZSB0YXJnZXQgTGFibWRhIGZ1bmNpdG9uLlxuICAgKiBAcGFyYW0gaW50ZXJ2YWxUaW1lIFNlY29uZHMgZm9yIGFuIGludGVydmFsLCB0aGUgcHJvZHVjdCBvZiBgZnJlcXVlbmN5YCBhbmQgYGludGVydmFsVGltZWAgc2hvdWxkIGJlIGFwcHJveGltYWdlbHkgMSBtaW51dGUuXG4gICAqIEBwYXJhbSBmcmVxdWVuY3kgSG93IG1hbnkgdGltZXMgeW91IGludGVudCB0byBleGVjdXRlIGluIGEgbWludXRlLlxuICAgKiBAcmV0dXJucyBUSGUgam9iIGRlZmluaXRpb24gZm9yIHRoZSBzdGF0ZSBtYWNoaW5lLlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVKb2JEZWZpbml0aW9uID0gKFxuICAgIGl0ZXJhdG9yRnVuY3Rpb246IElGdW5jdGlvbiwgaW50ZXJ2YWxUaW1lOiBudW1iZXIsIGZyZXF1ZW5jeTogbnVtYmVyKTogc2ZuLkNoYWluID0+IHtcbiAgICBjb25zdCBjb25maWd1cmVDb3VudCA9IG5ldyBzZm4uUGFzcyh0aGlzLCAnQ29uZmlndXJlQ291bnQnLCB7XG4gICAgICByZXN1bHQ6IHNmbi5SZXN1bHQuZnJvbU9iamVjdCh7XG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgICBjb3VudDogZnJlcXVlbmN5LFxuICAgICAgfSksXG4gICAgICByZXN1bHRQYXRoOiAnJC5pdGVyYXRvcicsXG4gICAgfSk7XG4gICAgY29uc3QgaXRlcmF0b3IgPSBuZXcgdGFza3MuTGFtYmRhSW52b2tlKHRoaXMsICdJdGVyYXRvcicsIHtcbiAgICAgIGxhbWJkYUZ1bmN0aW9uOiBpdGVyYXRvckZ1bmN0aW9uLFxuICAgICAgcmVzdWx0UGF0aDogJyQuaXRlcmF0b3InLFxuICAgICAgcmVzdWx0U2VsZWN0b3I6IHtcbiAgICAgICAgJ2luZGV4LiQnOiAnJC5QYXlsb2FkLmluZGV4JyxcbiAgICAgICAgJ2NvdW50LiQnOiAnJC5QYXlsb2FkLmNvdW50JyxcbiAgICAgICAgJ2NvbnRpbnVlLiQnOiAnJC5QYXlsb2FkLmNvbnRpbnVlJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3Qgd2FpdCA9IG5ldyBzZm4uV2FpdCh0aGlzLCAnV2FpdCBmb3IgdGhlIHRhcmdldCBMYW1iZGEgZnVuY3Rpb24gZmluaXNoZWQnLCB7XG4gICAgICB0aW1lOiBzZm4uV2FpdFRpbWUuZHVyYXRpb24oY2RrLkR1cmF0aW9uLnNlY29uZHMoaW50ZXJ2YWxUaW1lKSksXG4gICAgfSk7XG4gICAgd2FpdC5uZXh0KGl0ZXJhdG9yKTtcbiAgICBjb25zdCBkb25lID0gbmV3IHNmbi5QYXNzKHRoaXMsICdEb25lJyk7XG5cbiAgICBjb25zdCBpc0NvdW50UmVhY2hlZCA9IG5ldyBzZm4uQ2hvaWNlKHRoaXMsICdJc0NvdW50UmVhY2hlZCcpO1xuICAgIGlzQ291bnRSZWFjaGVkLndoZW4oc2ZuLkNvbmRpdGlvbi5ib29sZWFuRXF1YWxzKCckLml0ZXJhdG9yLmNvbnRpbnVlJywgdHJ1ZSksIHdhaXQpO1xuICAgIGlzQ291bnRSZWFjaGVkLm90aGVyd2lzZShkb25lKTtcbiAgICBjb25zdCBqb2JEZWZpbml0aW9uID0gY29uZmlndXJlQ291bnQubmV4dChpdGVyYXRvcikubmV4dChpc0NvdW50UmVhY2hlZCk7XG4gICAgcmV0dXJuIGpvYkRlZmluaXRpb247XG4gIH07XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSByb2xlIGFuZCBjb3JyZXNwb25kaW5nIHBvbGljaWVzIGZvciB0aGUgc3VibWludXRlIHN0YXRlIG1hY2hpbmUuXG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRGdW5jdGlvbkFybiB0aGUgQVJOIG9mIHRoZSBMYW1iZGEgZnVuY3Rpb24gdGhhdCBleGVjdXRlcyB5b3VyIGludGVudGlvbi5cbiAgICogQHBhcmFtIGl0ZXJhdG9yRnVuY3Rpb25Bcm4gdGhlIEFSTiBvZiB0aGUgaXRlcmF0b3IgTGFtYmRhIGZ1bmN0aW9uIGZvciB0aGUgdGFyZ2V0IExhbWJkYSBmdW5jdGlvbi5cbiAgICogQHJldHVybnMgdGhlIHJvbGUgYXMgdGhlIGRvY3VtZW50YXRpb24gaW5kaWNhdGVzLlxuICAgKi9cbiAgcHJpdmF0ZSBfY3JlYXRlV29ya0Zsb3dSb2xlID0gKHRhcmdldEZ1bmN0aW9uQXJuOiBzdHJpbmcsIGl0ZXJhdG9yRnVuY3Rpb25Bcm46IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IHdvcmtGbG93RXhlY3V0aW9uUm9sZSA9IG5ldyBpYW0uUm9sZSh0aGlzLCAnU3RlcEZ1bmN0aW9uRXhlY3V0aW9uUm9sZScsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdzdGF0ZXMuYW1hem9uYXdzLmNvbScpLFxuICAgICAgZGVzY3JpcHRpb246ICdFeGVjdXRlIGEgd29ya2Zsb3cgcmVsYXRlZCB0byBleGVjdXRpbmcgYSBMYW1iZGEgZnVuY3Rpb24gcGVyIHRpbWUgdW5pdCBsZXNzIHRoYW4gMSBtaW51dGUuJyxcbiAgICB9KTtcbiAgICB3b3JrRmxvd0V4ZWN1dGlvblJvbGUuYWRkVG9Qb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgc2lkOiAnTGFtYmRhSW52b2tlUGVybWlzc2lvbnMnLFxuICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgYWN0aW9uczogWydsYW1iZGE6SW52b2tlRnVuY3Rpb24nXSxcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB0YXJnZXRGdW5jdGlvbkFybixcbiAgICAgICAgaXRlcmF0b3JGdW5jdGlvbkFybixcbiAgICAgIF0sXG4gICAgfSkpO1xuICAgIHJldHVybiB3b3JrRmxvd0V4ZWN1dGlvblJvbGU7XG4gIH07XG59Il19