UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

254 lines 32.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable import/order */ const mock_sdk_1 = require("./mock-sdk"); const stack_activity_monitor_1 = require("../../lib/api/util/cloudformation/stack-activity-monitor"); const util_1 = require("../util"); let sdk; let printer; beforeEach(() => { sdk = new mock_sdk_1.MockSdk(); printer = new FakePrinter(); }); describe('stack monitor event ordering and pagination', () => { test('continue to the next page if it exists', async () => { await testMonitorWithEventCalls([ (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [event(102)], NextToken: 'some-token', }; }, (request) => { expect(request.NextToken).toBe('some-token'); return { StackEvents: [event(101)], }; }, ]); // Printer sees them in chronological order expect(printer.eventIds).toEqual(['101', '102']); }); test('do not page further if we already saw the last event', async () => { await testMonitorWithEventCalls([ (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [event(101)], }; }, (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [event(102), event(101)], NextToken: 'some-token', }; }, (request) => { // Did not use the token expect(request.NextToken).toBeUndefined(); return {}; }, ]); // Seen in chronological order expect(printer.eventIds).toEqual(['101', '102']); }); test('do not page further if the last event is too old', async () => { await testMonitorWithEventCalls([ (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [event(101), event(95)], NextToken: 'some-token', }; }, (request) => { // Start again from the top expect(request.NextToken).toBeUndefined(); return {}; }, ]); // Seen only the new one expect(printer.eventIds).toEqual(['101']); }); test('do a final request after the monitor is stopped', async () => { await testMonitorWithEventCalls([ // Before stop (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [event(101)], }; }, ], // After stop [ (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [event(102), event(101)], }; }, ]); // Seen both expect(printer.eventIds).toEqual(['101', '102']); }); }); describe('stack monitor, collecting errors from events', () => { test('return errors from the root stack', async () => { const monitor = await testMonitorWithEventCalls([ (request) => { expect(request.NextToken).toBeUndefined(); return { StackEvents: [addErrorToStackEvent(event(100))], }; }, ]); expect(monitor.errors).toStrictEqual(['Test Error']); }); test('return errors from the nested stack', async () => { const monitor = await testMonitorWithEventCalls([ (request) => { expect(request.StackName).toStrictEqual('StackName'); return { StackEvents: [ addErrorToStackEvent(event(100), { logicalResourceId: 'nestedStackLogicalResourceId', physicalResourceId: 'nestedStackPhysicalResourceId', resourceType: 'AWS::CloudFormation::Stack', resourceStatusReason: 'nested stack failed', }), ], }; }, (request) => { expect(request.StackName).toStrictEqual('nestedStackPhysicalResourceId'); return { StackEvents: [ addErrorToStackEvent(event(101), { logicalResourceId: 'nestedResource', resourceType: 'Some::Nested::Resource', resourceStatusReason: 'actual failure error message', }), ], }; }, ]); expect(monitor.errors).toStrictEqual(['actual failure error message', 'nested stack failed']); }); test('does not consider events without physical resource id for monitoring nested stacks', async () => { const monitor = await testMonitorWithEventCalls([ (request) => { expect(request.StackName).toStrictEqual('StackName'); return { StackEvents: [ addErrorToStackEvent(event(100), { logicalResourceId: 'nestedStackLogicalResourceId', physicalResourceId: '', resourceType: 'AWS::CloudFormation::Stack', resourceStatusReason: 'nested stack failed', }), ], }; }, (request) => { // Note that the second call happened for the top level stack instead of a nested stack expect(request.StackName).toStrictEqual('StackName'); return { StackEvents: [ addErrorToStackEvent(event(101), { logicalResourceId: 'OtherResource', resourceType: 'Some::Other::Resource', resourceStatusReason: 'some failure', }), ], }; }, ]); expect(monitor.errors).toStrictEqual(['nested stack failed', 'some failure']); }); test('does not check for nested stacks that have already completed successfully', async () => { const monitor = await testMonitorWithEventCalls([ (request) => { expect(request.StackName).toStrictEqual('StackName'); return { StackEvents: [ addErrorToStackEvent(event(100), { logicalResourceId: 'nestedStackLogicalResourceId', physicalResourceId: 'nestedStackPhysicalResourceId', resourceType: 'AWS::CloudFormation::Stack', resourceStatusReason: 'nested stack status reason', resourceStatus: 'CREATE_COMPLETE', }), ], }; }, ]); expect(monitor.errors).toStrictEqual([]); }); }); const T0 = 1597837230504; // Events 0-99 are before we started paying attention const T100 = T0 + 100 * 1000; function event(nr) { return { EventId: `${nr}`, StackId: 'StackId', StackName: 'StackName', Timestamp: new Date(T0 + nr * 1000), }; } function addErrorToStackEvent(eventToUpdate, props = {}) { eventToUpdate.ResourceStatus = props.resourceStatus ?? 'UPDATE_FAILED'; eventToUpdate.ResourceType = props.resourceType ?? 'Test::Resource::Type'; eventToUpdate.ResourceStatusReason = props.resourceStatusReason ?? 'Test Error'; eventToUpdate.LogicalResourceId = props.logicalResourceId ?? 'testLogicalId'; eventToUpdate.PhysicalResourceId = props.physicalResourceId ?? 'testPhysicalResourceId'; return eventToUpdate; } async function testMonitorWithEventCalls(beforeStopInvocations, afterStopInvocations = []) { let describeStackEvents = jest.fn(); let finished = false; for (const invocation of beforeStopInvocations) { const invocation_ = invocation; // Capture loop variable in local because of closure semantics const isLast = invocation === beforeStopInvocations[beforeStopInvocations.length - 1]; describeStackEvents = describeStackEvents.mockImplementationOnce(request => { const ret = invocation_(request); if (isLast) { finished = true; } return ret; }); } for (const invocation of afterStopInvocations) { describeStackEvents = describeStackEvents.mockImplementationOnce(invocation); } describeStackEvents.mockImplementation(() => { return {}; }); sdk.stubCloudFormation({ describeStackEvents }); const monitor = new stack_activity_monitor_1.StackActivityMonitor(sdk.cloudFormation(), 'StackName', printer, undefined, new Date(T100)).start(); await waitForCondition(() => finished); await monitor.stop(); return monitor; } class FakePrinter { constructor() { this.updateSleep = 0; this.activities = []; } get eventIds() { return this.activities.map(a => a.event.EventId); } addActivity(activity) { this.activities.push(activity); } print() { } start() { } stop() { } } async function waitForCondition(cb) { while (!cb()) { await (0, util_1.sleep)(10); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stbW9uaXRvci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RhY2stbW9uaXRvci50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaUNBQWlDO0FBQ2pDLHlDQUFxQztBQUNyQyxxR0FBaUk7QUFDakksa0NBQWdDO0FBRWhDLElBQUksR0FBWSxDQUFDO0FBQ2pCLElBQUksT0FBb0IsQ0FBQztBQUN6QixVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2QsR0FBRyxHQUFHLElBQUksa0JBQU8sRUFBRSxDQUFDO0lBQ3BCLE9BQU8sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBQzlCLENBQUMsQ0FBQyxDQUFDO0FBRUgsUUFBUSxDQUFDLDZDQUE2QyxFQUFFLEdBQUcsRUFBRTtJQUMzRCxJQUFJLENBQUMsd0NBQXdDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDeEQsTUFBTSx5QkFBeUIsQ0FBQztZQUM5QixDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNWLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQzFDLE9BQU87b0JBQ0wsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29CQUN6QixTQUFTLEVBQUUsWUFBWTtpQkFDeEIsQ0FBQztZQUNKLENBQUM7WUFDRCxDQUFDLE9BQU8sRUFBRSxFQUFFO2dCQUNWLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUM3QyxPQUFPO29CQUNMLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDMUIsQ0FBQztZQUNKLENBQUM7U0FDRixDQUFDLENBQUM7UUFFSCwyQ0FBMkM7UUFDM0MsTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUMs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TSxLQUFLLEtBQVcsQ0FBQztJQUNqQixLQUFLLEtBQVcsQ0FBQztJQUNqQixJQUFJLEtBQVcsQ0FBQztDQUN4QjtBQUVELEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxFQUFpQjtJQUMvQyxPQUFPLENBQUMsRUFBRSxFQUFFLEVBQUU7UUFDWixNQUFNLElBQUEsWUFBSyxFQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQ2pCO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9vcmRlciAqL1xuaW1wb3J0IHsgTW9ja1NkayB9IGZyb20gJy4vbW9jay1zZGsnO1xuaW1wb3J0IHsgU3RhY2tBY3Rpdml0eU1vbml0b3IsIElBY3Rpdml0eVByaW50ZXIsIFN0YWNrQWN0aXZpdHkgfSBmcm9tICcuLi8uLi9saWIvYXBpL3V0aWwvY2xvdWRmb3JtYXRpb24vc3RhY2stYWN0aXZpdHktbW9uaXRvcic7XG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gJy4uL3V0aWwnO1xuXG5sZXQgc2RrOiBNb2NrU2RrO1xubGV0IHByaW50ZXI6IEZha2VQcmludGVyO1xuYmVmb3JlRWFjaCgoKSA9PiB7XG4gIHNkayA9IG5ldyBNb2NrU2RrKCk7XG4gIHByaW50ZXIgPSBuZXcgRmFrZVByaW50ZXIoKTtcbn0pO1xuXG5kZXNjcmliZSgnc3RhY2sgbW9uaXRvciBldmVudCBvcmRlcmluZyBhbmQgcGFnaW5hdGlvbicsICgpID0+IHtcbiAgdGVzdCgnY29udGludWUgdG8gdGhlIG5leHQgcGFnZSBpZiBpdCBleGlzdHMnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgdGVzdE1vbml0b3JXaXRoRXZlbnRDYWxscyhbXG4gICAgICAocmVxdWVzdCkgPT4ge1xuICAgICAgICBleHBlY3QocmVxdWVzdC5OZXh0VG9rZW4pLnRvQmVVbmRlZmluZWQoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBTdGFja0V2ZW50czogW2V2ZW50KDEwMildLFxuICAgICAgICAgIE5leHRUb2tlbjogJ3NvbWUtdG9rZW4nLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXF1ZXN0Lk5leHRUb2tlbikudG9CZSgnc29tZS10b2tlbicpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKV0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgLy8gUHJpbnRlciBzZWVzIHRoZW0gaW4gY2hyb25vbG9naWNhbCBvcmRlclxuICAgIGV4cGVjdChwcmludGVyLmV2ZW50SWRzKS50b0VxdWFsKFsnMTAxJywgJzEwMiddKTtcbiAgfSk7XG5cbiAgdGVzdCgnZG8gbm90IHBhZ2UgZnVydGhlciBpZiB3ZSBhbHJlYWR5IHNhdyB0aGUgbGFzdCBldmVudCcsIGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFtcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXF1ZXN0Lk5leHRUb2tlbikudG9CZVVuZGVmaW5lZCgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKV0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgU3RhY2tFdmVudHM6IFtldmVudCgxMDIpLCBldmVudCgxMDEpXSxcbiAgICAgICAgICBOZXh0VG9rZW46ICdzb21lLXRva2VuJyxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICAocmVxdWVzdCkgPT4ge1xuICAgICAgICAvLyBEaWQgbm90IHVzZSB0aGUgdG9rZW5cbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH0sXG4gICAgXSk7XG5cbiAgICAvLyBTZWVuIGluIGNocm9ub2xvZ2ljYWwgb3JkZXJcbiAgICBleHBlY3QocHJpbnRlci5ldmVudElkcykudG9FcXVhbChbJzEwMScsICcxMDInXSk7XG4gIH0pO1xuXG4gIHRlc3QoJ2RvIG5vdCBwYWdlIGZ1cnRoZXIgaWYgdGhlIGxhc3QgZXZlbnQgaXMgdG9vIG9sZCcsIGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFtcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXF1ZXN0Lk5leHRUb2tlbikudG9CZVVuZGVmaW5lZCgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIFN0YWNrRXZlbnRzOiBbZXZlbnQoMTAxKSwgZXZlbnQoOTUpXSxcbiAgICAgICAgICBOZXh0VG9rZW46ICdzb21lLXRva2VuJyxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICAocmVxdWVzdCkgPT4ge1xuICAgICAgICAvLyBTdGFydCBhZ2FpbiBmcm9tIHRoZSB0b3BcbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICAgIH0sXG4gICAgXSk7XG5cbiAgICAvLyBTZWVuIG9ubHkgdGhlIG5ldyBvbmVcbiAgICBleHBlY3QocHJpbnRlci5ldmVudElkcykudG9FcXVhbChbJzEwMSddKTtcbiAgfSk7XG5cbiAgdGVzdCgnZG8gYSBmaW5hbCByZXF1ZXN0IGFmdGVyIHRoZSBtb25pdG9yIGlzIHN0b3BwZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgdGVzdE1vbml0b3JXaXRoRXZlbnRDYWxscyhbXG4gICAgICAvLyBCZWZvcmUgc3RvcFxuICAgICAgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgU3RhY2tFdmVudHM6IFtldmVudCgxMDEpXSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgXSxcbiAgICAvLyBBZnRlciBzdG9wXG4gICAgW1xuICAgICAgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuTmV4dFRva2VuKS50b0JlVW5kZWZpbmVkKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgU3RhY2tFdmVudHM6IFtldmVudCgxMDIpLCBldmVudCgxMDEpXSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgXSk7XG5cbiAgICAvLyBTZWVuIGJvdGhcbiAgICBleHBlY3QocHJpbnRlci5ldmVudElkcykudG9FcXVhbChbJzEwMScsICcxMDInXSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdzdGFjayBtb25pdG9yLCBjb2xsZWN0aW5nIGVycm9ycyBmcm9tIGV2ZW50cycsICgpID0+IHtcbiAgdGVzdCgncmV0dXJuIGVycm9ycyBmcm9tIHRoZSByb290IHN0YWNrJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG1vbml0b3IgPSBhd2FpdCB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFtcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXF1ZXN0Lk5leHRUb2tlbikudG9CZVVuZGVmaW5lZCgpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIFN0YWNrRXZlbnRzOiBbYWRkRXJyb3JUb1N0YWNrRXZlbnQoZXZlbnQoMTAwKSldLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICBdKTtcblxuICAgIGV4cGVjdChtb25pdG9yLmVycm9ycykudG9TdHJpY3RFcXVhbChbJ1Rlc3QgRXJyb3InXSk7XG4gIH0pO1xuXG4gIHRlc3QoJ3JldHVybiBlcnJvcnMgZnJvbSB0aGUgbmVzdGVkIHN0YWNrJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG1vbml0b3IgPSBhd2FpdCB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFtcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXF1ZXN0LlN0YWNrTmFtZSkudG9TdHJpY3RFcXVhbCgnU3RhY2tOYW1lJyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgU3RhY2tFdmVudHM6IFtcbiAgICAgICAgICAgIGFkZEVycm9yVG9TdGFja0V2ZW50KFxuICAgICAgICAgICAgICBldmVudCgxMDApLCB7XG4gICAgICAgICAgICAgICAgbG9naWNhbFJlc291cmNlSWQ6ICduZXN0ZWRTdGFja0xvZ2ljYWxSZXNvdXJjZUlkJyxcbiAgICAgICAgICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6ICduZXN0ZWRTdGFja1BoeXNpY2FsUmVzb3VyY2VJZCcsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiAnQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2snLFxuICAgICAgICAgICAgICAgIHJlc291cmNlU3RhdHVzUmVhc29uOiAnbmVzdGVkIHN0YWNrIGZhaWxlZCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgICAgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuU3RhY2tOYW1lKS50b1N0cmljdEVxdWFsKCduZXN0ZWRTdGFja1BoeXNpY2FsUmVzb3VyY2VJZCcpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIFN0YWNrRXZlbnRzOiBbXG4gICAgICAgICAgICBhZGRFcnJvclRvU3RhY2tFdmVudChcbiAgICAgICAgICAgICAgZXZlbnQoMTAxKSwge1xuICAgICAgICAgICAgICAgIGxvZ2ljYWxSZXNvdXJjZUlkOiAnbmVzdGVkUmVzb3VyY2UnLFxuICAgICAgICAgICAgICAgIHJlc291cmNlVHlwZTogJ1NvbWU6Ok5lc3RlZDo6UmVzb3VyY2UnLFxuICAgICAgICAgICAgICAgIHJlc291cmNlU3RhdHVzUmVhc29uOiAnYWN0dWFsIGZhaWx1cmUgZXJyb3IgbWVzc2FnZScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgZXhwZWN0KG1vbml0b3IuZXJyb3JzKS50b1N0cmljdEVxdWFsKFsnYWN0dWFsIGZhaWx1cmUgZXJyb3IgbWVzc2FnZScsICduZXN0ZWQgc3RhY2sgZmFpbGVkJ10pO1xuICB9KTtcblxuICB0ZXN0KCdkb2VzIG5vdCBjb25zaWRlciBldmVudHMgd2l0aG91dCBwaHlzaWNhbCByZXNvdXJjZSBpZCBmb3IgbW9uaXRvcmluZyBuZXN0ZWQgc3RhY2tzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG1vbml0b3IgPSBhd2FpdCB0ZXN0TW9uaXRvcldpdGhFdmVudENhbGxzKFtcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIGV4cGVjdChyZXF1ZXN0LlN0YWNrTmFtZSkudG9TdHJpY3RFcXVhbCgnU3RhY2tOYW1lJyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgU3RhY2tFdmVudHM6IFtcbiAgICAgICAgICAgIGFkZEVycm9yVG9TdGFja0V2ZW50KFxuICAgICAgICAgICAgICBldmVudCgxMDApLCB7XG4gICAgICAgICAgICAgICAgbG9naWNhbFJlc291cmNlSWQ6ICduZXN0ZWRTdGFja0xvZ2ljYWxSZXNvdXJjZUlkJyxcbiAgICAgICAgICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6ICcnLFxuICAgICAgICAgICAgICAgIHJlc291cmNlVHlwZTogJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICAgICAgICAgICByZXNvdXJjZVN0YXR1c1JlYXNvbjogJ25lc3RlZCBzdGFjayBmYWlsZWQnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICAgIChyZXF1ZXN0KSA9PiB7XG4gICAgICAgIC8vIE5vdGUgdGhhdCB0aGUgc2Vjb25kIGNhbGwgaGFwcGVuZWQgZm9yIHRoZSB0b3AgbGV2ZWwgc3RhY2sgaW5zdGVhZCBvZiBhIG5lc3RlZCBzdGFja1xuICAgICAgICBleHBlY3QocmVxdWVzdC5TdGFja05hbWUpLnRvU3RyaWN0RXF1YWwoJ1N0YWNrTmFtZScpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIFN0YWNrRXZlbnRzOiBbXG4gICAgICAgICAgICBhZGRFcnJvclRvU3RhY2tFdmVudChcbiAgICAgICAgICAgICAgZXZlbnQoMTAxKSwge1xuICAgICAgICAgICAgICAgIGxvZ2ljYWxSZXNvdXJjZUlkOiAnT3RoZXJSZXNvdXJjZScsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiAnU29tZTo6T3RoZXI6OlJlc291cmNlJyxcbiAgICAgICAgICAgICAgICByZXNvdXJjZVN0YXR1c1JlYXNvbjogJ3NvbWUgZmFpbHVyZScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApLFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIF0pO1xuXG4gICAgZXhwZWN0KG1vbml0b3IuZXJyb3JzKS50b1N0cmljdEVxdWFsKFsnbmVzdGVkIHN0YWNrIGZhaWxlZCcsICdzb21lIGZhaWx1cmUnXSk7XG4gIH0pO1xuXG4gIHRlc3QoJ2RvZXMgbm90IGNoZWNrIGZvciBuZXN0ZWQgc3RhY2tzIHRoYXQgaGF2ZSBhbHJlYWR5IGNvbXBsZXRlZCBzdWNjZXNzZnVsbHknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbW9uaXRvciA9IGF3YWl0IHRlc3RNb25pdG9yV2l0aEV2ZW50Q2FsbHMoW1xuICAgICAgKHJlcXVlc3QpID0+IHtcbiAgICAgICAgZXhwZWN0KHJlcXVlc3QuU3RhY2tOYW1lKS50b1N0cmljdEVxdWFsKCdTdGFja05hbWUnKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBTdGFja0V2ZW50czogW1xuICAgICAgICAgICAgYWRkRXJyb3JUb1N0YWNrRXZlbnQoXG4gICAgICAgICAgICAgIGV2ZW50KDEwMCksIHtcbiAgICAgICAgICAgICAgICBsb2dpY2FsUmVzb3VyY2VJZDogJ25lc3RlZFN0YWNrTG9naWNhbFJlc291cmNlSWQnLFxuICAgICAgICAgICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDogJ25lc3RlZFN0YWNrUGh5c2ljYWxSZXNvdXJjZUlkJyxcbiAgICAgICAgICAgICAgICByZXNvdXJjZVR5cGU6ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VTdGF0dXNSZWFzb246ICduZXN0ZWQgc3RhY2sgc3RhdHVzIHJlYXNvbicsXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICBdKTtcblxuICAgIGV4cGVjdChtb25pdG9yLmVycm9ycykudG9TdHJpY3RFcXVhbChbXSk7XG4gIH0pO1xufSk7XG5cbmNvbnN0IFQwID0gMTU5NzgzNzIzMDUwNDtcblxuLy8gRXZlbnRzIDAtOTkgYXJlIGJlZm9yZSB3ZSBzdGFydGVkIHBheWluZyBhdHRlbnRpb25cbmNvbnN0IFQxMDAgPSBUMCArIDEwMCAqIDEwMDA7XG5cbmZ1bmN0aW9uIGV2ZW50KG5yOiBudW1iZXIpOiBBV1MuQ2xvdWRGb3JtYXRpb24uU3RhY2tFdmVudCB7XG4gIHJldHVybiB7XG4gICAgRXZlbnRJZDogYCR7bnJ9YCxcbiAgICBTdGFja0lkOiAnU3RhY2tJZCcsXG4gICAgU3RhY2tOYW1lOiAnU3RhY2tOYW1lJyxcbiAgICBUaW1lc3RhbXA6IG5ldyBEYXRlKFQwICsgbnIgKiAxMDAwKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gYWRkRXJyb3JUb1N0YWNrRXZlbnQoXG4gIGV2ZW50VG9VcGRhdGU6IEFXUy5DbG91ZEZvcm1hdGlvbi5TdGFja0V2ZW50LFxuICBwcm9wczoge1xuICAgIHJlc291cmNlU3RhdHVzPzogc3RyaW5nLFxuICAgIHJlc291cmNlVHlwZT86IHN0cmluZyxcbiAgICByZXNvdXJjZVN0YXR1c1JlYXNvbj86IHN0cmluZyxcbiAgICBsb2dpY2FsUmVzb3VyY2VJZD86IHN0cmluZyxcbiAgICBwaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmcsXG4gIH0gPSB7fSxcbik6IEFXUy5DbG91ZEZvcm1hdGlvbi5TdGFja0V2ZW50IHtcbiAgZXZlbnRUb1VwZGF0ZS5SZXNvdXJjZVN0YXR1cyA9IHByb3BzLnJlc291cmNlU3RhdHVzID8/ICdVUERBVEVfRkFJTEVEJztcbiAgZXZlbnRUb1VwZGF0ZS5SZXNvdXJjZVR5cGUgPSBwcm9wcy5yZXNvdXJjZVR5cGUgPz8gJ1Rlc3Q6OlJlc291cmNlOjpUeXBlJztcbiAgZXZlbnRUb1VwZGF0ZS5SZXNvdXJjZVN0YXR1c1JlYXNvbiA9IHByb3BzLnJlc291cmNlU3RhdHVzUmVhc29uID8/ICdUZXN0IEVycm9yJztcbiAgZXZlbnRUb1VwZGF0ZS5Mb2dpY2FsUmVzb3VyY2VJZCA9IHByb3BzLmxvZ2ljYWxSZXNvdXJjZUlkID8/ICd0ZXN0TG9naWNhbElkJztcbiAgZXZlbnRUb1VwZGF0ZS5QaHlzaWNhbFJlc291cmNlSWQgPSBwcm9wcy5waHlzaWNhbFJlc291cmNlSWQgPz8gJ3Rlc3RQaHlzaWNhbFJlc291cmNlSWQnO1xuICByZXR1cm4gZXZlbnRUb1VwZGF0ZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdE1vbml0b3JXaXRoRXZlbnRDYWxscyhcbiAgYmVmb3JlU3RvcEludm9jYXRpb25zOiBBcnJheTwoeDogQVdTLkNsb3VkRm9ybWF0aW9uLkRlc2NyaWJlU3RhY2tFdmVudHNJbnB1dCkgPT4gQVdTLkNsb3VkRm9ybWF0aW9uLkRlc2NyaWJlU3RhY2tFdmVudHNPdXRwdXQ+LFxuICBhZnRlclN0b3BJbnZvY2F0aW9uczogQXJyYXk8KHg6IEFXUy5DbG91ZEZvcm1hdGlvbi5EZXNjcmliZVN0YWNrRXZlbnRzSW5wdXQpID0+IEFXUy5DbG91ZEZvcm1hdGlvbi5EZXNjcmliZVN0YWNrRXZlbnRzT3V0cHV0PiA9IFtdLFxuKTogUHJvbWlzZTxTdGFja0FjdGl2aXR5TW9uaXRvcj4ge1xuICBsZXQgZGVzY3JpYmVTdGFja0V2ZW50cyA9IChqZXN0LmZuKCkgYXMgamVzdC5Nb2NrPEFXUy5DbG91ZEZvcm1hdGlvbi5EZXNjcmliZVN0YWNrRXZlbnRzT3V0cHV0LCBbQVdTLkNsb3VkRm9ybWF0aW9uLkRlc2NyaWJlU3RhY2tFdmVudHNJbnB1dF0+KTtcblxuICBsZXQgZmluaXNoZWQgPSBmYWxzZTtcblxuICBmb3IgKGNvbnN0IGludm9jYXRpb24gb2YgYmVmb3JlU3RvcEludm9jYXRpb25zKSB7XG4gICAgY29uc3QgaW52b2NhdGlvbl8gPSBpbnZvY2F0aW9uOyAvLyBDYXB0dXJlIGxvb3AgdmFyaWFibGUgaW4gbG9jYWwgYmVjYXVzZSBvZiBjbG9zdXJlIHNlbWFudGljc1xuICAgIGNvbnN0IGlzTGFzdCA9IGludm9jYXRpb24gPT09IGJlZm9yZVN0b3BJbnZvY2F0aW9uc1tiZWZvcmVTdG9wSW52b2NhdGlvbnMubGVuZ3RoIC0gMV07XG4gICAgZGVzY3JpYmVTdGFja0V2ZW50cyA9IGRlc2NyaWJlU3RhY2tFdmVudHMubW9ja0ltcGxlbWVudGF0aW9uT25jZShyZXF1ZXN0ID0+IHtcbiAgICAgIGNvbnN0IHJldCA9IGludm9jYXRpb25fKHJlcXVlc3QpO1xuICAgICAgaWYgKGlzTGFzdCkge1xuICAgICAgICBmaW5pc2hlZCA9IHRydWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0pO1xuICB9XG4gIGZvciAoY29uc3QgaW52b2NhdGlvbiBvZiBhZnRlclN0b3BJbnZvY2F0aW9ucykge1xuICAgIGRlc2NyaWJlU3RhY2tFdmVudHMgPSBkZXNjcmliZVN0YWNrRXZlbnRzLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoaW52b2NhdGlvbik7XG4gIH1cbiAgZGVzY3JpYmVTdGFja0V2ZW50cy5tb2NrSW1wbGVtZW50YXRpb24oKCkgPT4geyByZXR1cm4ge307IH0pO1xuXG4gIHNkay5zdHViQ2xvdWRGb3JtYXRpb24oeyBkZXNjcmliZVN0YWNrRXZlbnRzIH0pO1xuXG4gIGNvbnN0IG1vbml0b3IgPSBuZXcgU3RhY2tBY3Rpdml0eU1vbml0b3Ioc2RrLmNsb3VkRm9ybWF0aW9uKCksICdTdGFja05hbWUnLCBwcmludGVyLCB1bmRlZmluZWQsIG5ldyBEYXRlKFQxMDApKS5zdGFydCgpO1xuICBhd2FpdCB3YWl0Rm9yQ29uZGl0aW9uKCgpID0+IGZpbmlzaGVkKTtcbiAgYXdhaXQgbW9uaXRvci5zdG9wKCk7XG4gIHJldHVybiBtb25pdG9yO1xufVxuXG5jbGFzcyBGYWtlUHJpbnRlciBpbXBsZW1lbnRzIElBY3Rpdml0eVByaW50ZXIge1xuICBwdWJsaWMgdXBkYXRlU2xlZXA6IG51bWJlciA9IDA7XG4gIHB1YmxpYyByZWFkb25seSBhY3Rpdml0aWVzOiBTdGFja0FjdGl2aXR5W10gPSBbXTtcblxuICBwdWJsaWMgZ2V0IGV2ZW50SWRzKCkge1xuICAgIHJldHVybiB0aGlzLmFjdGl2aXRpZXMubWFwKGEgPT4gYS5ldmVudC5FdmVudElkKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRBY3Rpdml0eShhY3Rpdml0eTogU3RhY2tBY3Rpdml0eSk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZpdGllcy5wdXNoKGFjdGl2aXR5KTtcbiAgfVxuXG4gIHB1YmxpYyBwcmludCgpOiB2b2lkIHsgfVxuICBwdWJsaWMgc3RhcnQoKTogdm9pZCB7IH1cbiAgcHVibGljIHN0b3AoKTogdm9pZCB7IH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gd2FpdEZvckNvbmRpdGlvbihjYjogKCkgPT4gYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICB3aGlsZSAoIWNiKCkpIHtcbiAgICBhd2FpdCBzbGVlcCgxMCk7XG4gIH1cbn1cbiJdfQ==