UNPKG

aws-rfdk

Version:

Package for core render farm constructs

572 lines 72.5 kB
"use strict"; /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ Object.defineProperty(exports, "__esModule", { value: true }); const aws_cdk_lib_1 = require("aws-cdk-lib"); const assertions_1 = require("aws-cdk-lib/assertions"); const aws_ec2_1 = require("aws-cdk-lib/aws-ec2"); const aws_ecr_assets_1 = require("aws-cdk-lib/aws-ecr-assets"); const aws_ecs_1 = require("aws-cdk-lib/aws-ecs"); const aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager"); const tag_helpers_1 = require("../../core/test/tag-helpers"); const lib_1 = require("../lib"); const env = { region: 'us-east-1', }; let app; let certificateSecret; let versionedInstallers; let dependencyStack; let dockerContainer; let images; let licenses; let rcsImage; let renderQueue; let stack; let vpc; let workerFleet; const DEFAULT_CONSTRUCT_ID = 'UBL'; describe('UsageBasedLicensing', () => { beforeEach(() => { // GIVEN app = new aws_cdk_lib_1.App(); dependencyStack = new aws_cdk_lib_1.Stack(app, 'DependencyStack', { env }); versionedInstallers = new lib_1.VersionQuery(dependencyStack, 'VersionQuery'); vpc = new aws_ec2_1.Vpc(dependencyStack, 'VPC'); rcsImage = aws_ecs_1.ContainerImage.fromDockerImageAsset(new aws_ecr_assets_1.DockerImageAsset(dependencyStack, 'Image', { directory: __dirname, })); renderQueue = new lib_1.RenderQueue(dependencyStack, 'RQ-NonDefaultPort', { vpc, images: { remoteConnectionServer: rcsImage }, repository: new lib_1.Repository(dependencyStack, 'RepositoryNonDefault', { vpc, version: versionedInstallers, }), version: versionedInstallers, }); jest.spyOn(renderQueue, 'configureSecretsManagementAutoRegistration'); stack = new aws_cdk_lib_1.Stack(app, 'Stack', { env }); certificateSecret = aws_secretsmanager_1.Secret.fromSecretCompleteArn(stack, 'CertSecret', 'arn:aws:secretsmanager:us-west-2:675872700355:secret:CertSecret-j1kiFz'); dockerContainer = new aws_ecr_assets_1.DockerImageAsset(stack, 'license-forwarder', { directory: __dirname, }); images = { licenseForwarder: aws_ecs_1.ContainerImage.fromDockerImageAsset(dockerContainer), }; licenses = [lib_1.UsageBasedLicense.forMaya()]; }); function createUbl(props) { return new lib_1.UsageBasedLicensing(stack, DEFAULT_CONSTRUCT_ID, { certificateSecret, images, licenses, renderQueue, vpc, ...props, }); } test('vpcSubnets specified => does not emit warnings', () => { // GIVEN const vpcSubnets = { subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS, }; // WHEN const ubl = createUbl({ vpcSubnets, }); // THEN assertions_1.Annotations.fromStack(stack).hasNoInfo(`/${ubl.node.path}`, assertions_1.Match.anyValue()); assertions_1.Annotations.fromStack(stack).hasNoWarning(`/${ubl.node.path}`, assertions_1.Match.anyValue()); assertions_1.Annotations.fromStack(stack).hasNoError(`/${ubl.node.path}`, assertions_1.Match.anyValue()); }); test('vpcSubnets not specified => emits warning about dedicated subnets', () => { // WHEN const ubl = createUbl(); // THEN assertions_1.Annotations.fromStack(stack).hasWarning(`/${ubl.node.path}`, 'Deadline Secrets Management is enabled on the Repository and VPC subnets have not been supplied. Using dedicated subnets is recommended. See https://github.com/aws/aws-rfdk/blobs/release/packages/aws-rfdk/lib/deadline/README.md#using-dedicated-subnets-for-deadline-components'); }); describe('configures auto registration', () => { test('default to private subnets', () => { // WHEN const ubl = createUbl(); // THEN const expectedCall = { dependent: ubl.service.node.defaultChild, registrationStatus: lib_1.SecretsManagementRegistrationStatus.REGISTERED, role: lib_1.SecretsManagementRole.CLIENT, vpc, vpcSubnets: { subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS }, }; // THEN expect(renderQueue.configureSecretsManagementAutoRegistration).toHaveBeenCalledWith(expectedCall); }); test.each([ [{ subnetType: aws_ec2_1.SubnetType.PUBLIC, }], ])('%s', (vpcSubnets) => { // WHEN const ubl = createUbl({ vpcSubnets, }); // THEN const expectedCall = { dependent: ubl.service.node.defaultChild, registrationStatus: lib_1.SecretsManagementRegistrationStatus.REGISTERED, role: lib_1.SecretsManagementRole.CLIENT, vpc, vpcSubnets, }; // THEN expect(renderQueue.configureSecretsManagementAutoRegistration).toHaveBeenCalledWith(expectedCall); }); }); test('creates an ECS cluster', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); }); describe('creates an ASG', () => { test('defaults', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MinSize: '1', MaxSize: '1', VPCZoneIdentifier: [ { 'Fn::ImportValue': assertions_1.Match.stringLikeRegexp(`${dependencyStack.stackName}:ExportsOutputRefVPCPrivateSubnet1Subnet.*`), }, { 'Fn::ImportValue': assertions_1.Match.stringLikeRegexp(`${dependencyStack.stackName}:ExportsOutputRefVPCPrivateSubnet2Subnet.*`), }, ], }); }); test('capacity can be specified', () => { // WHEN createUbl({ desiredCount: 2, }); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MinSize: '2', MaxSize: '2', }); }); test('gives write access to log group', () => { // GIVEN const ubl = createUbl(); // WHEN const logGroup = ubl.node.findChild(`${DEFAULT_CONSTRUCT_ID}LogGroup`); const asgRoleLogicalId = aws_cdk_lib_1.Stack.of(ubl).getLogicalId(ubl.asg.role.node.defaultChild); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: assertions_1.Match.arrayWith([ { Action: assertions_1.Match.arrayWith([ 'logs:CreateLogStream', 'logs:PutLogEvents', ]), Effect: 'Allow', Resource: stack.resolve(logGroup.logGroupArn), }, ]), Version: '2012-10-17', }, Roles: assertions_1.Match.arrayWith([ { Ref: asgRoleLogicalId }, ]), }); }); test('uses the supplied security group', () => { // GIVEN const securityGroup = new aws_ec2_1.SecurityGroup(stack, 'UblSecurityGroup', { vpc, }); // WHEN createUbl({ securityGroup }); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { SecurityGroups: assertions_1.Match.arrayWith([stack.resolve(securityGroup.securityGroupId)]), }); }); }); describe('creates an ECS service', () => { test('associated with the cluster', () => { // WHEN const ubl = createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { Cluster: { Ref: stack.getLogicalId(ubl.cluster.node.defaultChild) }, }); }); describe('DesiredCount', () => { test('defaults to 1', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DesiredCount: 1, }); }); test('can be specified', () => { // GIVEN const desiredCount = 2; // WHEN createUbl({ desiredCount }); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DesiredCount: desiredCount, }); }); }); test('sets launch type to EC2', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LaunchType: 'EC2', }); }); test('sets distinct instance placement constraint', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementConstraints: assertions_1.Match.arrayWith([ { Type: 'distinctInstance' }, ]), }); }); test('uses the task definition', () => { // WHEN const ubl = createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: stack.getLogicalId(ubl.service.taskDefinition.node.defaultChild) }, }); }); test('with the correct deployment configuration', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DeploymentConfiguration: { MaximumPercent: 100, MinimumHealthyPercent: 0, }, }); }); }); describe('creates a task definition', () => { test('container name is LicenseForwarderContainer', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Name: 'LicenseForwarderContainer', }, ], }); }); test('container is marked essential', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Essential: true, }, ], }); }); test('with increased ulimits', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Ulimits: [ { HardLimit: 200000, Name: 'nofile', SoftLimit: 200000, }, { HardLimit: 64000, Name: 'nproc', SoftLimit: 64000, }, ], }, ], }); }); test('with awslogs log driver', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { LogConfiguration: { LogDriver: 'awslogs', Options: { 'awslogs-group': {}, 'awslogs-stream-prefix': 'LicenseForwarder', 'awslogs-region': env.region, }, }, }, ], }); }); test('configures UBL certificates', () => { // GIVEN const ubl = createUbl(); // WHEN const taskRoleLogicalId = aws_cdk_lib_1.Stack.of(ubl).getLogicalId(ubl.service.taskDefinition.taskRole.node.defaultChild); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Environment: assertions_1.Match.arrayWith([ { Name: 'UBL_CERTIFICATES_URI', Value: certificateSecret.secretArn, }, ]), }, ], TaskRoleArn: { 'Fn::GetAtt': [ taskRoleLogicalId, 'Arn', ], }, }); assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: assertions_1.Match.arrayWith([ { Action: [ 'secretsmanager:GetSecretValue', 'secretsmanager:DescribeSecret', ], Effect: 'Allow', Resource: certificateSecret.secretArn, }, ]), Version: '2012-10-17', }, Roles: [ { Ref: aws_cdk_lib_1.Stack.of(ubl).getLogicalId(ubl.service.taskDefinition.taskRole.node.defaultChild) }, ], }); }); test('uses host networking', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { NetworkMode: 'host', }); }); test('is marked EC2 compatible only', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { RequiresCompatibilities: ['EC2'], }); }); }); test('License Forwarder subnet selection', () => { // GIVEN const publicSubnetIds = ['PublicSubnet1', 'PublicSubnet2']; const vpcFromAttributes = aws_ec2_1.Vpc.fromVpcAttributes(dependencyStack, 'AttrVpc', { availabilityZones: ['us-east-1a', 'us-east-1b'], vpcId: 'vpcid', publicSubnetIds, }); // WHEN createUbl({ vpc: vpcFromAttributes, vpcSubnets: { subnetType: aws_ec2_1.SubnetType.PUBLIC }, }); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { VPCZoneIdentifier: publicSubnetIds, }); }); test.each([ 'test-prefix/', '', ])('License Forwarder is created with correct LogGroup prefix %s', (testPrefix) => { // GIVEN const id = DEFAULT_CONSTRUCT_ID; // WHEN createUbl({ logGroupProps: { logGroupPrefix: testPrefix, }, }); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: testPrefix + id, }); }); describe('license limits', () => { test('multiple licenses with limits', () => { // WHEN createUbl({ licenses: [ lib_1.UsageBasedLicense.forMaya(10), lib_1.UsageBasedLicense.forVray(10), ], }); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Environment: assertions_1.Match.arrayWith([ { Name: 'UBL_LIMITS', Value: 'maya:10;vray:10', }, ]), }, ], }); }); test.each([ ['3dsMax', lib_1.UsageBasedLicense.for3dsMax(10), [27002]], ['Arnold', lib_1.UsageBasedLicense.forArnold(10), [5056, 7056]], ['Cinema4D', lib_1.UsageBasedLicense.forCinema4D(10), [5057, 5058, 7057, 7058]], ['Clarisse', lib_1.UsageBasedLicense.forClarisse(10), [40500]], ['Houdini', lib_1.UsageBasedLicense.forHoudini(10), [1715]], ['Katana', lib_1.UsageBasedLicense.forKatana(10), [4151, 6101]], ['KeyShot', lib_1.UsageBasedLicense.forKeyShot(10), [27003, 2703]], ['Krakatoa', lib_1.UsageBasedLicense.forKrakatoa(10), [27000, 2700]], ['Mantra', lib_1.UsageBasedLicense.forMantra(10), [1716]], ['Maxwell', lib_1.UsageBasedLicense.forMaxwell(10), [5555, 7055]], ['Maya', lib_1.UsageBasedLicense.forMaya(10), [27002, 2702]], ['Nuke', lib_1.UsageBasedLicense.forNuke(10), [4101, 6101]], ['RealFlow', lib_1.UsageBasedLicense.forRealFlow(10), [5055, 7055]], ['RedShift', lib_1.UsageBasedLicense.forRedShift(10), [5054, 7054]], ['Vray', lib_1.UsageBasedLicense.forVray(10), [30306]], ['Yeti', lib_1.UsageBasedLicense.forYeti(10), [5053, 7053]], ])('open port for license type %s', (_licenseName, license, ports) => { // GIVEN const ubl = createUbl(); const workerStack = new aws_cdk_lib_1.Stack(app, 'WorkerStack', { env }); workerFleet = new lib_1.WorkerInstanceFleet(workerStack, 'workerFleet', { vpc, workerMachineImage: new aws_ec2_1.GenericWindowsImage({ 'us-east-1': 'ami-any', }), renderQueue, securityGroup: aws_ec2_1.SecurityGroup.fromSecurityGroupId(workerStack, 'SG', 'sg-123456789', { allowAllOutbound: false, }), }); // WHEN ubl.grantPortAccess(workerFleet, [license]); // THEN ports.forEach(port => { assertions_1.Template.fromStack(workerStack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', ToPort: port, GroupId: { 'Fn::ImportValue': assertions_1.Match.stringLikeRegexp(`${aws_cdk_lib_1.Stack.of(ubl).stackName}:ExportsOutputFnGetAttUBLClusterASGInstanceSecurityGroup.*`), }, SourceSecurityGroupId: 'sg-123456789', }); }); }); test('requires one usage based license', () => { // Without any licenses expect(() => { createUbl({ licenses: [] }); }).toThrow('Should be specified at least one license with defined limit.'); }); }); describe('configures render queue', () => { test('adds ingress rule from UsageBasedLicensing ASG to RenderQueue ASG', () => { // GIVEN const renderQueueSecurityGroup = renderQueue.connections.securityGroups[0]; // WHEN const ubl = createUbl(); const ublSecurityGroup = ubl.connections.securityGroups[0]; assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 4433, ToPort: 4433, GroupId: stack.resolve(renderQueueSecurityGroup.securityGroupId), SourceSecurityGroupId: stack.resolve(ublSecurityGroup.securityGroupId), }); }); test('adds ingress rule from RenderQueue ASG to UsageBasedLicensing ASG', () => { // GIVEN const renderQueueSecurityGroup = renderQueue.backendConnections.securityGroups[0]; // WHEN const ubl = createUbl(); const ublSecurityGroup = ubl.connections.securityGroups[0]; assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { IpProtocol: 'tcp', FromPort: 17004, ToPort: 17004, GroupId: stack.resolve(ublSecurityGroup.securityGroupId), SourceSecurityGroupId: stack.resolve(renderQueueSecurityGroup.securityGroupId), }); }); test('sets RENDER_QUEUE_URI environment variable', () => { // WHEN createUbl(); // THEN assertions_1.Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Environment: assertions_1.Match.arrayWith([ { Name: 'RENDER_QUEUE_URI', Value: stack.resolve(`${renderQueue.endpoint.applicationProtocol.toLowerCase()}://${renderQueue.endpoint.socketAddress}`), }, ]), }, ], }); }); }); describe('tagging', () => { (0, tag_helpers_1.testConstructTags)({ constructName: 'UsageBasedLicensing', createConstruct: () => { createUbl(); return stack; }, resourceTypeCounts: { 'AWS::ECS::Cluster': 1, 'AWS::EC2::SecurityGroup': 1, 'AWS::IAM::Role': 5, 'AWS::AutoScaling::AutoScalingGroup': 1, 'AWS::Lambda::Function': 1, 'AWS::SNS::Topic': 1, 'AWS::ECS::TaskDefinition': 1, 'AWS::ECS::Service': 1, }, }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNhZ2UtYmFzZWQtbGljZW5zaW5nLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ1c2FnZS1iYXNlZC1saWNlbnNpbmcudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOztBQUVILDZDQUlxQjtBQUNyQix1REFJZ0M7QUFDaEMsaURBTzZCO0FBQzdCLCtEQUVvQztBQUNwQyxpREFHNkI7QUFJN0IsdUVBR3dDO0FBRXhDLDZEQUVxQztBQUNyQyxnQ0FjZ0I7QUFFaEIsTUFBTSxHQUFHLEdBQUc7SUFDVixNQUFNLEVBQUUsV0FBVztDQUNwQixDQUFDO0FBQ0YsSUFBSSxHQUFRLENBQUM7QUFDYixJQUFJLGlCQUEwQixDQUFDO0FBQy9CLElBQUksbUJBQTZCLENBQUM7QUFDbEMsSUFBSSxlQUFzQixDQUFDO0FBQzNCLElBQUksZUFBaUMsQ0FBQztBQUN0QyxJQUFJLE1BQWlDLENBQUM7QUFDdEMsSUFBSSxRQUE2QixDQUFDO0FBQ2xDLElBQUksUUFBd0IsQ0FBQztBQUM3QixJQUFJLFdBQXdCLENBQUM7QUFDN0IsSUFBSSxLQUFZLENBQUM7QUFDakIsSUFBSSxHQUFTLENBQUM7QUFDZCxJQUFJLFdBQXlCLENBQUM7QUFFOUIsTUFBTSxvQkFBb0IsR0FBRyxLQUFLLENBQUM7QUFFbkMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLEdBQUcsRUFBRTtJQUNuQyxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsUUFBUTtRQUNSLEdBQUcsR0FBRyxJQUFJLGlCQUFHLEVBQUUsQ0FBQztRQUVoQixlQUFlLEdBQUcsSUFBSSxtQkFBSyxDQUFDLEdBQUcsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFFN0QsbUJBQW1CLEdBQUcsSUFBSSxrQkFBWSxDQUFDLGVBQWUsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUV4RSxHQUFHLEdBQUcsSUFBSSxhQUFHLENBQUMsZUFBZSxFQUFFLEtBQUssQ0FBQyxDQUFD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QUNQLHFCQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLHFCQUFxQixDQUFDLDBCQUEwQixFQUFFO2dCQUMxRSxvQkFBb0IsRUFBRTtvQkFDcEI7d0JBQ0UsV0FBVyxFQUFFLGtCQUFLLENBQUMsU0FBUyxDQUFDOzRCQUMzQjtnQ0FDRSxJQUFJLEVBQUUsa0JBQWtCO2dDQUN4QixLQUFLLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLFdBQVcsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLE1BQU0sV0FBVyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsQ0FBQzs2QkFDMUg7eUJBQ0YsQ0FBQztxQkFDSDtpQkFDRjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRTtRQUN2QixJQUFBLCtCQUFpQixFQUFDO1lBQ2hCLGFBQWEsRUFBRSxxQkFBcUI7WUFDcEMsZUFBZSxFQUFFLEdBQUcsRUFBRTtnQkFDcEIsU0FBUyxFQUFFLENBQUM7Z0JBQ1osT0FBTyxLQUFLLENBQUM7WUFDZixDQUFDO1lBQ0Qsa0JBQWtCLEVBQUU7Z0JBQ2xCLG1CQUFtQixFQUFFLENBQUM7Z0JBQ3RCLHlCQUF5QixFQUFFLENBQUM7Z0JBQzVCLGdCQUFnQixFQUFFLENBQUM7Z0JBQ25CLG9DQUFvQyxFQUFFLENBQUM7Z0JBQ3ZDLHVCQUF1QixFQUFFLENBQUM7Z0JBQzFCLGlCQUFpQixFQUFFLENBQUM7Z0JBQ3BCLDBCQUEwQixFQUFFLENBQUM7Z0JBQzdCLG1CQUFtQixFQUFFLENBQUM7YUFDdkI7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHtcbiAgQXBwLFxuICBDZm5FbGVtZW50LFxuICBTdGFjayxcbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgQW5ub3RhdGlvbnMsXG4gIE1hdGNoLFxuICBUZW1wbGF0ZSxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXNzZXJ0aW9ucyc7XG5pbXBvcnQge1xuICBHZW5lcmljV2luZG93c0ltYWdlLFxuICBJVnBjLFxuICBTZWN1cml0eUdyb3VwLFxuICBTdWJuZXRTZWxlY3Rpb24sXG4gIFN1Ym5ldFR5cGUsXG4gIFZwYyxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQge1xuICBEb2NrZXJJbWFnZUFzc2V0LFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWNyLWFzc2V0cyc7XG5pbXBvcnQge1xuICBDZm5TZXJ2aWNlLFxuICBDb250YWluZXJJbWFnZSxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjcyc7XG5pbXBvcnQge1xuICBJTG9nR3JvdXAsXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCB7XG4gIElTZWNyZXQsXG4gIFNlY3JldCxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXNlY3JldHNtYW5hZ2VyJztcblxuaW1wb3J0IHtcbiAgdGVzdENvbnN0cnVjdFRhZ3MsXG59IGZyb20gJy4uLy4uL2NvcmUvdGVzdC90YWctaGVscGVycyc7XG5pbXBvcnQge1xuICBJVmVyc2lvbixcbiAgSVdvcmtlckZsZWV0LFxuICBSZW5kZXJRdWV1ZSxcbiAgUmVwb3NpdG9yeSxcbiAgU2VjcmV0c01hbmFnZW1lbnRSZWdpc3RyYXRpb25TdGF0dXMsXG4gIFNlY3JldHNNYW5hZ2VtZW50Um9sZSxcbiAgU3VibmV0SWRlbnRpdHlSZWdpc3RyYXRpb25TZXR0aW5nc1Byb3BzLFxuICBVc2FnZUJhc2VkTGljZW5zZSxcbiAgVXNhZ2VCYXNlZExpY2Vuc2luZyxcbiAgVXNhZ2VCYXNlZExpY2Vuc2luZ0ltYWdlcyxcbiAgVXNhZ2VCYXNlZExpY2Vuc2luZ1Byb3BzLFxuICBWZXJzaW9uUXVlcnksXG4gIFdvcmtlckluc3RhbmNlRmxlZXQsXG59IGZyb20gJy4uL2xpYic7XG5cbmNvbnN0IGVudiA9IHtcbiAgcmVnaW9uOiAndXMtZWFzdC0xJyxcbn07XG5sZXQgYXBwOiBBcHA7XG5sZXQgY2VydGlmaWNhdGVTZWNyZXQ6IElTZWNyZXQ7XG5sZXQgdmVyc2lvbmVkSW5zdGFsbGVyczogSVZlcnNpb247XG5sZXQgZGVwZW5kZW5jeVN0YWNrOiBTdGFjaztcbmxldCBkb2NrZXJDb250YWluZXI6IERvY2tlckltYWdlQXNzZXQ7XG5sZXQgaW1hZ2VzOiBVc2FnZUJhc2VkTGljZW5zaW5nSW1hZ2VzO1xubGV0IGxpY2Vuc2VzOiBVc2FnZUJhc2VkTGljZW5zZVtdO1xubGV0IHJjc0ltYWdlOiBDb250YWluZXJJbWFnZTtcbmxldCByZW5kZXJRdWV1ZTogUmVuZGVyUXVldWU7XG5sZXQgc3RhY2s6IFN0YWNrO1xubGV0IHZwYzogSVZwYztcbmxldCB3b3JrZXJGbGVldDogSVdvcmtlckZsZWV0O1xuXG5jb25zdCBERUZBVUxUX0NPTlNUUlVDVF9JRCA9ICdVQkwnO1xuXG5kZXNjcmliZSgnVXNhZ2VCYXNlZExpY2Vuc2luZycsICgpID0+IHtcbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgLy8gR0lWRU5cbiAgICBhcHAgPSBuZXcgQXBwKCk7XG5cbiAgICBkZXBlbmRlbmN5U3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnRGVwZW5kZW5jeVN0YWNrJywgeyBlbnYgfSk7XG5cbiAgICB2ZXJzaW9uZWRJbnN0YWxsZXJzID0gbmV3IFZlcnNpb25RdWVyeShkZXBlbmRlbmN5U3RhY2ssICdWZXJzaW9uUXVlcnknKTtcblxuICAgIHZwYyA9IG5ldyBWcGMoZGVwZW5kZW5jeVN0YWNrLCAnVlBDJyk7XG4gICAgcmNzSW1hZ2UgPSBDb250YWluZXJJbWFnZS5mcm9tRG9ja2VySW1hZ2VBc3NldChuZXcgRG9ja2VySW1hZ2VBc3NldChkZXBlbmRlbmN5U3RhY2ssICdJbWFnZScsIHtcbiAgICAgIGRpcmVjdG9yeTogX19kaXJuYW1lLFxuICAgIH0pKTtcbiAgICByZW5kZXJRdWV1ZSA9IG5ldyBSZW5kZXJRdWV1ZShkZXBlbmRlbmN5U3RhY2ssICdSUS1Ob25EZWZhdWx0UG9ydCcsIHtcbiAgICAgIHZwYyxcbiAgICAgIGltYWdlczogeyByZW1vdGVDb25uZWN0aW9uU2VydmVyOiByY3NJbWFnZSB9LFxuICAgICAgcmVwb3NpdG9yeTogbmV3IFJlcG9zaXRvcnkoZGVwZW5kZW5jeVN0YWNrLCAnUmVwb3NpdG9yeU5vbkRlZmF1bHQnLCB7XG4gICAgICAgIHZwYyxcbiAgICAgICAgdmVyc2lvbjogdmVyc2lvbmVkSW5zdGFsbGVycyxcbiAgICAgIH0pLFxuICAgICAgdmVyc2lvbjogdmVyc2lvbmVkSW5zdGFsbGVycyxcbiAgICB9KTtcbiAgICBqZXN0LnNweU9uKHJlbmRlclF1ZXVlLCAnY29uZmlndXJlU2VjcmV0c01hbmFnZW1lbnRBdXRvUmVnaXN0cmF0aW9uJyk7XG5cbiAgICBzdGFjayA9IG5ldyBTdGFjayhhcHAsICdTdGFjaycsIHsgZW52IH0pO1xuICAgIGNlcnRpZmljYXRlU2VjcmV0ID0gU2VjcmV0LmZyb21TZWNyZXRDb21wbGV0ZUFybihzdGFjaywgJ0NlcnRTZWNyZXQnLCAnYXJuOmF3czpzZWNyZXRzbWFuYWdlcjp1cy13ZXN0LTI6Njc1ODcyNzAwMzU1OnNlY3JldDpDZXJ0U2VjcmV0LWoxa2lGeicpO1xuICAgIGRvY2tlckNvbnRhaW5lciA9IG5ldyAgRG9ja2VySW1hZ2VBc3NldChzdGFjaywgJ2xpY2Vuc2UtZm9yd2FyZGVyJywge1xuICAgICAgZGlyZWN0b3J5OiBfX2Rpcm5hbWUsXG4gICAgfSk7XG4gICAgaW1hZ2VzID0ge1xuICAgICAgbGljZW5zZUZvcndhcmRlcjogQ29udGFpbmVySW1hZ2UuZnJvbURvY2tlckltYWdlQXNzZXQoZG9ja2VyQ29udGFpbmVyKSxcbiAgICB9O1xuICAgIGxpY2Vuc2VzID0gW1VzYWdlQmFzZWRMaWNlbnNlLmZvck1heWEoKV07XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGNyZWF0ZVVibChwcm9wcz86IFBhcnRpYWw8VXNhZ2VCYXNlZExpY2Vuc2luZ1Byb3BzPik6IFVzYWdlQmFzZWRMaWNlbnNpbmcge1xuICAgIHJldHVybiBuZXcgVXNhZ2VCYXNlZExpY2Vuc2luZyhzdGFjaywgREVGQVVMVF9DT05TVFJVQ1RfSUQsIHtcbiAgICAgIGNlcnRpZmljYXRlU2VjcmV0LFxuICAgICAgaW1hZ2VzLFxuICAgICAgbGljZW5zZXMsXG4gICAgICByZW5kZXJRdWV1ZSxcbiAgICAgIHZwYyxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgdGVzdCgndnBjU3VibmV0cyBzcGVjaWZpZWQgPT4gZG9lcyBub3QgZW1pdCB3YXJuaW5ncycsICgpID0+IHtcbiAgICAvLyBHSVZFTlxuICAgIGNvbnN0IHZwY1N1Ym5ldHM6IFN1Ym5ldFNlbGVjdGlvbiA9IHtcbiAgICAgIHN1Ym5ldFR5cGU6IFN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX0VHUkVTUyxcbiAgICB9O1xuXG4gICAgLy8gV0hFTlxuICAgIGNvbnN0IHVibCA9IGNyZWF0ZVVibCh7XG4gICAgICB2cGNTdWJuZXRzLFxuICAgIH0pO1xuXG4gICAgLy8gVEhFTlxuICAgIEFubm90YXRpb25zLmZyb21TdGFjayhzdGFjaykuaGFzTm9JbmZvKGAvJHt1Ymwubm9kZS5wYXRofWAsIE1hdGNoLmFueVZhbHVlKCkpO1xuICAgIEFubm90YXRpb25zLmZyb21TdGFjayhzdGFjaykuaGFzTm9XYXJuaW5nKGAvJHt1Ymwubm9kZS5wYXRofWAsIE1hdGNoLmFueVZhbHVlKCkpO1xuICAgIEFubm90YXRpb25zLmZyb21TdGFjayhzdGFjaykuaGFzTm9FcnJvcihgLyR7dWJsLm5vZGUucGF0aH1gLCBNYXRjaC5hbnlWYWx1