custom-resource-helper
Version:
Helper for cloudformation custom resources
107 lines • 16.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.customResourceHelper = void 0;
const axios_1 = __importDefault(require("axios"));
const log_factory_1 = require("./log-factory");
exports.customResourceHelper = (resourceHandlerFactory, logFactory) => async (event, context) => {
// Initialise default logger
let logger = log_factory_1.logFactory(event);
try {
// Replace logger if a factory was given
if (logFactory) {
logger = logFactory(event, context);
}
const resourceHandler = await resourceHandlerFactory(logger);
return await Promise.race([
handleRessource(event, context, resourceHandler, logger),
handleTimeout(context, logger)
]);
// Catch any exceptions, log the stacktrace, send a failure back to
// CloudFormation and then raise an exception
}
catch (error) {
logger.error(error);
const responseDetails = {
responseStatus: 'FAILED',
reason: error.message || 'Internal Error'
};
return sendResponse(event, context, responseDetails, logger);
}
};
const sendResponse = async (event, context, sendResponseDetails, logger) => {
const { responseStatus, physicalResourceId, responseData, reason } = sendResponseDetails;
const responseBody = JSON.stringify({
Status: responseStatus,
Reason: reason ||
`See the details in CloudWatch Log Stream: ${context.logStreamName}`,
PhysicalResourceId: physicalResourceId || 'None',
StackId: event.StackId,
RequestId: event.RequestId,
LogicalResourceId: event.LogicalResourceId,
Data: responseData || {}
});
logger.debug('Response body:');
logger.debug(responseBody);
const responseUrl = event.ResponseURL;
logger.debug(`CFN response URL: ${responseUrl}`);
try {
const response = await axios_1.default.put(responseUrl, responseBody, {
headers: { 'content-type': '', 'content-length': responseBody.length }
});
logger.info(`CloudFormation returned status code: ${response.status}`);
}
catch (error) {
logger.error('sendResponse(...) failed executing axios.put:');
logger.error(error);
throw error;
}
};
const handleRessource = async (event, context, resourceHandler, logger) => {
logger.debug(event);
// Define a physicalResourceId for the resource, if the event is an update and the
// returned physicalResourceId changes, cloudformation will then issue a delete
// against the old id
let physicalResourceId = 'None';
// Define an object to place any response information you would like to send
// back to CloudFormation(these keys can then be used by Fn:: GetAttr)
let responseData = {};
// Execute custom resource handlers
const { onCreate, onUpdate, onDelete } = resourceHandler;
switch (event.RequestType) {
case 'Create':
if (onCreate) {
({ physicalResourceId, responseData = {} } = await onCreate(event, context, logger));
}
break;
case 'Update':
if (onUpdate) {
({ physicalResourceId, responseData = {} } = await onUpdate(event, context, logger));
}
break;
case 'Delete':
if (onDelete) {
await onDelete(event, context, logger);
}
break;
default:
throw new Error('Invalid RequestType received');
}
// Send response back to CloudFormation
const responseDetails = {
responseStatus: 'SUCCESS',
reason: 'OK',
responseData,
physicalResourceId
};
return sendResponse(event, context, responseDetails, logger);
};
const handleTimeout = async (context, logger) => new Promise((_, reject) => {
setTimeout(() => {
logger.error('Execution is about to time out, sending failure message');
reject(new Error('Execution timed out'));
}, context.getRemainingTimeInMillis() - 3000);
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tLXJlc291cmNlLWhlbHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jdXN0b20tcmVzb3VyY2UtaGVscGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGtEQUEwQjtBQVUxQiwrQ0FJdUI7QUF5Q1YsUUFBQSxvQkFBb0IsR0FBRyxDQUNsQyxzQkFBOEMsRUFDOUMsVUFBdUIsRUFDYyxFQUFFLENBQUMsS0FBSyxFQUFFLEtBQXdDLEVBQUUsT0FBZ0IsRUFBaUIsRUFBRTtJQUM1SCw0QkFBNEI7SUFDNUIsSUFBSSxNQUFNLEdBQUcsd0JBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEMsSUFBSTtRQUNGLHdDQUF3QztRQUN4QyxJQUFJLFVBQVUsRUFBRTtZQUNkLE1BQU0sR0FBRyxVQUFVLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1NBQ3JDO1FBQ0QsTUFBTSxlQUFlLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM3RCxPQUFPLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUN4QixlQUFlLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDO1lBQ3hELGFBQWEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDO1NBQy9CLENBQUMsQ0FBQztRQUNILG1FQUFtRTtRQUNuRSw2Q0FBNkM7S0FDOUM7SUFBQyxPQUFPLEtBQUssRUFBRTtRQUNkLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEIsTUFBTSxlQUFlLEdBQXdCO1lBQzNDLGNBQWMsRUFBRSxRQUFRO1lBQ3hCLE1BQU0sRUFBRSxLQUFLLENBQUMsT0FBTyxJQUFJLGdCQUFnQjtTQUMxQyxDQUFDO1FBQ0YsT0FBTyxZQUFZLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUM7S0FDOUQ7QUFDSCxDQUFDLENBQUM7QUFT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TSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0tBQ25EO0lBRUQsdUNBQXVDO0lBQ3ZDLE1BQU0sZUFBZSxHQUF3QjtRQUMzQyxjQUFjLEVBQUUsU0FBUztRQUN6QixNQUFNLEVBQUUsSUFBSTtRQUNaLFlBQVk7UUFDWixrQkFBa0I7S0FDbkIsQ0FBQztJQUNGLE9BQU8sWUFBWSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBQy9ELENBQUMsQ0FBQztBQUVGLE1BQU0sYUFBYSxHQUFHLEtBQUssRUFBRSxPQUFnQixFQUFFLE1BQWMsRUFBaUIsRUFBRSxDQUM5RSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRTtJQUN4QixVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsTUFBTSxDQUFDLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO1FBQ3hFLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7SUFDM0MsQ0FBQyxFQUFFLE9BQU8sQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQ2hELENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGF4aW9zIGZyb20gJ2F4aW9zJztcbmltcG9ydCB0eXBlIHtcbiAgQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LFxuICBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlQ3JlYXRlRXZlbnQsXG4gIENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VVcGRhdGVFdmVudCxcbiAgQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZURlbGV0ZUV2ZW50LFxuICBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlSGFuZGxlcixcbiAgQ29udGV4dFxufSBmcm9tICdhd3MtbGFtYmRhJztcblxuaW1wb3J0IHtcbiAgbG9nRmFjdG9yeSBhcyBkZWZhdWx0TG9nRmFjdG9yeSxcbiAgTG9nRmFjdG9yeSxcbiAgTG9nZ2VyXG59IGZyb20gJy4vbG9nLWZhY3RvcnknO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlSGFuZGxlclJldHVybiB7XG4gIHBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICByZXNwb25zZURhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPbkNyZWF0ZUhhbmRsZXIge1xuICAoXG4gICAgZXZlbnQ6IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VDcmVhdGVFdmVudCxcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIGxvZ2dlcjogTG9nZ2VyXG4gICk6IFByb21pc2U8UmVzb3VyY2VIYW5kbGVyUmV0dXJuPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPblVwZGF0ZUhhbmRsZXIge1xuICAoXG4gICAgZXZlbnQ6IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VVcGRhdGVFdmVudCxcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIGxvZ2dlcjogTG9nZ2VyXG4gICk6IFByb21pc2U8UmVzb3VyY2VIYW5kbGVyUmV0dXJuPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPbkRlbGV0ZUhhbmRsZXIge1xuICAoXG4gICAgZXZlbnQ6IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VEZWxldGVFdmVudCxcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIGxvZ2dlcjogTG9nZ2VyXG4gICk6IFByb21pc2U8dm9pZD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VIYW5kbGVyIHtcbiAgb25DcmVhdGU/OiBPbkNyZWF0ZUhhbmRsZXI7XG4gIG9uVXBkYXRlPzogT25VcGRhdGVIYW5kbGVyO1xuICBvbkRlbGV0ZT86IE9uRGVsZXRlSGFuZGxlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvdXJjZUhhbmRsZXJGYWN0b3J5IHtcbiAgKGxvZ2dlcj86IExvZ2dlcik6IFJlc291cmNlSGFuZGxlciB8IFByb21pc2U8UmVzb3VyY2VIYW5kbGVyPjtcbn1cblxuZXhwb3J0IGNvbnN0IGN1c3RvbVJlc291cmNlSGVscGVyID0gKFxuICByZXNvdXJjZUhhbmRsZXJGYWN0b3J5OiBSZXNvdXJjZUhhbmRsZXJGYWN0b3J5LFxuICBsb2dGYWN0b3J5PzogTG9nRmFjdG9yeVxuKTogQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUhhbmRsZXIgPT4gYXN5bmMgKGV2ZW50OiBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgLy8gSW5pdGlhbGlzZSBkZWZhdWx0IGxvZ2dlclxuICBsZXQgbG9nZ2VyID0gZGVmYXVsdExvZ0ZhY3RvcnkoZXZlbnQpO1xuICB0cnkge1xuICAgIC8vIFJlcGxhY2UgbG9nZ2VyIGlmIGEgZmFjdG9yeSB3YXMgZ2l2ZW5cbiAgICBpZiAobG9nRmFjdG9yeSkge1xuICAgICAgbG9nZ2VyID0gbG9nRmFjdG9yeShldmVudCwgY29udGV4dCk7XG4gICAgfVxuICAgIGNvbnN0IHJlc291cmNlSGFuZGxlciA9IGF3YWl0IHJlc291cmNlSGFuZGxlckZhY3RvcnkobG9nZ2VyKTtcbiAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgIGhhbmRsZVJlc3NvdXJjZShldmVudCwgY29udGV4dCwgcmVzb3VyY2VIYW5kbGVyLCBsb2dnZXIpLFxuICAgICAgaGFuZGxlVGltZW91dChjb250ZXh0LCBsb2dnZXIpXG4gICAgXSk7XG4gICAgLy8gQ2F0Y2ggYW55IGV4Y2VwdGlvbnMsIGxvZyB0aGUgc3RhY2t0cmFjZSwgc2VuZCBhIGZhaWx1cmUgYmFjayB0b1xuICAgIC8vIENsb3VkRm9ybWF0aW9uIGFuZCB0aGVuIHJhaXNlIGFuIGV4Y2VwdGlvblxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ2dlci5lcnJvcihlcnJvcik7XG4gICAgY29uc3QgcmVzcG9uc2VEZXRhaWxzOiBTZW5kUmVzcG9uc2VEZXRhaWxzID0ge1xuICAgICAgcmVzcG9uc2VTdGF0dXM6ICdGQUlMRUQnLFxuICAgICAgcmVhc29uOiBlcnJvci5tZXNzYWdlIHx8ICdJbnRlcm5hbCBFcnJvcidcbiAgICB9O1xuICAgIHJldHVybiBzZW5kUmVzcG9uc2UoZXZlbnQsIGNvbnRleHQsIHJlc3BvbnNlRGV0YWlscywgbG9nZ2VyKTtcbiAgfVxufTtcblxuaW50ZXJmYWNlIFNlbmRSZXNwb25zZURldGFpbHMge1xuICByZXNwb25zZVN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCc7XG4gIHJlc3BvbnNlRGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBwaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmc7XG4gIHJlYXNvbj86IHN0cmluZztcbn1cblxuY29uc3Qgc2VuZFJlc3BvbnNlID0gYXN5bmMgKFxuICBldmVudDogQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LFxuICBjb250ZXh0OiBDb250ZXh0LFxuICBzZW5kUmVzcG9uc2VEZXRhaWxzOiBTZW5kUmVzcG9uc2VEZXRhaWxzLFxuICBsb2dnZXI6IExvZ2dlclxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IHtcbiAgICByZXNwb25zZVN0YXR1cyxcbiAgICBwaHlzaWNhbFJlc291cmNlSWQsXG4gICAgcmVzcG9uc2VEYXRhLFxuICAgIHJlYXNvblxuICB9ID0gc2VuZFJlc3BvbnNlRGV0YWlscztcblxuICBjb25zdCByZXNwb25zZUJvZHkgPSBKU09OLnN0cmluZ2lmeSh7XG4gICAgU3RhdHVzOiByZXNwb25zZVN0YXR1cyxcbiAgICBSZWFzb246XG4gICAgICByZWFzb24gfHxcbiAgICAgIGBTZWUgdGhlIGRldGFpbHMgaW4gQ2xvdWRXYXRjaCBMb2cgU3RyZWFtOiAke2NvbnRleHQubG9nU3RyZWFtTmFtZX1gLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkIHx8ICdOb25lJyxcbiAgICBTdGFja0lkOiBldmVudC5TdGFja0lkLFxuICAgIFJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIExvZ2ljYWxSZXNvdXJjZUlkOiBldmVudC5Mb2dpY2FsUmVzb3VyY2VJZCxcbiAgICBEYXRhOiByZXNwb25zZURhdGEgfHwge31cbiAgfSk7XG5cbiAgbG9nZ2VyLmRlYnVnKCdSZXNwb25zZSBib2R5OicpO1xuICBsb2dnZXIuZGVidWcocmVzcG9uc2VCb2R5KTtcblxuICBjb25zdCByZXNwb25zZVVybCA9IGV2ZW50LlJlc3BvbnNlVVJMO1xuICBsb2dnZXIuZGVidWcoYENGTiByZXNwb25zZSBVUkw6ICR7cmVzcG9uc2VVcmx9YCk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnB1dChyZXNwb25zZVVybCwgcmVzcG9uc2VCb2R5LCB7XG4gICAgICBoZWFkZXJzOiB7ICdjb250ZW50LXR5cGUnOiAnJywgJ2NvbnRlbnQtbGVuZ3RoJzogcmVzcG9uc2VCb2R5Lmxlbmd0aCB9XG4gICAgfSk7XG5cbiAgICBsb2dnZXIuaW5mbyhgQ2xvdWRGb3JtYXRpb24gcmV0dXJuZWQgc3RhdHVzIGNvZGU6ICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ2dlci5lcnJvcignc2VuZFJlc3BvbnNlKC4uLikgZmFpbGVkIGV4ZWN1dGluZyBheGlvcy5wdXQ6Jyk7XG4gICAgbG9nZ2VyLmVycm9yKGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufTtcblxuY29uc3QgaGFuZGxlUmVzc291cmNlID0gYXN5bmMgKFxuICBldmVudDogQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LFxuICBjb250ZXh0OiBDb250ZXh0LFxuICByZXNvdXJjZUhhbmRsZXI6IFJlc291cmNlSGFuZGxlcixcbiAgbG9nZ2VyOiBMb2dnZXJcbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBsb2dnZXIuZGVidWcoZXZlbnQpO1xuXG4gIC8vIERlZmluZSBhIHBoeXNpY2FsUmVzb3VyY2VJZCBmb3IgdGhlIHJlc291cmNlLCBpZiB0aGUgZXZlbnQgaXMgYW4gdXBkYXRlIGFuZCB0aGVcbiAgLy8gcmV0dXJuZWQgcGh5c2ljYWxSZXNvdXJjZUlkIGNoYW5nZXMsIGNsb3VkZm9ybWF0aW9uIHdpbGwgdGhlbiBpc3N1ZSBhIGRlbGV0ZVxuICAvLyBhZ2FpbnN0IHRoZSBvbGQgaWRcbiAgbGV0IHBoeXNpY2FsUmVzb3VyY2VJZCA9ICdOb25lJztcblxuICAvLyBEZWZpbmUgYW4gb2JqZWN0IHRvIHBsYWNlIGFueSByZXNwb25zZSBpbmZvcm1hdGlvbiB5b3Ugd291bGQgbGlrZSB0byBzZW5kXG4gIC8vIGJhY2sgdG8gQ2xvdWRGb3JtYXRpb24odGhlc2Uga2V5cyBjYW4gdGhlbiBiZSB1c2VkIGJ5IEZuOjogR2V0QXR0cilcbiAgbGV0IHJlc3BvbnNlRGF0YSA9IHt9O1xuXG4gIC8vIEV4ZWN1dGUgY3VzdG9tIHJlc291cmNlIGhhbmRsZXJzXG4gIGNvbnN0IHsgb25DcmVhdGUsIG9uVXBkYXRlLCBvbkRlbGV0ZSB9ID0gcmVzb3VyY2VIYW5kbGVyO1xuXG4gIHN3aXRjaCAoZXZlbnQuUmVxdWVzdFR5cGUpIHtcbiAgICBjYXNlICdDcmVhdGUnOlxuICAgICAgaWYob25DcmVhdGUpIHtcbiAgICAgICAgKHsgcGh5c2ljYWxSZXNvdXJjZUlkLCByZXNwb25zZURhdGEgPSB7fSB9ID0gYXdhaXQgb25DcmVhdGUoXG4gICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBsb2dnZXJcbiAgICAgICAgKSk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdVcGRhdGUnOlxuICAgICAgaWYob25VcGRhdGUpIHtcbiAgICAgICAgKHsgcGh5c2ljYWxSZXNvdXJjZUlkLCByZXNwb25zZURhdGEgPSB7fSB9ID0gYXdhaXQgb25VcGRhdGUoXG4gICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBsb2dnZXJcbiAgICAgICAgKSk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdEZWxldGUnOlxuICAgICAgaWYob25EZWxldGUpIHtcbiAgICAgICAgYXdhaXQgb25EZWxldGUoZXZlbnQsIGNvbnRleHQsIGxvZ2dlcik7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFJlcXVlc3RUeXBlIHJlY2VpdmVkJyk7XG4gIH1cblxuICAvLyBTZW5kIHJlc3BvbnNlIGJhY2sgdG8gQ2xvdWRGb3JtYXRpb25cbiAgY29uc3QgcmVzcG9uc2VEZXRhaWxzOiBTZW5kUmVzcG9uc2VEZXRhaWxzID0ge1xuICAgIHJlc3BvbnNlU3RhdHVzOiAnU1VDQ0VTUycsXG4gICAgcmVhc29uOiAnT0snLFxuICAgIHJlc3BvbnNlRGF0YSxcbiAgICBwaHlzaWNhbFJlc291cmNlSWRcbiAgfTtcbiAgcmV0dXJuIHNlbmRSZXNwb25zZShldmVudCwgY29udGV4dCwgcmVzcG9uc2VEZXRhaWxzLCBsb2dnZXIpO1xufTtcblxuY29uc3QgaGFuZGxlVGltZW91dCA9IGFzeW5jIChjb250ZXh0OiBDb250ZXh0LCBsb2dnZXI6IExvZ2dlcik6IFByb21pc2U8dm9pZD4gPT5cbiAgbmV3IFByb21pc2UoKF8sIHJlamVjdCkgPT4ge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgbG9nZ2VyLmVycm9yKCdFeGVjdXRpb24gaXMgYWJvdXQgdG8gdGltZSBvdXQsIHNlbmRpbmcgZmFpbHVyZSBtZXNzYWdlJyk7XG4gICAgICByZWplY3QobmV3IEVycm9yKCdFeGVjdXRpb24gdGltZWQgb3V0JykpO1xuICAgIH0sIGNvbnRleHQuZ2V0UmVtYWluaW5nVGltZUluTWlsbGlzKCkgLSAzMDAwKTtcbiAgfSk7XG4iXX0=