aws-rfdk
Version:
Package for core render farm constructs
572 lines • 72.5 kB
JavaScript
"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