aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
364 lines • 42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
jest.mock('promptly', () => {
return {
...jest.requireActual('promptly'),
confirm: jest.fn(),
prompt: jest.fn(),
};
});
const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
const promptly = require("promptly");
const util_1 = require("./util");
const mock_sdk_1 = require("./util/mock-sdk");
const deployments_1 = require("../lib/api/deployments");
const import_1 = require("../lib/import");
const promptlyConfirm = promptly.confirm;
const promptlyPrompt = promptly.prompt;
function stackWithQueue(props) {
return (0, util_1.testStack)({
stackName: 'StackWithQueue',
template: {
Resources: {
MyQueue: {
Type: 'AWS::SQS::Queue',
Properties: props,
},
},
},
});
}
const STACK_WITH_QUEUE = stackWithQueue({});
const STACK_WITH_NAMED_QUEUE = stackWithQueue({
QueueName: 'TheQueueName',
});
function stackWithGlobalTable(props) {
return (0, util_1.testStack)({
stackName: 'StackWithTable',
template: {
Resources: {
MyTable: {
Type: 'AWS::DynamoDB::GlobalTable',
Properties: props,
},
},
},
});
}
function stackWithKeySigningKey(props) {
return (0, util_1.testStack)({
stackName: 'StackWithKSK',
template: {
Resources: {
MyKSK: {
Type: 'AWS::Route53::KeySigningKey',
Properties: props,
},
},
},
});
}
let sdkProvider;
let deployments;
beforeEach(() => {
(0, mock_sdk_1.restoreSdkMocksToDefault)();
jest.resetAllMocks();
sdkProvider = new mock_sdk_1.MockSdkProvider();
deployments = new deployments_1.Deployments({ sdkProvider });
});
test('discovers importable resources', async () => {
givenCurrentStack(STACK_WITH_QUEUE.stackName, {
Resources: {},
});
const importer = new import_1.ResourceImporter(STACK_WITH_QUEUE, deployments);
const { additions } = await importer.discoverImportableResources();
expect(additions).toEqual([
expect.objectContaining({
logicalId: 'MyQueue',
}),
]);
});
test('by default, its an error if there are non-addition changes in the template', async () => {
givenCurrentStack(STACK_WITH_QUEUE.stackName, {
Resources: {
SomethingThatDisappeared: {
Type: 'AWS::S3::Bucket',
},
},
});
const importer = new import_1.ResourceImporter(STACK_WITH_QUEUE, deployments);
await expect(importer.discoverImportableResources()).rejects.toThrow(/No resource updates or deletes/);
// But the error can be silenced
await expect(importer.discoverImportableResources(true)).resolves.toBeTruthy();
});
test('asks human for resource identifiers', async () => {
// GIVEN
givenCurrentStack(STACK_WITH_QUEUE.stackName, { Resources: {} });
const importer = new import_1.ResourceImporter(STACK_WITH_QUEUE, deployments);
const { additions } = await importer.discoverImportableResources();
// WHEN
promptlyPrompt.mockResolvedValue('TheQueueName');
const importable = await importer.askForResourceIdentifiers(additions);
// THEN
expect(importable.resourceMap).toEqual({
MyQueue: {
QueueName: 'TheQueueName',
},
});
expect(importable.importResources).toEqual([
expect.objectContaining({
logicalId: 'MyQueue',
}),
]);
});
test('asks human to confirm automic import if identifier is in template', async () => {
// GIVEN
givenCurrentStack(STACK_WITH_NAMED_QUEUE.stackName, { Resources: {} });
const importer = new import_1.ResourceImporter(STACK_WITH_NAMED_QUEUE, deployments);
const { additions } = await importer.discoverImportableResources();
// WHEN
promptlyConfirm.mockResolvedValue(true);
const importable = await importer.askForResourceIdentifiers(additions);
// THEN
expect(importable.resourceMap).toEqual({
MyQueue: {
QueueName: 'TheQueueName',
},
});
expect(importable.importResources).toEqual([
expect.objectContaining({
logicalId: 'MyQueue',
}),
]);
});
test('asks human to confirm automic import if identifier is in template', async () => {
// GIVEN
givenCurrentStack(STACK_WITH_QUEUE.stackName, { Resources: {} });
const importer = new import_1.ResourceImporter(STACK_WITH_QUEUE, deployments);
const { additions } = await importer.discoverImportableResources();
const importMap = {
importResources: additions,
resourceMap: {
MyQueue: { QueueName: 'TheQueueName' },
},
};
// WHEN
await importer.importResourcesFromMap(importMap, {});
expect(mock_sdk_1.mockCloudFormationClient).toHaveReceivedCommandWith(client_cloudformation_1.CreateChangeSetCommand, {
ChangeSetName: expect.any(String),
StackName: STACK_WITH_QUEUE.stackName,
TemplateBody: expect.any(String),
ChangeSetType: 'IMPORT',
ResourcesToImport: [
{
LogicalResourceId: 'MyQueue',
ResourceIdentifier: { QueueName: 'TheQueueName' },
ResourceType: 'AWS::SQS::Queue',
},
],
});
});
test('importing resources from migrate strips cdk metadata and outputs', async () => {
// GIVEN
const MyQueue = {
Type: 'AWS::SQS::Queue',
Properties: {},
};
const stack = {
stackName: 'StackWithQueue',
template: {
Resources: {
MyQueue,
CDKMetadata: {
Type: 'AWS::CDK::Metadata',
Properties: {
Analytics: 'exists',
},
},
},
Outputs: {
Output: {
Description: 'There is an output',
Value: 'OutputValue',
},
},
},
};
givenCurrentStack(stack.stackName, stack);
const importer = new import_1.ResourceImporter((0, util_1.testStack)(stack), deployments);
const migrateMap = [
{
LogicalResourceId: 'MyQueue',
ResourceIdentifier: { QueueName: 'TheQueueName' },
ResourceType: 'AWS::SQS::Queue',
},
];
// WHEN
await importer.importResourcesFromMigrate(migrateMap, STACK_WITH_QUEUE.template);
// THEN
expect(mock_sdk_1.mockCloudFormationClient).toHaveReceivedCommandWith(client_cloudformation_1.CreateChangeSetCommand, {
ChangeSetName: expect.any(String),
StackName: STACK_WITH_QUEUE.stackName,
TemplateBody: expect.any(String),
ChangeSetType: 'IMPORT',
ResourcesToImport: [
{
LogicalResourceId: 'MyQueue',
ResourceIdentifier: { QueueName: 'TheQueueName' },
ResourceType: 'AWS::SQS::Queue',
},
],
});
});
test('only use one identifier if multiple are in template', async () => {
// GIVEN
const stack = stackWithGlobalTable({
TableName: 'TheTableName',
TableArn: 'ThisFieldDoesntExistInReality',
TableStreamArn: 'NorDoesThisOne',
});
// WHEN
promptlyConfirm.mockResolvedValue(true); // Confirm yes/no
await importTemplateFromClean(stack);
// THEN
expect(mock_sdk_1.mockCloudFormationClient).toHaveReceivedCommandWith(client_cloudformation_1.CreateChangeSetCommand, {
ChangeSetName: expect.any(String),
StackName: stack.stackName,
TemplateBody: expect.any(String),
ChangeSetType: 'IMPORT',
ResourcesToImport: [
{
LogicalResourceId: 'MyTable',
ResourceIdentifier: { TableName: 'TheTableName' },
ResourceType: 'AWS::DynamoDB::GlobalTable',
},
],
});
});
test('only ask user for one identifier if multiple possible ones are possible', async () => {
// GIVEN -- no identifiers in template, so ask user
const stack = stackWithGlobalTable({});
// WHEN
promptlyPrompt.mockResolvedValue('Banana');
const importable = await importTemplateFromClean(stack);
// THEN -- only asked once
expect(promptlyPrompt).toHaveBeenCalledTimes(1);
expect(importable.resourceMap).toEqual({
MyTable: { TableName: 'Banana' },
});
});
test('ask identifier if the value in the template is a CFN intrinsic', async () => {
// GIVEN -- identifier in template is a CFN intrinsic so it doesn't count
const stack = stackWithQueue({
QueueName: { Ref: 'SomeParam' },
});
// WHEN
promptlyPrompt.mockResolvedValue('Banana');
const importable = await importTemplateFromClean(stack);
// THEN
expect(importable.resourceMap).toEqual({
MyQueue: { QueueName: 'Banana' },
});
});
test('take compound identifiers from the template if found', async () => {
// GIVEN
const stack = stackWithKeySigningKey({
HostedZoneId: 'z-123',
Name: 'KeyName',
});
// WHEN
promptlyConfirm.mockResolvedValue(true);
await importTemplateFromClean(stack);
// THEN
expect(mock_sdk_1.mockCloudFormationClient).toHaveReceivedCommandWith(client_cloudformation_1.CreateChangeSetCommand, {
ChangeSetName: expect.any(String),
StackName: stack.stackName,
TemplateBody: expect.any(String),
ChangeSetType: 'IMPORT',
ResourcesToImport: [
{
LogicalResourceId: 'MyKSK',
ResourceIdentifier: { HostedZoneId: 'z-123', Name: 'KeyName' },
ResourceType: 'AWS::Route53::KeySigningKey',
},
],
});
});
test('ask user for compound identifiers if not found', async () => {
// GIVEN
const stack = stackWithKeySigningKey({});
// WHEN
promptlyPrompt.mockReturnValue('Banana');
await importTemplateFromClean(stack);
// THEN
expect(mock_sdk_1.mockCloudFormationClient).toHaveReceivedCommandWith(client_cloudformation_1.CreateChangeSetCommand, {
ChangeSetName: expect.any(String),
StackName: stack.stackName,
TemplateBody: expect.any(String),
ChangeSetType: 'IMPORT',
ResourcesToImport: [
{
LogicalResourceId: 'MyKSK',
ResourceIdentifier: { HostedZoneId: 'Banana', Name: 'Banana' },
ResourceType: 'AWS::Route53::KeySigningKey',
},
],
});
});
test('do not ask for second part of compound identifier if the user skips the first', async () => {
// GIVEN
const stack = stackWithKeySigningKey({});
// WHEN
promptlyPrompt.mockReturnValue('');
const importMap = await importTemplateFromClean(stack);
// THEN
expect(importMap.resourceMap).toEqual({});
});
/**
* Do a full import cycle with the given stack template
*/
async function importTemplateFromClean(stack) {
givenCurrentStack(stack.stackName, { Resources: {} });
const importer = new import_1.ResourceImporter(stack, deployments);
const { additions } = await importer.discoverImportableResources();
const importable = await importer.askForResourceIdentifiers(additions);
await importer.importResourcesFromMap(importable, {});
return importable;
}
function givenCurrentStack(stackName, template) {
mock_sdk_1.mockCloudFormationClient.on(client_cloudformation_1.DescribeStacksCommand).resolves({
Stacks: [
{
StackName: stackName,
CreationTime: new Date(),
StackStatus: client_cloudformation_1.StackStatus.UPDATE_COMPLETE,
StackStatusReason: 'It is magic',
Outputs: [],
},
],
});
mock_sdk_1.mockCloudFormationClient.on(client_cloudformation_1.GetTemplateCommand).resolves({
TemplateBody: JSON.stringify(template),
});
mock_sdk_1.mockCloudFormationClient.on(client_cloudformation_1.GetTemplateSummaryCommand).resolves({
ResourceIdentifierSummaries: [
{
ResourceType: 'AWS::SQS::Queue',
ResourceIdentifiers: ['QueueName'],
},
{
ResourceType: 'AWS::DynamoDB::GlobalTable',
ResourceIdentifiers: ['TableName', 'TableArn', 'TableStreamArn'],
},
{
ResourceType: 'AWS::Route53::KeySigningKey',
ResourceIdentifiers: ['HostedZoneId,Name'],
},
],
});
mock_sdk_1.mockCloudFormationClient.on(client_cloudformation_1.DescribeChangeSetCommand).resolves({
Status: client_cloudformation_1.StackStatus.CREATE_COMPLETE,
Changes: [],
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbXBvcnQudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtJQUN6QixPQUFPO1FBQ0wsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztRQUNqQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUNsQixNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtLQUNsQixDQUFDO0FBQ0osQ0FBQyxDQUFDLENBQUM7QUFFSCwwRUFPd0M7QUFDeEMscUNBQXFDO0FBQ3JDLGlDQUFtQztBQUNuQyw4Q0FBc0c7QUFDdEcsd0RBQXFEO0FBQ3JELDBDQUE0RDtBQUU1RCxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBb0IsQ0FBQztBQUN0RCxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsTUFBbUIsQ0FBQztBQUVwRCxTQUFTLGNBQWMsQ0FBQyxLQUE4QjtJQUNwRCxPQUFPLElBQUEsZ0JBQVMsRUFBQztRQUNmLFNBQVMsRUFBRSxnQkFBZ0I7UUFDM0IsUUFBUSxFQUFFO1lBQ1IsU0FBUyxFQUFFO2dCQUNULE9BQU8sRUFBRTtvQkFDUCxJQUFJLEVBQUUsaUJBQWlCO29CQUN2QixVQUFVLEVBQUUsS0FBSztpQkFDbEI7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELE1BQU0sZ0JBQWdCLEdBQUcsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBRTVDLE1BQU0sc0JBQXNCLEdBQUcsY0FBYyxDQUFDO0lBQzVDLFNBQVMsRUFBRSxjQUFjO0NBQzFCLENBQUMsQ0FBQztBQUVILFNBQVMsb0JBQW9CLENBQUMsS0FBOEI7SUFDMUQsT0FBTyxJQUFBLGdCQUFTLEVBQUM7UUFDZixTQUFTLEVBQUUsZ0JBQWdCO1FBQzNCLFFBQVEsRUFBRTtZQUNSLFNBQVMsRUFBRTtnQkFDVCxPQUFPLEVBQUU7b0JBQ1AsSUFBSSxFQUFFLDRCQUE0QjtvQkFDbEMsVUFBVSxFQUFFLEtBQUs7aUJBQ2xCO2FBQ0Y7U0FDRjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLHNCQUFzQixDQUFDLEtBQThCO0lBQzVELE9BQU8sSUFBQSxnQkFBUyxFQUFDO1FBQ2YsU0FBUyxFQUFFLGNBQWM7UUFDekIsUUFBUSxFQUFFO1lBQ1IsU0FBUyxFQUFFO2dCQUNULEtBQUssRUFBRTtvQkFDTCxJQUFJLEVBQUUsNkJBQTZCO29CQUNuQyxVQUFVLEVBQUUsS0FBSztpQkFDbEI7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELElBQUksV0FBNEIsQ0FBQztBQUNqQyxJQUFJLFdBQXdCLENBQUM7QUFDN0IsVUFBVSxDQUFDLEdBQUcsRUFBRTtJQUNkLElBQUEsbUNBQXdCLEdBQUUsQ0FBQztJQUMzQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDckIsV0FBVyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO0lBQ3BDLFdBQVcsR0FBRyxJQUFJLHlCQUFXLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQ2pELENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLGdDQUFnQyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ2hELGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRTtRQUM1QyxTQUFTLEVBQUUsRUFBRTtLQUNkLENBQUMsQ0FBQztJQUVILE1BQU0sUUFBUSxHQUFHLElBQUkseUJBQWdCLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDckUsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLE1BQU0sUUFBUSxDQUFDLDJCQUEyQixFQUFFLENBQUM7SUFDbkUsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4QixNQUFNLENBQUMsZ0JBQWdCLENBQUM7WUFDdEIsU0FBUyxFQUFFLFNBQVM7U0FDckIsQ0FBQztLQUNILENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLDRFQUE0RSxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQzVGLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRTtRQUM1QyxTQUFTLEVBQUU7WUFDVCx3QkFBd0IsRUFBRTtnQkFDeEIsSUFBSSxFQUFFLGlCQUFpQjthQUN4QjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsTUFBTSxRQUFRLEdBQUcsSUFBSSx5QkFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNyRSxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUV2RyxnQ0FBZ0M7SUFDaEMsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO0FBQ2pGLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHFDQUFxQyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3JELFFBQVE7SUFDUixpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRSxNQUFNLFFBQVEsR0FBRyxJQUFJLHlCQUFnQixDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3JFLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxNQUFNLFFBQVEsQ0FBQywyQkFBMkIsRUFBRSxDQUFDO0lBRW5FLE9BQU87SUFDUCxjQUFjLENBQUMsaUJBQWlCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDakQsTUFBTSxVQUFVLEdBQUcsTUFBTSxRQUFRLENBQUMseUJBQXlCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFdkUsT0FBTztJQUNQLE1BQU0sQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQ3JDLE9BQU8sRUFBRTtZQUNQLFNBQVMsRUFBRSxjQUFjO1NBQzFCO0tBQ0YsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDekMsTUFBTSxDQUFDLGdCQUFnQixDQUFDO1lBQ3RCLFNBQVMsRUFBRSxTQUFTO1NBQ3JCLENBQUM7S0FDSCxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxtRUFBbUUsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNuRixRQUFRO0lBQ1IsaUJBQWlCLENBQUMsc0JBQXNCLENBQUMsU0FBUyxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdkUsTUFBTSxRQUFRLEdBQUcsSUFBSSx5QkFBZ0IsQ0FBQyxzQkFBc0IsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUMzRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztJQUVuRSxPQUFPO0lBQ1AsZUFBZSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sVUFBVSxHQUFHLE1BQU0sUUFBUSxDQUFDLHlCQUF5QixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRXZFLE9BQU87SUFDUCxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNyQyxPQUFPLEVBQUU7WUFDUCxTQUFTLEVBQUUsY0FBYztTQUMxQjtLQUNGLENBQUMsQ0FBQztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUMsT0FBTyxDQUFDO1FBQ3pDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQztZQUN0QixTQUFTLEVBQUUsU0FBUztTQUNyQixDQUFDO0tBQ0gsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsbUVBQW1FLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDbkYsUUFBUTtJQUNSLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sUUFBUSxHQUFHLElBQUkseUJBQWdCLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDckUsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLE1BQU0sUUFBUSxDQUFDLDJCQUEyQixFQUFFLENBQUM7SUFDbkUsTUFBTSxTQUFTLEdBQWM7UUFDM0IsZUFBZSxFQUFFLFNBQVM7UUFDMUIsV0FBVyxFQUFFO1lBQ1gsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRTtTQUN2QztLQUNGLENBQUM7SUFFRixPQUFPO0lBQ1AsTUFBTSxRQUFRLENBQUMsc0JBQXNCLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRXJELE1BQU0sQ0FBQyxtQ0FBd0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLDhDQUFzQixFQUFFO1FBQ2pGLGFBQWEsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztRQUNqQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsU0FBUztRQUNyQyxZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFDaEMsYUFBYSxFQUFFLFFBQVE7UUFDdkIsaUJBQWlCLEVBQUU7WUFDakI7Z0JBQ0UsaUJBQWlCLEVBQUUsU0FBUztnQkFDNUIsa0JBQWtCLEVBQUUsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFO2dCQUNqRCxZQUFZLEVBQUUsaUJBQWlCO2FBQ2hDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNsRixRQUFRO0lBRVIsTUFBTSxPQUFPLEdBQUc7UUFDZCxJQUFJLEVBQUUsaUJBQWlCO1FBQ3ZCLFVBQVUsRUFBRSxFQUFFO0tBQ2YsQ0FBQztJQUNGLE1BQU0sS0FBSyxHQUFHO1FBQ1osU0FBUyxFQUFFLGdCQUFnQjtRQUMzQixRQUFRLEVBQUU7WUFDUixTQUFTLEVBQUU7Z0JBQ1QsT0FBTztnQkFDUCxXQUFXLEVBQUU7b0JBQ1gsSUFBSSxFQUFFLG9CQUFvQjtvQkFDMUIsVUFBVSxFQUFFO3dCQUNWLFNBQVMsRUFBRSxRQUFRO3FCQUNwQjtpQkFDRjthQUNGO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLE1BQU0sRUFBRTtvQkFDTixXQUFXLEVBQUUsb0JBQW9CO29CQUNqQyxLQUFLLEVBQUUsYUFBYTtpQkFDckI7YUFDRjtTQUNGO0tBQ0YsQ0FBQztJQUVGLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDMUMsTUFBTSxRQUFRLEdBQUcsSUFBSSx5QkFBZ0IsQ0FBQyxJQUFBLGdCQUFTLEVBQUMsS0FBSyxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDckUsTUFBTSxVQUFVLEdBQUc7UUFDakI7WUFDRSxpQkFBaUIsRUFBRSxTQUFTO1lBQzVCLGtCQUFrQixFQUFFLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRTtZQUNqRCxZQUFZLEVBQUUsaUJBQWlCO1NBQ2hDO0tBQ0YsQ0FBQztJQUVGLE9BQU87SUFDUCxNQUFNLFFBQVEsQ0FBQywwQkFBMEIsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFakYsT0FBTztJQUNQLE1BQU0sQ0FBQyxtQ0FBd0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLDhDQUFzQixFQUFFO1FBQ2pGLGFBQWEsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztRQUNqQyxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsU0FBUztRQUNyQyxZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFDaEMsYUFBYSxFQUFFLFFBQVE7UUFDdkIsaUJBQWlCLEVBQUU7WUFDakI7Z0JBQ0UsaUJBQWlCLEVBQUUsU0FBUztnQkFDNUIsa0JBQWtCLEVBQUUsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFO2dCQUNqRCxZQUFZLEVBQUUsaUJBQWlCO2FBQ2hDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxxREFBcUQsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNyRSxRQUFRO0lBQ1IsTUFBTSxLQUFLLEdBQUcsb0JBQW9CLENBQUM7UUFDakMsU0FBUyxFQUFFLGNBQWM7UUFDekIsUUFBUSxFQUFFLCtCQUErQjtRQUN6QyxjQUFjLEVBQUUsZ0JBQWdCO0tBQ2pDLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxlQUFlLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxpQkFBaUI7SUFDMUQsTUFBTSx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVyQyxPQUFPO0lBQ1AsTUFBTSxDQUFDLG1DQUF3QixDQUFDLENBQUMseUJBQXlCLENBQUMsOENBQXNCLEVBQUU7UUFDakYsYUFBYSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO1FBQ2pDLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztRQUMxQixZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFDaEMsYUFBYSxFQUFFLFFBQVE7UUFDdkIsaUJBQWlCLEVBQUU7WUFDakI7Z0JBQ0UsaUJBQWlCLEVBQUUsU0FBUztnQkFDNUIsa0JBQWtCLEVBQUUsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFO2dCQUNqRCxZQUFZLEVBQUUsNEJBQTRCO2FBQzNDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyx5RUFBeUUsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN6RixtREFBbUQ7SUFDbkQsTUFBTSxLQUFLLEdBQUcsb0JBQW9CLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFdkMsT0FBTztJQUNQLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxNQUFNLFVBQVUsR0FBRyxNQUFNLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXhELDBCQUEwQjtJQUMxQixNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDckMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRTtLQUNqQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxnRUFBZ0UsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNoRix5RUFBeUU7SUFDekUsTUFBTSxLQUFLLEdBQUcsY0FBYyxDQUFDO1FBQzNCLFNBQVMsRUFBRSxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUU7S0FDaEMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxNQUFNLFVBQVUsR0FBRyxNQUFNLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXhELE9BQU87SUFDUCxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNyQyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFO0tBQ2pDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHNEQUFzRCxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3RFLFFBQVE7SUFDUixNQUFNLEtBQUssR0FBRyxzQkFBc0IsQ0FBQztRQUNuQyxZQUFZLEVBQUUsT0FBTztRQUNyQixJQUFJLEVBQUUsU0FBUztLQUNoQixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsZUFBZSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFckMsT0FBTztJQUNQLE1BQU0sQ0FBQyxtQ0FBd0IsQ0FBQyxDQUFDLHlCQUF5QixDQUFDLDhDQUFzQixFQUFFO1FBQ2pGLGFBQWEsRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztRQUNqQyxTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7UUFDMUIsWUFBWSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO1FBQ2hDLGFBQWEsRUFBRSxRQUFRO1FBQ3ZCLGlCQUFpQixFQUFFO1lBQ2pCO2dCQUNFLGlCQUFpQixFQUFFLE9BQU87Z0JBQzFCLGtCQUFrQixFQUFFLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFO2dCQUM5RCxZQUFZLEVBQUUsNkJBQTZCO2FBQzVDO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxnREFBZ0QsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNoRSxRQUFRO0lBQ1IsTUFBTSxLQUFLLEdBQUcsc0JBQXNCLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFekMsT0FBTztJQUNQLGNBQWMsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDekMsTUFBTSx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVyQyxPQUFPO0lBQ1AsTUFBTSxDQUFDLG1DQUF3QixDQUFDLENBQUMseUJBQXlCLENBQUMsOENBQXNCLEVBQUU7UUFDakYsYUFBYSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO1FBQ2pDLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztRQUMxQixZQUFZLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7UUFDaEMsYUFBYSxFQUFFLFFBQVE7UUFDdkIsaUJBQWlCLEVBQUU7WUFDakI7Z0JBQ0UsaUJBQWlCLEVBQUUsT0FBTztnQkFDMUIsa0JBQWtCLEVBQUUsRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7Z0JBQzlELFlBQVksRUFBRSw2QkFBNkI7YUFDNUM7U0FDRjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLCtFQUErRSxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQy9GLFFBQVE7SUFDUixNQUFNLEtBQUssR0FBRyxzQkFBc0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUV6QyxPQUFPO0lBQ1AsY0FBYyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNuQyxNQUFNLFNBQVMsR0FBRyxNQUFNLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXZELE9BQU87SUFDUCxNQUFNLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUM1QyxDQUFDLENBQUMsQ0FBQztBQUVIOztHQUVHO0FBQ0gsS0FBSyxVQUFVLHVCQUF1QixDQUFDLEtBQW1DO0lBQ3hFLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxTQUFTLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUN0RCxNQUFNLFFBQVEsR0FBRyxJQUFJLHlCQUFnQixDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQztJQUMxRCxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztJQUNuRSxNQUFNLFVBQVUsR0FBRyxNQUFNLFFBQVEsQ0FBQyx5QkFBeUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN2RSxNQUFNLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEQsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQztBQUVELFNBQVMsaUJBQWlCLENBQUMsU0FBaUIsRUFBRSxRQUFhO0lBQ3pELG1DQUF3QixDQUFDLEVBQUUsQ0FBQyw2Q0FBcUIsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUMxRCxNQUFNLEVBQUU7WUFDTjtnQkFDRSxTQUFTLEVBQUUsU0FBUztnQkFDcEIsWUFBWSxFQUFFLElBQUksSUFBSSxFQUFFO2dCQUN4QixXQUFXLEVBQUUsbUNBQVcsQ0FBQyxlQUFlO2dCQUN4QyxpQkFBaUIsRUFBRSxhQUFhO2dCQUNoQyxPQUFPLEVBQUUsRUFBRTthQUNaO1NBQ0Y7S0FDRixDQUFDLENBQUM7SUFDSCxtQ0FBd0IsQ0FBQyxFQUFFLENBQUMsMENBQWtCLENBQUMsQ0FBQyxRQUFRLENBQUM7UUFDdkQsWUFBWSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDO0tBQ3ZDLENBQUMsQ0FBQztJQUNILG1DQUF3QixDQUFDLEVBQUUsQ0FBQyxpREFBeUIsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUM5RCwyQkFBMkIsRUFBRTtZQUMzQjtnQkFDRSxZQUFZLEVBQUUsaUJBQWlCO2dCQUMvQixtQkFBbUIsRUFBRSxDQUFDLFdBQVcsQ0FBQzthQUNuQztZQUNEO2dCQUNFLFlBQVksRUFBRSw0QkFBNEI7Z0JBQzFDLG1CQUFtQixFQUFFLENBQUMsV0FBVyxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQzthQUNqRTtZQUNEO2dCQUNFLFlBQVksRUFBRSw2QkFBNkI7Z0JBQzNDLG1CQUFtQixFQUFFLENBQUMsbUJBQW1CLENBQUM7YUFDM0M7U0FDRjtLQUNGLENBQUMsQ0FBQztJQUVILG1DQUF3QixDQUFDLEVBQUUsQ0FBQyxnREFBd0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQztRQUM3RCxNQUFNLEVBQUUsbUNBQVcsQ0FBQyxlQUFlO1FBQ25DLE9BQU8sRUFBRSxFQUFFO0tBQ1osQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImplc3QubW9jaygncHJvbXB0bHknLCAoKSA9PiB7XG4gIHJldHVybiB7XG4gICAgLi4uamVzdC5yZXF1aXJlQWN0dWFsKCdwcm9tcHRseScpLFxuICAgIGNvbmZpcm06IGplc3QuZm4oKSxcbiAgICBwcm9tcHQ6IGplc3QuZm4oKSxcbiAgfTtcbn0pO1xuXG5pbXBvcnQge1xuICBDcmVhdGVDaGFuZ2VTZXRDb21tYW5kLFxuICBEZXNjcmliZUNoYW5nZVNldENvbW1hbmQsXG4gIERlc2NyaWJlU3RhY2tzQ29tbWFuZCxcbiAgR2V0VGVtcGxhdGVDb21tYW5kLFxuICBHZXRUZW1wbGF0ZVN1bW1hcnlDb21tYW5kLFxuICBTdGFja1N0YXR1cyxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNsb3VkZm9ybWF0aW9uJztcbmltcG9ydCAqIGFzIHByb21wdGx5IGZyb20gJ3Byb21wdGx5JztcbmltcG9ydCB7IHRlc3RTdGFjayB9IGZyb20gJy4vdXRpbCc7XG5pbXBvcnQgeyBNb2NrU2RrUHJvdmlkZXIsIG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudCwgcmVzdG9yZVNka01vY2tzVG9EZWZhdWx0IH0gZnJvbSAnLi91dGlsL21vY2stc2RrJztcbmltcG9ydCB7IERlcGxveW1lbnRzIH0gZnJvbSAnLi4vbGliL2FwaS9kZXBsb3ltZW50cyc7XG5pbXBvcnQgeyBSZXNvdXJjZUltcG9ydGVyLCBJbXBvcnRNYXAgfSBmcm9tICcuLi9saWIvaW1wb3J0JztcblxuY29uc3QgcHJvbXB0bHlDb25maXJtID0gcHJvbXB0bHkuY29uZmlybSBhcyBqZXN0Lk1vY2s7XG5jb25zdCBwcm9tcHRseVByb21wdCA9IHByb21wdGx5LnByb21wdCBhcyBqZXN0Lk1vY2s7XG5cbmZ1bmN0aW9uIHN0YWNrV2l0aFF1ZXVlKHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICByZXR1cm4gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdTdGFja1dpdGhRdWV1ZScsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBNeVF1ZXVlOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6U1FTOjpRdWV1ZScsXG4gICAgICAgICAgUHJvcGVydGllczogcHJvcHMsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xufVxuXG5jb25zdCBTVEFDS19XSVRIX1FVRVVFID0gc3RhY2tXaXRoUXVldWUoe30pO1xuXG5jb25zdCBTVEFDS19XSVRIX05BTUVEX1FVRVVFID0gc3RhY2tXaXRoUXVldWUoe1xuICBRdWV1ZU5hbWU6ICdUaGVRdWV1ZU5hbWUnLFxufSk7XG5cbmZ1bmN0aW9uIHN0YWNrV2l0aEdsb2JhbFRhYmxlKHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICByZXR1cm4gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdTdGFja1dpdGhUYWJsZScsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBNeVRhYmxlOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6RHluYW1vREI6Okdsb2JhbFRhYmxlJyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiBwcm9wcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHN0YWNrV2l0aEtleVNpZ25pbmdLZXkocHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gIHJldHVybiB0ZXN0U3RhY2soe1xuICAgIHN0YWNrTmFtZTogJ1N0YWNrV2l0aEtTSycsXG4gICAgdGVtcGxhdGU6IHtcbiAgICAgIFJlc291cmNlczoge1xuICAgICAgICBNeUtTSzoge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OlJvdXRlNTM6OktleVNpZ25pbmdLZXknLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHByb3BzLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcbn1cblxubGV0IHNka1Byb3ZpZGVyOiBNb2NrU2RrUHJvdmlkZXI7XG5sZXQgZGVwbG95bWVudHM6IERlcGxveW1lbnRzO1xuYmVmb3JlRWFjaCgoKSA9PiB7XG4gIHJlc3RvcmVTZGtNb2Nrc1RvRGVmYXVsdCgpO1xuICBqZXN0LnJlc2V0QWxsTW9ja3MoKTtcbiAgc2RrUHJvdmlkZXIgPSBuZXcgTW9ja1Nka1Byb3ZpZGVyKCk7XG4gIGRlcGxveW1lbnRzID0gbmV3IERlcGxveW1lbnRzKHsgc2RrUHJvdmlkZXIgfSk7XG59KTtcblxudGVzdCgnZGlzY292ZXJzIGltcG9ydGFibGUgcmVzb3VyY2VzJywgYXN5bmMgKCkgPT4ge1xuICBnaXZlbkN1cnJlbnRTdGFjayhTVEFDS19XSVRIX1FVRVVFLnN0YWNrTmFtZSwge1xuICAgIFJlc291cmNlczoge30sXG4gIH0pO1xuXG4gIGNvbnN0IGltcG9ydGVyID0gbmV3IFJlc291cmNlSW1wb3J0ZXIoU1RBQ0tfV0lUSF9RVUVVRSwgZGVwbG95bWVudHMpO1xuICBjb25zdCB7IGFkZGl0aW9ucyB9ID0gYXdhaXQgaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKCk7XG4gIGV4cGVjdChhZGRpdGlvbnMpLnRvRXF1YWwoW1xuICAgIGV4cGVjdC5vYmplY3RDb250YWluaW5nKHtcbiAgICAgIGxvZ2ljYWxJZDogJ015UXVldWUnLFxuICAgIH0pLFxuICBdKTtcbn0pO1xuXG50ZXN0KCdieSBkZWZhdWx0LCBpdHMgYW4gZXJyb3IgaWYgdGhlcmUgYXJlIG5vbi1hZGRpdGlvbiBjaGFuZ2VzIGluIHRoZSB0ZW1wbGF0ZScsIGFzeW5jICgpID0+IHtcbiAgZ2l2ZW5DdXJyZW50U3RhY2soU1RBQ0tfV0lUSF9RVUVVRS5zdGFja05hbWUsIHtcbiAgICBSZXNvdXJjZXM6IHtcbiAgICAgIFNvbWV0aGluZ1RoYXREaXNhcHBlYXJlZDoge1xuICAgICAgICBUeXBlOiAnQVdTOjpTMzo6QnVja2V0JyxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3QgaW1wb3J0ZXIgPSBuZXcgUmVzb3VyY2VJbXBvcnRlcihTVEFDS19XSVRIX1FVRVVFLCBkZXBsb3ltZW50cyk7XG4gIGF3YWl0IGV4cGVjdChpbXBvcnRlci5kaXNjb3ZlckltcG9ydGFibGVSZXNvdXJjZXMoKSkucmVqZWN0cy50b1Rocm93KC9ObyByZXNvdXJjZSB1cGRhdGVzIG9yIGRlbGV0ZXMvKTtcblxuICAvLyBCdXQgdGhlIGVycm9yIGNhbiBiZSBzaWxlbmNlZFxuICBhd2FpdCBleHBlY3QoaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKHRydWUpKS5yZXNvbHZlcy50b0JlVHJ1dGh5KCk7XG59KTtcblxudGVzdCgnYXNrcyBodW1hbiBmb3IgcmVzb3VyY2UgaWRlbnRpZmllcnMnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuQ3VycmVudFN0YWNrKFNUQUNLX1dJVEhfUVVFVUUuc3RhY2tOYW1lLCB7IFJlc291cmNlczoge30gfSk7XG4gIGNvbnN0IGltcG9ydGVyID0gbmV3IFJlc291cmNlSW1wb3J0ZXIoU1RBQ0tfV0lUSF9RVUVVRSwgZGVwbG95bWVudHMpO1xuICBjb25zdCB7IGFkZGl0aW9ucyB9ID0gYXdhaXQgaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKCk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseVByb21wdC5tb2NrUmVzb2x2ZWRWYWx1ZSgnVGhlUXVldWVOYW1lJyk7XG4gIGNvbnN0IGltcG9ydGFibGUgPSBhd2FpdCBpbXBvcnRlci5hc2tGb3JSZXNvdXJjZUlkZW50aWZpZXJzKGFkZGl0aW9ucyk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoaW1wb3J0YWJsZS5yZXNvdXJjZU1hcCkudG9FcXVhbCh7XG4gICAgTXlRdWV1ZToge1xuICAgICAgUXVldWVOYW1lOiAnVGhlUXVldWVOYW1lJyxcbiAgICB9LFxuICB9KTtcbiAgZXhwZWN0KGltcG9ydGFibGUuaW1wb3J0UmVzb3VyY2VzKS50b0VxdWFsKFtcbiAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgICBsb2dpY2FsSWQ6ICdNeVF1ZXVlJyxcbiAgICB9KSxcbiAgXSk7XG59KTtcblxudGVzdCgnYXNrcyBodW1hbiB0byBjb25maXJtIGF1dG9taWMgaW1wb3J0IGlmIGlkZW50aWZpZXIgaXMgaW4gdGVtcGxhdGUnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuQ3VycmVudFN0YWNrKFNUQUNLX1dJVEhfTkFNRURfUVVFVUUuc3RhY2tOYW1lLCB7IFJlc291cmNlczoge30gfSk7XG4gIGNvbnN0IGltcG9ydGVyID0gbmV3IFJlc291cmNlSW1wb3J0ZXIoU1RBQ0tfV0lUSF9OQU1FRF9RVUVVRSwgZGVwbG95bWVudHMpO1xuICBjb25zdCB7IGFkZGl0aW9ucyB9ID0gYXdhaXQgaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKCk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseUNvbmZpcm0ubW9ja1Jlc29sdmVkVmFsdWUodHJ1ZSk7XG4gIGNvbnN0IGltcG9ydGFibGUgPSBhd2FpdCBpbXBvcnRlci5hc2tGb3JSZXNvdXJjZUlkZW50aWZpZXJzKGFkZGl0aW9ucyk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoaW1wb3J0YWJsZS5yZXNvdXJjZU1hcCkudG9FcXVhbCh7XG4gICAgTXlRdWV1ZToge1xuICAgICAgUXVldWVOYW1lOiAnVGhlUXVldWVOYW1lJyxcbiAgICB9LFxuICB9KTtcbiAgZXhwZWN0KGltcG9ydGFibGUuaW1wb3J0UmVzb3VyY2VzKS50b0VxdWFsKFtcbiAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgICBsb2dpY2FsSWQ6ICdNeVF1ZXVlJyxcbiAgICB9KSxcbiAgXSk7XG59KTtcblxudGVzdCgnYXNrcyBodW1hbiB0byBjb25maXJtIGF1dG9taWMgaW1wb3J0IGlmIGlkZW50aWZpZXIgaXMgaW4gdGVtcGxhdGUnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGdpdmVuQ3VycmVudFN0YWNrKFNUQUNLX1dJVEhfUVVFVUUuc3RhY2tOYW1lLCB7IFJlc291cmNlczoge30gfSk7XG4gIGNvbnN0IGltcG9ydGVyID0gbmV3IFJlc291cmNlSW1wb3J0ZXIoU1RBQ0tfV0lUSF9RVUVVRSwgZGVwbG95bWVudHMpO1xuICBjb25zdCB7IGFkZGl0aW9ucyB9ID0gYXdhaXQgaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKCk7XG4gIGNvbnN0IGltcG9ydE1hcDogSW1wb3J0TWFwID0ge1xuICAgIGltcG9ydFJlc291cmNlczogYWRkaXRpb25zLFxuICAgIHJlc291cmNlTWFwOiB7XG4gICAgICBNeVF1ZXVlOiB7IFF1ZXVlTmFtZTogJ1RoZVF1ZXVlTmFtZScgfSxcbiAgICB9LFxuICB9O1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgaW1wb3J0ZXIuaW1wb3J0UmVzb3VyY2VzRnJvbU1hcChpbXBvcnRNYXAsIHt9KTtcblxuICBleHBlY3QobW9ja0Nsb3VkRm9ybWF0aW9uQ2xpZW50KS50b0hhdmVSZWNlaXZlZENvbW1hbmRXaXRoKENyZWF0ZUNoYW5nZVNldENvbW1hbmQsIHtcbiAgICBDaGFuZ2VTZXROYW1lOiBleHBlY3QuYW55KFN0cmluZyksXG4gICAgU3RhY2tOYW1lOiBTVEFDS19XSVRIX1FVRVVFLnN0YWNrTmFtZSxcbiAgICBUZW1wbGF0ZUJvZHk6IGV4cGVjdC5hbnkoU3RyaW5nKSxcbiAgICBDaGFuZ2VTZXRUeXBlOiAnSU1QT1JUJyxcbiAgICBSZXNvdXJjZXNUb0ltcG9ydDogW1xuICAgICAge1xuICAgICAgICBMb2dpY2FsUmVzb3VyY2VJZDogJ015UXVldWUnLFxuICAgICAgICBSZXNvdXJjZUlkZW50aWZpZXI6IHsgUXVldWVOYW1lOiAnVGhlUXVldWVOYW1lJyB9LFxuICAgICAgICBSZXNvdXJjZVR5cGU6ICdBV1M6OlNRUzo6UXVldWUnLFxuICAgICAgfSxcbiAgICBdLFxuICB9KTtcbn0pO1xuXG50ZXN0KCdpbXBvcnRpbmcgcmVzb3VyY2VzIGZyb20gbWlncmF0ZSBzdHJpcHMgY2RrIG1ldGFkYXRhIGFuZCBvdXRwdXRzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuXG4gIGNvbnN0IE15UXVldWUgPSB7XG4gICAgVHlwZTogJ0FXUzo6U1FTOjpRdWV1ZScsXG4gICAgUHJvcGVydGllczoge30sXG4gIH07XG4gIGNvbnN0IHN0YWNrID0ge1xuICAgIHN0YWNrTmFtZTogJ1N0YWNrV2l0aFF1ZXVlJyxcbiAgICB0ZW1wbGF0ZToge1xuICAgICAgUmVzb3VyY2VzOiB7XG4gICAgICAgIE15UXVldWUsXG4gICAgICAgIENES01ldGFkYXRhOiB7XG4gICAgICAgICAgVHlwZTogJ0FXUzo6Q0RLOjpNZXRhZGF0YScsXG4gICAgICAgICAgUHJvcGVydGllczoge1xuICAgICAgICAgICAgQW5hbHl0aWNzOiAnZXhpc3RzJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIE91dHB1dHM6IHtcbiAgICAgICAgT3V0cHV0OiB7XG4gICAgICAgICAgRGVzY3JpcHRpb246ICdUaGVyZSBpcyBhbiBvdXRwdXQnLFxuICAgICAgICAgIFZhbHVlOiAnT3V0cHV0VmFsdWUnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xuXG4gIGdpdmVuQ3VycmVudFN0YWNrKHN0YWNrLnN0YWNrTmFtZSwgc3RhY2spO1xuICBjb25zdCBpbXBvcnRlciA9IG5ldyBSZXNvdXJjZUltcG9ydGVyKHRlc3RTdGFjayhzdGFjayksIGRlcGxveW1lbnRzKTtcbiAgY29uc3QgbWlncmF0ZU1hcCA9IFtcbiAgICB7XG4gICAgICBMb2dpY2FsUmVzb3VyY2VJZDogJ015UXVldWUnLFxuICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiB7IFF1ZXVlTmFtZTogJ1RoZVF1ZXVlTmFtZScgfSxcbiAgICAgIFJlc291cmNlVHlwZTogJ0FXUzo6U1FTOjpRdWV1ZScsXG4gICAgfSxcbiAgXTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGltcG9ydGVyLmltcG9ydFJlc291cmNlc0Zyb21NaWdyYXRlKG1pZ3JhdGVNYXAsIFNUQUNLX1dJVEhfUVVFVUUudGVtcGxhdGUpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudCkudG9IYXZlUmVjZWl2ZWRDb21tYW5kV2l0aChDcmVhdGVDaGFuZ2VTZXRDb21tYW5kLCB7XG4gICAgQ2hhbmdlU2V0TmFtZTogZXhwZWN0LmFueShTdHJpbmcpLFxuICAgIFN0YWNrTmFtZTogU1RBQ0tfV0lUSF9RVUVVRS5zdGFja05hbWUsXG4gICAgVGVtcGxhdGVCb2R5OiBleHBlY3QuYW55KFN0cmluZyksXG4gICAgQ2hhbmdlU2V0VHlwZTogJ0lNUE9SVCcsXG4gICAgUmVzb3VyY2VzVG9JbXBvcnQ6IFtcbiAgICAgIHtcbiAgICAgICAgTG9naWNhbFJlc291cmNlSWQ6ICdNeVF1ZXVlJyxcbiAgICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiB7IFF1ZXVlTmFtZTogJ1RoZVF1ZXVlTmFtZScgfSxcbiAgICAgICAgUmVzb3VyY2VUeXBlOiAnQVdTOjpTUVM6OlF1ZXVlJyxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG59KTtcblxudGVzdCgnb25seSB1c2Ugb25lIGlkZW50aWZpZXIgaWYgbXVsdGlwbGUgYXJlIGluIHRlbXBsYXRlJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25zdCBzdGFjayA9IHN0YWNrV2l0aEdsb2JhbFRhYmxlKHtcbiAgICBUYWJsZU5hbWU6ICdUaGVUYWJsZU5hbWUnLFxuICAgIFRhYmxlQXJuOiAnVGhpc0ZpZWxkRG9lc250RXhpc3RJblJlYWxpdHknLFxuICAgIFRhYmxlU3RyZWFtQXJuOiAnTm9yRG9lc1RoaXNPbmUnLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIHByb21wdGx5Q29uZmlybS5tb2NrUmVzb2x2ZWRWYWx1ZSh0cnVlKTsgLy8gQ29uZmlybSB5ZXMvbm9cbiAgYXdhaXQgaW1wb3J0VGVtcGxhdGVGcm9tQ2xlYW4oc3RhY2spO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudCkudG9IYXZlUmVjZWl2ZWRDb21tYW5kV2l0aChDcmVhdGVDaGFuZ2VTZXRDb21tYW5kLCB7XG4gICAgQ2hhbmdlU2V0TmFtZTogZXhwZWN0LmFueShTdHJpbmcpLFxuICAgIFN0YWNrTmFtZTogc3RhY2suc3RhY2tOYW1lLFxuICAgIFRlbXBsYXRlQm9keTogZXhwZWN0LmFueShTdHJpbmcpLFxuICAgIENoYW5nZVNldFR5cGU6ICdJTVBPUlQnLFxuICAgIFJlc291cmNlc1RvSW1wb3J0OiBbXG4gICAgICB7XG4gICAgICAgIExvZ2ljYWxSZXNvdXJjZUlkOiAnTXlUYWJsZScsXG4gICAgICAgIFJlc291cmNlSWRlbnRpZmllcjogeyBUYWJsZU5hbWU6ICdUaGVUYWJsZU5hbWUnIH0sXG4gICAgICAgIFJlc291cmNlVHlwZTogJ0FXUzo6RHluYW1vREI6Okdsb2JhbFRhYmxlJyxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG59KTtcblxudGVzdCgnb25seSBhc2sgdXNlciBmb3Igb25lIGlkZW50aWZpZXIgaWYgbXVsdGlwbGUgcG9zc2libGUgb25lcyBhcmUgcG9zc2libGUnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOIC0tIG5vIGlkZW50aWZpZXJzIGluIHRlbXBsYXRlLCBzbyBhc2sgdXNlclxuICBjb25zdCBzdGFjayA9IHN0YWNrV2l0aEdsb2JhbFRhYmxlKHt9KTtcblxuICAvLyBXSEVOXG4gIHByb21wdGx5UHJvbXB0Lm1vY2tSZXNvbHZlZFZhbHVlKCdCYW5hbmEnKTtcbiAgY29uc3QgaW1wb3J0YWJsZSA9IGF3YWl0IGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrKTtcblxuICAvLyBUSEVOIC0tIG9ubHkgYXNrZWQgb25jZVxuICBleHBlY3QocHJvbXB0bHlQcm9tcHQpLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygxKTtcbiAgZXhwZWN0KGltcG9ydGFibGUucmVzb3VyY2VNYXApLnRvRXF1YWwoe1xuICAgIE15VGFibGU6IHsgVGFibGVOYW1lOiAnQmFuYW5hJyB9LFxuICB9KTtcbn0pO1xuXG50ZXN0KCdhc2sgaWRlbnRpZmllciBpZiB0aGUgdmFsdWUgaW4gdGhlIHRlbXBsYXRlIGlzIGEgQ0ZOIGludHJpbnNpYycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU4gLS0gaWRlbnRpZmllciBpbiB0ZW1wbGF0ZSBpcyBhIENGTiBpbnRyaW5zaWMgc28gaXQgZG9lc24ndCBjb3VudFxuICBjb25zdCBzdGFjayA9IHN0YWNrV2l0aFF1ZXVlKHtcbiAgICBRdWV1ZU5hbWU6IHsgUmVmOiAnU29tZVBhcmFtJyB9LFxuICB9KTtcblxuICAvLyBXSEVOXG4gIHByb21wdGx5UHJvbXB0Lm1vY2tSZXNvbHZlZFZhbHVlKCdCYW5hbmEnKTtcbiAgY29uc3QgaW1wb3J0YWJsZSA9IGF3YWl0IGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrKTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChpbXBvcnRhYmxlLnJlc291cmNlTWFwKS50b0VxdWFsKHtcbiAgICBNeVF1ZXVlOiB7IFF1ZXVlTmFtZTogJ0JhbmFuYScgfSxcbiAgfSk7XG59KTtcblxudGVzdCgndGFrZSBjb21wb3VuZCBpZGVudGlmaWVycyBmcm9tIHRoZSB0ZW1wbGF0ZSBpZiBmb3VuZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3Qgc3RhY2sgPSBzdGFja1dpdGhLZXlTaWduaW5nS2V5KHtcbiAgICBIb3N0ZWRab25lSWQ6ICd6LTEyMycsXG4gICAgTmFtZTogJ0tleU5hbWUnLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIHByb21wdGx5Q29uZmlybS5tb2NrUmVzb2x2ZWRWYWx1ZSh0cnVlKTtcbiAgYXdhaXQgaW1wb3J0VGVtcGxhdGVGcm9tQ2xlYW4oc3RhY2spO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudCkudG9IYXZlUmVjZWl2ZWRDb21tYW5kV2l0aChDcmVhdGVDaGFuZ2VTZXRDb21tYW5kLCB7XG4gICAgQ2hhbmdlU2V0TmFtZTogZXhwZWN0LmFueShTdHJpbmcpLFxuICAgIFN0YWNrTmFtZTogc3RhY2suc3RhY2tOYW1lLFxuICAgIFRlbXBsYXRlQm9keTogZXhwZWN0LmFueShTdHJpbmcpLFxuICAgIENoYW5nZVNldFR5cGU6ICdJTVBPUlQnLFxuICAgIFJlc291cmNlc1RvSW1wb3J0OiBbXG4gICAgICB7XG4gICAgICAgIExvZ2ljYWxSZXNvdXJjZUlkOiAnTXlLU0snLFxuICAgICAgICBSZXNvdXJjZUlkZW50aWZpZXI6IHsgSG9zdGVkWm9uZUlkOiAnei0xMjMnLCBOYW1lOiAnS2V5TmFtZScgfSxcbiAgICAgICAgUmVzb3VyY2VUeXBlOiAnQVdTOjpSb3V0ZTUzOjpLZXlTaWduaW5nS2V5JyxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG59KTtcblxudGVzdCgnYXNrIHVzZXIgZm9yIGNvbXBvdW5kIGlkZW50aWZpZXJzIGlmIG5vdCBmb3VuZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3Qgc3RhY2sgPSBzdGFja1dpdGhLZXlTaWduaW5nS2V5KHt9KTtcblxuICAvLyBXSEVOXG4gIHByb21wdGx5UHJvbXB0Lm1vY2tSZXR1cm5WYWx1ZSgnQmFuYW5hJyk7XG4gIGF3YWl0IGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrKTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChtb2NrQ2xvdWRGb3JtYXRpb25DbGllbnQpLnRvSGF2ZVJlY2VpdmVkQ29tbWFuZFdpdGgoQ3JlYXRlQ2hhbmdlU2V0Q29tbWFuZCwge1xuICAgIENoYW5nZVNldE5hbWU6IGV4cGVjdC5hbnkoU3RyaW5nKSxcbiAgICBTdGFja05hbWU6IHN0YWNrLnN0YWNrTmFtZSxcbiAgICBUZW1wbGF0ZUJvZHk6IGV4cGVjdC5hbnkoU3RyaW5nKSxcbiAgICBDaGFuZ2VTZXRUeXBlOiAnSU1QT1JUJyxcbiAgICBSZXNvdXJjZXNUb0ltcG9ydDogW1xuICAgICAge1xuICAgICAgICBMb2dpY2FsUmVzb3VyY2VJZDogJ015S1NLJyxcbiAgICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiB7IEhvc3RlZFpvbmVJZDogJ0JhbmFuYScsIE5hbWU6ICdCYW5hbmEnIH0sXG4gICAgICAgIFJlc291cmNlVHlwZTogJ0FXUzo6Um91dGU1Mzo6S2V5U2lnbmluZ0tleScsXG4gICAgICB9LFxuICAgIF0sXG4gIH0pO1xufSk7XG5cbnRlc3QoJ2RvIG5vdCBhc2sgZm9yIHNlY29uZCBwYXJ0IG9mIGNvbXBvdW5kIGlkZW50aWZpZXIgaWYgdGhlIHVzZXIgc2tpcHMgdGhlIGZpcnN0JywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25zdCBzdGFjayA9IHN0YWNrV2l0aEtleVNpZ25pbmdLZXkoe30pO1xuXG4gIC8vIFdIRU5cbiAgcHJvbXB0bHlQcm9tcHQubW9ja1JldHVyblZhbHVlKCcnKTtcbiAgY29uc3QgaW1wb3J0TWFwID0gYXdhaXQgaW1wb3J0VGVtcGxhdGVGcm9tQ2xlYW4oc3RhY2spO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGltcG9ydE1hcC5yZXNvdXJjZU1hcCkudG9FcXVhbCh7fSk7XG59KTtcblxuLyoqXG4gKiBEbyBhIGZ1bGwgaW1wb3J0IGN5Y2xlIHdpdGggdGhlIGdpdmVuIHN0YWNrIHRlbXBsYXRlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrOiBSZXR1cm5UeXBlPHR5cGVvZiB0ZXN0U3RhY2s+KSB7XG4gIGdpdmVuQ3VycmVudFN0YWNrKHN0YWNrLnN0YWNrTmFtZSwgeyBSZXNvdXJjZXM6IHt9IH0pO1xuICBjb25zdCBpbXBvcnRlciA9IG5ldyBSZXNvdXJjZUltcG9ydGVyKHN0YWNrLCBkZXBsb3ltZW50cyk7XG4gIGNvbnN0IHsgYWRkaXRpb25zIH0gPSBhd2FpdCBpbXBvcnRlci5kaXNjb3ZlckltcG9ydGFibGVSZXNvdXJjZXMoKTtcbiAgY29uc3QgaW1wb3J0YWJsZSA9IGF3YWl0IGltcG9ydGVyLmFza0ZvclJlc291cmNlSWRlbnRpZmllcnMoYWRkaXRpb25zKTtcbiAgYXdhaXQgaW1wb3J0ZXIuaW1wb3J0UmVzb3VyY2VzRnJvbU1hcChpbXBvcnRhYmxlLCB7fSk7XG4gIHJldHVybiBpbXBvcnRhYmxlO1xufVxuXG5mdW5jdGlvbiBnaXZlbkN1cnJlbnRTdGFjayhzdGFja05hbWU6IHN0cmluZywgdGVtcGxhdGU6IGFueSkge1xuICBtb2NrQ2xvdWRGb3JtYXRpb25DbGllbnQub24oRGVzY3JpYmVTdGFja3NDb21tYW5kKS5yZXNvbHZlcyh7XG4gICAgU3RhY2tzOiBbXG4gICAgICB7XG4gICAgICAgIFN0YWNrTmFtZTogc3RhY2tOYW1lLFxuICAgICAgICBDcmVhdGlvblRpbWU6IG5ldyBEYXRlKCksXG4gICAgICAgIFN0YWNrU3RhdHVzOiBTdGFja1N0YXR1cy5VUERBVEVfQ09NUExFVEUsXG4gICAgICAgIFN0YWNrU3RhdHVzUmVhc29uOiAnSXQgaXMgbWFnaWMnLFxuICAgICAgICBPdXRwdXRzOiBbXSxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG4gIG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudC5vbihHZXRUZW1wbGF0ZUNvbW1hbmQpLnJlc29sdmVzKHtcbiAgICBUZW1wbGF0ZUJvZHk6IEpTT04uc3RyaW5naWZ5KHRlbXBsYXRlKSxcbiAgfSk7XG4gIG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudC5vbihHZXRUZW1wbGF0ZVN1bW1hcnlDb21tYW5kKS5yZXNvbHZlcyh7XG4gICAgUmVzb3VyY2VJZGVudGlmaWVyU3VtbWFyaWVzOiBbXG4gICAgICB7XG4gICAgICAgIFJlc291cmNlVHlwZTogJ0FXUzo6U1FTOjpRdWV1ZScsXG4gICAgICAgIFJlc291cmNlSWRlbnRpZmllcnM6IFsnUXVldWVOYW1lJ10sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBSZXNvdXJjZVR5cGU6ICdBV1M6OkR5bmFtb0RCOjpHbG9iYWxUYWJsZScsXG4gICAgICAgIFJlc291cmNlSWRlbnRpZmllcnM6IFsnVGFibGVOYW1lJywgJ1RhYmxlQXJuJywgJ1RhYmxlU3RyZWFtQXJuJ10sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBSZXNvdXJjZVR5cGU6ICdBV1M6OlJvdXRlNTM6OktleVNpZ25pbmdLZXknLFxuICAgICAgICBSZXNvdXJjZUlkZW50aWZpZXJzOiBbJ0hvc3RlZFpvbmVJZCxOYW1lJ10sXG4gICAgICB9LFxuICAgIF0sXG4gIH0pO1xuXG4gIG1vY2tDbG91ZEZvcm1hdGlvbkNsaWVudC5vbihEZXNjcmliZUNoYW5nZVNldENvbW1hbmQpLnJlc29sdmVzKHtcbiAgICBTdGF0dXM6IFN0YWNrU3RhdHVzLkNSRUFURV9DT01QTEVURSxcbiAgICBDaGFuZ2VzOiBbXSxcbiAgfSk7XG59XG4iXX0=