aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
314 lines • 34.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable import/order */
jest.mock('promptly', () => {
return {
...jest.requireActual('promptly'),
confirm: jest.fn(),
prompt: jest.fn(),
};
});
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;
let createChangeSetInput;
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(() => {
jest.resetAllMocks();
sdkProvider = new mock_sdk_1.MockSdkProvider({ realSdk: false });
deployments = new deployments_1.Deployments({ sdkProvider });
createChangeSetInput = undefined;
});
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.importResources(importMap, {
stack: STACK_WITH_QUEUE,
});
expect(createChangeSetInput?.ResourcesToImport).toEqual([
{
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(createChangeSetInput?.ResourcesToImport).toEqual([
{
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(createChangeSetInput?.ResourcesToImport).toEqual([
{
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(createChangeSetInput?.ResourcesToImport).toEqual([
{
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.importResources(importable, { stack });
return importable;
}
function givenCurrentStack(stackName, template) {
sdkProvider.stubCloudFormation({
describeStacks() {
return {
Stacks: [
{
StackName: stackName,
CreationTime: new Date(),
StackStatus: 'UPDATE_COMPLETE',
StackStatusReason: 'It is magic',
Outputs: [],
},
],
};
},
getTemplate() {
return {
TemplateBody: JSON.stringify(template),
};
},
getTemplateSummary() {
return {
ResourceIdentifierSummaries: [
{
ResourceType: 'AWS::SQS::Queue',
ResourceIdentifiers: ['QueueName'],
},
{
ResourceType: 'AWS::DynamoDB::GlobalTable',
ResourceIdentifiers: ['TableName', 'TableArn', 'TableStreamArn'],
},
{
ResourceType: 'AWS::Route53::KeySigningKey',
ResourceIdentifiers: ['HostedZoneId,Name'],
},
],
};
},
deleteChangeSet() {
return {};
},
createChangeSet(request) {
createChangeSetInput = request;
return {};
},
describeChangeSet() {
return {
Status: 'CREATE_COMPLETE',
Changes: [],
};
},
executeChangeSet() {
return {};
},
describeStackEvents() {
return {};
},
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbXBvcnQudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFpQztBQUNqQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUU7SUFDekIsT0FBTztRQUNMLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUM7UUFDakMsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7UUFDbEIsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7S0FDbEIsQ0FBQztBQUNKLENBQUMsQ0FBQyxDQUFDO0FBRUgscUNBQXFDO0FBQ3JDLGlDQUFtQztBQUNuQyw4Q0FBa0Q7QUFDbEQsd0RBQXFEO0FBQ3JELDBDQUE0RDtBQUU1RCxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBb0IsQ0FBQztBQUN0RCxNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsTUFBbUIsQ0FBQztBQUVwRCxJQUFJLG9CQUF5RSxDQUFDO0FBRTlFLFNBQVMsY0FBYyxDQUFDLEtBQThCO0lBQ3BELE9BQU8sSUFBQSxnQkFBUyxFQUFDO1FBQ2YsU0FBUyxFQUFFLGdCQUFnQjtRQUMzQixRQUFRLEVBQUU7WUFDUixTQUFTLEVBQUU7Z0JBQ1QsT0FBTyxFQUFFO29CQUNQLElBQUksRUFBRSxpQkFBaUI7b0JBQ3ZCLFVBQVUsRUFBRSxLQUFLO2lCQUNsQjthQUNGO1NBQ0Y7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUM7QUFFNUMsTUFBTSxzQkFBc0IsR0FBRyxjQUFjLENBQUM7SUFDNUMsU0FBUyxFQUFFLGNBQWM7Q0FDMUIsQ0FBQyxDQUFDO0FBRUgsU0FBUyxvQkFBb0IsQ0FBQyxLQUE4QjtJQUMxRCxPQUFPLElBQUEsZ0JBQVMsRUFBQztRQUNmLFNBQVMsRUFBRSxnQkFBZ0I7UUFDM0Is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bmplc3QubW9jaygncHJvbXB0bHknLCAoKSA9PiB7XG4gIHJldHVybiB7XG4gICAgLi4uamVzdC5yZXF1aXJlQWN0dWFsKCdwcm9tcHRseScpLFxuICAgIGNvbmZpcm06IGplc3QuZm4oKSxcbiAgICBwcm9tcHQ6IGplc3QuZm4oKSxcbiAgfTtcbn0pO1xuXG5pbXBvcnQgKiBhcyBwcm9tcHRseSBmcm9tICdwcm9tcHRseSc7XG5pbXBvcnQgeyB0ZXN0U3RhY2sgfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IHsgTW9ja1Nka1Byb3ZpZGVyIH0gZnJvbSAnLi91dGlsL21vY2stc2RrJztcbmltcG9ydCB7IERlcGxveW1lbnRzIH0gZnJvbSAnLi4vbGliL2FwaS9kZXBsb3ltZW50cyc7XG5pbXBvcnQgeyBSZXNvdXJjZUltcG9ydGVyLCBJbXBvcnRNYXAgfSBmcm9tICcuLi9saWIvaW1wb3J0JztcblxuY29uc3QgcHJvbXB0bHlDb25maXJtID0gcHJvbXB0bHkuY29uZmlybSBhcyBqZXN0Lk1vY2s7XG5jb25zdCBwcm9tcHRseVByb21wdCA9IHByb21wdGx5LnByb21wdCBhcyBqZXN0Lk1vY2s7XG5cbmxldCBjcmVhdGVDaGFuZ2VTZXRJbnB1dDogQVdTLkNsb3VkRm9ybWF0aW9uLkNyZWF0ZUNoYW5nZVNldElucHV0IHwgdW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBzdGFja1dpdGhRdWV1ZShwcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pIHtcbiAgcmV0dXJuIHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnU3RhY2tXaXRoUXVldWUnLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgTXlRdWV1ZToge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OlNRUzo6UXVldWUnLFxuICAgICAgICAgIFByb3BlcnRpZXM6IHByb3BzLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9KTtcbn1cblxuY29uc3QgU1RBQ0tfV0lUSF9RVUVVRSA9IHN0YWNrV2l0aFF1ZXVlKHt9KTtcblxuY29uc3QgU1RBQ0tfV0lUSF9OQU1FRF9RVUVVRSA9IHN0YWNrV2l0aFF1ZXVlKHtcbiAgUXVldWVOYW1lOiAnVGhlUXVldWVOYW1lJyxcbn0pO1xuXG5mdW5jdGlvbiBzdGFja1dpdGhHbG9iYWxUYWJsZShwcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pIHtcbiAgcmV0dXJuIHRlc3RTdGFjayh7XG4gICAgc3RhY2tOYW1lOiAnU3RhY2tXaXRoVGFibGUnLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgTXlUYWJsZToge1xuICAgICAgICAgIFR5cGU6ICdBV1M6OkR5bmFtb0RCOjpHbG9iYWxUYWJsZScsXG4gICAgICAgICAgUHJvcGVydGllczogcHJvcHMsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzdGFja1dpdGhLZXlTaWduaW5nS2V5KHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICByZXR1cm4gdGVzdFN0YWNrKHtcbiAgICBzdGFja05hbWU6ICdTdGFja1dpdGhLU0snLFxuICAgIHRlbXBsYXRlOiB7XG4gICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgTXlLU0s6IHtcbiAgICAgICAgICBUeXBlOiAnQVdTOjpSb3V0ZTUzOjpLZXlTaWduaW5nS2V5JyxcbiAgICAgICAgICBQcm9wZXJ0aWVzOiBwcm9wcyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSk7XG59XG5cbmxldCBzZGtQcm92aWRlcjogTW9ja1Nka1Byb3ZpZGVyO1xubGV0IGRlcGxveW1lbnRzOiBEZXBsb3ltZW50cztcbmJlZm9yZUVhY2goKCkgPT4ge1xuICBqZXN0LnJlc2V0QWxsTW9ja3MoKTtcbiAgc2RrUHJvdmlkZXIgPSBuZXcgTW9ja1Nka1Byb3ZpZGVyKHsgcmVhbFNkazogZmFsc2UgfSk7XG4gIGRlcGxveW1lbnRzID0gbmV3IERlcGxveW1lbnRzKHsgc2RrUHJvdmlkZXIgfSk7XG4gIGNyZWF0ZUNoYW5nZVNldElucHV0ID0gdW5kZWZpbmVkO1xufSk7XG5cbnRlc3QoJ2Rpc2NvdmVycyBpbXBvcnRhYmxlIHJlc291cmNlcycsIGFzeW5jICgpID0+IHtcbiAgZ2l2ZW5DdXJyZW50U3RhY2soU1RBQ0tfV0lUSF9RVUVVRS5zdGFja05hbWUsIHtcbiAgICBSZXNvdXJjZXM6IHt9LFxuICB9KTtcblxuICBjb25zdCBpbXBvcnRlciA9IG5ldyBSZXNvdXJjZUltcG9ydGVyKFNUQUNLX1dJVEhfUVVFVUUsIGRlcGxveW1lbnRzKTtcbiAgY29uc3QgeyBhZGRpdGlvbnMgfSA9IGF3YWl0IGltcG9ydGVyLmRpc2NvdmVySW1wb3J0YWJsZVJlc291cmNlcygpO1xuICBleHBlY3QoYWRkaXRpb25zKS50b0VxdWFsKFtcbiAgICBleHBlY3Qub2JqZWN0Q29udGFpbmluZyh7XG4gICAgICBsb2dpY2FsSWQ6ICdNeVF1ZXVlJyxcbiAgICB9KSxcbiAgXSk7XG59KTtcblxudGVzdCgnYnkgZGVmYXVsdCwgaXRzIGFuIGVycm9yIGlmIHRoZXJlIGFyZSBub24tYWRkaXRpb24gY2hhbmdlcyBpbiB0aGUgdGVtcGxhdGUnLCBhc3luYyAoKSA9PiB7XG4gIGdpdmVuQ3VycmVudFN0YWNrKFNUQUNLX1dJVEhfUVVFVUUuc3RhY2tOYW1lLCB7XG4gICAgUmVzb3VyY2VzOiB7XG4gICAgICBTb21ldGhpbmdUaGF0RGlzYXBwZWFyZWQ6IHtcbiAgICAgICAgVHlwZTogJ0FXUzo6UzM6OkJ1Y2tldCcsXG4gICAgICB9LFxuICAgIH0sXG4gIH0pO1xuXG4gIGNvbnN0IGltcG9ydGVyID0gbmV3IFJlc291cmNlSW1wb3J0ZXIoU1RBQ0tfV0lUSF9RVUVVRSwgZGVwbG95bWVudHMpO1xuICBhd2FpdCBleHBlY3QoaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKCkpLnJlamVjdHMudG9UaHJvdygvTm8gcmVzb3VyY2UgdXBkYXRlcyBvciBkZWxldGVzLyk7XG5cbiAgLy8gQnV0IHRoZSBlcnJvciBjYW4gYmUgc2lsZW5jZWRcbiAgYXdhaXQgZXhwZWN0KGltcG9ydGVyLmRpc2NvdmVySW1wb3J0YWJsZVJlc291cmNlcyh0cnVlKSkucmVzb2x2ZXMudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2Fza3MgaHVtYW4gZm9yIHJlc291cmNlIGlkZW50aWZpZXJzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlbkN1cnJlbnRTdGFjayhTVEFDS19XSVRIX1FVRVVFLnN0YWNrTmFtZSwgeyBSZXNvdXJjZXM6IHt9IH0pO1xuICBjb25zdCBpbXBvcnRlciA9IG5ldyBSZXNvdXJjZUltcG9ydGVyKFNUQUNLX1dJVEhfUVVFVUUsIGRlcGxveW1lbnRzKTtcbiAgY29uc3QgeyBhZGRpdGlvbnMgfSA9IGF3YWl0IGltcG9ydGVyLmRpc2NvdmVySW1wb3J0YWJsZVJlc291cmNlcygpO1xuXG4gIC8vIFdIRU5cbiAgcHJvbXB0bHlQcm9tcHQubW9ja1Jlc29sdmVkVmFsdWUoJ1RoZVF1ZXVlTmFtZScpO1xuICBjb25zdCBpbXBvcnRhYmxlID0gYXdhaXQgaW1wb3J0ZXIuYXNrRm9yUmVzb3VyY2VJZGVudGlmaWVycyhhZGRpdGlvbnMpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGltcG9ydGFibGUucmVzb3VyY2VNYXApLnRvRXF1YWwoe1xuICAgIE15UXVldWU6IHtcbiAgICAgIFF1ZXVlTmFtZTogJ1RoZVF1ZXVlTmFtZScsXG4gICAgfSxcbiAgfSk7XG4gIGV4cGVjdChpbXBvcnRhYmxlLmltcG9ydFJlc291cmNlcykudG9FcXVhbChbXG4gICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgbG9naWNhbElkOiAnTXlRdWV1ZScsXG4gICAgfSksXG4gIF0pO1xufSk7XG5cbnRlc3QoJ2Fza3MgaHVtYW4gdG8gY29uZmlybSBhdXRvbWljIGltcG9ydCBpZiBpZGVudGlmaWVyIGlzIGluIHRlbXBsYXRlJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlbkN1cnJlbnRTdGFjayhTVEFDS19XSVRIX05BTUVEX1FVRVVFLnN0YWNrTmFtZSwgeyBSZXNvdXJjZXM6IHt9IH0pO1xuICBjb25zdCBpbXBvcnRlciA9IG5ldyBSZXNvdXJjZUltcG9ydGVyKFNUQUNLX1dJVEhfTkFNRURfUVVFVUUsIGRlcGxveW1lbnRzKTtcbiAgY29uc3QgeyBhZGRpdGlvbnMgfSA9IGF3YWl0IGltcG9ydGVyLmRpc2NvdmVySW1wb3J0YWJsZVJlc291cmNlcygpO1xuXG4gIC8vIFdIRU5cbiAgcHJvbXB0bHlDb25maXJtLm1vY2tSZXNvbHZlZFZhbHVlKHRydWUpO1xuICBjb25zdCBpbXBvcnRhYmxlID0gYXdhaXQgaW1wb3J0ZXIuYXNrRm9yUmVzb3VyY2VJZGVudGlmaWVycyhhZGRpdGlvbnMpO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGltcG9ydGFibGUucmVzb3VyY2VNYXApLnRvRXF1YWwoe1xuICAgIE15UXVldWU6IHtcbiAgICAgIFF1ZXVlTmFtZTogJ1RoZVF1ZXVlTmFtZScsXG4gICAgfSxcbiAgfSk7XG4gIGV4cGVjdChpbXBvcnRhYmxlLmltcG9ydFJlc291cmNlcykudG9FcXVhbChbXG4gICAgZXhwZWN0Lm9iamVjdENvbnRhaW5pbmcoe1xuICAgICAgbG9naWNhbElkOiAnTXlRdWV1ZScsXG4gICAgfSksXG4gIF0pO1xufSk7XG5cbnRlc3QoJ2Fza3MgaHVtYW4gdG8gY29uZmlybSBhdXRvbWljIGltcG9ydCBpZiBpZGVudGlmaWVyIGlzIGluIHRlbXBsYXRlJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBnaXZlbkN1cnJlbnRTdGFjayhTVEFDS19XSVRIX1FVRVVFLnN0YWNrTmFtZSwgeyBSZXNvdXJjZXM6IHt9IH0pO1xuICBjb25zdCBpbXBvcnRlciA9IG5ldyBSZXNvdXJjZUltcG9ydGVyKFNUQUNLX1dJVEhfUVVFVUUsIGRlcGxveW1lbnRzKTtcbiAgY29uc3QgeyBhZGRpdGlvbnMgfSA9IGF3YWl0IGltcG9ydGVyLmRpc2NvdmVySW1wb3J0YWJsZVJlc291cmNlcygpO1xuICBjb25zdCBpbXBvcnRNYXA6IEltcG9ydE1hcCA9IHtcbiAgICBpbXBvcnRSZXNvdXJjZXM6IGFkZGl0aW9ucyxcbiAgICByZXNvdXJjZU1hcDoge1xuICAgICAgTXlRdWV1ZTogeyBRdWV1ZU5hbWU6ICdUaGVRdWV1ZU5hbWUnIH0sXG4gICAgfSxcbiAgfTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGltcG9ydGVyLmltcG9ydFJlc291cmNlcyhpbXBvcnRNYXAsIHtcbiAgICBzdGFjazogU1RBQ0tfV0lUSF9RVUVVRSxcbiAgfSk7XG5cbiAgZXhwZWN0KGNyZWF0ZUNoYW5nZVNldElucHV0Py5SZXNvdXJjZXNUb0ltcG9ydCkudG9FcXVhbChbXG4gICAge1xuICAgICAgTG9naWNhbFJlc291cmNlSWQ6ICdNeVF1ZXVlJyxcbiAgICAgIFJlc291cmNlSWRlbnRpZmllcjogeyBRdWV1ZU5hbWU6ICdUaGVRdWV1ZU5hbWUnIH0sXG4gICAgICBSZXNvdXJjZVR5cGU6ICdBV1M6OlNRUzo6UXVldWUnLFxuICAgIH0sXG4gIF0pO1xufSk7XG5cbnRlc3QoJ29ubHkgdXNlIG9uZSBpZGVudGlmaWVyIGlmIG11bHRpcGxlIGFyZSBpbiB0ZW1wbGF0ZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3Qgc3RhY2sgPSBzdGFja1dpdGhHbG9iYWxUYWJsZSh7XG4gICAgVGFibGVOYW1lOiAnVGhlVGFibGVOYW1lJyxcbiAgICBUYWJsZUFybjogJ1RoaXNGaWVsZERvZXNudEV4aXN0SW5SZWFsaXR5JyxcbiAgICBUYWJsZVN0cmVhbUFybjogJ05vckRvZXNUaGlzT25lJyxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseUNvbmZpcm0ubW9ja1Jlc29sdmVkVmFsdWUodHJ1ZSk7IC8vIENvbmZpcm0geWVzL25vXG4gIGF3YWl0IGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrKTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjcmVhdGVDaGFuZ2VTZXRJbnB1dD8uUmVzb3VyY2VzVG9JbXBvcnQpLnRvRXF1YWwoW1xuICAgIHtcbiAgICAgIExvZ2ljYWxSZXNvdXJjZUlkOiAnTXlUYWJsZScsXG4gICAgICBSZXNvdXJjZUlkZW50aWZpZXI6IHsgVGFibGVOYW1lOiAnVGhlVGFibGVOYW1lJyB9LFxuICAgICAgUmVzb3VyY2VUeXBlOiAnQVdTOjpEeW5hbW9EQjo6R2xvYmFsVGFibGUnLFxuICAgIH0sXG4gIF0pO1xufSk7XG5cbnRlc3QoJ29ubHkgYXNrIHVzZXIgZm9yIG9uZSBpZGVudGlmaWVyIGlmIG11bHRpcGxlIHBvc3NpYmxlIG9uZXMgYXJlIHBvc3NpYmxlJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTiAtLSBubyBpZGVudGlmaWVycyBpbiB0ZW1wbGF0ZSwgc28gYXNrIHVzZXJcbiAgY29uc3Qgc3RhY2sgPSBzdGFja1dpdGhHbG9iYWxUYWJsZSh7fSk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseVByb21wdC5tb2NrUmVzb2x2ZWRWYWx1ZSgnQmFuYW5hJyk7XG4gIGNvbnN0IGltcG9ydGFibGUgPSBhd2FpdCBpbXBvcnRUZW1wbGF0ZUZyb21DbGVhbihzdGFjayk7XG5cbiAgLy8gVEhFTiAtLSBvbmx5IGFza2VkIG9uY2VcbiAgZXhwZWN0KHByb21wdGx5UHJvbXB0KS50b0hhdmVCZWVuQ2FsbGVkVGltZXMoMSk7XG4gIGV4cGVjdChpbXBvcnRhYmxlLnJlc291cmNlTWFwKS50b0VxdWFsKHtcbiAgICBNeVRhYmxlOiB7IFRhYmxlTmFtZTogJ0JhbmFuYScgfSxcbiAgfSk7XG59KTtcblxudGVzdCgnYXNrIGlkZW50aWZpZXIgaWYgdGhlIHZhbHVlIGluIHRoZSB0ZW1wbGF0ZSBpcyBhIENGTiBpbnRyaW5zaWMnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOIC0tIGlkZW50aWZpZXIgaW4gdGVtcGxhdGUgaXMgYSBDRk4gaW50cmluc2ljIHNvIGl0IGRvZXNuJ3QgY291bnRcbiAgY29uc3Qgc3RhY2sgPSBzdGFja1dpdGhRdWV1ZSh7XG4gICAgUXVldWVOYW1lOiB7IFJlZjogJ1NvbWVQYXJhbScgfSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseVByb21wdC5tb2NrUmVzb2x2ZWRWYWx1ZSgnQmFuYW5hJyk7XG4gIGNvbnN0IGltcG9ydGFibGUgPSBhd2FpdCBpbXBvcnRUZW1wbGF0ZUZyb21DbGVhbihzdGFjayk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoaW1wb3J0YWJsZS5yZXNvdXJjZU1hcCkudG9FcXVhbCh7XG4gICAgTXlRdWV1ZTogeyBRdWV1ZU5hbWU6ICdCYW5hbmEnIH0sXG4gIH0pO1xufSk7XG5cbnRlc3QoJ3Rha2UgY29tcG91bmQgaWRlbnRpZmllcnMgZnJvbSB0aGUgdGVtcGxhdGUgaWYgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbnN0IHN0YWNrID0gc3RhY2tXaXRoS2V5U2lnbmluZ0tleSh7XG4gICAgSG9zdGVkWm9uZUlkOiAnei0xMjMnLFxuICAgIE5hbWU6ICdLZXlOYW1lJyxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseUNvbmZpcm0ubW9ja1Jlc29sdmVkVmFsdWUodHJ1ZSk7XG4gIGF3YWl0IGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrKTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChjcmVhdGVDaGFuZ2VTZXRJbnB1dD8uUmVzb3VyY2VzVG9JbXBvcnQpLnRvRXF1YWwoW1xuICAgIHtcbiAgICAgIExvZ2ljYWxSZXNvdXJjZUlkOiAnTXlLU0snLFxuICAgICAgUmVzb3VyY2VJZGVudGlmaWVyOiB7IEhvc3RlZFpvbmVJZDogJ3otMTIzJywgTmFtZTogJ0tleU5hbWUnIH0sXG4gICAgICBSZXNvdXJjZVR5cGU6ICdBV1M6OlJvdXRlNTM6OktleVNpZ25pbmdLZXknLFxuICAgIH0sXG4gIF0pO1xufSk7XG5cbnRlc3QoJ2FzayB1c2VyIGZvciBjb21wb3VuZCBpZGVudGlmaWVycyBpZiBub3QgZm91bmQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbnN0IHN0YWNrID0gc3RhY2tXaXRoS2V5U2lnbmluZ0tleSh7fSk7XG5cbiAgLy8gV0hFTlxuICBwcm9tcHRseVByb21wdC5tb2NrUmV0dXJuVmFsdWUoJ0JhbmFuYScpO1xuICBhd2FpdCBpbXBvcnRUZW1wbGF0ZUZyb21DbGVhbihzdGFjayk7XG5cbiAgLy8gVEhFTlxuICBleHBlY3QoY3JlYXRlQ2hhbmdlU2V0SW5wdXQ/LlJlc291cmNlc1RvSW1wb3J0KS50b0VxdWFsKFtcbiAgICB7XG4gICAgICBMb2dpY2FsUmVzb3VyY2VJZDogJ015S1NLJyxcbiAgICAgIFJlc291cmNlSWRlbnRpZmllcjogeyBIb3N0ZWRab25lSWQ6ICdCYW5hbmEnLCBOYW1lOiAnQmFuYW5hJyB9LFxuICAgICAgUmVzb3VyY2VUeXBlOiAnQVdTOjpSb3V0ZTUzOjpLZXlTaWduaW5nS2V5JyxcbiAgICB9LFxuICBdKTtcbn0pO1xuXG50ZXN0KCdkbyBub3QgYXNrIGZvciBzZWNvbmQgcGFydCBvZiBjb21wb3VuZCBpZGVudGlmaWVyIGlmIHRoZSB1c2VyIHNraXBzIHRoZSBmaXJzdCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uc3Qgc3RhY2sgPSBzdGFja1dpdGhLZXlTaWduaW5nS2V5KHt9KTtcblxuICAvLyBXSEVOXG4gIHByb21wdGx5UHJvbXB0Lm1vY2tSZXR1cm5WYWx1ZSgnJyk7XG4gIGNvbnN0IGltcG9ydE1hcCA9IGF3YWl0IGltcG9ydFRlbXBsYXRlRnJvbUNsZWFuKHN0YWNrKTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChpbXBvcnRNYXAucmVzb3VyY2VNYXApLnRvRXF1YWwoe30pO1xufSk7XG5cbi8qKlxuICogRG8gYSBmdWxsIGltcG9ydCBjeWNsZSB3aXRoIHRoZSBnaXZlbiBzdGFjayB0ZW1wbGF0ZVxuICovXG5hc3luYyBmdW5jdGlvbiBpbXBvcnRUZW1wbGF0ZUZyb21DbGVhbihzdGFjazogUmV0dXJuVHlwZTx0eXBlb2YgdGVzdFN0YWNrPikge1xuICBnaXZlbkN1cnJlbnRTdGFjayhzdGFjay5zdGFja05hbWUsIHsgUmVzb3VyY2VzOiB7fSB9KTtcbiAgY29uc3QgaW1wb3J0ZXIgPSBuZXcgUmVzb3VyY2VJbXBvcnRlcihzdGFjaywgZGVwbG95bWVudHMpO1xuICBjb25zdCB7IGFkZGl0aW9ucyB9ID0gYXdhaXQgaW1wb3J0ZXIuZGlzY292ZXJJbXBvcnRhYmxlUmVzb3VyY2VzKCk7XG4gIGNvbnN0IGltcG9ydGFibGUgPSBhd2FpdCBpbXBvcnRlci5hc2tGb3JSZXNvdXJjZUlkZW50aWZpZXJzKGFkZGl0aW9ucyk7XG4gIGF3YWl0IGltcG9ydGVyLmltcG9ydFJlc291cmNlcyhpbXBvcnRhYmxlLCB7IHN0YWNrIH0pO1xuICByZXR1cm4gaW1wb3J0YWJsZTtcbn1cblxuZnVuY3Rpb24gZ2l2ZW5DdXJyZW50U3RhY2soc3RhY2tOYW1lOiBzdHJpbmcsIHRlbXBsYXRlOiBhbnkpIHtcbiAgc2RrUHJvdmlkZXIuc3R1YkNsb3VkRm9ybWF0aW9uKHtcbiAgICBkZXNjcmliZVN0YWNrcygpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YWNrczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIFN0YWNrTmFtZTogc3RhY2tOYW1lLFxuICAgICAgICAgICAgQ3JlYXRpb25UaW1lOiBuZXcgRGF0ZSgpLFxuICAgICAgICAgICAgU3RhY2tTdGF0dXM6ICdVUERBVEVfQ09NUExFVEUnLFxuICAgICAgICAgICAgU3RhY2tTdGF0dXNSZWFzb246ICdJdCBpcyBtYWdpYycsXG4gICAgICAgICAgICBPdXRwdXRzOiBbXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9LFxuICAgIGdldFRlbXBsYXRlKCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgVGVtcGxhdGVCb2R5OiBKU09OLnN0cmluZ2lmeSh0ZW1wbGF0ZSksXG4gICAgICB9O1xuICAgIH0sXG4gICAgZ2V0VGVtcGxhdGVTdW1tYXJ5KCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUmVzb3VyY2VJZGVudGlmaWVyU3VtbWFyaWVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgUmVzb3VyY2VUeXBlOiAnQVdTOjpTUVM6OlF1ZXVlJyxcbiAgICAgICAgICAgIFJlc291cmNlSWRlbnRpZmllcnM6IFsnUXVldWVOYW1lJ10sXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBSZXNvdXJjZVR5cGU6ICdBV1M6OkR5bmFtb0RCOjpHbG9iYWxUYWJsZScsXG4gICAgICAgICAgICBSZXNvdXJjZUlkZW50aWZpZXJzOiBbJ1RhYmxlTmFtZScsICdUYWJsZUFybicsICdUYWJsZVN0cmVhbUFybiddLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgUmVzb3VyY2VUeXBlOiAnQVdTOjpSb3V0ZTUzOjpLZXlTaWduaW5nS2V5JyxcbiAgICAgICAgICAgIFJlc291cmNlSWRlbnRpZmllcnM6IFsnSG9zdGVkWm9uZUlkLE5hbWUnXSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9LFxuICAgIGRlbGV0ZUNoYW5nZVNldCgpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9LFxuICAgIGNyZWF0ZUNoYW5nZVNldChyZXF1ZXN0KSB7XG4gICAgICBjcmVhdGVDaGFuZ2VTZXRJbnB1dCA9IHJlcXVlc3Q7XG4gICAgICByZXR1cm4ge307XG4gICAgfSxcbiAgICBkZXNjcmliZUNoYW5nZVNldCgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFN0YXR1czogJ0NSRUFURV9DT01QTEVURScsXG4gICAgICAgIENoYW5nZXM6IFtdLFxuICAgICAgfTtcbiAgICB9LFxuICAgIGV4ZWN1dGVDaGFuZ2VTZXQoKSB7XG4gICAgICByZXR1cm4ge307XG4gICAgfSxcbiAgICBkZXNjcmliZVN0YWNrRXZlbnRzKCkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0sXG4gIH0pO1xufVxuIl19