UNPKG

@aws-solutions-constructs/core

Version:
486 lines 62.8 kB
"use strict"; /** * 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 }); const aws_cdk_lib_1 = require("aws-cdk-lib"); const ec2 = require("aws-cdk-lib/aws-ec2"); const lambda = require("aws-cdk-lib/aws-lambda"); const defaults = require("../index"); const assertions_1 = require("aws-cdk-lib/assertions"); const aws_cdk_lib_2 = require("aws-cdk-lib"); const iam = require("aws-cdk-lib/aws-iam"); test("test FunctionProps override code and runtime", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), runtime: lambda.Runtime.PYTHON_3_6, handler: "index.handler", }; defaults.deployLambdaFunction(stack, inProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: "python3.6", }); }); test("test FunctionProps override timeout", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", timeout: aws_cdk_lib_2.Duration.seconds(5), }; defaults.deployLambdaFunction(stack, inProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_STRING, Timeout: 5, }); }); test("test FunctionProps for environment variable when runtime = NODEJS", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", }; defaults.deployLambdaFunction(stack, inProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_STRING, Environment: { Variables: { AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1", }, }, }); }); test("test FunctionProps when runtime = PYTHON", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), runtime: lambda.Runtime.PYTHON_3_6, handler: "index.handler", }; defaults.deployLambdaFunction(stack, inProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: "python3.6", TracingConfig: { Mode: "Active", }, }); }); test("test buildLambdaFunction with deploy = true", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", }; defaults.buildLambdaFunction(stack, { lambdaFunctionProps: inProps, }); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_STRING, }); }); test("test buildLambdaFunction with existing Lambda function (no VPC)", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", }; const newFunction = new lambda.Function(stack, "existingFunction", inProps); const construct = defaults.buildLambdaFunction(stack, { existingLambdaObj: newFunction }); expect(construct).toBe(newFunction); }); test("test buildLambdaFunction with FunctionProps", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), runtime: lambda.Runtime.PYTHON_3_6, handler: "index.handler", }; defaults.deployLambdaFunction(stack, inProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: "python3.6", }); }); test("test exception", () => { const stack = new aws_cdk_lib_1.Stack(); try { defaults.buildLambdaFunction(stack, {}); } catch (e) { expect(e).toBeInstanceOf(Error); } }); test("test buildLambdaFunction with Tracing Disabled", () => { const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), runtime: lambda.Runtime.PYTHON_3_6, handler: "index.handler", tracing: lambda.Tracing.DISABLED, }; defaults.deployLambdaFunction(stack, inProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::Lambda::Function", { Handler: "index.handler", Role: { "Fn::GetAtt": ["LambdaFunctionServiceRole0C4CDE0B", "Arn"], }, Runtime: "python3.6", }); }); test("test buildLambdaFunction when Lambda properties includes a VPC", () => { const stack = new aws_cdk_lib_1.Stack(); const fakeVpc = new ec2.Vpc(stack, "vpc", {}); const lambdaFunctionProps = { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), vpc: fakeVpc, }; defaults.deployLambdaFunction(stack, lambdaFunctionProps); assertions_1.Template.fromStack(stack).hasResourceProperties("AWS::IAM::Policy", { PolicyDocument: { Statement: [ { Action: [ "ec2:CreateNetworkInterface", "ec2:DescribeNetworkInterfaces", "ec2:DeleteNetworkInterface", "ec2:AssignPrivateIpAddresses", "ec2:UnassignPrivateIpAddresses", ], Effect: "Allow", Resource: "*", }, { Action: ["xray:PutTraceSegments", "xray:PutTelemetryRecords"], Effect: "Allow", Resource: "*", }, ], Version: "2012-10-17", }, }); }); test("Test for error if VPC in arguments AND in Lambda Function properties", () => { const stack = new aws_cdk_lib_1.Stack(); const fakeVpc = new ec2.Vpc(stack, "vpc", {}); const lambdaFunctionProps = { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), vpc: fakeVpc, }; const app = () => { defaults.deployLambdaFunction(stack, lambdaFunctionProps, undefined, fakeVpc); }; expect(app).toThrowError(); }); test("Test minimal deployment with an existing VPC and existing Lambda function not in a VPC", () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const testLambdaFunction = new lambda.Function(stack, 'test-lamba', { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), }); const testVpc = new ec2.Vpc(stack, "test-vpc", {}); const app = () => { defaults.buildLambdaFunction(stack, { existingLambdaObj: testLambdaFunction, vpc: testVpc, }); }; // Assertion expect(app).toThrowError(); }); test("Test minimal deployment with an existing VPC and existing Lambda function in a VPC", () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const testVpc = new ec2.Vpc(stack, "test-vpc", {}); const testLambdaFunction = new lambda.Function(stack, 'test-lamba', { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), vpc: testVpc, }); defaults.buildLambdaFunction(stack, { existingLambdaObj: testLambdaFunction, vpc: testVpc, }); // All we're doing here is confirming that buildLambdaFunction does NOT // throw an exception when the existing Lambda function is in a VPCs }); test("Test generating synthesized permission IDs", () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const coreName = "TestInvokePermission"; const testLambdaFunction = new lambda.Function(stack, 'test-lamba', { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), }); defaults.addPermission(testLambdaFunction, coreName, { principal: new iam.ServicePrincipal('iot.amazonaws.com'), sourceArn: 'fake:arn' }); defaults.addPermission(testLambdaFunction, coreName, { principal: new iam.ServicePrincipal('iot.amazonaws.com'), sourceArn: 'fake:arn:two' }); // Synth on this stack masks the information we're looking for in // a longer resource name, so we can't use expect.toHaveResource. We // need to look at the value in the CDK structure. expect(testLambdaFunction.permissionsNode.children.find(permission => permission.node.id === `${coreName}-1`)).toBeDefined(); expect(testLambdaFunction.permissionsNode.children.find(permission => permission.node.id === `${coreName}-2`)).toBeDefined(); }); test("Test invalid synthesized permission names", () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const coreName = "TestInvokePermission"; const testLambdaFunction = new lambda.Function(stack, 'test-lamba', { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), }); testLambdaFunction.addPermission(coreName, { principal: new iam.ServicePrincipal('iot.amazonaws.com'), sourceArn: 'fake:arn' }); const app = () => { defaults.addPermission(testLambdaFunction, coreName, { principal: new iam.ServicePrincipal('iot.amazonaws.com'), sourceArn: 'fake:arn:two' }); }; // Assertion expect(app).toThrowError(); }); test('Test environment variable for correct node version', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler' }; defaults.deployLambdaFunction(stack, inProps); // Assertion assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.handler', Role: { 'Fn::GetAtt': ['LambdaFunctionServiceRole0C4CDE0B', 'Arn'] }, Runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_STRING, Environment: { Variables: { AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1' } } }); }); test('Test minimum deployment with an existing VPC as a vpc parameter in deployLambdaFunction', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const inProps = { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler' }; const fakeVpc = new ec2.Vpc(stack, 'vpc', {}); defaults.deployLambdaFunction(stack, inProps, undefined, fakeVpc); // Assertion assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { VpcConfig: { SecurityGroupIds: [ { 'Fn::GetAtt': [ 'ReplaceDefaultSecurityGroupsecuritygroup8F9FCFA1', 'GroupId' ] } ], SubnetIds: [ { Ref: 'vpcPrivateSubnet1Subnet934893E8' }, { Ref: 'vpcPrivateSubnet2Subnet7031C2BA' } ] } }); }); test("Test retrieving lambda vpc security group ids", () => { const stack = new aws_cdk_lib_1.Stack(); const vpc = defaults.getTestVpc(stack); const securityGroup1 = new ec2.SecurityGroup(stack, 'SecurityGroup1', { vpc }); const securityGroup2 = new ec2.SecurityGroup(stack, 'SecurityGroup2', { vpc }); const testLambdaFunction = new lambda.Function(stack, 'test-lamba', { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", code: lambda.Code.fromAsset(`${__dirname}/lambda`), securityGroups: [securityGroup1, securityGroup2], vpc }); const securityGroups = defaults.getLambdaVpcSecurityGroupIds(testLambdaFunction); expect(securityGroups).toContain(securityGroup1.securityGroupId); expect(securityGroups).toContain(securityGroup2.securityGroupId); }); test('test buildLambdaFunction with lambdaFunctionProps default id', () => { const stack = new aws_cdk_lib_1.Stack(); defaults.buildLambdaFunction(stack, { lambdaFunctionProps: { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler', code: lambda.Code.fromAsset(`${__dirname}/lambda`), } }); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': ['LambdaFunctionServiceRole0C4CDE0B', 'Arn'], }, }); }); test('test buildLambdaFunction with lambdaFunctionProps custom id', () => { const stack = new aws_cdk_lib_1.Stack(); defaults.buildLambdaFunction(stack, { lambdaFunctionProps: { functionName: 'MyTestFunction', runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler', code: lambda.Code.fromAsset(`${__dirname}/lambda`), } }); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': ['MyTestFunctionServiceRole37517223', 'Arn'], }, }); }); test('buildLambdaFunction uses constructId when specified', () => { const stack = new aws_cdk_lib_1.Stack(); defaults.buildLambdaFunction(stack, { lambdaFunctionProps: { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler', code: lambda.Code.fromAsset(`${__dirname}/lambda`), } }, 'MyConstructId'); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': ['MyConstructIdServiceRole271C08FC', 'Arn'], }, }); }); // specifying constructId takes precedence over functionName for setting the // underlying lambda function and iam role construct ids. test('buildLambdaFunction uses constructId when both constructId and functionName are specified', () => { const stack = new aws_cdk_lib_1.Stack(); defaults.buildLambdaFunction(stack, { lambdaFunctionProps: { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler', functionName: 'MyTestFunction', code: lambda.Code.fromAsset(`${__dirname}/lambda`), } }, 'MyConstructId'); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': ['MyConstructIdServiceRole271C08FC', 'Arn'], }, }); }); test('buildLambdaFunction uses functionName when constructId is not specified', () => { const stack = new aws_cdk_lib_1.Stack(); defaults.buildLambdaFunction(stack, { lambdaFunctionProps: { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler', functionName: 'MyTestFunction', code: lambda.Code.fromAsset(`${__dirname}/lambda`), } }); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': ['MyTestFunctionServiceRole37517223', 'Arn'], }, }); }); test('buildLambdaFunction uses default name when neither constructId or functionName is specified', () => { const stack = new aws_cdk_lib_1.Stack(); defaults.buildLambdaFunction(stack, { lambdaFunctionProps: { runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: 'index.handler', code: lambda.Code.fromAsset(`${__dirname}/lambda`), } }); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': ['LambdaFunctionServiceRole0C4CDE0B', 'Arn'], }, }); }); // --------------------------- // Prop Tests // --------------------------- test("Test fail Lambda function check", () => { const stack = new aws_cdk_lib_1.Stack(); const props = { lambdaFunctionProps: { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", }, existingLambdaObj: new lambda.Function(stack, "placeholder", { code: lambda.Code.fromAsset(`${__dirname}/lambda`), runtime: defaults.COMMERCIAL_REGION_LAMBDA_NODE_RUNTIME, handler: "index.handler", }), }; const app = () => { defaults.CheckLambdaProps(props); }; // Assertion expect(app).toThrowError("Error - Either provide lambdaFunctionProps or existingLambdaObj, but not both.\n"); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLWhlbHBlci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibGFtYmRhLWhlbHBlci50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7R0FXRzs7QUFFSCw2Q0FBb0M7QUFDcEMsMkNBQTJDO0FBQzNDLGlEQUFpRDtBQUNqRCxxQ0FBcUM7QUFDckMsdURBQWtEO0FBQ2xELDZDQUF1QztBQUN2QywyQ0FBMkM7QUFFM0MsSUFBSSxDQUFDLDhDQUE4QyxFQUFFLEdBQUcsRUFBRTtJQUN4RCxNQUFNLEtBQUssR0FBRyxJQUFJLG1CQUFLLEVBQUUsQ0FBQztJQUUxQixNQUFNLE9BQU8sR0FBeUI7UUFDcEMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsU0FBUyxjQUFjLENBQUM7UUFDdkQsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVTtRQUNsQyxPQUFPLEVBQUUsZUFBZTtLQUN6QixDQUFDO0lBRUYsUUFBUSxDQUFDLG9CQUFvQixDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUU5QyxxQkFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQyx1QkFBdUIsRUFBRTtRQUN2RSxPQUFPLEVBQUUsZUFBZTtRQUN4QixJQUFJLEVBQUU7WUFDSixZQUFZLEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxLQUFLLENBQUM7U0FDM0Q7UUFDRCxPQUFPLEVBQUUsV0FBVztLQUNyQixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxxQ0FBcUMsRUFBRSxHQUFHLEVBQUU7SUFDL0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxtQkFBSyxFQUFFLENBQUM7SUFFMUIsTUFBTSxPQUFPLEdBQXlCO1FBQ3BDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLFNBQVMsU0FBUyxDQUFDO1FB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bSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBTdGFjayB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCI7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSBcImF3cy1jZGstbGliL2F3cy1sYW1iZGFcIjtcbmltcG9ydCAqIGFzIGRlZmF1bHRzIGZyb20gXCIuLi9pbmRleFwiO1xuaW1wb3J0IHsgVGVtcGxhdGUgfSBmcm9tICdhd3MtY2RrLWxpYi9hc3NlcnRpb25zJztcbmltcG9ydCB7IER1cmF0aW9uIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5cbnRlc3QoXCJ0ZXN0IEZ1bmN0aW9uUHJvcHMgb3ZlcnJpZGUgY29kZSBhbmQgcnVudGltZVwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgaW5Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhLXRlc3RgKSxcbiAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5QWVRIT05fM182LFxuICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICB9O1xuXG4gIGRlZmF1bHRzLmRlcGxveUxhbWJkYUZ1bmN0aW9uKHN0YWNrLCBpblByb3BzKTtcblxuICBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLCB7XG4gICAgSGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgUm9sZToge1xuICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcIkxhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGUwQzRDREUwQlwiLCBcIkFyblwiXSxcbiAgICB9LFxuICAgIFJ1bnRpbWU6IFwicHl0aG9uMy42XCIsXG4gIH0pO1xufSk7XG5cbnRlc3QoXCJ0ZXN0IEZ1bmN0aW9uUHJvcHMgb3ZlcnJpZGUgdGltZW91dFwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgaW5Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhYCksXG4gICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDUpLFxuICB9O1xuXG4gIGRlZmF1bHRzLmRlcGxveUxhbWJkYUZ1bmN0aW9uKHN0YWNrLCBpblByb3BzKTtcblxuICBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLCB7XG4gICAgSGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgUm9sZToge1xuICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcIkxhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGUwQzRDREUwQlwiLCBcIkFyblwiXSxcbiAgICB9LFxuICAgIFJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1NUUklORyxcbiAgICBUaW1lb3V0OiA1LFxuICB9KTtcbn0pO1xuXG50ZXN0KFwidGVzdCBGdW5jdGlvblByb3BzIGZvciBlbnZpcm9ubWVudCB2YXJpYWJsZSB3aGVuIHJ1bnRpbWUgPSBOT0RFSlNcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuXG4gIGNvbnN0IGluUHJvcHM6IGxhbWJkYS5GdW5jdGlvblByb3BzID0ge1xuICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChgJHtfX2Rpcm5hbWV9L2xhbWJkYWApLFxuICAgIHJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1JVTlRJTUUsXG4gICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gIH07XG5cbiAgZGVmYXVsdHMuZGVwbG95TGFtYmRhRnVuY3Rpb24oc3RhY2ssIGluUHJvcHMpO1xuXG4gIFRlbXBsYXRlLmZyb21TdGFjayhzdGFjaykuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKFwiQVdTOjpMYW1iZGE6OkZ1bmN0aW9uXCIsIHtcbiAgICBIYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICBSb2xlOiB7XG4gICAgICBcIkZuOjpHZXRBdHRcIjogW1wiTGFtYmRhRnVuY3Rpb25TZXJ2aWNlUm9sZTBDNENERTBCXCIsIFwiQXJuXCJdLFxuICAgIH0sXG4gICAgUnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfU1RSSU5HLFxuICAgIEVudmlyb25tZW50OiB7XG4gICAgICBWYXJpYWJsZXM6IHtcbiAgICAgICAgQVdTX05PREVKU19DT05ORUNUSU9OX1JFVVNFX0VOQUJMRUQ6IFwiMVwiLFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcbn0pO1xuXG50ZXN0KFwidGVzdCBGdW5jdGlvblByb3BzIHdoZW4gcnVudGltZSA9IFBZVEhPTlwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgaW5Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhLXRlc3RgKSxcbiAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5QWVRIT05fM182LFxuICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICB9O1xuXG4gIGRlZmF1bHRzLmRlcGxveUxhbWJkYUZ1bmN0aW9uKHN0YWNrLCBpblByb3BzKTtcblxuICBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmhhc1Jlc291cmNlUHJvcGVydGllcyhcbiAgICBcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLFxuICAgIHtcbiAgICAgIEhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgICAgUm9sZToge1xuICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1wiTGFtYmRhRnVuY3Rpb25TZXJ2aWNlUm9sZTBDNENERTBCXCIsIFwiQXJuXCJdLFxuICAgICAgfSxcbiAgICAgIFJ1bnRpbWU6IFwicHl0aG9uMy42XCIsXG4gICAgICBUcmFjaW5nQ29uZmlnOiB7XG4gICAgICAgIE1vZGU6IFwiQWN0aXZlXCIsXG4gICAgICB9LFxuICAgIH1cbiAgKTtcbn0pO1xuXG50ZXN0KFwidGVzdCBidWlsZExhbWJkYUZ1bmN0aW9uIHdpdGggZGVwbG95ID0gdHJ1ZVwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgaW5Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhLXRlc3RgKSxcbiAgICBydW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9SVU5USU1FLFxuICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICB9O1xuXG4gIGRlZmF1bHRzLmJ1aWxkTGFtYmRhRnVuY3Rpb24oc3RhY2ssIHtcbiAgICBsYW1iZGFGdW5jdGlvblByb3BzOiBpblByb3BzLFxuICB9KTtcblxuICBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLCB7XG4gICAgSGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgUm9sZToge1xuICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcIkxhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGUwQzRDREUwQlwiLCBcIkFyblwiXSxcbiAgICB9LFxuICAgIFJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1NUUklORyxcbiAgfSk7XG59KTtcblxudGVzdChcInRlc3QgYnVpbGRMYW1iZGFGdW5jdGlvbiB3aXRoIGV4aXN0aW5nIExhbWJkYSBmdW5jdGlvbiAobm8gVlBDKVwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgaW5Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhLXRlc3RgKSxcbiAgICBydW50aW1lOiBkZWZhdWx0cy5DT01NRVJDSUFMX1JFR0lPTl9MQU1CREFfTk9ERV9SVU5USU1FLFxuICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICB9O1xuXG4gIGNvbnN0IG5ld0Z1bmN0aW9uID0gbmV3IGxhbWJkYS5GdW5jdGlvbihzdGFjaywgXCJleGlzdGluZ0Z1bmN0aW9uXCIsIGluUHJvcHMpO1xuXG4gIGNvbnN0IGNvbnN0cnVjdCA9IGRlZmF1bHRzLmJ1aWxkTGFtYmRhRnVuY3Rpb24oc3RhY2ssIHtcbiAgICBleGlzdGluZ0xhbWJkYU9iajogbmV3RnVuY3Rpb25cbiAgfSk7XG5cbiAgZXhwZWN0KGNvbnN0cnVjdCkudG9CZShuZXdGdW5jdGlvbik7XG5cbn0pO1xuXG50ZXN0KFwidGVzdCBidWlsZExhbWJkYUZ1bmN0aW9uIHdpdGggRnVuY3Rpb25Qcm9wc1wiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgaW5Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhLXRlc3RgKSxcbiAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5QWVRIT05fM182LFxuICAgIGhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICB9O1xuXG4gIGRlZmF1bHRzLmRlcGxveUxhbWJkYUZ1bmN0aW9uKHN0YWNrLCBpblByb3BzKTtcblxuICBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6TGFtYmRhOjpGdW5jdGlvblwiLCB7XG4gICAgSGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgUm9sZToge1xuICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcIkxhbWJkYUZ1bmN0aW9uU2VydmljZVJvbGUwQzRDREUwQlwiLCBcIkFyblwiXSxcbiAgICB9LFxuICAgIFJ1bnRpbWU6IFwicHl0aG9uMy42XCIsXG4gIH0pO1xufSk7XG5cbnRlc3QoXCJ0ZXN0IGV4Y2VwdGlvblwiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgdHJ5IHtcbiAgICBkZWZhdWx0cy5idWlsZExhbWJkYUZ1bmN0aW9uKHN0YWNrLCB7fSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBleHBlY3QoZSkudG9CZUluc3RhbmNlT2YoRXJyb3IpO1xuICB9XG59KTtcblxudGVzdChcInRlc3QgYnVpbGRMYW1iZGFGdW5jdGlvbiB3aXRoIFRyYWNpbmcgRGlzYWJsZWRcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuXG4gIGNvbnN0IGluUHJvcHM6IGxhbWJkYS5GdW5jdGlvblByb3BzID0ge1xuICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChgJHtfX2Rpcm5hbWV9L2xhbWJkYS10ZXN0YCksXG4gICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfNixcbiAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICB0cmFjaW5nOiBsYW1iZGEuVHJhY2luZy5ESVNBQkxFRCxcbiAgfTtcblxuICBkZWZhdWx0cy5kZXBsb3lMYW1iZGFGdW5jdGlvbihzdGFjaywgaW5Qcm9wcyk7XG5cbiAgVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoXCJBV1M6OkxhbWJkYTo6RnVuY3Rpb25cIiwge1xuICAgIEhhbmRsZXI6IFwiaW5kZXguaGFuZGxlclwiLFxuICAgIFJvbGU6IHtcbiAgICAgIFwiRm46OkdldEF0dFwiOiBbXCJMYW1iZGFGdW5jdGlvblNlcnZpY2VSb2xlMEM0Q0RFMEJcIiwgXCJBcm5cIl0sXG4gICAgfSxcbiAgICBSdW50aW1lOiBcInB5dGhvbjMuNlwiLFxuICB9KTtcbn0pO1xuXG50ZXN0KFwidGVzdCBidWlsZExhbWJkYUZ1bmN0aW9uIHdoZW4gTGFtYmRhIHByb3BlcnRpZXMgaW5jbHVkZXMgYSBWUENcIiwgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuXG4gIGNvbnN0IGZha2VWcGMgPSBuZXcgZWMyLlZwYyhzdGFjaywgXCJ2cGNcIiwge30pO1xuXG4gIGNvbnN0IGxhbWJkYUZ1bmN0aW9uUHJvcHM6IGxhbWJkYS5GdW5jdGlvblByb3BzID0ge1xuICAgIHJ1bnRpbWU6IGRlZmF1bHRzLkNPTU1FUkNJQUxfUkVHSU9OX0xBTUJEQV9OT0RFX1JVTlRJTUUsXG4gICAgaGFuZGxlcjogXCJpbmRleC5oYW5kbGVyXCIsXG4gICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KGAke19fZGlybmFtZX0vbGFtYmRhYCksXG4gICAgdnBjOiBmYWtlVnBjLFxuICB9O1xuXG4gIGRlZmF1bHRzLmRlcGxveUxhbWJkYUZ1bmN0aW9uKHN0YWNrLCBsYW1iZGFGdW5jdGlvblByb3BzKTtcblxuICBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spLmhhc1Jlc291cmNlUHJvcGVydGllcyhcIkFXUzo6SUFNOjpQb2xpY3lcIiwge1xuICAgIFBvbGljeURvY3VtZW50OiB7XG4gICAgICBTdGF0ZW1lbnQ6IFtcbiAgICAgICAge1xuICAgICAgICAgIEFjdGlvbjogW1xuICAgICAgICAgICAgXCJlYzI6Q3JlYXRlTmV0d29ya0ludGVyZmFjZVwiLFxuICAgICAgICAgICAgXCJlYzI6RGVzY3JpYmVOZXR3b3JrSW50ZXJmYWNlc1wiLFxuICAgICAgICAgICAgXCJlYzI6RGVsZXRlTmV0d29ya0ludGVyZmFjZVwiLFxuICAgICAgICAgICAgXCJlYzI6QXNzaWduUHJpdmF0ZUlwQWRkcmVzc2VzXCIsXG4gICAgICAgICAgICBcImVjMjpVbmFzc2lnblByaXZhdGVJcEFkZHJlc3Nlc1wiLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgRWZmZWN0OiBcIkFsbG93XCIsXG4gICAgICAgICAgUmVzb3VyY2U6IFwiKlwiLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgQWN0aW9uOiBbXCJ4cmF5OlB1dFRyYWNlU2VnbWVudHNcIiwgXCJ4cmF5OlB1dFRlbGVtZXRyeVJlY29yZHNcIl0sXG4gICAgICAgICAgRWZmZWN0OiBcIkFsbG93XCIsXG4gICAgICAgICAgUmVzb3VyY2U6IFwiKlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiLFxuICAgIH0sXG4gIH0pO1xufSk7XG5cbnRlc3QoXCJUZXN0IGZvciBlcnJvciBpZiBWUEMgaW4gYXJndW1lbnRzIEFORCBpbiBMYW1iZGEgRnVuY3Rpb24gcHJvcGVydGllc1wiLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgZmFrZVZwYyA9IG5ldyBlYzIuVnBjKHN0YWNrLCBcInZwY1wiLCB7fSk7XG5cbiAgY29uc3QgbGFtYmRhRnVuY3Rpb25Qcm9wczogbGFtYmRhLkZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgICB2cGM6IGZha2VWcGMsXG4gIH07XG5cbiAgY29uc3QgYXBwID0gKCkgPT4ge1xuICAgIGRlZmF1bHRzLmRlcGxveUxhbWJkYUZ1bmN0aW9uKHN0YWNrLCBsYW1iZGFGdW5jdGlvblByb3BzLCB1bmRlZmluZWQsIGZha2VWcGMpO1xuICB9O1xuXG4gIGV4cGVjdChhcHApLnRvVGhyb3dFcnJvcigpO1xufSk7XG5cbnRlc3QoXCJUZXN0IG1pbmltYWwgZGVwbG95bWVudCB3aXRoIGFuIGV4aXN0aW5nIFZQQyBhbmQgZXhpc3RpbmcgTGFtYmRhIGZ1bmN0aW9uIG5vdCBpbiBhIFZQQ1wiLCAoKSA9PiB7XG4gIC8vIFN0YWNrXG4gIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG5cbiAgY29uc3QgdGVzdExhbWJkYUZ1bmN0aW9uID0gbmV3IGxhbWJkYS5GdW5jdGlvbihzdGFjaywgJ3Rlc3QtbGFtYmEnLCB7XG4gICAgcnVudGltZTogZGVmYXVsdHMuQ09NTUVSQ0lBTF9SRUdJT05fTEFNQkRBX05PREVfUlVOVElNRSxcbiAgICBoYW5kbGVyOiBcImluZGV4LmhhbmRsZXJcIixcbiAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQoYCR7X19kaXJuYW1lfS9sYW1iZGFgKSxcbiAgfSk7XG5cbiAgY29uc3QgdGVzdFZwYyA9IG5ldyBlYzIuVnBjKHN0YWNrLCBcInRlc3QtdnBjXCIsIHt9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgZGVmYXVsdHMuYnVpbGRMYW1iZGFGdW5jdGlvbihzdGFjaywge1xuICAgICAgZXhpc3RpbmdMYW1iZGFPYmo6IHRlc3RMYW1iZGFGdW5jdGlvbixcbiAgICAgIHZwYzogdGVzdFZwYyxcbiAgICB9KTtcblxuICB9O1xuXG4gIC8vIEFzc2VydGlvblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoKTtcblxufSk7XG5cbnRlc3QoXCJUZXN0IG1pbmltYWwgZGVwbG95bWVudCB3aXR